2 * Copyright (C) 2006-2011 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
,
40 typedef struct private_child_sa_t private_child_sa_t
;
43 * Private data of a child_sa_t object.
45 struct private_child_sa_t
{
47 * Public interface of child_sa_t.
62 * our actually used SPI, 0 if unused
67 * others used SPI, 0 if unused
72 * our Compression Parameter Index (CPI) used, 0 if unused
77 * others Compression Parameter Index (CPI) used, 0 if unused
82 * List for local traffic selectors
87 * List for remote traffic selectors
89 linked_list_t
*other_ts
;
92 * Protocol used to protect this SA, ESP|AH
94 protocol_id_t protocol
;
97 * reqid used for this child_sa
102 * inbound mark used for this child_sa
107 * outbound mark used for this child_sa
112 * absolute time when rekeying is scheduled
117 * absolute time when the SA expires
122 * state of the CHILD_SA
124 child_sa_state_t state
;
127 * Specifies if UDP encapsulation is enabled (NAT traversal)
132 * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
134 ipcomp_transform_t ipcomp
;
137 * mode this SA uses, tunnel/transport
142 * Action to enforce if peer closes the CHILD_SA
144 action_t close_action
;
147 * Action to enforce if peer is considered dead
154 proposal_t
*proposal
;
157 * config used to create this child
162 * time of last use in seconds (inbound)
164 u_int32_t my_usetime
;
167 * time of last use in seconds (outbound)
169 u_int32_t other_usetime
;
172 * last number of inbound bytes
174 u_int64_t my_usebytes
;
177 * last number of outbound bytes
179 u_int64_t other_usebytes
;
183 * convert an IKEv2 specific protocol identifier to the IP protocol identifier.
185 static inline u_int8_t
proto_ike2ip(protocol_id_t protocol
)
198 METHOD(child_sa_t
, get_name
, char*,
199 private_child_sa_t
*this)
201 return this->config
->get_name(this->config
);
204 METHOD(child_sa_t
, get_reqid
, u_int32_t
,
205 private_child_sa_t
*this)
210 METHOD(child_sa_t
, get_config
, child_cfg_t
*,
211 private_child_sa_t
*this)
216 METHOD(child_sa_t
, set_state
, void,
217 private_child_sa_t
*this, child_sa_state_t state
)
219 charon
->bus
->child_state_change(charon
->bus
, &this->public, state
);
223 METHOD(child_sa_t
, get_state
, child_sa_state_t
,
224 private_child_sa_t
*this)
229 METHOD(child_sa_t
, get_spi
, u_int32_t
,
230 private_child_sa_t
*this, bool inbound
)
232 return inbound ?
this->my_spi
: this->other_spi
;
235 METHOD(child_sa_t
, get_cpi
, u_int16_t
,
236 private_child_sa_t
*this, bool inbound
)
238 return inbound ?
this->my_cpi
: this->other_cpi
;
241 METHOD(child_sa_t
, get_protocol
, protocol_id_t
,
242 private_child_sa_t
*this)
244 return this->protocol
;
247 METHOD(child_sa_t
, set_protocol
, void,
248 private_child_sa_t
*this, protocol_id_t protocol
)
250 this->protocol
= protocol
;
253 METHOD(child_sa_t
, get_mode
, ipsec_mode_t
,
254 private_child_sa_t
*this)
259 METHOD(child_sa_t
, set_mode
, void,
260 private_child_sa_t
*this, ipsec_mode_t mode
)
265 METHOD(child_sa_t
, has_encap
, bool,
266 private_child_sa_t
*this)
271 METHOD(child_sa_t
, get_ipcomp
, ipcomp_transform_t
,
272 private_child_sa_t
*this)
277 METHOD(child_sa_t
, set_ipcomp
, void,
278 private_child_sa_t
*this, ipcomp_transform_t ipcomp
)
280 this->ipcomp
= ipcomp
;
283 METHOD(child_sa_t
, set_close_action
, void,
284 private_child_sa_t
*this, action_t action
)
286 this->close_action
= action
;
289 METHOD(child_sa_t
, get_close_action
, action_t
,
290 private_child_sa_t
*this)
292 return this->close_action
;
295 METHOD(child_sa_t
, set_dpd_action
, void,
296 private_child_sa_t
*this, action_t action
)
298 this->dpd_action
= action
;
301 METHOD(child_sa_t
, get_dpd_action
, action_t
,
302 private_child_sa_t
*this)
304 return this->dpd_action
;
307 METHOD(child_sa_t
, get_proposal
, proposal_t
*,
308 private_child_sa_t
*this)
310 return this->proposal
;
313 METHOD(child_sa_t
, set_proposal
, void,
314 private_child_sa_t
*this, proposal_t
*proposal
)
316 this->proposal
= proposal
->clone(proposal
);
319 METHOD(child_sa_t
, get_traffic_selectors
, linked_list_t
*,
320 private_child_sa_t
*this, bool local
)
322 return local ?
this->my_ts
: this->other_ts
;
325 typedef struct policy_enumerator_t policy_enumerator_t
;
328 * Private policy enumerator
330 struct policy_enumerator_t
{
331 /** implements enumerator_t */
333 /** enumerator over own TS */
335 /** enumerator over others TS */
337 /** list of others TS, to recreate enumerator */
339 /** currently enumerating TS for "me" side */
340 traffic_selector_t
*ts
;
343 METHOD(enumerator_t
, policy_enumerate
, bool,
344 policy_enumerator_t
*this, traffic_selector_t
**my_out
,
345 traffic_selector_t
**other_out
)
347 traffic_selector_t
*other_ts
;
349 while (this->ts
|| this->mine
->enumerate(this->mine
, &this->ts
))
351 if (!this->other
->enumerate(this->other
, &other_ts
))
352 { /* end of others list, restart with new of mine */
353 this->other
->destroy(this->other
);
354 this->other
= this->list
->create_enumerator(this->list
);
358 if (this->ts
->get_type(this->ts
) != other_ts
->get_type(other_ts
))
359 { /* family mismatch */
362 if (this->ts
->get_protocol(this->ts
) &&
363 other_ts
->get_protocol(other_ts
) &&
364 this->ts
->get_protocol(this->ts
) != other_ts
->get_protocol(other_ts
))
365 { /* protocol mismatch */
369 *other_out
= other_ts
;
375 METHOD(enumerator_t
, policy_destroy
, void,
376 policy_enumerator_t
*this)
378 this->mine
->destroy(this->mine
);
379 this->other
->destroy(this->other
);
383 METHOD(child_sa_t
, create_policy_enumerator
, enumerator_t
*,
384 private_child_sa_t
*this)
386 policy_enumerator_t
*e
;
390 .enumerate
= (void*)_policy_enumerate
,
391 .destroy
= _policy_destroy
,
393 .mine
= this->my_ts
->create_enumerator(this->my_ts
),
394 .other
= this->other_ts
->create_enumerator(this->other_ts
),
395 .list
= this->other_ts
,
403 * update the cached usebytes
404 * returns SUCCESS if the usebytes have changed, FAILED if not or no SPIs
405 * are available, and NOT_SUPPORTED if the kernel interface does not support
406 * querying the usebytes.
408 static status_t
update_usebytes(private_child_sa_t
*this, bool inbound
)
410 status_t status
= FAILED
;
417 status
= hydra
->kernel_interface
->query_sa(hydra
->kernel_interface
,
418 this->other_addr
, this->my_addr
, this->my_spi
,
419 proto_ike2ip(this->protocol
), this->mark_in
,
421 if (status
== SUCCESS
)
423 if (bytes
> this->my_usebytes
)
425 this->my_usebytes
= bytes
;
436 status
= hydra
->kernel_interface
->query_sa(hydra
->kernel_interface
,
437 this->my_addr
, this->other_addr
, this->other_spi
,
438 proto_ike2ip(this->protocol
), this->mark_out
,
440 if (status
== SUCCESS
)
442 if (bytes
> this->other_usebytes
)
444 this->other_usebytes
= bytes
;
455 * updates the cached usetime
457 static void update_usetime(private_child_sa_t
*this, bool inbound
)
459 enumerator_t
*enumerator
;
460 traffic_selector_t
*my_ts
, *other_ts
;
461 u_int32_t last_use
= 0;
463 enumerator
= create_policy_enumerator(this);
464 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
466 u_int32_t in
, out
, fwd
;
470 if (hydra
->kernel_interface
->query_policy(hydra
->kernel_interface
,
471 other_ts
, my_ts
, POLICY_IN
, this->mark_in
, &in
) == SUCCESS
)
473 last_use
= max(last_use
, in
);
475 if (this->mode
!= MODE_TRANSPORT
)
477 if (hydra
->kernel_interface
->query_policy(hydra
->kernel_interface
,
478 other_ts
, my_ts
, POLICY_FWD
, this->mark_in
, &fwd
) == SUCCESS
)
480 last_use
= max(last_use
, fwd
);
486 if (hydra
->kernel_interface
->query_policy(hydra
->kernel_interface
,
487 my_ts
, other_ts
, POLICY_OUT
, this->mark_out
, &out
) == SUCCESS
)
489 last_use
= max(last_use
, out
);
493 enumerator
->destroy(enumerator
);
501 this->my_usetime
= last_use
;
505 this->other_usetime
= last_use
;
509 METHOD(child_sa_t
, get_usestats
, void,
510 private_child_sa_t
*this, bool inbound
, time_t *time
, u_int64_t
*bytes
)
512 if (update_usebytes(this, inbound
) != FAILED
)
514 /* there was traffic since last update or the kernel interface
515 * does not support querying the number of usebytes.
517 update_usetime(this, inbound
);
521 *time
= inbound ?
this->my_usetime
: this->other_usetime
;
525 *bytes
= inbound ?
this->my_usebytes
: this->other_usebytes
;
529 METHOD(child_sa_t
, get_lifetime
, time_t,
530 private_child_sa_t
*this, bool hard
)
532 return hard ?
this->expire_time
: this->rekey_time
;
535 METHOD(child_sa_t
, alloc_spi
, u_int32_t
,
536 private_child_sa_t
*this, protocol_id_t protocol
)
538 if (hydra
->kernel_interface
->get_spi(hydra
->kernel_interface
,
539 this->other_addr
, this->my_addr
,
540 proto_ike2ip(protocol
), this->reqid
,
541 &this->my_spi
) == SUCCESS
)
548 METHOD(child_sa_t
, alloc_cpi
, u_int16_t
,
549 private_child_sa_t
*this)
551 if (hydra
->kernel_interface
->get_cpi(hydra
->kernel_interface
,
552 this->other_addr
, this->my_addr
,
553 this->reqid
, &this->my_cpi
) == SUCCESS
)
560 METHOD(child_sa_t
, install
, status_t
,
561 private_child_sa_t
*this, chunk_t encr
, chunk_t integ
, u_int32_t spi
,
562 u_int16_t cpi
, bool inbound
, bool tfcv3
, linked_list_t
*my_ts
,
563 linked_list_t
*other_ts
)
565 u_int16_t enc_alg
= ENCR_UNDEFINED
, int_alg
= AUTH_UNDEFINED
, size
;
566 u_int16_t esn
= NO_EXT_SEQ_NUMBERS
;
567 traffic_selector_t
*src_ts
= NULL
, *dst_ts
= NULL
;
569 lifetime_cfg_t
*lifetime
;
575 /* now we have to decide which spi to use. Use self allocated, if "in",
576 * or the one in the proposal, if not "in" (others). Additionally,
577 * source and dest host switch depending on the role */
581 src
= this->other_addr
;
582 if (this->my_spi
== spi
)
583 { /* alloc_spi has been called, do an SA update */
592 dst
= this->other_addr
;
593 this->other_spi
= spi
;
594 this->other_cpi
= cpi
;
598 tfc
= this->config
->get_tfc(this->config
);
602 DBG2(DBG_CHD
, "adding %s %N SA", inbound ?
"inbound" : "outbound",
603 protocol_id_names
, this->protocol
);
605 /* send SA down to the kernel */
606 DBG2(DBG_CHD
, " SPI 0x%.8x, src %H dst %H", ntohl(spi
), src
, dst
);
608 this->proposal
->get_algorithm(this->proposal
, ENCRYPTION_ALGORITHM
,
610 this->proposal
->get_algorithm(this->proposal
, INTEGRITY_ALGORITHM
,
612 this->proposal
->get_algorithm(this->proposal
, EXTENDED_SEQUENCE_NUMBERS
,
615 lifetime
= this->config
->get_lifetime(this->config
);
617 now
= time_monotonic(NULL
);
618 if (lifetime
->time
.rekey
)
620 this->rekey_time
= now
+ lifetime
->time
.rekey
;
622 if (lifetime
->time
.life
)
624 this->expire_time
= now
+ lifetime
->time
.life
;
627 if (!lifetime
->time
.jitter
&& !inbound
)
628 { /* avoid triggering multiple rekey events */
629 lifetime
->time
.rekey
= 0;
632 if (this->mode
== MODE_BEET
|| this->mode
== MODE_TRANSPORT
)
634 /* BEET requires the bound address from the traffic selectors.
635 * TODO: We add just the first traffic selector for now, as the
636 * kernel accepts a single TS per SA only */
639 my_ts
->get_first(my_ts
, (void**)&dst_ts
);
640 other_ts
->get_first(other_ts
, (void**)&src_ts
);
644 my_ts
->get_first(my_ts
, (void**)&src_ts
);
645 other_ts
->get_first(other_ts
, (void**)&dst_ts
);
649 status
= hydra
->kernel_interface
->add_sa(hydra
->kernel_interface
,
650 src
, dst
, spi
, proto_ike2ip(this->protocol
), this->reqid
,
651 inbound ?
this->mark_in
: this->mark_out
, tfc
,
652 lifetime
, enc_alg
, encr
, int_alg
, integ
, this->mode
,
653 this->ipcomp
, cpi
, this->encap
, esn
, update
, src_ts
, dst_ts
);
660 METHOD(child_sa_t
, add_policies
, status_t
,
661 private_child_sa_t
*this, linked_list_t
*my_ts_list
,
662 linked_list_t
*other_ts_list
)
664 enumerator_t
*enumerator
;
665 traffic_selector_t
*my_ts
, *other_ts
;
666 status_t status
= SUCCESS
;
668 /* apply traffic selectors */
669 enumerator
= my_ts_list
->create_enumerator(my_ts_list
);
670 while (enumerator
->enumerate(enumerator
, &my_ts
))
672 this->my_ts
->insert_last(this->my_ts
, my_ts
->clone(my_ts
));
674 enumerator
->destroy(enumerator
);
675 enumerator
= other_ts_list
->create_enumerator(other_ts_list
);
676 while (enumerator
->enumerate(enumerator
, &other_ts
))
678 this->other_ts
->insert_last(this->other_ts
, other_ts
->clone(other_ts
));
680 enumerator
->destroy(enumerator
);
682 if (this->config
->install_policy(this->config
))
684 policy_priority_t priority
;
685 ipsec_sa_cfg_t my_sa
= {
687 .reqid
= this->reqid
,
689 .transform
= this->ipcomp
,
693 my_sa
.ipcomp
.cpi
= this->my_cpi
;
694 other_sa
.ipcomp
.cpi
= this->other_cpi
;
696 if (this->protocol
== PROTO_ESP
)
698 my_sa
.esp
.use
= TRUE
;
699 my_sa
.esp
.spi
= this->my_spi
;
700 other_sa
.esp
.use
= TRUE
;
701 other_sa
.esp
.spi
= this->other_spi
;
706 my_sa
.ah
.spi
= this->my_spi
;
707 other_sa
.ah
.use
= TRUE
;
708 other_sa
.ah
.spi
= this->other_spi
;
711 priority
= this->state
== CHILD_CREATED ? POLICY_PRIORITY_ROUTED
712 : POLICY_PRIORITY_DEFAULT
;
714 /* enumerate pairs of traffic selectors */
715 enumerator
= create_policy_enumerator(this);
716 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
718 /* install 3 policies: out, in and forward */
719 status
|= hydra
->kernel_interface
->add_policy(
720 hydra
->kernel_interface
,
721 this->my_addr
, this->other_addr
, my_ts
, other_ts
,
722 POLICY_OUT
, POLICY_IPSEC
, &other_sa
,
723 this->mark_out
, priority
);
725 status
|= hydra
->kernel_interface
->add_policy(
726 hydra
->kernel_interface
,
727 this->other_addr
, this->my_addr
, other_ts
, my_ts
,
728 POLICY_IN
, POLICY_IPSEC
, &my_sa
,
729 this->mark_in
, priority
);
730 if (this->mode
!= MODE_TRANSPORT
)
732 status
|= hydra
->kernel_interface
->add_policy(
733 hydra
->kernel_interface
,
734 this->other_addr
, this->my_addr
, other_ts
, my_ts
,
735 POLICY_FWD
, POLICY_IPSEC
, &my_sa
,
736 this->mark_in
, priority
);
739 if (status
!= SUCCESS
)
744 enumerator
->destroy(enumerator
);
747 if (status
== SUCCESS
&& this->state
== CHILD_CREATED
)
748 { /* switch to routed state if no SAD entry set up */
749 set_state(this, CHILD_ROUTED
);
754 METHOD(child_sa_t
, update
, status_t
,
755 private_child_sa_t
*this, host_t
*me
, host_t
*other
, host_t
*vip
,
758 child_sa_state_t old
;
759 bool transport_proxy_mode
;
761 /* anything changed at all? */
762 if (me
->equals(me
, this->my_addr
) &&
763 other
->equals(other
, this->other_addr
) && this->encap
== encap
)
769 set_state(this, CHILD_UPDATING
);
770 transport_proxy_mode
= this->config
->use_proxy_mode(this->config
) &&
771 this->mode
== MODE_TRANSPORT
;
773 if (!transport_proxy_mode
)
775 /* update our (initator) SA */
778 if (hydra
->kernel_interface
->update_sa(hydra
->kernel_interface
,
779 this->my_spi
, proto_ike2ip(this->protocol
),
780 this->ipcomp
!= IPCOMP_NONE ?
this->my_cpi
: 0,
781 this->other_addr
, this->my_addr
, other
, me
,
782 this->encap
, encap
, this->mark_in
) == NOT_SUPPORTED
)
784 return NOT_SUPPORTED
;
788 /* update his (responder) SA */
791 if (hydra
->kernel_interface
->update_sa(hydra
->kernel_interface
,
792 this->other_spi
, proto_ike2ip(this->protocol
),
793 this->ipcomp
!= IPCOMP_NONE ?
this->other_cpi
: 0,
794 this->my_addr
, this->other_addr
, me
, other
,
795 this->encap
, encap
, this->mark_out
) == NOT_SUPPORTED
)
797 return NOT_SUPPORTED
;
802 if (this->config
->install_policy(this->config
))
804 ipsec_sa_cfg_t my_sa
= {
806 .reqid
= this->reqid
,
808 .transform
= this->ipcomp
,
812 my_sa
.ipcomp
.cpi
= this->my_cpi
;
813 other_sa
.ipcomp
.cpi
= this->other_cpi
;
815 if (this->protocol
== PROTO_ESP
)
817 my_sa
.esp
.use
= TRUE
;
818 my_sa
.esp
.spi
= this->my_spi
;
819 other_sa
.esp
.use
= TRUE
;
820 other_sa
.esp
.spi
= this->other_spi
;
825 my_sa
.ah
.spi
= this->my_spi
;
826 other_sa
.ah
.use
= TRUE
;
827 other_sa
.ah
.spi
= this->other_spi
;
830 /* update policies */
831 if (!me
->ip_equals(me
, this->my_addr
) ||
832 !other
->ip_equals(other
, this->other_addr
))
834 enumerator_t
*enumerator
;
835 traffic_selector_t
*my_ts
, *other_ts
;
837 /* always use high priorities, as hosts getting updated are INSTALLED */
838 enumerator
= create_policy_enumerator(this);
839 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
841 /* remove old policies first */
842 hydra
->kernel_interface
->del_policy(hydra
->kernel_interface
,
843 my_ts
, other_ts
, POLICY_OUT
, this->reqid
,
844 this->mark_out
, POLICY_PRIORITY_DEFAULT
);
845 hydra
->kernel_interface
->del_policy(hydra
->kernel_interface
,
846 other_ts
, my_ts
, POLICY_IN
, this->reqid
,
847 this->mark_in
, POLICY_PRIORITY_DEFAULT
);
848 if (this->mode
!= MODE_TRANSPORT
)
850 hydra
->kernel_interface
->del_policy(hydra
->kernel_interface
,
851 other_ts
, my_ts
, POLICY_FWD
, this->reqid
,
852 this->mark_in
, POLICY_PRIORITY_DEFAULT
);
855 /* check whether we have to update a "dynamic" traffic selector */
856 if (!me
->ip_equals(me
, this->my_addr
) &&
857 my_ts
->is_host(my_ts
, this->my_addr
))
859 my_ts
->set_address(my_ts
, me
);
861 if (!other
->ip_equals(other
, this->other_addr
) &&
862 other_ts
->is_host(other_ts
, this->other_addr
))
864 other_ts
->set_address(other_ts
, other
);
867 /* we reinstall the virtual IP to handle interface roaming
871 hydra
->kernel_interface
->del_ip(hydra
->kernel_interface
, vip
);
872 hydra
->kernel_interface
->add_ip(hydra
->kernel_interface
, vip
, me
);
875 /* reinstall updated policies */
876 hydra
->kernel_interface
->add_policy(hydra
->kernel_interface
,
877 me
, other
, my_ts
, other_ts
, POLICY_OUT
, POLICY_IPSEC
,
878 &other_sa
, this->mark_out
, POLICY_PRIORITY_DEFAULT
);
879 hydra
->kernel_interface
->add_policy(hydra
->kernel_interface
,
880 other
, me
, other_ts
, my_ts
, POLICY_IN
, POLICY_IPSEC
,
881 &my_sa
, this->mark_in
, POLICY_PRIORITY_DEFAULT
);
882 if (this->mode
!= MODE_TRANSPORT
)
884 hydra
->kernel_interface
->add_policy(hydra
->kernel_interface
,
885 other
, me
, other_ts
, my_ts
, POLICY_FWD
, POLICY_IPSEC
,
886 &my_sa
, this->mark_in
, POLICY_PRIORITY_DEFAULT
);
889 enumerator
->destroy(enumerator
);
893 if (!transport_proxy_mode
)
896 if (!me
->equals(me
, this->my_addr
))
898 this->my_addr
->destroy(this->my_addr
);
899 this->my_addr
= me
->clone(me
);
901 if (!other
->equals(other
, this->other_addr
))
903 this->other_addr
->destroy(this->other_addr
);
904 this->other_addr
= other
->clone(other
);
909 set_state(this, old
);
914 METHOD(child_sa_t
, destroy
, void,
915 private_child_sa_t
*this)
917 enumerator_t
*enumerator
;
918 traffic_selector_t
*my_ts
, *other_ts
;
919 policy_priority_t priority
;
921 priority
= this->state
== CHILD_ROUTED ? POLICY_PRIORITY_ROUTED
922 : POLICY_PRIORITY_DEFAULT
;
924 set_state(this, CHILD_DESTROYING
);
926 /* delete SAs in the kernel, if they are set up */
929 /* if CHILD was not established, use PROTO_ESP used during alloc_spi().
930 * TODO: For AH support, we have to store protocol specific SPI.s */
931 if (this->protocol
== PROTO_NONE
)
933 this->protocol
= PROTO_ESP
;
935 hydra
->kernel_interface
->del_sa(hydra
->kernel_interface
,
936 this->other_addr
, this->my_addr
, this->my_spi
,
937 proto_ike2ip(this->protocol
), this->my_cpi
,
942 hydra
->kernel_interface
->del_sa(hydra
->kernel_interface
,
943 this->my_addr
, this->other_addr
, this->other_spi
,
944 proto_ike2ip(this->protocol
), this->other_cpi
,
948 if (this->config
->install_policy(this->config
))
950 /* delete all policies in the kernel */
951 enumerator
= create_policy_enumerator(this);
952 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
954 hydra
->kernel_interface
->del_policy(hydra
->kernel_interface
,
955 my_ts
, other_ts
, POLICY_OUT
, this->reqid
,
956 this->mark_out
, priority
);
957 hydra
->kernel_interface
->del_policy(hydra
->kernel_interface
,
958 other_ts
, my_ts
, POLICY_IN
, this->reqid
,
959 this->mark_in
, priority
);
960 if (this->mode
!= MODE_TRANSPORT
)
962 hydra
->kernel_interface
->del_policy(hydra
->kernel_interface
,
963 other_ts
, my_ts
, POLICY_FWD
, this->reqid
,
964 this->mark_in
, priority
);
967 enumerator
->destroy(enumerator
);
970 this->my_ts
->destroy_offset(this->my_ts
, offsetof(traffic_selector_t
, destroy
));
971 this->other_ts
->destroy_offset(this->other_ts
, offsetof(traffic_selector_t
, destroy
));
972 this->my_addr
->destroy(this->my_addr
);
973 this->other_addr
->destroy(this->other_addr
);
974 DESTROY_IF(this->proposal
);
975 this->config
->destroy(this->config
);
980 * Described in header.
982 child_sa_t
* child_sa_create(host_t
*me
, host_t
* other
,
983 child_cfg_t
*config
, u_int32_t rekey
, bool encap
)
985 static u_int32_t reqid
= 0;
986 private_child_sa_t
*this;
990 .get_name
= _get_name
,
991 .get_reqid
= _get_reqid
,
992 .get_config
= _get_config
,
993 .get_state
= _get_state
,
994 .set_state
= _set_state
,
997 .get_protocol
= _get_protocol
,
998 .set_protocol
= _set_protocol
,
999 .get_mode
= _get_mode
,
1000 .set_mode
= _set_mode
,
1001 .get_proposal
= _get_proposal
,
1002 .set_proposal
= _set_proposal
,
1003 .get_lifetime
= _get_lifetime
,
1004 .get_usestats
= _get_usestats
,
1005 .has_encap
= _has_encap
,
1006 .get_ipcomp
= _get_ipcomp
,
1007 .set_ipcomp
= _set_ipcomp
,
1008 .get_close_action
= _get_close_action
,
1009 .set_close_action
= _set_close_action
,
1010 .get_dpd_action
= _get_dpd_action
,
1011 .set_dpd_action
= _set_dpd_action
,
1012 .alloc_spi
= _alloc_spi
,
1013 .alloc_cpi
= _alloc_cpi
,
1014 .install
= _install
,
1016 .add_policies
= _add_policies
,
1017 .get_traffic_selectors
= _get_traffic_selectors
,
1018 .create_policy_enumerator
= _create_policy_enumerator
,
1019 .destroy
= _destroy
,
1021 .my_addr
= me
->clone(me
),
1022 .other_addr
= other
->clone(other
),
1024 .ipcomp
= IPCOMP_NONE
,
1025 .state
= CHILD_CREATED
,
1026 .my_ts
= linked_list_create(),
1027 .other_ts
= linked_list_create(),
1028 .protocol
= PROTO_NONE
,
1029 .mode
= MODE_TUNNEL
,
1030 .close_action
= config
->get_close_action(config
),
1031 .dpd_action
= config
->get_dpd_action(config
),
1032 .reqid
= config
->get_reqid(config
),
1033 .mark_in
= config
->get_mark(config
, TRUE
),
1034 .mark_out
= config
->get_mark(config
, FALSE
),
1037 this->config
= config
;
1038 config
->get_ref(config
);
1042 /* reuse old reqid if we are rekeying an existing CHILD_SA */
1043 this->reqid
= rekey ? rekey
: ++reqid
;
1046 /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
1047 if (config
->get_mode(config
) == MODE_TRANSPORT
&&
1048 config
->use_proxy_mode(config
))
1054 enumerator_t
*enumerator
;
1055 linked_list_t
*my_ts_list
, *other_ts_list
;
1056 traffic_selector_t
*my_ts
, *other_ts
;
1058 this->mode
= MODE_TRANSPORT
;
1060 my_ts_list
= config
->get_traffic_selectors(config
, TRUE
, NULL
, me
);
1061 enumerator
= my_ts_list
->create_enumerator(my_ts_list
);
1062 if (enumerator
->enumerate(enumerator
, &my_ts
))
1064 if (my_ts
->is_host(my_ts
, NULL
) &&
1065 !my_ts
->is_host(my_ts
, this->my_addr
))
1067 type
= my_ts
->get_type(my_ts
);
1068 family
= (type
== TS_IPV4_ADDR_RANGE
) ? AF_INET
: AF_INET6
;
1069 addr
= my_ts
->get_from_address(my_ts
);
1070 host
= host_create_from_chunk(family
, addr
, 0);
1072 DBG1(DBG_CHD
, "my address: %H is a transport mode proxy for %H",
1073 this->my_addr
, host
);
1074 this->my_addr
->destroy(this->my_addr
);
1075 this->my_addr
= host
;
1078 enumerator
->destroy(enumerator
);
1079 my_ts_list
->destroy_offset(my_ts_list
, offsetof(traffic_selector_t
, destroy
));
1081 other_ts_list
= config
->get_traffic_selectors(config
, FALSE
, NULL
, other
);
1082 enumerator
= other_ts_list
->create_enumerator(other_ts_list
);
1083 if (enumerator
->enumerate(enumerator
, &other_ts
))
1085 if (other_ts
->is_host(other_ts
, NULL
) &&
1086 !other_ts
->is_host(other_ts
, this->other_addr
))
1088 type
= other_ts
->get_type(other_ts
);
1089 family
= (type
== TS_IPV4_ADDR_RANGE
) ? AF_INET
: AF_INET6
;
1090 addr
= other_ts
->get_from_address(other_ts
);
1091 host
= host_create_from_chunk(family
, addr
, 0);
1093 DBG1(DBG_CHD
, "other address: %H is a transport mode proxy for %H",
1094 this->other_addr
, host
);
1095 this->other_addr
->destroy(this->other_addr
);
1096 this->other_addr
= host
;
1099 enumerator
->destroy(enumerator
);
1100 other_ts_list
->destroy_offset(other_ts_list
, offsetof(traffic_selector_t
, destroy
));
1103 return &this->public;