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 * TRUE if this CHILD_SA is used to install trap policies
132 * Specifies if UDP encapsulation is enabled (NAT traversal)
137 * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
139 ipcomp_transform_t ipcomp
;
142 * mode this SA uses, tunnel/transport
147 * Action to enforce if peer closes the CHILD_SA
149 action_t close_action
;
152 * Action to enforce if peer is considered dead
159 proposal_t
*proposal
;
162 * config used to create this child
167 * time of last use in seconds (inbound)
169 u_int32_t my_usetime
;
172 * time of last use in seconds (outbound)
174 u_int32_t other_usetime
;
177 * last number of inbound bytes
179 u_int64_t my_usebytes
;
182 * last number of outbound bytes
184 u_int64_t other_usebytes
;
187 * last number of inbound packets
189 u_int64_t my_usepackets
;
192 * last number of outbound bytes
194 u_int64_t other_usepackets
;
198 * convert an IKEv2 specific protocol identifier to the IP protocol identifier.
200 static inline u_int8_t
proto_ike2ip(protocol_id_t protocol
)
213 METHOD(child_sa_t
, get_name
, char*,
214 private_child_sa_t
*this)
216 return this->config
->get_name(this->config
);
219 METHOD(child_sa_t
, get_reqid
, u_int32_t
,
220 private_child_sa_t
*this)
225 METHOD(child_sa_t
, get_config
, child_cfg_t
*,
226 private_child_sa_t
*this)
231 METHOD(child_sa_t
, set_state
, void,
232 private_child_sa_t
*this, child_sa_state_t state
)
234 charon
->bus
->child_state_change(charon
->bus
, &this->public, state
);
238 METHOD(child_sa_t
, get_state
, child_sa_state_t
,
239 private_child_sa_t
*this)
244 METHOD(child_sa_t
, get_spi
, u_int32_t
,
245 private_child_sa_t
*this, bool inbound
)
247 return inbound ?
this->my_spi
: this->other_spi
;
250 METHOD(child_sa_t
, get_cpi
, u_int16_t
,
251 private_child_sa_t
*this, bool inbound
)
253 return inbound ?
this->my_cpi
: this->other_cpi
;
256 METHOD(child_sa_t
, get_protocol
, protocol_id_t
,
257 private_child_sa_t
*this)
259 return this->protocol
;
262 METHOD(child_sa_t
, set_protocol
, void,
263 private_child_sa_t
*this, protocol_id_t protocol
)
265 this->protocol
= protocol
;
268 METHOD(child_sa_t
, get_mode
, ipsec_mode_t
,
269 private_child_sa_t
*this)
274 METHOD(child_sa_t
, set_mode
, void,
275 private_child_sa_t
*this, ipsec_mode_t mode
)
280 METHOD(child_sa_t
, has_encap
, bool,
281 private_child_sa_t
*this)
286 METHOD(child_sa_t
, get_ipcomp
, ipcomp_transform_t
,
287 private_child_sa_t
*this)
292 METHOD(child_sa_t
, set_ipcomp
, void,
293 private_child_sa_t
*this, ipcomp_transform_t ipcomp
)
295 this->ipcomp
= ipcomp
;
298 METHOD(child_sa_t
, set_close_action
, void,
299 private_child_sa_t
*this, action_t action
)
301 this->close_action
= action
;
304 METHOD(child_sa_t
, get_close_action
, action_t
,
305 private_child_sa_t
*this)
307 return this->close_action
;
310 METHOD(child_sa_t
, set_dpd_action
, void,
311 private_child_sa_t
*this, action_t action
)
313 this->dpd_action
= action
;
316 METHOD(child_sa_t
, get_dpd_action
, action_t
,
317 private_child_sa_t
*this)
319 return this->dpd_action
;
322 METHOD(child_sa_t
, get_proposal
, proposal_t
*,
323 private_child_sa_t
*this)
325 return this->proposal
;
328 METHOD(child_sa_t
, set_proposal
, void,
329 private_child_sa_t
*this, proposal_t
*proposal
)
331 this->proposal
= proposal
->clone(proposal
);
334 METHOD(child_sa_t
, get_traffic_selectors
, linked_list_t
*,
335 private_child_sa_t
*this, bool local
)
337 return local ?
this->my_ts
: this->other_ts
;
340 typedef struct policy_enumerator_t policy_enumerator_t
;
343 * Private policy enumerator
345 struct policy_enumerator_t
{
346 /** implements enumerator_t */
348 /** enumerator over own TS */
350 /** enumerator over others TS */
352 /** list of others TS, to recreate enumerator */
354 /** currently enumerating TS for "me" side */
355 traffic_selector_t
*ts
;
358 METHOD(enumerator_t
, policy_enumerate
, bool,
359 policy_enumerator_t
*this, traffic_selector_t
**my_out
,
360 traffic_selector_t
**other_out
)
362 traffic_selector_t
*other_ts
;
364 while (this->ts
|| this->mine
->enumerate(this->mine
, &this->ts
))
366 if (!this->other
->enumerate(this->other
, &other_ts
))
367 { /* end of others list, restart with new of mine */
368 this->other
->destroy(this->other
);
369 this->other
= this->list
->create_enumerator(this->list
);
373 if (this->ts
->get_type(this->ts
) != other_ts
->get_type(other_ts
))
374 { /* family mismatch */
377 if (this->ts
->get_protocol(this->ts
) &&
378 other_ts
->get_protocol(other_ts
) &&
379 this->ts
->get_protocol(this->ts
) != other_ts
->get_protocol(other_ts
))
380 { /* protocol mismatch */
384 *other_out
= other_ts
;
390 METHOD(enumerator_t
, policy_destroy
, void,
391 policy_enumerator_t
*this)
393 this->mine
->destroy(this->mine
);
394 this->other
->destroy(this->other
);
398 METHOD(child_sa_t
, create_policy_enumerator
, enumerator_t
*,
399 private_child_sa_t
*this)
401 policy_enumerator_t
*e
;
405 .enumerate
= (void*)_policy_enumerate
,
406 .destroy
= _policy_destroy
,
408 .mine
= this->my_ts
->create_enumerator(this->my_ts
),
409 .other
= this->other_ts
->create_enumerator(this->other_ts
),
410 .list
= this->other_ts
,
418 * update the cached usebytes
419 * returns SUCCESS if the usebytes have changed, FAILED if not or no SPIs
420 * are available, and NOT_SUPPORTED if the kernel interface does not support
421 * querying the usebytes.
423 static status_t
update_usebytes(private_child_sa_t
*this, bool inbound
)
425 status_t status
= FAILED
;
426 u_int64_t bytes
, packets
;
432 status
= hydra
->kernel_interface
->query_sa(hydra
->kernel_interface
,
433 this->other_addr
, this->my_addr
, this->my_spi
,
434 proto_ike2ip(this->protocol
), this->mark_in
,
436 if (status
== SUCCESS
)
438 if (bytes
> this->my_usebytes
)
440 this->my_usebytes
= bytes
;
441 this->my_usepackets
= packets
;
452 status
= hydra
->kernel_interface
->query_sa(hydra
->kernel_interface
,
453 this->my_addr
, this->other_addr
, this->other_spi
,
454 proto_ike2ip(this->protocol
), this->mark_out
,
456 if (status
== SUCCESS
)
458 if (bytes
> this->other_usebytes
)
460 this->other_usebytes
= bytes
;
461 this->other_usepackets
= packets
;
472 * updates the cached usetime
474 static void update_usetime(private_child_sa_t
*this, bool inbound
)
476 enumerator_t
*enumerator
;
477 traffic_selector_t
*my_ts
, *other_ts
;
478 u_int32_t last_use
= 0;
480 enumerator
= create_policy_enumerator(this);
481 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
483 u_int32_t in
, out
, fwd
;
487 if (hydra
->kernel_interface
->query_policy(hydra
->kernel_interface
,
488 other_ts
, my_ts
, POLICY_IN
, this->mark_in
, &in
) == SUCCESS
)
490 last_use
= max(last_use
, in
);
492 if (this->mode
!= MODE_TRANSPORT
)
494 if (hydra
->kernel_interface
->query_policy(hydra
->kernel_interface
,
495 other_ts
, my_ts
, POLICY_FWD
, this->mark_in
, &fwd
) == SUCCESS
)
497 last_use
= max(last_use
, fwd
);
503 if (hydra
->kernel_interface
->query_policy(hydra
->kernel_interface
,
504 my_ts
, other_ts
, POLICY_OUT
, this->mark_out
, &out
) == SUCCESS
)
506 last_use
= max(last_use
, out
);
510 enumerator
->destroy(enumerator
);
518 this->my_usetime
= last_use
;
522 this->other_usetime
= last_use
;
526 METHOD(child_sa_t
, get_usestats
, void,
527 private_child_sa_t
*this, bool inbound
,
528 time_t *time
, u_int64_t
*bytes
, u_int64_t
*packets
)
530 if ((!bytes
&& !packets
) || update_usebytes(this, inbound
) != FAILED
)
532 /* there was traffic since last update or the kernel interface
533 * does not support querying the number of usebytes.
537 update_usetime(this, inbound
);
542 *time
= inbound ?
this->my_usetime
: this->other_usetime
;
546 *bytes
= inbound ?
this->my_usebytes
: this->other_usebytes
;
550 *packets
= inbound ?
this->my_usepackets
: this->other_usepackets
;
554 METHOD(child_sa_t
, get_mark
, mark_t
,
555 private_child_sa_t
*this, bool inbound
)
559 return this->mark_in
;
561 return this->mark_out
;
564 METHOD(child_sa_t
, get_lifetime
, time_t,
565 private_child_sa_t
*this, bool hard
)
567 return hard ?
this->expire_time
: this->rekey_time
;
570 METHOD(child_sa_t
, alloc_spi
, u_int32_t
,
571 private_child_sa_t
*this, protocol_id_t protocol
)
573 if (hydra
->kernel_interface
->get_spi(hydra
->kernel_interface
,
574 this->other_addr
, this->my_addr
,
575 proto_ike2ip(protocol
), this->reqid
,
576 &this->my_spi
) == SUCCESS
)
583 METHOD(child_sa_t
, alloc_cpi
, u_int16_t
,
584 private_child_sa_t
*this)
586 if (hydra
->kernel_interface
->get_cpi(hydra
->kernel_interface
,
587 this->other_addr
, this->my_addr
,
588 this->reqid
, &this->my_cpi
) == SUCCESS
)
595 METHOD(child_sa_t
, install
, status_t
,
596 private_child_sa_t
*this, chunk_t encr
, chunk_t integ
, u_int32_t spi
,
597 u_int16_t cpi
, bool inbound
, bool tfcv3
, linked_list_t
*my_ts
,
598 linked_list_t
*other_ts
)
600 u_int16_t enc_alg
= ENCR_UNDEFINED
, int_alg
= AUTH_UNDEFINED
, size
;
601 u_int16_t esn
= NO_EXT_SEQ_NUMBERS
;
602 traffic_selector_t
*src_ts
= NULL
, *dst_ts
= NULL
;
604 lifetime_cfg_t
*lifetime
;
610 /* now we have to decide which spi to use. Use self allocated, if "in",
611 * or the one in the proposal, if not "in" (others). Additionally,
612 * source and dest host switch depending on the role */
616 src
= this->other_addr
;
617 if (this->my_spi
== spi
)
618 { /* alloc_spi has been called, do an SA update */
627 dst
= this->other_addr
;
628 this->other_spi
= spi
;
629 this->other_cpi
= cpi
;
633 tfc
= this->config
->get_tfc(this->config
);
637 DBG2(DBG_CHD
, "adding %s %N SA", inbound ?
"inbound" : "outbound",
638 protocol_id_names
, this->protocol
);
640 /* send SA down to the kernel */
641 DBG2(DBG_CHD
, " SPI 0x%.8x, src %H dst %H", ntohl(spi
), src
, dst
);
643 this->proposal
->get_algorithm(this->proposal
, ENCRYPTION_ALGORITHM
,
645 this->proposal
->get_algorithm(this->proposal
, INTEGRITY_ALGORITHM
,
647 this->proposal
->get_algorithm(this->proposal
, EXTENDED_SEQUENCE_NUMBERS
,
650 lifetime
= this->config
->get_lifetime(this->config
);
652 now
= time_monotonic(NULL
);
653 if (lifetime
->time
.rekey
)
655 if (this->rekey_time
)
657 this->rekey_time
= min(this->rekey_time
, now
+ lifetime
->time
.rekey
);
661 this->rekey_time
= now
+ lifetime
->time
.rekey
;
664 if (lifetime
->time
.life
)
666 this->expire_time
= now
+ lifetime
->time
.life
;
669 if (!lifetime
->time
.jitter
&& !inbound
)
670 { /* avoid triggering multiple rekey events */
671 lifetime
->time
.rekey
= 0;
674 /* BEET requires the bound address from the traffic selectors.
675 * TODO: We add just the first traffic selector for now, as the
676 * kernel accepts a single TS per SA only */
679 my_ts
->get_first(my_ts
, (void**)&dst_ts
);
680 other_ts
->get_first(other_ts
, (void**)&src_ts
);
684 my_ts
->get_first(my_ts
, (void**)&src_ts
);
685 other_ts
->get_first(other_ts
, (void**)&dst_ts
);
688 status
= hydra
->kernel_interface
->add_sa(hydra
->kernel_interface
,
689 src
, dst
, spi
, proto_ike2ip(this->protocol
), this->reqid
,
690 inbound ?
this->mark_in
: this->mark_out
, tfc
,
691 lifetime
, enc_alg
, encr
, int_alg
, integ
, this->mode
,
692 this->ipcomp
, cpi
, this->encap
, esn
, update
, src_ts
, dst_ts
);
700 * Install 3 policies: out, in and forward
702 static status_t
install_policies_internal(private_child_sa_t
*this,
703 host_t
*my_addr
, host_t
*other_addr
, traffic_selector_t
*my_ts
,
704 traffic_selector_t
*other_ts
, ipsec_sa_cfg_t
*my_sa
,
705 ipsec_sa_cfg_t
*other_sa
, policy_type_t type
, policy_priority_t priority
)
707 status_t status
= SUCCESS
;
708 status
|= hydra
->kernel_interface
->add_policy(hydra
->kernel_interface
,
709 my_addr
, other_addr
, my_ts
, other_ts
,
710 POLICY_OUT
, type
, other_sa
,
711 this->mark_out
, priority
);
713 status
|= hydra
->kernel_interface
->add_policy(hydra
->kernel_interface
,
714 other_addr
, my_addr
, other_ts
, my_ts
,
715 POLICY_IN
, type
, my_sa
,
716 this->mark_in
, priority
);
717 if (this->mode
!= MODE_TRANSPORT
)
719 status
|= hydra
->kernel_interface
->add_policy(hydra
->kernel_interface
,
720 other_addr
, my_addr
, other_ts
, my_ts
,
721 POLICY_FWD
, type
, my_sa
,
722 this->mark_in
, priority
);
728 * Delete 3 policies: out, in and forward
730 static void del_policies_internal(private_child_sa_t
*this,
731 traffic_selector_t
*my_ts
, traffic_selector_t
*other_ts
,
732 policy_priority_t priority
)
734 hydra
->kernel_interface
->del_policy(hydra
->kernel_interface
,
735 my_ts
, other_ts
, POLICY_OUT
, this->reqid
,
736 this->mark_out
, priority
);
737 hydra
->kernel_interface
->del_policy(hydra
->kernel_interface
,
738 other_ts
, my_ts
, POLICY_IN
, this->reqid
,
739 this->mark_in
, priority
);
740 if (this->mode
!= MODE_TRANSPORT
)
742 hydra
->kernel_interface
->del_policy(hydra
->kernel_interface
,
743 other_ts
, my_ts
, POLICY_FWD
, this->reqid
,
744 this->mark_in
, priority
);
748 METHOD(child_sa_t
, add_policies
, status_t
,
749 private_child_sa_t
*this, linked_list_t
*my_ts_list
,
750 linked_list_t
*other_ts_list
)
752 enumerator_t
*enumerator
;
753 traffic_selector_t
*my_ts
, *other_ts
;
754 status_t status
= SUCCESS
;
756 /* apply traffic selectors */
757 enumerator
= my_ts_list
->create_enumerator(my_ts_list
);
758 while (enumerator
->enumerate(enumerator
, &my_ts
))
760 this->my_ts
->insert_last(this->my_ts
, my_ts
->clone(my_ts
));
762 enumerator
->destroy(enumerator
);
763 enumerator
= other_ts_list
->create_enumerator(other_ts_list
);
764 while (enumerator
->enumerate(enumerator
, &other_ts
))
766 this->other_ts
->insert_last(this->other_ts
, other_ts
->clone(other_ts
));
768 enumerator
->destroy(enumerator
);
770 if (this->config
->install_policy(this->config
))
772 policy_priority_t priority
;
773 ipsec_sa_cfg_t my_sa
= {
775 .reqid
= this->reqid
,
777 .transform
= this->ipcomp
,
781 my_sa
.ipcomp
.cpi
= this->my_cpi
;
782 other_sa
.ipcomp
.cpi
= this->other_cpi
;
784 if (this->protocol
== PROTO_ESP
)
786 my_sa
.esp
.use
= TRUE
;
787 my_sa
.esp
.spi
= this->my_spi
;
788 other_sa
.esp
.use
= TRUE
;
789 other_sa
.esp
.spi
= this->other_spi
;
794 my_sa
.ah
.spi
= this->my_spi
;
795 other_sa
.ah
.use
= TRUE
;
796 other_sa
.ah
.spi
= this->other_spi
;
799 /* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
800 * entry) we install a trap policy */
801 this->trap
= this->state
== CHILD_CREATED
;
802 priority
= this->trap ? POLICY_PRIORITY_ROUTED
803 : POLICY_PRIORITY_DEFAULT
;
805 /* enumerate pairs of traffic selectors */
806 enumerator
= create_policy_enumerator(this);
807 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
809 /* install outbound drop policy to avoid packets leaving unencrypted
810 * when updating policies */
811 if (priority
== POLICY_PRIORITY_DEFAULT
)
813 status
|= install_policies_internal(this, this->my_addr
,
814 this->other_addr
, my_ts
, other_ts
,
815 &my_sa
, &other_sa
, POLICY_DROP
,
816 POLICY_PRIORITY_FALLBACK
);
819 /* install policies */
820 status
|= install_policies_internal(this, this->my_addr
,
821 this->other_addr
, my_ts
, other_ts
,
822 &my_sa
, &other_sa
, POLICY_IPSEC
, priority
);
824 if (status
!= SUCCESS
)
829 enumerator
->destroy(enumerator
);
832 if (status
== SUCCESS
&& this->trap
)
834 set_state(this, CHILD_ROUTED
);
840 * Callback to reinstall a virtual IP
842 static void reinstall_vip(host_t
*vip
, host_t
*me
)
846 if (hydra
->kernel_interface
->get_interface(hydra
->kernel_interface
,
849 hydra
->kernel_interface
->del_ip(hydra
->kernel_interface
, vip
, -1, TRUE
);
850 hydra
->kernel_interface
->add_ip(hydra
->kernel_interface
, vip
, -1, iface
);
855 METHOD(child_sa_t
, update
, status_t
,
856 private_child_sa_t
*this, host_t
*me
, host_t
*other
, linked_list_t
*vips
,
859 child_sa_state_t old
;
860 bool transport_proxy_mode
;
862 /* anything changed at all? */
863 if (me
->equals(me
, this->my_addr
) &&
864 other
->equals(other
, this->other_addr
) && this->encap
== encap
)
870 set_state(this, CHILD_UPDATING
);
871 transport_proxy_mode
= this->config
->use_proxy_mode(this->config
) &&
872 this->mode
== MODE_TRANSPORT
;
874 if (!transport_proxy_mode
)
876 /* update our (initiator) SA */
879 if (hydra
->kernel_interface
->update_sa(hydra
->kernel_interface
,
880 this->my_spi
, proto_ike2ip(this->protocol
),
881 this->ipcomp
!= IPCOMP_NONE ?
this->my_cpi
: 0,
882 this->other_addr
, this->my_addr
, other
, me
,
883 this->encap
, encap
, this->mark_in
) == NOT_SUPPORTED
)
885 return NOT_SUPPORTED
;
889 /* update his (responder) SA */
892 if (hydra
->kernel_interface
->update_sa(hydra
->kernel_interface
,
893 this->other_spi
, proto_ike2ip(this->protocol
),
894 this->ipcomp
!= IPCOMP_NONE ?
this->other_cpi
: 0,
895 this->my_addr
, this->other_addr
, me
, other
,
896 this->encap
, encap
, this->mark_out
) == NOT_SUPPORTED
)
898 return NOT_SUPPORTED
;
903 if (this->config
->install_policy(this->config
))
905 ipsec_sa_cfg_t my_sa
= {
907 .reqid
= this->reqid
,
909 .transform
= this->ipcomp
,
913 my_sa
.ipcomp
.cpi
= this->my_cpi
;
914 other_sa
.ipcomp
.cpi
= this->other_cpi
;
916 if (this->protocol
== PROTO_ESP
)
918 my_sa
.esp
.use
= TRUE
;
919 my_sa
.esp
.spi
= this->my_spi
;
920 other_sa
.esp
.use
= TRUE
;
921 other_sa
.esp
.spi
= this->other_spi
;
926 my_sa
.ah
.spi
= this->my_spi
;
927 other_sa
.ah
.use
= TRUE
;
928 other_sa
.ah
.spi
= this->other_spi
;
931 /* update policies */
932 if (!me
->ip_equals(me
, this->my_addr
) ||
933 !other
->ip_equals(other
, this->other_addr
))
935 enumerator_t
*enumerator
;
936 traffic_selector_t
*my_ts
, *other_ts
;
938 /* always use high priorities, as hosts getting updated are INSTALLED */
939 enumerator
= create_policy_enumerator(this);
940 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
942 traffic_selector_t
*old_my_ts
= NULL
, *old_other_ts
= NULL
;
943 /* remove old policies first */
944 del_policies_internal(this, my_ts
, other_ts
,
945 POLICY_PRIORITY_DEFAULT
);
947 /* check if we have to update a "dynamic" traffic selector */
948 if (!me
->ip_equals(me
, this->my_addr
) &&
949 my_ts
->is_host(my_ts
, this->my_addr
))
951 old_my_ts
= my_ts
->clone(my_ts
);
952 my_ts
->set_address(my_ts
, me
);
954 if (!other
->ip_equals(other
, this->other_addr
) &&
955 other_ts
->is_host(other_ts
, this->other_addr
))
957 old_other_ts
= other_ts
->clone(other_ts
);
958 other_ts
->set_address(other_ts
, other
);
961 /* we reinstall the virtual IP to handle interface roaming
963 vips
->invoke_function(vips
, (void*)reinstall_vip
, me
);
965 /* reinstall updated policies */
966 install_policies_internal(this, me
, other
, my_ts
, other_ts
,
967 &my_sa
, &other_sa
, POLICY_IPSEC
,
968 POLICY_PRIORITY_DEFAULT
);
970 /* update fallback policies after the new policy is in place */
971 if (old_my_ts
|| old_other_ts
)
973 del_policies_internal(this, old_my_ts ?
: my_ts
,
974 old_other_ts ?
: other_ts
,
975 POLICY_PRIORITY_FALLBACK
);
976 install_policies_internal(this, me
, other
, my_ts
, other_ts
,
977 &my_sa
, &other_sa
, POLICY_DROP
,
978 POLICY_PRIORITY_FALLBACK
);
979 DESTROY_IF(old_my_ts
);
980 DESTROY_IF(old_other_ts
);
983 enumerator
->destroy(enumerator
);
987 if (!transport_proxy_mode
)
990 if (!me
->equals(me
, this->my_addr
))
992 this->my_addr
->destroy(this->my_addr
);
993 this->my_addr
= me
->clone(me
);
995 if (!other
->equals(other
, this->other_addr
))
997 this->other_addr
->destroy(this->other_addr
);
998 this->other_addr
= other
->clone(other
);
1002 this->encap
= encap
;
1003 set_state(this, old
);
1008 METHOD(child_sa_t
, destroy
, void,
1009 private_child_sa_t
*this)
1011 enumerator_t
*enumerator
;
1012 traffic_selector_t
*my_ts
, *other_ts
;
1013 policy_priority_t priority
;
1015 priority
= this->trap ? POLICY_PRIORITY_ROUTED
: POLICY_PRIORITY_DEFAULT
;
1017 set_state(this, CHILD_DESTROYING
);
1019 /* delete SAs in the kernel, if they are set up */
1022 /* if CHILD was not established, use PROTO_ESP used during alloc_spi().
1023 * TODO: For AH support, we have to store protocol specific SPI.s */
1024 if (this->protocol
== PROTO_NONE
)
1026 this->protocol
= PROTO_ESP
;
1028 hydra
->kernel_interface
->del_sa(hydra
->kernel_interface
,
1029 this->other_addr
, this->my_addr
, this->my_spi
,
1030 proto_ike2ip(this->protocol
), this->my_cpi
,
1033 if (this->other_spi
)
1035 hydra
->kernel_interface
->del_sa(hydra
->kernel_interface
,
1036 this->my_addr
, this->other_addr
, this->other_spi
,
1037 proto_ike2ip(this->protocol
), this->other_cpi
,
1041 if (this->config
->install_policy(this->config
))
1043 /* delete all policies in the kernel */
1044 enumerator
= create_policy_enumerator(this);
1045 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
1047 del_policies_internal(this, my_ts
, other_ts
, priority
);
1048 if (priority
== POLICY_PRIORITY_DEFAULT
)
1050 del_policies_internal(this, my_ts
, other_ts
,
1051 POLICY_PRIORITY_FALLBACK
);
1054 enumerator
->destroy(enumerator
);
1057 this->my_ts
->destroy_offset(this->my_ts
, offsetof(traffic_selector_t
, destroy
));
1058 this->other_ts
->destroy_offset(this->other_ts
, offsetof(traffic_selector_t
, destroy
));
1059 this->my_addr
->destroy(this->my_addr
);
1060 this->other_addr
->destroy(this->other_addr
);
1061 DESTROY_IF(this->proposal
);
1062 this->config
->destroy(this->config
);
1067 * Described in header.
1069 child_sa_t
* child_sa_create(host_t
*me
, host_t
* other
,
1070 child_cfg_t
*config
, u_int32_t rekey
, bool encap
)
1072 static u_int32_t reqid
= 0;
1073 private_child_sa_t
*this;
1077 .get_name
= _get_name
,
1078 .get_reqid
= _get_reqid
,
1079 .get_config
= _get_config
,
1080 .get_state
= _get_state
,
1081 .set_state
= _set_state
,
1082 .get_spi
= _get_spi
,
1083 .get_cpi
= _get_cpi
,
1084 .get_protocol
= _get_protocol
,
1085 .set_protocol
= _set_protocol
,
1086 .get_mode
= _get_mode
,
1087 .set_mode
= _set_mode
,
1088 .get_proposal
= _get_proposal
,
1089 .set_proposal
= _set_proposal
,
1090 .get_lifetime
= _get_lifetime
,
1091 .get_usestats
= _get_usestats
,
1092 .get_mark
= _get_mark
,
1093 .has_encap
= _has_encap
,
1094 .get_ipcomp
= _get_ipcomp
,
1095 .set_ipcomp
= _set_ipcomp
,
1096 .get_close_action
= _get_close_action
,
1097 .set_close_action
= _set_close_action
,
1098 .get_dpd_action
= _get_dpd_action
,
1099 .set_dpd_action
= _set_dpd_action
,
1100 .alloc_spi
= _alloc_spi
,
1101 .alloc_cpi
= _alloc_cpi
,
1102 .install
= _install
,
1104 .add_policies
= _add_policies
,
1105 .get_traffic_selectors
= _get_traffic_selectors
,
1106 .create_policy_enumerator
= _create_policy_enumerator
,
1107 .destroy
= _destroy
,
1109 .my_addr
= me
->clone(me
),
1110 .other_addr
= other
->clone(other
),
1112 .ipcomp
= IPCOMP_NONE
,
1113 .state
= CHILD_CREATED
,
1114 .my_ts
= linked_list_create(),
1115 .other_ts
= linked_list_create(),
1116 .protocol
= PROTO_NONE
,
1117 .mode
= MODE_TUNNEL
,
1118 .close_action
= config
->get_close_action(config
),
1119 .dpd_action
= config
->get_dpd_action(config
),
1120 .reqid
= config
->get_reqid(config
),
1121 .mark_in
= config
->get_mark(config
, TRUE
),
1122 .mark_out
= config
->get_mark(config
, FALSE
),
1125 this->config
= config
;
1126 config
->get_ref(config
);
1130 /* reuse old reqid if we are rekeying an existing CHILD_SA */
1131 this->reqid
= rekey ? rekey
: ++reqid
;
1134 if (this->mark_in
.value
== MARK_REQID
)
1136 this->mark_in
.value
= this->reqid
;
1138 if (this->mark_out
.value
== MARK_REQID
)
1140 this->mark_out
.value
= this->reqid
;
1143 /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
1144 if (config
->get_mode(config
) == MODE_TRANSPORT
&&
1145 config
->use_proxy_mode(config
))
1151 enumerator_t
*enumerator
;
1152 linked_list_t
*my_ts_list
, *other_ts_list
, *list
;
1153 traffic_selector_t
*my_ts
, *other_ts
;
1155 this->mode
= MODE_TRANSPORT
;
1157 list
= linked_list_create_with_items(me
, NULL
);
1158 my_ts_list
= config
->get_traffic_selectors(config
, TRUE
, NULL
, list
);
1159 list
->destroy(list
);
1160 enumerator
= my_ts_list
->create_enumerator(my_ts_list
);
1161 if (enumerator
->enumerate(enumerator
, &my_ts
))
1163 if (my_ts
->is_host(my_ts
, NULL
) &&
1164 !my_ts
->is_host(my_ts
, this->my_addr
))
1166 type
= my_ts
->get_type(my_ts
);
1167 family
= (type
== TS_IPV4_ADDR_RANGE
) ? AF_INET
: AF_INET6
;
1168 addr
= my_ts
->get_from_address(my_ts
);
1169 host
= host_create_from_chunk(family
, addr
, 0);
1171 DBG1(DBG_CHD
, "my address: %H is a transport mode proxy for %H",
1172 this->my_addr
, host
);
1173 this->my_addr
->destroy(this->my_addr
);
1174 this->my_addr
= host
;
1177 enumerator
->destroy(enumerator
);
1178 my_ts_list
->destroy_offset(my_ts_list
, offsetof(traffic_selector_t
, destroy
));
1180 list
= linked_list_create_with_items(other
, NULL
);
1181 other_ts_list
= config
->get_traffic_selectors(config
, FALSE
, NULL
, list
);
1182 list
->destroy(list
);
1183 enumerator
= other_ts_list
->create_enumerator(other_ts_list
);
1184 if (enumerator
->enumerate(enumerator
, &other_ts
))
1186 if (other_ts
->is_host(other_ts
, NULL
) &&
1187 !other_ts
->is_host(other_ts
, this->other_addr
))
1189 type
= other_ts
->get_type(other_ts
);
1190 family
= (type
== TS_IPV4_ADDR_RANGE
) ? AF_INET
: AF_INET6
;
1191 addr
= other_ts
->get_from_address(other_ts
);
1192 host
= host_create_from_chunk(family
, addr
, 0);
1194 DBG1(DBG_CHD
, "other address: %H is a transport mode proxy for %H",
1195 this->other_addr
, host
);
1196 this->other_addr
->destroy(this->other_addr
);
1197 this->other_addr
= host
;
1200 enumerator
->destroy(enumerator
);
1201 other_ts_list
->destroy_offset(other_ts_list
, offsetof(traffic_selector_t
, destroy
));
1204 return &this->public;