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