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