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