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_TRANSPORT
)
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
);
501 status
= charon
->kernel_interface
->add_sa(charon
->kernel_interface
,
502 src
, dst
, spi
, this->protocol
, this->reqid
,
503 in ? soft
: 0, hard
, enc_alg
, encr
, int_alg
, integ
,
504 mode
, this->ipcomp
, in ?
this->my_cpi
: this->other_cpi
,
508 this->rekey_time
= now
+ soft
;
509 this->expire_time
= now
+ hard
;
514 * Implementation of child_sa_t.add
516 static status_t
add(private_child_sa_t
*this,
517 proposal_t
*proposal
, ipsec_mode_t mode
,
518 chunk_t integ_in
, chunk_t integ_out
,
519 chunk_t encr_in
, chunk_t encr_out
)
521 this->proposal
= proposal
->clone(proposal
);
522 this->protocol
= proposal
->get_protocol(proposal
);
524 /* get SPIs for inbound SAs, write to proposal */
525 if (alloc_proposal(this, proposal
) != SUCCESS
)
529 /* install inbound SAs using allocated SPI */
530 if (install(this, proposal
, mode
, integ_in
, encr_in
, TRUE
) != SUCCESS
)
534 /* install outbound SAs using received SPI*/
535 if (install(this, this->proposal
, mode
, integ_out
, encr_out
, FALSE
) != SUCCESS
)
543 * Implementation of child_sa_t.update
545 static status_t
update(private_child_sa_t
*this,
546 proposal_t
*proposal
, ipsec_mode_t mode
,
547 chunk_t integ_in
, chunk_t integ_out
,
548 chunk_t encr_in
, chunk_t encr_out
)
550 this->proposal
= proposal
->clone(proposal
);
551 this->protocol
= proposal
->get_protocol(proposal
);
553 /* install outbound SAs */
554 if (install(this, proposal
, mode
, integ_out
, encr_out
, FALSE
) != SUCCESS
)
558 /* install inbound SAs */
559 if (install(this, proposal
, mode
, integ_in
, encr_in
, TRUE
) != SUCCESS
)
567 * Implementation of child_sa_t.get_proposal
569 static proposal_t
* get_proposal(private_child_sa_t
*this)
571 return this->proposal
;
575 * Implementation of child_sa_t.add_policies
577 static status_t
add_policies(private_child_sa_t
*this,
578 linked_list_t
*my_ts_list
, linked_list_t
*other_ts_list
,
579 ipsec_mode_t mode
, protocol_id_t proto
)
581 enumerator_t
*enumerator
;
582 traffic_selector_t
*my_ts
, *other_ts
;
583 status_t status
= SUCCESS
;
584 bool routed
= (this->state
== CHILD_CREATED
);
586 if (this->protocol
== PROTO_NONE
)
587 { /* update if not set yet */
588 this->protocol
= proto
;
591 /* apply traffic selectors */
592 enumerator
= my_ts_list
->create_enumerator(my_ts_list
);
593 while (enumerator
->enumerate(enumerator
, &my_ts
))
595 this->my_ts
->insert_last(this->my_ts
, my_ts
->clone(my_ts
));
597 enumerator
->destroy(enumerator
);
598 enumerator
= other_ts_list
->create_enumerator(other_ts_list
);
599 while (enumerator
->enumerate(enumerator
, &other_ts
))
601 this->other_ts
->insert_last(this->other_ts
, other_ts
->clone(other_ts
));
603 enumerator
->destroy(enumerator
);
605 if (this->config
->install_policy(this->config
))
607 /* enumerate pairs of traffic selectors */
608 enumerator
= create_policy_enumerator(this);
609 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
611 /* install 3 policies: out, in and forward */
612 status
|= charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
613 this->my_addr
, this->other_addr
, my_ts
, other_ts
, POLICY_OUT
,
614 this->other_spi
, this->protocol
, this->reqid
, mode
, this->ipcomp
,
615 this->other_cpi
, routed
);
617 status
|= charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
618 this->other_addr
, this->my_addr
, other_ts
, my_ts
, POLICY_IN
,
619 this->my_spi
, this->protocol
, this->reqid
, mode
, this->ipcomp
,
620 this->my_cpi
, routed
);
621 if (mode
!= MODE_TRANSPORT
)
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 if (!this->config
->use_proxy_mode(this->config
) || this->mode
!= MODE_TRANSPORT
)
678 /* update our (initator) SA */
681 if (charon
->kernel_interface
->update_sa(charon
->kernel_interface
,
682 this->my_spi
, this->protocol
,
683 this->ipcomp
!= IPCOMP_NONE ?
this->my_cpi
: 0,
684 this->other_addr
, this->my_addr
, other
, me
,
685 this->encap
, encap
) == NOT_SUPPORTED
)
687 return NOT_SUPPORTED
;
691 /* update his (responder) SA */
694 if (charon
->kernel_interface
->update_sa(charon
->kernel_interface
,
695 this->other_spi
, this->protocol
,
696 this->ipcomp
!= IPCOMP_NONE ?
this->other_cpi
: 0,
697 this->my_addr
, this->other_addr
, me
, other
,
698 this->encap
, encap
) == NOT_SUPPORTED
)
700 return NOT_SUPPORTED
;
705 if (!me
->equals(me
, this->my_addr
))
707 this->my_addr
->destroy(this->my_addr
);
708 this->my_addr
= me
->clone(me
);
710 if (!other
->equals(other
, this->other_addr
))
712 this->other_addr
->destroy(this->other_addr
);
713 this->other_addr
= other
->clone(other
);
717 if (this->config
->install_policy(this->config
))
719 /* update policies */
720 if (!me
->ip_equals(me
, this->my_addr
) ||
721 !other
->ip_equals(other
, this->other_addr
))
723 enumerator_t
*enumerator
;
724 traffic_selector_t
*my_ts
, *other_ts
;
726 /* always use high priorities, as hosts getting updated are INSTALLED */
727 enumerator
= create_policy_enumerator(this);
728 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
730 /* remove old policies first */
731 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
732 my_ts
, other_ts
, POLICY_OUT
, FALSE
);
733 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
734 other_ts
, my_ts
, POLICY_IN
, FALSE
);
735 if (this->mode
!= MODE_TRANSPORT
)
737 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
738 other_ts
, my_ts
, POLICY_FWD
, FALSE
);
741 /* check whether we have to update a "dynamic" traffic selector */
742 if (!me
->ip_equals(me
, this->my_addr
) &&
743 my_ts
->is_host(my_ts
, this->my_addr
))
745 my_ts
->set_address(my_ts
, me
);
747 if (!other
->ip_equals(other
, this->other_addr
) &&
748 other_ts
->is_host(other_ts
, this->other_addr
))
750 other_ts
->set_address(other_ts
, other
);
753 /* we reinstall the virtual IP to handle interface roaming
757 charon
->kernel_interface
->del_ip(charon
->kernel_interface
, vip
);
758 charon
->kernel_interface
->add_ip(charon
->kernel_interface
, vip
, me
);
761 /* reinstall updated policies */
762 charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
763 me
, other
, my_ts
, other_ts
, POLICY_OUT
, this->other_spi
,
764 this->protocol
, this->reqid
, this->mode
, this->ipcomp
,
765 this->other_cpi
, FALSE
);
766 charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
767 other
, me
, other_ts
, my_ts
, POLICY_IN
, this->my_spi
,
768 this->protocol
, this->reqid
, this->mode
, this->ipcomp
,
769 this->my_cpi
, FALSE
);
770 if (this->mode
!= MODE_TRANSPORT
)
772 charon
->kernel_interface
->add_policy(charon
->kernel_interface
,
773 other
, me
, other_ts
, my_ts
, POLICY_FWD
, this->my_spi
,
774 this->protocol
, this->reqid
, this->mode
, this->ipcomp
,
775 this->my_cpi
, FALSE
);
778 enumerator
->destroy(enumerator
);
783 set_state(this, old
);
789 * Implementation of child_sa_t.activate_ipcomp.
791 static void activate_ipcomp(private_child_sa_t
*this, ipcomp_transform_t ipcomp
,
794 this->ipcomp
= ipcomp
;
795 this->other_cpi
= other_cpi
;
799 * Implementation of child_sa_t.allocate_cpi.
801 static u_int16_t
allocate_cpi(private_child_sa_t
*this)
803 if (!this->cpi_allocated
)
805 charon
->kernel_interface
->get_cpi(charon
->kernel_interface
,
806 this->other_addr
, this->my_addr
, this->reqid
, &this->my_cpi
);
807 this->cpi_allocated
= TRUE
;
813 * Implementation of child_sa_t.destroy.
815 static void destroy(private_child_sa_t
*this)
817 enumerator_t
*enumerator
;
818 traffic_selector_t
*my_ts
, *other_ts
;
819 bool unrouted
= (this->state
== CHILD_ROUTED
);
821 set_state(this, CHILD_DESTROYING
);
823 /* delete SAs in the kernel, if they are set up */
826 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
827 this->my_addr
, this->my_spi
, this->protocol
,
830 if (this->alloc_esp_spi
&& this->alloc_esp_spi
!= this->my_spi
)
832 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
833 this->my_addr
, this->alloc_esp_spi
, PROTO_ESP
, 0);
835 if (this->alloc_ah_spi
&& this->alloc_ah_spi
!= this->my_spi
)
837 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
838 this->my_addr
, this->alloc_ah_spi
, PROTO_AH
, 0);
842 charon
->kernel_interface
->del_sa(charon
->kernel_interface
,
843 this->other_addr
, this->other_spi
, this->protocol
,
847 if (this->config
->install_policy(this->config
))
849 /* delete all policies in the kernel */
850 enumerator
= create_policy_enumerator(this);
851 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
853 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
854 my_ts
, other_ts
, POLICY_OUT
, unrouted
);
855 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
856 other_ts
, my_ts
, POLICY_IN
, unrouted
);
857 if (this->mode
!= MODE_TRANSPORT
)
859 charon
->kernel_interface
->del_policy(charon
->kernel_interface
,
860 other_ts
, my_ts
, POLICY_FWD
, unrouted
);
863 enumerator
->destroy(enumerator
);
866 this->my_ts
->destroy_offset(this->my_ts
, offsetof(traffic_selector_t
, destroy
));
867 this->other_ts
->destroy_offset(this->other_ts
, offsetof(traffic_selector_t
, destroy
));
868 this->my_addr
->destroy(this->my_addr
);
869 this->other_addr
->destroy(this->other_addr
);
870 DESTROY_IF(this->proposal
);
871 this->config
->destroy(this->config
);
876 * Described in header.
878 child_sa_t
* child_sa_create(host_t
*me
, host_t
* other
,
879 child_cfg_t
*config
, u_int32_t rekey
, bool encap
)
881 static u_int32_t reqid
= 0;
882 private_child_sa_t
*this = malloc_thing(private_child_sa_t
);
884 /* public functions */
885 this->public.get_name
= (char*(*)(child_sa_t
*))get_name
;
886 this->public.get_reqid
= (u_int32_t(*)(child_sa_t
*))get_reqid
;
887 this->public.get_spi
= (u_int32_t(*)(child_sa_t
*, bool))get_spi
;
888 this->public.get_cpi
= (u_int16_t(*)(child_sa_t
*, bool))get_cpi
;
889 this->public.get_protocol
= (protocol_id_t(*)(child_sa_t
*))get_protocol
;
890 this->public.get_mode
= (ipsec_mode_t(*)(child_sa_t
*))get_mode
;
891 this->public.get_ipcomp
= (ipcomp_transform_t(*)(child_sa_t
*))get_ipcomp
;
892 this->public.has_encap
= (bool(*)(child_sa_t
*))has_encap
;
893 this->public.get_lifetime
= (u_int32_t(*)(child_sa_t
*, bool))get_lifetime
;
894 this->public.get_usetime
= (u_int32_t(*)(child_sa_t
*, bool))get_usetime
;
895 this->public.alloc
= (status_t(*)(child_sa_t
*,linked_list_t
*))alloc
;
896 this->public.add
= (status_t(*)(child_sa_t
*,proposal_t
*,ipsec_mode_t
,chunk_t
,chunk_t
,chunk_t
,chunk_t
))add
;
897 this->public.update
= (status_t(*)(child_sa_t
*,proposal_t
*,ipsec_mode_t
,chunk_t
,chunk_t
,chunk_t
,chunk_t
))update
;
898 this->public.get_proposal
= (proposal_t
*(*)(child_sa_t
*))get_proposal
;
899 this->public.update_hosts
= (status_t (*)(child_sa_t
*,host_t
*,host_t
*,host_t
*,bool))update_hosts
;
900 this->public.add_policies
= (status_t (*)(child_sa_t
*, linked_list_t
*,linked_list_t
*,ipsec_mode_t
,protocol_id_t
))add_policies
;
901 this->public.get_traffic_selectors
= (linked_list_t
*(*)(child_sa_t
*,bool))get_traffic_selectors
;
902 this->public.create_policy_enumerator
= (enumerator_t
*(*)(child_sa_t
*))create_policy_enumerator
;
903 this->public.set_state
= (void(*)(child_sa_t
*,child_sa_state_t
))set_state
;
904 this->public.get_state
= (child_sa_state_t(*)(child_sa_t
*))get_state
;
905 this->public.get_config
= (child_cfg_t
*(*)(child_sa_t
*))get_config
;
906 this->public.activate_ipcomp
= (void(*)(child_sa_t
*,ipcomp_transform_t
,u_int16_t
))activate_ipcomp
;
907 this->public.allocate_cpi
= (u_int16_t(*)(child_sa_t
*))allocate_cpi
;
908 this->public.destroy
= (void(*)(child_sa_t
*))destroy
;
911 this->my_addr
= me
->clone(me
);
912 this->other_addr
= other
->clone(other
);
917 this->alloc_ah_spi
= 0;
918 this->alloc_esp_spi
= 0;
920 this->cpi_allocated
= FALSE
;
921 this->ipcomp
= IPCOMP_NONE
;
922 this->state
= CHILD_CREATED
;
923 /* reuse old reqid if we are rekeying an existing CHILD_SA */
924 this->reqid
= rekey ? rekey
: ++reqid
;
925 this->my_ts
= linked_list_create();
926 this->other_ts
= linked_list_create();
927 this->protocol
= PROTO_NONE
;
928 this->mode
= MODE_TUNNEL
;
929 this->proposal
= NULL
;
930 this->config
= config
;
931 config
->get_ref(config
);
933 /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
934 if (config
->get_mode(config
) == MODE_TRANSPORT
&&
935 config
->use_proxy_mode(config
))
941 enumerator_t
*enumerator
;
942 linked_list_t
*my_ts_list
, *other_ts_list
;
943 traffic_selector_t
*my_ts
, *other_ts
;
945 this->mode
= MODE_TRANSPORT
;
947 my_ts_list
= config
->get_traffic_selectors(config
, TRUE
, NULL
, me
);
948 enumerator
= my_ts_list
->create_enumerator(my_ts_list
);
949 if (enumerator
->enumerate(enumerator
, &my_ts
))
951 if (my_ts
->is_host(my_ts
, NULL
) &&
952 !my_ts
->is_host(my_ts
, this->my_addr
))
954 type
= my_ts
->get_type(my_ts
);
955 family
= (type
== TS_IPV4_ADDR_RANGE
) ? AF_INET
: AF_INET6
;
956 addr
= my_ts
->get_from_address(my_ts
);
957 host
= host_create_from_chunk(family
, addr
, 0);
959 DBG1(DBG_CHD
, "my address: %H is a transport mode proxy for %H",
960 this->my_addr
, host
);
961 this->my_addr
->destroy(this->my_addr
);
962 this->my_addr
= host
;
965 enumerator
->destroy(enumerator
);
966 my_ts_list
->destroy_offset(my_ts_list
, offsetof(traffic_selector_t
, destroy
));
968 other_ts_list
= config
->get_traffic_selectors(config
, FALSE
, NULL
, other
);
969 enumerator
= other_ts_list
->create_enumerator(other_ts_list
);
970 if (enumerator
->enumerate(enumerator
, &other_ts
))
972 if (other_ts
->is_host(other_ts
, NULL
) &&
973 !other_ts
->is_host(other_ts
, this->other_addr
))
975 type
= other_ts
->get_type(other_ts
);
976 family
= (type
== TS_IPV4_ADDR_RANGE
) ? AF_INET
: AF_INET6
;
977 addr
= other_ts
->get_from_address(other_ts
);
978 host
= host_create_from_chunk(family
, addr
, 0);
980 DBG1(DBG_CHD
, "other address: %H is a transport mode proxy for %H",
981 this->other_addr
, host
);
982 this->other_addr
->destroy(this->other_addr
);
983 this->other_addr
= host
;
986 enumerator
->destroy(enumerator
);
987 other_ts_list
->destroy_offset(other_ts_list
, offsetof(traffic_selector_t
, destroy
));
990 return &this->public;