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