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