8a7e64ac4039e6e1229687f47637233ed6bb1e85
[strongswan.git] / src / charon / sa / child_sa.c
1 /**
2 * @file child_sa.c
3 *
4 * @brief Implementation of child_sa_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
10 * Copyright (C) 2005-2006 Martin Willi
11 * Copyright (C) 2005 Jan Hutter
12 * Hochschule fuer Technik Rapperswil
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 */
24
25 #include "child_sa.h"
26
27 #include <string.h>
28
29 #include <daemon.h>
30
31
32 /**
33 * String mappings for child_sa_state_t.
34 */
35 mapping_t child_sa_state_m[] = {
36 {CHILD_CREATED, "CREATED"},
37 {CHILD_INSTALLED, "INSTALLED"},
38 {CHILD_ROUTED, "ROUTED"},
39 {CHILD_REKEYING, "REKEYING"},
40 {CHILD_DELETING, "DELETING"},
41 {MAPPING_END, NULL}
42 };
43
44 typedef struct sa_policy_t sa_policy_t;
45
46 /**
47 * Struct used to store information for a policy. This
48 * is needed since we must provide all this information
49 * for deleting a policy...
50 */
51 struct sa_policy_t {
52 /**
53 * Traffic selector for us
54 */
55 traffic_selector_t *my_ts;
56
57 /**
58 * Traffic selector for other
59 */
60 traffic_selector_t *other_ts;
61 };
62
63 typedef struct private_child_sa_t private_child_sa_t;
64
65 /**
66 * Private data of a child_sa_t object.
67 */
68 struct private_child_sa_t {
69 /**
70 * Public interface of child_sa_t.
71 */
72 child_sa_t public;
73
74 /**
75 * Name of the policy used by this CHILD_SA
76 */
77 char *name;
78
79 struct {
80 /** address of peer */
81 host_t *addr;
82 /** actual used SPI, 0 if unused */
83 u_int32_t spi;
84 } me, other;
85
86 /**
87 * Allocated SPI for a ESP proposal candidates
88 */
89 u_int32_t alloc_esp_spi;
90
91 /**
92 * Allocated SPI for a AH proposal candidates
93 */
94 u_int32_t alloc_ah_spi;
95
96 /**
97 * Protocol used to protect this SA, ESP|AH
98 */
99 protocol_id_t protocol;
100
101 /**
102 * List containing sa_policy_t objects
103 */
104 linked_list_t *policies;
105
106 /**
107 * Seperate list for local traffic selectors
108 */
109 linked_list_t *my_ts;
110
111 /**
112 * Seperate list for remote traffic selectors
113 */
114 linked_list_t *other_ts;
115
116 /**
117 * reqid used for this child_sa
118 */
119 u_int32_t reqid;
120
121 /**
122 * encryption algorithm used for this SA
123 */
124 algorithm_t encryption;
125
126 /**
127 * integrity protection algorithm used for this SA
128 */
129 algorithm_t integrity;
130
131 /**
132 * time, on which SA was installed
133 */
134 time_t install_time;
135
136 /**
137 * Lifetime before rekeying
138 */
139 u_int32_t soft_lifetime;
140
141 /**
142 * Lifetime before delete
143 */
144 u_int32_t hard_lifetime;
145
146 /**
147 * state of the CHILD_SA
148 */
149 child_sa_state_t state;
150
151 /**
152 * transaction which is rekeying this CHILD_SA
153 */
154 void *rekeying_transaction;
155
156 /**
157 * Specifies if NAT traversal is used
158 */
159 bool use_natt;
160
161 /**
162 * Specifies if CHILD_SA goes to ROUTED state if DPD detected
163 */
164 bool stays_routed;
165
166 /**
167 * CHILD_SAs own logger
168 */
169 logger_t *logger;
170 };
171
172 /**
173 * Implementation of child_sa_t.get_name.
174 */
175 static char *get_name(private_child_sa_t *this)
176 {
177 return this->name;
178 }
179
180 /**
181 * Implementation of child_sa_t.set_name.
182 */
183 static void set_name(private_child_sa_t *this, char* name)
184 {
185 free(this->name);
186 this->name = strdup(name);
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_spi
199 */
200 u_int32_t get_spi(private_child_sa_t *this, bool inbound)
201 {
202 if (inbound)
203 {
204 return this->me.spi;
205 }
206 return this->other.spi;
207 }
208
209 /**
210 * Implements child_sa_t.get_protocol
211 */
212 protocol_id_t get_protocol(private_child_sa_t *this)
213 {
214 return this->protocol;
215 }
216
217 /**
218 * Implements child_sa_t.get_state
219 */
220 static child_sa_state_t get_state(private_child_sa_t *this)
221 {
222 return this->state;
223 }
224
225 /**
226 * Implements child_sa_t.set_state
227 */
228 static void set_state(private_child_sa_t *this, child_sa_state_t state)
229 {
230 this->state = state;
231 }
232
233 /**
234 * Allocate SPI for a single proposal
235 */
236 static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal)
237 {
238 protocol_id_t protocol = proposal->get_protocol(proposal);
239
240 if (protocol == PROTO_AH)
241 {
242 /* get a new spi for AH, if not already done */
243 if (this->alloc_ah_spi == 0)
244 {
245 if (charon->kernel_interface->get_spi(
246 charon->kernel_interface,
247 this->other.addr, this->me.addr,
248 PROTO_AH, this->reqid,
249 &this->alloc_ah_spi) != SUCCESS)
250 {
251 return FAILED;
252 }
253 }
254 proposal->set_spi(proposal, this->alloc_ah_spi);
255 }
256 if (protocol == PROTO_ESP)
257 {
258 /* get a new spi for ESP, if not already done */
259 if (this->alloc_esp_spi == 0)
260 {
261 if (charon->kernel_interface->get_spi(
262 charon->kernel_interface,
263 this->other.addr, this->me.addr,
264 PROTO_ESP, this->reqid,
265 &this->alloc_esp_spi) != SUCCESS)
266 {
267 return FAILED;
268 }
269 }
270 proposal->set_spi(proposal, this->alloc_esp_spi);
271 }
272 return SUCCESS;
273 }
274
275
276 /**
277 * Implements child_sa_t.alloc
278 */
279 static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
280 {
281 iterator_t *iterator;
282 proposal_t *proposal;
283
284 /* iterator through proposals to update spis */
285 iterator = proposals->create_iterator(proposals, TRUE);
286 while(iterator->has_next(iterator))
287 {
288 iterator->current(iterator, (void**)&proposal);
289 if (alloc_proposal(this, proposal) != SUCCESS)
290 {
291 iterator->destroy(iterator);
292 return FAILED;
293 }
294 }
295 iterator->destroy(iterator);
296 return SUCCESS;
297 }
298
299 static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus, bool mine)
300 {
301 u_int32_t spi;
302 algorithm_t *enc_algo, *int_algo;
303 algorithm_t enc_algo_none = {ENCR_UNDEFINED, 0};
304 algorithm_t int_algo_none = {AUTH_UNDEFINED, 0};
305 host_t *src;
306 host_t *dst;
307 natt_conf_t *natt;
308 status_t status;
309
310 this->protocol = proposal->get_protocol(proposal);
311
312 /* now we have to decide which spi to use. Use self allocated, if "mine",
313 * or the one in the proposal, if not "mine" (others). Additionally,
314 * source and dest host switch depending on the role */
315 if (mine)
316 {
317 /* if we have allocated SPIs for AH and ESP, we must delete the unused
318 * one. */
319 if (this->protocol == PROTO_ESP)
320 {
321 this->me.spi = this->alloc_esp_spi;
322 if (this->alloc_ah_spi)
323 {
324 charon->kernel_interface->del_sa(charon->kernel_interface, this->me.addr,
325 this->alloc_ah_spi, PROTO_AH);
326 }
327 }
328 else
329 {
330 this->me.spi = this->alloc_ah_spi;
331 if (this->alloc_esp_spi)
332 {
333 charon->kernel_interface->del_sa(charon->kernel_interface, this->me.addr,
334 this->alloc_esp_spi, PROTO_ESP);
335 }
336 }
337 spi = this->me.spi;
338 dst = this->me.addr;
339 src = this->other.addr;
340 }
341 else
342 {
343 this->other.spi = proposal->get_spi(proposal);
344 spi = this->other.spi;
345 src = this->me.addr;
346 dst = this->other.addr;
347 }
348
349 this->logger->log(this->logger, CONTROL|LEVEL1, "adding %s %s SA",
350 mine ? "inbound" : "outbound",
351 mapping_find(protocol_id_m, this->protocol));
352
353 /* select encryption algo */
354 if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_algo))
355 {
356 this->logger->log(this->logger, CONTROL|LEVEL2, " using %s for encryption",
357 mapping_find(encryption_algorithm_m, enc_algo->algorithm));
358 }
359 else
360 {
361 enc_algo = &enc_algo_none;
362 }
363
364 /* select integrity algo */
365 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_algo))
366 {
367 this->logger->log(this->logger, CONTROL|LEVEL2, " using %s for integrity",
368 mapping_find(integrity_algorithm_m, int_algo->algorithm));
369 }
370 else
371 {
372 int_algo = &int_algo_none;
373 }
374
375 /* setup nat-t */
376 if (this->use_natt)
377 {
378 natt = alloca(sizeof(natt_conf_t));
379 natt->sport = src->get_port(src);
380 natt->dport = dst->get_port(dst);
381 }
382 else
383 {
384 natt = NULL;
385 }
386
387
388 /* send SA down to the kernel */
389 this->logger->log(this->logger, CONTROL|LEVEL2,
390 " SPI 0x%.8x, src %s dst %s",
391 ntohl(spi), src->get_string(src), dst->get_string(dst));
392 status = charon->kernel_interface->add_sa(charon->kernel_interface,
393 src, dst,
394 spi, this->protocol,
395 this->reqid,
396 mine ? this->soft_lifetime : 0,
397 this->hard_lifetime,
398 enc_algo, int_algo,
399 prf_plus, natt, mine);
400
401 this->encryption = *enc_algo;
402 this->integrity = *int_algo;
403 this->install_time = time(NULL);
404
405 return status;
406 }
407
408 static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus)
409 {
410 u_int32_t outbound_spi, inbound_spi;
411
412 /* backup outbound spi, as alloc overwrites it */
413 outbound_spi = proposal->get_spi(proposal);
414
415 /* get SPIs inbound SAs */
416 if (alloc_proposal(this, proposal) != SUCCESS)
417 {
418 return FAILED;
419 }
420 inbound_spi = proposal->get_spi(proposal);
421
422 /* install inbound SAs */
423 if (install(this, proposal, prf_plus, TRUE) != SUCCESS)
424 {
425 return FAILED;
426 }
427
428 /* install outbound SAs, restore spi*/
429 proposal->set_spi(proposal, outbound_spi);
430 if (install(this, proposal, prf_plus, FALSE) != SUCCESS)
431 {
432 return FAILED;
433 }
434 proposal->set_spi(proposal, inbound_spi);
435
436 this->state = CHILD_INSTALLED;
437
438 return SUCCESS;
439 }
440
441 static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus)
442 {
443 u_int32_t inbound_spi;
444
445 /* backup received spi, as install() overwrites it */
446 inbound_spi = proposal->get_spi(proposal);
447
448 /* install outbound SAs */
449 if (install(this, proposal, prf_plus, FALSE) != SUCCESS)
450 {
451 return FAILED;
452 }
453
454 /* restore spi */
455 proposal->set_spi(proposal, inbound_spi);
456 /* install inbound SAs */
457 if (install(this, proposal, prf_plus, TRUE) != SUCCESS)
458 {
459 return FAILED;
460 }
461
462 this->state = CHILD_INSTALLED;
463
464 return SUCCESS;
465 }
466
467 static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list)
468 {
469 iterator_t *my_iter, *other_iter;
470 traffic_selector_t *my_ts, *other_ts;
471
472 /* iterate over both lists */
473 my_iter = my_ts_list->create_iterator(my_ts_list, TRUE);
474 other_iter = other_ts_list->create_iterator(other_ts_list, TRUE);
475 while (my_iter->has_next(my_iter))
476 {
477 my_iter->current(my_iter, (void**)&my_ts);
478 other_iter->reset(other_iter);
479 while (other_iter->has_next(other_iter))
480 {
481 /* set up policies for every entry in my_ts_list to every entry in other_ts_list */
482 status_t status;
483 sa_policy_t *policy;
484
485 other_iter->current(other_iter, (void**)&other_ts);
486
487 if (my_ts->get_type(my_ts) != other_ts->get_type(other_ts))
488 {
489 this->logger->log(this->logger, CONTROL|LEVEL1,
490 "CHILD_SA policy uses two different IP families, ignored");
491 continue;
492 }
493
494 /* only set up policies if protocol matches, or if one is zero (any) */
495 if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts) &&
496 my_ts->get_protocol(my_ts) && other_ts->get_protocol(other_ts))
497 {
498 this->logger->log(this->logger, CONTROL|LEVEL1,
499 "CHILD_SA policy uses two different protocols, ignored");
500 continue;
501 }
502
503 /* install 3 policies: out, in and forward */
504 status = charon->kernel_interface->add_policy(charon->kernel_interface,
505 this->me.addr, this->other.addr, my_ts, other_ts,
506 POLICY_OUT, this->protocol, this->reqid, FALSE);
507
508 status |= charon->kernel_interface->add_policy(charon->kernel_interface,
509 this->other.addr, this->me.addr, other_ts, my_ts,
510 POLICY_IN, this->protocol, this->reqid, FALSE);
511
512 status |= charon->kernel_interface->add_policy(charon->kernel_interface,
513 this->other.addr, this->me.addr, other_ts, my_ts,
514 POLICY_FWD, this->protocol, this->reqid, FALSE);
515
516 if (status != SUCCESS)
517 {
518 my_iter->destroy(my_iter);
519 other_iter->destroy(other_iter);
520 return status;
521 }
522
523 /* store policy to delete/update them later */
524 policy = malloc_thing(sa_policy_t);
525 policy->my_ts = my_ts->clone(my_ts);
526 policy->other_ts = other_ts->clone(other_ts);
527 this->policies->insert_last(this->policies, (void*)policy);
528 /* add to separate list to query them via get_*_traffic_selectors() */
529 this->my_ts->insert_last(this->my_ts, (void*)policy->my_ts);
530 this->other_ts->insert_last(this->other_ts, (void*)policy->other_ts);
531 }
532 }
533 my_iter->destroy(my_iter);
534 other_iter->destroy(other_iter);
535
536 /* switch to routed state if no SAD entry set up */
537 if (this->state == CHILD_CREATED)
538 {
539 this->state = CHILD_ROUTED;
540 }
541
542 return SUCCESS;
543 }
544
545 /**
546 * Implementation of child_sa_t.get_my_traffic_selectors.
547 */
548 static linked_list_t *get_my_traffic_selectors(private_child_sa_t *this)
549 {
550 return this->my_ts;
551 }
552
553 /**
554 * Implementation of child_sa_t.get_my_traffic_selectors.
555 */
556 static linked_list_t *get_other_traffic_selectors(private_child_sa_t *this)
557 {
558 return this->other_ts;
559 }
560
561 /**
562 * Implementation of child_sa_t.set_rekeying_transaction.
563 */
564 static void set_rekeying_transaction(private_child_sa_t *this, void *transaction)
565 {
566 this->rekeying_transaction = transaction;
567 }
568
569 /**
570 * Implementation of child_sa_t.get_rekeying_transaction.
571 */
572 static void* get_rekeying_transaction(private_child_sa_t *this)
573 {
574 return this->rekeying_transaction;
575 }
576
577 /**
578 * Implementation of child_sa_t.get_use_time
579 */
580 static status_t get_use_time(private_child_sa_t *this, bool inbound, time_t *use_time)
581 {
582 iterator_t *iterator;
583 sa_policy_t *policy;
584 status_t status = FAILED;
585
586 *use_time = UNDEFINED_TIME;
587
588 iterator = this->policies->create_iterator(this->policies, TRUE);
589 while (iterator->iterate(iterator, (void**)&policy))
590 {
591 if (inbound)
592 {
593 time_t in = UNDEFINED_TIME, fwd = UNDEFINED_TIME;
594
595 status = charon->kernel_interface->query_policy(
596 charon->kernel_interface,
597 policy->other_ts, policy->my_ts,
598 POLICY_IN, (u_int32_t*)&in);
599 status |= charon->kernel_interface->query_policy(
600 charon->kernel_interface,
601 policy->other_ts, policy->my_ts,
602 POLICY_FWD, (u_int32_t*)&fwd);
603 *use_time = max(in, fwd);
604 }
605 else
606 {
607 status = charon->kernel_interface->query_policy(
608 charon->kernel_interface,
609 policy->my_ts, policy->other_ts,
610 POLICY_OUT, (u_int32_t*)use_time);
611 }
612 }
613 iterator->destroy(iterator);
614 return status;
615 }
616
617 /**
618 * Implementation of child_sa_t.log_status.
619 */
620 static void log_status(private_child_sa_t *this, logger_t *logger)
621 {
622 iterator_t *iterator;
623 char use_in_str[12] = "unused";
624 char use_out_str[12] = "unused";
625 char rekey_str[12] = "disabled";
626 char enc_str[32] = "";
627 char int_str[32] = "";
628 u_int32_t use_in, use_out, use_fwd, now, rekeying;
629 status_t status;
630
631 if (logger == NULL)
632 {
633 logger = this->logger;
634 }
635 now = (u_int32_t)time(NULL);
636
637 if (this->state == CHILD_INSTALLED)
638 {
639 /* query SA times */
640 status = charon->kernel_interface->query_sa(charon->kernel_interface,
641 this->me.addr, this->me.spi, this->protocol, &use_in);
642 if (status == SUCCESS && use_in)
643 {
644 snprintf(use_in_str, sizeof(use_in_str), "%ds", now - use_in);
645 }
646 status = charon->kernel_interface->query_sa(charon->kernel_interface,
647 this->other.addr, this->other.spi, this->protocol, &use_out);
648 if (status == SUCCESS && use_out)
649 {
650 snprintf(use_out_str, sizeof(use_out_str), "%ds", now - use_out);
651 }
652
653 /* calculate rekey times */
654 if (this->soft_lifetime)
655 {
656 rekeying = this->soft_lifetime - (now - this->install_time);
657 snprintf(rekey_str, sizeof(rekey_str), "%ds", (int)rekeying);
658 }
659
660 /* algorithms used */
661 if (this->protocol == PROTO_ESP)
662 {
663 if (this->encryption.key_size)
664 {
665 snprintf(enc_str, sizeof(enc_str), "%s-%d,",
666 mapping_find(encryption_algorithm_m, this->encryption.algorithm),
667 this->encryption.key_size);
668 }
669 else
670 {
671 snprintf(enc_str, sizeof(enc_str), "%s,",
672 mapping_find(encryption_algorithm_m, this->encryption.algorithm));
673 }
674 }
675 if (this->integrity.key_size)
676 {
677 snprintf(int_str, sizeof(int_str), "%s-%d",
678 mapping_find(integrity_algorithm_m, this->integrity.algorithm),
679 this->integrity.key_size);
680 }
681 else
682 {
683 snprintf(int_str, sizeof(int_str), "%s",
684 mapping_find(integrity_algorithm_m, this->integrity.algorithm));
685 }
686
687 logger->log(logger, CONTROL|LEVEL1,
688 " \"%s\": state: %s, reqid: %d, ",
689 this->name, mapping_find(child_sa_state_m, this->state), this->reqid);
690 logger->log(logger, CONTROL|LEVEL1,
691 " \"%s\": %s (%s%s), SPIs (in/out): 0x%x/0x%x",
692 this->name, this->protocol == PROTO_ESP ? "ESP" : "AH",
693 enc_str, int_str,
694 htonl(this->me.spi), htonl(this->other.spi));
695 logger->log(logger, CONTROL|LEVEL1,
696 " \"%s\": rekeying: %s, key age (in/out): %s/%s",
697 this->name, rekey_str, use_in_str, use_out_str);
698 }
699 else
700 {
701 logger->log(logger, CONTROL|LEVEL1, " \"%s\": state: %s, reqid: %d",
702 this->name, mapping_find(child_sa_state_m, this->state),
703 this->reqid);
704 }
705
706 iterator = this->policies->create_iterator(this->policies, TRUE);
707 while (iterator->has_next(iterator))
708 {
709 sa_policy_t *policy;
710 char *my_str;
711 char *other_str;
712 char pol_in_str[12] = "unused";
713 char pol_out_str[12] = "unused";
714 char pol_fwd_str[12] = "unused";
715
716 /* get ts strings */
717 iterator->current(iterator, (void**)&policy);
718 my_str = policy->my_ts->get_string(policy->my_ts);
719 other_str = policy->other_ts->get_string(policy->other_ts);
720
721 /* query policy times */
722 status = charon->kernel_interface->query_policy(charon->kernel_interface,
723 policy->other_ts, policy->my_ts, POLICY_IN, &use_in);
724 if (status == SUCCESS && use_in)
725 {
726 snprintf(pol_in_str, sizeof(pol_in_str), "%ds", now - use_in);
727 }
728 status = charon->kernel_interface->query_policy(charon->kernel_interface,
729 policy->my_ts, policy->other_ts, POLICY_OUT, &use_out);
730 if (status == SUCCESS && use_out)
731 {
732 snprintf(pol_out_str, sizeof(pol_out_str), "%ds", now - use_out);
733 }
734 status = charon->kernel_interface->query_policy(charon->kernel_interface,
735 policy->other_ts, policy->my_ts, POLICY_FWD, &use_fwd);
736 if (status == SUCCESS && use_fwd)
737 {
738 snprintf(pol_fwd_str, sizeof(pol_fwd_str), "%ds", now - use_fwd);
739 }
740
741 logger->log(logger, CONTROL,
742 " \"%s\": %s====%s, last use (in/out/fwd): %s/%s/%s",
743 this->name, my_str, other_str, pol_in_str, pol_out_str, pol_fwd_str);
744 }
745 iterator->destroy(iterator);
746 }
747
748 /**
749 * Update the host adress/port of a SA
750 */
751 static status_t update_sa_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other,
752 int my_changes, int other_changes, bool mine)
753 {
754 host_t *src, *dst, *new_src, *new_dst;
755 int src_changes, dst_changes;
756 status_t status;
757 u_int32_t spi;
758
759 if (mine)
760 {
761 src = this->other.addr;
762 dst = this->me.addr;
763 new_src = new_other;
764 new_dst = new_me;
765 src_changes = other_changes;
766 dst_changes = my_changes;
767 spi = this->other.spi;
768 }
769 else
770 {
771 src = this->me.addr;
772 dst = this->other.addr;
773 new_src = new_me;
774 new_dst = new_other;
775 src_changes = my_changes;
776 dst_changes = other_changes;
777 spi = this->me.spi;
778 }
779
780 this->logger->log(this->logger, CONTROL|LEVEL1,
781 "updating %s SA 0x%x, from %s:%d..%s:%d to %s:%d..%s:%d",
782 mapping_find(protocol_id_m, this->protocol), ntohl(spi),
783 src->get_string(src), src->get_port(src),
784 dst->get_string(dst), dst->get_port(dst),
785 new_src->get_string(new_src), new_src->get_port(new_src),
786 new_dst->get_string(new_dst), new_dst->get_port(new_dst));
787
788 status = charon->kernel_interface->update_sa(charon->kernel_interface,
789 dst, spi, this->protocol,
790 new_src, new_dst,
791 src_changes, dst_changes);
792
793 if (status != SUCCESS)
794 {
795 return FAILED;
796 }
797 return SUCCESS;
798 }
799
800 /**
801 * Update the host adress/port of a policy
802 */
803 static status_t update_policy_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other)
804 {
805 iterator_t *iterator;
806 sa_policy_t *policy;
807 status_t status;
808
809 iterator = this->policies->create_iterator(this->policies, TRUE);
810 while (iterator->iterate(iterator, (void**)&policy))
811 {
812 status = charon->kernel_interface->add_policy(
813 charon->kernel_interface,
814 new_me, new_other,
815 policy->my_ts, policy->other_ts,
816 POLICY_OUT, this->protocol, this->reqid, TRUE);
817
818 status |= charon->kernel_interface->add_policy(
819 charon->kernel_interface,
820 new_other, new_me,
821 policy->other_ts, policy->my_ts,
822 POLICY_IN, this->protocol, this->reqid, TRUE);
823
824 status |= charon->kernel_interface->add_policy(
825 charon->kernel_interface,
826 new_other, new_me,
827 policy->other_ts, policy->my_ts,
828 POLICY_FWD, this->protocol, this->reqid, TRUE);
829
830 if (status != SUCCESS)
831 {
832 iterator->destroy(iterator);
833 return FAILED;
834 }
835 }
836 iterator->destroy(iterator);
837
838 return SUCCESS;
839 }
840
841 /**
842 * Implementation of child_sa_t.update_hosts.
843 */
844 static status_t update_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other,
845 host_diff_t my_changes, host_diff_t other_changes)
846 {
847 if (!my_changes && !other_changes)
848 {
849 return SUCCESS;
850 }
851
852 /* update our (initator) SAs */
853 if (update_sa_hosts(this, new_me, new_other, my_changes, other_changes, TRUE) != SUCCESS)
854 {
855 return FAILED;
856 }
857
858 /* update his (responder) SAs */
859 if (update_sa_hosts(this, new_me, new_other, my_changes, other_changes, FALSE) != SUCCESS)
860 {
861 return FAILED;
862 }
863
864 /* update policies */
865 if (my_changes & HOST_DIFF_ADDR || other_changes & HOST_DIFF_ADDR)
866 {
867 if (update_policy_hosts(this, new_me, new_other) != SUCCESS)
868 {
869 return FAILED;
870 }
871 }
872
873 /* update hosts */
874 if (my_changes)
875 {
876 this->me.addr->destroy(this->me.addr);
877 this->me.addr = new_me->clone(new_me);
878 }
879
880 if (other_changes)
881 {
882 this->other.addr->destroy(this->other.addr);
883 this->other.addr = new_other->clone(new_other);
884 }
885
886 return SUCCESS;
887 }
888
889 /**
890 * Implementation of child_sa_t.destroy.
891 */
892 static void destroy(private_child_sa_t *this)
893 {
894 sa_policy_t *policy;
895
896 /* delete SAs in the kernel, if they are set up */
897 if (this->me.spi)
898 {
899 charon->kernel_interface->del_sa(charon->kernel_interface,
900 this->me.addr, this->me.spi, this->protocol);
901 }
902 if (this->alloc_esp_spi && this->alloc_esp_spi != this->me.spi)
903 {
904 charon->kernel_interface->del_sa(charon->kernel_interface,
905 this->me.addr, this->alloc_esp_spi, PROTO_ESP);
906 }
907 if (this->alloc_ah_spi && this->alloc_ah_spi != this->me.spi)
908 {
909 charon->kernel_interface->del_sa(charon->kernel_interface,
910 this->me.addr, this->alloc_ah_spi, PROTO_AH);
911 }
912 if (this->other.spi)
913 {
914 charon->kernel_interface->del_sa(charon->kernel_interface,
915 this->other.addr, this->other.spi, this->protocol);
916 }
917
918 /* delete all policies in the kernel */
919 while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
920 {
921 /* let rekeyed policies, as they are used by another child_sa */
922 charon->kernel_interface->del_policy(charon->kernel_interface,
923 policy->my_ts, policy->other_ts,
924 POLICY_OUT);
925
926 charon->kernel_interface->del_policy(charon->kernel_interface,
927 policy->other_ts, policy->my_ts,
928 POLICY_IN);
929
930 charon->kernel_interface->del_policy(charon->kernel_interface,
931 policy->other_ts, policy->my_ts,
932 POLICY_FWD);
933 policy->my_ts->destroy(policy->my_ts);
934 policy->other_ts->destroy(policy->other_ts);
935 free(policy);
936 }
937 this->policies->destroy(this->policies);
938
939 this->my_ts->destroy(this->my_ts);
940 this->other_ts->destroy(this->other_ts);
941 this->me.addr->destroy(this->me.addr);
942 this->other.addr->destroy(this->other.addr);
943 free(this->name);
944 free(this);
945 }
946
947 /*
948 * Described in header.
949 */
950 child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
951 u_int32_t soft_lifetime, u_int32_t hard_lifetime,
952 bool use_natt)
953 {
954 static u_int32_t reqid = REQID_START;
955 private_child_sa_t *this = malloc_thing(private_child_sa_t);
956
957 /* public functions */
958 this->public.get_name = (char*(*)(child_sa_t*))get_name;
959 this->public.set_name = (void(*)(child_sa_t*,char*))set_name;
960 this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid;
961 this->public.get_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi;
962 this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol;
963 this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
964 this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add;
965 this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update;
966 this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_diff_t,host_diff_t))update_hosts;
967 this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
968 this->public.get_my_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_my_traffic_selectors;
969 this->public.get_other_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_other_traffic_selectors;
970 this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
971 this->public.set_rekeying_transaction = (void (*)(child_sa_t*,void*))set_rekeying_transaction;
972 this->public.get_rekeying_transaction = (void* (*)(child_sa_t*))get_rekeying_transaction;
973 this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
974 this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
975 this->public.log_status = (void (*)(child_sa_t*, logger_t*))log_status;
976 this->public.destroy = (void(*)(child_sa_t*))destroy;
977
978 /* private data */
979 this->logger = logger_manager->get_logger(logger_manager, CHILD_SA);
980 this->name = strdup("(uninitialized)");
981 this->me.addr = me->clone(me);
982 this->other.addr = other->clone(other);
983 this->me.spi = 0;
984 this->other.spi = 0;
985 this->alloc_ah_spi = 0;
986 this->alloc_esp_spi = 0;
987 this->use_natt = use_natt;
988 this->soft_lifetime = soft_lifetime;
989 this->hard_lifetime = hard_lifetime;
990 this->state = CHILD_CREATED;
991 /* reuse old reqid if we are rekeying an existing CHILD_SA */
992 this->reqid = rekey ? rekey : ++reqid;
993 this->encryption.algorithm = ENCR_UNDEFINED;
994 this->encryption.key_size = 0;
995 this->integrity.algorithm = AUTH_UNDEFINED;
996 this->encryption.key_size = 0;
997 this->policies = linked_list_create();
998 this->my_ts = linked_list_create();
999 this->other_ts = linked_list_create();
1000 this->protocol = PROTO_NONE;
1001 this->rekeying_transaction = NULL;
1002
1003 return &this->public;
1004 }