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 * Implementation of child_sa_t.has_encap
253 static bool has_encap(private_child_sa_t
*this)
259 * Implementation of child_sa_t.get_ipcomp
261 static ipcomp_transform_t
get_ipcomp(private_child_sa_t
*this)
267 * Implements child_sa_t.get_state
269 static child_sa_state_t
get_state(private_child_sa_t
*this)
275 * Implements child_sa_t.get_config
277 static child_cfg_t
* get_config(private_child_sa_t
*this)
282 typedef struct policy_enumerator_t policy_enumerator_t
;
285 * Private policy enumerator
287 struct policy_enumerator_t
{
288 /** implements enumerator_t */
290 /** enumerator over own TS */
292 /** enumerator over others TS */
294 /** list of others TS, to recreate enumerator */
296 /** currently enumerating TS for "me" side */
297 traffic_selector_t
*ts
;
301 * enumerator function of create_policy_enumerator()
303 static bool policy_enumerate(policy_enumerator_t
*this,
304 traffic_selector_t
**my_out
, traffic_selector_t
**other_out
)
306 traffic_selector_t
*other_ts
;
308 while (this->ts
|| this->mine
->enumerate(this->mine
, &this->ts
))
310 if (!this->other
->enumerate(this->other
, &other_ts
))
311 { /* end of others list, restart with new of mine */
312 this->other
->destroy(this->other
);
313 this->other
= this->list
->create_enumerator(this->list
);
317 if (this->ts
->get_type(this->ts
) != other_ts
->get_type(other_ts
))
318 { /* family mismatch */
321 if (this->ts
->get_protocol(this->ts
) &&
322 other_ts
->get_protocol(other_ts
) &&
323 this->ts
->get_protocol(this->ts
) != other_ts
->get_protocol(other_ts
))
324 { /* protocol mismatch */
328 *other_out
= other_ts
;
335 * destroy function of create_policy_enumerator()
337 static void policy_destroy(policy_enumerator_t
*this)
339 this->mine
->destroy(this->mine
);
340 this->other
->destroy(this->other
);
345 * Implementation of child_sa_t.create_policy_enumerator
347 static enumerator_t
* create_policy_enumerator(private_child_sa_t
*this)
349 policy_enumerator_t
*e
= malloc_thing(policy_enumerator_t
);
351 e
->public.enumerate
= (void*)policy_enumerate
;
352 e
->public.destroy
= (void*)policy_destroy
;
353 e
->mine
= this->my_ts
->create_enumerator(this->my_ts
);
354 e
->other
= this->other_ts
->create_enumerator(this->other_ts
);
355 e
->list
= this->other_ts
;
362 * Implementation of child_sa_t.get_usetime
364 static u_int32_t
get_usetime(private_child_sa_t
*this, bool inbound
)
366 enumerator_t
*enumerator
;
367 traffic_selector_t
*my_ts
, *other_ts
;
368 u_int32_t last_use
= 0;
370 enumerator
= create_policy_enumerator(this);
371 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
373 u_int32_t in
, out
, fwd
;
377 if (charon
->kernel_interface
->query_policy(charon
->kernel_interface
,
378 other_ts
, my_ts
, POLICY_IN
, &in
) == SUCCESS
)
380 last_use
= max(last_use
, in
);
382 if (charon
->kernel_interface
->query_policy(charon
->kernel_interface
,
383 other_ts
, my_ts
, POLICY_FWD
, &fwd
) == SUCCESS
)
385 last_use
= max(last_use
, fwd
);
390 if (charon
->kernel_interface
->query_policy(charon
->kernel_interface
,
391 my_ts
, other_ts
, POLICY_OUT
, &out
) == SUCCESS
)
393 last_use
= max(last_use
, out
);
397 enumerator
->destroy(enumerator
);
402 * Implementation of child_sa_t.get_lifetime
404 static u_int32_t
get_lifetime(private_child_sa_t
*this, bool hard
)
408 return this->expire_time
;
410 return this->rekey_time
;
414 * Implementation of child_sa_t.get_integrity
416 static integrity_algorithm_t
get_integrity(private_child_sa_t
*this,
417 bool inbound
, chunk_t
*key
)
419 *key
= this->int_key
[!!inbound
];
420 return this->int_alg
;
424 * Implementation of child_sa_t.get_encryption
426 static encryption_algorithm_t
get_encryption(private_child_sa_t
*this,
427 bool inbound
, chunk_t
*key
)
429 *key
= this->enc_key
[!!inbound
];
430 return this->enc_alg
;
434 * Implementation of child_sa_t.get_mode
436 static ipsec_mode_t
get_mode(private_child_sa_t
*this)
442 * Implements child_sa_t.set_state
444 static void set_state(private_child_sa_t
*this, child_sa_state_t state
)
446 charon
->bus
->child_state_change(charon
->bus
, &this->public, state
);
451 * Allocate SPI for a single proposal
453 static status_t
alloc_proposal(private_child_sa_t
*this, proposal_t
*proposal
)
455 protocol_id_t protocol
= proposal
->get_protocol(proposal
);
457 if (protocol
== PROTO_AH
)
459 /* get a new spi for AH, if not already done */
460 if (this->alloc_ah_spi
== 0)
462 if (charon
->kernel_interface
->get_spi(
463 charon
->kernel_interface
,
464 this->other
.addr
, this->me
.addr
,
465 PROTO_AH
, this->reqid
,
466 &this->alloc_ah_spi
) != SUCCESS
)
471 proposal
->set_spi(proposal
, this->alloc_ah_spi
);
473 if (protocol
== PROTO_ESP
)
475 /* get a new spi for ESP, if not already done */
476 if (this->alloc_esp_spi
== 0)
478 if (charon
->kernel_interface
->get_spi(
479 charon
->kernel_interface
,
480 this->other
.addr
, this->me
.addr
,
481 PROTO_ESP
, this->reqid
,
482 &this->alloc_esp_spi
) != SUCCESS
)
487 proposal
->set_spi(proposal
, this->alloc_esp_spi
);
494 * Implements child_sa_t.alloc
496 static status_t
alloc(private_child_sa_t
*this, linked_list_t
*proposals
)
498 iterator_t
*iterator
;
499 proposal_t
*proposal
;
501 /* iterator through proposals to update spis */
502 iterator
= proposals
->create_iterator(proposals
, TRUE
);
503 while(iterator
->iterate(iterator
, (void**)&proposal
))
505 if (alloc_proposal(this, proposal
) != SUCCESS
)
507 iterator
->destroy(iterator
);
511 iterator
->destroy(iterator
);
515 static status_t
install(private_child_sa_t
*this, proposal_t
*proposal
,
516 ipsec_mode_t mode
, prf_plus_t
*prf_plus
, bool mine
)
518 u_int32_t spi
, cpi
, soft
, hard
, now
;
522 u_int16_t enc_size
, int_size
;
524 this->protocol
= proposal
->get_protocol(proposal
);
526 /* now we have to decide which spi to use. Use self allocated, if "mine",
527 * or the one in the proposal, if not "mine" (others). Additionally,
528 * source and dest host switch depending on the role */
531 /* if we have allocated SPIs for AH and ESP, we must delete the unused
533 if (this->protocol
== PROTO_ESP
)
535 this->me
.spi
= this->alloc_esp_spi
;
536 if (this->alloc_ah_spi
)
538 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
539 this->me
.addr
, this->alloc_ah_spi
, PROTO_AH
);
544 this->me
.spi
= this->alloc_ah_spi
;
545 if (this->alloc_esp_spi
)
547 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
548 this->me
.addr
, this->alloc_esp_spi
, PROTO_ESP
);
553 src
= this->other
.addr
;
557 this->other
.spi
= proposal
->get_spi(proposal
);
558 spi
= this->other
.spi
;
560 dst
= this->other
.addr
;
563 DBG2(DBG_CHD
, "adding %s %N SA", mine ?
"inbound" : "outbound",
564 protocol_id_names
, this->protocol
);
566 /* select encryption algo, derive key */
567 if (proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
,
568 &this->enc_alg
, &enc_size
))
570 DBG2(DBG_CHD
, " using %N for encryption",
571 encryption_algorithm_names
, this->enc_alg
);
573 if (this->enc_alg
!= ENCR_UNDEFINED
)
577 enc_size
= lookup_keylen(keylen_enc
, this->enc_alg
);
581 DBG1(DBG_CHD
, "no keylenth defined for %N",
582 encryption_algorithm_names
, this->enc_alg
);
585 /* CCM/GCM needs additional keymat */
586 switch (this->enc_alg
)
588 case ENCR_AES_CCM_ICV8
:
589 case ENCR_AES_CCM_ICV12
:
590 case ENCR_AES_CCM_ICV16
:
593 case ENCR_AES_GCM_ICV8
:
594 case ENCR_AES_GCM_ICV12
:
595 case ENCR_AES_GCM_ICV16
:
602 prf_plus
->allocate_bytes(prf_plus
, enc_size
/ 8, &this->enc_key
[!!mine
]);
605 /* select integrity algo, derive key */
606 if (proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
,
607 &this->int_alg
, &int_size
))
609 DBG2(DBG_CHD
, " using %N for integrity",
610 integrity_algorithm_names
, this->int_alg
);
612 if (this->int_alg
!= AUTH_UNDEFINED
)
616 int_size
= lookup_keylen(keylen_int
, this->int_alg
);
620 DBG1(DBG_CHD
, "no keylenth defined for %N",
621 integrity_algorithm_names
, this->int_alg
);
624 prf_plus
->allocate_bytes(prf_plus
, int_size
/ 8, &this->int_key
[!!mine
]);
627 /* send SA down to the kernel */
628 DBG2(DBG_CHD
, " SPI 0x%.8x, src %H dst %H", ntohl(spi
), src
, dst
);
630 if (this->ipcomp
!= IPCOMP_NONE
)
632 /* we install an additional IPComp SA */
633 cpi
= htonl(ntohs(mine ?
this->me
.cpi
: this->other
.cpi
));
634 charon
->kernel_interface
->add_sa(charon
->kernel_interface
,
635 src
, dst
, cpi
, IPPROTO_COMP
, this->reqid
, 0, 0,
636 ENCR_UNDEFINED
, chunk_empty
, AUTH_UNDEFINED
, chunk_empty
,
637 mode
, this->ipcomp
, FALSE
, mine
);
640 soft
= this->config
->get_lifetime(this->config
, TRUE
);
641 hard
= this->config
->get_lifetime(this->config
, FALSE
);
642 status
= charon
->kernel_interface
->add_sa(charon
->kernel_interface
, src
, dst
,
643 spi
, this->protocol
, this->reqid
, mine ? soft
: 0, hard
,
644 this->enc_alg
, this->enc_key
[!!mine
],
645 this->int_alg
, this->int_key
[!!mine
],
646 mode
, IPCOMP_NONE
, this->encap
, mine
);
649 this->rekey_time
= now
+ soft
;
650 this->expire_time
= now
+ hard
;
654 static status_t
add(private_child_sa_t
*this, proposal_t
*proposal
,
655 ipsec_mode_t mode
, prf_plus_t
*prf_plus
)
657 u_int32_t outbound_spi
, inbound_spi
;
659 /* backup outbound spi, as alloc overwrites it */
660 outbound_spi
= proposal
->get_spi(proposal
);
662 /* get SPIs inbound SAs */
663 if (alloc_proposal(this, proposal
) != SUCCESS
)
667 inbound_spi
= proposal
->get_spi(proposal
);
669 /* install inbound SAs */
670 if (install(this, proposal
, mode
, prf_plus
, TRUE
) != SUCCESS
)
675 /* install outbound SAs, restore spi*/
676 proposal
->set_spi(proposal
, outbound_spi
);
677 if (install(this, proposal
, mode
, prf_plus
, FALSE
) != SUCCESS
)
681 proposal
->set_spi(proposal
, inbound_spi
);
686 static status_t
update(private_child_sa_t
*this, proposal_t
*proposal
,
687 ipsec_mode_t mode
, prf_plus_t
*prf_plus
)
689 u_int32_t inbound_spi
;
691 /* backup received spi, as install() overwrites it */
692 inbound_spi
= proposal
->get_spi(proposal
);
694 /* install outbound SAs */
695 if (install(this, proposal
, mode
, prf_plus
, FALSE
) != SUCCESS
)
701 proposal
->set_spi(proposal
, inbound_spi
);
702 /* install inbound SAs */
703 if (install(this, proposal
, mode
, prf_plus
, TRUE
) != SUCCESS
)
711 static status_t
add_policies(private_child_sa_t
*this,
712 linked_list_t
*my_ts_list
, linked_list_t
*other_ts_list
,
713 ipsec_mode_t mode
, protocol_id_t proto
)
715 enumerator_t
*enumerator
;
716 traffic_selector_t
*my_ts
, *other_ts
;
717 status_t status
= SUCCESS
;
718 bool high_prio
= TRUE
;
720 if (this->state
== CHILD_CREATED
)
721 { /* use low prio for ROUTED policies */
724 if (this->protocol
== PROTO_NONE
)
725 { /* update if not set yet */
726 this->protocol
= proto
;
729 /* apply traffic selectors */
730 enumerator
= my_ts_list
->create_enumerator(my_ts_list
);
731 while (enumerator
->enumerate(enumerator
, &my_ts
))
733 this->my_ts
->insert_last(this->my_ts
, my_ts
->clone(my_ts
));
735 enumerator
->destroy(enumerator
);
736 enumerator
= other_ts_list
->create_enumerator(other_ts_list
);
737 while (enumerator
->enumerate(enumerator
, &other_ts
))
739 this->other_ts
->insert_last(this->other_ts
, other_ts
->clone(other_ts
));
741 enumerator
->destroy(enumerator
);
743 /* enumerate pairs of traffic selectors */
744 enumerator
= create_policy_enumerator(this);
745 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
747 /* install 3 policies: out, in and forward */
748 status
|= charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
749 this->me
.addr
, this->other
.addr
, my_ts
, other_ts
, POLICY_OUT
,
750 this->protocol
, this->reqid
, high_prio
, mode
, this->ipcomp
);
752 status
|= charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
753 this->other
.addr
, this->me
.addr
, other_ts
, my_ts
, POLICY_IN
,
754 this->protocol
, this->reqid
, high_prio
, mode
, this->ipcomp
);
756 status
|= charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
757 this->other
.addr
, this->me
.addr
, other_ts
, my_ts
, POLICY_FWD
,
758 this->protocol
, this->reqid
, high_prio
, mode
, this->ipcomp
);
760 if (status
!= SUCCESS
)
765 enumerator
->destroy(enumerator
);
767 if (status
== SUCCESS
)
769 /* switch to routed state if no SAD entry set up */
770 if (this->state
== CHILD_CREATED
)
772 set_state(this, CHILD_ROUTED
);
774 /* needed to update hosts */
781 * Implementation of child_sa_t.get_traffic_selectors.
783 static linked_list_t
*get_traffic_selectors(private_child_sa_t
*this, bool local
)
789 return this->other_ts
;
793 * Implementation of child_sa_t.update_hosts.
795 static status_t
update_hosts(private_child_sa_t
*this,
796 host_t
*me
, host_t
*other
, host_t
*vip
, bool encap
)
798 child_sa_state_t old
;
800 /* anything changed at all? */
801 if (me
->equals(me
, this->me
.addr
) &&
802 other
->equals(other
, this->other
.addr
) && this->encap
== encap
)
808 set_state(this, CHILD_UPDATING
);
812 if (this->ipcomp
!= IPCOMP_NONE
)
814 /* update our (initator) IPComp SA */
815 charon
->kernel_interface
->update_sa(charon
->kernel_interface
,
816 htonl(ntohs(this->me
.cpi
)), IPPROTO_COMP
,
817 this->other
.addr
, this->me
.addr
, other
, me
, FALSE
);
818 /* update his (responder) IPComp SA */
819 charon
->kernel_interface
->update_sa(charon
->kernel_interface
,
820 htonl(ntohs(this->other
.cpi
)), IPPROTO_COMP
,
821 this->me
.addr
, this->other
.addr
, me
, other
, FALSE
);
824 /* update our (initator) SA */
825 charon
->kernel_interface
->update_sa(charon
->kernel_interface
, this->me
.spi
,
826 this->protocol
, this->other
.addr
, this->me
.addr
, other
, me
, encap
);
827 /* update his (responder) SA */
828 charon
->kernel_interface
->update_sa(charon
->kernel_interface
, this->other
.spi
,
829 this->protocol
, this->me
.addr
, this->other
.addr
, me
, other
, encap
);
831 /* update policies */
832 if (!me
->ip_equals(me
, this->me
.addr
) ||
833 !other
->ip_equals(other
, this->other
.addr
))
835 enumerator_t
*enumerator
;
836 traffic_selector_t
*my_ts
, *other_ts
;
838 /* always use high priorities, as hosts getting updated are INSTALLED */
839 enumerator
= create_policy_enumerator(this);
840 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
842 /* remove old policies first */
843 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
844 my_ts
, other_ts
, POLICY_OUT
);
845 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
846 other_ts
, my_ts
, POLICY_IN
);
847 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
848 other_ts
, my_ts
, POLICY_FWD
);
850 /* check whether we have to update a "dynamic" traffic selector */
851 if (!me
->ip_equals(me
, this->me
.addr
) &&
852 my_ts
->is_host(my_ts
, this->me
.addr
))
854 my_ts
->set_address(my_ts
, me
);
856 if (!other
->ip_equals(other
, this->other
.addr
) &&
857 other_ts
->is_host(other_ts
, this->other
.addr
))
859 other_ts
->set_address(other_ts
, other
);
862 /* we reinstall the virtual IP to handle interface roaming
866 charon
->kernel_interface
->del_ip(charon
->kernel_interface
, vip
);
867 charon
->kernel_interface
->add_ip(charon
->kernel_interface
, vip
, me
);
870 /* reinstall updated policies */
871 charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
872 me
, other
, my_ts
, other_ts
, POLICY_OUT
, this->protocol
,
873 this->reqid
, TRUE
, this->mode
, this->ipcomp
);
874 charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
875 other
, me
, other_ts
, my_ts
, POLICY_IN
, this->protocol
,
876 this->reqid
, TRUE
, this->mode
, this->ipcomp
);
877 charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
878 other
, me
, other_ts
, my_ts
, POLICY_FWD
, this->protocol
,
879 this->reqid
, TRUE
, this->mode
, this->ipcomp
);
881 enumerator
->destroy(enumerator
);
885 if (!me
->equals(me
, this->me
.addr
))
887 this->me
.addr
->destroy(this->me
.addr
);
888 this->me
.addr
= me
->clone(me
);
890 if (!other
->equals(other
, this->other
.addr
))
892 this->other
.addr
->destroy(this->other
.addr
);
893 this->other
.addr
= other
->clone(other
);
896 set_state(this, old
);
902 * Implementation of child_sa_t.activate_ipcomp.
904 static void activate_ipcomp(private_child_sa_t
*this, ipcomp_transform_t ipcomp
,
907 this->ipcomp
= ipcomp
;
908 this->other
.cpi
= other_cpi
;
912 * Implementation of child_sa_t.allocate_cpi.
914 static u_int16_t
allocate_cpi(private_child_sa_t
*this)
916 if (!this->cpi_allocated
)
918 charon
->kernel_interface
->get_cpi(charon
->kernel_interface
,
919 this->other
.addr
, this->me
.addr
, this->reqid
, &this->me
.cpi
);
920 this->cpi_allocated
= TRUE
;
926 * Implementation of child_sa_t.destroy.
928 static void destroy(private_child_sa_t
*this)
930 enumerator_t
*enumerator
;
931 traffic_selector_t
*my_ts
, *other_ts
;
933 set_state(this, CHILD_DESTROYING
);
935 /* delete SAs in the kernel, if they are set up */
938 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
939 this->me
.addr
, this->me
.spi
, this->protocol
);
941 if (this->alloc_esp_spi
&& this->alloc_esp_spi
!= this->me
.spi
)
943 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
944 this->me
.addr
, this->alloc_esp_spi
, PROTO_ESP
);
946 if (this->alloc_ah_spi
&& this->alloc_ah_spi
!= this->me
.spi
)
948 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
949 this->me
.addr
, this->alloc_ah_spi
, PROTO_AH
);
953 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
954 this->other
.addr
, this->other
.spi
, this->protocol
);
958 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
959 this->me
.addr
, htonl(ntohs(this->me
.cpi
)), IPPROTO_COMP
);
963 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
964 this->other
.addr
, htonl(ntohs(this->other
.cpi
)), IPPROTO_COMP
);
967 /* delete all policies in the kernel */
968 enumerator
= create_policy_enumerator(this);
969 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
971 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
972 my_ts
, other_ts
, POLICY_OUT
);
973 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
974 other_ts
, my_ts
, POLICY_IN
);
975 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
976 other_ts
, my_ts
, POLICY_FWD
);
978 enumerator
->destroy(enumerator
);
980 chunk_clear(&this->enc_key
[0]);
981 chunk_clear(&this->enc_key
[1]);
982 chunk_clear(&this->int_key
[0]);
983 chunk_clear(&this->int_key
[1]);
984 this->my_ts
->destroy_offset(this->my_ts
, offsetof(traffic_selector_t
, destroy
));
985 this->other_ts
->destroy_offset(this->other_ts
, offsetof(traffic_selector_t
, destroy
));
986 this->me
.addr
->destroy(this->me
.addr
);
987 this->other
.addr
->destroy(this->other
.addr
);
988 this->config
->destroy(this->config
);
993 * Described in header.
995 child_sa_t
* child_sa_create(host_t
*me
, host_t
* other
,
996 child_cfg_t
*config
, u_int32_t rekey
, bool encap
)
998 static u_int32_t reqid
= 0;
999 private_child_sa_t
*this = malloc_thing(private_child_sa_t
);
1001 /* public functions */
1002 this->public.get_name
= (char*(*)(child_sa_t
*))get_name
;
1003 this->public.get_reqid
= (u_int32_t(*)(child_sa_t
*))get_reqid
;
1004 this->public.get_spi
= (u_int32_t(*)(child_sa_t
*, bool))get_spi
;
1005 this->public.get_cpi
= (u_int16_t(*)(child_sa_t
*, bool))get_cpi
;
1006 this->public.get_protocol
= (protocol_id_t(*)(child_sa_t
*))get_protocol
;
1007 this->public.get_mode
= (ipsec_mode_t(*)(child_sa_t
*))get_mode
;
1008 this->public.get_ipcomp
= (ipcomp_transform_t(*)(child_sa_t
*))get_ipcomp
;
1009 this->public.has_encap
= (bool(*)(child_sa_t
*))has_encap
;
1010 this->public.get_encryption
= (encryption_algorithm_t(*)(child_sa_t
*, bool, chunk_t
*))get_encryption
;
1011 this->public.get_integrity
= (integrity_algorithm_t(*)(child_sa_t
*, bool, chunk_t
*))get_integrity
;
1012 this->public.get_lifetime
= (u_int32_t(*)(child_sa_t
*, bool))get_lifetime
;
1013 this->public.get_usetime
= (u_int32_t(*)(child_sa_t
*, bool))get_usetime
;
1014 this->public.alloc
= (status_t(*)(child_sa_t
*,linked_list_t
*))alloc
;
1015 this->public.add
= (status_t(*)(child_sa_t
*,proposal_t
*,ipsec_mode_t
,prf_plus_t
*))add
;
1016 this->public.update
= (status_t(*)(child_sa_t
*,proposal_t
*,ipsec_mode_t
,prf_plus_t
*))update
;
1017 this->public.update_hosts
= (status_t (*)(child_sa_t
*,host_t
*,host_t
*,host_t
*,bool))update_hosts
;
1018 this->public.add_policies
= (status_t (*)(child_sa_t
*, linked_list_t
*,linked_list_t
*,ipsec_mode_t
,protocol_id_t
))add_policies
;
1019 this->public.get_traffic_selectors
= (linked_list_t
*(*)(child_sa_t
*,bool))get_traffic_selectors
;
1020 this->public.create_policy_enumerator
= (enumerator_t
*(*)(child_sa_t
*))create_policy_enumerator
;
1021 this->public.set_state
= (void(*)(child_sa_t
*,child_sa_state_t
))set_state
;
1022 this->public.get_state
= (child_sa_state_t(*)(child_sa_t
*))get_state
;
1023 this->public.get_config
= (child_cfg_t
*(*)(child_sa_t
*))get_config
;
1024 this->public.activate_ipcomp
= (void(*)(child_sa_t
*,ipcomp_transform_t
,u_int16_t
))activate_ipcomp
;
1025 this->public.allocate_cpi
= (u_int16_t(*)(child_sa_t
*))allocate_cpi
;
1026 this->public.destroy
= (void(*)(child_sa_t
*))destroy
;
1029 this->me
.addr
= me
->clone(me
);
1030 this->other
.addr
= other
->clone(other
);
1033 this->other
.spi
= 0;
1034 this->other
.cpi
= 0;
1035 this->alloc_ah_spi
= 0;
1036 this->alloc_esp_spi
= 0;
1037 this->encap
= encap
;
1038 this->cpi_allocated
= FALSE
;
1039 this->ipcomp
= IPCOMP_NONE
;
1040 this->state
= CHILD_CREATED
;
1041 /* reuse old reqid if we are rekeying an existing CHILD_SA */
1042 this->reqid
= rekey ? rekey
: ++reqid
;
1043 this->enc_alg
= ENCR_UNDEFINED
;
1044 this->enc_key
[0] = this->enc_key
[1] = chunk_empty
;
1045 this->int_alg
= AUTH_UNDEFINED
;
1046 this->int_key
[0] = this->int_key
[1] = chunk_empty
;
1047 this->my_ts
= linked_list_create();
1048 this->other_ts
= linked_list_create();
1049 this->protocol
= PROTO_NONE
;
1050 this->mode
= MODE_TUNNEL
;
1051 this->config
= config
;
1052 config
->get_ref(config
);
1054 return &this->public;