child-sa: Add method to associate rekeyed CHILD_SAs with their replacement
[strongswan.git] / src / libcharon / sa / child_sa.c
1 /*
2 * Copyright (C) 2006-2017 Tobias Brunner
3 * Copyright (C) 2016 Andreas Steffen
4 * Copyright (C) 2005-2008 Martin Willi
5 * Copyright (C) 2006 Daniel Roethlisberger
6 * Copyright (C) 2005 Jan Hutter
7 * HSR Hochschule fuer Technik Rapperswil
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * for more details.
18 */
19
20 #define _GNU_SOURCE
21 #include "child_sa.h"
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <time.h>
26
27 #include <daemon.h>
28 #include <collections/array.h>
29
30 ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
31 "CREATED",
32 "ROUTED",
33 "INSTALLING",
34 "INSTALLED_INBOUND",
35 "INSTALLED",
36 "UPDATING",
37 "REKEYING",
38 "REKEYED",
39 "RETRYING",
40 "DELETING",
41 "DESTROYING",
42 );
43
44 typedef struct private_child_sa_t private_child_sa_t;
45
46 /**
47 * Private data of a child_sa_t object.
48 */
49 struct private_child_sa_t {
50 /**
51 * Public interface of child_sa_t.
52 */
53 child_sa_t public;
54
55 /**
56 * address of us
57 */
58 host_t *my_addr;
59
60 /**
61 * address of remote
62 */
63 host_t *other_addr;
64
65 /**
66 * our actually used SPI, 0 if unused
67 */
68 uint32_t my_spi;
69
70 /**
71 * others used SPI, 0 if unused
72 */
73 uint32_t other_spi;
74
75 /**
76 * our Compression Parameter Index (CPI) used, 0 if unused
77 */
78 uint16_t my_cpi;
79
80 /**
81 * others Compression Parameter Index (CPI) used, 0 if unused
82 */
83 uint16_t other_cpi;
84
85 /**
86 * Array for local traffic selectors
87 */
88 array_t *my_ts;
89
90 /**
91 * Array for remote traffic selectors
92 */
93 array_t *other_ts;
94
95 /**
96 * Outbound encryption key cached during a rekeying
97 */
98 chunk_t encr_r;
99
100 /**
101 * Outbound integrity key cached during a rekeying
102 */
103 chunk_t integ_r;
104
105 /**
106 * Whether the outbound SA has only been registered yet during a rekeying
107 */
108 bool outbound_registered;
109
110 /**
111 * Whether the peer supports TFCv3
112 */
113 bool tfcv3;
114
115 /**
116 * The outbound SPI of the CHILD_SA that replaced this one during a rekeying
117 */
118 uint32_t rekey_spi;
119
120 /**
121 * Protocol used to protect this SA, ESP|AH
122 */
123 protocol_id_t protocol;
124
125 /**
126 * reqid used for this child_sa
127 */
128 uint32_t reqid;
129
130 /**
131 * Did we allocate/confirm and must release the reqid?
132 */
133 bool reqid_allocated;
134
135 /**
136 * Is the reqid statically configured
137 */
138 bool static_reqid;
139
140 /**
141 * Unique CHILD_SA identifier
142 */
143 uint32_t unique_id;
144
145 /**
146 * Whether FWD policieis in the outbound direction should be installed
147 */
148 bool policies_fwd_out;
149
150 /**
151 * inbound mark used for this child_sa
152 */
153 mark_t mark_in;
154
155 /**
156 * outbound mark used for this child_sa
157 */
158 mark_t mark_out;
159
160 /**
161 * absolute time when rekeying is scheduled
162 */
163 time_t rekey_time;
164
165 /**
166 * absolute time when the SA expires
167 */
168 time_t expire_time;
169
170 /**
171 * absolute time when SA has been installed
172 */
173 time_t install_time;
174
175 /**
176 * state of the CHILD_SA
177 */
178 child_sa_state_t state;
179
180 /**
181 * TRUE if this CHILD_SA is used to install trap policies
182 */
183 bool trap;
184
185 /**
186 * Specifies if UDP encapsulation is enabled (NAT traversal)
187 */
188 bool encap;
189
190 /**
191 * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
192 */
193 ipcomp_transform_t ipcomp;
194
195 /**
196 * mode this SA uses, tunnel/transport
197 */
198 ipsec_mode_t mode;
199
200 /**
201 * Action to enforce if peer closes the CHILD_SA
202 */
203 action_t close_action;
204
205 /**
206 * Action to enforce if peer is considered dead
207 */
208 action_t dpd_action;
209
210 /**
211 * selected proposal
212 */
213 proposal_t *proposal;
214
215 /**
216 * config used to create this child
217 */
218 child_cfg_t *config;
219
220 /**
221 * time of last use in seconds (inbound)
222 */
223 time_t my_usetime;
224
225 /**
226 * time of last use in seconds (outbound)
227 */
228 time_t other_usetime;
229
230 /**
231 * last number of inbound bytes
232 */
233 uint64_t my_usebytes;
234
235 /**
236 * last number of outbound bytes
237 */
238 uint64_t other_usebytes;
239
240 /**
241 * last number of inbound packets
242 */
243 uint64_t my_usepackets;
244
245 /**
246 * last number of outbound bytes
247 */
248 uint64_t other_usepackets;
249 };
250
251 /**
252 * convert an IKEv2 specific protocol identifier to the IP protocol identifier.
253 */
254 static inline uint8_t proto_ike2ip(protocol_id_t protocol)
255 {
256 switch (protocol)
257 {
258 case PROTO_ESP:
259 return IPPROTO_ESP;
260 case PROTO_AH:
261 return IPPROTO_AH;
262 default:
263 return protocol;
264 }
265 }
266
267 METHOD(child_sa_t, get_name, char*,
268 private_child_sa_t *this)
269 {
270 return this->config->get_name(this->config);
271 }
272
273 METHOD(child_sa_t, get_reqid, uint32_t,
274 private_child_sa_t *this)
275 {
276 return this->reqid;
277 }
278
279 METHOD(child_sa_t, get_unique_id, uint32_t,
280 private_child_sa_t *this)
281 {
282 return this->unique_id;
283 }
284
285 METHOD(child_sa_t, get_config, child_cfg_t*,
286 private_child_sa_t *this)
287 {
288 return this->config;
289 }
290
291 METHOD(child_sa_t, set_state, void,
292 private_child_sa_t *this, child_sa_state_t state)
293 {
294 charon->bus->child_state_change(charon->bus, &this->public, state);
295 this->state = state;
296 }
297
298 METHOD(child_sa_t, get_state, child_sa_state_t,
299 private_child_sa_t *this)
300 {
301 return this->state;
302 }
303
304 METHOD(child_sa_t, get_spi, uint32_t,
305 private_child_sa_t *this, bool inbound)
306 {
307 return inbound ? this->my_spi : this->other_spi;
308 }
309
310 METHOD(child_sa_t, get_cpi, uint16_t,
311 private_child_sa_t *this, bool inbound)
312 {
313 return inbound ? this->my_cpi : this->other_cpi;
314 }
315
316 METHOD(child_sa_t, get_protocol, protocol_id_t,
317 private_child_sa_t *this)
318 {
319 return this->protocol;
320 }
321
322 METHOD(child_sa_t, set_protocol, void,
323 private_child_sa_t *this, protocol_id_t protocol)
324 {
325 this->protocol = protocol;
326 }
327
328 METHOD(child_sa_t, get_mode, ipsec_mode_t,
329 private_child_sa_t *this)
330 {
331 return this->mode;
332 }
333
334 METHOD(child_sa_t, set_mode, void,
335 private_child_sa_t *this, ipsec_mode_t mode)
336 {
337 this->mode = mode;
338 }
339
340 METHOD(child_sa_t, has_encap, bool,
341 private_child_sa_t *this)
342 {
343 return this->encap;
344 }
345
346 METHOD(child_sa_t, get_ipcomp, ipcomp_transform_t,
347 private_child_sa_t *this)
348 {
349 return this->ipcomp;
350 }
351
352 METHOD(child_sa_t, set_ipcomp, void,
353 private_child_sa_t *this, ipcomp_transform_t ipcomp)
354 {
355 this->ipcomp = ipcomp;
356 }
357
358 METHOD(child_sa_t, set_close_action, void,
359 private_child_sa_t *this, action_t action)
360 {
361 this->close_action = action;
362 }
363
364 METHOD(child_sa_t, get_close_action, action_t,
365 private_child_sa_t *this)
366 {
367 return this->close_action;
368 }
369
370 METHOD(child_sa_t, set_dpd_action, void,
371 private_child_sa_t *this, action_t action)
372 {
373 this->dpd_action = action;
374 }
375
376 METHOD(child_sa_t, get_dpd_action, action_t,
377 private_child_sa_t *this)
378 {
379 return this->dpd_action;
380 }
381
382 METHOD(child_sa_t, get_proposal, proposal_t*,
383 private_child_sa_t *this)
384 {
385 return this->proposal;
386 }
387
388 METHOD(child_sa_t, set_proposal, void,
389 private_child_sa_t *this, proposal_t *proposal)
390 {
391 this->proposal = proposal->clone(proposal);
392 }
393
394 METHOD(child_sa_t, create_ts_enumerator, enumerator_t*,
395 private_child_sa_t *this, bool local)
396 {
397 if (local)
398 {
399 return array_create_enumerator(this->my_ts);
400 }
401 return array_create_enumerator(this->other_ts);
402 }
403
404 typedef struct policy_enumerator_t policy_enumerator_t;
405
406 /**
407 * Private policy enumerator
408 */
409 struct policy_enumerator_t {
410 /** implements enumerator_t */
411 enumerator_t public;
412 /** enumerator over own TS */
413 enumerator_t *mine;
414 /** enumerator over others TS */
415 enumerator_t *other;
416 /** array of others TS, to recreate enumerator */
417 array_t *array;
418 /** currently enumerating TS for "me" side */
419 traffic_selector_t *ts;
420 };
421
422 METHOD(enumerator_t, policy_enumerate, bool,
423 policy_enumerator_t *this, traffic_selector_t **my_out,
424 traffic_selector_t **other_out)
425 {
426 traffic_selector_t *other_ts;
427
428 while (this->ts || this->mine->enumerate(this->mine, &this->ts))
429 {
430 if (!this->other->enumerate(this->other, &other_ts))
431 { /* end of others list, restart with new of mine */
432 this->other->destroy(this->other);
433 this->other = array_create_enumerator(this->array);
434 this->ts = NULL;
435 continue;
436 }
437 if (this->ts->get_type(this->ts) != other_ts->get_type(other_ts))
438 { /* family mismatch */
439 continue;
440 }
441 if (this->ts->get_protocol(this->ts) &&
442 other_ts->get_protocol(other_ts) &&
443 this->ts->get_protocol(this->ts) != other_ts->get_protocol(other_ts))
444 { /* protocol mismatch */
445 continue;
446 }
447 if (my_out)
448 {
449 *my_out = this->ts;
450 }
451 if (other_out)
452 {
453 *other_out = other_ts;
454 }
455 return TRUE;
456 }
457 return FALSE;
458 }
459
460 METHOD(enumerator_t, policy_destroy, void,
461 policy_enumerator_t *this)
462 {
463 this->mine->destroy(this->mine);
464 this->other->destroy(this->other);
465 free(this);
466 }
467
468 METHOD(child_sa_t, create_policy_enumerator, enumerator_t*,
469 private_child_sa_t *this)
470 {
471 policy_enumerator_t *e;
472
473 INIT(e,
474 .public = {
475 .enumerate = (void*)_policy_enumerate,
476 .destroy = _policy_destroy,
477 },
478 .mine = array_create_enumerator(this->my_ts),
479 .other = array_create_enumerator(this->other_ts),
480 .array = this->other_ts,
481 .ts = NULL,
482 );
483
484 return &e->public;
485 }
486
487 /**
488 * update the cached usebytes
489 * returns SUCCESS if the usebytes have changed, FAILED if not or no SPIs
490 * are available, and NOT_SUPPORTED if the kernel interface does not support
491 * querying the usebytes.
492 */
493 static status_t update_usebytes(private_child_sa_t *this, bool inbound)
494 {
495 status_t status = FAILED;
496 uint64_t bytes, packets;
497 time_t time;
498
499 if (inbound)
500 {
501 if (this->my_spi)
502 {
503 kernel_ipsec_sa_id_t id = {
504 .src = this->other_addr,
505 .dst = this->my_addr,
506 .spi = this->my_spi,
507 .proto = proto_ike2ip(this->protocol),
508 };
509 kernel_ipsec_query_sa_t query = {};
510
511 status = charon->kernel->query_sa(charon->kernel, &id, &query,
512 &bytes, &packets, &time);
513 if (status == SUCCESS)
514 {
515 if (bytes > this->my_usebytes)
516 {
517 this->my_usebytes = bytes;
518 this->my_usepackets = packets;
519 if (time)
520 {
521 this->my_usetime = time;
522 }
523 }
524 else
525 {
526 status = FAILED;
527 }
528 }
529 }
530 }
531 else
532 {
533 if (this->other_spi)
534 {
535 kernel_ipsec_sa_id_t id = {
536 .src = this->my_addr,
537 .dst = this->other_addr,
538 .spi = this->other_spi,
539 .proto = proto_ike2ip(this->protocol),
540 .mark = this->mark_out,
541 };
542 kernel_ipsec_query_sa_t query = {};
543
544 status = charon->kernel->query_sa(charon->kernel, &id, &query,
545 &bytes, &packets, &time);
546 if (status == SUCCESS)
547 {
548 if (bytes > this->other_usebytes)
549 {
550 this->other_usebytes = bytes;
551 this->other_usepackets = packets;
552 if (time)
553 {
554 this->other_usetime = time;
555 }
556 }
557 else
558 {
559 status = FAILED;
560 }
561 }
562 }
563 }
564 return status;
565 }
566
567 /**
568 * updates the cached usetime
569 */
570 static bool update_usetime(private_child_sa_t *this, bool inbound)
571 {
572 enumerator_t *enumerator;
573 traffic_selector_t *my_ts, *other_ts;
574 time_t last_use = 0;
575
576 enumerator = create_policy_enumerator(this);
577 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
578 {
579 time_t in, out, fwd;
580
581 if (inbound)
582 {
583 kernel_ipsec_policy_id_t id = {
584 .dir = POLICY_IN,
585 .src_ts = other_ts,
586 .dst_ts = my_ts,
587 .mark = this->mark_in,
588 };
589 kernel_ipsec_query_policy_t query = {};
590
591 if (charon->kernel->query_policy(charon->kernel, &id, &query,
592 &in) == SUCCESS)
593 {
594 last_use = max(last_use, in);
595 }
596 if (this->mode != MODE_TRANSPORT)
597 {
598 id.dir = POLICY_FWD;
599 if (charon->kernel->query_policy(charon->kernel, &id, &query,
600 &fwd) == SUCCESS)
601 {
602 last_use = max(last_use, fwd);
603 }
604 }
605 }
606 else
607 {
608 kernel_ipsec_policy_id_t id = {
609 .dir = POLICY_OUT,
610 .src_ts = my_ts,
611 .dst_ts = other_ts,
612 .mark = this->mark_out,
613 .interface = this->config->get_interface(this->config),
614 };
615 kernel_ipsec_query_policy_t query = {};
616
617 if (charon->kernel->query_policy(charon->kernel, &id, &query,
618 &out) == SUCCESS)
619 {
620 last_use = max(last_use, out);
621 }
622 }
623 }
624 enumerator->destroy(enumerator);
625
626 if (last_use == 0)
627 {
628 return FALSE;
629 }
630 if (inbound)
631 {
632 this->my_usetime = last_use;
633 }
634 else
635 {
636 this->other_usetime = last_use;
637 }
638 return TRUE;
639 }
640
641 METHOD(child_sa_t, get_usestats, void,
642 private_child_sa_t *this, bool inbound,
643 time_t *time, uint64_t *bytes, uint64_t *packets)
644 {
645 if ((!bytes && !packets) || update_usebytes(this, inbound) != FAILED)
646 {
647 /* there was traffic since last update or the kernel interface
648 * does not support querying the number of usebytes.
649 */
650 if (time)
651 {
652 if (!update_usetime(this, inbound) && !bytes && !packets)
653 {
654 /* if policy query did not yield a usetime, query SAs instead */
655 update_usebytes(this, inbound);
656 }
657 }
658 }
659 if (time)
660 {
661 *time = inbound ? this->my_usetime : this->other_usetime;
662 }
663 if (bytes)
664 {
665 *bytes = inbound ? this->my_usebytes : this->other_usebytes;
666 }
667 if (packets)
668 {
669 *packets = inbound ? this->my_usepackets : this->other_usepackets;
670 }
671 }
672
673 METHOD(child_sa_t, get_mark, mark_t,
674 private_child_sa_t *this, bool inbound)
675 {
676 if (inbound)
677 {
678 return this->mark_in;
679 }
680 return this->mark_out;
681 }
682
683 METHOD(child_sa_t, get_lifetime, time_t,
684 private_child_sa_t *this, bool hard)
685 {
686 return hard ? this->expire_time : this->rekey_time;
687 }
688
689 METHOD(child_sa_t, get_installtime, time_t,
690 private_child_sa_t *this)
691 {
692 return this->install_time;
693 }
694
695 METHOD(child_sa_t, alloc_spi, uint32_t,
696 private_child_sa_t *this, protocol_id_t protocol)
697 {
698 if (charon->kernel->get_spi(charon->kernel, this->other_addr, this->my_addr,
699 proto_ike2ip(protocol), &this->my_spi) == SUCCESS)
700 {
701 /* if we allocate a SPI, but then are unable to establish the SA, we
702 * need to know the protocol family to delete the partial SA */
703 this->protocol = protocol;
704 return this->my_spi;
705 }
706 return 0;
707 }
708
709 METHOD(child_sa_t, alloc_cpi, uint16_t,
710 private_child_sa_t *this)
711 {
712 if (charon->kernel->get_cpi(charon->kernel, this->other_addr, this->my_addr,
713 &this->my_cpi) == SUCCESS)
714 {
715 return this->my_cpi;
716 }
717 return 0;
718 }
719
720 /**
721 * Install the given SA in the kernel
722 */
723 static status_t install_internal(private_child_sa_t *this, chunk_t encr,
724 chunk_t integ, uint32_t spi, uint16_t cpi, bool initiator, bool inbound,
725 bool tfcv3)
726 {
727 uint16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
728 uint16_t esn = NO_EXT_SEQ_NUMBERS;
729 linked_list_t *my_ts, *other_ts, *src_ts, *dst_ts;
730 time_t now;
731 kernel_ipsec_sa_id_t id;
732 kernel_ipsec_add_sa_t sa;
733 lifetime_cfg_t *lifetime;
734 uint32_t tfc = 0;
735 host_t *src, *dst;
736 status_t status;
737 bool update = FALSE;
738
739 /* BEET requires the bound address from the traffic selectors */
740 my_ts = linked_list_create_from_enumerator(
741 array_create_enumerator(this->my_ts));
742 other_ts = linked_list_create_from_enumerator(
743 array_create_enumerator(this->other_ts));
744
745 /* now we have to decide which spi to use. Use self allocated, if "in",
746 * or the one in the proposal, if not "in" (others). Additionally,
747 * source and dest host switch depending on the role */
748 if (inbound)
749 {
750 dst = this->my_addr;
751 src = this->other_addr;
752 if (this->my_spi == spi)
753 { /* alloc_spi has been called, do an SA update */
754 update = TRUE;
755 }
756 this->my_spi = spi;
757 this->my_cpi = cpi;
758 dst_ts = my_ts;
759 src_ts = other_ts;
760 }
761 else
762 {
763 src = this->my_addr;
764 dst = this->other_addr;
765 this->other_spi = spi;
766 this->other_cpi = cpi;
767 src_ts = my_ts;
768 dst_ts = other_ts;
769
770 if (tfcv3)
771 {
772 tfc = this->config->get_tfc(this->config);
773 }
774 }
775
776 DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
777 protocol_id_names, this->protocol);
778
779 /* send SA down to the kernel */
780 DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
781
782 this->proposal->get_algorithm(this->proposal, ENCRYPTION_ALGORITHM,
783 &enc_alg, &size);
784 this->proposal->get_algorithm(this->proposal, INTEGRITY_ALGORITHM,
785 &int_alg, &size);
786 this->proposal->get_algorithm(this->proposal, EXTENDED_SEQUENCE_NUMBERS,
787 &esn, NULL);
788
789 if (!this->reqid_allocated && !this->static_reqid)
790 {
791 status = charon->kernel->alloc_reqid(charon->kernel, my_ts, other_ts,
792 this->mark_in, this->mark_out, &this->reqid);
793 if (status != SUCCESS)
794 {
795 my_ts->destroy(my_ts);
796 other_ts->destroy(other_ts);
797 return status;
798 }
799 this->reqid_allocated = TRUE;
800 }
801
802 lifetime = this->config->get_lifetime(this->config, TRUE);
803
804 now = time_monotonic(NULL);
805 if (lifetime->time.rekey)
806 {
807 if (this->rekey_time)
808 {
809 this->rekey_time = min(this->rekey_time, now + lifetime->time.rekey);
810 }
811 else
812 {
813 this->rekey_time = now + lifetime->time.rekey;
814 }
815 }
816 if (lifetime->time.life)
817 {
818 this->expire_time = now + lifetime->time.life;
819 }
820
821 if (!lifetime->time.jitter && !inbound)
822 { /* avoid triggering multiple rekey events */
823 lifetime->time.rekey = 0;
824 }
825
826 id = (kernel_ipsec_sa_id_t){
827 .src = src,
828 .dst = dst,
829 .spi = spi,
830 .proto = proto_ike2ip(this->protocol),
831 .mark = inbound ? (mark_t){} : this->mark_out,
832 };
833 sa = (kernel_ipsec_add_sa_t){
834 .reqid = this->reqid,
835 .mode = this->mode,
836 .src_ts = src_ts,
837 .dst_ts = dst_ts,
838 .interface = inbound ? NULL : this->config->get_interface(this->config),
839 .lifetime = lifetime,
840 .enc_alg = enc_alg,
841 .enc_key = encr,
842 .int_alg = int_alg,
843 .int_key = integ,
844 .replay_window = this->config->get_replay_window(this->config),
845 .tfc = tfc,
846 .ipcomp = this->ipcomp,
847 .cpi = cpi,
848 .encap = this->encap,
849 .hw_offload = this->config->has_option(this->config, OPT_HW_OFFLOAD),
850 .esn = esn,
851 .initiator = initiator,
852 .inbound = inbound,
853 .update = update,
854 };
855
856 status = charon->kernel->add_sa(charon->kernel, &id, &sa);
857
858 my_ts->destroy(my_ts);
859 other_ts->destroy(other_ts);
860 free(lifetime);
861
862 return status;
863 }
864
865 METHOD(child_sa_t, install, status_t,
866 private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
867 uint16_t cpi, bool initiator, bool inbound, bool tfcv3)
868 {
869 return install_internal(this, encr, integ, spi, cpi, initiator, inbound,
870 tfcv3);
871 }
872
873 /**
874 * Check kernel interface if policy updates are required
875 */
876 static bool require_policy_update()
877 {
878 kernel_feature_t f;
879
880 f = charon->kernel->get_features(charon->kernel);
881 return !(f & KERNEL_NO_POLICY_UPDATES);
882 }
883
884 /**
885 * Prepare SA config to install/delete policies
886 */
887 static void prepare_sa_cfg(private_child_sa_t *this, ipsec_sa_cfg_t *my_sa,
888 ipsec_sa_cfg_t *other_sa)
889 {
890 enumerator_t *enumerator;
891
892 *my_sa = (ipsec_sa_cfg_t){
893 .mode = this->mode,
894 .reqid = this->reqid,
895 .ipcomp = {
896 .transform = this->ipcomp,
897 },
898 };
899 *other_sa = *my_sa;
900
901 my_sa->ipcomp.cpi = this->my_cpi;
902 other_sa->ipcomp.cpi = this->other_cpi;
903
904 if (this->protocol == PROTO_ESP)
905 {
906 my_sa->esp.use = TRUE;
907 my_sa->esp.spi = this->my_spi;
908 other_sa->esp.use = TRUE;
909 other_sa->esp.spi = this->other_spi;
910 }
911 else
912 {
913 my_sa->ah.use = TRUE;
914 my_sa->ah.spi = this->my_spi;
915 other_sa->ah.use = TRUE;
916 other_sa->ah.spi = this->other_spi;
917 }
918
919 enumerator = create_policy_enumerator(this);
920 while (enumerator->enumerate(enumerator, NULL, NULL))
921 {
922 my_sa->policy_count++;
923 other_sa->policy_count++;
924 }
925 enumerator->destroy(enumerator);
926 }
927
928 /**
929 * Install inbound policie(s): in, fwd
930 */
931 static status_t install_policies_inbound(private_child_sa_t *this,
932 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
933 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
934 ipsec_sa_cfg_t *other_sa, policy_type_t type,
935 policy_priority_t priority, uint32_t manual_prio)
936 {
937 kernel_ipsec_policy_id_t in_id = {
938 .dir = POLICY_IN,
939 .src_ts = other_ts,
940 .dst_ts = my_ts,
941 .mark = this->mark_in,
942 };
943 kernel_ipsec_manage_policy_t in_policy = {
944 .type = type,
945 .prio = priority,
946 .manual_prio = manual_prio,
947 .src = other_addr,
948 .dst = my_addr,
949 .sa = my_sa,
950 };
951 status_t status = SUCCESS;
952
953 status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
954 if (this->mode != MODE_TRANSPORT)
955 {
956 in_id.dir = POLICY_FWD;
957 status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
958 }
959 return status;
960 }
961
962 /**
963 * Install outbound policie(s): out, [fwd]
964 */
965 static status_t install_policies_outbound(private_child_sa_t *this,
966 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
967 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
968 ipsec_sa_cfg_t *other_sa, policy_type_t type,
969 policy_priority_t priority, uint32_t manual_prio)
970 {
971 kernel_ipsec_policy_id_t out_id = {
972 .dir = POLICY_OUT,
973 .src_ts = my_ts,
974 .dst_ts = other_ts,
975 .mark = this->mark_out,
976 .interface = this->config->get_interface(this->config),
977 };
978 kernel_ipsec_manage_policy_t out_policy = {
979 .type = type,
980 .prio = priority,
981 .manual_prio = manual_prio,
982 .src = my_addr,
983 .dst = other_addr,
984 .sa = other_sa,
985 };
986 status_t status = SUCCESS;
987
988 status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
989
990 if (this->mode != MODE_TRANSPORT && this->policies_fwd_out)
991 {
992 /* install an "outbound" FWD policy in case there is a drop policy
993 * matching outbound forwarded traffic, to allow another tunnel to use
994 * the reversed subnets and do the same we don't set a reqid (this also
995 * allows the kernel backend to distinguish between the two types of
996 * FWD policies). To avoid problems with symmetrically overlapping
997 * policies of two SAs we install them with reduced priority. As they
998 * basically act as bypass policies for drop policies we use a higher
999 * priority than is used for them. */
1000 out_id.dir = POLICY_FWD;
1001 other_sa->reqid = 0;
1002 if (priority == POLICY_PRIORITY_DEFAULT)
1003 {
1004 out_policy.prio = POLICY_PRIORITY_ROUTED;
1005 }
1006 status |= charon->kernel->add_policy(charon->kernel, &out_id,
1007 &out_policy);
1008 /* reset the reqid for any other further policies */
1009 other_sa->reqid = this->reqid;
1010 }
1011 return status;
1012 }
1013
1014 /**
1015 * Install all policies
1016 */
1017 static status_t install_policies_internal(private_child_sa_t *this,
1018 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1019 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1020 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1021 policy_priority_t priority, uint32_t manual_prio)
1022 {
1023 status_t status = SUCCESS;
1024
1025 status |= install_policies_inbound(this, my_addr, other_addr, my_ts,
1026 other_ts, my_sa, other_sa, type,
1027 priority, manual_prio);
1028 status |= install_policies_outbound(this, my_addr, other_addr, my_ts,
1029 other_ts, my_sa, other_sa, type,
1030 priority, manual_prio);
1031 return status;
1032 }
1033
1034 /**
1035 * Delete inbound policies: in, fwd
1036 */
1037 static void del_policies_inbound(private_child_sa_t *this,
1038 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1039 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1040 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1041 policy_priority_t priority, uint32_t manual_prio)
1042 {
1043 kernel_ipsec_policy_id_t in_id = {
1044 .dir = POLICY_IN,
1045 .src_ts = other_ts,
1046 .dst_ts = my_ts,
1047 .mark = this->mark_in,
1048 };
1049 kernel_ipsec_manage_policy_t in_policy = {
1050 .type = type,
1051 .prio = priority,
1052 .manual_prio = manual_prio,
1053 .src = other_addr,
1054 .dst = my_addr,
1055 .sa = my_sa,
1056 };
1057
1058 charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
1059
1060 if (this->mode != MODE_TRANSPORT)
1061 {
1062 in_id.dir = POLICY_FWD;
1063 charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
1064 }
1065 }
1066
1067 /**
1068 * Delete outbound policies: out, [fwd]
1069 */
1070 static void del_policies_outbound(private_child_sa_t *this,
1071 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1072 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1073 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1074 policy_priority_t priority, uint32_t manual_prio)
1075 {
1076 kernel_ipsec_policy_id_t out_id = {
1077 .dir = POLICY_OUT,
1078 .src_ts = my_ts,
1079 .dst_ts = other_ts,
1080 .mark = this->mark_out,
1081 .interface = this->config->get_interface(this->config),
1082 };
1083 kernel_ipsec_manage_policy_t out_policy = {
1084 .type = type,
1085 .prio = priority,
1086 .manual_prio = manual_prio,
1087 .src = my_addr,
1088 .dst = other_addr,
1089 .sa = other_sa,
1090 };
1091
1092 charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
1093
1094 if (this->mode != MODE_TRANSPORT && this->policies_fwd_out)
1095 {
1096 out_id.dir = POLICY_FWD;
1097 other_sa->reqid = 0;
1098 if (priority == POLICY_PRIORITY_DEFAULT)
1099 {
1100 out_policy.prio = POLICY_PRIORITY_ROUTED;
1101 }
1102 charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
1103 other_sa->reqid = this->reqid;
1104 }
1105 }
1106
1107 /**
1108 * Delete in- and outbound policies
1109 */
1110 static void del_policies_internal(private_child_sa_t *this,
1111 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1112 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1113 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1114 policy_priority_t priority, uint32_t manual_prio)
1115 {
1116 del_policies_outbound(this, my_addr, other_addr, my_ts, other_ts, my_sa,
1117 other_sa, type, priority, manual_prio);
1118 del_policies_inbound(this, my_addr, other_addr, my_ts, other_ts, my_sa,
1119 other_sa, type, priority, manual_prio);
1120 }
1121
1122 METHOD(child_sa_t, set_policies, void,
1123 private_child_sa_t *this, linked_list_t *my_ts_list,
1124 linked_list_t *other_ts_list)
1125 {
1126 enumerator_t *enumerator;
1127 traffic_selector_t *my_ts, *other_ts;
1128
1129 if (array_count(this->my_ts))
1130 {
1131 array_destroy_offset(this->my_ts,
1132 offsetof(traffic_selector_t, destroy));
1133 this->my_ts = array_create(0, 0);
1134 }
1135 enumerator = my_ts_list->create_enumerator(my_ts_list);
1136 while (enumerator->enumerate(enumerator, &my_ts))
1137 {
1138 array_insert(this->my_ts, ARRAY_TAIL, my_ts->clone(my_ts));
1139 }
1140 enumerator->destroy(enumerator);
1141 array_sort(this->my_ts, (void*)traffic_selector_cmp, NULL);
1142
1143 if (array_count(this->other_ts))
1144 {
1145 array_destroy_offset(this->other_ts,
1146 offsetof(traffic_selector_t, destroy));
1147 this->other_ts = array_create(0, 0);
1148 }
1149 enumerator = other_ts_list->create_enumerator(other_ts_list);
1150 while (enumerator->enumerate(enumerator, &other_ts))
1151 {
1152 array_insert(this->other_ts, ARRAY_TAIL, other_ts->clone(other_ts));
1153 }
1154 enumerator->destroy(enumerator);
1155 array_sort(this->other_ts, (void*)traffic_selector_cmp, NULL);
1156 }
1157
1158 METHOD(child_sa_t, install_policies, status_t,
1159 private_child_sa_t *this)
1160 {
1161 enumerator_t *enumerator;
1162 linked_list_t *my_ts_list, *other_ts_list;
1163 traffic_selector_t *my_ts, *other_ts;
1164 status_t status = SUCCESS;
1165
1166 if (!this->reqid_allocated && !this->static_reqid)
1167 {
1168 my_ts_list = linked_list_create_from_enumerator(
1169 array_create_enumerator(this->my_ts));
1170 other_ts_list = linked_list_create_from_enumerator(
1171 array_create_enumerator(this->other_ts));
1172 status = charon->kernel->alloc_reqid(
1173 charon->kernel, my_ts_list, other_ts_list,
1174 this->mark_in, this->mark_out, &this->reqid);
1175 my_ts_list->destroy(my_ts_list);
1176 other_ts_list->destroy(other_ts_list);
1177 if (status != SUCCESS)
1178 {
1179 return status;
1180 }
1181 this->reqid_allocated = TRUE;
1182 }
1183
1184 if (!this->config->has_option(this->config, OPT_NO_POLICIES))
1185 {
1186 policy_priority_t priority;
1187 ipsec_sa_cfg_t my_sa, other_sa;
1188 uint32_t manual_prio;
1189
1190 prepare_sa_cfg(this, &my_sa, &other_sa);
1191 manual_prio = this->config->get_manual_prio(this->config);
1192
1193 /* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
1194 * entry) we install a trap policy */
1195 this->trap = this->state == CHILD_CREATED;
1196 priority = this->trap ? POLICY_PRIORITY_ROUTED
1197 : POLICY_PRIORITY_DEFAULT;
1198
1199 /* enumerate pairs of traffic selectors */
1200 enumerator = create_policy_enumerator(this);
1201 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1202 {
1203 /* install outbound drop policy to avoid packets leaving unencrypted
1204 * when updating policies */
1205 if (priority == POLICY_PRIORITY_DEFAULT && manual_prio == 0 &&
1206 require_policy_update() && !this->outbound_registered)
1207 {
1208 status |= install_policies_outbound(this, this->my_addr,
1209 this->other_addr, my_ts, other_ts,
1210 &my_sa, &other_sa, POLICY_DROP,
1211 POLICY_PRIORITY_FALLBACK, 0);
1212 }
1213
1214 status |= install_policies_inbound(this, this->my_addr,
1215 this->other_addr, my_ts, other_ts,
1216 &my_sa, &other_sa, POLICY_IPSEC,
1217 priority, manual_prio);
1218
1219 if (!this->outbound_registered)
1220 {
1221 status |= install_policies_outbound(this, this->my_addr,
1222 this->other_addr, my_ts, other_ts,
1223 &my_sa, &other_sa, POLICY_IPSEC,
1224 priority, manual_prio);
1225
1226 }
1227 if (status != SUCCESS)
1228 {
1229 break;
1230 }
1231 }
1232 enumerator->destroy(enumerator);
1233 }
1234
1235 if (status == SUCCESS && this->trap)
1236 {
1237 set_state(this, CHILD_ROUTED);
1238 }
1239 return status;
1240 }
1241
1242 METHOD(child_sa_t, register_outbound, void,
1243 private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
1244 uint16_t cpi, bool tfcv3)
1245 {
1246 DBG2(DBG_CHD, "registering outbound %N SA", protocol_id_names,
1247 this->protocol);
1248 DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), this->my_addr,
1249 this->other_addr);
1250
1251 this->other_spi = spi;
1252 this->other_cpi = cpi;
1253 this->encr_r = chunk_clone(encr);
1254 this->integ_r = chunk_clone(integ);
1255 this->tfcv3 = tfcv3;
1256 this->outbound_registered = TRUE;
1257 }
1258
1259 METHOD(child_sa_t, install_outbound, status_t,
1260 private_child_sa_t *this)
1261 {
1262 enumerator_t *enumerator;
1263 traffic_selector_t *my_ts, *other_ts;
1264 status_t status;
1265
1266 this->outbound_registered = FALSE;
1267
1268 status = install_internal(this, this->encr_r, this->integ_r,
1269 this->other_spi, this->other_cpi, FALSE, FALSE,
1270 this->tfcv3);
1271 chunk_clear(&this->encr_r);
1272 chunk_clear(&this->integ_r);
1273 if (status != SUCCESS)
1274 {
1275 return status;
1276 }
1277 if (!this->config->has_option(this->config, OPT_NO_POLICIES))
1278 {
1279 ipsec_sa_cfg_t my_sa, other_sa;
1280 uint32_t manual_prio;
1281
1282 prepare_sa_cfg(this, &my_sa, &other_sa);
1283 manual_prio = this->config->get_manual_prio(this->config);
1284
1285 enumerator = create_policy_enumerator(this);
1286 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1287 {
1288 /* install outbound drop policy to avoid packets leaving unencrypted
1289 * when updating policies */
1290 if (manual_prio == 0 && require_policy_update())
1291 {
1292 status |= install_policies_outbound(this, this->my_addr,
1293 this->other_addr, my_ts, other_ts,
1294 &my_sa, &other_sa, POLICY_DROP,
1295 POLICY_PRIORITY_FALLBACK, 0);
1296 }
1297 status |= install_policies_outbound(this, this->my_addr,
1298 this->other_addr, my_ts, other_ts,
1299 &my_sa, &other_sa, POLICY_IPSEC,
1300 POLICY_PRIORITY_DEFAULT, manual_prio);
1301 if (status != SUCCESS)
1302 {
1303 break;
1304 }
1305 }
1306 enumerator->destroy(enumerator);
1307 }
1308 return status;
1309 }
1310
1311 METHOD(child_sa_t, set_rekey_spi, void,
1312 private_child_sa_t *this, uint32_t spi)
1313 {
1314 this->rekey_spi = spi;
1315 }
1316
1317 METHOD(child_sa_t, get_rekey_spi, uint32_t,
1318 private_child_sa_t *this)
1319 {
1320 return this->rekey_spi;
1321 }
1322
1323 /**
1324 * Callback to reinstall a virtual IP
1325 */
1326 static void reinstall_vip(host_t *vip, host_t *me)
1327 {
1328 char *iface;
1329
1330 if (charon->kernel->get_interface(charon->kernel, me, &iface))
1331 {
1332 charon->kernel->del_ip(charon->kernel, vip, -1, TRUE);
1333 charon->kernel->add_ip(charon->kernel, vip, -1, iface);
1334 free(iface);
1335 }
1336 }
1337
1338 METHOD(child_sa_t, update, status_t,
1339 private_child_sa_t *this, host_t *me, host_t *other, linked_list_t *vips,
1340 bool encap)
1341 {
1342 child_sa_state_t old;
1343 bool transport_proxy_mode;
1344
1345 /* anything changed at all? */
1346 if (me->equals(me, this->my_addr) &&
1347 other->equals(other, this->other_addr) && this->encap == encap)
1348 {
1349 return SUCCESS;
1350 }
1351
1352 old = this->state;
1353 set_state(this, CHILD_UPDATING);
1354 transport_proxy_mode = this->mode == MODE_TRANSPORT &&
1355 this->config->has_option(this->config,
1356 OPT_PROXY_MODE);
1357
1358 if (!transport_proxy_mode)
1359 {
1360 /* update our (initiator) SA */
1361 if (this->my_spi)
1362 {
1363 kernel_ipsec_sa_id_t id = {
1364 .src = this->other_addr,
1365 .dst = this->my_addr,
1366 .spi = this->my_spi,
1367 .proto = proto_ike2ip(this->protocol),
1368 };
1369 kernel_ipsec_update_sa_t sa = {
1370 .cpi = this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
1371 .new_src = other,
1372 .new_dst = me,
1373 .encap = this->encap,
1374 .new_encap = encap,
1375 };
1376 if (charon->kernel->update_sa(charon->kernel, &id,
1377 &sa) == NOT_SUPPORTED)
1378 {
1379 set_state(this, old);
1380 return NOT_SUPPORTED;
1381 }
1382 }
1383
1384 /* update his (responder) SA */
1385 if (this->other_spi)
1386 {
1387 kernel_ipsec_sa_id_t id = {
1388 .src = this->my_addr,
1389 .dst = this->other_addr,
1390 .spi = this->other_spi,
1391 .proto = proto_ike2ip(this->protocol),
1392 .mark = this->mark_out,
1393 };
1394 kernel_ipsec_update_sa_t sa = {
1395 .cpi = this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
1396 .new_src = me,
1397 .new_dst = other,
1398 .encap = this->encap,
1399 .new_encap = encap,
1400 };
1401 if (charon->kernel->update_sa(charon->kernel, &id,
1402 &sa) == NOT_SUPPORTED)
1403 {
1404 set_state(this, old);
1405 return NOT_SUPPORTED;
1406 }
1407 }
1408 }
1409
1410 if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
1411 require_policy_update())
1412 {
1413 if (!me->ip_equals(me, this->my_addr) ||
1414 !other->ip_equals(other, this->other_addr))
1415 {
1416 ipsec_sa_cfg_t my_sa, other_sa;
1417 enumerator_t *enumerator;
1418 traffic_selector_t *my_ts, *other_ts;
1419 uint32_t manual_prio;
1420
1421 prepare_sa_cfg(this, &my_sa, &other_sa);
1422 manual_prio = this->config->get_manual_prio(this->config);
1423
1424 /* always use high priorities, as hosts getting updated are INSTALLED */
1425 enumerator = create_policy_enumerator(this);
1426 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1427 {
1428 traffic_selector_t *old_my_ts = NULL, *old_other_ts = NULL;
1429
1430 /* remove old policies first */
1431 del_policies_internal(this, this->my_addr, this->other_addr,
1432 my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC,
1433 POLICY_PRIORITY_DEFAULT, manual_prio);
1434
1435 /* check if we have to update a "dynamic" traffic selector */
1436 if (!me->ip_equals(me, this->my_addr) &&
1437 my_ts->is_host(my_ts, this->my_addr))
1438 {
1439 old_my_ts = my_ts->clone(my_ts);
1440 my_ts->set_address(my_ts, me);
1441 }
1442 if (!other->ip_equals(other, this->other_addr) &&
1443 other_ts->is_host(other_ts, this->other_addr))
1444 {
1445 old_other_ts = other_ts->clone(other_ts);
1446 other_ts->set_address(other_ts, other);
1447 }
1448
1449 /* we reinstall the virtual IP to handle interface roaming
1450 * correctly */
1451 vips->invoke_function(vips, (void*)reinstall_vip, me);
1452
1453 /* reinstall updated policies */
1454 install_policies_internal(this, me, other, my_ts, other_ts,
1455 &my_sa, &other_sa, POLICY_IPSEC,
1456 POLICY_PRIORITY_DEFAULT, manual_prio);
1457
1458 /* update fallback policies after the new policy is in place */
1459 if (manual_prio == 0)
1460 {
1461 del_policies_outbound(this, this->my_addr, this->other_addr,
1462 old_my_ts ?: my_ts,
1463 old_other_ts ?: other_ts,
1464 &my_sa, &other_sa, POLICY_DROP,
1465 POLICY_PRIORITY_FALLBACK, 0);
1466 install_policies_outbound(this, me, other, my_ts, other_ts,
1467 &my_sa, &other_sa, POLICY_DROP,
1468 POLICY_PRIORITY_FALLBACK, 0);
1469 }
1470 DESTROY_IF(old_my_ts);
1471 DESTROY_IF(old_other_ts);
1472 }
1473 enumerator->destroy(enumerator);
1474 }
1475 }
1476
1477 if (!transport_proxy_mode)
1478 {
1479 /* apply hosts */
1480 if (!me->equals(me, this->my_addr))
1481 {
1482 this->my_addr->destroy(this->my_addr);
1483 this->my_addr = me->clone(me);
1484 }
1485 if (!other->equals(other, this->other_addr))
1486 {
1487 this->other_addr->destroy(this->other_addr);
1488 this->other_addr = other->clone(other);
1489 }
1490 }
1491
1492 this->encap = encap;
1493 set_state(this, old);
1494
1495 return SUCCESS;
1496 }
1497
1498 METHOD(child_sa_t, destroy, void,
1499 private_child_sa_t *this)
1500 {
1501 enumerator_t *enumerator;
1502 traffic_selector_t *my_ts, *other_ts;
1503 policy_priority_t priority;
1504
1505 priority = this->trap ? POLICY_PRIORITY_ROUTED : POLICY_PRIORITY_DEFAULT;
1506
1507 set_state(this, CHILD_DESTROYING);
1508
1509 if (!this->config->has_option(this->config, OPT_NO_POLICIES))
1510 {
1511 ipsec_sa_cfg_t my_sa, other_sa;
1512 uint32_t manual_prio;
1513
1514 prepare_sa_cfg(this, &my_sa, &other_sa);
1515 manual_prio = this->config->get_manual_prio(this->config);
1516
1517 /* delete all policies in the kernel */
1518 enumerator = create_policy_enumerator(this);
1519 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1520 {
1521 del_policies_internal(this, this->my_addr, this->other_addr,
1522 my_ts, other_ts, &my_sa, &other_sa,
1523 POLICY_IPSEC, priority, manual_prio);
1524 if (priority == POLICY_PRIORITY_DEFAULT && manual_prio == 0 &&
1525 require_policy_update())
1526 {
1527 del_policies_outbound(this, this->my_addr, this->other_addr,
1528 my_ts, other_ts, &my_sa, &other_sa,
1529 POLICY_DROP, POLICY_PRIORITY_FALLBACK, 0);
1530 }
1531 }
1532 enumerator->destroy(enumerator);
1533 }
1534
1535 /* delete SAs in the kernel, if they are set up */
1536 if (this->my_spi)
1537 {
1538 kernel_ipsec_sa_id_t id = {
1539 .src = this->other_addr,
1540 .dst = this->my_addr,
1541 .spi = this->my_spi,
1542 .proto = proto_ike2ip(this->protocol),
1543 };
1544 kernel_ipsec_del_sa_t sa = {
1545 .cpi = this->my_cpi,
1546 };
1547 charon->kernel->del_sa(charon->kernel, &id, &sa);
1548 }
1549 if (this->other_spi)
1550 {
1551 kernel_ipsec_sa_id_t id = {
1552 .src = this->my_addr,
1553 .dst = this->other_addr,
1554 .spi = this->other_spi,
1555 .proto = proto_ike2ip(this->protocol),
1556 .mark = this->mark_out,
1557 };
1558 kernel_ipsec_del_sa_t sa = {
1559 .cpi = this->other_cpi,
1560 };
1561 charon->kernel->del_sa(charon->kernel, &id, &sa);
1562 }
1563
1564 if (this->reqid_allocated)
1565 {
1566 if (charon->kernel->release_reqid(charon->kernel,
1567 this->reqid, this->mark_in, this->mark_out) != SUCCESS)
1568 {
1569 DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid);
1570 }
1571 }
1572
1573 array_destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
1574 array_destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
1575 this->my_addr->destroy(this->my_addr);
1576 this->other_addr->destroy(this->other_addr);
1577 DESTROY_IF(this->proposal);
1578 this->config->destroy(this->config);
1579 chunk_clear(&this->encr_r);
1580 chunk_clear(&this->integ_r);
1581 free(this);
1582 }
1583
1584 /**
1585 * Get proxy address for one side, if any
1586 */
1587 static host_t* get_proxy_addr(child_cfg_t *config, host_t *ike, bool local)
1588 {
1589 host_t *host = NULL;
1590 uint8_t mask;
1591 enumerator_t *enumerator;
1592 linked_list_t *ts_list, *list;
1593 traffic_selector_t *ts;
1594
1595 list = linked_list_create_with_items(ike, NULL);
1596 ts_list = config->get_traffic_selectors(config, local, NULL, list);
1597 list->destroy(list);
1598
1599 enumerator = ts_list->create_enumerator(ts_list);
1600 while (enumerator->enumerate(enumerator, &ts))
1601 {
1602 if (ts->is_host(ts, NULL) && ts->to_subnet(ts, &host, &mask))
1603 {
1604 DBG1(DBG_CHD, "%s address: %H is a transport mode proxy for %H",
1605 local ? "my" : "other", ike, host);
1606 break;
1607 }
1608 }
1609 enumerator->destroy(enumerator);
1610 ts_list->destroy_offset(ts_list, offsetof(traffic_selector_t, destroy));
1611
1612 if (!host)
1613 {
1614 host = ike->clone(ike);
1615 }
1616 return host;
1617 }
1618
1619 /**
1620 * Described in header.
1621 */
1622 child_sa_t * child_sa_create(host_t *me, host_t* other,
1623 child_cfg_t *config, uint32_t rekey, bool encap,
1624 u_int mark_in, u_int mark_out)
1625 {
1626 private_child_sa_t *this;
1627 static refcount_t unique_id = 0, unique_mark = 0;
1628 refcount_t mark;
1629
1630 INIT(this,
1631 .public = {
1632 .get_name = _get_name,
1633 .get_reqid = _get_reqid,
1634 .get_unique_id = _get_unique_id,
1635 .get_config = _get_config,
1636 .get_state = _get_state,
1637 .set_state = _set_state,
1638 .get_spi = _get_spi,
1639 .get_cpi = _get_cpi,
1640 .get_protocol = _get_protocol,
1641 .set_protocol = _set_protocol,
1642 .get_mode = _get_mode,
1643 .set_mode = _set_mode,
1644 .get_proposal = _get_proposal,
1645 .set_proposal = _set_proposal,
1646 .get_lifetime = _get_lifetime,
1647 .get_installtime = _get_installtime,
1648 .get_usestats = _get_usestats,
1649 .get_mark = _get_mark,
1650 .has_encap = _has_encap,
1651 .get_ipcomp = _get_ipcomp,
1652 .set_ipcomp = _set_ipcomp,
1653 .get_close_action = _get_close_action,
1654 .set_close_action = _set_close_action,
1655 .get_dpd_action = _get_dpd_action,
1656 .set_dpd_action = _set_dpd_action,
1657 .alloc_spi = _alloc_spi,
1658 .alloc_cpi = _alloc_cpi,
1659 .install = _install,
1660 .register_outbound = _register_outbound,
1661 .install_outbound = _install_outbound,
1662 .set_rekey_spi = _set_rekey_spi,
1663 .get_rekey_spi = _get_rekey_spi,
1664 .update = _update,
1665 .set_policies = _set_policies,
1666 .install_policies = _install_policies,
1667 .create_ts_enumerator = _create_ts_enumerator,
1668 .create_policy_enumerator = _create_policy_enumerator,
1669 .destroy = _destroy,
1670 },
1671 .encap = encap,
1672 .ipcomp = IPCOMP_NONE,
1673 .state = CHILD_CREATED,
1674 .my_ts = array_create(0, 0),
1675 .other_ts = array_create(0, 0),
1676 .protocol = PROTO_NONE,
1677 .mode = MODE_TUNNEL,
1678 .close_action = config->get_close_action(config),
1679 .dpd_action = config->get_dpd_action(config),
1680 .reqid = config->get_reqid(config),
1681 .unique_id = ref_get(&unique_id),
1682 .mark_in = config->get_mark(config, TRUE),
1683 .mark_out = config->get_mark(config, FALSE),
1684 .install_time = time_monotonic(NULL),
1685 .policies_fwd_out = config->has_option(config, OPT_FWD_OUT_POLICIES),
1686 );
1687
1688 this->config = config;
1689 config->get_ref(config);
1690
1691 if (mark_in)
1692 {
1693 this->mark_in.value = mark_in;
1694 }
1695 if (mark_out)
1696 {
1697 this->mark_out.value = mark_out;
1698 }
1699 if (this->mark_in.value == MARK_UNIQUE ||
1700 this->mark_out.value == MARK_UNIQUE)
1701 {
1702 mark = ref_get(&unique_mark);
1703 if (this->mark_in.value == MARK_UNIQUE)
1704 {
1705 this->mark_in.value = mark;
1706 }
1707 if (this->mark_out.value == MARK_UNIQUE)
1708 {
1709 this->mark_out.value = mark;
1710 }
1711 }
1712
1713 if (!this->reqid)
1714 {
1715 /* reuse old reqid if we are rekeying an existing CHILD_SA. While the
1716 * reqid cache would find the same reqid for our selectors, this does
1717 * not work in a special case: If an SA is triggered by a trap policy,
1718 * but the negotiated SA gets narrowed, we still must reuse the same
1719 * reqid to successfully "trigger" the SA on the kernel level. Rekeying
1720 * such an SA requires an explicit reqid, as the cache currently knows
1721 * the original selectors only for that reqid. */
1722 if (rekey)
1723 {
1724 this->reqid = rekey;
1725 }
1726 else
1727 {
1728 this->reqid = charon->traps->find_reqid(charon->traps, config);
1729 }
1730 }
1731 else
1732 {
1733 this->static_reqid = TRUE;
1734 }
1735
1736 /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
1737 if (config->get_mode(config) == MODE_TRANSPORT &&
1738 config->has_option(config, OPT_PROXY_MODE))
1739 {
1740 this->mode = MODE_TRANSPORT;
1741
1742 this->my_addr = get_proxy_addr(config, me, TRUE);
1743 this->other_addr = get_proxy_addr(config, other, FALSE);
1744 }
1745 else
1746 {
1747 this->my_addr = me->clone(me);
1748 this->other_addr = other->clone(other);
1749 }
1750 return &this->public;
1751 }