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