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