2 * Copyright (C) 2006-2008 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
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>.
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
29 ENUM(child_sa_state_names
, CHILD_CREATED
, CHILD_DESTROYING
,
39 typedef struct private_child_sa_t private_child_sa_t
;
42 * Private data of a child_sa_t object.
44 struct private_child_sa_t
{
46 * Public interface of child_sa_t.
51 /** address of peer */
53 /** actual used SPI, 0 if unused */
55 /** Compression Parameter Index (CPI) used, 0 if unused */
60 * Allocated SPI for a ESP proposal candidates
62 u_int32_t alloc_esp_spi
;
65 * Allocated SPI for a AH proposal candidates
67 u_int32_t alloc_ah_spi
;
70 * Protocol used to protect this SA, ESP|AH
72 protocol_id_t protocol
;
75 * Separate list for local traffic selectors
80 * Separate list for remote traffic selectors
82 linked_list_t
*other_ts
;
85 * reqid used for this child_sa
90 * encryption algorithm used for this SA
95 * Encryption key data, inbound and outbound
100 * integrity protection algorithm used for this SA
105 * integrity key data, inbound and outbound
110 * absolute time when rekeying is scheduled
115 * absolute time when the SA expires
120 * state of the CHILD_SA
122 child_sa_state_t state
;
125 * Specifies if UDP encapsulation is enabled (NAT traversal)
130 * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
132 ipcomp_transform_t ipcomp
;
135 * TRUE if we allocated (or tried to allocate) a CPI
140 * mode this SA uses, tunnel/transport
145 * config used to create this child
150 typedef struct keylen_entry_t keylen_entry_t
;
153 * Implicit key length for an algorithm
155 struct keylen_entry_t
{
156 /** IKEv2 algorithm identifier */
158 /** key length in bits */
162 #define END_OF_LIST -1
165 * Keylen for encryption algos
167 keylen_entry_t keylen_enc
[] = {
174 * Keylen for integrity algos
176 keylen_entry_t keylen_int
[] = {
177 {AUTH_HMAC_MD5_96
, 128},
178 {AUTH_HMAC_SHA1_96
, 160},
179 {AUTH_HMAC_SHA2_256_128
, 256},
180 {AUTH_HMAC_SHA2_384_192
, 384},
181 {AUTH_HMAC_SHA2_512_256
, 512},
182 {AUTH_AES_XCBC_96
, 128},
187 * Lookup key length of an algorithm
189 static int lookup_keylen(keylen_entry_t
*list
, int algo
)
191 while (list
->algo
!= END_OF_LIST
)
193 if (algo
== list
->algo
)
203 * Implementation of child_sa_t.get_name.
205 static char *get_name(private_child_sa_t
*this)
207 return this->config
->get_name(this->config
);
211 * Implements child_sa_t.get_reqid
213 static u_int32_t
get_reqid(private_child_sa_t
*this)
219 * Implements child_sa_t.get_spi
221 u_int32_t
get_spi(private_child_sa_t
*this, bool inbound
)
227 return this->other
.spi
;
231 * Implements child_sa_t.get_cpi
233 u_int16_t
get_cpi(private_child_sa_t
*this, bool inbound
)
239 return this->other
.cpi
;
243 * Implements child_sa_t.get_protocol
245 protocol_id_t
get_protocol(private_child_sa_t
*this)
247 return this->protocol
;
251 * Implements child_sa_t.get_state
253 static child_sa_state_t
get_state(private_child_sa_t
*this)
259 * Implements child_sa_t.get_config
261 static child_cfg_t
* get_config(private_child_sa_t
*this)
266 typedef struct policy_enumerator_t policy_enumerator_t
;
269 * Private policy enumerator
271 struct policy_enumerator_t
{
272 /** implements enumerator_t */
274 /** enumerator over own TS */
276 /** enumerator over others TS */
278 /** list of others TS, to recreate enumerator */
280 /** currently enumerating TS for "me" side */
281 traffic_selector_t
*ts
;
285 * enumerator function of create_policy_enumerator()
287 static bool policy_enumerate(policy_enumerator_t
*this,
288 traffic_selector_t
**my_out
, traffic_selector_t
**other_out
)
290 traffic_selector_t
*other_ts
;
292 while (this->ts
|| this->mine
->enumerate(this->mine
, &this->ts
))
294 if (!this->other
->enumerate(this->other
, &other_ts
))
295 { /* end of others list, restart with new of mine */
296 this->other
->destroy(this->other
);
297 this->other
= this->list
->create_enumerator(this->list
);
301 if (this->ts
->get_type(this->ts
) != other_ts
->get_type(other_ts
))
302 { /* family mismatch */
305 if (this->ts
->get_protocol(this->ts
) &&
306 other_ts
->get_protocol(other_ts
) &&
307 this->ts
->get_protocol(this->ts
) != other_ts
->get_protocol(other_ts
))
308 { /* protocol mismatch */
312 *other_out
= other_ts
;
319 * destroy function of create_policy_enumerator()
321 static void policy_destroy(policy_enumerator_t
*this)
323 this->mine
->destroy(this->mine
);
324 this->other
->destroy(this->other
);
329 * Implementation of child_sa_t.create_policy_enumerator
331 static enumerator_t
* create_policy_enumerator(private_child_sa_t
*this)
333 policy_enumerator_t
*e
= malloc_thing(policy_enumerator_t
);
335 e
->public.enumerate
= (void*)policy_enumerate
;
336 e
->public.destroy
= (void*)policy_destroy
;
337 e
->mine
= this->my_ts
->create_enumerator(this->my_ts
);
338 e
->other
= this->other_ts
->create_enumerator(this->other_ts
);
339 e
->list
= this->other_ts
;
346 * Implementation of child_sa_t.get_usetime
348 static u_int32_t
get_usetime(private_child_sa_t
*this, bool inbound
)
350 enumerator_t
*enumerator
;
351 traffic_selector_t
*my_ts
, *other_ts
;
352 u_int32_t last_use
= 0;
354 enumerator
= create_policy_enumerator(this);
355 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
357 u_int32_t in
, out
, fwd
;
361 if (charon
->kernel_interface
->query_policy(charon
->kernel_interface
,
362 other_ts
, my_ts
, POLICY_IN
, &in
) == SUCCESS
)
364 last_use
= max(last_use
, in
);
366 if (charon
->kernel_interface
->query_policy(charon
->kernel_interface
,
367 other_ts
, my_ts
, POLICY_FWD
, &fwd
) == SUCCESS
)
369 last_use
= max(last_use
, fwd
);
374 if (charon
->kernel_interface
->query_policy(charon
->kernel_interface
,
375 my_ts
, other_ts
, POLICY_OUT
, &out
) == SUCCESS
)
377 last_use
= max(last_use
, out
);
381 enumerator
->destroy(enumerator
);
386 * Implementation of child_sa_t.get_lifetime
388 static u_int32_t
get_lifetime(private_child_sa_t
*this, bool hard
)
392 return this->expire_time
;
394 return this->rekey_time
;
398 * Implementation of child_sa_t.get_integrity
400 static integrity_algorithm_t
get_integrity(private_child_sa_t
*this,
401 bool inbound
, chunk_t
*key
)
403 *key
= this->int_key
[!!inbound
];
404 return this->int_alg
;
408 * Implementation of child_sa_t.get_encryption
410 static encryption_algorithm_t
get_encryption(private_child_sa_t
*this,
411 bool inbound
, chunk_t
*key
)
413 *key
= this->enc_key
[!!inbound
];
414 return this->enc_alg
;
418 * Implementation of child_sa_t.get_mode
420 static ipsec_mode_t
get_mode(private_child_sa_t
*this)
426 * Implements child_sa_t.set_state
428 static void set_state(private_child_sa_t
*this, child_sa_state_t state
)
430 charon
->bus
->child_state_change(charon
->bus
, &this->public, state
);
435 * Allocate SPI for a single proposal
437 static status_t
alloc_proposal(private_child_sa_t
*this, proposal_t
*proposal
)
439 protocol_id_t protocol
= proposal
->get_protocol(proposal
);
441 if (protocol
== PROTO_AH
)
443 /* get a new spi for AH, if not already done */
444 if (this->alloc_ah_spi
== 0)
446 if (charon
->kernel_interface
->get_spi(
447 charon
->kernel_interface
,
448 this->other
.addr
, this->me
.addr
,
449 PROTO_AH
, this->reqid
,
450 &this->alloc_ah_spi
) != SUCCESS
)
455 proposal
->set_spi(proposal
, this->alloc_ah_spi
);
457 if (protocol
== PROTO_ESP
)
459 /* get a new spi for ESP, if not already done */
460 if (this->alloc_esp_spi
== 0)
462 if (charon
->kernel_interface
->get_spi(
463 charon
->kernel_interface
,
464 this->other
.addr
, this->me
.addr
,
465 PROTO_ESP
, this->reqid
,
466 &this->alloc_esp_spi
) != SUCCESS
)
471 proposal
->set_spi(proposal
, this->alloc_esp_spi
);
478 * Implements child_sa_t.alloc
480 static status_t
alloc(private_child_sa_t
*this, linked_list_t
*proposals
)
482 iterator_t
*iterator
;
483 proposal_t
*proposal
;
485 /* iterator through proposals to update spis */
486 iterator
= proposals
->create_iterator(proposals
, TRUE
);
487 while(iterator
->iterate(iterator
, (void**)&proposal
))
489 if (alloc_proposal(this, proposal
) != SUCCESS
)
491 iterator
->destroy(iterator
);
495 iterator
->destroy(iterator
);
499 static status_t
install(private_child_sa_t
*this, proposal_t
*proposal
,
500 ipsec_mode_t mode
, prf_plus_t
*prf_plus
, bool mine
)
502 u_int32_t spi
, cpi
, soft
, hard
, now
;
506 u_int16_t enc_size
, int_size
;
508 this->protocol
= proposal
->get_protocol(proposal
);
510 /* now we have to decide which spi to use. Use self allocated, if "mine",
511 * or the one in the proposal, if not "mine" (others). Additionally,
512 * source and dest host switch depending on the role */
515 /* if we have allocated SPIs for AH and ESP, we must delete the unused
517 if (this->protocol
== PROTO_ESP
)
519 this->me
.spi
= this->alloc_esp_spi
;
520 if (this->alloc_ah_spi
)
522 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
523 this->me
.addr
, this->alloc_ah_spi
, PROTO_AH
);
528 this->me
.spi
= this->alloc_ah_spi
;
529 if (this->alloc_esp_spi
)
531 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
532 this->me
.addr
, this->alloc_esp_spi
, PROTO_ESP
);
537 src
= this->other
.addr
;
541 this->other
.spi
= proposal
->get_spi(proposal
);
542 spi
= this->other
.spi
;
544 dst
= this->other
.addr
;
547 DBG2(DBG_CHD
, "adding %s %N SA", mine ?
"inbound" : "outbound",
548 protocol_id_names
, this->protocol
);
550 /* select encryption algo, derive key */
551 if (proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
,
552 &this->enc_alg
, &enc_size
))
554 DBG2(DBG_CHD
, " using %N for encryption",
555 encryption_algorithm_names
, this->enc_alg
);
557 if (this->enc_alg
!= ENCR_UNDEFINED
)
561 enc_size
= lookup_keylen(keylen_enc
, this->enc_alg
);
565 DBG1(DBG_CHD
, "no keylenth defined for %N",
566 encryption_algorithm_names
, this->enc_alg
);
569 /* CCM/GCM needs additional keymat */
570 switch (this->enc_alg
)
572 case ENCR_AES_CCM_ICV8
:
573 case ENCR_AES_CCM_ICV12
:
574 case ENCR_AES_CCM_ICV16
:
577 case ENCR_AES_GCM_ICV8
:
578 case ENCR_AES_GCM_ICV12
:
579 case ENCR_AES_GCM_ICV16
:
586 prf_plus
->allocate_bytes(prf_plus
, enc_size
/ 8, &this->enc_key
[!!mine
]);
589 /* select integrity algo, derive key */
590 if (proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
,
591 &this->int_alg
, &int_size
))
593 DBG2(DBG_CHD
, " using %N for integrity",
594 integrity_algorithm_names
, this->int_alg
);
596 if (this->int_alg
!= AUTH_UNDEFINED
)
600 int_size
= lookup_keylen(keylen_int
, this->int_alg
);
604 DBG1(DBG_CHD
, "no keylenth defined for %N",
605 integrity_algorithm_names
, this->int_alg
);
608 prf_plus
->allocate_bytes(prf_plus
, int_size
/ 8, &this->int_key
[!!mine
]);
611 /* send SA down to the kernel */
612 DBG2(DBG_CHD
, " SPI 0x%.8x, src %H dst %H", ntohl(spi
), src
, dst
);
614 if (this->ipcomp
!= IPCOMP_NONE
)
616 /* we install an additional IPComp SA */
617 cpi
= htonl(ntohs(mine ?
this->me
.cpi
: this->other
.cpi
));
618 charon
->kernel_interface
->add_sa(charon
->kernel_interface
,
619 src
, dst
, cpi
, IPPROTO_COMP
, this->reqid
, 0, 0,
620 ENCR_UNDEFINED
, chunk_empty
, AUTH_UNDEFINED
, chunk_empty
,
621 mode
, this->ipcomp
, FALSE
, mine
);
624 soft
= this->config
->get_lifetime(this->config
, TRUE
);
625 hard
= this->config
->get_lifetime(this->config
, FALSE
);
626 status
= charon
->kernel_interface
->add_sa(charon
->kernel_interface
, src
, dst
,
627 spi
, this->protocol
, this->reqid
, mine ? soft
: 0, hard
,
628 this->enc_alg
, this->enc_key
[!!mine
],
629 this->int_alg
, this->int_key
[!!mine
],
630 mode
, IPCOMP_NONE
, this->encap
, mine
);
633 this->rekey_time
= now
+ soft
;
634 this->expire_time
= now
+ hard
;
638 static status_t
add(private_child_sa_t
*this, proposal_t
*proposal
,
639 ipsec_mode_t mode
, prf_plus_t
*prf_plus
)
641 u_int32_t outbound_spi
, inbound_spi
;
643 /* backup outbound spi, as alloc overwrites it */
644 outbound_spi
= proposal
->get_spi(proposal
);
646 /* get SPIs inbound SAs */
647 if (alloc_proposal(this, proposal
) != SUCCESS
)
651 inbound_spi
= proposal
->get_spi(proposal
);
653 /* install inbound SAs */
654 if (install(this, proposal
, mode
, prf_plus
, TRUE
) != SUCCESS
)
659 /* install outbound SAs, restore spi*/
660 proposal
->set_spi(proposal
, outbound_spi
);
661 if (install(this, proposal
, mode
, prf_plus
, FALSE
) != SUCCESS
)
665 proposal
->set_spi(proposal
, inbound_spi
);
670 static status_t
update(private_child_sa_t
*this, proposal_t
*proposal
,
671 ipsec_mode_t mode
, prf_plus_t
*prf_plus
)
673 u_int32_t inbound_spi
;
675 /* backup received spi, as install() overwrites it */
676 inbound_spi
= proposal
->get_spi(proposal
);
678 /* install outbound SAs */
679 if (install(this, proposal
, mode
, prf_plus
, FALSE
) != SUCCESS
)
685 proposal
->set_spi(proposal
, inbound_spi
);
686 /* install inbound SAs */
687 if (install(this, proposal
, mode
, prf_plus
, TRUE
) != SUCCESS
)
695 static status_t
add_policies(private_child_sa_t
*this,
696 linked_list_t
*my_ts_list
, linked_list_t
*other_ts_list
,
697 ipsec_mode_t mode
, protocol_id_t proto
)
699 enumerator_t
*enumerator
;
700 traffic_selector_t
*my_ts
, *other_ts
;
701 status_t status
= SUCCESS
;
702 bool high_prio
= TRUE
;
704 if (this->state
== CHILD_CREATED
)
705 { /* use low prio for ROUTED policies */
708 if (this->protocol
== PROTO_NONE
)
709 { /* update if not set yet */
710 this->protocol
= proto
;
713 /* apply traffic selectors */
714 enumerator
= my_ts_list
->create_enumerator(my_ts_list
);
715 while (enumerator
->enumerate(enumerator
, &my_ts
))
717 this->my_ts
->insert_last(this->my_ts
, my_ts
->clone(my_ts
));
719 enumerator
->destroy(enumerator
);
720 enumerator
= other_ts_list
->create_enumerator(other_ts_list
);
721 while (enumerator
->enumerate(enumerator
, &other_ts
))
723 this->other_ts
->insert_last(this->other_ts
, other_ts
->clone(other_ts
));
725 enumerator
->destroy(enumerator
);
727 /* enumerate pairs of traffic selectors */
728 enumerator
= create_policy_enumerator(this);
729 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
731 /* install 3 policies: out, in and forward */
732 status
|= charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
733 this->me
.addr
, this->other
.addr
, my_ts
, other_ts
, POLICY_OUT
,
734 this->protocol
, this->reqid
, high_prio
, mode
, this->ipcomp
);
736 status
|= charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
737 this->other
.addr
, this->me
.addr
, other_ts
, my_ts
, POLICY_IN
,
738 this->protocol
, this->reqid
, high_prio
, mode
, this->ipcomp
);
740 status
|= charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
741 this->other
.addr
, this->me
.addr
, other_ts
, my_ts
, POLICY_FWD
,
742 this->protocol
, this->reqid
, high_prio
, mode
, this->ipcomp
);
744 if (status
!= SUCCESS
)
749 enumerator
->destroy(enumerator
);
751 if (status
== SUCCESS
)
753 /* switch to routed state if no SAD entry set up */
754 if (this->state
== CHILD_CREATED
)
756 set_state(this, CHILD_ROUTED
);
758 /* needed to update hosts */
765 * Implementation of child_sa_t.get_traffic_selectors.
767 static linked_list_t
*get_traffic_selectors(private_child_sa_t
*this, bool local
)
773 return this->other_ts
;
777 * Implementation of child_sa_t.update_hosts.
779 static status_t
update_hosts(private_child_sa_t
*this,
780 host_t
*me
, host_t
*other
, host_t
*vip
, bool encap
)
782 child_sa_state_t old
;
784 /* anything changed at all? */
785 if (me
->equals(me
, this->me
.addr
) &&
786 other
->equals(other
, this->other
.addr
) && this->encap
== encap
)
792 set_state(this, CHILD_UPDATING
);
796 if (this->ipcomp
!= IPCOMP_NONE
)
798 /* update our (initator) IPComp SA */
799 charon
->kernel_interface
->update_sa(charon
->kernel_interface
,
800 htonl(ntohs(this->me
.cpi
)), IPPROTO_COMP
,
801 this->other
.addr
, this->me
.addr
, other
, me
, FALSE
);
802 /* update his (responder) IPComp SA */
803 charon
->kernel_interface
->update_sa(charon
->kernel_interface
,
804 htonl(ntohs(this->other
.cpi
)), IPPROTO_COMP
,
805 this->me
.addr
, this->other
.addr
, me
, other
, FALSE
);
808 /* update our (initator) SA */
809 charon
->kernel_interface
->update_sa(charon
->kernel_interface
, this->me
.spi
,
810 this->protocol
, this->other
.addr
, this->me
.addr
, other
, me
, encap
);
811 /* update his (responder) SA */
812 charon
->kernel_interface
->update_sa(charon
->kernel_interface
, this->other
.spi
,
813 this->protocol
, this->me
.addr
, this->other
.addr
, me
, other
, encap
);
815 /* update policies */
816 if (!me
->ip_equals(me
, this->me
.addr
) ||
817 !other
->ip_equals(other
, this->other
.addr
))
819 enumerator_t
*enumerator
;
820 traffic_selector_t
*my_ts
, *other_ts
;
822 /* always use high priorities, as hosts getting updated are INSTALLED */
823 enumerator
= create_policy_enumerator(this);
824 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
826 /* remove old policies first */
827 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
828 my_ts
, other_ts
, POLICY_OUT
);
829 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
830 other_ts
, my_ts
, POLICY_IN
);
831 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
832 other_ts
, my_ts
, POLICY_FWD
);
834 /* check whether we have to update a "dynamic" traffic selector */
835 if (!me
->ip_equals(me
, this->me
.addr
) &&
836 my_ts
->is_host(my_ts
, this->me
.addr
))
838 my_ts
->set_address(my_ts
, me
);
840 if (!other
->ip_equals(other
, this->other
.addr
) &&
841 other_ts
->is_host(other_ts
, this->other
.addr
))
843 other_ts
->set_address(other_ts
, other
);
846 /* we reinstall the virtual IP to handle interface roaming
850 charon
->kernel_interface
->del_ip(charon
->kernel_interface
, vip
);
851 charon
->kernel_interface
->add_ip(charon
->kernel_interface
, vip
, me
);
854 /* reinstall updated policies */
855 charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
856 me
, other
, my_ts
, other_ts
, POLICY_OUT
, this->protocol
,
857 this->reqid
, TRUE
, this->mode
, this->ipcomp
);
858 charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
859 other
, me
, other_ts
, my_ts
, POLICY_IN
, this->protocol
,
860 this->reqid
, TRUE
, this->mode
, this->ipcomp
);
861 charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
862 other
, me
, other_ts
, my_ts
, POLICY_FWD
, this->protocol
,
863 this->reqid
, TRUE
, this->mode
, this->ipcomp
);
865 enumerator
->destroy(enumerator
);
869 if (!me
->equals(me
, this->me
.addr
))
871 this->me
.addr
->destroy(this->me
.addr
);
872 this->me
.addr
= me
->clone(me
);
874 if (!other
->equals(other
, this->other
.addr
))
876 this->other
.addr
->destroy(this->other
.addr
);
877 this->other
.addr
= other
->clone(other
);
880 set_state(this, old
);
886 * Implementation of child_sa_t.activate_ipcomp.
888 static void activate_ipcomp(private_child_sa_t
*this, ipcomp_transform_t ipcomp
,
891 this->ipcomp
= ipcomp
;
892 this->other
.cpi
= other_cpi
;
896 * Implementation of child_sa_t.allocate_cpi.
898 static u_int16_t
allocate_cpi(private_child_sa_t
*this)
900 if (!this->cpi_allocated
)
902 charon
->kernel_interface
->get_cpi(charon
->kernel_interface
,
903 this->other
.addr
, this->me
.addr
, this->reqid
, &this->me
.cpi
);
904 this->cpi_allocated
= TRUE
;
910 * Implementation of child_sa_t.destroy.
912 static void destroy(private_child_sa_t
*this)
914 enumerator_t
*enumerator
;
915 traffic_selector_t
*my_ts
, *other_ts
;
917 set_state(this, CHILD_DESTROYING
);
919 /* delete SAs in the kernel, if they are set up */
922 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
923 this->me
.addr
, this->me
.spi
, this->protocol
);
925 if (this->alloc_esp_spi
&& this->alloc_esp_spi
!= this->me
.spi
)
927 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
928 this->me
.addr
, this->alloc_esp_spi
, PROTO_ESP
);
930 if (this->alloc_ah_spi
&& this->alloc_ah_spi
!= this->me
.spi
)
932 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
933 this->me
.addr
, this->alloc_ah_spi
, PROTO_AH
);
937 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
938 this->other
.addr
, this->other
.spi
, this->protocol
);
942 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
943 this->me
.addr
, htonl(ntohs(this->me
.cpi
)), IPPROTO_COMP
);
947 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
948 this->other
.addr
, htonl(ntohs(this->other
.cpi
)), IPPROTO_COMP
);
951 /* delete all policies in the kernel */
952 enumerator
= create_policy_enumerator(this);
953 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
955 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
956 my_ts
, other_ts
, POLICY_OUT
);
957 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
958 other_ts
, my_ts
, POLICY_IN
);
959 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
960 other_ts
, my_ts
, POLICY_FWD
);
962 enumerator
->destroy(enumerator
);
964 chunk_clear(&this->enc_key
[0]);
965 chunk_clear(&this->enc_key
[1]);
966 chunk_clear(&this->int_key
[0]);
967 chunk_clear(&this->int_key
[1]);
968 this->my_ts
->destroy_offset(this->my_ts
, offsetof(traffic_selector_t
, destroy
));
969 this->other_ts
->destroy_offset(this->other_ts
, offsetof(traffic_selector_t
, destroy
));
970 this->me
.addr
->destroy(this->me
.addr
);
971 this->other
.addr
->destroy(this->other
.addr
);
972 this->config
->destroy(this->config
);
977 * Described in header.
979 child_sa_t
* child_sa_create(host_t
*me
, host_t
* other
,
980 child_cfg_t
*config
, u_int32_t rekey
, bool encap
)
982 static u_int32_t reqid
= 0;
983 private_child_sa_t
*this = malloc_thing(private_child_sa_t
);
985 /* public functions */
986 this->public.get_name
= (char*(*)(child_sa_t
*))get_name
;
987 this->public.get_reqid
= (u_int32_t(*)(child_sa_t
*))get_reqid
;
988 this->public.get_spi
= (u_int32_t(*)(child_sa_t
*, bool))get_spi
;
989 this->public.get_cpi
= (u_int16_t(*)(child_sa_t
*, bool))get_cpi
;
990 this->public.get_protocol
= (protocol_id_t(*)(child_sa_t
*))get_protocol
;
991 this->public.get_mode
= (ipsec_mode_t(*)(child_sa_t
*))get_mode
;
992 this->public.get_encryption
= (encryption_algorithm_t(*)(child_sa_t
*, bool, chunk_t
*))get_encryption
;
993 this->public.get_integrity
= (integrity_algorithm_t(*)(child_sa_t
*, bool, chunk_t
*))get_integrity
;
994 this->public.get_lifetime
= (u_int32_t(*)(child_sa_t
*, bool))get_lifetime
;
995 this->public.get_usetime
= (u_int32_t(*)(child_sa_t
*, bool))get_usetime
;
996 this->public.alloc
= (status_t(*)(child_sa_t
*,linked_list_t
*))alloc
;
997 this->public.add
= (status_t(*)(child_sa_t
*,proposal_t
*,ipsec_mode_t
,prf_plus_t
*))add
;
998 this->public.update
= (status_t(*)(child_sa_t
*,proposal_t
*,ipsec_mode_t
,prf_plus_t
*))update
;
999 this->public.update_hosts
= (status_t (*)(child_sa_t
*,host_t
*,host_t
*,host_t
*,bool))update_hosts
;
1000 this->public.add_policies
= (status_t (*)(child_sa_t
*, linked_list_t
*,linked_list_t
*,ipsec_mode_t
,protocol_id_t
))add_policies
;
1001 this->public.get_traffic_selectors
= (linked_list_t
*(*)(child_sa_t
*,bool))get_traffic_selectors
;
1002 this->public.create_policy_enumerator
= (enumerator_t
*(*)(child_sa_t
*))create_policy_enumerator
;
1003 this->public.set_state
= (void(*)(child_sa_t
*,child_sa_state_t
))set_state
;
1004 this->public.get_state
= (child_sa_state_t(*)(child_sa_t
*))get_state
;
1005 this->public.get_config
= (child_cfg_t
*(*)(child_sa_t
*))get_config
;
1006 this->public.activate_ipcomp
= (void(*)(child_sa_t
*,ipcomp_transform_t
,u_int16_t
))activate_ipcomp
;
1007 this->public.allocate_cpi
= (u_int16_t(*)(child_sa_t
*))allocate_cpi
;
1008 this->public.destroy
= (void(*)(child_sa_t
*))destroy
;
1011 this->me
.addr
= me
->clone(me
);
1012 this->other
.addr
= other
->clone(other
);
1015 this->other
.spi
= 0;
1016 this->other
.cpi
= 0;
1017 this->alloc_ah_spi
= 0;
1018 this->alloc_esp_spi
= 0;
1019 this->encap
= encap
;
1020 this->cpi_allocated
= FALSE
;
1021 this->ipcomp
= IPCOMP_NONE
;
1022 this->state
= CHILD_CREATED
;
1023 /* reuse old reqid if we are rekeying an existing CHILD_SA */
1024 this->reqid
= rekey ? rekey
: ++reqid
;
1025 this->enc_alg
= ENCR_UNDEFINED
;
1026 this->enc_key
[0] = this->enc_key
[1] = chunk_empty
;
1027 this->int_alg
= AUTH_UNDEFINED
;
1028 this->int_key
[0] = this->int_key
[1] = chunk_empty
;
1029 this->my_ts
= linked_list_create();
1030 this->other_ts
= linked_list_create();
1031 this->protocol
= PROTO_NONE
;
1032 this->mode
= MODE_TUNNEL
;
1033 this->config
= config
;
1034 config
->get_ref(config
);
1036 return &this->public;