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