2 * Coypright (C) 2016 Andreas Steffen
3 * Copyright (C) 2006-2016 Tobias Brunner
4 * Copyright (C) 2005-2008 Martin Willi
5 * Copyright (C) 2006 Daniel Roethlisberger
6 * Copyright (C) 2005 Jan Hutter
7 * HSR Hochschule fuer Technik Rapperswil
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
28 #include <collections/array.h>
30 ENUM(child_sa_state_names
, CHILD_CREATED
, CHILD_DESTROYING
,
43 typedef struct private_child_sa_t private_child_sa_t
;
46 * Private data of a child_sa_t object.
48 struct private_child_sa_t
{
50 * Public interface of child_sa_t.
65 * our actually used SPI, 0 if unused
70 * others used SPI, 0 if unused
75 * our Compression Parameter Index (CPI) used, 0 if unused
80 * others Compression Parameter Index (CPI) used, 0 if unused
85 * Array for local traffic selectors
90 * Array for remote traffic selectors
95 * Protocol used to protect this SA, ESP|AH
97 protocol_id_t protocol
;
100 * reqid used for this child_sa
105 * Did we allocate/confirm and must release the reqid?
107 bool reqid_allocated
;
110 * Is the reqid statically configured
115 * Unique CHILD_SA identifier
120 * inbound mark used for this child_sa
125 * outbound mark used for this child_sa
130 * absolute time when rekeying is scheduled
135 * absolute time when the SA expires
140 * absolute time when SA has been installed
145 * state of the CHILD_SA
147 child_sa_state_t state
;
150 * TRUE if this CHILD_SA is used to install trap policies
155 * Specifies if UDP encapsulation is enabled (NAT traversal)
160 * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
162 ipcomp_transform_t ipcomp
;
165 * mode this SA uses, tunnel/transport
170 * Action to enforce if peer closes the CHILD_SA
172 action_t close_action
;
175 * Action to enforce if peer is considered dead
182 proposal_t
*proposal
;
185 * config used to create this child
190 * time of last use in seconds (inbound)
195 * time of last use in seconds (outbound)
197 time_t other_usetime
;
200 * last number of inbound bytes
202 uint64_t my_usebytes
;
205 * last number of outbound bytes
207 uint64_t other_usebytes
;
210 * last number of inbound packets
212 uint64_t my_usepackets
;
215 * last number of outbound bytes
217 uint64_t other_usepackets
;
221 * convert an IKEv2 specific protocol identifier to the IP protocol identifier.
223 static inline uint8_t proto_ike2ip(protocol_id_t protocol
)
236 METHOD(child_sa_t
, get_name
, char*,
237 private_child_sa_t
*this)
239 return this->config
->get_name(this->config
);
242 METHOD(child_sa_t
, get_reqid
, uint32_t,
243 private_child_sa_t
*this)
248 METHOD(child_sa_t
, get_unique_id
, uint32_t,
249 private_child_sa_t
*this)
251 return this->unique_id
;
254 METHOD(child_sa_t
, get_config
, child_cfg_t
*,
255 private_child_sa_t
*this)
260 METHOD(child_sa_t
, set_state
, void,
261 private_child_sa_t
*this, child_sa_state_t state
)
263 charon
->bus
->child_state_change(charon
->bus
, &this->public, state
);
267 METHOD(child_sa_t
, get_state
, child_sa_state_t
,
268 private_child_sa_t
*this)
273 METHOD(child_sa_t
, get_spi
, uint32_t,
274 private_child_sa_t
*this, bool inbound
)
276 return inbound ?
this->my_spi
: this->other_spi
;
279 METHOD(child_sa_t
, get_cpi
, uint16_t,
280 private_child_sa_t
*this, bool inbound
)
282 return inbound ?
this->my_cpi
: this->other_cpi
;
285 METHOD(child_sa_t
, get_protocol
, protocol_id_t
,
286 private_child_sa_t
*this)
288 return this->protocol
;
291 METHOD(child_sa_t
, set_protocol
, void,
292 private_child_sa_t
*this, protocol_id_t protocol
)
294 this->protocol
= protocol
;
297 METHOD(child_sa_t
, get_mode
, ipsec_mode_t
,
298 private_child_sa_t
*this)
303 METHOD(child_sa_t
, set_mode
, void,
304 private_child_sa_t
*this, ipsec_mode_t mode
)
309 METHOD(child_sa_t
, has_encap
, bool,
310 private_child_sa_t
*this)
315 METHOD(child_sa_t
, get_ipcomp
, ipcomp_transform_t
,
316 private_child_sa_t
*this)
321 METHOD(child_sa_t
, set_ipcomp
, void,
322 private_child_sa_t
*this, ipcomp_transform_t ipcomp
)
324 this->ipcomp
= ipcomp
;
327 METHOD(child_sa_t
, set_close_action
, void,
328 private_child_sa_t
*this, action_t action
)
330 this->close_action
= action
;
333 METHOD(child_sa_t
, get_close_action
, action_t
,
334 private_child_sa_t
*this)
336 return this->close_action
;
339 METHOD(child_sa_t
, set_dpd_action
, void,
340 private_child_sa_t
*this, action_t action
)
342 this->dpd_action
= action
;
345 METHOD(child_sa_t
, get_dpd_action
, action_t
,
346 private_child_sa_t
*this)
348 return this->dpd_action
;
351 METHOD(child_sa_t
, get_proposal
, proposal_t
*,
352 private_child_sa_t
*this)
354 return this->proposal
;
357 METHOD(child_sa_t
, set_proposal
, void,
358 private_child_sa_t
*this, proposal_t
*proposal
)
360 this->proposal
= proposal
->clone(proposal
);
363 METHOD(child_sa_t
, create_ts_enumerator
, enumerator_t
*,
364 private_child_sa_t
*this, bool local
)
368 return array_create_enumerator(this->my_ts
);
370 return array_create_enumerator(this->other_ts
);
373 typedef struct policy_enumerator_t policy_enumerator_t
;
376 * Private policy enumerator
378 struct policy_enumerator_t
{
379 /** implements enumerator_t */
381 /** enumerator over own TS */
383 /** enumerator over others TS */
385 /** array of others TS, to recreate enumerator */
387 /** currently enumerating TS for "me" side */
388 traffic_selector_t
*ts
;
391 METHOD(enumerator_t
, policy_enumerate
, bool,
392 policy_enumerator_t
*this, traffic_selector_t
**my_out
,
393 traffic_selector_t
**other_out
)
395 traffic_selector_t
*other_ts
;
397 while (this->ts
|| this->mine
->enumerate(this->mine
, &this->ts
))
399 if (!this->other
->enumerate(this->other
, &other_ts
))
400 { /* end of others list, restart with new of mine */
401 this->other
->destroy(this->other
);
402 this->other
= array_create_enumerator(this->array
);
406 if (this->ts
->get_type(this->ts
) != other_ts
->get_type(other_ts
))
407 { /* family mismatch */
410 if (this->ts
->get_protocol(this->ts
) &&
411 other_ts
->get_protocol(other_ts
) &&
412 this->ts
->get_protocol(this->ts
) != other_ts
->get_protocol(other_ts
))
413 { /* protocol mismatch */
422 *other_out
= other_ts
;
429 METHOD(enumerator_t
, policy_destroy
, void,
430 policy_enumerator_t
*this)
432 this->mine
->destroy(this->mine
);
433 this->other
->destroy(this->other
);
437 METHOD(child_sa_t
, create_policy_enumerator
, enumerator_t
*,
438 private_child_sa_t
*this)
440 policy_enumerator_t
*e
;
444 .enumerate
= (void*)_policy_enumerate
,
445 .destroy
= _policy_destroy
,
447 .mine
= array_create_enumerator(this->my_ts
),
448 .other
= array_create_enumerator(this->other_ts
),
449 .array
= this->other_ts
,
457 * update the cached usebytes
458 * returns SUCCESS if the usebytes have changed, FAILED if not or no SPIs
459 * are available, and NOT_SUPPORTED if the kernel interface does not support
460 * querying the usebytes.
462 static status_t
update_usebytes(private_child_sa_t
*this, bool inbound
)
464 status_t status
= FAILED
;
465 uint64_t bytes
, packets
;
472 kernel_ipsec_sa_id_t id
= {
473 .src
= this->other_addr
,
474 .dst
= this->my_addr
,
476 .proto
= proto_ike2ip(this->protocol
),
477 .mark
= this->mark_in
,
479 kernel_ipsec_query_sa_t query
= {};
481 status
= charon
->kernel
->query_sa(charon
->kernel
, &id
, &query
,
482 &bytes
, &packets
, &time
);
483 if (status
== SUCCESS
)
485 if (bytes
> this->my_usebytes
)
487 this->my_usebytes
= bytes
;
488 this->my_usepackets
= packets
;
491 this->my_usetime
= time
;
503 kernel_ipsec_sa_id_t id
= {
504 .src
= this->my_addr
,
505 .dst
= this->other_addr
,
506 .spi
= this->other_spi
,
507 .proto
= proto_ike2ip(this->protocol
),
508 .mark
= this->mark_out
,
510 kernel_ipsec_query_sa_t query
= {};
512 status
= charon
->kernel
->query_sa(charon
->kernel
, &id
, &query
,
513 &bytes
, &packets
, &time
);
514 if (status
== SUCCESS
)
516 if (bytes
> this->other_usebytes
)
518 this->other_usebytes
= bytes
;
519 this->other_usepackets
= packets
;
522 this->other_usetime
= time
;
534 * updates the cached usetime
536 static bool update_usetime(private_child_sa_t
*this, bool inbound
)
538 enumerator_t
*enumerator
;
539 traffic_selector_t
*my_ts
, *other_ts
;
542 enumerator
= create_policy_enumerator(this);
543 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
549 kernel_ipsec_policy_id_t id
= {
553 .mark
= this->mark_in
,
555 kernel_ipsec_query_policy_t query
= {};
557 if (charon
->kernel
->query_policy(charon
->kernel
, &id
, &query
,
560 last_use
= max(last_use
, in
);
562 if (this->mode
!= MODE_TRANSPORT
)
565 if (charon
->kernel
->query_policy(charon
->kernel
, &id
, &query
,
568 last_use
= max(last_use
, fwd
);
574 kernel_ipsec_policy_id_t id
= {
578 .mark
= this->mark_out
,
580 kernel_ipsec_query_policy_t query
= {};
582 if (charon
->kernel
->query_policy(charon
->kernel
, &id
, &query
,
585 last_use
= max(last_use
, out
);
589 enumerator
->destroy(enumerator
);
597 this->my_usetime
= last_use
;
601 this->other_usetime
= last_use
;
606 METHOD(child_sa_t
, get_usestats
, void,
607 private_child_sa_t
*this, bool inbound
,
608 time_t *time
, uint64_t *bytes
, uint64_t *packets
)
610 if ((!bytes
&& !packets
) || update_usebytes(this, inbound
) != FAILED
)
612 /* there was traffic since last update or the kernel interface
613 * does not support querying the number of usebytes.
617 if (!update_usetime(this, inbound
) && !bytes
&& !packets
)
619 /* if policy query did not yield a usetime, query SAs instead */
620 update_usebytes(this, inbound
);
626 *time
= inbound ?
this->my_usetime
: this->other_usetime
;
630 *bytes
= inbound ?
this->my_usebytes
: this->other_usebytes
;
634 *packets
= inbound ?
this->my_usepackets
: this->other_usepackets
;
638 METHOD(child_sa_t
, get_mark
, mark_t
,
639 private_child_sa_t
*this, bool inbound
)
643 return this->mark_in
;
645 return this->mark_out
;
648 METHOD(child_sa_t
, get_lifetime
, time_t,
649 private_child_sa_t
*this, bool hard
)
651 return hard ?
this->expire_time
: this->rekey_time
;
654 METHOD(child_sa_t
, get_installtime
, time_t,
655 private_child_sa_t
*this)
657 return this->install_time
;
660 METHOD(child_sa_t
, alloc_spi
, uint32_t,
661 private_child_sa_t
*this, protocol_id_t protocol
)
663 if (charon
->kernel
->get_spi(charon
->kernel
, this->other_addr
, this->my_addr
,
664 proto_ike2ip(protocol
), &this->my_spi
) == SUCCESS
)
666 /* if we allocate a SPI, but then are unable to establish the SA, we
667 * need to know the protocol family to delete the partial SA */
668 this->protocol
= protocol
;
674 METHOD(child_sa_t
, alloc_cpi
, uint16_t,
675 private_child_sa_t
*this)
677 if (charon
->kernel
->get_cpi(charon
->kernel
, this->other_addr
, this->my_addr
,
678 &this->my_cpi
) == SUCCESS
)
685 METHOD(child_sa_t
, install
, status_t
,
686 private_child_sa_t
*this, chunk_t encr
, chunk_t integ
, uint32_t spi
,
687 uint16_t cpi
, bool initiator
, bool inbound
, bool tfcv3
,
688 linked_list_t
*my_ts
, linked_list_t
*other_ts
)
690 uint16_t enc_alg
= ENCR_UNDEFINED
, int_alg
= AUTH_UNDEFINED
, size
;
691 uint16_t esn
= NO_EXT_SEQ_NUMBERS
;
692 linked_list_t
*src_ts
= NULL
, *dst_ts
= NULL
;
694 kernel_ipsec_sa_id_t id
;
695 kernel_ipsec_add_sa_t sa
;
696 lifetime_cfg_t
*lifetime
;
702 /* now we have to decide which spi to use. Use self allocated, if "in",
703 * or the one in the proposal, if not "in" (others). Additionally,
704 * source and dest host switch depending on the role */
708 src
= this->other_addr
;
709 if (this->my_spi
== spi
)
710 { /* alloc_spi has been called, do an SA update */
719 dst
= this->other_addr
;
720 this->other_spi
= spi
;
721 this->other_cpi
= cpi
;
725 tfc
= this->config
->get_tfc(this->config
);
729 DBG2(DBG_CHD
, "adding %s %N SA", inbound ?
"inbound" : "outbound",
730 protocol_id_names
, this->protocol
);
732 /* send SA down to the kernel */
733 DBG2(DBG_CHD
, " SPI 0x%.8x, src %H dst %H", ntohl(spi
), src
, dst
);
735 this->proposal
->get_algorithm(this->proposal
, ENCRYPTION_ALGORITHM
,
737 this->proposal
->get_algorithm(this->proposal
, INTEGRITY_ALGORITHM
,
739 this->proposal
->get_algorithm(this->proposal
, EXTENDED_SEQUENCE_NUMBERS
,
742 if (!this->reqid_allocated
&& !this->static_reqid
)
744 status
= charon
->kernel
->alloc_reqid(charon
->kernel
, my_ts
, other_ts
,
745 this->mark_in
, this->mark_out
, &this->reqid
);
746 if (status
!= SUCCESS
)
750 this->reqid_allocated
= TRUE
;
753 lifetime
= this->config
->get_lifetime(this->config
);
755 now
= time_monotonic(NULL
);
756 if (lifetime
->time
.rekey
)
758 if (this->rekey_time
)
760 this->rekey_time
= min(this->rekey_time
, now
+ lifetime
->time
.rekey
);
764 this->rekey_time
= now
+ lifetime
->time
.rekey
;
767 if (lifetime
->time
.life
)
769 this->expire_time
= now
+ lifetime
->time
.life
;
772 if (!lifetime
->time
.jitter
&& !inbound
)
773 { /* avoid triggering multiple rekey events */
774 lifetime
->time
.rekey
= 0;
777 /* BEET requires the bound address from the traffic selectors */
789 id
= (kernel_ipsec_sa_id_t
){
793 .proto
= proto_ike2ip(this->protocol
),
794 .mark
= inbound ?
this->mark_in
: this->mark_out
,
796 sa
= (kernel_ipsec_add_sa_t
){
797 .reqid
= this->reqid
,
801 .lifetime
= lifetime
,
806 .replay_window
= this->config
->get_replay_window(this->config
),
808 .ipcomp
= this->ipcomp
,
810 .encap
= this->encap
,
812 .initiator
= initiator
,
817 status
= charon
->kernel
->add_sa(charon
->kernel
, &id
, &sa
);
825 * Check kernel interface if policy updates are required
827 static bool require_policy_update()
831 f
= charon
->kernel
->get_features(charon
->kernel
);
832 return !(f
& KERNEL_NO_POLICY_UPDATES
);
836 * Prepare SA config to install/delete policies
838 static void prepare_sa_cfg(private_child_sa_t
*this, ipsec_sa_cfg_t
*my_sa
,
839 ipsec_sa_cfg_t
*other_sa
)
841 enumerator_t
*enumerator
;
843 *my_sa
= (ipsec_sa_cfg_t
){
845 .reqid
= this->reqid
,
847 .transform
= this->ipcomp
,
852 my_sa
->ipcomp
.cpi
= this->my_cpi
;
853 other_sa
->ipcomp
.cpi
= this->other_cpi
;
855 if (this->protocol
== PROTO_ESP
)
857 my_sa
->esp
.use
= TRUE
;
858 my_sa
->esp
.spi
= this->my_spi
;
859 other_sa
->esp
.use
= TRUE
;
860 other_sa
->esp
.spi
= this->other_spi
;
864 my_sa
->ah
.use
= TRUE
;
865 my_sa
->ah
.spi
= this->my_spi
;
866 other_sa
->ah
.use
= TRUE
;
867 other_sa
->ah
.spi
= this->other_spi
;
870 enumerator
= create_policy_enumerator(this);
871 while (enumerator
->enumerate(enumerator
, NULL
, NULL
))
873 my_sa
->policy_count
++;
874 other_sa
->policy_count
++;
876 enumerator
->destroy(enumerator
);
880 * Install 3 policies: out, in and forward
882 static status_t
install_policies_internal(private_child_sa_t
*this,
883 host_t
*my_addr
, host_t
*other_addr
, traffic_selector_t
*my_ts
,
884 traffic_selector_t
*other_ts
, ipsec_sa_cfg_t
*my_sa
,
885 ipsec_sa_cfg_t
*other_sa
, policy_type_t type
,
886 policy_priority_t priority
, uint32_t manual_prio
)
888 kernel_ipsec_policy_id_t out_id
= {
892 .mark
= this->mark_out
,
897 .mark
= this->mark_in
,
899 kernel_ipsec_manage_policy_t out_policy
= {
902 .manual_prio
= manual_prio
,
909 .manual_prio
= manual_prio
,
914 status_t status
= SUCCESS
;
916 status
|= charon
->kernel
->add_policy(charon
->kernel
, &out_id
, &out_policy
);
917 status
|= charon
->kernel
->add_policy(charon
->kernel
, &in_id
, &in_policy
);
918 if (this->mode
!= MODE_TRANSPORT
)
920 in_id
.dir
= POLICY_FWD
;
921 status
|= charon
->kernel
->add_policy(charon
->kernel
, &in_id
, &in_policy
);
923 /* install an "outbound" FWD policy in case there is a drop policy
924 * matching outbound forwarded traffic, to allow another tunnel to use
925 * the reversed subnets and do the same we don't set a reqid (this also
926 * allows the kernel backend to distinguish between the two types of
928 out_id
.dir
= POLICY_FWD
;
930 status
|= charon
->kernel
->add_policy(charon
->kernel
, &out_id
, &out_policy
);
931 /* reset the reqid for any other further policies */
932 other_sa
->reqid
= this->reqid
;
938 * Delete 3 policies: out, in and forward
940 static void del_policies_internal(private_child_sa_t
*this,
941 host_t
*my_addr
, host_t
*other_addr
, traffic_selector_t
*my_ts
,
942 traffic_selector_t
*other_ts
, ipsec_sa_cfg_t
*my_sa
,
943 ipsec_sa_cfg_t
*other_sa
, policy_type_t type
,
944 policy_priority_t priority
, uint32_t manual_prio
)
946 kernel_ipsec_policy_id_t out_id
= {
950 .mark
= this->mark_out
,
955 .mark
= this->mark_in
,
957 kernel_ipsec_manage_policy_t out_policy
= {
960 .manual_prio
= manual_prio
,
967 .manual_prio
= manual_prio
,
973 charon
->kernel
->del_policy(charon
->kernel
, &out_id
, &out_policy
);
974 charon
->kernel
->del_policy(charon
->kernel
, &in_id
, &in_policy
);
975 if (this->mode
!= MODE_TRANSPORT
)
977 in_id
.dir
= POLICY_FWD
;
978 charon
->kernel
->del_policy(charon
->kernel
, &in_id
, &in_policy
);
980 out_id
.dir
= POLICY_FWD
;
982 charon
->kernel
->del_policy(charon
->kernel
, &out_id
, &out_policy
);
983 other_sa
->reqid
= this->reqid
;
987 METHOD(child_sa_t
, add_policies
, status_t
,
988 private_child_sa_t
*this, linked_list_t
*my_ts_list
,
989 linked_list_t
*other_ts_list
)
991 enumerator_t
*enumerator
;
992 traffic_selector_t
*my_ts
, *other_ts
;
993 status_t status
= SUCCESS
;
995 if (!this->reqid_allocated
&& !this->static_reqid
)
997 /* trap policy, get or confirm reqid */
998 status
= charon
->kernel
->alloc_reqid(
999 charon
->kernel
, my_ts_list
, other_ts_list
,
1000 this->mark_in
, this->mark_out
, &this->reqid
);
1001 if (status
!= SUCCESS
)
1005 this->reqid_allocated
= TRUE
;
1008 /* apply traffic selectors */
1009 enumerator
= my_ts_list
->create_enumerator(my_ts_list
);
1010 while (enumerator
->enumerate(enumerator
, &my_ts
))
1012 array_insert(this->my_ts
, ARRAY_TAIL
, my_ts
->clone(my_ts
));
1014 enumerator
->destroy(enumerator
);
1015 array_sort(this->my_ts
, (void*)traffic_selector_cmp
, NULL
);
1017 enumerator
= other_ts_list
->create_enumerator(other_ts_list
);
1018 while (enumerator
->enumerate(enumerator
, &other_ts
))
1020 array_insert(this->other_ts
, ARRAY_TAIL
, other_ts
->clone(other_ts
));
1022 enumerator
->destroy(enumerator
);
1023 array_sort(this->other_ts
, (void*)traffic_selector_cmp
, NULL
);
1025 if (this->config
->install_policy(this->config
))
1027 policy_priority_t priority
;
1028 ipsec_sa_cfg_t my_sa
, other_sa
;
1029 uint32_t manual_prio
;
1031 prepare_sa_cfg(this, &my_sa
, &other_sa
);
1032 manual_prio
= this->config
->get_manual_prio(this->config
);
1034 /* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
1035 * entry) we install a trap policy */
1036 this->trap
= this->state
== CHILD_CREATED
;
1037 priority
= this->trap ? POLICY_PRIORITY_ROUTED
1038 : POLICY_PRIORITY_DEFAULT
;
1040 /* enumerate pairs of traffic selectors */
1041 enumerator
= create_policy_enumerator(this);
1042 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
1044 /* install outbound drop policy to avoid packets leaving unencrypted
1045 * when updating policies */
1046 if (priority
== POLICY_PRIORITY_DEFAULT
&& manual_prio
== 0 &&
1047 require_policy_update())
1049 status
|= install_policies_internal(this, this->my_addr
,
1050 this->other_addr
, my_ts
, other_ts
,
1051 &my_sa
, &other_sa
, POLICY_DROP
,
1052 POLICY_PRIORITY_FALLBACK
, 0);
1055 /* install policies */
1056 status
|= install_policies_internal(this, this->my_addr
,
1057 this->other_addr
, my_ts
, other_ts
,
1058 &my_sa
, &other_sa
, POLICY_IPSEC
,
1059 priority
, manual_prio
);
1061 if (status
!= SUCCESS
)
1066 enumerator
->destroy(enumerator
);
1069 if (status
== SUCCESS
&& this->trap
)
1071 set_state(this, CHILD_ROUTED
);
1077 * Callback to reinstall a virtual IP
1079 static void reinstall_vip(host_t
*vip
, host_t
*me
)
1083 if (charon
->kernel
->get_interface(charon
->kernel
, me
, &iface
))
1085 charon
->kernel
->del_ip(charon
->kernel
, vip
, -1, TRUE
);
1086 charon
->kernel
->add_ip(charon
->kernel
, vip
, -1, iface
);
1091 METHOD(child_sa_t
, update
, status_t
,
1092 private_child_sa_t
*this, host_t
*me
, host_t
*other
, linked_list_t
*vips
,
1095 child_sa_state_t old
;
1096 bool transport_proxy_mode
;
1098 /* anything changed at all? */
1099 if (me
->equals(me
, this->my_addr
) &&
1100 other
->equals(other
, this->other_addr
) && this->encap
== encap
)
1106 set_state(this, CHILD_UPDATING
);
1107 transport_proxy_mode
= this->config
->use_proxy_mode(this->config
) &&
1108 this->mode
== MODE_TRANSPORT
;
1110 if (!transport_proxy_mode
)
1112 /* update our (initiator) SA */
1115 kernel_ipsec_sa_id_t id
= {
1116 .src
= this->other_addr
,
1117 .dst
= this->my_addr
,
1118 .spi
= this->my_spi
,
1119 .proto
= proto_ike2ip(this->protocol
),
1120 .mark
= this->mark_in
,
1122 kernel_ipsec_update_sa_t sa
= {
1123 .cpi
= this->ipcomp
!= IPCOMP_NONE ?
this->my_cpi
: 0,
1126 .encap
= this->encap
,
1129 if (charon
->kernel
->update_sa(charon
->kernel
, &id
,
1130 &sa
) == NOT_SUPPORTED
)
1132 set_state(this, old
);
1133 return NOT_SUPPORTED
;
1137 /* update his (responder) SA */
1138 if (this->other_spi
)
1140 kernel_ipsec_sa_id_t id
= {
1141 .src
= this->my_addr
,
1142 .dst
= this->other_addr
,
1143 .spi
= this->other_spi
,
1144 .proto
= proto_ike2ip(this->protocol
),
1145 .mark
= this->mark_out
,
1147 kernel_ipsec_update_sa_t sa
= {
1148 .cpi
= this->ipcomp
!= IPCOMP_NONE ?
this->other_cpi
: 0,
1151 .encap
= this->encap
,
1154 if (charon
->kernel
->update_sa(charon
->kernel
, &id
,
1155 &sa
) == NOT_SUPPORTED
)
1157 set_state(this, old
);
1158 return NOT_SUPPORTED
;
1163 if (this->config
->install_policy(this->config
) && require_policy_update())
1165 if (!me
->ip_equals(me
, this->my_addr
) ||
1166 !other
->ip_equals(other
, this->other_addr
))
1168 ipsec_sa_cfg_t my_sa
, other_sa
;
1169 enumerator_t
*enumerator
;
1170 traffic_selector_t
*my_ts
, *other_ts
;
1171 uint32_t manual_prio
;
1173 prepare_sa_cfg(this, &my_sa
, &other_sa
);
1174 manual_prio
= this->config
->get_manual_prio(this->config
);
1176 /* always use high priorities, as hosts getting updated are INSTALLED */
1177 enumerator
= create_policy_enumerator(this);
1178 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
1180 traffic_selector_t
*old_my_ts
= NULL
, *old_other_ts
= NULL
;
1182 /* remove old policies first */
1183 del_policies_internal(this, this->my_addr
, this->other_addr
,
1184 my_ts
, other_ts
, &my_sa
, &other_sa
, POLICY_IPSEC
,
1185 POLICY_PRIORITY_DEFAULT
, manual_prio
);
1187 /* check if we have to update a "dynamic" traffic selector */
1188 if (!me
->ip_equals(me
, this->my_addr
) &&
1189 my_ts
->is_host(my_ts
, this->my_addr
))
1191 old_my_ts
= my_ts
->clone(my_ts
);
1192 my_ts
->set_address(my_ts
, me
);
1194 if (!other
->ip_equals(other
, this->other_addr
) &&
1195 other_ts
->is_host(other_ts
, this->other_addr
))
1197 old_other_ts
= other_ts
->clone(other_ts
);
1198 other_ts
->set_address(other_ts
, other
);
1201 /* we reinstall the virtual IP to handle interface roaming
1203 vips
->invoke_function(vips
, (void*)reinstall_vip
, me
);
1205 /* reinstall updated policies */
1206 install_policies_internal(this, me
, other
, my_ts
, other_ts
,
1207 &my_sa
, &other_sa
, POLICY_IPSEC
,
1208 POLICY_PRIORITY_DEFAULT
, manual_prio
);
1210 /* update fallback policies after the new policy is in place */
1211 if (manual_prio
== 0)
1213 del_policies_internal(this, this->my_addr
, this->other_addr
,
1215 old_other_ts ?
: other_ts
,
1216 &my_sa
, &other_sa
, POLICY_DROP
,
1217 POLICY_PRIORITY_FALLBACK
, 0);
1218 install_policies_internal(this, me
, other
, my_ts
, other_ts
,
1219 &my_sa
, &other_sa
, POLICY_DROP
,
1220 POLICY_PRIORITY_FALLBACK
, 0);
1222 DESTROY_IF(old_my_ts
);
1223 DESTROY_IF(old_other_ts
);
1225 enumerator
->destroy(enumerator
);
1229 if (!transport_proxy_mode
)
1232 if (!me
->equals(me
, this->my_addr
))
1234 this->my_addr
->destroy(this->my_addr
);
1235 this->my_addr
= me
->clone(me
);
1237 if (!other
->equals(other
, this->other_addr
))
1239 this->other_addr
->destroy(this->other_addr
);
1240 this->other_addr
= other
->clone(other
);
1244 this->encap
= encap
;
1245 set_state(this, old
);
1250 METHOD(child_sa_t
, destroy
, void,
1251 private_child_sa_t
*this)
1253 enumerator_t
*enumerator
;
1254 traffic_selector_t
*my_ts
, *other_ts
;
1255 policy_priority_t priority
;
1257 priority
= this->trap ? POLICY_PRIORITY_ROUTED
: POLICY_PRIORITY_DEFAULT
;
1259 set_state(this, CHILD_DESTROYING
);
1261 if (this->config
->install_policy(this->config
))
1263 ipsec_sa_cfg_t my_sa
, other_sa
;
1264 uint32_t manual_prio
;
1266 prepare_sa_cfg(this, &my_sa
, &other_sa
);
1267 manual_prio
= this->config
->get_manual_prio(this->config
);
1269 /* delete all policies in the kernel */
1270 enumerator
= create_policy_enumerator(this);
1271 while (enumerator
->enumerate(enumerator
, &my_ts
, &other_ts
))
1273 del_policies_internal(this, this->my_addr
, this->other_addr
,
1274 my_ts
, other_ts
, &my_sa
, &other_sa
,
1275 POLICY_IPSEC
, priority
, manual_prio
);
1276 if (priority
== POLICY_PRIORITY_DEFAULT
&& manual_prio
== 0 &&
1277 require_policy_update())
1279 del_policies_internal(this, this->my_addr
, this->other_addr
,
1280 my_ts
, other_ts
, &my_sa
, &other_sa
,
1281 POLICY_DROP
, POLICY_PRIORITY_FALLBACK
, 0);
1284 enumerator
->destroy(enumerator
);
1287 /* delete SAs in the kernel, if they are set up */
1290 kernel_ipsec_sa_id_t id
= {
1291 .src
= this->other_addr
,
1292 .dst
= this->my_addr
,
1293 .spi
= this->my_spi
,
1294 .proto
= proto_ike2ip(this->protocol
),
1295 .mark
= this->mark_in
,
1297 kernel_ipsec_del_sa_t sa
= {
1298 .cpi
= this->my_cpi
,
1300 charon
->kernel
->del_sa(charon
->kernel
, &id
, &sa
);
1302 if (this->other_spi
)
1304 kernel_ipsec_sa_id_t id
= {
1305 .src
= this->my_addr
,
1306 .dst
= this->other_addr
,
1307 .spi
= this->other_spi
,
1308 .proto
= proto_ike2ip(this->protocol
),
1309 .mark
= this->mark_out
,
1311 kernel_ipsec_del_sa_t sa
= {
1312 .cpi
= this->other_cpi
,
1314 charon
->kernel
->del_sa(charon
->kernel
, &id
, &sa
);
1317 if (this->reqid_allocated
)
1319 if (charon
->kernel
->release_reqid(charon
->kernel
,
1320 this->reqid
, this->mark_in
, this->mark_out
) != SUCCESS
)
1322 DBG1(DBG_CHD
, "releasing reqid %u failed", this->reqid
);
1326 array_destroy_offset(this->my_ts
, offsetof(traffic_selector_t
, destroy
));
1327 array_destroy_offset(this->other_ts
, offsetof(traffic_selector_t
, destroy
));
1328 this->my_addr
->destroy(this->my_addr
);
1329 this->other_addr
->destroy(this->other_addr
);
1330 DESTROY_IF(this->proposal
);
1331 this->config
->destroy(this->config
);
1336 * Get proxy address for one side, if any
1338 static host_t
* get_proxy_addr(child_cfg_t
*config
, host_t
*ike
, bool local
)
1340 host_t
*host
= NULL
;
1342 enumerator_t
*enumerator
;
1343 linked_list_t
*ts_list
, *list
;
1344 traffic_selector_t
*ts
;
1346 list
= linked_list_create_with_items(ike
, NULL
);
1347 ts_list
= config
->get_traffic_selectors(config
, local
, NULL
, list
);
1348 list
->destroy(list
);
1350 enumerator
= ts_list
->create_enumerator(ts_list
);
1351 while (enumerator
->enumerate(enumerator
, &ts
))
1353 if (ts
->is_host(ts
, NULL
) && ts
->to_subnet(ts
, &host
, &mask
))
1355 DBG1(DBG_CHD
, "%s address: %H is a transport mode proxy for %H",
1356 local ?
"my" : "other", ike
, host
);
1360 enumerator
->destroy(enumerator
);
1361 ts_list
->destroy_offset(ts_list
, offsetof(traffic_selector_t
, destroy
));
1365 host
= ike
->clone(ike
);
1371 * Described in header.
1373 child_sa_t
* child_sa_create(host_t
*me
, host_t
* other
,
1374 child_cfg_t
*config
, uint32_t rekey
, bool encap
,
1375 u_int mark_in
, u_int mark_out
)
1377 private_child_sa_t
*this;
1378 static refcount_t unique_id
= 0, unique_mark
= 0, mark
;
1382 .get_name
= _get_name
,
1383 .get_reqid
= _get_reqid
,
1384 .get_unique_id
= _get_unique_id
,
1385 .get_config
= _get_config
,
1386 .get_state
= _get_state
,
1387 .set_state
= _set_state
,
1388 .get_spi
= _get_spi
,
1389 .get_cpi
= _get_cpi
,
1390 .get_protocol
= _get_protocol
,
1391 .set_protocol
= _set_protocol
,
1392 .get_mode
= _get_mode
,
1393 .set_mode
= _set_mode
,
1394 .get_proposal
= _get_proposal
,
1395 .set_proposal
= _set_proposal
,
1396 .get_lifetime
= _get_lifetime
,
1397 .get_installtime
= _get_installtime
,
1398 .get_usestats
= _get_usestats
,
1399 .get_mark
= _get_mark
,
1400 .has_encap
= _has_encap
,
1401 .get_ipcomp
= _get_ipcomp
,
1402 .set_ipcomp
= _set_ipcomp
,
1403 .get_close_action
= _get_close_action
,
1404 .set_close_action
= _set_close_action
,
1405 .get_dpd_action
= _get_dpd_action
,
1406 .set_dpd_action
= _set_dpd_action
,
1407 .alloc_spi
= _alloc_spi
,
1408 .alloc_cpi
= _alloc_cpi
,
1409 .install
= _install
,
1411 .add_policies
= _add_policies
,
1412 .create_ts_enumerator
= _create_ts_enumerator
,
1413 .create_policy_enumerator
= _create_policy_enumerator
,
1414 .destroy
= _destroy
,
1417 .ipcomp
= IPCOMP_NONE
,
1418 .state
= CHILD_CREATED
,
1419 .my_ts
= array_create(0, 0),
1420 .other_ts
= array_create(0, 0),
1421 .protocol
= PROTO_NONE
,
1422 .mode
= MODE_TUNNEL
,
1423 .close_action
= config
->get_close_action(config
),
1424 .dpd_action
= config
->get_dpd_action(config
),
1425 .reqid
= config
->get_reqid(config
),
1426 .unique_id
= ref_get(&unique_id
),
1427 .mark_in
= config
->get_mark(config
, TRUE
),
1428 .mark_out
= config
->get_mark(config
, FALSE
),
1429 .install_time
= time_monotonic(NULL
),
1432 this->config
= config
;
1433 config
->get_ref(config
);
1437 this->mark_in
.value
= mark_in
;
1441 this->mark_out
.value
= mark_out
;
1443 if (this->mark_in
.value
== MARK_UNIQUE
||
1444 this->mark_out
.value
== MARK_UNIQUE
)
1446 mark
= ref_get(&unique_mark
);
1447 if (this->mark_in
.value
== MARK_UNIQUE
)
1449 this->mark_in
.value
= mark
;
1451 if (this->mark_out
.value
== MARK_UNIQUE
)
1453 this->mark_out
.value
= mark
;
1459 /* reuse old reqid if we are rekeying an existing CHILD_SA. While the
1460 * reqid cache would find the same reqid for our selectors, this does
1461 * not work in a special case: If an SA is triggered by a trap policy,
1462 * but the negotiated SA gets narrowed, we still must reuse the same
1463 * reqid to successfully "trigger" the SA on the kernel level. Rekeying
1464 * such an SA requires an explicit reqid, as the cache currently knows
1465 * the original selectors only for that reqid. */
1468 this->reqid
= rekey
;
1472 this->reqid
= charon
->traps
->find_reqid(charon
->traps
, config
);
1477 this->static_reqid
= TRUE
;
1480 /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
1481 if (config
->get_mode(config
) == MODE_TRANSPORT
&&
1482 config
->use_proxy_mode(config
))
1484 this->mode
= MODE_TRANSPORT
;
1486 this->my_addr
= get_proxy_addr(config
, me
, TRUE
);
1487 this->other_addr
= get_proxy_addr(config
, other
, FALSE
);
1491 this->my_addr
= me
->clone(me
);
1492 this->other_addr
= other
->clone(other
);
1494 return &this->public;