Merge branch 'ikev1'
[strongswan.git] / src / libcharon / sa / child_sa.c
1 /*
2 * Copyright (C) 2006-2011 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Copyright (C) 2006 Daniel Roethlisberger
5 * Copyright (C) 2005 Jan Hutter
6 * Hochschule fuer Technik Rapperswil
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #define _GNU_SOURCE
20 #include "child_sa.h"
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <time.h>
25
26 #include <hydra.h>
27 #include <daemon.h>
28
29 ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
30 "CREATED",
31 "ROUTED",
32 "INSTALLING",
33 "INSTALLED",
34 "UPDATING",
35 "REKEYING",
36 "DELETING",
37 "DESTROYING",
38 );
39
40 typedef struct private_child_sa_t private_child_sa_t;
41
42 /**
43 * Private data of a child_sa_t object.
44 */
45 struct private_child_sa_t {
46 /**
47 * Public interface of child_sa_t.
48 */
49 child_sa_t public;
50
51 /**
52 * address of us
53 */
54 host_t *my_addr;
55
56 /**
57 * address of remote
58 */
59 host_t *other_addr;
60
61 /**
62 * our actually used SPI, 0 if unused
63 */
64 u_int32_t my_spi;
65
66 /**
67 * others used SPI, 0 if unused
68 */
69 u_int32_t other_spi;
70
71 /**
72 * our Compression Parameter Index (CPI) used, 0 if unused
73 */
74 u_int16_t my_cpi;
75
76 /**
77 * others Compression Parameter Index (CPI) used, 0 if unused
78 */
79 u_int16_t other_cpi;
80
81 /**
82 * List for local traffic selectors
83 */
84 linked_list_t *my_ts;
85
86 /**
87 * List for remote traffic selectors
88 */
89 linked_list_t *other_ts;
90
91 /**
92 * Protocol used to protect this SA, ESP|AH
93 */
94 protocol_id_t protocol;
95
96 /**
97 * reqid used for this child_sa
98 */
99 u_int32_t reqid;
100
101 /**
102 * inbound mark used for this child_sa
103 */
104 mark_t mark_in;
105
106 /**
107 * outbound mark used for this child_sa
108 */
109 mark_t mark_out;
110
111 /**
112 * absolute time when rekeying is scheduled
113 */
114 time_t rekey_time;
115
116 /**
117 * absolute time when the SA expires
118 */
119 time_t expire_time;
120
121 /**
122 * state of the CHILD_SA
123 */
124 child_sa_state_t state;
125
126 /**
127 * Specifies if UDP encapsulation is enabled (NAT traversal)
128 */
129 bool encap;
130
131 /**
132 * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
133 */
134 ipcomp_transform_t ipcomp;
135
136 /**
137 * mode this SA uses, tunnel/transport
138 */
139 ipsec_mode_t mode;
140
141 /**
142 * Action to enforce if peer closes the CHILD_SA
143 */
144 action_t close_action;
145
146 /**
147 * Action to enforce if peer is considered dead
148 */
149 action_t dpd_action;
150
151 /**
152 * selected proposal
153 */
154 proposal_t *proposal;
155
156 /**
157 * config used to create this child
158 */
159 child_cfg_t *config;
160
161 /**
162 * time of last use in seconds (inbound)
163 */
164 u_int32_t my_usetime;
165
166 /**
167 * time of last use in seconds (outbound)
168 */
169 u_int32_t other_usetime;
170
171 /**
172 * last number of inbound bytes
173 */
174 u_int64_t my_usebytes;
175
176 /**
177 * last number of outbound bytes
178 */
179 u_int64_t other_usebytes;
180 };
181
182 /**
183 * convert an IKEv2 specific protocol identifier to the IP protocol identifier.
184 */
185 static inline u_int8_t proto_ike2ip(protocol_id_t protocol)
186 {
187 switch (protocol)
188 {
189 case PROTO_ESP:
190 return IPPROTO_ESP;
191 case PROTO_AH:
192 return IPPROTO_AH;
193 default:
194 return protocol;
195 }
196 }
197
198 METHOD(child_sa_t, get_name, char*,
199 private_child_sa_t *this)
200 {
201 return this->config->get_name(this->config);
202 }
203
204 METHOD(child_sa_t, get_reqid, u_int32_t,
205 private_child_sa_t *this)
206 {
207 return this->reqid;
208 }
209
210 METHOD(child_sa_t, get_config, child_cfg_t*,
211 private_child_sa_t *this)
212 {
213 return this->config;
214 }
215
216 METHOD(child_sa_t, set_state, void,
217 private_child_sa_t *this, child_sa_state_t state)
218 {
219 charon->bus->child_state_change(charon->bus, &this->public, state);
220 this->state = state;
221 }
222
223 METHOD(child_sa_t, get_state, child_sa_state_t,
224 private_child_sa_t *this)
225 {
226 return this->state;
227 }
228
229 METHOD(child_sa_t, get_spi, u_int32_t,
230 private_child_sa_t *this, bool inbound)
231 {
232 return inbound ? this->my_spi : this->other_spi;
233 }
234
235 METHOD(child_sa_t, get_cpi, u_int16_t,
236 private_child_sa_t *this, bool inbound)
237 {
238 return inbound ? this->my_cpi : this->other_cpi;
239 }
240
241 METHOD(child_sa_t, get_protocol, protocol_id_t,
242 private_child_sa_t *this)
243 {
244 return this->protocol;
245 }
246
247 METHOD(child_sa_t, set_protocol, void,
248 private_child_sa_t *this, protocol_id_t protocol)
249 {
250 this->protocol = protocol;
251 }
252
253 METHOD(child_sa_t, get_mode, ipsec_mode_t,
254 private_child_sa_t *this)
255 {
256 return this->mode;
257 }
258
259 METHOD(child_sa_t, set_mode, void,
260 private_child_sa_t *this, ipsec_mode_t mode)
261 {
262 this->mode = mode;
263 }
264
265 METHOD(child_sa_t, has_encap, bool,
266 private_child_sa_t *this)
267 {
268 return this->encap;
269 }
270
271 METHOD(child_sa_t, get_ipcomp, ipcomp_transform_t,
272 private_child_sa_t *this)
273 {
274 return this->ipcomp;
275 }
276
277 METHOD(child_sa_t, set_ipcomp, void,
278 private_child_sa_t *this, ipcomp_transform_t ipcomp)
279 {
280 this->ipcomp = ipcomp;
281 }
282
283 METHOD(child_sa_t, set_close_action, void,
284 private_child_sa_t *this, action_t action)
285 {
286 this->close_action = action;
287 }
288
289 METHOD(child_sa_t, get_close_action, action_t,
290 private_child_sa_t *this)
291 {
292 return this->close_action;
293 }
294
295 METHOD(child_sa_t, set_dpd_action, void,
296 private_child_sa_t *this, action_t action)
297 {
298 this->dpd_action = action;
299 }
300
301 METHOD(child_sa_t, get_dpd_action, action_t,
302 private_child_sa_t *this)
303 {
304 return this->dpd_action;
305 }
306
307 METHOD(child_sa_t, get_proposal, proposal_t*,
308 private_child_sa_t *this)
309 {
310 return this->proposal;
311 }
312
313 METHOD(child_sa_t, set_proposal, void,
314 private_child_sa_t *this, proposal_t *proposal)
315 {
316 this->proposal = proposal->clone(proposal);
317 }
318
319 METHOD(child_sa_t, get_traffic_selectors, linked_list_t*,
320 private_child_sa_t *this, bool local)
321 {
322 return local ? this->my_ts : this->other_ts;
323 }
324
325 typedef struct policy_enumerator_t policy_enumerator_t;
326
327 /**
328 * Private policy enumerator
329 */
330 struct policy_enumerator_t {
331 /** implements enumerator_t */
332 enumerator_t public;
333 /** enumerator over own TS */
334 enumerator_t *mine;
335 /** enumerator over others TS */
336 enumerator_t *other;
337 /** list of others TS, to recreate enumerator */
338 linked_list_t *list;
339 /** currently enumerating TS for "me" side */
340 traffic_selector_t *ts;
341 };
342
343 METHOD(enumerator_t, policy_enumerate, bool,
344 policy_enumerator_t *this, traffic_selector_t **my_out,
345 traffic_selector_t **other_out)
346 {
347 traffic_selector_t *other_ts;
348
349 while (this->ts || this->mine->enumerate(this->mine, &this->ts))
350 {
351 if (!this->other->enumerate(this->other, &other_ts))
352 { /* end of others list, restart with new of mine */
353 this->other->destroy(this->other);
354 this->other = this->list->create_enumerator(this->list);
355 this->ts = NULL;
356 continue;
357 }
358 if (this->ts->get_type(this->ts) != other_ts->get_type(other_ts))
359 { /* family mismatch */
360 continue;
361 }
362 if (this->ts->get_protocol(this->ts) &&
363 other_ts->get_protocol(other_ts) &&
364 this->ts->get_protocol(this->ts) != other_ts->get_protocol(other_ts))
365 { /* protocol mismatch */
366 continue;
367 }
368 *my_out = this->ts;
369 *other_out = other_ts;
370 return TRUE;
371 }
372 return FALSE;
373 }
374
375 METHOD(enumerator_t, policy_destroy, void,
376 policy_enumerator_t *this)
377 {
378 this->mine->destroy(this->mine);
379 this->other->destroy(this->other);
380 free(this);
381 }
382
383 METHOD(child_sa_t, create_policy_enumerator, enumerator_t*,
384 private_child_sa_t *this)
385 {
386 policy_enumerator_t *e;
387
388 INIT(e,
389 .public = {
390 .enumerate = (void*)_policy_enumerate,
391 .destroy = _policy_destroy,
392 },
393 .mine = this->my_ts->create_enumerator(this->my_ts),
394 .other = this->other_ts->create_enumerator(this->other_ts),
395 .list = this->other_ts,
396 .ts = NULL,
397 );
398
399 return &e->public;
400 }
401
402 /**
403 * update the cached usebytes
404 * returns SUCCESS if the usebytes have changed, FAILED if not or no SPIs
405 * are available, and NOT_SUPPORTED if the kernel interface does not support
406 * querying the usebytes.
407 */
408 static status_t update_usebytes(private_child_sa_t *this, bool inbound)
409 {
410 status_t status = FAILED;
411 u_int64_t bytes;
412
413 if (inbound)
414 {
415 if (this->my_spi)
416 {
417 status = hydra->kernel_interface->query_sa(hydra->kernel_interface,
418 this->other_addr, this->my_addr, this->my_spi,
419 proto_ike2ip(this->protocol), this->mark_in,
420 &bytes);
421 if (status == SUCCESS)
422 {
423 if (bytes > this->my_usebytes)
424 {
425 this->my_usebytes = bytes;
426 return SUCCESS;
427 }
428 return FAILED;
429 }
430 }
431 }
432 else
433 {
434 if (this->other_spi)
435 {
436 status = hydra->kernel_interface->query_sa(hydra->kernel_interface,
437 this->my_addr, this->other_addr, this->other_spi,
438 proto_ike2ip(this->protocol), this->mark_out,
439 &bytes);
440 if (status == SUCCESS)
441 {
442 if (bytes > this->other_usebytes)
443 {
444 this->other_usebytes = bytes;
445 return SUCCESS;
446 }
447 return FAILED;
448 }
449 }
450 }
451 return status;
452 }
453
454 /**
455 * updates the cached usetime
456 */
457 static void update_usetime(private_child_sa_t *this, bool inbound)
458 {
459 enumerator_t *enumerator;
460 traffic_selector_t *my_ts, *other_ts;
461 u_int32_t last_use = 0;
462
463 enumerator = create_policy_enumerator(this);
464 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
465 {
466 u_int32_t in, out, fwd;
467
468 if (inbound)
469 {
470 if (hydra->kernel_interface->query_policy(hydra->kernel_interface,
471 other_ts, my_ts, POLICY_IN, this->mark_in, &in) == SUCCESS)
472 {
473 last_use = max(last_use, in);
474 }
475 if (this->mode != MODE_TRANSPORT)
476 {
477 if (hydra->kernel_interface->query_policy(hydra->kernel_interface,
478 other_ts, my_ts, POLICY_FWD, this->mark_in, &fwd) == SUCCESS)
479 {
480 last_use = max(last_use, fwd);
481 }
482 }
483 }
484 else
485 {
486 if (hydra->kernel_interface->query_policy(hydra->kernel_interface,
487 my_ts, other_ts, POLICY_OUT, this->mark_out, &out) == SUCCESS)
488 {
489 last_use = max(last_use, out);
490 }
491 }
492 }
493 enumerator->destroy(enumerator);
494
495 if (last_use == 0)
496 {
497 return;
498 }
499 if (inbound)
500 {
501 this->my_usetime = last_use;
502 }
503 else
504 {
505 this->other_usetime = last_use;
506 }
507 }
508
509 METHOD(child_sa_t, get_usestats, void,
510 private_child_sa_t *this, bool inbound, time_t *time, u_int64_t *bytes)
511 {
512 if (update_usebytes(this, inbound) != FAILED)
513 {
514 /* there was traffic since last update or the kernel interface
515 * does not support querying the number of usebytes.
516 */
517 update_usetime(this, inbound);
518 }
519 if (time)
520 {
521 *time = inbound ? this->my_usetime : this->other_usetime;
522 }
523 if (bytes)
524 {
525 *bytes = inbound ? this->my_usebytes : this->other_usebytes;
526 }
527 }
528
529 METHOD(child_sa_t, get_mark, mark_t,
530 private_child_sa_t *this, bool inbound)
531 {
532 if (inbound)
533 {
534 return this->mark_in;
535 }
536 return this->mark_out;
537 }
538
539 METHOD(child_sa_t, get_lifetime, time_t,
540 private_child_sa_t *this, bool hard)
541 {
542 return hard ? this->expire_time : this->rekey_time;
543 }
544
545 METHOD(child_sa_t, alloc_spi, u_int32_t,
546 private_child_sa_t *this, protocol_id_t protocol)
547 {
548 if (hydra->kernel_interface->get_spi(hydra->kernel_interface,
549 this->other_addr, this->my_addr,
550 proto_ike2ip(protocol), this->reqid,
551 &this->my_spi) == SUCCESS)
552 {
553 return this->my_spi;
554 }
555 return 0;
556 }
557
558 METHOD(child_sa_t, alloc_cpi, u_int16_t,
559 private_child_sa_t *this)
560 {
561 if (hydra->kernel_interface->get_cpi(hydra->kernel_interface,
562 this->other_addr, this->my_addr,
563 this->reqid, &this->my_cpi) == SUCCESS)
564 {
565 return this->my_cpi;
566 }
567 return 0;
568 }
569
570 METHOD(child_sa_t, install, status_t,
571 private_child_sa_t *this, chunk_t encr, chunk_t integ, u_int32_t spi,
572 u_int16_t cpi, bool inbound, bool tfcv3, linked_list_t *my_ts,
573 linked_list_t *other_ts)
574 {
575 u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
576 u_int16_t esn = NO_EXT_SEQ_NUMBERS;
577 traffic_selector_t *src_ts = NULL, *dst_ts = NULL;
578 time_t now;
579 lifetime_cfg_t *lifetime;
580 u_int32_t tfc = 0;
581 host_t *src, *dst;
582 status_t status;
583 bool update = FALSE;
584
585 /* now we have to decide which spi to use. Use self allocated, if "in",
586 * or the one in the proposal, if not "in" (others). Additionally,
587 * source and dest host switch depending on the role */
588 if (inbound)
589 {
590 dst = this->my_addr;
591 src = this->other_addr;
592 if (this->my_spi == spi)
593 { /* alloc_spi has been called, do an SA update */
594 update = TRUE;
595 }
596 this->my_spi = spi;
597 this->my_cpi = cpi;
598 }
599 else
600 {
601 src = this->my_addr;
602 dst = this->other_addr;
603 this->other_spi = spi;
604 this->other_cpi = cpi;
605
606 if (tfcv3)
607 {
608 tfc = this->config->get_tfc(this->config);
609 }
610 }
611
612 DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
613 protocol_id_names, this->protocol);
614
615 /* send SA down to the kernel */
616 DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
617
618 this->proposal->get_algorithm(this->proposal, ENCRYPTION_ALGORITHM,
619 &enc_alg, &size);
620 this->proposal->get_algorithm(this->proposal, INTEGRITY_ALGORITHM,
621 &int_alg, &size);
622 this->proposal->get_algorithm(this->proposal, EXTENDED_SEQUENCE_NUMBERS,
623 &esn, NULL);
624
625 lifetime = this->config->get_lifetime(this->config);
626
627 now = time_monotonic(NULL);
628 if (lifetime->time.rekey)
629 {
630 this->rekey_time = now + lifetime->time.rekey;
631 }
632 if (lifetime->time.life)
633 {
634 this->expire_time = now + lifetime->time.life;
635 }
636
637 if (!lifetime->time.jitter && !inbound)
638 { /* avoid triggering multiple rekey events */
639 lifetime->time.rekey = 0;
640 }
641
642 if (this->mode == MODE_BEET || this->mode == MODE_TRANSPORT)
643 {
644 /* BEET requires the bound address from the traffic selectors.
645 * TODO: We add just the first traffic selector for now, as the
646 * kernel accepts a single TS per SA only */
647 if (inbound)
648 {
649 my_ts->get_first(my_ts, (void**)&dst_ts);
650 other_ts->get_first(other_ts, (void**)&src_ts);
651 }
652 else
653 {
654 my_ts->get_first(my_ts, (void**)&src_ts);
655 other_ts->get_first(other_ts, (void**)&dst_ts);
656 }
657 }
658
659 status = hydra->kernel_interface->add_sa(hydra->kernel_interface,
660 src, dst, spi, proto_ike2ip(this->protocol), this->reqid,
661 inbound ? this->mark_in : this->mark_out, tfc,
662 lifetime, enc_alg, encr, int_alg, integ, this->mode,
663 this->ipcomp, cpi, this->encap, esn, update, src_ts, dst_ts);
664
665 free(lifetime);
666
667 return status;
668 }
669
670 /**
671 * Install 3 policies: out, in and forward
672 */
673 static status_t install_policies_internal(private_child_sa_t *this,
674 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
675 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
676 ipsec_sa_cfg_t *other_sa, policy_type_t type, policy_priority_t priority)
677 {
678 status_t status = SUCCESS;
679 status |= hydra->kernel_interface->add_policy(hydra->kernel_interface,
680 my_addr, other_addr, my_ts, other_ts,
681 POLICY_OUT, type, other_sa,
682 this->mark_out, priority);
683
684 status |= hydra->kernel_interface->add_policy(hydra->kernel_interface,
685 other_addr, my_addr, other_ts, my_ts,
686 POLICY_IN, type, my_sa,
687 this->mark_in, priority);
688 if (this->mode != MODE_TRANSPORT)
689 {
690 status |= hydra->kernel_interface->add_policy(hydra->kernel_interface,
691 other_addr, my_addr, other_ts, my_ts,
692 POLICY_FWD, type, my_sa,
693 this->mark_in, priority);
694 }
695 return status;
696 }
697
698 /**
699 * Delete 3 policies: out, in and forward
700 */
701 static void del_policies_internal(private_child_sa_t *this,
702 traffic_selector_t *my_ts, traffic_selector_t *other_ts,
703 policy_priority_t priority)
704 {
705 hydra->kernel_interface->del_policy(hydra->kernel_interface,
706 my_ts, other_ts, POLICY_OUT, this->reqid,
707 this->mark_out, priority);
708 hydra->kernel_interface->del_policy(hydra->kernel_interface,
709 other_ts, my_ts, POLICY_IN, this->reqid,
710 this->mark_in, priority);
711 if (this->mode != MODE_TRANSPORT)
712 {
713 hydra->kernel_interface->del_policy(hydra->kernel_interface,
714 other_ts, my_ts, POLICY_FWD, this->reqid,
715 this->mark_in, priority);
716 }
717 }
718
719 METHOD(child_sa_t, add_policies, status_t,
720 private_child_sa_t *this, linked_list_t *my_ts_list,
721 linked_list_t *other_ts_list)
722 {
723 enumerator_t *enumerator;
724 traffic_selector_t *my_ts, *other_ts;
725 status_t status = SUCCESS;
726
727 /* apply traffic selectors */
728 enumerator = my_ts_list->create_enumerator(my_ts_list);
729 while (enumerator->enumerate(enumerator, &my_ts))
730 {
731 this->my_ts->insert_last(this->my_ts, my_ts->clone(my_ts));
732 }
733 enumerator->destroy(enumerator);
734 enumerator = other_ts_list->create_enumerator(other_ts_list);
735 while (enumerator->enumerate(enumerator, &other_ts))
736 {
737 this->other_ts->insert_last(this->other_ts, other_ts->clone(other_ts));
738 }
739 enumerator->destroy(enumerator);
740
741 if (this->config->install_policy(this->config))
742 {
743 policy_priority_t priority;
744 ipsec_sa_cfg_t my_sa = {
745 .mode = this->mode,
746 .reqid = this->reqid,
747 .ipcomp = {
748 .transform = this->ipcomp,
749 },
750 }, other_sa = my_sa;
751
752 my_sa.ipcomp.cpi = this->my_cpi;
753 other_sa.ipcomp.cpi = this->other_cpi;
754
755 if (this->protocol == PROTO_ESP)
756 {
757 my_sa.esp.use = TRUE;
758 my_sa.esp.spi = this->my_spi;
759 other_sa.esp.use = TRUE;
760 other_sa.esp.spi = this->other_spi;
761 }
762 else
763 {
764 my_sa.ah.use = TRUE;
765 my_sa.ah.spi = this->my_spi;
766 other_sa.ah.use = TRUE;
767 other_sa.ah.spi = this->other_spi;
768 }
769
770 priority = this->state == CHILD_CREATED ? POLICY_PRIORITY_ROUTED
771 : POLICY_PRIORITY_DEFAULT;
772
773 /* enumerate pairs of traffic selectors */
774 enumerator = create_policy_enumerator(this);
775 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
776 {
777 /* install outbound drop policy to avoid packets leaving unencrypted
778 * when updating policies */
779 if (priority == POLICY_PRIORITY_DEFAULT)
780 {
781 status |= install_policies_internal(this, this->my_addr,
782 this->other_addr, my_ts, other_ts,
783 &my_sa, &other_sa, POLICY_DROP,
784 POLICY_PRIORITY_FALLBACK);
785 }
786
787 /* install policies */
788 status |= install_policies_internal(this, this->my_addr,
789 this->other_addr, my_ts, other_ts,
790 &my_sa, &other_sa, POLICY_IPSEC, priority);
791
792 if (status != SUCCESS)
793 {
794 break;
795 }
796 }
797 enumerator->destroy(enumerator);
798 }
799
800 if (status == SUCCESS && this->state == CHILD_CREATED)
801 { /* switch to routed state if no SAD entry set up */
802 set_state(this, CHILD_ROUTED);
803 }
804 return status;
805 }
806
807 METHOD(child_sa_t, update, status_t,
808 private_child_sa_t *this, host_t *me, host_t *other, host_t *vip,
809 bool encap)
810 {
811 child_sa_state_t old;
812 bool transport_proxy_mode;
813
814 /* anything changed at all? */
815 if (me->equals(me, this->my_addr) &&
816 other->equals(other, this->other_addr) && this->encap == encap)
817 {
818 return SUCCESS;
819 }
820
821 old = this->state;
822 set_state(this, CHILD_UPDATING);
823 transport_proxy_mode = this->config->use_proxy_mode(this->config) &&
824 this->mode == MODE_TRANSPORT;
825
826 if (!transport_proxy_mode)
827 {
828 /* update our (initiator) SA */
829 if (this->my_spi)
830 {
831 if (hydra->kernel_interface->update_sa(hydra->kernel_interface,
832 this->my_spi, proto_ike2ip(this->protocol),
833 this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
834 this->other_addr, this->my_addr, other, me,
835 this->encap, encap, this->mark_in) == NOT_SUPPORTED)
836 {
837 return NOT_SUPPORTED;
838 }
839 }
840
841 /* update his (responder) SA */
842 if (this->other_spi)
843 {
844 if (hydra->kernel_interface->update_sa(hydra->kernel_interface,
845 this->other_spi, proto_ike2ip(this->protocol),
846 this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
847 this->my_addr, this->other_addr, me, other,
848 this->encap, encap, this->mark_out) == NOT_SUPPORTED)
849 {
850 return NOT_SUPPORTED;
851 }
852 }
853 }
854
855 if (this->config->install_policy(this->config))
856 {
857 ipsec_sa_cfg_t my_sa = {
858 .mode = this->mode,
859 .reqid = this->reqid,
860 .ipcomp = {
861 .transform = this->ipcomp,
862 },
863 }, other_sa = my_sa;
864
865 my_sa.ipcomp.cpi = this->my_cpi;
866 other_sa.ipcomp.cpi = this->other_cpi;
867
868 if (this->protocol == PROTO_ESP)
869 {
870 my_sa.esp.use = TRUE;
871 my_sa.esp.spi = this->my_spi;
872 other_sa.esp.use = TRUE;
873 other_sa.esp.spi = this->other_spi;
874 }
875 else
876 {
877 my_sa.ah.use = TRUE;
878 my_sa.ah.spi = this->my_spi;
879 other_sa.ah.use = TRUE;
880 other_sa.ah.spi = this->other_spi;
881 }
882
883 /* update policies */
884 if (!me->ip_equals(me, this->my_addr) ||
885 !other->ip_equals(other, this->other_addr))
886 {
887 enumerator_t *enumerator;
888 traffic_selector_t *my_ts, *other_ts;
889
890 /* always use high priorities, as hosts getting updated are INSTALLED */
891 enumerator = create_policy_enumerator(this);
892 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
893 {
894 traffic_selector_t *old_my_ts = NULL, *old_other_ts = NULL;
895 /* remove old policies first */
896 del_policies_internal(this, my_ts, other_ts,
897 POLICY_PRIORITY_DEFAULT);
898
899 /* check if we have to update a "dynamic" traffic selector */
900 if (!me->ip_equals(me, this->my_addr) &&
901 my_ts->is_host(my_ts, this->my_addr))
902 {
903 old_my_ts = my_ts->clone(my_ts);
904 my_ts->set_address(my_ts, me);
905 }
906 if (!other->ip_equals(other, this->other_addr) &&
907 other_ts->is_host(other_ts, this->other_addr))
908 {
909 old_other_ts = other_ts->clone(other_ts);
910 other_ts->set_address(other_ts, other);
911 }
912
913 /* we reinstall the virtual IP to handle interface roaming
914 * correctly */
915 if (vip)
916 {
917 hydra->kernel_interface->del_ip(hydra->kernel_interface,
918 vip);
919 hydra->kernel_interface->add_ip(hydra->kernel_interface,
920 vip, me);
921 }
922
923 /* reinstall updated policies */
924 install_policies_internal(this, me, other, my_ts, other_ts,
925 &my_sa, &other_sa, POLICY_IPSEC,
926 POLICY_PRIORITY_DEFAULT);
927
928 /* update fallback policies after the new policy is in place */
929 if (old_my_ts || old_other_ts)
930 {
931 del_policies_internal(this, old_my_ts ?: my_ts,
932 old_other_ts ?: other_ts,
933 POLICY_PRIORITY_FALLBACK);
934 install_policies_internal(this, me, other, my_ts, other_ts,
935 &my_sa, &other_sa, POLICY_DROP,
936 POLICY_PRIORITY_FALLBACK);
937 DESTROY_IF(old_my_ts);
938 DESTROY_IF(old_other_ts);
939 }
940 }
941 enumerator->destroy(enumerator);
942 }
943 }
944
945 if (!transport_proxy_mode)
946 {
947 /* apply hosts */
948 if (!me->equals(me, this->my_addr))
949 {
950 this->my_addr->destroy(this->my_addr);
951 this->my_addr = me->clone(me);
952 }
953 if (!other->equals(other, this->other_addr))
954 {
955 this->other_addr->destroy(this->other_addr);
956 this->other_addr = other->clone(other);
957 }
958 }
959
960 this->encap = encap;
961 set_state(this, old);
962
963 return SUCCESS;
964 }
965
966 METHOD(child_sa_t, destroy, void,
967 private_child_sa_t *this)
968 {
969 enumerator_t *enumerator;
970 traffic_selector_t *my_ts, *other_ts;
971 policy_priority_t priority;
972
973 priority = this->state == CHILD_ROUTED ? POLICY_PRIORITY_ROUTED
974 : POLICY_PRIORITY_DEFAULT;
975
976 set_state(this, CHILD_DESTROYING);
977
978 /* delete SAs in the kernel, if they are set up */
979 if (this->my_spi)
980 {
981 /* if CHILD was not established, use PROTO_ESP used during alloc_spi().
982 * TODO: For AH support, we have to store protocol specific SPI.s */
983 if (this->protocol == PROTO_NONE)
984 {
985 this->protocol = PROTO_ESP;
986 }
987 hydra->kernel_interface->del_sa(hydra->kernel_interface,
988 this->other_addr, this->my_addr, this->my_spi,
989 proto_ike2ip(this->protocol), this->my_cpi,
990 this->mark_in);
991 }
992 if (this->other_spi)
993 {
994 hydra->kernel_interface->del_sa(hydra->kernel_interface,
995 this->my_addr, this->other_addr, this->other_spi,
996 proto_ike2ip(this->protocol), this->other_cpi,
997 this->mark_out);
998 }
999
1000 if (this->config->install_policy(this->config))
1001 {
1002 /* delete all policies in the kernel */
1003 enumerator = create_policy_enumerator(this);
1004 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1005 {
1006 del_policies_internal(this, my_ts, other_ts, priority);
1007 if (priority == POLICY_PRIORITY_DEFAULT)
1008 {
1009 del_policies_internal(this, my_ts, other_ts,
1010 POLICY_PRIORITY_FALLBACK);
1011 }
1012 }
1013 enumerator->destroy(enumerator);
1014 }
1015
1016 this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
1017 this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
1018 this->my_addr->destroy(this->my_addr);
1019 this->other_addr->destroy(this->other_addr);
1020 DESTROY_IF(this->proposal);
1021 this->config->destroy(this->config);
1022 free(this);
1023 }
1024
1025 /**
1026 * Described in header.
1027 */
1028 child_sa_t * child_sa_create(host_t *me, host_t* other,
1029 child_cfg_t *config, u_int32_t rekey, bool encap)
1030 {
1031 static u_int32_t reqid = 0;
1032 private_child_sa_t *this;
1033
1034 INIT(this,
1035 .public = {
1036 .get_name = _get_name,
1037 .get_reqid = _get_reqid,
1038 .get_config = _get_config,
1039 .get_state = _get_state,
1040 .set_state = _set_state,
1041 .get_spi = _get_spi,
1042 .get_cpi = _get_cpi,
1043 .get_protocol = _get_protocol,
1044 .set_protocol = _set_protocol,
1045 .get_mode = _get_mode,
1046 .set_mode = _set_mode,
1047 .get_proposal = _get_proposal,
1048 .set_proposal = _set_proposal,
1049 .get_lifetime = _get_lifetime,
1050 .get_usestats = _get_usestats,
1051 .get_mark = _get_mark,
1052 .has_encap = _has_encap,
1053 .get_ipcomp = _get_ipcomp,
1054 .set_ipcomp = _set_ipcomp,
1055 .get_close_action = _get_close_action,
1056 .set_close_action = _set_close_action,
1057 .get_dpd_action = _get_dpd_action,
1058 .set_dpd_action = _set_dpd_action,
1059 .alloc_spi = _alloc_spi,
1060 .alloc_cpi = _alloc_cpi,
1061 .install = _install,
1062 .update = _update,
1063 .add_policies = _add_policies,
1064 .get_traffic_selectors = _get_traffic_selectors,
1065 .create_policy_enumerator = _create_policy_enumerator,
1066 .destroy = _destroy,
1067 },
1068 .my_addr = me->clone(me),
1069 .other_addr = other->clone(other),
1070 .encap = encap,
1071 .ipcomp = IPCOMP_NONE,
1072 .state = CHILD_CREATED,
1073 .my_ts = linked_list_create(),
1074 .other_ts = linked_list_create(),
1075 .protocol = PROTO_NONE,
1076 .mode = MODE_TUNNEL,
1077 .close_action = config->get_close_action(config),
1078 .dpd_action = config->get_dpd_action(config),
1079 .reqid = config->get_reqid(config),
1080 .mark_in = config->get_mark(config, TRUE),
1081 .mark_out = config->get_mark(config, FALSE),
1082 );
1083
1084 this->config = config;
1085 config->get_ref(config);
1086
1087 if (!this->reqid)
1088 {
1089 /* reuse old reqid if we are rekeying an existing CHILD_SA */
1090 this->reqid = rekey ? rekey : ++reqid;
1091 }
1092
1093 if (this->mark_in.value == MARK_REQID)
1094 {
1095 this->mark_in.value = this->reqid;
1096 }
1097 if (this->mark_out.value == MARK_REQID)
1098 {
1099 this->mark_out.value = this->reqid;
1100 }
1101
1102 /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
1103 if (config->get_mode(config) == MODE_TRANSPORT &&
1104 config->use_proxy_mode(config))
1105 {
1106 ts_type_t type;
1107 int family;
1108 chunk_t addr;
1109 host_t *host;
1110 enumerator_t *enumerator;
1111 linked_list_t *my_ts_list, *other_ts_list;
1112 traffic_selector_t *my_ts, *other_ts;
1113
1114 this->mode = MODE_TRANSPORT;
1115
1116 my_ts_list = config->get_traffic_selectors(config, TRUE, NULL, me);
1117 enumerator = my_ts_list->create_enumerator(my_ts_list);
1118 if (enumerator->enumerate(enumerator, &my_ts))
1119 {
1120 if (my_ts->is_host(my_ts, NULL) &&
1121 !my_ts->is_host(my_ts, this->my_addr))
1122 {
1123 type = my_ts->get_type(my_ts);
1124 family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
1125 addr = my_ts->get_from_address(my_ts);
1126 host = host_create_from_chunk(family, addr, 0);
1127 free(addr.ptr);
1128 DBG1(DBG_CHD, "my address: %H is a transport mode proxy for %H",
1129 this->my_addr, host);
1130 this->my_addr->destroy(this->my_addr);
1131 this->my_addr = host;
1132 }
1133 }
1134 enumerator->destroy(enumerator);
1135 my_ts_list->destroy_offset(my_ts_list, offsetof(traffic_selector_t, destroy));
1136
1137 other_ts_list = config->get_traffic_selectors(config, FALSE, NULL, other);
1138 enumerator = other_ts_list->create_enumerator(other_ts_list);
1139 if (enumerator->enumerate(enumerator, &other_ts))
1140 {
1141 if (other_ts->is_host(other_ts, NULL) &&
1142 !other_ts->is_host(other_ts, this->other_addr))
1143 {
1144 type = other_ts->get_type(other_ts);
1145 family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
1146 addr = other_ts->get_from_address(other_ts);
1147 host = host_create_from_chunk(family, addr, 0);
1148 free(addr.ptr);
1149 DBG1(DBG_CHD, "other address: %H is a transport mode proxy for %H",
1150 this->other_addr, host);
1151 this->other_addr->destroy(this->other_addr);
1152 this->other_addr = host;
1153 }
1154 }
1155 enumerator->destroy(enumerator);
1156 other_ts_list->destroy_offset(other_ts_list, offsetof(traffic_selector_t, destroy));
1157 }
1158
1159 return &this->public;
1160 }