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