fixed statusall rekey time jitter bug (again)
[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) 2005-2007 Martin Willi
10 * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
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 #define _GNU_SOURCE
26 #include "child_sa.h"
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <printf.h>
31
32 #include <daemon.h>
33
34 ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DELETING,
35 "CREATED",
36 "ROUTED",
37 "INSTALLED",
38 "REKEYING",
39 "DELETING",
40 );
41
42 typedef struct sa_policy_t sa_policy_t;
43
44 /**
45 * Struct used to store information for a policy. This
46 * is needed since we must provide all this information
47 * for deleting a policy...
48 */
49 struct sa_policy_t {
50 /**
51 * Traffic selector for us
52 */
53 traffic_selector_t *my_ts;
54
55 /**
56 * Traffic selector for other
57 */
58 traffic_selector_t *other_ts;
59 };
60
61 typedef struct private_child_sa_t private_child_sa_t;
62
63 /**
64 * Private data of a child_sa_t \ 1bject.
65 */
66 struct private_child_sa_t {
67 /**
68 * Public interface of child_sa_t.
69 */
70 child_sa_t public;
71
72 struct {
73 /** address of peer */
74 host_t *addr;
75 /** id of peer */
76 identification_t *id;
77 /** actual used SPI, 0 if unused */
78 u_int32_t spi;
79 } me, other;
80
81 /**
82 * Allocated SPI for a ESP proposal candidates
83 */
84 u_int32_t alloc_esp_spi;
85
86 /**
87 * Allocated SPI for a AH proposal candidates
88 */
89 u_int32_t alloc_ah_spi;
90
91 /**
92 * Protocol used to protect this SA, ESP|AH
93 */
94 protocol_id_t protocol;
95
96 /**
97 * List containing sa_policy_t objects
98 */
99 linked_list_t *policies;
100
101 /**
102 * Seperate list for local traffic selectors
103 */
104 linked_list_t *my_ts;
105
106 /**
107 * Seperate list for remote traffic selectors
108 */
109 linked_list_t *other_ts;
110
111 /**
112 * reqid used for this child_sa
113 */
114 u_int32_t reqid;
115
116 /**
117 * encryption algorithm used for this SA
118 */
119 algorithm_t encryption;
120
121 /**
122 * integrity protection algorithm used for this SA
123 */
124 algorithm_t integrity;
125
126 /**
127 * time, on which SA was installed
128 */
129 time_t install_time;
130
131 /**
132 * absolute time when rekeying is sceduled
133 */
134 time_t rekey_time;
135
136 /**
137 * state of the CHILD_SA
138 */
139 child_sa_state_t state;
140
141 /**
142 * Specifies if NAT traversal is used
143 */
144 bool use_natt;
145
146 /**
147 * mode this SA uses, tunnel/transport
148 */
149 mode_t mode;
150
151 /**
152 * virtual IP assinged to local host
153 */
154 host_t *virtual_ip;
155
156 /**
157 * policy used to create this child
158 */
159 policy_t *policy;
160 };
161
162 /**
163 * Implementation of child_sa_t.get_name.
164 */
165 static char *get_name(private_child_sa_t *this)
166 {
167 return this->policy->get_name(this->policy);;
168 }
169
170 /**
171 * Implements child_sa_t.get_reqid
172 */
173 static u_int32_t get_reqid(private_child_sa_t *this)
174 {
175 return this->reqid;
176 }
177
178 /**
179 * Implements child_sa_t.get_spi
180 */
181 u_int32_t get_spi(private_child_sa_t *this, bool inbound)
182 {
183 if (inbound)
184 {
185 return this->me.spi;
186 }
187 return this->other.spi;
188 }
189
190 /**
191 * Implements child_sa_t.get_protocol
192 */
193 protocol_id_t get_protocol(private_child_sa_t *this)
194 {
195 return this->protocol;
196 }
197
198 /**
199 * Implements child_sa_t.get_state
200 */
201 static child_sa_state_t get_state(private_child_sa_t *this)
202 {
203 return this->state;
204 }
205
206 /**
207 * Implements child_sa_t.get_policy
208 */
209 static policy_t* get_policy(private_child_sa_t *this)
210 {
211 return this->policy;
212 }
213
214 /**
215 * Run the up/down script
216 */
217 static void updown(private_child_sa_t *this, bool up)
218 {
219 sa_policy_t *policy;
220 iterator_t *iterator;
221 char *script;
222
223 script = this->policy->get_updown(this->policy);
224
225 if (script == NULL)
226 {
227 return;
228 }
229
230 iterator = this->policies->create_iterator(this->policies, TRUE);
231 while (iterator->iterate(iterator, (void**)&policy))
232 {
233 char command[1024];
234 char *ifname = NULL;
235 char *my_client, *other_client, *my_client_mask, *other_client_mask;
236 char *pos, *virtual_ip;
237 FILE *shell;
238
239 /* get subnet/bits from string */
240 asprintf(&my_client, "%R", policy->my_ts);
241 pos = strchr(my_client, '/');
242 *pos = '\0';
243 my_client_mask = pos + 1;
244 pos = strchr(my_client_mask, '[');
245 if (pos)
246 {
247 *pos = '\0';
248 }
249 asprintf(&other_client, "%R", policy->other_ts);
250 pos = strchr(other_client, '/');
251 *pos = '\0';
252 other_client_mask = pos + 1;
253 pos = strchr(other_client_mask, '[');
254 if (pos)
255 {
256 *pos = '\0';
257 }
258
259 if (this->virtual_ip)
260 {
261 asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ",
262 this->virtual_ip);
263 }
264 else
265 {
266 asprintf(&virtual_ip, "");
267 }
268
269 ifname = charon->kernel_interface->get_interface(charon->kernel_interface,
270 this->me.addr);
271
272 /* build the command with all env variables.
273 * TODO: PLUTO_PEER_CA and PLUTO_NEXT_HOP are currently missing
274 */
275 snprintf(command, sizeof(command),
276 "2>&1 "
277 "PLUTO_VERSION='1.1' "
278 "PLUTO_VERB='%s%s%s' "
279 "PLUTO_CONNECTION='%s' "
280 "PLUTO_INTERFACE='%s' "
281 "PLUTO_REQID='%u' "
282 "PLUTO_ME='%H' "
283 "PLUTO_MY_ID='%D' "
284 "PLUTO_MY_CLIENT='%s/%s' "
285 "PLUTO_MY_CLIENT_NET='%s' "
286 "PLUTO_MY_CLIENT_MASK='%s' "
287 "PLUTO_MY_PORT='%u' "
288 "PLUTO_MY_PROTOCOL='%u' "
289 "PLUTO_PEER='%H' "
290 "PLUTO_PEER_ID='%D' "
291 "PLUTO_PEER_CLIENT='%s/%s' "
292 "PLUTO_PEER_CLIENT_NET='%s' "
293 "PLUTO_PEER_CLIENT_MASK='%s' "
294 "PLUTO_PEER_PORT='%u' "
295 "PLUTO_PEER_PROTOCOL='%u' "
296 "%s"
297 "%s"
298 "%s",
299 up ? "up" : "down",
300 policy->my_ts->is_host(policy->my_ts,
301 this->me.addr) ? "-host" : "-client",
302 this->me.addr->get_family(this->me.addr) == AF_INET ? "" : "-ipv6",
303 this->policy->get_name(this->policy),
304 ifname ? ifname : "(unknown)",
305 this->reqid,
306 this->me.addr,
307 this->me.id,
308 my_client, my_client_mask,
309 my_client, my_client_mask,
310 policy->my_ts->get_from_port(policy->my_ts),
311 policy->my_ts->get_protocol(policy->my_ts),
312 this->other.addr,
313 this->other.id,
314 other_client, other_client_mask,
315 other_client, other_client_mask,
316 policy->other_ts->get_from_port(policy->other_ts),
317 policy->other_ts->get_protocol(policy->other_ts),
318 virtual_ip,
319 this->policy->get_hostaccess(this->policy) ?
320 "PLUTO_HOST_ACCESS='1' " : "",
321 script);
322 free(ifname);
323 free(my_client);
324 free(other_client);
325 free(virtual_ip);
326
327 shell = popen(command, "r");
328
329 if (shell == NULL)
330 {
331 DBG1(DBG_CHD, "could not execute updown script '%s'", script);
332 return;
333 }
334
335 while (TRUE)
336 {
337 char resp[128];
338
339 if (fgets(resp, sizeof(resp), shell) == NULL)
340 {
341 if (ferror(shell))
342 {
343 DBG1(DBG_CHD, "error reading output from updown script");
344 return;
345 }
346 else
347 {
348 break;
349 }
350 }
351 else
352 {
353 char *e = resp + strlen(resp);
354 if (e > resp && e[-1] == '\n')
355 { /* trim trailing '\n' */
356 e[-1] = '\0';
357 }
358 DBG1(DBG_CHD, "updown: %s", resp);
359 }
360 }
361 pclose(shell);
362 }
363 iterator->destroy(iterator);
364 }
365
366 /**
367 * Implements child_sa_t.set_state
368 */
369 static void set_state(private_child_sa_t *this, child_sa_state_t state)
370 {
371 this->state = state;
372 if (state == CHILD_INSTALLED)
373 {
374 updown(this, TRUE);
375 }
376 }
377
378 /**
379 * Allocate SPI for a single proposal
380 */
381 static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal)
382 {
383 protocol_id_t protocol = proposal->get_protocol(proposal);
384
385 if (protocol == PROTO_AH)
386 {
387 /* get a new spi for AH, if not already done */
388 if (this->alloc_ah_spi == 0)
389 {
390 if (charon->kernel_interface->get_spi(
391 charon->kernel_interface,
392 this->other.addr, this->me.addr,
393 PROTO_AH, this->reqid,
394 &this->alloc_ah_spi) != SUCCESS)
395 {
396 return FAILED;
397 }
398 }
399 proposal->set_spi(proposal, this->alloc_ah_spi);
400 }
401 if (protocol == PROTO_ESP)
402 {
403 /* get a new spi for ESP, if not already done */
404 if (this->alloc_esp_spi == 0)
405 {
406 if (charon->kernel_interface->get_spi(
407 charon->kernel_interface,
408 this->other.addr, this->me.addr,
409 PROTO_ESP, this->reqid,
410 &this->alloc_esp_spi) != SUCCESS)
411 {
412 return FAILED;
413 }
414 }
415 proposal->set_spi(proposal, this->alloc_esp_spi);
416 }
417 return SUCCESS;
418 }
419
420
421 /**
422 * Implements child_sa_t.alloc
423 */
424 static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
425 {
426 iterator_t *iterator;
427 proposal_t *proposal;
428
429 /* iterator through proposals to update spis */
430 iterator = proposals->create_iterator(proposals, TRUE);
431 while(iterator->iterate(iterator, (void**)&proposal))
432 {
433 if (alloc_proposal(this, proposal) != SUCCESS)
434 {
435 iterator->destroy(iterator);
436 return FAILED;
437 }
438 }
439 iterator->destroy(iterator);
440 return SUCCESS;
441 }
442
443 static status_t install(private_child_sa_t *this, proposal_t *proposal,
444 mode_t mode, prf_plus_t *prf_plus, bool mine)
445 {
446 u_int32_t spi, soft, hard;;
447 algorithm_t *enc_algo, *int_algo;
448 algorithm_t enc_algo_none = {ENCR_UNDEFINED, 0};
449 algorithm_t int_algo_none = {AUTH_UNDEFINED, 0};
450 host_t *src;
451 host_t *dst;
452 natt_conf_t *natt;
453 status_t status;
454
455 this->protocol = proposal->get_protocol(proposal);
456
457 /* now we have to decide which spi to use. Use self allocated, if "mine",
458 * or the one in the proposal, if not "mine" (others). Additionally,
459 * source and dest host switch depending on the role */
460 if (mine)
461 {
462 /* if we have allocated SPIs for AH and ESP, we must delete the unused
463 * one. */
464 if (this->protocol == PROTO_ESP)
465 {
466 this->me.spi = this->alloc_esp_spi;
467 if (this->alloc_ah_spi)
468 {
469 charon->kernel_interface->del_sa(charon->kernel_interface, this->me.addr,
470 this->alloc_ah_spi, PROTO_AH);
471 }
472 }
473 else
474 {
475 this->me.spi = this->alloc_ah_spi;
476 if (this->alloc_esp_spi)
477 {
478 charon->kernel_interface->del_sa(charon->kernel_interface, this->me.addr,
479 this->alloc_esp_spi, PROTO_ESP);
480 }
481 }
482 spi = this->me.spi;
483 dst = this->me.addr;
484 src = this->other.addr;
485 }
486 else
487 {
488 this->other.spi = proposal->get_spi(proposal);
489 spi = this->other.spi;
490 src = this->me.addr;
491 dst = this->other.addr;
492 }
493
494 DBG2(DBG_CHD, "adding %s %N SA", mine ? "inbound" : "outbound",
495 protocol_id_names, this->protocol);
496
497 /* select encryption algo */
498 if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_algo))
499 {
500 DBG2(DBG_CHD, " using %N for encryption",
501 encryption_algorithm_names, enc_algo->algorithm);
502 }
503 else
504 {
505 enc_algo = &enc_algo_none;
506 }
507
508 /* select integrity algo */
509 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_algo))
510 {
511 DBG2(DBG_CHD, " using %N for integrity",
512 integrity_algorithm_names, int_algo->algorithm);
513 }
514 else
515 {
516 int_algo = &int_algo_none;
517 }
518
519 /* setup nat-t */
520 if (this->use_natt)
521 {
522 natt = alloca(sizeof(natt_conf_t));
523 natt->sport = src->get_port(src);
524 natt->dport = dst->get_port(dst);
525 }
526 else
527 {
528 natt = NULL;
529 }
530
531 soft = this->policy->get_soft_lifetime(this->policy);
532 hard = this->policy->get_hard_lifetime(this->policy);
533
534 /* send SA down to the kernel */
535 DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
536 status = charon->kernel_interface->add_sa(charon->kernel_interface,
537 src, dst, spi, this->protocol,
538 this->reqid, mine ? soft : 0,
539 hard, enc_algo, int_algo,
540 prf_plus, natt, mode, mine);
541
542 this->encryption = *enc_algo;
543 this->integrity = *int_algo;
544 this->install_time = time(NULL);
545 this->rekey_time = soft;
546
547 return status;
548 }
549
550 static status_t add(private_child_sa_t *this, proposal_t *proposal,
551 mode_t mode, prf_plus_t *prf_plus)
552 {
553 u_int32_t outbound_spi, inbound_spi;
554
555 /* backup outbound spi, as alloc overwrites it */
556 outbound_spi = proposal->get_spi(proposal);
557
558 /* get SPIs inbound SAs */
559 if (alloc_proposal(this, proposal) != SUCCESS)
560 {
561 return FAILED;
562 }
563 inbound_spi = proposal->get_spi(proposal);
564
565 /* install inbound SAs */
566 if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
567 {
568 return FAILED;
569 }
570
571 /* install outbound SAs, restore spi*/
572 proposal->set_spi(proposal, outbound_spi);
573 if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
574 {
575 return FAILED;
576 }
577 proposal->set_spi(proposal, inbound_spi);
578
579 return SUCCESS;
580 }
581
582 static status_t update(private_child_sa_t *this, proposal_t *proposal,
583 mode_t mode, prf_plus_t *prf_plus)
584 {
585 u_int32_t inbound_spi;
586
587 /* backup received spi, as install() overwrites it */
588 inbound_spi = proposal->get_spi(proposal);
589
590 /* install outbound SAs */
591 if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
592 {
593 return FAILED;
594 }
595
596 /* restore spi */
597 proposal->set_spi(proposal, inbound_spi);
598 /* install inbound SAs */
599 if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
600 {
601 return FAILED;
602 }
603
604 return SUCCESS;
605 }
606
607 static status_t add_policies(private_child_sa_t *this,
608 linked_list_t *my_ts_list,
609 linked_list_t *other_ts_list, mode_t mode)
610 {
611 iterator_t *my_iter, *other_iter;
612 traffic_selector_t *my_ts, *other_ts;
613 /* use low prio for ROUTED policies */
614 bool high_prio = (this->state != CHILD_CREATED);
615
616 /* iterate over both lists */
617 my_iter = my_ts_list->create_iterator(my_ts_list, TRUE);
618 other_iter = other_ts_list->create_iterator(other_ts_list, TRUE);
619 while (my_iter->iterate(my_iter, (void**)&my_ts))
620 {
621 other_iter->reset(other_iter);
622 while (other_iter->iterate(other_iter, (void**)&other_ts))
623 {
624 /* set up policies for every entry in my_ts_list to every entry in other_ts_list */
625 status_t status;
626 sa_policy_t *policy;
627
628 if (my_ts->get_type(my_ts) != other_ts->get_type(other_ts))
629 {
630 DBG2(DBG_CHD,
631 "CHILD_SA policy uses two different IP families, ignored");
632 continue;
633 }
634
635 /* only set up policies if protocol matches, or if one is zero (any) */
636 if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts) &&
637 my_ts->get_protocol(my_ts) && other_ts->get_protocol(other_ts))
638 {
639 DBG2(DBG_CHD,
640 "CHILD_SA policy uses two different protocols, ignored");
641 continue;
642 }
643
644 /* install 3 policies: out, in and forward */
645 status = charon->kernel_interface->add_policy(charon->kernel_interface,
646 this->me.addr, this->other.addr, my_ts, other_ts, POLICY_OUT,
647 this->protocol, this->reqid, high_prio, mode, FALSE);
648
649 status |= charon->kernel_interface->add_policy(charon->kernel_interface,
650 this->other.addr, this->me.addr, other_ts, my_ts, POLICY_IN,
651 this->protocol, this->reqid, high_prio, mode, FALSE);
652
653 status |= charon->kernel_interface->add_policy(charon->kernel_interface,
654 this->other.addr, this->me.addr, other_ts, my_ts, POLICY_FWD,
655 this->protocol, this->reqid, high_prio, mode, FALSE);
656
657 if (status != SUCCESS)
658 {
659 my_iter->destroy(my_iter);
660 other_iter->destroy(other_iter);
661 return status;
662 }
663
664 /* store policy to delete/update them later */
665 policy = malloc_thing(sa_policy_t);
666 policy->my_ts = my_ts->clone(my_ts);
667 policy->other_ts = other_ts->clone(other_ts);
668 this->policies->insert_last(this->policies, (void*)policy);
669 /* add to separate list to query them via get_*_traffic_selectors() */
670 this->my_ts->insert_last(this->my_ts, (void*)policy->my_ts);
671 this->other_ts->insert_last(this->other_ts, (void*)policy->other_ts);
672 }
673 }
674 my_iter->destroy(my_iter);
675 other_iter->destroy(other_iter);
676
677 /* switch to routed state if no SAD entry set up */
678 if (this->state == CHILD_CREATED)
679 {
680 this->state = CHILD_ROUTED;
681 }
682 /* needed to update hosts */
683 this->mode = mode;
684 return SUCCESS;
685 }
686
687 /**
688 * Implementation of child_sa_t.get_my_traffic_selectors.
689 */
690 static linked_list_t *get_my_traffic_selectors(private_child_sa_t *this)
691 {
692 return this->my_ts;
693 }
694
695 /**
696 * Implementation of child_sa_t.get_my_traffic_selectors.
697 */
698 static linked_list_t *get_other_traffic_selectors(private_child_sa_t *this)
699 {
700 return this->other_ts;
701 }
702
703 /**
704 * Implementation of child_sa_t.get_use_time
705 */
706 static status_t get_use_time(private_child_sa_t *this, bool inbound, time_t *use_time)
707 {
708 iterator_t *iterator;
709 sa_policy_t *policy;
710 status_t status = FAILED;
711
712 *use_time = UNDEFINED_TIME;
713
714 iterator = this->policies->create_iterator(this->policies, TRUE);
715 while (iterator->iterate(iterator, (void**)&policy))
716 {
717 if (inbound)
718 {
719 time_t in = UNDEFINED_TIME, fwd = UNDEFINED_TIME;
720
721 status = charon->kernel_interface->query_policy(
722 charon->kernel_interface,
723 policy->other_ts, policy->my_ts,
724 POLICY_IN, (u_int32_t*)&in);
725 status |= charon->kernel_interface->query_policy(
726 charon->kernel_interface,
727 policy->other_ts, policy->my_ts,
728 POLICY_FWD, (u_int32_t*)&fwd);
729 *use_time = max(in, fwd);
730 }
731 else
732 {
733 status = charon->kernel_interface->query_policy(
734 charon->kernel_interface,
735 policy->my_ts, policy->other_ts,
736 POLICY_OUT, (u_int32_t*)use_time);
737 }
738 }
739 iterator->destroy(iterator);
740 return status;
741 }
742
743 /**
744 * output handler in printf()
745 */
746 static int print(FILE *stream, const struct printf_info *info,
747 const void *const *args)
748 {
749 private_child_sa_t *this = *((private_child_sa_t**)(args[0]));
750 iterator_t *iterator;
751 sa_policy_t *policy;
752 u_int32_t now, rekeying;
753 u_int32_t use, use_in, use_fwd;
754 status_t status;
755 size_t written = 0;
756
757 if (this == NULL)
758 {
759 return fprintf(stream, "(null)");
760 }
761
762 now = time(NULL);
763
764 written += fprintf(stream, "%12s{%d}: %N, %N",
765 this->policy->get_name(this->policy), this->reqid,
766 child_sa_state_names, this->state,
767 mode_names, this->mode);
768
769 if (this->state == CHILD_INSTALLED)
770 {
771 written += fprintf(stream, ", %N SPIs: 0x%0x_i 0x%0x_o",
772 protocol_id_names, this->protocol,
773 htonl(this->me.spi), htonl(this->other.spi));
774
775 if (info->alt)
776 {
777 written += fprintf(stream, "\n%12s{%d}: ",
778 this->policy->get_name(this->policy),
779 this->reqid);
780
781 if (this->protocol == PROTO_ESP)
782 {
783 written += fprintf(stream, "%N", encryption_algorithm_names,
784 this->encryption.algorithm);
785
786 if (this->encryption.key_size)
787 {
788 written += fprintf(stream, "-%d", this->encryption.key_size);
789 }
790 written += fprintf(stream, "/");
791 }
792
793 written += fprintf(stream, "%N", integrity_algorithm_names,
794 this->integrity.algorithm);
795 if (this->integrity.key_size)
796 {
797 written += fprintf(stream, "-%d", this->integrity.key_size);
798 }
799 written += fprintf(stream, ", rekeying ");
800
801 /* calculate rekey times */
802 if (this->rekey_time)
803 {
804 rekeying = this->install_time + this->rekey_time - now;
805 written += fprintf(stream, "in %ds", rekeying);
806 }
807 else
808 {
809 written += fprintf(stream, "disabled");
810 }
811 }
812 }
813 iterator = this->policies->create_iterator(this->policies, TRUE);
814 while (iterator->iterate(iterator, (void**)&policy))
815 {
816 written += fprintf(stream, "\n%12s{%d}: %R===%R, last use: ",
817 this->policy->get_name(this->policy), this->reqid,
818 policy->my_ts, policy->other_ts);
819
820 /* query time of last policy use */
821
822 /* inbound: POLICY_IN or POLICY_FWD */
823 status = charon->kernel_interface->query_policy(charon->kernel_interface,
824 policy->other_ts, policy->my_ts, POLICY_IN, &use_in);
825 use_in = (status == SUCCESS)? use_in : 0;
826 status = charon->kernel_interface->query_policy(charon->kernel_interface,
827 policy->other_ts, policy->my_ts, POLICY_FWD, &use_fwd);
828 use_fwd = (status == SUCCESS)? use_fwd : 0;
829 use = max(use_in, use_fwd);
830 if (use)
831 {
832 written += fprintf(stream, "%ds_i ", now - use);
833 }
834 else
835 {
836 written += fprintf(stream, "no_i ");
837 }
838
839 /* outbound: POLICY_OUT */
840 status = charon->kernel_interface->query_policy(charon->kernel_interface,
841 policy->my_ts, policy->other_ts, POLICY_OUT, &use);
842 if (status == SUCCESS && use)
843 {
844 written += fprintf(stream, "%ds_o ", now - use);
845 }
846 else
847 {
848 written += fprintf(stream, "no_o ");
849 }
850 }
851 iterator->destroy(iterator);
852 return written;
853 }
854
855 /**
856 * register printf() handlers
857 */
858 static void __attribute__ ((constructor))print_register()
859 {
860 register_printf_function(PRINTF_CHILD_SA, print, arginfo_ptr);
861 }
862
863 /**
864 * Update the host adress/port of a SA
865 */
866 static status_t update_sa_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other,
867 int my_changes, int other_changes, bool mine)
868 {
869 host_t *src, *dst, *new_src, *new_dst;
870 int src_changes, dst_changes;
871 status_t status;
872 u_int32_t spi;
873
874 if (mine)
875 {
876 src = this->other.addr;
877 dst = this->me.addr;
878 new_src = new_other;
879 new_dst = new_me;
880 src_changes = other_changes;
881 dst_changes = my_changes;
882 spi = this->other.spi;
883 }
884 else
885 {
886 src = this->me.addr;
887 dst = this->other.addr;
888 new_src = new_me;
889 new_dst = new_other;
890 src_changes = my_changes;
891 dst_changes = other_changes;
892 spi = this->me.spi;
893 }
894
895 DBG2(DBG_CHD, "updating %N SA 0x%x, from %#H..#H to %#H..%#H",
896 protocol_id_names, this->protocol, ntohl(spi), src, dst, new_src, new_dst);
897
898 status = charon->kernel_interface->update_sa(charon->kernel_interface,
899 dst, spi, this->protocol,
900 new_src, new_dst,
901 src_changes, dst_changes);
902
903 if (status != SUCCESS)
904 {
905 return FAILED;
906 }
907 return SUCCESS;
908 }
909
910 /**
911 * Update the host adress/port of a policy
912 */
913 static status_t update_policy_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other)
914 {
915 iterator_t *iterator;
916 sa_policy_t *policy;
917 status_t status;
918 /* we always use high priorities, as hosts getting updated are INSTALLED */
919
920 iterator = this->policies->create_iterator(this->policies, TRUE);
921 while (iterator->iterate(iterator, (void**)&policy))
922 {
923 status = charon->kernel_interface->add_policy(
924 charon->kernel_interface,
925 new_me, new_other,
926 policy->my_ts, policy->other_ts,
927 POLICY_OUT, this->protocol, this->reqid, TRUE, this->mode, TRUE);
928
929 status |= charon->kernel_interface->add_policy(
930 charon->kernel_interface,
931 new_other, new_me,
932 policy->other_ts, policy->my_ts,
933 POLICY_IN, this->protocol, this->reqid, TRUE, this->mode, TRUE);
934
935 status |= charon->kernel_interface->add_policy(
936 charon->kernel_interface,
937 new_other, new_me,
938 policy->other_ts, policy->my_ts,
939 POLICY_FWD, this->protocol, this->reqid, TRUE, this->mode, TRUE);
940
941 if (status != SUCCESS)
942 {
943 iterator->destroy(iterator);
944 return FAILED;
945 }
946 }
947 iterator->destroy(iterator);
948
949 return SUCCESS;
950 }
951
952 /**
953 * Implementation of child_sa_t.update_hosts.
954 */
955 static status_t update_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other,
956 host_diff_t my_changes, host_diff_t other_changes)
957 {
958 if (!my_changes && !other_changes)
959 {
960 return SUCCESS;
961 }
962
963 /* update our (initator) SAs */
964 if (update_sa_hosts(this, new_me, new_other, my_changes, other_changes, TRUE) != SUCCESS)
965 {
966 return FAILED;
967 }
968
969 /* update his (responder) SAs */
970 if (update_sa_hosts(this, new_me, new_other, my_changes, other_changes, FALSE) != SUCCESS)
971 {
972 return FAILED;
973 }
974
975 /* update policies */
976 if (my_changes & HOST_DIFF_ADDR || other_changes & HOST_DIFF_ADDR)
977 {
978 if (update_policy_hosts(this, new_me, new_other) != SUCCESS)
979 {
980 return FAILED;
981 }
982 }
983
984 /* update hosts */
985 if (my_changes)
986 {
987 this->me.addr->destroy(this->me.addr);
988 this->me.addr = new_me->clone(new_me);
989 }
990
991 if (other_changes)
992 {
993 this->other.addr->destroy(this->other.addr);
994 this->other.addr = new_other->clone(new_other);
995 }
996
997 return SUCCESS;
998 }
999
1000 /**
1001 * Implementation of child_sa_t.set_virtual_ip.
1002 */
1003 static void set_virtual_ip(private_child_sa_t *this, host_t *ip)
1004 {
1005 this->virtual_ip = ip->clone(ip);
1006 }
1007
1008 /**
1009 * Implementation of child_sa_t.destroy.
1010 */
1011 static void destroy(private_child_sa_t *this)
1012 {
1013 sa_policy_t *policy;
1014
1015 if (this->state == CHILD_DELETING || this->state == CHILD_INSTALLED)
1016 {
1017 updown(this, FALSE);
1018 }
1019
1020 /* delete SAs in the kernel, if they are set up */
1021 if (this->me.spi)
1022 {
1023 charon->kernel_interface->del_sa(charon->kernel_interface,
1024 this->me.addr, this->me.spi, this->protocol);
1025 }
1026 if (this->alloc_esp_spi && this->alloc_esp_spi != this->me.spi)
1027 {
1028 charon->kernel_interface->del_sa(charon->kernel_interface,
1029 this->me.addr, this->alloc_esp_spi, PROTO_ESP);
1030 }
1031 if (this->alloc_ah_spi && this->alloc_ah_spi != this->me.spi)
1032 {
1033 charon->kernel_interface->del_sa(charon->kernel_interface,
1034 this->me.addr, this->alloc_ah_spi, PROTO_AH);
1035 }
1036 if (this->other.spi)
1037 {
1038 charon->kernel_interface->del_sa(charon->kernel_interface,
1039 this->other.addr, this->other.spi, this->protocol);
1040 }
1041
1042 /* delete all policies in the kernel */
1043 while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
1044 {
1045 /* let rekeyed policies, as they are used by another child_sa */
1046 charon->kernel_interface->del_policy(charon->kernel_interface,
1047 policy->my_ts, policy->other_ts,
1048 POLICY_OUT);
1049
1050 charon->kernel_interface->del_policy(charon->kernel_interface,
1051 policy->other_ts, policy->my_ts,
1052 POLICY_IN);
1053
1054 charon->kernel_interface->del_policy(charon->kernel_interface,
1055 policy->other_ts, policy->my_ts,
1056 POLICY_FWD);
1057 policy->my_ts->destroy(policy->my_ts);
1058 policy->other_ts->destroy(policy->other_ts);
1059 free(policy);
1060 }
1061 this->policies->destroy(this->policies);
1062
1063 this->my_ts->destroy(this->my_ts);
1064 this->other_ts->destroy(this->other_ts);
1065 this->me.addr->destroy(this->me.addr);
1066 this->other.addr->destroy(this->other.addr);
1067 this->me.id->destroy(this->me.id);
1068 this->other.id->destroy(this->other.id);
1069 this->policy->destroy(this->policy);
1070 DESTROY_IF(this->virtual_ip);
1071 free(this);
1072 }
1073
1074 /*
1075 * Described in header.
1076 */
1077 child_sa_t * child_sa_create(host_t *me, host_t* other,
1078 identification_t *my_id, identification_t *other_id,
1079 policy_t *policy, u_int32_t rekey, bool use_natt)
1080 {
1081 static u_int32_t reqid = 0;
1082 private_child_sa_t *this = malloc_thing(private_child_sa_t);
1083
1084 /* public functions */
1085 this->public.get_name = (char*(*)(child_sa_t*))get_name;
1086 this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid;
1087 this->public.get_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi;
1088 this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol;
1089 this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
1090 this->public.add = (status_t(*)(child_sa_t*,proposal_t*,mode_t,prf_plus_t*))add;
1091 this->public.update = (status_t(*)(child_sa_t*,proposal_t*,mode_t,prf_plus_t*))update;
1092 this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_diff_t,host_diff_t))update_hosts;
1093 this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,mode_t))add_policies;
1094 this->public.get_my_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_my_traffic_selectors;
1095 this->public.get_other_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_other_traffic_selectors;
1096 this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
1097 this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
1098 this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
1099 this->public.get_policy = (policy_t*(*)(child_sa_t*))get_policy;
1100 this->public.set_virtual_ip = (void(*)(child_sa_t*,host_t*))set_virtual_ip;
1101 this->public.destroy = (void(*)(child_sa_t*))destroy;
1102
1103 /* private data */
1104 this->me.addr = me->clone(me);
1105 this->other.addr = other->clone(other);
1106 this->me.id = my_id->clone(my_id);
1107 this->other.id = other_id->clone(other_id);
1108 this->me.spi = 0;
1109 this->other.spi = 0;
1110 this->alloc_ah_spi = 0;
1111 this->alloc_esp_spi = 0;
1112 this->use_natt = use_natt;
1113 this->state = CHILD_CREATED;
1114 /* reuse old reqid if we are rekeying an existing CHILD_SA */
1115 this->reqid = rekey ? rekey : ++reqid;
1116 this->encryption.algorithm = ENCR_UNDEFINED;
1117 this->encryption.key_size = 0;
1118 this->integrity.algorithm = AUTH_UNDEFINED;
1119 this->encryption.key_size = 0;
1120 this->policies = linked_list_create();
1121 this->my_ts = linked_list_create();
1122 this->other_ts = linked_list_create();
1123 this->protocol = PROTO_NONE;
1124 this->mode = MODE_TUNNEL;
1125 this->virtual_ip = NULL;
1126 this->policy = policy;
1127 policy->get_ref(policy);
1128
1129 return &this->public;
1130 }