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
30 ENUM(child_sa_state_names
, CHILD_CREATED
, CHILD_DESTROYING
,
41 typedef struct private_child_sa_t private_child_sa_t
;
44 * Private data of a child_sa_t object.
46 struct private_child_sa_t
{
48 * Public interface of child_sa_t.
63 * our actually used SPI, 0 if unused
68 * others used SPI, 0 if unused
73 * our Compression Parameter Index (CPI) used, 0 if unused
78 * others Compression Parameter Index (CPI) used, 0 if unused
83 * List for local traffic selectors
88 * List for remote traffic selectors
90 linked_list_t
*other_ts
;
93 * Allocated SPI for a ESP proposal candidates
95 u_int32_t alloc_esp_spi
;
98 * Allocated SPI for a AH proposal candidates
100 u_int32_t alloc_ah_spi
;
103 * Protocol used to protect this SA, ESP|AH
105 protocol_id_t protocol
;
108 * reqid used for this child_sa
113 * absolute time when rekeying is scheduled
118 * absolute time when the SA expires
123 * state of the CHILD_SA
125 child_sa_state_t state
;
128 * Specifies if UDP encapsulation is enabled (NAT traversal)
133 * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
135 ipcomp_transform_t ipcomp
;
138 * TRUE if we allocated (or tried to allocate) a CPI
143 * mode this SA uses, tunnel/transport
150 proposal_t
*proposal
;
153 * config used to create this child
159 * Implementation of child_sa_t.get_name
161 static char *get_name(private_child_sa_t
*this)
163 return this->config
->get_name(this->config
);
167 * Implements child_sa_t.get_reqid
169 static u_int32_t
get_reqid(private_child_sa_t
*this)
175 * Implements child_sa_t.get_spi
177 u_int32_t
get_spi(private_child_sa_t
*this, bool inbound
)
179 return inbound ?
this->my_spi
: this->other_spi
;
183 * Implements child_sa_t.get_cpi
185 u_int16_t
get_cpi(private_child_sa_t
*this, bool inbound
)
187 return inbound ?
this->my_cpi
: this->other_cpi
;
191 * Implements child_sa_t.get_protocol
193 protocol_id_t
get_protocol(private_child_sa_t
*this)
195 return this->protocol
;
199 * Implementation of child_sa_t.get_mode
201 static ipsec_mode_t
get_mode(private_child_sa_t
*this)
207 * Implementation of child_sa_t.has_encap
209 static bool has_encap(private_child_sa_t
*this)
215 * Implementation of child_sa_t.get_ipcomp
217 static ipcomp_transform_t
get_ipcomp(private_child_sa_t
*this)
223 * Implements child_sa_t.get_state
225 static child_sa_state_t
get_state(private_child_sa_t
*this)
231 * Implements child_sa_t.get_config
233 static child_cfg_t
* get_config(private_child_sa_t
*this)
238 typedef struct policy_enumerator_t policy_enumerator_t
;
241 * Private policy enumerator
243 struct policy_enumerator_t
{
244 /** implements enumerator_t */
246 /** enumerator over own TS */
248 /** enumerator over others TS */
250 /** list of others TS, to recreate enumerator */
252 /** currently enumerating TS for "me" side */
253 traffic_selector_t
*ts
;
257 * enumerator function of create_policy_enumerator()
259 static bool policy_enumerate(policy_enumerator_t
*this,
260 traffic_selector_t
**my_out
, traffic_selector_t
**other_out
)
262 traffic_selector_t
*other_ts
;
264 while (this->ts
|| this->mine
->enumerate(this->mine
, &this->ts
))
266 if (!this->other
->enumerate(this->other
, &other_ts
))
267 { /* end of others list, restart with new of mine */
268 this->other
->destroy(this->other
);
269 this->other
= this->list
->create_enumerator(this->list
);
273 if (this->ts
->get_type(this->ts
) != other_ts
->get_type(other_ts
))
274 { /* family mismatch */
277 if (this->ts
->get_protocol(this->ts
) &&
278 other_ts
->get_protocol(other_ts
) &&
279 this->ts
->get_protocol(this->ts
) != other_ts
->get_protocol(other_ts
))
280 { /* protocol mismatch */
284 *other_out
= other_ts
;
291 * destroy function of create_policy_enumerator()
293 static void policy_destroy(policy_enumerator_t
*this)
295 this->mine
->destroy(this->mine
);
296 this->other
->destroy(this->other
);
301 * Implementation of child_sa_t.create_policy_enumerator
303 static enumerator_t
* create_policy_enumerator(private_child_sa_t
*this)
305 policy_enumerator_t
*e
= malloc_thing(policy_enumerator_t
);
307 e
->public.enumerate
= (void*)policy_enumerate
;
308 e
->public.destroy
= (void*)policy_destroy
;
309 e
->mine
= this->my_ts
->create_enumerator(this->my_ts
);
310 e
->other
= this->other_ts
->create_enumerator(this->other_ts
);
311 e
->list
= this->other_ts
;
318 * Implementation of child_sa_t.get_usetime
320 static u_int32_t
get_usetime(private_child_sa_t
*this, bool inbound
)
322 enumerator_t
*enumerator
;
323 traffic_selector_t
*my_ts
, *other_ts
;
324 u_int32_t last_use
= 0;
326 enumerator
= create_policy_enumerator(this);
327 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
329 u_int32_t in
, out
, fwd
;
333 if (charon
->kernel_interface
->query_policy(charon
->kernel_interface
,
334 other_ts
, my_ts
, POLICY_IN
, &in
) == SUCCESS
)
336 last_use
= max(last_use
, in
);
338 if (this->mode
== MODE_TUNNEL
)
340 if (charon
->kernel_interface
->query_policy(charon
->kernel_interface
,
341 other_ts
, my_ts
, POLICY_FWD
, &fwd
) == SUCCESS
)
343 last_use
= max(last_use
, fwd
);
349 if (charon
->kernel_interface
->query_policy(charon
->kernel_interface
,
350 my_ts
, other_ts
, POLICY_OUT
, &out
) == SUCCESS
)
352 last_use
= max(last_use
, out
);
356 enumerator
->destroy(enumerator
);
361 * Implementation of child_sa_t.get_lifetime
363 static u_int32_t
get_lifetime(private_child_sa_t
*this, bool hard
)
365 return hard ?
this->expire_time
: this->rekey_time
;
369 * Implements child_sa_t.set_state
371 static void set_state(private_child_sa_t
*this, child_sa_state_t state
)
373 charon
->bus
->child_state_change(charon
->bus
, &this->public, state
);
378 * Allocate SPI for a single proposal
380 static status_t
alloc_proposal(private_child_sa_t
*this, proposal_t
*proposal
)
382 protocol_id_t protocol
= proposal
->get_protocol(proposal
);
384 if (protocol
== PROTO_AH
)
386 /* get a new spi for AH, if not already done */
387 if (this->alloc_ah_spi
== 0)
389 if (charon
->kernel_interface
->get_spi(
390 charon
->kernel_interface
,
391 this->other_addr
, this->my_addr
,
392 PROTO_AH
, this->reqid
,
393 &this->alloc_ah_spi
) != SUCCESS
)
398 proposal
->set_spi(proposal
, this->alloc_ah_spi
);
400 if (protocol
== PROTO_ESP
)
402 /* get a new spi for ESP, if not already done */
403 if (this->alloc_esp_spi
== 0)
405 if (charon
->kernel_interface
->get_spi(
406 charon
->kernel_interface
,
407 this->other_addr
, this->my_addr
,
408 PROTO_ESP
, this->reqid
,
409 &this->alloc_esp_spi
) != SUCCESS
)
414 proposal
->set_spi(proposal
, this->alloc_esp_spi
);
420 * Implements child_sa_t.alloc
422 static status_t
alloc(private_child_sa_t
*this, linked_list_t
*proposals
)
424 iterator_t
*iterator
;
425 proposal_t
*proposal
;
427 /* iterator through proposals to update spis */
428 iterator
= proposals
->create_iterator(proposals
, TRUE
);
429 while(iterator
->iterate(iterator
, (void**)&proposal
))
431 if (alloc_proposal(this, proposal
) != SUCCESS
)
433 iterator
->destroy(iterator
);
437 iterator
->destroy(iterator
);
442 * Install an SA for one direction
444 static status_t
install(private_child_sa_t
*this, proposal_t
*proposal
,
445 ipsec_mode_t mode
, chunk_t integ
, chunk_t encr
, bool in
)
447 u_int16_t enc_alg
= ENCR_UNDEFINED
, int_alg
= AUTH_UNDEFINED
, size
;
448 u_int32_t spi
, soft
, hard
, now
;
452 /* now we have to decide which spi to use. Use self allocated, if "in",
453 * or the one in the proposal, if not "in" (others). Additionally,
454 * source and dest host switch depending on the role */
457 /* if we have allocated SPIs for AH and ESP, we must delete the unused
459 if (this->protocol
== PROTO_ESP
)
461 this->my_spi
= this->alloc_esp_spi
;
462 if (this->alloc_ah_spi
)
464 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
465 this->my_addr
, this->alloc_ah_spi
, 0, PROTO_AH
);
470 this->my_spi
= this->alloc_ah_spi
;
471 if (this->alloc_esp_spi
)
473 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
474 this->my_addr
, this->alloc_esp_spi
, 0, PROTO_ESP
);
479 src
= this->other_addr
;
483 this->other_spi
= proposal
->get_spi(proposal
);
484 spi
= this->other_spi
;
486 dst
= this->other_addr
;
489 DBG2(DBG_CHD
, "adding %s %N SA", in ?
"inbound" : "outbound",
490 protocol_id_names
, this->protocol
);
492 /* send SA down to the kernel */
493 DBG2(DBG_CHD
, " SPI 0x%.8x, src %H dst %H", ntohl(spi
), src
, dst
);
495 proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
, &enc_alg
, &size
);
496 proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
, &int_alg
, &size
);
498 soft
= this->config
->get_lifetime(this->config
, TRUE
);
499 hard
= this->config
->get_lifetime(this->config
, FALSE
);
500 status
= charon
->kernel_interface
->add_sa(charon
->kernel_interface
,
501 src
, dst
, spi
, this->protocol
, this->reqid
,
502 in ? soft
: 0, hard
, enc_alg
, encr
, int_alg
, integ
,
503 mode
, this->ipcomp
, in ?
this->my_cpi
: this->other_cpi
,
507 this->rekey_time
= now
+ soft
;
508 this->expire_time
= now
+ hard
;
513 * Implementation of child_sa_t.add
515 static status_t
add(private_child_sa_t
*this,
516 proposal_t
*proposal
, ipsec_mode_t mode
,
517 chunk_t integ_in
, chunk_t integ_out
,
518 chunk_t encr_in
, chunk_t encr_out
)
520 this->proposal
= proposal
->clone(proposal
);
521 this->protocol
= proposal
->get_protocol(proposal
);
523 /* get SPIs for inbound SAs, write to proposal */
524 if (alloc_proposal(this, proposal
) != SUCCESS
)
528 /* install inbound SAs using allocated SPI */
529 if (install(this, proposal
, mode
, integ_in
, encr_in
, TRUE
) != SUCCESS
)
533 /* install outbound SAs using received SPI*/
534 if (install(this, this->proposal
, mode
, integ_out
, encr_out
, FALSE
) != SUCCESS
)
542 * Implementation of child_sa_t.update
544 static status_t
update(private_child_sa_t
*this,
545 proposal_t
*proposal
, ipsec_mode_t mode
,
546 chunk_t integ_in
, chunk_t integ_out
,
547 chunk_t encr_in
, chunk_t encr_out
)
549 this->proposal
= proposal
->clone(proposal
);
550 this->protocol
= proposal
->get_protocol(proposal
);
552 /* install outbound SAs */
553 if (install(this, proposal
, mode
, integ_out
, encr_out
, FALSE
) != SUCCESS
)
557 /* install inbound SAs */
558 if (install(this, proposal
, mode
, integ_in
, encr_in
, TRUE
) != SUCCESS
)
566 * Implementation of child_sa_t.get_proposal
568 static proposal_t
* get_proposal(private_child_sa_t
*this)
570 return this->proposal
;
574 * Implementation of child_sa_t.add_policies
576 static status_t
add_policies(private_child_sa_t
*this,
577 linked_list_t
*my_ts_list
, linked_list_t
*other_ts_list
,
578 ipsec_mode_t mode
, protocol_id_t proto
)
580 enumerator_t
*enumerator
;
581 traffic_selector_t
*my_ts
, *other_ts
;
582 status_t status
= SUCCESS
;
583 bool routed
= (this->state
== CHILD_CREATED
);
585 if (this->protocol
== PROTO_NONE
)
586 { /* update if not set yet */
587 this->protocol
= proto
;
590 /* apply traffic selectors */
591 enumerator
= my_ts_list
->create_enumerator(my_ts_list
);
592 while (enumerator
->enumerate(enumerator
, &my_ts
))
594 this->my_ts
->insert_last(this->my_ts
, my_ts
->clone(my_ts
));
596 enumerator
->destroy(enumerator
);
597 enumerator
= other_ts_list
->create_enumerator(other_ts_list
);
598 while (enumerator
->enumerate(enumerator
, &other_ts
))
600 this->other_ts
->insert_last(this->other_ts
, other_ts
->clone(other_ts
));
602 enumerator
->destroy(enumerator
);
604 if (this->config
->install_policy(this->config
))
606 /* enumerate pairs of traffic selectors */
607 enumerator
= create_policy_enumerator(this);
608 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
610 /* install 3 policies: out, in and forward */
611 status
|= charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
612 this->my_addr
, this->other_addr
, my_ts
, other_ts
, POLICY_OUT
,
613 this->other_spi
, this->protocol
, this->reqid
, mode
, this->ipcomp
,
614 this->other_cpi
, routed
);
616 status
|= charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
617 this->other_addr
, this->my_addr
, other_ts
, my_ts
, POLICY_IN
,
618 this->my_spi
, this->protocol
, this->reqid
, mode
, this->ipcomp
,
619 this->my_cpi
, routed
);
621 if (mode
== MODE_TUNNEL
)
623 status
|= charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
624 this->other_addr
, this->my_addr
, other_ts
, my_ts
, POLICY_FWD
,
625 this->my_spi
, this->protocol
, this->reqid
, mode
, this->ipcomp
,
626 this->my_cpi
, routed
);
629 if (status
!= SUCCESS
)
634 enumerator
->destroy(enumerator
);
637 if (status
== SUCCESS
)
639 /* switch to routed state if no SAD entry set up */
640 if (this->state
== CHILD_CREATED
)
642 set_state(this, CHILD_ROUTED
);
644 /* needed to update hosts */
651 * Implementation of child_sa_t.get_traffic_selectors.
653 static linked_list_t
*get_traffic_selectors(private_child_sa_t
*this, bool local
)
655 return local ?
this->my_ts
: this->other_ts
;
659 * Implementation of child_sa_t.update_hosts.
661 static status_t
update_hosts(private_child_sa_t
*this,
662 host_t
*me
, host_t
*other
, host_t
*vip
, bool encap
)
664 child_sa_state_t old
;
666 /* anything changed at all? */
667 if (me
->equals(me
, this->my_addr
) &&
668 other
->equals(other
, this->other_addr
) && this->encap
== encap
)
674 set_state(this, CHILD_UPDATING
);
676 /* update our (initator) SA */
677 if (charon
->kernel_interface
->update_sa(charon
->kernel_interface
, this->my_spi
,
678 this->protocol
, this->ipcomp
!= IPCOMP_NONE ?
this->my_cpi
: 0,
679 this->other_addr
, this->my_addr
, other
, me
,
680 this->encap
, encap
) == NOT_SUPPORTED
)
682 return NOT_SUPPORTED
;
685 /* update his (responder) SA */
686 if (charon
->kernel_interface
->update_sa(charon
->kernel_interface
, this->other_spi
,
687 this->protocol
, this->ipcomp
!= IPCOMP_NONE ?
this->other_cpi
: 0,
688 this->my_addr
, this->other_addr
, me
, other
,
689 this->encap
, encap
) == NOT_SUPPORTED
)
691 return NOT_SUPPORTED
;
694 if (this->config
->install_policy(this->config
))
696 /* update policies */
697 if (!me
->ip_equals(me
, this->my_addr
) ||
698 !other
->ip_equals(other
, this->other_addr
))
700 enumerator_t
*enumerator
;
701 traffic_selector_t
*my_ts
, *other_ts
;
703 /* always use high priorities, as hosts getting updated are INSTALLED */
704 enumerator
= create_policy_enumerator(this);
705 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
707 /* remove old policies first */
708 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
709 my_ts
, other_ts
, POLICY_OUT
, FALSE
);
710 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
711 other_ts
, my_ts
, POLICY_IN
, FALSE
);
712 if (this->mode
== MODE_TUNNEL
)
714 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
715 other_ts
, my_ts
, POLICY_FWD
, FALSE
);
718 /* check whether we have to update a "dynamic" traffic selector */
719 if (!me
->ip_equals(me
, this->my_addr
) &&
720 my_ts
->is_host(my_ts
, this->my_addr
))
722 my_ts
->set_address(my_ts
, me
);
724 if (!other
->ip_equals(other
, this->other_addr
) &&
725 other_ts
->is_host(other_ts
, this->other_addr
))
727 other_ts
->set_address(other_ts
, other
);
730 /* we reinstall the virtual IP to handle interface roaming
734 charon
->kernel_interface
->del_ip(charon
->kernel_interface
, vip
);
735 charon
->kernel_interface
->add_ip(charon
->kernel_interface
, vip
, me
);
738 /* reinstall updated policies */
739 charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
740 me
, other
, my_ts
, other_ts
, POLICY_OUT
, this->other_spi
,
741 this->protocol
, this->reqid
, this->mode
, this->ipcomp
,
742 this->other_cpi
, FALSE
);
743 charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
744 other
, me
, other_ts
, my_ts
, POLICY_IN
, this->my_spi
,
745 this->protocol
, this->reqid
, this->mode
, this->ipcomp
,
746 this->my_cpi
, FALSE
);
747 if (this->mode
== MODE_TUNNEL
)
749 charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
750 other
, me
, other_ts
, my_ts
, POLICY_FWD
, this->my_spi
,
751 this->protocol
, this->reqid
, this->mode
, this->ipcomp
,
752 this->my_cpi
, FALSE
);
755 enumerator
->destroy(enumerator
);
760 if (!this->config
->use_proxy_mode(this->config
) || this->mode
!= MODE_TRANSPORT
)
762 if (!me
->equals(me
, this->my_addr
))
764 this->my_addr
->destroy(this->my_addr
);
765 this->my_addr
= me
->clone(me
);
767 if (!other
->equals(other
, this->other_addr
))
769 this->other_addr
->destroy(this->other_addr
);
770 this->other_addr
= other
->clone(other
);
775 set_state(this, old
);
781 * Implementation of child_sa_t.activate_ipcomp.
783 static void activate_ipcomp(private_child_sa_t
*this, ipcomp_transform_t ipcomp
,
786 this->ipcomp
= ipcomp
;
787 this->other_cpi
= other_cpi
;
791 * Implementation of child_sa_t.allocate_cpi.
793 static u_int16_t
allocate_cpi(private_child_sa_t
*this)
795 if (!this->cpi_allocated
)
797 charon
->kernel_interface
->get_cpi(charon
->kernel_interface
,
798 this->other_addr
, this->my_addr
, this->reqid
, &this->my_cpi
);
799 this->cpi_allocated
= TRUE
;
805 * Implementation of child_sa_t.destroy.
807 static void destroy(private_child_sa_t
*this)
809 enumerator_t
*enumerator
;
810 traffic_selector_t
*my_ts
, *other_ts
;
811 bool unrouted
= (this->state
== CHILD_ROUTED
);
813 set_state(this, CHILD_DESTROYING
);
815 /* delete SAs in the kernel, if they are set up */
818 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
819 this->my_addr
, this->my_spi
, this->protocol
,
822 if (this->alloc_esp_spi
&& this->alloc_esp_spi
!= this->my_spi
)
824 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
825 this->my_addr
, this->alloc_esp_spi
, PROTO_ESP
, 0);
827 if (this->alloc_ah_spi
&& this->alloc_ah_spi
!= this->my_spi
)
829 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
830 this->my_addr
, this->alloc_ah_spi
, PROTO_AH
, 0);
834 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
835 this->other_addr
, this->other_spi
, this->protocol
,
839 if (this->config
->install_policy(this->config
))
841 /* delete all policies in the kernel */
842 enumerator
= create_policy_enumerator(this);
843 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
845 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
846 my_ts
, other_ts
, POLICY_OUT
, unrouted
);
847 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
848 other_ts
, my_ts
, POLICY_IN
, unrouted
);
849 if (this->mode
== MODE_TUNNEL
)
851 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
852 other_ts
, my_ts
, POLICY_FWD
, unrouted
);
855 enumerator
->destroy(enumerator
);
858 this->my_ts
->destroy_offset(this->my_ts
, offsetof(traffic_selector_t
, destroy
));
859 this->other_ts
->destroy_offset(this->other_ts
, offsetof(traffic_selector_t
, destroy
));
860 this->my_addr
->destroy(this->my_addr
);
861 this->other_addr
->destroy(this->other_addr
);
862 DESTROY_IF(this->proposal
);
863 this->config
->destroy(this->config
);
868 * Described in header.
870 child_sa_t
* child_sa_create(host_t
*me
, host_t
* other
,
871 child_cfg_t
*config
, u_int32_t rekey
, bool encap
)
873 static u_int32_t reqid
= 0;
874 private_child_sa_t
*this = malloc_thing(private_child_sa_t
);
876 /* public functions */
877 this->public.get_name
= (char*(*)(child_sa_t
*))get_name
;
878 this->public.get_reqid
= (u_int32_t(*)(child_sa_t
*))get_reqid
;
879 this->public.get_spi
= (u_int32_t(*)(child_sa_t
*, bool))get_spi
;
880 this->public.get_cpi
= (u_int16_t(*)(child_sa_t
*, bool))get_cpi
;
881 this->public.get_protocol
= (protocol_id_t(*)(child_sa_t
*))get_protocol
;
882 this->public.get_mode
= (ipsec_mode_t(*)(child_sa_t
*))get_mode
;
883 this->public.get_ipcomp
= (ipcomp_transform_t(*)(child_sa_t
*))get_ipcomp
;
884 this->public.has_encap
= (bool(*)(child_sa_t
*))has_encap
;
885 this->public.get_lifetime
= (u_int32_t(*)(child_sa_t
*, bool))get_lifetime
;
886 this->public.get_usetime
= (u_int32_t(*)(child_sa_t
*, bool))get_usetime
;
887 this->public.alloc
= (status_t(*)(child_sa_t
*,linked_list_t
*))alloc
;
888 this->public.add
= (status_t(*)(child_sa_t
*,proposal_t
*,ipsec_mode_t
,chunk_t
,chunk_t
,chunk_t
,chunk_t
))add
;
889 this->public.update
= (status_t(*)(child_sa_t
*,proposal_t
*,ipsec_mode_t
,chunk_t
,chunk_t
,chunk_t
,chunk_t
))update
;
890 this->public.get_proposal
= (proposal_t
*(*)(child_sa_t
*))get_proposal
;
891 this->public.update_hosts
= (status_t (*)(child_sa_t
*,host_t
*,host_t
*,host_t
*,bool))update_hosts
;
892 this->public.add_policies
= (status_t (*)(child_sa_t
*, linked_list_t
*,linked_list_t
*,ipsec_mode_t
,protocol_id_t
))add_policies
;
893 this->public.get_traffic_selectors
= (linked_list_t
*(*)(child_sa_t
*,bool))get_traffic_selectors
;
894 this->public.create_policy_enumerator
= (enumerator_t
*(*)(child_sa_t
*))create_policy_enumerator
;
895 this->public.set_state
= (void(*)(child_sa_t
*,child_sa_state_t
))set_state
;
896 this->public.get_state
= (child_sa_state_t(*)(child_sa_t
*))get_state
;
897 this->public.get_config
= (child_cfg_t
*(*)(child_sa_t
*))get_config
;
898 this->public.activate_ipcomp
= (void(*)(child_sa_t
*,ipcomp_transform_t
,u_int16_t
))activate_ipcomp
;
899 this->public.allocate_cpi
= (u_int16_t(*)(child_sa_t
*))allocate_cpi
;
900 this->public.destroy
= (void(*)(child_sa_t
*))destroy
;
903 this->my_addr
= me
->clone(me
);
904 this->other_addr
= other
->clone(other
);
909 this->alloc_ah_spi
= 0;
910 this->alloc_esp_spi
= 0;
912 this->cpi_allocated
= FALSE
;
913 this->ipcomp
= IPCOMP_NONE
;
914 this->state
= CHILD_CREATED
;
915 /* reuse old reqid if we are rekeying an existing CHILD_SA */
916 this->reqid
= rekey ? rekey
: ++reqid
;
917 this->my_ts
= linked_list_create();
918 this->other_ts
= linked_list_create();
919 this->protocol
= PROTO_NONE
;
920 this->mode
= MODE_TUNNEL
;
921 this->proposal
= NULL
;
922 this->config
= config
;
923 config
->get_ref(config
);
925 /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
926 if (config
->get_mode(config
) == MODE_TRANSPORT
&&
927 config
->use_proxy_mode(config
))
933 enumerator_t
*enumerator
;
934 linked_list_t
*my_ts_list
, *other_ts_list
;
935 traffic_selector_t
*my_ts
, *other_ts
;
937 this->mode
= MODE_TRANSPORT
;
939 my_ts_list
= config
->get_traffic_selectors(config
, TRUE
, NULL
, me
);
940 enumerator
= my_ts_list
->create_enumerator(my_ts_list
);
941 if (enumerator
->enumerate(enumerator
, &my_ts
))
943 if (my_ts
->is_host(my_ts
, NULL
) &&
944 !my_ts
->is_host(my_ts
, this->my_addr
))
946 type
= my_ts
->get_type(my_ts
);
947 family
= (type
== TS_IPV4_ADDR_RANGE
) ? AF_INET
: AF_INET6
;
948 addr
= my_ts
->get_from_address(my_ts
);
949 host
= host_create_from_chunk(family
, addr
, 0);
951 DBG1(DBG_CHD
, "my address: %H is a transport mode proxy for %H",
952 this->my_addr
, host
);
953 this->my_addr
->destroy(this->my_addr
);
954 this->my_addr
= host
;
957 enumerator
->destroy(enumerator
);
958 my_ts_list
->destroy_offset(my_ts_list
, offsetof(traffic_selector_t
, destroy
));
960 other_ts_list
= config
->get_traffic_selectors(config
, FALSE
, NULL
, other
);
961 enumerator
= other_ts_list
->create_enumerator(other_ts_list
);
962 if (enumerator
->enumerate(enumerator
, &other_ts
))
964 if (other_ts
->is_host(other_ts
, NULL
) &&
965 !other_ts
->is_host(other_ts
, this->other_addr
))
967 type
= other_ts
->get_type(other_ts
);
968 family
= (type
== TS_IPV4_ADDR_RANGE
) ? AF_INET
: AF_INET6
;
969 addr
= other_ts
->get_from_address(other_ts
);
970 host
= host_create_from_chunk(family
, addr
, 0);
972 DBG1(DBG_CHD
, "other address: %H is a transport mode proxy for %H",
973 this->other_addr
, host
);
974 this->other_addr
->destroy(this->other_addr
);
975 this->other_addr
= host
;
978 enumerator
->destroy(enumerator
);
979 other_ts_list
->destroy_offset(other_ts_list
, offsetof(traffic_selector_t
, destroy
));
982 return &this->public;