summaryrefslogtreecommitdiff
path: root/src/libcharon/sa
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa')
-rw-r--r--src/libcharon/sa/child_sa.c398
-rw-r--r--src/libcharon/sa/child_sa.h18
-rw-r--r--src/libcharon/sa/child_sa_manager.c14
-rw-r--r--src/libcharon/sa/child_sa_manager.h4
-rw-r--r--src/libcharon/sa/eap/eap_manager.c8
-rw-r--r--src/libcharon/sa/eap/eap_manager.h6
-rw-r--r--src/libcharon/sa/eap/eap_method.h6
-rw-r--r--src/libcharon/sa/ike_sa.c72
-rw-r--r--src/libcharon/sa/ike_sa.h48
-rw-r--r--src/libcharon/sa/ike_sa_id.c20
-rw-r--r--src/libcharon/sa/ike_sa_id.h14
-rw-r--r--src/libcharon/sa/ike_sa_manager.c94
-rw-r--r--src/libcharon/sa/ike_sa_manager.h4
-rw-r--r--src/libcharon/sa/ikev1/keymat_v1.c48
-rw-r--r--src/libcharon/sa/ikev1/keymat_v1.h8
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c100
-rw-r--r--src/libcharon/sa/ikev1/tasks/aggressive_mode.c17
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_delete.c2
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_dpd.c8
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_dpd.h2
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_natd.c4
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_vendor.c2
-rw-r--r--src/libcharon/sa/ikev1/tasks/main_mode.c22
-rw-r--r--src/libcharon/sa/ikev1/tasks/mode_config.c2
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_delete.c10
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_delete.h2
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c60
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.h6
-rw-r--r--src/libcharon/sa/ikev1/tasks/xauth.c2
-rw-r--r--src/libcharon/sa/ikev2/authenticators/eap_authenticator.c16
-rw-r--r--src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c4
-rw-r--r--src/libcharon/sa/ikev2/connect_manager.c34
-rw-r--r--src/libcharon/sa/ikev2/keymat_v2.c20
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c284
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.c74
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.h2
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_delete.c73
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_delete.h2
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_rekey.c146
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_rekey.h23
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_auth.c23
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_auth_lifetime.c8
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_delete.c62
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_init.c12
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_me.c2
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_mobike.c2
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_natd.c6
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_rekey.c261
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_rekey.h10
-rw-r--r--src/libcharon/sa/redirect_manager.c2
-rw-r--r--src/libcharon/sa/shunt_manager.c110
-rw-r--r--src/libcharon/sa/task_manager.h25
-rw-r--r--src/libcharon/sa/trap_manager.c26
-rw-r--r--src/libcharon/sa/trap_manager.h10
54 files changed, 1444 insertions, 794 deletions
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 56b7cb5a4..8a405d93c 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -1,9 +1,10 @@
/*
- * Copyright (C) 2006-2015 Tobias Brunner
+ * Coypright (C) 2016 Andreas Steffen
+ * Copyright (C) 2006-2016 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -63,22 +64,22 @@ struct private_child_sa_t {
/**
* our actually used SPI, 0 if unused
*/
- u_int32_t my_spi;
+ uint32_t my_spi;
/**
* others used SPI, 0 if unused
*/
- u_int32_t other_spi;
+ uint32_t other_spi;
/**
* our Compression Parameter Index (CPI) used, 0 if unused
*/
- u_int16_t my_cpi;
+ uint16_t my_cpi;
/**
* others Compression Parameter Index (CPI) used, 0 if unused
*/
- u_int16_t other_cpi;
+ uint16_t other_cpi;
/**
* Array for local traffic selectors
@@ -98,7 +99,7 @@ struct private_child_sa_t {
/**
* reqid used for this child_sa
*/
- u_int32_t reqid;
+ uint32_t reqid;
/**
* Did we allocate/confirm and must release the reqid?
@@ -113,7 +114,7 @@ struct private_child_sa_t {
/*
* Unique CHILD_SA identifier
*/
- u_int32_t unique_id;
+ uint32_t unique_id;
/**
* inbound mark used for this child_sa
@@ -198,28 +199,28 @@ struct private_child_sa_t {
/**
* last number of inbound bytes
*/
- u_int64_t my_usebytes;
+ uint64_t my_usebytes;
/**
* last number of outbound bytes
*/
- u_int64_t other_usebytes;
+ uint64_t other_usebytes;
/**
* last number of inbound packets
*/
- u_int64_t my_usepackets;
+ uint64_t my_usepackets;
/**
* last number of outbound bytes
*/
- u_int64_t other_usepackets;
+ uint64_t other_usepackets;
};
/**
* convert an IKEv2 specific protocol identifier to the IP protocol identifier.
*/
-static inline u_int8_t proto_ike2ip(protocol_id_t protocol)
+static inline uint8_t proto_ike2ip(protocol_id_t protocol)
{
switch (protocol)
{
@@ -238,13 +239,13 @@ METHOD(child_sa_t, get_name, char*,
return this->config->get_name(this->config);
}
-METHOD(child_sa_t, get_reqid, u_int32_t,
+METHOD(child_sa_t, get_reqid, uint32_t,
private_child_sa_t *this)
{
return this->reqid;
}
-METHOD(child_sa_t, get_unique_id, u_int32_t,
+METHOD(child_sa_t, get_unique_id, uint32_t,
private_child_sa_t *this)
{
return this->unique_id;
@@ -269,13 +270,13 @@ METHOD(child_sa_t, get_state, child_sa_state_t,
return this->state;
}
-METHOD(child_sa_t, get_spi, u_int32_t,
+METHOD(child_sa_t, get_spi, uint32_t,
private_child_sa_t *this, bool inbound)
{
return inbound ? this->my_spi : this->other_spi;
}
-METHOD(child_sa_t, get_cpi, u_int16_t,
+METHOD(child_sa_t, get_cpi, uint16_t,
private_child_sa_t *this, bool inbound)
{
return inbound ? this->my_cpi : this->other_cpi;
@@ -461,17 +462,24 @@ METHOD(child_sa_t, create_policy_enumerator, enumerator_t*,
static status_t update_usebytes(private_child_sa_t *this, bool inbound)
{
status_t status = FAILED;
- u_int64_t bytes, packets;
+ uint64_t bytes, packets;
time_t time;
if (inbound)
{
if (this->my_spi)
{
- status = charon->kernel->query_sa(charon->kernel, this->other_addr,
- this->my_addr, this->my_spi,
- proto_ike2ip(this->protocol), this->mark_in,
- &bytes, &packets, &time);
+ kernel_ipsec_sa_id_t id = {
+ .src = this->other_addr,
+ .dst = this->my_addr,
+ .spi = this->my_spi,
+ .proto = proto_ike2ip(this->protocol),
+ .mark = this->mark_in,
+ };
+ kernel_ipsec_query_sa_t query = {};
+
+ status = charon->kernel->query_sa(charon->kernel, &id, &query,
+ &bytes, &packets, &time);
if (status == SUCCESS)
{
if (bytes > this->my_usebytes)
@@ -492,10 +500,17 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
{
if (this->other_spi)
{
- status = charon->kernel->query_sa(charon->kernel, this->my_addr,
- this->other_addr, this->other_spi,
- proto_ike2ip(this->protocol), this->mark_out,
- &bytes, &packets, &time);
+ kernel_ipsec_sa_id_t id = {
+ .src = this->my_addr,
+ .dst = this->other_addr,
+ .spi = this->other_spi,
+ .proto = proto_ike2ip(this->protocol),
+ .mark = this->mark_out,
+ };
+ kernel_ipsec_query_sa_t query = {};
+
+ status = charon->kernel->query_sa(charon->kernel, &id, &query,
+ &bytes, &packets, &time);
if (status == SUCCESS)
{
if (bytes > this->other_usebytes)
@@ -531,15 +546,24 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
if (inbound)
{
- if (charon->kernel->query_policy(charon->kernel, other_ts,
- my_ts, POLICY_IN, this->mark_in, &in) == SUCCESS)
+ kernel_ipsec_policy_id_t id = {
+ .dir = POLICY_IN,
+ .src_ts = other_ts,
+ .dst_ts = my_ts,
+ .mark = this->mark_in,
+ };
+ kernel_ipsec_query_policy_t query = {};
+
+ if (charon->kernel->query_policy(charon->kernel, &id, &query,
+ &in) == SUCCESS)
{
last_use = max(last_use, in);
}
if (this->mode != MODE_TRANSPORT)
{
- if (charon->kernel->query_policy(charon->kernel, other_ts,
- my_ts, POLICY_FWD, this->mark_in, &fwd) == SUCCESS)
+ id.dir = POLICY_FWD;
+ if (charon->kernel->query_policy(charon->kernel, &id, &query,
+ &fwd) == SUCCESS)
{
last_use = max(last_use, fwd);
}
@@ -547,8 +571,17 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
}
else
{
- if (charon->kernel->query_policy(charon->kernel, my_ts,
- other_ts, POLICY_OUT, this->mark_out, &out) == SUCCESS)
+ kernel_ipsec_policy_id_t id = {
+ .dir = POLICY_OUT,
+ .src_ts = my_ts,
+ .dst_ts = other_ts,
+ .mark = this->mark_out,
+ .interface = this->config->get_interface(this->config),
+ };
+ kernel_ipsec_query_policy_t query = {};
+
+ if (charon->kernel->query_policy(charon->kernel, &id, &query,
+ &out) == SUCCESS)
{
last_use = max(last_use, out);
}
@@ -573,7 +606,7 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
METHOD(child_sa_t, get_usestats, void,
private_child_sa_t *this, bool inbound,
- time_t *time, u_int64_t *bytes, u_int64_t *packets)
+ time_t *time, uint64_t *bytes, uint64_t *packets)
{
if ((!bytes && !packets) || update_usebytes(this, inbound) != FAILED)
{
@@ -625,7 +658,7 @@ METHOD(child_sa_t, get_installtime, time_t,
return this->install_time;
}
-METHOD(child_sa_t, alloc_spi, u_int32_t,
+METHOD(child_sa_t, alloc_spi, uint32_t,
private_child_sa_t *this, protocol_id_t protocol)
{
if (charon->kernel->get_spi(charon->kernel, this->other_addr, this->my_addr,
@@ -639,7 +672,7 @@ METHOD(child_sa_t, alloc_spi, u_int32_t,
return 0;
}
-METHOD(child_sa_t, alloc_cpi, u_int16_t,
+METHOD(child_sa_t, alloc_cpi, uint16_t,
private_child_sa_t *this)
{
if (charon->kernel->get_cpi(charon->kernel, this->other_addr, this->my_addr,
@@ -651,16 +684,18 @@ METHOD(child_sa_t, alloc_cpi, u_int16_t,
}
METHOD(child_sa_t, install, status_t,
- private_child_sa_t *this, chunk_t encr, chunk_t integ, u_int32_t spi,
- u_int16_t cpi, bool initiator, bool inbound, bool tfcv3,
+ private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
+ uint16_t cpi, bool initiator, bool inbound, bool tfcv3,
linked_list_t *my_ts, linked_list_t *other_ts)
{
- u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
- u_int16_t esn = NO_EXT_SEQ_NUMBERS;
+ uint16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
+ uint16_t esn = NO_EXT_SEQ_NUMBERS;
linked_list_t *src_ts = NULL, *dst_ts = NULL;
time_t now;
+ kernel_ipsec_sa_id_t id;
+ kernel_ipsec_add_sa_t sa;
lifetime_cfg_t *lifetime;
- u_int32_t tfc = 0;
+ uint32_t tfc = 0;
host_t *src, *dst;
status_t status;
bool update = FALSE;
@@ -716,7 +751,7 @@ METHOD(child_sa_t, install, status_t,
this->reqid_allocated = TRUE;
}
- lifetime = this->config->get_lifetime(this->config);
+ lifetime = this->config->get_lifetime(this->config, TRUE);
now = time_monotonic(NULL);
if (lifetime->time.rekey)
@@ -752,12 +787,36 @@ METHOD(child_sa_t, install, status_t,
dst_ts = other_ts;
}
- status = charon->kernel->add_sa(charon->kernel,
- src, dst, spi, proto_ike2ip(this->protocol), this->reqid,
- inbound ? this->mark_in : this->mark_out, tfc,
- lifetime, enc_alg, encr, int_alg, integ, this->mode,
- this->ipcomp, cpi, this->config->get_replay_window(this->config),
- initiator, this->encap, esn, inbound, update, src_ts, dst_ts);
+ id = (kernel_ipsec_sa_id_t){
+ .src = src,
+ .dst = dst,
+ .spi = spi,
+ .proto = proto_ike2ip(this->protocol),
+ .mark = inbound ? this->mark_in : this->mark_out,
+ };
+ sa = (kernel_ipsec_add_sa_t){
+ .reqid = this->reqid,
+ .mode = this->mode,
+ .src_ts = src_ts,
+ .dst_ts = dst_ts,
+ .interface = inbound ? NULL : this->config->get_interface(this->config),
+ .lifetime = lifetime,
+ .enc_alg = enc_alg,
+ .enc_key = encr,
+ .int_alg = int_alg,
+ .int_key = integ,
+ .replay_window = this->config->get_replay_window(this->config),
+ .tfc = tfc,
+ .ipcomp = this->ipcomp,
+ .cpi = cpi,
+ .encap = this->encap,
+ .esn = esn,
+ .initiator = initiator,
+ .inbound = inbound,
+ .update = update,
+ };
+
+ status = charon->kernel->add_sa(charon->kernel, &id, &sa);
free(lifetime);
@@ -825,24 +884,62 @@ static void prepare_sa_cfg(private_child_sa_t *this, ipsec_sa_cfg_t *my_sa,
static status_t install_policies_internal(private_child_sa_t *this,
host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
- ipsec_sa_cfg_t *other_sa, policy_type_t type, policy_priority_t priority)
+ ipsec_sa_cfg_t *other_sa, policy_type_t type,
+ policy_priority_t priority, uint32_t manual_prio)
{
+ kernel_ipsec_policy_id_t out_id = {
+ .dir = POLICY_OUT,
+ .src_ts = my_ts,
+ .dst_ts = other_ts,
+ .mark = this->mark_out,
+ .interface = this->config->get_interface(this->config),
+ }, in_id = {
+ .dir = POLICY_IN,
+ .src_ts = other_ts,
+ .dst_ts = my_ts,
+ .mark = this->mark_in,
+ };
+ kernel_ipsec_manage_policy_t out_policy = {
+ .type = type,
+ .prio = priority,
+ .manual_prio = manual_prio,
+ .src = my_addr,
+ .dst = other_addr,
+ .sa = other_sa,
+ }, in_policy = {
+ .type = type,
+ .prio = priority,
+ .manual_prio = manual_prio,
+ .src = other_addr,
+ .dst = my_addr,
+ .sa = my_sa,
+ };
status_t status = SUCCESS;
- status |= charon->kernel->add_policy(charon->kernel,
- my_addr, other_addr, my_ts, other_ts,
- POLICY_OUT, type, other_sa,
- this->mark_out, priority);
-
- status |= charon->kernel->add_policy(charon->kernel,
- other_addr, my_addr, other_ts, my_ts,
- POLICY_IN, type, my_sa,
- this->mark_in, priority);
+
+ status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
+ status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
if (this->mode != MODE_TRANSPORT)
{
- status |= charon->kernel->add_policy(charon->kernel,
- other_addr, my_addr, other_ts, my_ts,
- POLICY_FWD, type, my_sa,
- this->mark_in, priority);
+ in_id.dir = POLICY_FWD;
+ status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
+
+ /* install an "outbound" FWD policy in case there is a drop policy
+ * matching outbound forwarded traffic, to allow another tunnel to use
+ * the reversed subnets and do the same we don't set a reqid (this also
+ * allows the kernel backend to distinguish between the two types of
+ * FWD policies). To avoid problems with symmetrically overlapping
+ * policies of two SAs we install them with reduced priority. As they
+ * basically act as bypass policies for drop policies we use a higher
+ * priority than is used for them. */
+ out_id.dir = POLICY_FWD;
+ other_sa->reqid = 0;
+ if (priority == POLICY_PRIORITY_DEFAULT)
+ {
+ out_policy.prio = POLICY_PRIORITY_ROUTED;
+ }
+ status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
+ /* reset the reqid for any other further policies */
+ other_sa->reqid = this->reqid;
}
return status;
}
@@ -853,20 +950,52 @@ static status_t install_policies_internal(private_child_sa_t *this,
static void del_policies_internal(private_child_sa_t *this,
host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
- ipsec_sa_cfg_t *other_sa, policy_type_t type, policy_priority_t priority)
+ ipsec_sa_cfg_t *other_sa, policy_type_t type,
+ policy_priority_t priority, uint32_t manual_prio)
{
+ kernel_ipsec_policy_id_t out_id = {
+ .dir = POLICY_OUT,
+ .src_ts = my_ts,
+ .dst_ts = other_ts,
+ .mark = this->mark_out,
+ .interface = this->config->get_interface(this->config),
+ }, in_id = {
+ .dir = POLICY_IN,
+ .src_ts = other_ts,
+ .dst_ts = my_ts,
+ .mark = this->mark_in,
+ };
+ kernel_ipsec_manage_policy_t out_policy = {
+ .type = type,
+ .prio = priority,
+ .manual_prio = manual_prio,
+ .src = my_addr,
+ .dst = other_addr,
+ .sa = other_sa,
+ }, in_policy = {
+ .type = type,
+ .prio = priority,
+ .manual_prio = manual_prio,
+ .src = other_addr,
+ .dst = my_addr,
+ .sa = my_sa,
+ };
- charon->kernel->del_policy(charon->kernel,
- my_addr, other_addr, my_ts, other_ts, POLICY_OUT, type,
- other_sa, this->mark_out, priority);
- charon->kernel->del_policy(charon->kernel,
- other_addr, my_addr, other_ts, my_ts, POLICY_IN,
- type, my_sa, this->mark_in, priority);
+ charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
+ charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
if (this->mode != MODE_TRANSPORT)
{
- charon->kernel->del_policy(charon->kernel,
- other_addr, my_addr, other_ts, my_ts, POLICY_FWD,
- type, my_sa, this->mark_in, priority);
+ in_id.dir = POLICY_FWD;
+ charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
+
+ out_id.dir = POLICY_FWD;
+ other_sa->reqid = 0;
+ if (priority == POLICY_PRIORITY_DEFAULT)
+ {
+ out_policy.prio = POLICY_PRIORITY_ROUTED;
+ }
+ charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
+ other_sa->reqid = this->reqid;
}
}
@@ -912,8 +1041,10 @@ METHOD(child_sa_t, add_policies, status_t,
{
policy_priority_t priority;
ipsec_sa_cfg_t my_sa, other_sa;
+ uint32_t manual_prio;
prepare_sa_cfg(this, &my_sa, &other_sa);
+ manual_prio = this->config->get_manual_prio(this->config);
/* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
* entry) we install a trap policy */
@@ -927,18 +1058,20 @@ METHOD(child_sa_t, add_policies, status_t,
{
/* install outbound drop policy to avoid packets leaving unencrypted
* when updating policies */
- if (priority == POLICY_PRIORITY_DEFAULT && require_policy_update())
+ if (priority == POLICY_PRIORITY_DEFAULT && manual_prio == 0 &&
+ require_policy_update())
{
status |= install_policies_internal(this, this->my_addr,
this->other_addr, my_ts, other_ts,
&my_sa, &other_sa, POLICY_DROP,
- POLICY_PRIORITY_FALLBACK);
+ POLICY_PRIORITY_FALLBACK, 0);
}
/* install policies */
status |= install_policies_internal(this, this->my_addr,
this->other_addr, my_ts, other_ts,
- &my_sa, &other_sa, POLICY_IPSEC, priority);
+ &my_sa, &other_sa, POLICY_IPSEC,
+ priority, manual_prio);
if (status != SUCCESS)
{
@@ -994,11 +1127,22 @@ METHOD(child_sa_t, update, status_t,
/* update our (initiator) SA */
if (this->my_spi)
{
- if (charon->kernel->update_sa(charon->kernel,
- this->my_spi, proto_ike2ip(this->protocol),
- this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
- this->other_addr, this->my_addr, other, me,
- this->encap, encap, this->mark_in) == NOT_SUPPORTED)
+ kernel_ipsec_sa_id_t id = {
+ .src = this->other_addr,
+ .dst = this->my_addr,
+ .spi = this->my_spi,
+ .proto = proto_ike2ip(this->protocol),
+ .mark = this->mark_in,
+ };
+ kernel_ipsec_update_sa_t sa = {
+ .cpi = this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
+ .new_src = other,
+ .new_dst = me,
+ .encap = this->encap,
+ .new_encap = encap,
+ };
+ if (charon->kernel->update_sa(charon->kernel, &id,
+ &sa) == NOT_SUPPORTED)
{
set_state(this, old);
return NOT_SUPPORTED;
@@ -1008,11 +1152,22 @@ METHOD(child_sa_t, update, status_t,
/* update his (responder) SA */
if (this->other_spi)
{
- if (charon->kernel->update_sa(charon->kernel,
- this->other_spi, proto_ike2ip(this->protocol),
- this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
- this->my_addr, this->other_addr, me, other,
- this->encap, encap, this->mark_out) == NOT_SUPPORTED)
+ kernel_ipsec_sa_id_t id = {
+ .src = this->my_addr,
+ .dst = this->other_addr,
+ .spi = this->other_spi,
+ .proto = proto_ike2ip(this->protocol),
+ .mark = this->mark_out,
+ };
+ kernel_ipsec_update_sa_t sa = {
+ .cpi = this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
+ .new_src = me,
+ .new_dst = other,
+ .encap = this->encap,
+ .new_encap = encap,
+ };
+ if (charon->kernel->update_sa(charon->kernel, &id,
+ &sa) == NOT_SUPPORTED)
{
set_state(this, old);
return NOT_SUPPORTED;
@@ -1028,18 +1183,21 @@ METHOD(child_sa_t, update, status_t,
ipsec_sa_cfg_t my_sa, other_sa;
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
+ uint32_t manual_prio;
prepare_sa_cfg(this, &my_sa, &other_sa);
+ manual_prio = this->config->get_manual_prio(this->config);
/* always use high priorities, as hosts getting updated are INSTALLED */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
traffic_selector_t *old_my_ts = NULL, *old_other_ts = NULL;
+
/* remove old policies first */
del_policies_internal(this, this->my_addr, this->other_addr,
- my_ts, other_ts, &my_sa, &other_sa,
- POLICY_IPSEC, POLICY_PRIORITY_DEFAULT);
+ my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC,
+ POLICY_PRIORITY_DEFAULT, manual_prio);
/* check if we have to update a "dynamic" traffic selector */
if (!me->ip_equals(me, this->my_addr) &&
@@ -1062,17 +1220,20 @@ METHOD(child_sa_t, update, status_t,
/* reinstall updated policies */
install_policies_internal(this, me, other, my_ts, other_ts,
&my_sa, &other_sa, POLICY_IPSEC,
- POLICY_PRIORITY_DEFAULT);
+ POLICY_PRIORITY_DEFAULT, manual_prio);
/* update fallback policies after the new policy is in place */
- del_policies_internal(this, this->my_addr, this->other_addr,
- old_my_ts ?: my_ts,
- old_other_ts ?: other_ts,
- &my_sa, &other_sa, POLICY_DROP,
- POLICY_PRIORITY_FALLBACK);
- install_policies_internal(this, me, other, my_ts, other_ts,
+ if (manual_prio == 0)
+ {
+ del_policies_internal(this, this->my_addr, this->other_addr,
+ old_my_ts ?: my_ts,
+ old_other_ts ?: other_ts,
+ &my_sa, &other_sa, POLICY_DROP,
+ POLICY_PRIORITY_FALLBACK, 0);
+ install_policies_internal(this, me, other, my_ts, other_ts,
&my_sa, &other_sa, POLICY_DROP,
- POLICY_PRIORITY_FALLBACK);
+ POLICY_PRIORITY_FALLBACK, 0);
+ }
DESTROY_IF(old_my_ts);
DESTROY_IF(old_other_ts);
}
@@ -1115,20 +1276,24 @@ METHOD(child_sa_t, destroy, void,
if (this->config->install_policy(this->config))
{
ipsec_sa_cfg_t my_sa, other_sa;
+ uint32_t manual_prio;
prepare_sa_cfg(this, &my_sa, &other_sa);
+ manual_prio = this->config->get_manual_prio(this->config);
/* delete all policies in the kernel */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
del_policies_internal(this, this->my_addr, this->other_addr,
- my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC, priority);
- if (priority == POLICY_PRIORITY_DEFAULT && require_policy_update())
+ my_ts, other_ts, &my_sa, &other_sa,
+ POLICY_IPSEC, priority, manual_prio);
+ if (priority == POLICY_PRIORITY_DEFAULT && manual_prio == 0 &&
+ require_policy_update())
{
del_policies_internal(this, this->my_addr, this->other_addr,
- my_ts, other_ts, &my_sa, &other_sa, POLICY_DROP,
- POLICY_PRIORITY_FALLBACK);
+ my_ts, other_ts, &my_sa, &other_sa,
+ POLICY_DROP, POLICY_PRIORITY_FALLBACK, 0);
}
}
enumerator->destroy(enumerator);
@@ -1137,17 +1302,31 @@ METHOD(child_sa_t, destroy, void,
/* delete SAs in the kernel, if they are set up */
if (this->my_spi)
{
- charon->kernel->del_sa(charon->kernel,
- this->other_addr, this->my_addr, this->my_spi,
- proto_ike2ip(this->protocol), this->my_cpi,
- this->mark_in);
+ kernel_ipsec_sa_id_t id = {
+ .src = this->other_addr,
+ .dst = this->my_addr,
+ .spi = this->my_spi,
+ .proto = proto_ike2ip(this->protocol),
+ .mark = this->mark_in,
+ };
+ kernel_ipsec_del_sa_t sa = {
+ .cpi = this->my_cpi,
+ };
+ charon->kernel->del_sa(charon->kernel, &id, &sa);
}
if (this->other_spi)
{
- charon->kernel->del_sa(charon->kernel,
- this->my_addr, this->other_addr, this->other_spi,
- proto_ike2ip(this->protocol), this->other_cpi,
- this->mark_out);
+ kernel_ipsec_sa_id_t id = {
+ .src = this->my_addr,
+ .dst = this->other_addr,
+ .spi = this->other_spi,
+ .proto = proto_ike2ip(this->protocol),
+ .mark = this->mark_out,
+ };
+ kernel_ipsec_del_sa_t sa = {
+ .cpi = this->other_cpi,
+ };
+ charon->kernel->del_sa(charon->kernel, &id, &sa);
}
if (this->reqid_allocated)
@@ -1174,7 +1353,7 @@ METHOD(child_sa_t, destroy, void,
static host_t* get_proxy_addr(child_cfg_t *config, host_t *ike, bool local)
{
host_t *host = NULL;
- u_int8_t mask;
+ uint8_t mask;
enumerator_t *enumerator;
linked_list_t *ts_list, *list;
traffic_selector_t *ts;
@@ -1207,11 +1386,12 @@ static host_t* get_proxy_addr(child_cfg_t *config, host_t *ike, bool local)
* Described in header.
*/
child_sa_t * child_sa_create(host_t *me, host_t* other,
- child_cfg_t *config, u_int32_t rekey, bool encap,
+ child_cfg_t *config, uint32_t rekey, bool encap,
u_int mark_in, u_int mark_out)
{
private_child_sa_t *this;
- static refcount_t unique_id = 0, unique_mark = 0, mark;
+ static refcount_t unique_id = 0, unique_mark = 0;
+ refcount_t mark;
INIT(this,
.public = {
diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
index debe8eb2c..bc7df996a 100644
--- a/src/libcharon/sa/child_sa.h
+++ b/src/libcharon/sa/child_sa.h
@@ -128,7 +128,7 @@ struct child_sa_t {
*
* @return reqid of the CHILD SA
*/
- u_int32_t (*get_reqid)(child_sa_t *this);
+ uint32_t (*get_reqid)(child_sa_t *this);
/**
* Get the unique numerical identifier for this CHILD_SA.
@@ -138,7 +138,7 @@ struct child_sa_t {
*
* @return unique CHILD_SA identifier
*/
- u_int32_t (*get_unique_id)(child_sa_t *this);
+ uint32_t (*get_unique_id)(child_sa_t *this);
/**
* Get the config used to set up this child sa.
@@ -171,7 +171,7 @@ struct child_sa_t {
* @param inbound TRUE to get inbound SPI, FALSE for outbound.
* @return SPI of the CHILD SA
*/
- u_int32_t (*get_spi) (child_sa_t *this, bool inbound);
+ uint32_t (*get_spi) (child_sa_t *this, bool inbound);
/**
* Get the CPI of this CHILD_SA.
@@ -183,7 +183,7 @@ struct child_sa_t {
* @param inbound TRUE to get inbound CPI, FALSE for outbound.
* @return CPI of the CHILD SA
*/
- u_int16_t (*get_cpi) (child_sa_t *this, bool inbound);
+ uint16_t (*get_cpi) (child_sa_t *this, bool inbound);
/**
* Get the protocol which this CHILD_SA uses to protect traffic.
@@ -300,7 +300,7 @@ struct child_sa_t {
* @param[out] packets number of processed packets (NULL to ignore)
*/
void (*get_usestats)(child_sa_t *this, bool inbound, time_t *time,
- u_int64_t *bytes, u_int64_t *packets);
+ uint64_t *bytes, uint64_t *packets);
/**
* Get the mark used with this CHILD_SA.
@@ -335,14 +335,14 @@ struct child_sa_t {
* @param spi SPI output pointer
* @return SPI, 0 on failure
*/
- u_int32_t (*alloc_spi)(child_sa_t *this, protocol_id_t protocol);
+ uint32_t (*alloc_spi)(child_sa_t *this, protocol_id_t protocol);
/**
* Allocate a CPI to use for IPComp.
*
* @return CPI, 0 on failure
*/
- u_int16_t (*alloc_cpi)(child_sa_t *this);
+ uint16_t (*alloc_cpi)(child_sa_t *this);
/**
* Install an IPsec SA for one direction.
@@ -359,7 +359,7 @@ struct child_sa_t {
* @return SUCCESS or FAILED
*/
status_t (*install)(child_sa_t *this, chunk_t encr, chunk_t integ,
- u_int32_t spi, u_int16_t cpi,
+ uint32_t spi, uint16_t cpi,
bool initiator, bool inbound, bool tfcv3,
linked_list_t *my_ts, linked_list_t *other_ts);
/**
@@ -404,7 +404,7 @@ struct child_sa_t {
* @return child_sa_t object
*/
child_sa_t * child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
- u_int32_t reqid, bool encap,
+ uint32_t reqid, bool encap,
u_int mark_in, u_int mark_out);
#endif /** CHILD_SA_H_ @}*/
diff --git a/src/libcharon/sa/child_sa_manager.c b/src/libcharon/sa/child_sa_manager.c
index 071a119da..13f22cf5f 100644
--- a/src/libcharon/sa/child_sa_manager.c
+++ b/src/libcharon/sa/child_sa_manager.c
@@ -59,11 +59,11 @@ typedef struct {
/** the associated IKE_SA */
ike_sa_id_t *ike_id;
/** unique CHILD_SA identifier */
- u_int32_t unique_id;
+ uint32_t unique_id;
/** inbound SPI */
- u_int32_t spi_in;
+ uint32_t spi_in;
/** outbound SPI */
- u_int32_t spi_out;
+ uint32_t spi_out;
/** inbound host address */
host_t *host_in;
/** outbound host address and port */
@@ -202,7 +202,7 @@ METHOD(child_sa_manager_t, remove_, void,
* Check out an IKE_SA for a given CHILD_SA
*/
static ike_sa_t *checkout_ikesa(private_child_sa_manager_t *this,
- ike_sa_id_t *id, u_int32_t unique_id, child_sa_t **child_sa)
+ ike_sa_id_t *id, uint32_t unique_id, child_sa_t **child_sa)
{
enumerator_t *enumerator;
child_sa_t *current;
@@ -238,7 +238,7 @@ static ike_sa_t *checkout_ikesa(private_child_sa_manager_t *this,
}
METHOD(child_sa_manager_t, checkout_by_id, ike_sa_t*,
- private_child_sa_manager_t *this, u_int32_t unique_id,
+ private_child_sa_manager_t *this, uint32_t unique_id,
child_sa_t **child_sa)
{
ike_sa_id_t *id;
@@ -262,11 +262,11 @@ METHOD(child_sa_manager_t, checkout_by_id, ike_sa_t*,
}
METHOD(child_sa_manager_t, checkout, ike_sa_t*,
- private_child_sa_manager_t *this, protocol_id_t protocol, u_int32_t spi,
+ private_child_sa_manager_t *this, protocol_id_t protocol, uint32_t spi,
host_t *dst, child_sa_t **child_sa)
{
ike_sa_id_t *id;
- u_int32_t unique_id;
+ uint32_t unique_id;
child_entry_t *entry, key = {
.spi_in = spi,
.spi_out = spi,
diff --git a/src/libcharon/sa/child_sa_manager.h b/src/libcharon/sa/child_sa_manager.h
index 4d57528e8..f1d6ad9e0 100644
--- a/src/libcharon/sa/child_sa_manager.h
+++ b/src/libcharon/sa/child_sa_manager.h
@@ -59,7 +59,7 @@ struct child_sa_manager_t {
* @return IKE_SA, NULL if not found
*/
ike_sa_t *(*checkout)(child_sa_manager_t *this,
- protocol_id_t protocol, u_int32_t spi, host_t *dst,
+ protocol_id_t protocol, uint32_t spi, host_t *dst,
child_sa_t **child_sa);
/**
@@ -72,7 +72,7 @@ struct child_sa_manager_t {
* @param child_sa returns CHILD_SA managed by IKE_SA
* @return IKE_SA, NULL if not found
*/
- ike_sa_t *(*checkout_by_id)(child_sa_manager_t *this, u_int32_t unique_id,
+ ike_sa_t *(*checkout_by_id)(child_sa_manager_t *this, uint32_t unique_id,
child_sa_t **child_sa);
/**
diff --git a/src/libcharon/sa/eap/eap_manager.c b/src/libcharon/sa/eap/eap_manager.c
index 1886307e9..e4fcbc8f0 100644
--- a/src/libcharon/sa/eap/eap_manager.c
+++ b/src/libcharon/sa/eap/eap_manager.c
@@ -35,7 +35,7 @@ struct eap_entry_t {
/**
* vendor ID, 0 for default EAP methods
*/
- u_int32_t vendor;
+ uint32_t vendor;
/**
* Role of the method returned by the constructor, EAP_SERVER or EAP_PEER
@@ -70,7 +70,7 @@ struct private_eap_manager_t {
};
METHOD(eap_manager_t, add_method, void,
- private_eap_manager_t *this, eap_type_t type, u_int32_t vendor,
+ private_eap_manager_t *this, eap_type_t type, uint32_t vendor,
eap_role_t role, eap_constructor_t constructor)
{
eap_entry_t *entry = malloc_thing(eap_entry_t);
@@ -109,7 +109,7 @@ METHOD(eap_manager_t, remove_method, void,
* filter the registered methods
*/
static bool filter_methods(uintptr_t role, eap_entry_t **entry,
- eap_type_t *type, void *in, u_int32_t *vendor)
+ eap_type_t *type, void *in, uint32_t *vendor)
{
if ((*entry)->role != (eap_role_t)role)
{
@@ -144,7 +144,7 @@ METHOD(eap_manager_t, create_enumerator, enumerator_t*,
}
METHOD(eap_manager_t, create_instance, eap_method_t*,
- private_eap_manager_t *this, eap_type_t type, u_int32_t vendor,
+ private_eap_manager_t *this, eap_type_t type, uint32_t vendor,
eap_role_t role, identification_t *server, identification_t *peer)
{
enumerator_t *enumerator;
diff --git a/src/libcharon/sa/eap/eap_manager.h b/src/libcharon/sa/eap/eap_manager.h
index e318ef57a..4ed1cae20 100644
--- a/src/libcharon/sa/eap/eap_manager.h
+++ b/src/libcharon/sa/eap/eap_manager.h
@@ -44,7 +44,7 @@ struct eap_manager_t {
* @param role EAP role of the registered method
* @param constructor constructor function, returns an eap_method_t
*/
- void (*add_method)(eap_manager_t *this, eap_type_t type, u_int32_t vendor,
+ void (*add_method)(eap_manager_t *this, eap_type_t type, uint32_t vendor,
eap_role_t role, eap_constructor_t constructor);
/**
@@ -61,7 +61,7 @@ struct eap_manager_t {
* even though it is registered as method with this manager).
*
* @param role EAP role of methods to enumerate
- * @return enumerator over (eap_type_t type, u_int32_t vendor)
+ * @return enumerator over (eap_type_t type, uint32_t vendor)
*/
enumerator_t* (*create_enumerator)(eap_manager_t *this, eap_role_t role);
@@ -76,7 +76,7 @@ struct eap_manager_t {
* @return EAP method instance, NULL if no constructor found
*/
eap_method_t* (*create_instance)(eap_manager_t *this, eap_type_t type,
- u_int32_t vendor, eap_role_t role,
+ uint32_t vendor, eap_role_t role,
identification_t *server,
identification_t *peer);
diff --git a/src/libcharon/sa/eap/eap_method.h b/src/libcharon/sa/eap/eap_method.h
index 689c0f990..8e25f7df8 100644
--- a/src/libcharon/sa/eap/eap_method.h
+++ b/src/libcharon/sa/eap/eap_method.h
@@ -96,7 +96,7 @@ struct eap_method_t {
* @param vendor pointer receiving vendor identifier for type, 0 for none
* @return type of the EAP method
*/
- eap_type_t (*get_type) (eap_method_t *this, u_int32_t *vendor);
+ eap_type_t (*get_type) (eap_method_t *this, uint32_t *vendor);
/**
* Check if this EAP method authenticates the server.
@@ -126,7 +126,7 @@ struct eap_method_t {
*
* @return current EAP identifier
*/
- u_int8_t (*get_identifier) (eap_method_t *this);
+ uint8_t (*get_identifier) (eap_method_t *this);
/**
* Set the EAP identifier to a deterministic value, overwriting
@@ -134,7 +134,7 @@ struct eap_method_t {
*
* @param identifier current EAP identifier
*/
- void (*set_identifier) (eap_method_t *this, u_int8_t identifier);
+ void (*set_identifier) (eap_method_t *this, uint8_t identifier);
/**
* Get authentication details performed by this EAP method.
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index bcbff3211..009277ddd 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2006-2015 Tobias Brunner
+ * Copyright (C) 2006-2016 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -71,6 +71,7 @@ ENUM(ike_sa_state_names, IKE_CREATED, IKE_DESTROYING,
"ESTABLISHED",
"PASSIVE",
"REKEYING",
+ "REKEYED",
"DELETING",
"DESTROYING",
);
@@ -101,7 +102,7 @@ struct private_ike_sa_t {
/**
* unique numerical ID for this IKE_SA.
*/
- u_int32_t unique_id;
+ uint32_t unique_id;
/**
* Current state of the IKE_SA
@@ -233,12 +234,12 @@ struct private_ike_sa_t {
/**
* number pending UPDATE_SA_ADDRESS (MOBIKE)
*/
- u_int32_t pending_updates;
+ uint32_t pending_updates;
/**
* NAT keep alive interval
*/
- u_int32_t keepalive_interval;
+ uint32_t keepalive_interval;
/**
* The schedueld keep alive job, if any
@@ -249,7 +250,7 @@ struct private_ike_sa_t {
* interval for retries during initiation (e.g. if DNS resolution failed),
* 0 to disable (default)
*/
- u_int32_t retry_initiate_interval;
+ uint32_t retry_initiate_interval;
/**
* TRUE if a retry_initiate_job has been queued
@@ -259,12 +260,12 @@ struct private_ike_sa_t {
/**
* Timestamps for this IKE_SA
*/
- u_int32_t stats[STAT_MAX];
+ uint32_t stats[STAT_MAX];
/**
* how many times we have retried so far (keyingtries)
*/
- u_int32_t keyingtry;
+ uint32_t keyingtry;
/**
* local host address to be used for IKE, set via MIGRATE kernel message
@@ -343,7 +344,7 @@ static time_t get_use_time(private_ike_sa_t* this, bool inbound)
return use_time;
}
-METHOD(ike_sa_t, get_unique_id, u_int32_t,
+METHOD(ike_sa_t, get_unique_id, uint32_t,
private_ike_sa_t *this)
{
return this->unique_id;
@@ -359,7 +360,7 @@ METHOD(ike_sa_t, get_name, char*,
return "(unnamed)";
}
-METHOD(ike_sa_t, get_statistic, u_int32_t,
+METHOD(ike_sa_t, get_statistic, uint32_t,
private_ike_sa_t *this, statistic_t kind)
{
if (kind < STAT_MAX)
@@ -370,7 +371,7 @@ METHOD(ike_sa_t, get_statistic, u_int32_t,
}
METHOD(ike_sa_t, set_statistic, void,
- private_ike_sa_t *this, statistic_t kind, u_int32_t value)
+ private_ike_sa_t *this, statistic_t kind, uint32_t value)
{
if (kind < STAT_MAX)
{
@@ -604,7 +605,7 @@ METHOD(ike_sa_t, set_proposal, void,
}
METHOD(ike_sa_t, set_message_id, void,
- private_ike_sa_t *this, bool initiate, u_int32_t mid)
+ private_ike_sa_t *this, bool initiate, uint32_t mid)
{
if (initiate)
{
@@ -814,7 +815,7 @@ METHOD(ike_sa_t, set_state, void,
this->state == IKE_PASSIVE)
{
job_t *job;
- u_int32_t t;
+ uint32_t t;
/* calculate rekey, reauth and lifetime */
this->stats[STAT_ESTABLISHED] = time_monotonic(NULL);
@@ -1035,12 +1036,12 @@ METHOD(ike_sa_t, has_mapping_changed, bool,
}
METHOD(ike_sa_t, set_pending_updates, void,
- private_ike_sa_t *this, u_int32_t updates)
+ private_ike_sa_t *this, uint32_t updates)
{
this->pending_updates = updates;
}
-METHOD(ike_sa_t, get_pending_updates, u_int32_t,
+METHOD(ike_sa_t, get_pending_updates, uint32_t,
private_ike_sa_t *this)
{
return this->pending_updates;
@@ -1203,6 +1204,7 @@ METHOD(ike_sa_t, generate_message_fragmented, status_t,
packet_t *packet;
status_t status;
bool use_frags = FALSE;
+ bool pre_generated = FALSE;
if (this->ike_cfg)
{
@@ -1237,14 +1239,21 @@ METHOD(ike_sa_t, generate_message_fragmented, status_t,
return SUCCESS;
}
+ pre_generated = message->is_encoded(message);
this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
message->set_ike_sa_id(message, this->ike_sa_id);
- charon->bus->message(charon->bus, message, FALSE, TRUE);
+ if (!pre_generated)
+ {
+ charon->bus->message(charon->bus, message, FALSE, TRUE);
+ }
status = message->fragment(message, this->keymat, this->fragment_size,
&fragments);
if (status == SUCCESS)
{
- charon->bus->message(charon->bus, message, FALSE, FALSE);
+ if (!pre_generated)
+ {
+ charon->bus->message(charon->bus, message, FALSE, FALSE);
+ }
*packets = enumerator_create_filter(fragments, (void*)filter_fragments,
this, NULL);
}
@@ -1432,7 +1441,7 @@ static void resolve_hosts(private_ike_sa_t *this)
}
METHOD(ike_sa_t, initiate, status_t,
- private_ike_sa_t *this, child_cfg_t *child_cfg, u_int32_t reqid,
+ private_ike_sa_t *this, child_cfg_t *child_cfg, uint32_t reqid,
traffic_selector_t *tsi, traffic_selector_t *tsr)
{
bool defer_initiate = FALSE;
@@ -1642,7 +1651,7 @@ METHOD(ike_sa_t, add_child_sa, void,
}
METHOD(ike_sa_t, get_child_sa, child_sa_t*,
- private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi, bool inbound)
+ private_ike_sa_t *this, protocol_id_t protocol, uint32_t spi, bool inbound)
{
enumerator_t *enumerator;
child_sa_t *current, *found = NULL;
@@ -1721,7 +1730,7 @@ METHOD(ike_sa_t, remove_child_sa, void,
}
METHOD(ike_sa_t, rekey_child_sa, status_t,
- private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi)
+ private_ike_sa_t *this, protocol_id_t protocol, uint32_t spi)
{
if (this->state == IKE_PASSIVE)
{
@@ -1732,7 +1741,7 @@ METHOD(ike_sa_t, rekey_child_sa, status_t,
}
METHOD(ike_sa_t, delete_child_sa, status_t,
- private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi, bool expired)
+ private_ike_sa_t *this, protocol_id_t protocol, uint32_t spi, bool expired)
{
if (this->state == IKE_PASSIVE)
{
@@ -1744,7 +1753,7 @@ METHOD(ike_sa_t, delete_child_sa, status_t,
}
METHOD(ike_sa_t, destroy_child_sa, status_t,
- private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi)
+ private_ike_sa_t *this, protocol_id_t protocol, uint32_t spi)
{
enumerator_t *enumerator;
child_sa_t *child_sa;
@@ -2301,7 +2310,7 @@ METHOD(ike_sa_t, redirect, status_t,
}
METHOD(ike_sa_t, retransmit, status_t,
- private_ike_sa_t *this, u_int32_t message_id)
+ private_ike_sa_t *this, uint32_t message_id)
{
if (this->state == IKE_PASSIVE)
{
@@ -2316,7 +2325,7 @@ METHOD(ike_sa_t, retransmit, status_t,
case IKE_CONNECTING:
{
/* retry IKE_SA_INIT/Main Mode if we have multiple keyingtries */
- u_int32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg);
+ uint32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg);
charon->bus->alert(charon->bus, ALERT_PEER_INIT_UNREACHABLE,
this->keyingtry);
this->keyingtry++;
@@ -2348,7 +2357,8 @@ METHOD(ike_sa_t, retransmit, status_t,
reestablish(this);
break;
}
- if (this->state != IKE_CONNECTING)
+ if (this->state != IKE_CONNECTING &&
+ this->state != IKE_REKEYED)
{
charon->bus->ike_updown(charon->bus, &this->public, FALSE);
}
@@ -2358,9 +2368,9 @@ METHOD(ike_sa_t, retransmit, status_t,
}
METHOD(ike_sa_t, set_auth_lifetime, status_t,
- private_ike_sa_t *this, u_int32_t lifetime)
+ private_ike_sa_t *this, uint32_t lifetime)
{
- u_int32_t diff, hard, soft, now;
+ uint32_t diff, hard, soft, now;
bool send_update;
diff = this->peer_cfg->get_over_time(this->peer_cfg);
@@ -2500,6 +2510,7 @@ METHOD(ike_sa_t, roam, status_t,
case IKE_DELETING:
case IKE_DESTROYING:
case IKE_PASSIVE:
+ case IKE_REKEYED:
return SUCCESS;
default:
break;
@@ -2609,6 +2620,12 @@ METHOD(ike_sa_t, queue_task, void,
this->task_manager->queue_task(this->task_manager, task);
}
+METHOD(ike_sa_t, queue_task_delayed, void,
+ private_ike_sa_t *this, task_t *task, uint32_t delay)
+{
+ this->task_manager->queue_task_delayed(this->task_manager, task, delay);
+}
+
METHOD(ike_sa_t, inherit_pre, void,
private_ike_sa_t *this, ike_sa_t *other_public)
{
@@ -2927,6 +2944,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
.create_task_enumerator = _create_task_enumerator,
.flush_queue = _flush_queue,
.queue_task = _queue_task,
+ .queue_task_delayed = _queue_task_delayed,
#ifdef ME
.act_as_mediation_server = _act_as_mediation_server,
.get_server_reflexive_host = _get_server_reflexive_host,
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index 836360e3c..6f5040d7c 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2006-2015 Tobias Brunner
+ * Copyright (C) 2006-2016 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -58,12 +58,12 @@ typedef struct ike_sa_t ike_sa_t;
/**
* After which time rekeying should be retried if it failed, in seconds.
*/
-#define RETRY_INTERVAL 30
+#define RETRY_INTERVAL 15
/**
* Jitter to subtract from RETRY_INTERVAL to randomize rekey retry.
*/
-#define RETRY_JITTER 20
+#define RETRY_JITTER 10
/**
* Number of redirects allowed within REDIRECT_LOOP_DETECT_PERIOD.
@@ -309,6 +309,11 @@ enum ike_sa_state_t {
IKE_REKEYING,
/**
+ * IKE_SA has been rekeyed (or is redundant)
+ */
+ IKE_REKEYED,
+
+ /**
* IKE_SA is in progress of deletion
*/
IKE_DELETING,
@@ -353,7 +358,7 @@ struct ike_sa_t {
*
* @return unique ID
*/
- u_int32_t (*get_unique_id) (ike_sa_t *this);
+ uint32_t (*get_unique_id) (ike_sa_t *this);
/**
* Get the state of the IKE_SA.
@@ -382,7 +387,7 @@ struct ike_sa_t {
* @param kind kind of requested value
* @return value as integer
*/
- u_int32_t (*get_statistic)(ike_sa_t *this, statistic_t kind);
+ uint32_t (*get_statistic)(ike_sa_t *this, statistic_t kind);
/**
* Set statistic value of the IKE_SA.
@@ -390,7 +395,7 @@ struct ike_sa_t {
* @param kind kind of value to update
* @param value value as integer
*/
- void (*set_statistic)(ike_sa_t *this, statistic_t kind, u_int32_t value);
+ void (*set_statistic)(ike_sa_t *this, statistic_t kind, uint32_t value);
/**
* Get the own host address.
@@ -557,7 +562,7 @@ struct ike_sa_t {
* @param initiate TRUE to set message ID for initiating
* @param mid message id to set
*/
- void (*set_message_id)(ike_sa_t *this, bool initiate, u_int32_t mid);
+ void (*set_message_id)(ike_sa_t *this, bool initiate, uint32_t mid);
/**
* Add an additional address for the peer.
@@ -630,14 +635,14 @@ struct ike_sa_t {
*
* @return number of pending updates
*/
- u_int32_t (*get_pending_updates)(ike_sa_t *this);
+ uint32_t (*get_pending_updates)(ike_sa_t *this);
/**
* Set the number of queued MOBIKE address updates.
*
* @param updates number of pending updates
*/
- void (*set_pending_updates)(ike_sa_t *this, u_int32_t updates);
+ void (*set_pending_updates)(ike_sa_t *this, uint32_t updates);
#ifdef ME
/**
@@ -752,7 +757,7 @@ struct ike_sa_t {
* - DESTROY_ME if initialization failed
*/
status_t (*initiate) (ike_sa_t *this, child_cfg_t *child_cfg,
- u_int32_t reqid, traffic_selector_t *tsi,
+ uint32_t reqid, traffic_selector_t *tsi,
traffic_selector_t *tsr);
/**
@@ -850,7 +855,7 @@ struct ike_sa_t {
* - SUCCESS
* - NOT_FOUND if request doesn't have to be retransmited
*/
- status_t (*retransmit) (ike_sa_t *this, u_int32_t message_id);
+ status_t (*retransmit) (ike_sa_t *this, uint32_t message_id);
/**
* Sends a DPD request to the peer.
@@ -924,7 +929,7 @@ struct ike_sa_t {
* @return child_sa, or NULL if none found
*/
child_sa_t* (*get_child_sa) (ike_sa_t *this, protocol_id_t protocol,
- u_int32_t spi, bool inbound);
+ uint32_t spi, bool inbound);
/**
* Get the number of CHILD_SAs.
@@ -958,7 +963,7 @@ struct ike_sa_t {
* - NOT_FOUND, if IKE_SA has no such CHILD_SA
* - SUCCESS, if rekeying initiated
*/
- status_t (*rekey_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi);
+ status_t (*rekey_child_sa) (ike_sa_t *this, protocol_id_t protocol, uint32_t spi);
/**
* Close the CHILD SA with the specified protocol/SPI.
@@ -975,7 +980,7 @@ struct ike_sa_t {
* - SUCCESS, if delete message sent
*/
status_t (*delete_child_sa)(ike_sa_t *this, protocol_id_t protocol,
- u_int32_t spi, bool expired);
+ uint32_t spi, bool expired);
/**
* Destroy a CHILD SA with the specified protocol/SPI.
@@ -988,7 +993,7 @@ struct ike_sa_t {
* - NOT_FOUND, if IKE_SA has no such CHILD_SA
* - SUCCESS
*/
- status_t (*destroy_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi);
+ status_t (*destroy_child_sa) (ike_sa_t *this, protocol_id_t protocol, uint32_t spi);
/**
* Rekey the IKE_SA.
@@ -1028,7 +1033,7 @@ struct ike_sa_t {
* @param lifetime lifetime in seconds
* @return DESTROY_ME to destroy the IKE_SA
*/
- status_t (*set_auth_lifetime)(ike_sa_t *this, u_int32_t lifetime);
+ status_t (*set_auth_lifetime)(ike_sa_t *this, uint32_t lifetime);
/**
* Add a virtual IP to use for this IKE_SA and its children.
@@ -1119,6 +1124,15 @@ struct ike_sa_t {
void (*queue_task)(ike_sa_t *this, task_t *task);
/**
+ * Queue a task in the manager, but delay its initiation for at least the
+ * given number of seconds.
+ *
+ * @param task task to queue
+ * @param delay minimum delay in s before initiating the task
+ */
+ void (*queue_task_delayed)(ike_sa_t *this, task_t *task, uint32_t delay);
+
+ /**
* Inherit required attributes to new SA before rekeying.
*
* Some properties of the SA must be applied before starting IKE_SA
diff --git a/src/libcharon/sa/ike_sa_id.c b/src/libcharon/sa/ike_sa_id.c
index e52086483..b4e66ed73 100644
--- a/src/libcharon/sa/ike_sa_id.c
+++ b/src/libcharon/sa/ike_sa_id.c
@@ -34,17 +34,17 @@ struct private_ike_sa_id_t {
/**
* Major IKE version of IKE_SA.
*/
- u_int8_t ike_version;
+ uint8_t ike_version;
/**
* SPI of initiator.
*/
- u_int64_t initiator_spi;
+ uint64_t initiator_spi;
/**
* SPI of responder.
*/
- u_int64_t responder_spi;
+ uint64_t responder_spi;
/**
* Role for specific IKE_SA.
@@ -52,31 +52,31 @@ struct private_ike_sa_id_t {
bool is_initiator_flag;
};
-METHOD(ike_sa_id_t, get_ike_version, u_int8_t,
+METHOD(ike_sa_id_t, get_ike_version, uint8_t,
private_ike_sa_id_t *this)
{
return this->ike_version;
}
METHOD(ike_sa_id_t, set_responder_spi, void,
- private_ike_sa_id_t *this, u_int64_t responder_spi)
+ private_ike_sa_id_t *this, uint64_t responder_spi)
{
this->responder_spi = responder_spi;
}
METHOD(ike_sa_id_t, set_initiator_spi, void,
- private_ike_sa_id_t *this, u_int64_t initiator_spi)
+ private_ike_sa_id_t *this, uint64_t initiator_spi)
{
this->initiator_spi = initiator_spi;
}
-METHOD(ike_sa_id_t, get_initiator_spi, u_int64_t,
+METHOD(ike_sa_id_t, get_initiator_spi, uint64_t,
private_ike_sa_id_t *this)
{
return this->initiator_spi;
}
-METHOD(ike_sa_id_t, get_responder_spi, u_int64_t,
+METHOD(ike_sa_id_t, get_responder_spi, uint64_t,
private_ike_sa_id_t *this)
{
return this->responder_spi;
@@ -134,8 +134,8 @@ METHOD(ike_sa_id_t, destroy, void,
/*
* Described in header.
*/
-ike_sa_id_t * ike_sa_id_create(u_int8_t ike_version, u_int64_t initiator_spi,
- u_int64_t responder_spi, bool is_initiator_flag)
+ike_sa_id_t * ike_sa_id_create(uint8_t ike_version, uint64_t initiator_spi,
+ uint64_t responder_spi, bool is_initiator_flag)
{
private_ike_sa_id_t *this;
diff --git a/src/libcharon/sa/ike_sa_id.h b/src/libcharon/sa/ike_sa_id.h
index 5eb754e95..b3a9ef61f 100644
--- a/src/libcharon/sa/ike_sa_id.h
+++ b/src/libcharon/sa/ike_sa_id.h
@@ -41,7 +41,7 @@ struct ike_sa_id_t {
*
* @return IKE version
*/
- u_int8_t (*get_ike_version) (ike_sa_id_t *this);
+ uint8_t (*get_ike_version) (ike_sa_id_t *this);
/**
* Set the SPI of the responder.
@@ -50,28 +50,28 @@ struct ike_sa_id_t {
*
* @param responder_spi SPI of responder to set
*/
- void (*set_responder_spi) (ike_sa_id_t *this, u_int64_t responder_spi);
+ void (*set_responder_spi) (ike_sa_id_t *this, uint64_t responder_spi);
/**
* Set the SPI of the initiator.
*
* @param initiator_spi SPI to set
*/
- void (*set_initiator_spi) (ike_sa_id_t *this, u_int64_t initiator_spi);
+ void (*set_initiator_spi) (ike_sa_id_t *this, uint64_t initiator_spi);
/**
* Get the initiator SPI.
*
* @return SPI of the initiator
*/
- u_int64_t (*get_initiator_spi) (ike_sa_id_t *this);
+ uint64_t (*get_initiator_spi) (ike_sa_id_t *this);
/**
* Get the responder SPI.
*
* @return SPI of the responder
*/
- u_int64_t (*get_responder_spi) (ike_sa_id_t *this);
+ uint64_t (*get_responder_spi) (ike_sa_id_t *this);
/**
* Check if two ike_sa_id_t objects are equal.
@@ -131,7 +131,7 @@ struct ike_sa_id_t {
* @param is_initiaor TRUE if we are the original initiator
* @return ike_sa_id_t object
*/
-ike_sa_id_t * ike_sa_id_create(u_int8_t ike_version, u_int64_t initiator_spi,
- u_int64_t responder_spi, bool is_initiaor);
+ike_sa_id_t * ike_sa_id_create(uint8_t ike_version, uint64_t initiator_spi,
+ uint64_t responder_spi, bool is_initiaor);
#endif /** IKE_SA_ID_H_ @}*/
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 307ea3b4a..ce44207c4 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -113,7 +113,7 @@ struct entry_t {
/**
* message ID or hash of currently processing message, -1 if none
*/
- u_int32_t processing;
+ uint32_t processing;
};
/**
@@ -265,7 +265,7 @@ struct init_hash_t {
chunk_t hash;
/** our SPI allocated for the IKE_SA based on this message */
- u_int64_t our_spi;
+ uint64_t our_spi;
};
typedef struct segment_t segment_t;
@@ -977,9 +977,9 @@ static void remove_connected_peers(private_ike_sa_manager_t *this, entry_t *entr
/**
* Get a random SPI for new IKE_SAs
*/
-static u_int64_t get_spi(private_ike_sa_manager_t *this)
+static uint64_t get_spi(private_ike_sa_manager_t *this)
{
- u_int64_t spi;
+ uint64_t spi;
this->spi_lock->read_lock(this->spi_lock);
if (this->spi_cb.cb)
@@ -987,7 +987,7 @@ static u_int64_t get_spi(private_ike_sa_manager_t *this)
spi = this->spi_cb.cb(this->spi_cb.data);
}
else if (!this->rng ||
- !this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi))
+ !this->rng->get_bytes(this->rng, sizeof(spi), (uint8_t*)&spi))
{
spi = 0;
}
@@ -1007,8 +1007,8 @@ static bool get_init_hash(hasher_t *hasher, message_t *message, chunk_t *hash)
if (message->get_first_payload_type(message) == PLV1_FRAGMENT)
{ /* only hash the source IP, port and SPI for fragmented init messages */
- u_int16_t port;
- u_int64_t spi;
+ uint16_t port;
+ uint64_t spi;
src = message->get_source(message);
if (!hasher->allocate_hash(hasher, src->get_address(src), NULL))
@@ -1050,13 +1050,13 @@ static bool get_init_hash(hasher_t *hasher, message_t *message, chunk_t *hash)
* FAILED if the SPI allocation failed
*/
static status_t check_and_put_init_hash(private_ike_sa_manager_t *this,
- chunk_t init_hash, u_int64_t *our_spi)
+ chunk_t init_hash, uint64_t *our_spi)
{
table_item_t *item;
u_int row, segment;
mutex_t *mutex;
init_hash_t *init;
- u_int64_t spi;
+ uint64_t spi;
row = chunk_hash(init_hash) & this->table_mask;
segment = row & this->segment_mask;
@@ -1174,8 +1174,8 @@ METHOD(ike_sa_manager_t, checkout_new, ike_sa_t*,
{
ike_sa_id_t *ike_sa_id;
ike_sa_t *ike_sa;
- u_int8_t ike_version;
- u_int64_t spi;
+ uint8_t ike_version;
+ uint64_t spi;
ike_version = version == IKEV1 ? IKEV1_MAJOR_VERSION : IKEV2_MAJOR_VERSION;
@@ -1208,7 +1208,7 @@ METHOD(ike_sa_manager_t, checkout_new, ike_sa_t*,
/**
* Get the message ID or message hash to detect early retransmissions
*/
-static u_int32_t get_message_id_or_hash(message_t *message)
+static uint32_t get_message_id_or_hash(message_t *message)
{
if (message->get_major_version(message) == IKEV1_MAJOR_VERSION)
{
@@ -1273,7 +1273,7 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
if (is_init)
{
hasher_t *hasher;
- u_int64_t our_spi;
+ uint64_t our_spi;
chunk_t hash;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
@@ -1415,7 +1415,8 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*,
{
continue;
}
- if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING)
+ if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING ||
+ entry->ike_sa->get_state(entry->ike_sa) == IKE_REKEYED)
{ /* skip IKE_SAs which are not usable, wake other waiting threads */
entry->condvar->signal(entry->condvar);
continue;
@@ -1455,7 +1456,7 @@ out:
}
METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*,
- private_ike_sa_manager_t *this, u_int32_t id)
+ private_ike_sa_manager_t *this, uint32_t id)
{
enumerator_t *enumerator;
entry_t *entry;
@@ -2094,10 +2095,41 @@ METHOD(ike_sa_manager_t, set_spi_cb, void,
this->spi_lock->unlock(this->spi_lock);
}
+/**
+ * Destroy all entries
+ */
+static void destroy_all_entries(private_ike_sa_manager_t *this)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ u_int segment;
+
+ enumerator = create_table_enumerator(this);
+ while (enumerator->enumerate(enumerator, &entry, &segment))
+ {
+ charon->bus->set_sa(charon->bus, entry->ike_sa);
+ if (entry->half_open)
+ {
+ remove_half_open(this, entry);
+ }
+ if (entry->my_id && entry->other_id)
+ {
+ remove_connected_peers(this, entry);
+ }
+ if (entry->init_hash.ptr)
+ {
+ remove_init_hash(this, entry->init_hash);
+ }
+ remove_entry_at((private_enumerator_t*)enumerator);
+ entry_destroy(entry);
+ }
+ enumerator->destroy(enumerator);
+ charon->bus->set_sa(charon->bus, NULL);
+}
+
METHOD(ike_sa_manager_t, flush, void,
private_ike_sa_manager_t *this)
{
- /* destroy all list entries */
enumerator_t *enumerator;
entry_t *entry;
u_int segment;
@@ -2153,31 +2185,11 @@ METHOD(ike_sa_manager_t, flush, void,
DBG2(DBG_MGR, "destroy all entries");
/* Step 4: destroy all entries */
- enumerator = create_table_enumerator(this);
- while (enumerator->enumerate(enumerator, &entry, &segment))
- {
- charon->bus->set_sa(charon->bus, entry->ike_sa);
- if (entry->half_open)
- {
- remove_half_open(this, entry);
- }
- if (entry->my_id && entry->other_id)
- {
- remove_connected_peers(this, entry);
- }
- if (entry->init_hash.ptr)
- {
- remove_init_hash(this, entry->init_hash);
- }
- remove_entry_at((private_enumerator_t*)enumerator);
- entry_destroy(entry);
- }
- enumerator->destroy(enumerator);
- charon->bus->set_sa(charon->bus, NULL);
+ destroy_all_entries(this);
unlock_all_segments(this);
this->spi_lock->write_lock(this->spi_lock);
- this->rng->destroy(this->rng);
+ DESTROY_IF(this->rng);
this->rng = NULL;
this->spi_cb.cb = NULL;
this->spi_cb.data = NULL;
@@ -2189,7 +2201,11 @@ METHOD(ike_sa_manager_t, destroy, void,
{
u_int i;
- /* these are already cleared in flush() above */
+ /* in case new SAs were checked in after flush() was called */
+ lock_all_segments(this);
+ destroy_all_entries(this);
+ unlock_all_segments(this);
+
free(this->ike_sa_table);
free(this->half_open_table);
free(this->connected_peers_table);
diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h
index f1b7c2579..4298c54e2 100644
--- a/src/libcharon/sa/ike_sa_manager.h
+++ b/src/libcharon/sa/ike_sa_manager.h
@@ -38,7 +38,7 @@ typedef struct ike_sa_manager_t ike_sa_manager_t;
* @param data data supplied during registration of the callback
* @return allocated SPI, 0 on failure
*/
-typedef u_int64_t (*spi_cb_t)(void *data);
+typedef uint64_t (*spi_cb_t)(void *data);
/**
* Manages and synchronizes access to all IKE_SAs.
@@ -147,7 +147,7 @@ struct ike_sa_manager_t {
* - checked out IKE_SA, if found
* - NULL, if not found
*/
- ike_sa_t* (*checkout_by_id) (ike_sa_manager_t* this, u_int32_t id);
+ ike_sa_t* (*checkout_by_id) (ike_sa_manager_t* this, uint32_t id);
/**
* Check out an IKE_SA by the policy/connection name.
diff --git a/src/libcharon/sa/ikev1/keymat_v1.c b/src/libcharon/sa/ikev1/keymat_v1.c
index e428966ad..be6b03bef 100644
--- a/src/libcharon/sa/ikev1/keymat_v1.c
+++ b/src/libcharon/sa/ikev1/keymat_v1.c
@@ -32,7 +32,7 @@ typedef struct private_keymat_v1_t private_keymat_v1_t;
*/
typedef struct {
/** message ID */
- u_int32_t mid;
+ uint32_t mid;
/** current IV */
chunk_t iv;
/** last block of encrypted message */
@@ -128,7 +128,7 @@ static void iv_data_destroy(iv_data_t *this)
*/
typedef struct {
/** message ID */
- u_int32_t mid;
+ uint32_t mid;
/** Ni_b (Nonce from first message) */
chunk_t n_i;
/** Nr_b (Nonce from second message) */
@@ -272,7 +272,7 @@ static bool expand_skeyid_e(chunk_t skeyid_e, size_t key_size, prf_t *prf,
static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e)
{
private_aead_t *this;
- u_int16_t alg, key_size;
+ uint16_t alg, key_size;
crypter_t *crypter;
chunk_t ka;
@@ -324,7 +324,7 @@ static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e)
/**
* Converts integrity algorithm to PRF algorithm
*/
-static u_int16_t auth_to_prf(u_int16_t alg)
+static uint16_t auth_to_prf(uint16_t alg)
{
switch (alg)
{
@@ -348,7 +348,7 @@ static u_int16_t auth_to_prf(u_int16_t alg)
/**
* Converts integrity algorithm to hash algorithm
*/
-static u_int16_t auth_to_hash(u_int16_t alg)
+static uint16_t auth_to_hash(uint16_t alg)
{
switch (alg)
{
@@ -370,7 +370,7 @@ static u_int16_t auth_to_hash(u_int16_t alg)
/**
* Adjust the key length for PRF algorithms that expect a fixed key length.
*/
-static void adjust_keylen(u_int16_t alg, chunk_t *key)
+static void adjust_keylen(uint16_t alg, chunk_t *key)
{
switch (alg)
{
@@ -393,10 +393,10 @@ METHOD(keymat_v1_t, derive_ike_keys, bool,
{
chunk_t g_xy, g_xi, g_xr, dh_me, spi_i, spi_r, nonces, data, skeyid_e;
chunk_t skeyid;
- u_int16_t alg;
+ uint16_t alg;
- spi_i = chunk_alloca(sizeof(u_int64_t));
- spi_r = chunk_alloca(sizeof(u_int64_t));
+ spi_i = chunk_alloca(sizeof(uint64_t));
+ spi_r = chunk_alloca(sizeof(uint64_t));
if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
{ /* no PRF negotiated, use HMAC version of integrity algorithm instead */
@@ -431,8 +431,8 @@ METHOD(keymat_v1_t, derive_ike_keys, bool,
}
DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &g_xy);
- *((u_int64_t*)spi_i.ptr) = id->get_initiator_spi(id);
- *((u_int64_t*)spi_r.ptr) = id->get_responder_spi(id);
+ *((uint64_t*)spi_i.ptr) = id->get_initiator_spi(id);
+ *((uint64_t*)spi_r.ptr) = id->get_responder_spi(id);
nonces = chunk_cata("cc", nonce_i, nonce_r);
switch (auth)
@@ -585,11 +585,11 @@ METHOD(keymat_v1_t, derive_ike_keys, bool,
METHOD(keymat_v1_t, derive_child_keys, bool,
private_keymat_v1_t *this, proposal_t *proposal, diffie_hellman_t *dh,
- u_int32_t spi_i, u_int32_t spi_r, chunk_t nonce_i, chunk_t nonce_r,
+ uint32_t spi_i, uint32_t spi_r, chunk_t nonce_i, chunk_t nonce_r,
chunk_t *encr_i, chunk_t *integ_i, chunk_t *encr_r, chunk_t *integ_r)
{
- u_int16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
- u_int8_t protocol;
+ uint16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
+ uint8_t protocol;
prf_plus_t *prf_plus;
chunk_t seed, secret = chunk_empty;
bool success = FALSE;
@@ -725,7 +725,7 @@ failure:
METHOD(keymat_v1_t, create_hasher, bool,
private_keymat_v1_t *this, proposal_t *proposal)
{
- u_int16_t alg;
+ uint16_t alg;
if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL) ||
(alg = auth_to_hash(alg)) == HASH_UNKNOWN)
{
@@ -754,7 +754,7 @@ METHOD(keymat_v1_t, get_hash, bool,
ike_sa_id_t *ike_sa_id, chunk_t sa_i, chunk_t id, chunk_t *hash)
{
chunk_t data;
- u_int64_t spi, spi_other;
+ uint64_t spi, spi_other;
/* HASH_I = prf(SKEYID, g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b )
* HASH_R = prf(SKEYID, g^xr | g^xi | CKY-R | CKY-I | SAi_b | IDir_b )
@@ -810,7 +810,7 @@ static chunk_t get_message_data(message_t *message, generator_t *generator)
{
payload_t *payload, *next;
enumerator_t *enumerator;
- u_int32_t *lenpos;
+ uint32_t *lenpos;
if (message->is_encoded(message))
{ /* inbound, although the message is generated, we cannot access the
@@ -850,7 +850,7 @@ static chunk_t get_message_data(message_t *message, generator_t *generator)
* Try to find data about a Quick Mode with the given message ID,
* if none is found, state is generated.
*/
-static qm_data_t *lookup_quick_mode(private_keymat_v1_t *this, u_int32_t mid)
+static qm_data_t *lookup_quick_mode(private_keymat_v1_t *this, uint32_t mid)
{
enumerator_t *enumerator;
qm_data_t *qm, *found = NULL;
@@ -885,7 +885,7 @@ static qm_data_t *lookup_quick_mode(private_keymat_v1_t *this, u_int32_t mid)
METHOD(keymat_v1_t, get_hash_phase2, bool,
private_keymat_v1_t *this, message_t *message, chunk_t *hash)
{
- u_int32_t mid, mid_n;
+ uint32_t mid, mid_n;
chunk_t data = chunk_empty;
bool add_message = TRUE;
char *name = "Hash";
@@ -993,7 +993,7 @@ static bool generate_iv(private_keymat_v1_t *this, iv_data_t *iv)
else
{
/* initial phase 2 IV = hash(last_phase1_block | mid) */
- u_int32_t net;;
+ uint32_t net;;
chunk_t data;
net = htonl(iv->mid);
@@ -1014,7 +1014,7 @@ static bool generate_iv(private_keymat_v1_t *this, iv_data_t *iv)
/**
* Try to find an IV for the given message ID, if not found, generate it.
*/
-static iv_data_t *lookup_iv(private_keymat_v1_t *this, u_int32_t mid)
+static iv_data_t *lookup_iv(private_keymat_v1_t *this, uint32_t mid)
{
enumerator_t *enumerator;
iv_data_t *iv, *found = NULL;
@@ -1057,7 +1057,7 @@ static iv_data_t *lookup_iv(private_keymat_v1_t *this, u_int32_t mid)
}
METHOD(keymat_v1_t, get_iv, bool,
- private_keymat_v1_t *this, u_int32_t mid, chunk_t *out)
+ private_keymat_v1_t *this, uint32_t mid, chunk_t *out)
{
iv_data_t *iv;
@@ -1071,7 +1071,7 @@ METHOD(keymat_v1_t, get_iv, bool,
}
METHOD(keymat_v1_t, update_iv, bool,
- private_keymat_v1_t *this, u_int32_t mid, chunk_t last_block)
+ private_keymat_v1_t *this, uint32_t mid, chunk_t last_block)
{
iv_data_t *iv = lookup_iv(this, mid);
if (iv)
@@ -1084,7 +1084,7 @@ METHOD(keymat_v1_t, update_iv, bool,
}
METHOD(keymat_v1_t, confirm_iv, bool,
- private_keymat_v1_t *this, u_int32_t mid)
+ private_keymat_v1_t *this, uint32_t mid)
{
iv_data_t *iv = lookup_iv(this, mid);
if (iv)
diff --git a/src/libcharon/sa/ikev1/keymat_v1.h b/src/libcharon/sa/ikev1/keymat_v1.h
index cc9f3b339..46eeea8b6 100644
--- a/src/libcharon/sa/ikev1/keymat_v1.h
+++ b/src/libcharon/sa/ikev1/keymat_v1.h
@@ -72,7 +72,7 @@ struct keymat_v1_t {
* @param integ_r allocated responders integrity key
*/
bool (*derive_child_keys)(keymat_v1_t *this, proposal_t *proposal,
- diffie_hellman_t *dh, u_int32_t spi_i, u_int32_t spi_r,
+ diffie_hellman_t *dh, uint32_t spi_i, uint32_t spi_r,
chunk_t nonce_i, chunk_t nonce_r,
chunk_t *encr_i, chunk_t *integ_i,
chunk_t *encr_r, chunk_t *integ_r);
@@ -127,7 +127,7 @@ struct keymat_v1_t {
* @param iv chunk receiving IV, internal data
* @return TRUE if IV allocated successfully
*/
- bool (*get_iv)(keymat_v1_t *this, u_int32_t mid, chunk_t *iv);
+ bool (*get_iv)(keymat_v1_t *this, uint32_t mid, chunk_t *iv);
/**
* Updates the IV for the next message with the given message ID.
@@ -141,7 +141,7 @@ struct keymat_v1_t {
* @param last_block last block of encrypted message (gets cloned)
* @return TRUE if IV updated successfully
*/
- bool (*update_iv)(keymat_v1_t *this, u_int32_t mid, chunk_t last_block);
+ bool (*update_iv)(keymat_v1_t *this, uint32_t mid, chunk_t last_block);
/**
* Confirms the updated IV for the given message ID.
@@ -152,7 +152,7 @@ struct keymat_v1_t {
* @param mid message ID
* @return TRUE if IV confirmed successfully
*/
- bool (*confirm_iv)(keymat_v1_t *this, u_int32_t mid);
+ bool (*confirm_iv)(keymat_v1_t *this, uint32_t mid);
};
/**
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index 3c601a4fa..b0c4f5f84 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2007-2015 Tobias Brunner
+ * Copyright (C) 2007-2016 Tobias Brunner
* Copyright (C) 2007-2011 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -67,7 +67,7 @@ struct exchange_t {
/**
* Message ID used for this transaction
*/
- u_int32_t mid;
+ uint32_t mid;
/**
* generated packet for retransmission
@@ -104,12 +104,12 @@ struct private_task_manager_t {
/**
* Message ID of the last response
*/
- u_int32_t mid;
+ uint32_t mid;
/**
* Hash of a previously received message
*/
- u_int32_t hash;
+ uint32_t hash;
/**
* packet(s) for retransmission
@@ -119,7 +119,7 @@ struct private_task_manager_t {
/**
* Sequence number of the last sent message
*/
- u_int32_t seqnr;
+ uint32_t seqnr;
/**
* how many times we have retransmitted so far
@@ -135,12 +135,12 @@ struct private_task_manager_t {
/**
* Message ID of the exchange
*/
- u_int32_t mid;
+ uint32_t mid;
/**
* Hashes of old responses we can ignore
*/
- u_int32_t old_hashes[MAX_OLD_HASHES];
+ uint32_t old_hashes[MAX_OLD_HASHES];
/**
* Position in old hash array
@@ -150,7 +150,7 @@ struct private_task_manager_t {
/**
* Sequence number of the last sent message
*/
- u_int32_t seqnr;
+ uint32_t seqnr;
/**
* how many times we have retransmitted so far
@@ -212,12 +212,12 @@ struct private_task_manager_t {
/**
* Sequence number for sending DPD requests
*/
- u_int32_t dpd_send;
+ uint32_t dpd_send;
/**
* Sequence number for received DPD requests
*/
- u_int32_t dpd_recv;
+ uint32_t dpd_recv;
};
/**
@@ -341,11 +341,11 @@ static bool generate_message(private_task_manager_t *this, message_t *message,
/**
* Retransmit a packet (or its fragments)
*/
-static status_t retransmit_packet(private_task_manager_t *this, u_int32_t seqnr,
+static status_t retransmit_packet(private_task_manager_t *this, uint32_t seqnr,
u_int mid, u_int retransmitted, array_t *packets)
{
packet_t *packet;
- u_int32_t t;
+ uint32_t t;
array_get(packets, 0, &packet);
if (retransmitted > this->retransmit_tries)
@@ -354,14 +354,15 @@ static status_t retransmit_packet(private_task_manager_t *this, u_int32_t seqnr,
charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_TIMEOUT, packet);
return DESTROY_ME;
}
- t = (u_int32_t)(this->retransmit_timeout * 1000.0 *
+ t = (uint32_t)(this->retransmit_timeout * 1000.0 *
pow(this->retransmit_base, retransmitted));
if (retransmitted)
{
DBG1(DBG_IKE, "sending retransmit %u of %s message ID %u, seq %u",
retransmitted, seqnr < RESPONDING_SEQ ? "request" : "response",
mid, seqnr < RESPONDING_SEQ ? seqnr : seqnr - RESPONDING_SEQ);
- charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, packet);
+ charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, packet,
+ retransmitted);
}
send_packets(this, packets);
lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
@@ -370,7 +371,7 @@ static status_t retransmit_packet(private_task_manager_t *this, u_int32_t seqnr,
}
METHOD(task_manager_t, retransmit, status_t,
- private_task_manager_t *this, u_int32_t seqnr)
+ private_task_manager_t *this, uint32_t seqnr)
{
status_t status = SUCCESS;
@@ -514,26 +515,26 @@ METHOD(task_manager_t, initiate, status_t,
new_mid = TRUE;
break;
}
- if (!mode_config_expected(this) &&
- activate_task(this, TASK_QUICK_MODE))
+ if (activate_task(this, TASK_ISAKMP_DELETE))
{
- exchange = QUICK_MODE;
+ exchange = INFORMATIONAL_V1;
new_mid = TRUE;
break;
}
- if (activate_task(this, TASK_INFORMATIONAL))
+ if (activate_task(this, TASK_QUICK_DELETE))
{
exchange = INFORMATIONAL_V1;
new_mid = TRUE;
break;
}
- if (activate_task(this, TASK_QUICK_DELETE))
+ if (!mode_config_expected(this) &&
+ activate_task(this, TASK_QUICK_MODE))
{
- exchange = INFORMATIONAL_V1;
+ exchange = QUICK_MODE;
new_mid = TRUE;
break;
}
- if (activate_task(this, TASK_ISAKMP_DELETE))
+ if (activate_task(this, TASK_INFORMATIONAL))
{
exchange = INFORMATIONAL_V1;
new_mid = TRUE;
@@ -807,7 +808,7 @@ static void send_notify(private_task_manager_t *this, message_t *request,
message_t *response;
array_t *packets = NULL;
host_t *me, *other;
- u_int32_t mid;
+ uint32_t mid;
if (request->get_exchange_type(request) == INFORMATIONAL_V1)
{ /* don't respond to INFORMATIONAL requests to avoid a notify war */
@@ -857,7 +858,7 @@ static bool process_dpd(private_task_manager_t *this, message_t *message)
{
notify_payload_t *notify;
notify_type_t type;
- u_int32_t seq;
+ uint32_t seq;
chunk_t data;
type = DPD_R_U_THERE;
@@ -910,7 +911,7 @@ static bool process_dpd(private_task_manager_t *this, message_t *message)
* Check if we already have a quick mode task queued for the exchange with the
* given message ID
*/
-static bool have_quick_mode_task(private_task_manager_t *this, u_int32_t mid)
+static bool have_quick_mode_task(private_task_manager_t *this, uint32_t mid)
{
enumerator_t *enumerator;
quick_mode_t *qm;
@@ -935,9 +936,9 @@ static bool have_quick_mode_task(private_task_manager_t *this, u_int32_t mid)
}
/**
- * Check if we still have an aggressive mode task queued
+ * Check if we still have a specific task queued
*/
-static bool have_aggressive_mode_task(private_task_manager_t *this)
+static bool have_task_queued(private_task_manager_t *this, task_type_t type)
{
enumerator_t *enumerator;
task_t *task;
@@ -946,7 +947,7 @@ static bool have_aggressive_mode_task(private_task_manager_t *this)
enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
while (enumerator->enumerate(enumerator, &task))
{
- if (task->get_type(task) == TASK_AGGRESSIVE_MODE)
+ if (task->get_type(task) == type)
{
found = TRUE;
break;
@@ -1180,6 +1181,12 @@ static status_t process_response(private_task_manager_t *this,
}
enumerator->destroy(enumerator);
+ if (this->initiating.retransmitted)
+ {
+ packet_t *packet = NULL;
+ array_get(this->initiating.packets, 0, &packet);
+ charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_CLEARED, packet);
+ }
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
clear_packets(this->initiating.packets);
@@ -1305,7 +1312,7 @@ static status_t queue_message(private_task_manager_t *this, message_t *msg)
METHOD(task_manager_t, process_message, status_t,
private_task_manager_t *this, message_t *msg)
{
- u_int32_t hash, mid, i;
+ uint32_t hash, mid, i;
host_t *me, *other;
status_t status;
@@ -1405,7 +1412,7 @@ METHOD(task_manager_t, process_message, status_t,
/* drop XAuth/Mode Config/Quick Mode messages until we received the last
* Aggressive Mode message. since Informational messages are not
* retransmitted we queue them. */
- if (have_aggressive_mode_task(this))
+ if (have_task_queued(this, TASK_AGGRESSIVE_MODE))
{
if (msg->get_exchange_type(msg) == INFORMATIONAL_V1)
{
@@ -1427,6 +1434,13 @@ METHOD(task_manager_t, process_message, status_t,
return queue_message(this, msg);
}
+ /* some peers send INITIAL_CONTACT notifies during XAuth, cache it */
+ if (have_task_queued(this, TASK_XAUTH) &&
+ msg->get_exchange_type(msg) == INFORMATIONAL_V1)
+ {
+ return queue_message(this, msg);
+ }
+
msg->set_request(msg, TRUE);
charon->bus->message(charon->bus, msg, TRUE, FALSE);
status = parse_message(this, msg);
@@ -1499,8 +1513,8 @@ static bool has_queued(private_task_manager_t *this, task_type_t type)
return found;
}
-METHOD(task_manager_t, queue_task, void,
- private_task_manager_t *this, task_t *task)
+METHOD(task_manager_t, queue_task_delayed, void,
+ private_task_manager_t *this, task_t *task, uint32_t delay)
{
task_type_t type = task->get_type(task);
@@ -1521,6 +1535,12 @@ METHOD(task_manager_t, queue_task, void,
this->queued_tasks->insert_last(this->queued_tasks, task);
}
+METHOD(task_manager_t, queue_task, void,
+ private_task_manager_t *this, task_t *task)
+{
+ queue_task_delayed(this, task, 0);
+}
+
METHOD(task_manager_t, queue_ike, void,
private_task_manager_t *this)
{
@@ -1660,7 +1680,7 @@ METHOD(task_manager_t, queue_mobike, void,
}
METHOD(task_manager_t, queue_child, void,
- private_task_manager_t *this, child_cfg_t *cfg, u_int32_t reqid,
+ private_task_manager_t *this, child_cfg_t *cfg, uint32_t reqid,
traffic_selector_t *tsi, traffic_selector_t *tsr)
{
quick_mode_t *task;
@@ -1739,7 +1759,7 @@ static traffic_selector_t* get_first_ts(child_sa_t *child_sa, bool local)
}
METHOD(task_manager_t, queue_child_rekey, void,
- private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi)
+ private_task_manager_t *this, protocol_id_t protocol, uint32_t spi)
{
child_sa_t *child_sa;
child_cfg_t *cfg;
@@ -1754,6 +1774,7 @@ METHOD(task_manager_t, queue_child_rekey, void,
{
if (is_redundant(this, child_sa))
{
+ child_sa->set_state(child_sa, CHILD_REKEYED);
queue_task(this, (task_t*)quick_delete_create(this->ike_sa,
protocol, spi, FALSE, FALSE));
}
@@ -1774,7 +1795,7 @@ METHOD(task_manager_t, queue_child_rekey, void,
}
METHOD(task_manager_t, queue_child_delete, void,
- private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi,
+ private_task_manager_t *this, protocol_id_t protocol, uint32_t spi,
bool expired)
{
queue_task(this, (task_t*)quick_delete_create(this->ike_sa, protocol,
@@ -1785,7 +1806,7 @@ METHOD(task_manager_t, queue_dpd, void,
private_task_manager_t *this)
{
peer_cfg_t *peer_cfg;
- u_int32_t t, retransmit;
+ uint32_t t, retransmit;
queue_task(this, (task_t*)isakmp_dpd_create(this->ike_sa, DPD_R_U_THERE,
this->dpd_send++));
@@ -1798,7 +1819,7 @@ METHOD(task_manager_t, queue_dpd, void,
/* use the same timeout as a retransmitting IKE message would have */
for (retransmit = 0; retransmit <= this->retransmit_tries; retransmit++)
{
- t += (u_int32_t)(this->retransmit_timeout * 1000.0 *
+ t += (uint32_t)(this->retransmit_timeout * 1000.0 *
pow(this->retransmit_base, retransmit));
}
}
@@ -1871,7 +1892,7 @@ METHOD(task_manager_t, incr_mid, void,
}
METHOD(task_manager_t, reset, void,
- private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
+ private_task_manager_t *this, uint32_t initiate, uint32_t respond)
{
enumerator_t *enumerator;
task_t *task;
@@ -1960,6 +1981,7 @@ task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
.task_manager = {
.process_message = _process_message,
.queue_task = _queue_task,
+ .queue_task_delayed = _queue_task_delayed,
.queue_ike = _queue_ike,
.queue_ike_rekey = _queue_ike_rekey,
.queue_ike_reauth = _queue_ike_reauth,
diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
index 710bf1cd2..9b5f676a3 100644
--- a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
@@ -77,7 +77,7 @@ struct private_aggressive_mode_t {
/**
* Negotiated SA lifetime
*/
- u_int32_t lifetime;
+ uint32_t lifetime;
/**
* Negotiated authentication method
@@ -164,7 +164,7 @@ static status_t send_notify(private_aggressive_mode_t *this, notify_type_t type)
{
notify_payload_t *notify;
ike_sa_id_t *ike_sa_id;
- u_int64_t spi_i, spi_r;
+ uint64_t spi_i, spi_r;
chunk_t spi;
notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
@@ -219,7 +219,7 @@ METHOD(task_t, build_i, status_t,
linked_list_t *proposals;
identification_t *id;
packet_t *packet;
- u_int16_t group;
+ uint16_t group;
DBG0(DBG_IKE, "initiating Aggressive Mode IKE_SA %s[%d] to %H",
this->ike_sa->get_name(this->ike_sa),
@@ -377,7 +377,8 @@ METHOD(task_t, process_r, status_t,
id_payload_t *id_payload;
identification_t *id;
linked_list_t *list;
- u_int16_t group;
+ uint16_t group;
+ bool prefer_configured;
this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
DBG0(DBG_IKE, "%H is initiating a Aggressive Mode IKE_SA",
@@ -401,8 +402,10 @@ METHOD(task_t, process_r, status_t,
}
list = sa_payload->get_proposals(sa_payload);
+ prefer_configured = lib->settings->get_bool(lib->settings,
+ "%s.prefer_configured_proposals", TRUE, lib->ns);
this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
- list, FALSE);
+ list, FALSE, prefer_configured);
list->destroy_offset(list, offsetof(proposal_t, destroy));
if (!this->proposal)
{
@@ -629,7 +632,7 @@ METHOD(task_t, process_i, status_t,
id_payload_t *id_payload;
identification_t *id, *cid;
linked_list_t *list;
- u_int32_t lifetime;
+ uint32_t lifetime;
sa_payload = (sa_payload_t*)message->get_payload(message,
PLV1_SECURITY_ASSOCIATION);
@@ -640,7 +643,7 @@ METHOD(task_t, process_i, status_t,
}
list = sa_payload->get_proposals(sa_payload);
this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
- list, FALSE);
+ list, FALSE, TRUE);
list->destroy_offset(list, offsetof(proposal_t, destroy));
if (!this->proposal)
{
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_delete.c b/src/libcharon/sa/ikev1/tasks/isakmp_delete.c
index a56805afb..df0293d4f 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_delete.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_delete.c
@@ -81,7 +81,7 @@ METHOD(task_t, process_r, status_t,
payload_t *payload;
delete_payload_t *delete_payload;
ike_sa_id_t *id;
- u_int64_t spi_i, spi_r;
+ uint64_t spi_i, spi_r;
bool found = FALSE;
/* some peers send DELETE payloads for other IKE_SAs, e.g. those for expired
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_dpd.c b/src/libcharon/sa/ikev1/tasks/isakmp_dpd.c
index 5522e9221..840d352b1 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_dpd.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_dpd.c
@@ -33,7 +33,7 @@ struct private_isakmp_dpd_t {
/**
* Sequence number.
*/
- u_int32_t seqnr;
+ uint32_t seqnr;
/**
* DPD notify type
@@ -51,8 +51,8 @@ METHOD(task_t, build, status_t,
{
notify_payload_t *notify;
ike_sa_id_t *ike_sa_id;
- u_int64_t spi_i, spi_r;
- u_int32_t seqnr;
+ uint64_t spi_i, spi_r;
+ uint32_t seqnr;
chunk_t spi;
notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
@@ -100,7 +100,7 @@ METHOD(task_t, destroy, void,
* Described in header.
*/
isakmp_dpd_t *isakmp_dpd_create(ike_sa_t *ike_sa, notify_type_t type,
- u_int32_t seqnr)
+ uint32_t seqnr)
{
private_isakmp_dpd_t *this;
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_dpd.h b/src/libcharon/sa/ikev1/tasks/isakmp_dpd.h
index 06a0175eb..9a69b423c 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_dpd.h
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_dpd.h
@@ -47,6 +47,6 @@ struct isakmp_dpd_t {
* @return ISAKMP_DPD task to handle by the task_manager
*/
isakmp_dpd_t *isakmp_dpd_create(ike_sa_t *ike_sa, notify_type_t type,
- u_int32_t seqnr);
+ uint32_t seqnr);
#endif /** ISAKMP_DPD_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_natd.c b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
index cb1a31371..d17948cd0 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
@@ -129,8 +129,8 @@ static chunk_t generate_natd_hash(private_isakmp_natd_t *this,
{
hasher_t *hasher;
chunk_t natd_chunk, natd_hash;
- u_int64_t spi_i, spi_r;
- u_int16_t port;
+ uint64_t spi_i, spi_r;
+ uint16_t port;
hasher = this->keymat->get_hasher(this->keymat);
if (!hasher)
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
index 0162fd84e..f28b83e8a 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
@@ -170,7 +170,7 @@ static struct {
* for fragmentation of base ISAKMP messages (Cisco adds that and thus sends
* 0xc0000000)
*/
-static const u_int32_t fragmentation_ike = 0x80000000;
+static const uint32_t fragmentation_ike = 0x80000000;
static bool is_known_vid(chunk_t data, int i)
{
diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c
index 3ea4a2a85..628ea0de8 100644
--- a/src/libcharon/sa/ikev1/tasks/main_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/main_mode.c
@@ -77,7 +77,7 @@ struct private_main_mode_t {
/**
* Negotiated SA lifetime
*/
- u_int32_t lifetime;
+ uint32_t lifetime;
/**
* Negotiated authentication method
@@ -173,7 +173,7 @@ static status_t send_notify(private_main_mode_t *this, notify_type_t type)
{
notify_payload_t *notify;
ike_sa_id_t *ike_sa_id;
- u_int64_t spi_i, spi_r;
+ uint64_t spi_i, spi_r;
chunk_t spi;
notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
@@ -215,7 +215,7 @@ static void add_initial_contact(private_main_mode_t *this, message_t *message,
host_t *host;
notify_payload_t *notify;
ike_sa_id_t *ike_sa_id;
- u_int64_t spi_i, spi_r;
+ uint64_t spi_i, spi_r;
chunk_t spi;
idr = this->ph1->get_id(this->ph1, this->peer_cfg, FALSE);
@@ -303,7 +303,7 @@ METHOD(task_t, build_i, status_t,
}
case MM_SA:
{
- u_int16_t group;
+ uint16_t group;
if (!this->ph1->create_hasher(this->ph1))
{
@@ -367,7 +367,7 @@ METHOD(task_t, process_r, status_t,
{
linked_list_t *list;
sa_payload_t *sa_payload;
- bool private;
+ bool private, prefer_configured;
this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
DBG0(DBG_IKE, "%H is initiating a Main Mode IKE_SA",
@@ -392,9 +392,11 @@ METHOD(task_t, process_r, status_t,
list = sa_payload->get_proposals(sa_payload);
private = this->ike_sa->supports_extension(this->ike_sa,
- EXT_STRONGSWAN);
+ EXT_STRONGSWAN);
+ prefer_configured = lib->settings->get_bool(lib->settings,
+ "%s.prefer_configured_proposals", TRUE, lib->ns);
this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
- list, private);
+ list, private, prefer_configured);
list->destroy_offset(list, offsetof(proposal_t, destroy));
if (!this->proposal)
{
@@ -411,7 +413,7 @@ METHOD(task_t, process_r, status_t,
}
case MM_SA:
{
- u_int16_t group;
+ uint16_t group;
if (!this->ph1->create_hasher(this->ph1))
{
@@ -627,7 +629,7 @@ METHOD(task_t, process_i, status_t,
linked_list_t *list;
sa_payload_t *sa_payload;
auth_method_t method;
- u_int32_t lifetime;
+ uint32_t lifetime;
bool private;
sa_payload = (sa_payload_t*)message->get_payload(message,
@@ -641,7 +643,7 @@ METHOD(task_t, process_i, status_t,
private = this->ike_sa->supports_extension(this->ike_sa,
EXT_STRONGSWAN);
this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
- list, private);
+ list, private, TRUE);
list->destroy_offset(list, offsetof(proposal_t, destroy));
if (!this->proposal)
{
diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.c b/src/libcharon/sa/ikev1/tasks/mode_config.c
index b9f924009..7098d24a2 100644
--- a/src/libcharon/sa/ikev1/tasks/mode_config.c
+++ b/src/libcharon/sa/ikev1/tasks/mode_config.c
@@ -58,7 +58,7 @@ struct private_mode_config_t {
/**
* Identifier to include in response
*/
- u_int16_t identifier;
+ uint16_t identifier;
};
/**
diff --git a/src/libcharon/sa/ikev1/tasks/quick_delete.c b/src/libcharon/sa/ikev1/tasks/quick_delete.c
index ade59a2dd..66ef50811 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_delete.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_delete.c
@@ -69,7 +69,7 @@ struct private_quick_delete_t {
/**
* Inbound SPI of CHILD_SA to delete
*/
- u_int32_t spi;
+ uint32_t spi;
/**
* Send delete even if SA does not exist
@@ -86,9 +86,9 @@ struct private_quick_delete_t {
* Delete the specified CHILD_SA, if found
*/
static bool delete_child(private_quick_delete_t *this, protocol_id_t protocol,
- u_int32_t spi, bool remote_close)
+ uint32_t spi, bool remote_close)
{
- u_int64_t bytes_in, bytes_out;
+ uint64_t bytes_in, bytes_out;
child_sa_t *child_sa;
linked_list_t *my_ts, *other_ts;
child_cfg_t *child_cfg;
@@ -200,7 +200,7 @@ METHOD(task_t, process_r, status_t,
payload_t *payload;
delete_payload_t *delete_payload;
protocol_id_t protocol;
- u_int32_t spi;
+ uint32_t spi;
payloads = message->create_payload_enumerator(message);
while (payloads->enumerate(payloads, &payload))
@@ -260,7 +260,7 @@ METHOD(task_t, destroy, void,
* Described in header.
*/
quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
- u_int32_t spi, bool force, bool expired)
+ uint32_t spi, bool force, bool expired)
{
private_quick_delete_t *this;
diff --git a/src/libcharon/sa/ikev1/tasks/quick_delete.h b/src/libcharon/sa/ikev1/tasks/quick_delete.h
index 4df30c8fe..6227b364b 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_delete.h
+++ b/src/libcharon/sa/ikev1/tasks/quick_delete.h
@@ -50,6 +50,6 @@ struct quick_delete_t {
* @return quick_delete task to handle by the task_manager
*/
quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
- u_int32_t spi, bool force, bool expired);
+ uint32_t spi, bool force, bool expired);
#endif /** QUICK_DELETE_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index b4fe04663..bbd1cb09f 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -98,22 +98,22 @@ struct private_quick_mode_t {
/**
* Initiators ESP SPI
*/
- u_int32_t spi_i;
+ uint32_t spi_i;
/**
* Responder ESP SPI
*/
- u_int32_t spi_r;
+ uint32_t spi_r;
/**
* Initiators IPComp CPI
*/
- u_int16_t cpi_i;
+ uint16_t cpi_i;
/**
* Responders IPComp CPI
*/
- u_int16_t cpi_r;
+ uint16_t cpi_r;
/**
* selected CHILD_SA proposal
@@ -143,17 +143,17 @@ struct private_quick_mode_t {
/**
* Negotiated lifetime of new SA
*/
- u_int32_t lifetime;
+ uint32_t lifetime;
/**
- * Negotaited lifebytes of new SA
+ * Negotiated lifebytes of new SA
*/
- u_int64_t lifebytes;
+ uint64_t lifebytes;
/**
* Reqid to use, 0 for auto-allocate
*/
- u_int32_t reqid;
+ uint32_t reqid;
/**
* Explicit inbound mark value to use, if any
@@ -168,7 +168,7 @@ struct private_quick_mode_t {
/**
* SPI of SA we rekey
*/
- u_int32_t rekey;
+ uint32_t rekey;
/**
* Delete old child after successful rekey
@@ -193,7 +193,7 @@ struct private_quick_mode_t {
/**
* Message ID of handled quick mode exchange
*/
- u_int32_t mid;
+ uint32_t mid;
/** states of quick mode */
enum {
@@ -207,7 +207,7 @@ struct private_quick_mode_t {
*/
static void schedule_inactivity_timeout(private_quick_mode_t *this)
{
- u_int32_t timeout;
+ uint32_t timeout;
bool close_ike;
timeout = this->config->get_inactivity(this->config);
@@ -722,12 +722,12 @@ static void get_lifetimes(private_quick_mode_t *this)
{
lifetime_cfg_t *lft;
- lft = this->config->get_lifetime(this->config);
+ lft = this->config->get_lifetime(this->config, TRUE);
if (lft->time.life)
{
this->lifetime = lft->time.life;
}
- else if (lft->bytes.life)
+ if (lft->bytes.life)
{
this->lifebytes = lft->bytes.life;
}
@@ -739,8 +739,8 @@ static void get_lifetimes(private_quick_mode_t *this)
*/
static void apply_lifetimes(private_quick_mode_t *this, sa_payload_t *sa_payload)
{
- u_int32_t lifetime;
- u_int64_t lifebytes;
+ uint32_t lifetime;
+ uint64_t lifebytes;
lifetime = sa_payload->get_lifetime(sa_payload);
lifebytes = sa_payload->get_lifebytes(sa_payload);
@@ -863,7 +863,7 @@ METHOD(task_t, build_i, status_t,
if (group != MODP_NONE)
{
proposal_t *proposal;
- u_int16_t preferred_group;
+ uint16_t preferred_group;
proposal = this->ike_sa->get_proposal(this->ike_sa);
proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
@@ -1007,7 +1007,6 @@ static void check_for_rekeyed_child(private_quick_mode_t *this)
{
case CHILD_INSTALLED:
case CHILD_REKEYING:
- case CHILD_REKEYED:
policies = child_sa->create_policy_enumerator(child_sa);
if (policies->enumerate(policies, &local, &remote) &&
local->equals(local, this->tsr) &&
@@ -1026,9 +1025,10 @@ static void check_for_rekeyed_child(private_quick_mode_t *this)
child_sa->get_unique_id(child_sa));
}
policies->destroy(policies);
- break;
- default:
- break;
+ break;
+ case CHILD_REKEYED:
+ default:
+ break;
}
}
}
@@ -1050,8 +1050,8 @@ METHOD(task_t, process_r, status_t,
sa_payload_t *sa_payload;
linked_list_t *tsi, *tsr, *hostsi, *hostsr, *list = NULL;
peer_cfg_t *peer_cfg;
- u_int16_t group;
- bool private;
+ uint16_t group;
+ bool private, prefer_configured;
sa_payload = (sa_payload_t*)message->get_payload(message,
PLV1_SECURITY_ASSOCIATION);
@@ -1109,8 +1109,10 @@ METHOD(task_t, process_r, status_t,
}
private = this->ike_sa->supports_extension(this->ike_sa,
EXT_STRONGSWAN);
- this->proposal = this->config->select_proposal(this->config,
- list, FALSE, private);
+ prefer_configured = lib->settings->get_bool(lib->settings,
+ "%s.prefer_configured_proposals", TRUE, lib->ns);
+ this->proposal = this->config->select_proposal(this->config, list,
+ FALSE, private, prefer_configured);
list->destroy_offset(list, offsetof(proposal_t, destroy));
get_lifetimes(this);
@@ -1323,8 +1325,8 @@ METHOD(task_t, process_i, status_t,
}
private = this->ike_sa->supports_extension(this->ike_sa,
EXT_STRONGSWAN);
- this->proposal = this->config->select_proposal(this->config,
- list, FALSE, private);
+ this->proposal = this->config->select_proposal(this->config, list,
+ FALSE, private, TRUE);
list->destroy_offset(list, offsetof(proposal_t, destroy));
if (!this->proposal)
{
@@ -1365,14 +1367,14 @@ METHOD(task_t, get_type, task_type_t,
return TASK_QUICK_MODE;
}
-METHOD(quick_mode_t, get_mid, u_int32_t,
+METHOD(quick_mode_t, get_mid, uint32_t,
private_quick_mode_t *this)
{
return this->mid;
}
METHOD(quick_mode_t, use_reqid, void,
- private_quick_mode_t *this, u_int32_t reqid)
+ private_quick_mode_t *this, uint32_t reqid)
{
this->reqid = reqid;
}
@@ -1385,7 +1387,7 @@ METHOD(quick_mode_t, use_marks, void,
}
METHOD(quick_mode_t, rekey, void,
- private_quick_mode_t *this, u_int32_t spi)
+ private_quick_mode_t *this, uint32_t spi)
{
this->rekey = spi;
}
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.h b/src/libcharon/sa/ikev1/tasks/quick_mode.h
index 062d63465..fe684568a 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.h
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.h
@@ -46,14 +46,14 @@ struct quick_mode_t {
*
* @return message ID, or 0 (not defined yet or as initiator)
*/
- u_int32_t (*get_mid)(quick_mode_t *this);
+ uint32_t (*get_mid)(quick_mode_t *this);
/**
* Use a specific reqid to install this CHILD_SA.
*
* @param reqid reqid to use
*/
- void (*use_reqid)(quick_mode_t *this, u_int32_t reqid);
+ void (*use_reqid)(quick_mode_t *this, uint32_t reqid);
/**
* Use specific mark values, overriding configuration.
@@ -68,7 +68,7 @@ struct quick_mode_t {
*
* @param spi spi of SA to rekey
*/
- void (*rekey)(quick_mode_t *this, u_int32_t spi);
+ void (*rekey)(quick_mode_t *this, uint32_t spi);
};
/**
diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c
index ecdfc780d..968b4386c 100644
--- a/src/libcharon/sa/ikev1/tasks/xauth.c
+++ b/src/libcharon/sa/ikev1/tasks/xauth.c
@@ -68,7 +68,7 @@ struct private_xauth_t {
/**
* received identifier
*/
- u_int16_t identifier;
+ uint16_t identifier;
/**
* status of Xauth exchange
diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
index 91f6187f9..3ab59fada 100644
--- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
@@ -104,7 +104,7 @@ struct private_eap_authenticator_t {
* load an EAP method
*/
static eap_method_t *load_method(private_eap_authenticator_t *this,
- eap_type_t type, u_int32_t vendor, eap_role_t role)
+ eap_type_t type, uint32_t vendor, eap_role_t role)
{
identification_t *server, *peer, *aaa;
auth_cfg_t *auth;
@@ -143,7 +143,7 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
auth_cfg_t *auth;
eap_type_t type;
identification_t *id;
- u_int32_t vendor;
+ uint32_t vendor;
eap_payload_t *out;
char *action;
@@ -237,7 +237,7 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
eap_payload_t *in)
{
eap_type_t type, received_type, conf_type;
- u_int32_t vendor, received_vendor, conf_vendor;
+ uint32_t vendor, received_vendor, conf_vendor;
eap_payload_t *out;
auth_cfg_t *auth;
@@ -341,7 +341,7 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this,
eap_payload_t *in)
{
eap_type_t type, conf_type;
- u_int32_t vendor, conf_vendor;
+ uint32_t vendor, conf_vendor;
auth_cfg_t *auth;
eap_payload_t *out;
identification_t *id;
@@ -449,7 +449,7 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
auth_cfg_t *auth;
keymat_v2_t *keymat;
eap_type_t type;
- u_int32_t vendor;
+ uint32_t vendor;
auth_payload = (auth_payload_t*)message->get_payload(message,
PLV2_AUTH);
@@ -595,7 +595,7 @@ METHOD(authenticator_t, process_client, status_t,
}
if (this->require_mutual && !this->method->is_mutual(this->method))
{ /* we require mutual authentication due to EAP-only */
- u_int32_t vendor;
+ uint32_t vendor;
DBG1(DBG_IKE, "EAP-only authentication requires a mutual and "
"MSK deriving EAP method, but %N is not",
@@ -623,7 +623,7 @@ METHOD(authenticator_t, process_client, status_t,
case EAP_SUCCESS:
{
eap_type_t type;
- u_int32_t vendor;
+ uint32_t vendor;
auth_cfg_t *cfg;
if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
@@ -685,7 +685,7 @@ METHOD(authenticator_t, is_mutual, bool,
{
if (this->method)
{
- u_int32_t vendor;
+ uint32_t vendor;
if (this->method->get_type(this->method, &vendor) != EAP_IDENTITY ||
vendor != 0)
diff --git a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
index 04ccd4f4f..6fd34e0a6 100644
--- a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
@@ -63,7 +63,7 @@ struct private_pubkey_authenticator_t {
static bool parse_signature_auth_data(chunk_t *auth_data, key_type_t *key_type,
signature_scheme_t *scheme)
{
- u_int8_t len;
+ uint8_t len;
int oid;
if (!auth_data->len)
@@ -91,7 +91,7 @@ static bool build_signature_auth_data(chunk_t *auth_data,
signature_scheme_t scheme)
{
chunk_t data;
- u_int8_t len;
+ uint8_t len;
int oid;
oid = signature_scheme_to_oid(scheme);
diff --git a/src/libcharon/sa/ikev2/connect_manager.c b/src/libcharon/sa/ikev2/connect_manager.c
index 161c4fdaf..280796d8c 100644
--- a/src/libcharon/sa/ikev2/connect_manager.c
+++ b/src/libcharon/sa/ikev2/connect_manager.c
@@ -92,10 +92,10 @@ typedef struct endpoint_pair_t endpoint_pair_t;
*/
struct endpoint_pair_t {
/** pair id */
- u_int32_t id;
+ uint32_t id;
/** priority */
- u_int64_t priority;
+ uint64_t priority;
/** local endpoint */
host_t *local;
@@ -107,7 +107,7 @@ struct endpoint_pair_t {
check_state_t state;
/** number of retransmissions */
- u_int32_t retransmitted;
+ uint32_t retransmitted;
/** the generated packet */
packet_t *packet;
@@ -132,8 +132,8 @@ static endpoint_pair_t *endpoint_pair_create(endpoint_notify_t *initiator,
{
endpoint_pair_t *this;
- u_int32_t pi = initiator->get_priority(initiator);
- u_int32_t pr = responder->get_priority(responder);
+ uint32_t pi = initiator->get_priority(initiator);
+ uint32_t pr = responder->get_priority(responder);
INIT(this,
.priority = pow(2, 32) * min(pi, pr) + 2 * max(pi, pr)
@@ -313,7 +313,7 @@ typedef struct check_t check_t;
*/
struct check_t {
/** message id */
- u_int32_t mid;
+ uint32_t mid;
/** source of the connectivity check */
host_t *src;
@@ -375,7 +375,7 @@ struct callback_data_t {
chunk_t connect_id;
/** message (pair) id */
- u_int32_t mid;
+ uint32_t mid;
};
/**
@@ -406,7 +406,7 @@ static callback_data_t *callback_data_create(private_connect_manager_t *connect_
* Creates a new retransmission data object
*/
static callback_data_t *retransmit_data_create(private_connect_manager_t *connect_manager,
- chunk_t connect_id, u_int32_t mid)
+ chunk_t connect_id, uint32_t mid)
{
callback_data_t *this = callback_data_create(connect_manager, connect_id);
this->mid = mid;
@@ -576,7 +576,7 @@ static status_t get_pair_by_hosts(linked_list_t *pairs, host_t *local,
(void**)pair, local, remote);
}
-static bool match_pair_by_id(endpoint_pair_t *current, u_int32_t *id)
+static bool match_pair_by_id(endpoint_pair_t *current, uint32_t *id)
{
return current->id == *id;
}
@@ -584,7 +584,7 @@ static bool match_pair_by_id(endpoint_pair_t *current, u_int32_t *id)
/**
* Searches for a pair with a specific id
*/
-static status_t get_pair_by_id(check_list_t *checklist, u_int32_t id,
+static status_t get_pair_by_id(check_list_t *checklist, uint32_t id,
endpoint_pair_t **pair)
{
return checklist->pairs->find_first(checklist->pairs,
@@ -669,7 +669,7 @@ static void prune_pairs(linked_list_t *pairs)
{
enumerator_t *enumerator, *search;
endpoint_pair_t *current, *other;
- u_int32_t id = 0;
+ uint32_t id = 0;
enumerator = pairs->create_enumerator(pairs);
search = pairs->create_enumerator(pairs);
@@ -826,7 +826,7 @@ static status_t process_payloads(message_t *message, check_t *check)
static chunk_t build_signature(private_connect_manager_t *this,
check_list_t *checklist, check_t *check, bool outbound)
{
- u_int32_t mid;
+ uint32_t mid;
chunk_t mid_chunk, key_chunk, sig_chunk;
chunk_t sig_hash;
@@ -851,7 +851,7 @@ static chunk_t build_signature(private_connect_manager_t *this,
}
static void queue_retransmission(private_connect_manager_t *this, check_list_t *checklist, endpoint_pair_t *pair);
-static void schedule_checks(private_connect_manager_t *this, check_list_t *checklist, u_int32_t time);
+static void schedule_checks(private_connect_manager_t *this, check_list_t *checklist, uint32_t time);
static void finish_checks(private_connect_manager_t *this, check_list_t *checklist);
/**
@@ -1019,11 +1019,11 @@ static void queue_retransmission(private_connect_manager_t *this, check_list_t *
job = (job_t*)callback_job_create((callback_job_cb_t)retransmit, data,
(callback_job_cleanup_t)callback_data_destroy, NULL);
- u_int32_t retransmission = pair->retransmitted + 1;
- u_int32_t rto = ME_INTERVAL;
+ uint32_t retransmission = pair->retransmitted + 1;
+ uint32_t rto = ME_INTERVAL;
if (retransmission > ME_BOOST)
{
- rto = (u_int32_t)(ME_INTERVAL * pow(ME_RETRANS_BASE, retransmission - ME_BOOST));
+ rto = (uint32_t)(ME_INTERVAL * pow(ME_RETRANS_BASE, retransmission - ME_BOOST));
}
DBG2(DBG_IKE, "scheduling retransmission %d of pair '%d' in %dms",
retransmission, pair->id, rto);
@@ -1165,7 +1165,7 @@ static job_requeue_t sender(callback_data_t *data)
* Schedules checks for a checklist (time in ms)
*/
static void schedule_checks(private_connect_manager_t *this,
- check_list_t *checklist, u_int32_t time)
+ check_list_t *checklist, uint32_t time)
{
callback_data_t *data = callback_data_create(this, checklist->connect_id);
checklist->sender = (job_t*)callback_job_create((callback_job_cb_t)sender,
diff --git a/src/libcharon/sa/ikev2/keymat_v2.c b/src/libcharon/sa/ikev2/keymat_v2.c
index 55cb5dd9c..e37399841 100644
--- a/src/libcharon/sa/ikev2/keymat_v2.c
+++ b/src/libcharon/sa/ikev2/keymat_v2.c
@@ -99,8 +99,8 @@ METHOD(keymat_t, create_nonce_gen, nonce_gen_t*,
/**
* Derive IKE keys for a combined AEAD algorithm
*/
-static bool derive_ike_aead(private_keymat_v2_t *this, u_int16_t alg,
- u_int16_t key_size, prf_plus_t *prf_plus)
+static bool derive_ike_aead(private_keymat_v2_t *this, uint16_t alg,
+ uint16_t key_size, prf_plus_t *prf_plus)
{
aead_t *aead_i, *aead_r;
chunk_t key = chunk_empty;
@@ -189,8 +189,8 @@ failure:
/**
* Derive IKE keys for traditional encryption and MAC algorithms
*/
-static bool derive_ike_traditional(private_keymat_v2_t *this, u_int16_t enc_alg,
- u_int16_t enc_size, u_int16_t int_alg, prf_plus_t *prf_plus)
+static bool derive_ike_traditional(private_keymat_v2_t *this, uint16_t enc_alg,
+ uint16_t enc_size, uint16_t int_alg, prf_plus_t *prf_plus)
{
crypter_t *crypter_i = NULL, *crypter_r = NULL;
signer_t *signer_i, *signer_r;
@@ -302,11 +302,11 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
chunk_t skeyseed, key, secret, full_nonce, fixed_nonce, prf_plus_seed;
chunk_t spi_i, spi_r;
prf_plus_t *prf_plus = NULL;
- u_int16_t alg, key_size, int_alg;
+ uint16_t alg, key_size, int_alg;
prf_t *rekey_prf = NULL;
- spi_i = chunk_alloca(sizeof(u_int64_t));
- spi_r = chunk_alloca(sizeof(u_int64_t));
+ spi_i = chunk_alloca(sizeof(uint64_t));
+ spi_r = chunk_alloca(sizeof(uint64_t));
if (!dh->get_shared_secret(dh, &secret))
{
@@ -354,8 +354,8 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
break;
}
fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
- *((u_int64_t*)spi_i.ptr) = id->get_initiator_spi(id);
- *((u_int64_t*)spi_r.ptr) = id->get_responder_spi(id);
+ *((uint64_t*)spi_i.ptr) = id->get_initiator_spi(id);
+ *((uint64_t*)spi_r.ptr) = id->get_responder_spi(id);
prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
/* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
@@ -489,7 +489,7 @@ METHOD(keymat_v2_t, derive_child_keys, bool,
chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i,
chunk_t *encr_r, chunk_t *integ_r)
{
- u_int16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
+ uint16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
chunk_t seed, secret = chunk_empty;
prf_plus_t *prf_plus;
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index c2f972ab1..41a4e1b75 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2007-2015 Tobias Brunner
+ * Copyright (C) 2007-2016 Tobias Brunner
* Copyright (C) 2007-2010 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -43,30 +43,14 @@
#include <encoding/payloads/unknown_payload.h>
#include <processing/jobs/retransmit_job.h>
#include <processing/jobs/delete_ike_sa_job.h>
+#include <processing/jobs/initiate_tasks_job.h>
#ifdef ME
#include <sa/ikev2/tasks/ike_me.h>
#endif
-typedef struct exchange_t exchange_t;
-
-/**
- * An exchange in the air, used do detect and handle retransmission
- */
-struct exchange_t {
-
- /**
- * Message ID used for this transaction
- */
- u_int32_t mid;
-
- /**
- * generated packet for retransmission
- */
- packet_t *packet;
-};
-
typedef struct private_task_manager_t private_task_manager_t;
+typedef struct queued_task_t queued_task_t;
/**
* private data of the task manager
@@ -90,7 +74,7 @@ struct private_task_manager_t {
/**
* Message ID of the exchange
*/
- u_int32_t mid;
+ uint32_t mid;
/**
* packet(s) for retransmission
@@ -111,7 +95,7 @@ struct private_task_manager_t {
/**
* Message ID of the exchange
*/
- u_int32_t mid;
+ uint32_t mid;
/**
* how many times we have retransmitted so far
@@ -182,6 +166,22 @@ struct private_task_manager_t {
};
/**
+ * Queued tasks
+ */
+struct queued_task_t {
+
+ /**
+ * Queued task
+ */
+ task_t *task;
+
+ /**
+ * Time before which the task is not to be initiated
+ */
+ timeval_t time;
+};
+
+/**
* Reset retransmission packet list
*/
static void clear_packets(array_t *array)
@@ -216,6 +216,12 @@ METHOD(task_manager_t, flush_queue, void,
}
while (array_remove(array, ARRAY_TAIL, &task))
{
+ if (queue == TASK_QUEUE_QUEUED)
+ {
+ queued_task_t *queued = (queued_task_t*)task;
+ task = queued->task;
+ free(queued);
+ }
task->destroy(task);
}
}
@@ -229,22 +235,28 @@ METHOD(task_manager_t, flush, void,
}
/**
- * move a task of a specific type from the queue to the active list
+ * Move a task of a specific type from the queue to the active list, if it is
+ * not delayed.
*/
static bool activate_task(private_task_manager_t *this, task_type_t type)
{
enumerator_t *enumerator;
- task_t *task;
+ queued_task_t *queued;
+ timeval_t now;
bool found = FALSE;
+ time_monotonic(&now);
+
enumerator = array_create_enumerator(this->queued_tasks);
- while (enumerator->enumerate(enumerator, (void**)&task))
+ while (enumerator->enumerate(enumerator, (void**)&queued))
{
- if (task->get_type(task) == type)
+ if (queued->task->get_type(queued->task) == type &&
+ !timercmp(&now, &queued->time, <))
{
DBG2(DBG_IKE, " activating %N task", task_type_names, type);
array_remove_at(this->queued_tasks, enumerator);
- array_insert(this->active_tasks, ARRAY_TAIL, task);
+ array_insert(this->active_tasks, ARRAY_TAIL, queued->task);
+ free(queued);
found = TRUE;
break;
}
@@ -303,12 +315,12 @@ static bool generate_message(private_task_manager_t *this, message_t *message,
}
METHOD(task_manager_t, retransmit, status_t,
- private_task_manager_t *this, u_int32_t message_id)
+ private_task_manager_t *this, uint32_t message_id)
{
if (message_id == this->initiating.mid &&
array_count(this->initiating.packets))
{
- u_int32_t timeout;
+ uint32_t timeout;
job_t *job;
enumerator_t *enumerator;
packet_t *packet;
@@ -336,7 +348,7 @@ METHOD(task_manager_t, retransmit, status_t,
{
if (this->initiating.retransmitted <= this->retransmit_tries)
{
- timeout = (u_int32_t)(this->retransmit_timeout * 1000.0 *
+ timeout = (uint32_t)(this->retransmit_timeout * 1000.0 *
pow(this->retransmit_base, this->initiating.retransmitted));
}
else
@@ -352,7 +364,8 @@ METHOD(task_manager_t, retransmit, status_t,
{
DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
this->initiating.retransmitted, message_id);
- charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, packet);
+ charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, packet,
+ this->initiating.retransmitted);
}
if (!mobike)
{
@@ -534,6 +547,7 @@ METHOD(task_manager_t, initiate, status_t,
break;
}
case IKE_REKEYING:
+ case IKE_REKEYED:
if (activate_task(this, TASK_IKE_DELETE))
{
exchange = INFORMATIONAL;
@@ -610,7 +624,8 @@ METHOD(task_manager_t, initiate, status_t,
case FAILED:
default:
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
- if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING &&
+ this->ike_sa->get_state(this->ike_sa) != IKE_REKEYED)
{
charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
}
@@ -694,6 +709,13 @@ static status_t process_response(private_task_manager_t *this,
}
enumerator->destroy(enumerator);
+ if (this->initiating.retransmitted)
+ {
+ packet_t *packet = NULL;
+ array_get(this->initiating.packets, 0, &packet);
+ charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_CLEARED, packet);
+ }
+
/* catch if we get resetted while processing */
this->reset = FALSE;
enumerator = array_create_enumerator(this->active_tasks);
@@ -751,8 +773,7 @@ static bool handle_collisions(private_task_manager_t *this, task_t *task)
/* do we have to check */
if (type == TASK_IKE_REKEY || type == TASK_CHILD_REKEY ||
- type == TASK_CHILD_DELETE || type == TASK_IKE_DELETE ||
- type == TASK_IKE_REAUTH)
+ type == TASK_CHILD_DELETE || type == TASK_IKE_DELETE)
{
/* find an exchange collision, and notify these tasks */
enumerator = array_create_enumerator(this->active_tasks);
@@ -761,8 +782,7 @@ static bool handle_collisions(private_task_manager_t *this, task_t *task)
switch (active->get_type(active))
{
case TASK_IKE_REKEY:
- if (type == TASK_IKE_REKEY || type == TASK_IKE_DELETE ||
- type == TASK_IKE_REAUTH)
+ if (type == TASK_IKE_REKEY || type == TASK_IKE_DELETE)
{
ike_rekey_t *rekey = (ike_rekey_t*)active;
rekey->collide(rekey, task);
@@ -799,7 +819,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
host_t *me, *other;
bool delete = FALSE, hook = FALSE;
ike_sa_id_t *id = NULL;
- u_int64_t responder_spi = 0;
+ uint64_t responder_spi = 0;
bool result;
me = request->get_destination(request);
@@ -839,6 +859,10 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
/* FALL */
case DESTROY_ME:
/* destroy IKE_SA, but SEND response first */
+ if (handle_collisions(this, task))
+ {
+ array_remove_at(this->passive_tasks, enumerator);
+ }
delete = TRUE;
break;
}
@@ -901,9 +925,11 @@ static status_t process_request(private_task_manager_t *this,
payload_t *payload;
notify_payload_t *notify;
delete_payload_t *delete;
+ ike_sa_state_t state;
if (array_count(this->passive_tasks) == 0)
{ /* create tasks depending on request type, if not already some queued */
+ state = this->ike_sa->get_state(this->ike_sa);
switch (message->get_exchange_type(message))
{
case IKE_SA_INIT:
@@ -939,8 +965,8 @@ static status_t process_request(private_task_manager_t *this,
{ /* FIXME: we should prevent this on mediation connections */
bool notify_found = FALSE, ts_found = FALSE;
- if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED ||
- this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING)
+ if (state == IKE_CREATED ||
+ state == IKE_CONNECTING)
{
DBG1(DBG_IKE, "received CREATE_CHILD_SA request for "
"unestablished IKE_SA, rejected");
@@ -1005,6 +1031,14 @@ static status_t process_request(private_task_manager_t *this,
case PLV2_NOTIFY:
{
notify = (notify_payload_t*)payload;
+ if (state == IKE_REKEYED)
+ {
+ DBG1(DBG_IKE, "received unexpected notify %N "
+ "for rekeyed IKE_SA, ignored",
+ notify_type_names,
+ notify->get_notify_type(notify));
+ break;
+ }
switch (notify->get_notify_type(notify))
{
case ADDITIONAL_IP4_ADDRESS:
@@ -1252,7 +1286,7 @@ static void send_notify_response(private_task_manager_t *this,
static status_t parse_message(private_task_manager_t *this, message_t *msg)
{
status_t status;
- u_int8_t type = 0;
+ uint8_t type = 0;
status = msg->parse_body(msg, this->ike_sa->get_keymat(this->ike_sa));
@@ -1345,8 +1379,10 @@ METHOD(task_manager_t, process_message, status_t,
{
host_t *me, *other;
status_t status;
- u_int32_t mid;
+ uint32_t mid;
bool schedule_delete_job = FALSE;
+ ike_sa_state_t state;
+ exchange_type_t type;
charon->bus->message(charon->bus, msg, TRUE, FALSE);
status = parse_message(this, msg);
@@ -1387,15 +1423,16 @@ METHOD(task_manager_t, process_message, status_t,
{
if (mid == this->responding.mid)
{
- /* reject initial messages if not received in specific states */
- if ((msg->get_exchange_type(msg) == IKE_SA_INIT &&
- this->ike_sa->get_state(this->ike_sa) != IKE_CREATED) ||
- (msg->get_exchange_type(msg) == IKE_AUTH &&
- this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING))
+ /* reject initial messages if not received in specific states,
+ * after rekeying we only expect a DELETE in an INFORMATIONAL */
+ type = msg->get_exchange_type(msg);
+ state = this->ike_sa->get_state(this->ike_sa);
+ if ((type == IKE_SA_INIT && state != IKE_CREATED) ||
+ (type == IKE_AUTH && state != IKE_CONNECTING) ||
+ (state == IKE_REKEYED && type != INFORMATIONAL))
{
DBG1(DBG_IKE, "ignoring %N in IKE_SA state %N",
- exchange_type_names, msg->get_exchange_type(msg),
- ike_sa_state_names, this->ike_sa->get_state(this->ike_sa));
+ exchange_type_names, type, ike_sa_state_names, state);
return FAILED;
}
if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
@@ -1499,18 +1536,19 @@ METHOD(task_manager_t, process_message, status_t,
return SUCCESS;
}
-METHOD(task_manager_t, queue_task, void,
- private_task_manager_t *this, task_t *task)
+METHOD(task_manager_t, queue_task_delayed, void,
+ private_task_manager_t *this, task_t *task, uint32_t delay)
{
+ enumerator_t *enumerator;
+ queued_task_t *queued;
+ timeval_t time;
+
if (task->get_type(task) == TASK_IKE_MOBIKE)
{ /* there is no need to queue more than one mobike task */
- enumerator_t *enumerator;
- task_t *current;
-
enumerator = array_create_enumerator(this->queued_tasks);
- while (enumerator->enumerate(enumerator, &current))
+ while (enumerator->enumerate(enumerator, &queued))
{
- if (current->get_type(current) == TASK_IKE_MOBIKE)
+ if (queued->task->get_type(queued->task) == TASK_IKE_MOBIKE)
{
enumerator->destroy(enumerator);
task->destroy(task);
@@ -1519,8 +1557,35 @@ METHOD(task_manager_t, queue_task, void,
}
enumerator->destroy(enumerator);
}
- DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
- array_insert(this->queued_tasks, ARRAY_TAIL, task);
+ time_monotonic(&time);
+ if (delay)
+ {
+ job_t *job;
+
+ DBG2(DBG_IKE, "queueing %N task (delayed by %us)", task_type_names,
+ task->get_type(task), delay);
+ time.tv_sec += delay;
+
+ job = (job_t*)initiate_tasks_job_create(
+ this->ike_sa->get_id(this->ike_sa));
+ lib->scheduler->schedule_job_tv(lib->scheduler, job, time);
+ }
+ else
+ {
+ DBG2(DBG_IKE, "queueing %N task", task_type_names,
+ task->get_type(task));
+ }
+ INIT(queued,
+ .task = task,
+ .time = time,
+ );
+ array_insert(this->queued_tasks, ARRAY_TAIL, queued);
+}
+
+METHOD(task_manager_t, queue_task, void,
+ private_task_manager_t *this, task_t *task)
+{
+ queue_task_delayed(this, task, 0);
}
/**
@@ -1530,12 +1595,12 @@ static bool has_queued(private_task_manager_t *this, task_type_t type)
{
enumerator_t *enumerator;
bool found = FALSE;
- task_t *task;
+ queued_task_t *queued;
enumerator = array_create_enumerator(this->queued_tasks);
- while (enumerator->enumerate(enumerator, &task))
+ while (enumerator->enumerate(enumerator, &queued))
{
- if (task->get_type(task) == type)
+ if (queued->task->get_type(queued->task) == type)
{
found = TRUE;
break;
@@ -1614,7 +1679,7 @@ static void trigger_mbb_reauth(private_task_manager_t *this)
child_cfg_t *cfg;
ike_sa_t *new;
host_t *host;
- task_t *task;
+ queued_task_t *queued;
new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
this->ike_sa->get_version(this->ike_sa), TRUE);
@@ -1645,13 +1710,14 @@ static void trigger_mbb_reauth(private_task_manager_t *this)
enumerator->destroy(enumerator);
enumerator = array_create_enumerator(this->queued_tasks);
- while (enumerator->enumerate(enumerator, &task))
+ while (enumerator->enumerate(enumerator, &queued))
{
- if (task->get_type(task) == TASK_CHILD_CREATE)
+ if (queued->task->get_type(queued->task) == TASK_CHILD_CREATE)
{
- task->migrate(task, new);
- new->queue_task(new, task);
+ queued->task->migrate(queued->task, new);
+ new->queue_task(new, queued->task);
array_remove_at(this->queued_tasks, enumerator);
+ free(queued);
}
}
enumerator->destroy(enumerator);
@@ -1726,7 +1792,7 @@ METHOD(task_manager_t, queue_mobike, void,
}
METHOD(task_manager_t, queue_child, void,
- private_task_manager_t *this, child_cfg_t *cfg, u_int32_t reqid,
+ private_task_manager_t *this, child_cfg_t *cfg, uint32_t reqid,
traffic_selector_t *tsi, traffic_selector_t *tsr)
{
child_create_t *task;
@@ -1740,13 +1806,13 @@ METHOD(task_manager_t, queue_child, void,
}
METHOD(task_manager_t, queue_child_rekey, void,
- private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi)
+ private_task_manager_t *this, protocol_id_t protocol, uint32_t spi)
{
queue_task(this, (task_t*)child_rekey_create(this->ike_sa, protocol, spi));
}
METHOD(task_manager_t, queue_child_delete, void,
- private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi,
+ private_task_manager_t *this, protocol_id_t protocol, uint32_t spi,
bool expired)
{
queue_task(this, (task_t*)child_delete_create(this->ike_sa,
@@ -1776,34 +1842,62 @@ METHOD(task_manager_t, adopt_tasks, void,
private_task_manager_t *this, task_manager_t *other_public)
{
private_task_manager_t *other = (private_task_manager_t*)other_public;
- task_t *task;
+ queued_task_t *queued;
+ timeval_t now;
+
+ time_monotonic(&now);
/* move queued tasks from other to this */
- while (array_remove(other->queued_tasks, ARRAY_TAIL, &task))
+ while (array_remove(other->queued_tasks, ARRAY_TAIL, &queued))
{
- DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
- task->migrate(task, this->ike_sa);
- array_insert(this->queued_tasks, ARRAY_HEAD, task);
+ DBG2(DBG_IKE, "migrating %N task", task_type_names,
+ queued->task->get_type(queued->task));
+ queued->task->migrate(queued->task, this->ike_sa);
+ /* don't delay tasks on the new IKE_SA */
+ queued->time = now;
+ array_insert(this->queued_tasks, ARRAY_HEAD, queued);
}
}
/**
- * Migrates child-creating tasks from src to dst
+ * Migrates child-creating tasks from other to this
*/
static void migrate_child_tasks(private_task_manager_t *this,
- array_t *src, array_t *dst)
+ private_task_manager_t *other,
+ task_queue_t queue)
{
enumerator_t *enumerator;
+ array_t *array;
task_t *task;
- enumerator = array_create_enumerator(src);
+ switch (queue)
+ {
+ case TASK_QUEUE_ACTIVE:
+ array = other->active_tasks;
+ break;
+ case TASK_QUEUE_QUEUED:
+ array = other->queued_tasks;
+ break;
+ default:
+ return;
+ }
+
+ enumerator = array_create_enumerator(array);
while (enumerator->enumerate(enumerator, &task))
{
+ queued_task_t *queued = NULL;
+
+ if (queue == TASK_QUEUE_QUEUED)
+ {
+ queued = (queued_task_t*)task;
+ task = queued->task;
+ }
if (task->get_type(task) == TASK_CHILD_CREATE)
{
- array_remove_at(src, enumerator);
+ array_remove_at(array, enumerator);
task->migrate(task, this->ike_sa);
- array_insert(dst, ARRAY_TAIL, task);
+ queue_task(this, task);
+ free(queued);
}
}
enumerator->destroy(enumerator);
@@ -1815,9 +1909,9 @@ METHOD(task_manager_t, adopt_child_tasks, void,
private_task_manager_t *other = (private_task_manager_t*)other_public;
/* move active child tasks from other to this */
- migrate_child_tasks(this, other->active_tasks, this->queued_tasks);
+ migrate_child_tasks(this, other, TASK_QUEUE_ACTIVE);
/* do the same for queued tasks */
- migrate_child_tasks(this, other->queued_tasks, this->queued_tasks);
+ migrate_child_tasks(this, other, TASK_QUEUE_QUEUED);
}
METHOD(task_manager_t, busy, bool,
@@ -1827,10 +1921,12 @@ METHOD(task_manager_t, busy, bool,
}
METHOD(task_manager_t, reset, void,
- private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
+ private_task_manager_t *this, uint32_t initiate, uint32_t respond)
{
enumerator_t *enumerator;
+ queued_task_t *queued;
task_t *task;
+ timeval_t now;
/* reset message counters and retransmit packets */
clear_packets(this->responding.packets);
@@ -1849,11 +1945,13 @@ METHOD(task_manager_t, reset, void,
}
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
+ time_monotonic(&now);
/* reset queued tasks */
enumerator = array_create_enumerator(this->queued_tasks);
- while (enumerator->enumerate(enumerator, &task))
+ while (enumerator->enumerate(enumerator, &queued))
{
- task->migrate(task, this->ike_sa);
+ queued->time = now;
+ queued->task->migrate(queued->task, this->ike_sa);
}
enumerator->destroy(enumerator);
@@ -1861,12 +1959,25 @@ METHOD(task_manager_t, reset, void,
while (array_remove(this->active_tasks, ARRAY_TAIL, &task))
{
task->migrate(task, this->ike_sa);
- array_insert(this->queued_tasks, ARRAY_HEAD, task);
+ INIT(queued,
+ .task = task,
+ .time = now,
+ );
+ array_insert(this->queued_tasks, ARRAY_HEAD, queued);
}
this->reset = TRUE;
}
+/**
+ * Filter queued tasks
+ */
+static bool filter_queued(void *unused, queued_task_t **queued, task_t **task)
+{
+ *task = (*queued)->task;
+ return TRUE;
+}
+
METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
private_task_manager_t *this, task_queue_t queue)
{
@@ -1877,7 +1988,9 @@ METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
case TASK_QUEUE_PASSIVE:
return array_create_enumerator(this->passive_tasks);
case TASK_QUEUE_QUEUED:
- return array_create_enumerator(this->queued_tasks);
+ return enumerator_create_filter(
+ array_create_enumerator(this->queued_tasks),
+ (void*)filter_queued, NULL, NULL);
default:
return enumerator_create_empty();
}
@@ -1913,6 +2026,7 @@ task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa)
.task_manager = {
.process_message = _process_message,
.queue_task = _queue_task,
+ .queue_task_delayed = _queue_task_delayed,
.queue_ike = _queue_ike,
.queue_ike_rekey = _queue_ike_rekey,
.queue_ike_reauth = _queue_ike_reauth,
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index 3d4ded944..64a82850b 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2016 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -29,7 +29,7 @@
#include <encoding/payloads/delete_payload.h>
#include <processing/jobs/delete_ike_sa_job.h>
#include <processing/jobs/inactivity_job.h>
-
+#include <processing/jobs/initiate_tasks_job.h>
typedef struct private_child_create_t private_child_create_t;
@@ -151,27 +151,27 @@ struct private_child_create_t {
/**
* Own allocated SPI
*/
- u_int32_t my_spi;
+ uint32_t my_spi;
/**
* SPI received in proposal
*/
- u_int32_t other_spi;
+ uint32_t other_spi;
/**
* Own allocated Compression Parameter Index (CPI)
*/
- u_int16_t my_cpi;
+ uint16_t my_cpi;
/**
* Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED
*/
- u_int16_t other_cpi;
+ uint16_t other_cpi;
/**
* reqid to use if we are rekeying
*/
- u_int32_t reqid;
+ uint32_t reqid;
/**
* Explicit inbound mark value
@@ -205,6 +205,25 @@ struct private_child_create_t {
};
/**
+ * Schedule a retry if creating the CHILD_SA temporary failed
+ */
+static void schedule_delayed_retry(private_child_create_t *this)
+{
+ child_create_t *task;
+ uint32_t retry;
+
+ retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
+
+ task = child_create_create(this->ike_sa,
+ this->config->get_ref(this->config), FALSE,
+ this->packet_tsi, this->packet_tsr);
+ task->use_reqid(task, this->reqid);
+ DBG1(DBG_IKE, "creating CHILD_SA failed, trying again in %d seconds",
+ retry);
+ this->ike_sa->queue_task_delayed(this->ike_sa, (task_t*)task, retry);
+}
+
+/**
* get the nonce from a message
*/
static status_t get_nonce(message_t *message, chunk_t *nonce)
@@ -306,7 +325,7 @@ static bool allocate_spi(private_child_create_t *this)
*/
static void schedule_inactivity_timeout(private_child_create_t *this)
{
- u_int32_t timeout, id;
+ uint32_t timeout, id;
bool close_ike;
timeout = this->config->get_inactivity(this->config);
@@ -386,7 +405,7 @@ static linked_list_t* get_transport_nat_ts(private_child_create_t *this,
linked_list_t *out;
traffic_selector_t *ts;
host_t *ike, *first = NULL;
- u_int8_t mask;
+ uint8_t mask;
if (local)
{
@@ -464,7 +483,7 @@ static status_t select_and_install(private_child_create_t *this,
chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
linked_list_t *my_ts, *other_ts;
host_t *me, *other;
- bool private;
+ bool private, prefer_configured;
if (this->proposals == NULL)
{
@@ -481,8 +500,10 @@ static status_t select_and_install(private_child_create_t *this,
other = this->ike_sa->get_other_host(this->ike_sa);
private = this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN);
+ prefer_configured = lib->settings->get_bool(lib->settings,
+ "%s.prefer_configured_proposals", TRUE, lib->ns);
this->proposal = this->config->select_proposal(this->config,
- this->proposals, no_dh, private);
+ this->proposals, no_dh, private, prefer_configured);
if (this->proposal == NULL)
{
DBG1(DBG_IKE, "no acceptable proposal found");
@@ -501,7 +522,7 @@ static status_t select_and_install(private_child_create_t *this,
if (!this->proposal->has_dh_group(this->proposal, this->dh_group))
{
- u_int16_t group;
+ uint16_t group;
if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
&group, NULL))
@@ -798,7 +819,7 @@ static bool build_payloads(private_child_create_t *this, message_t *message)
* Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI
*/
static void add_ipcomp_notify(private_child_create_t *this,
- message_t *message, u_int8_t ipcomp)
+ message_t *message, uint8_t ipcomp)
{
this->my_cpi = this->child_sa->alloc_cpi(this->child_sa);
if (this->my_cpi)
@@ -838,11 +859,11 @@ static void handle_notify(private_child_create_t *this, notify_payload_t *notify
case IPCOMP_SUPPORTED:
{
ipcomp_transform_t ipcomp;
- u_int16_t cpi;
+ uint16_t cpi;
chunk_t data;
data = notify->get_notification_data(notify);
- cpi = *(u_int16_t*)data.ptr;
+ cpi = *(uint16_t*)data.ptr;
ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
switch (ipcomp)
{
@@ -1232,13 +1253,13 @@ METHOD(task_t, build_r, status_t,
if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
{
DBG1(DBG_IKE, "unable to create CHILD_SA while rekeying IKE_SA");
- message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
+ message->add_notify(message, TRUE, TEMPORARY_FAILURE, chunk_empty);
return SUCCESS;
}
if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
{
DBG1(DBG_IKE, "unable to create CHILD_SA while deleting IKE_SA");
- message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
+ message->add_notify(message, TRUE, TEMPORARY_FAILURE, chunk_empty);
return SUCCESS;
}
@@ -1310,7 +1331,7 @@ METHOD(task_t, build_r, status_t,
return SUCCESS;
case INVALID_ARG:
{
- u_int16_t group = htons(this->dh_group);
+ uint16_t group = htons(this->dh_group);
message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
chunk_from_thing(group));
handle_child_sa_failure(this, message);
@@ -1441,10 +1462,21 @@ METHOD(task_t, process_i, status_t,
/* an error in CHILD_SA creation is not critical */
return SUCCESS;
}
+ case TEMPORARY_FAILURE:
+ {
+ DBG1(DBG_IKE, "received %N notify, will retry later",
+ notify_type_names, type);
+ enumerator->destroy(enumerator);
+ if (!this->rekey)
+ { /* the rekey task will retry itself if necessary */
+ schedule_delayed_retry(this);
+ }
+ return SUCCESS;
+ }
case INVALID_KE_PAYLOAD:
{
chunk_t data;
- u_int16_t group = MODP_NONE;
+ uint16_t group = MODP_NONE;
data = notify->get_notification_data(notify);
if (data.len == sizeof(group))
@@ -1529,7 +1561,7 @@ METHOD(task_t, process_i, status_t,
}
METHOD(child_create_t, use_reqid, void,
- private_child_create_t *this, u_int32_t reqid)
+ private_child_create_t *this, uint32_t reqid)
{
this->reqid = reqid;
}
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.h b/src/libcharon/sa/ikev2/tasks/child_create.h
index 46d9403ee..f48d7b0a9 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.h
+++ b/src/libcharon/sa/ikev2/tasks/child_create.h
@@ -49,7 +49,7 @@ struct child_create_t {
*
* @param reqid reqid to use
*/
- void (*use_reqid) (child_create_t *this, u_int32_t reqid);
+ void (*use_reqid) (child_create_t *this, uint32_t reqid);
/**
* Use specific mark values to override configuration.
diff --git a/src/libcharon/sa/ikev2/tasks/child_delete.c b/src/libcharon/sa/ikev2/tasks/child_delete.c
index 877ae0531..6fa8836ac 100644
--- a/src/libcharon/sa/ikev2/tasks/child_delete.c
+++ b/src/libcharon/sa/ikev2/tasks/child_delete.c
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2009-2016 Tobias Brunner
* Copyright (C) 2006-2007 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -18,7 +19,7 @@
#include <daemon.h>
#include <encoding/payloads/delete_payload.h>
#include <sa/ikev2/tasks/child_create.h>
-
+#include <sa/ikev2/tasks/child_rekey.h>
typedef struct private_child_delete_t private_child_delete_t;
@@ -50,7 +51,7 @@ struct private_child_delete_t {
/**
* Inbound SPI of CHILD_SA to delete
*/
- u_int32_t spi;
+ uint32_t spi;
/**
* whether to enforce delete action policy
@@ -86,7 +87,7 @@ static void build_payloads(private_child_delete_t *this, message_t *message)
while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
protocol_id_t protocol = child_sa->get_protocol(child_sa);
- u_int32_t spi = child_sa->get_spi(child_sa, TRUE);
+ uint32_t spi = child_sa->get_spi(child_sa, TRUE);
switch (protocol)
{
@@ -119,6 +120,33 @@ static void build_payloads(private_child_delete_t *this, message_t *message)
}
/**
+ * Check if the given CHILD_SA is the redundant SA created in a rekey collision.
+ */
+static bool is_redundant(private_child_delete_t *this, child_sa_t *child)
+{
+ enumerator_t *tasks;
+ task_t *task;
+
+ tasks = this->ike_sa->create_task_enumerator(this->ike_sa,
+ TASK_QUEUE_ACTIVE);
+ while (tasks->enumerate(tasks, &task))
+ {
+ if (task->get_type(task) == TASK_CHILD_REKEY)
+ {
+ child_rekey_t *rekey = (child_rekey_t*)task;
+
+ if (rekey->is_redundant(rekey, child))
+ {
+ tasks->destroy(tasks);
+ return TRUE;
+ }
+ }
+ }
+ tasks->destroy(tasks);
+ return FALSE;
+}
+
+/**
* read in payloads and find the children to delete
*/
static void process_payloads(private_child_delete_t *this, message_t *message)
@@ -126,7 +154,7 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
enumerator_t *payloads, *spis;
payload_t *payload;
delete_payload_t *delete_payload;
- u_int32_t spi;
+ uint32_t spi;
protocol_id_t protocol;
child_sa_t *child_sa;
@@ -157,24 +185,31 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
switch (child_sa->get_state(child_sa))
{
- case CHILD_REKEYING:
+ case CHILD_REKEYED:
this->rekeyed = TRUE;
- /* we reply as usual, rekeying will fail */
break;
case CHILD_DELETING:
/* we don't send back a delete if we initiated ourself */
if (!this->initiator)
{
- this->ike_sa->destroy_child_sa(this->ike_sa,
- protocol, spi);
continue;
}
/* fall through */
+ case CHILD_REKEYING:
+ /* we reply as usual, rekeying will fail */
case CHILD_INSTALLED:
if (!this->initiator)
- { /* reestablish installed children if required */
- this->check_delete_action = TRUE;
+ {
+ if (is_redundant(this, child_sa))
+ {
+ this->rekeyed = TRUE;
+ }
+ else
+ {
+ this->check_delete_action = TRUE;
+ }
}
+ break;
default:
break;
}
@@ -199,14 +234,14 @@ static status_t destroy_and_reestablish(private_child_delete_t *this)
child_sa_t *child_sa;
child_cfg_t *child_cfg;
protocol_id_t protocol;
- u_int32_t spi, reqid;
+ uint32_t spi, reqid;
action_t action;
status_t status = SUCCESS;
enumerator = this->child_sas->create_enumerator(this->child_sas);
while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
- /* signal child down event if we are not rekeying */
+ /* signal child down event if we weren't rekeying */
if (!this->rekeyed)
{
charon->bus->child_updown(charon->bus, child_sa, FALSE);
@@ -254,7 +289,7 @@ static void log_children(private_child_delete_t *this)
linked_list_t *my_ts, *other_ts;
enumerator_t *enumerator;
child_sa_t *child_sa;
- u_int64_t bytes_in, bytes_out;
+ uint64_t bytes_in, bytes_out;
enumerator = this->child_sas->create_enumerator(this->child_sas);
while (enumerator->enumerate(enumerator, (void**)&child_sa))
@@ -308,7 +343,7 @@ METHOD(task_t, build_i, status_t,
this->spi = child_sa->get_spi(child_sa, TRUE);
}
this->child_sas->insert_last(this->child_sas, child_sa);
- if (child_sa->get_state(child_sa) == CHILD_REKEYING)
+ if (child_sa->get_state(child_sa) == CHILD_REKEYED)
{
this->rekeyed = TRUE;
}
@@ -347,11 +382,7 @@ METHOD(task_t, process_r, status_t,
METHOD(task_t, build_r, status_t,
private_child_delete_t *this, message_t *message)
{
- /* if we are rekeying, we send an empty informational */
- if (this->ike_sa->get_state(this->ike_sa) != IKE_REKEYING)
- {
- build_payloads(this, message);
- }
+ build_payloads(this, message);
DBG1(DBG_IKE, "CHILD_SA closed");
return destroy_and_reestablish(this);
}
@@ -391,7 +422,7 @@ METHOD(task_t, destroy, void,
* Described in header.
*/
child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
- u_int32_t spi, bool expired)
+ uint32_t spi, bool expired)
{
private_child_delete_t *this;
diff --git a/src/libcharon/sa/ikev2/tasks/child_delete.h b/src/libcharon/sa/ikev2/tasks/child_delete.h
index 1ada0699e..1e9b2d2f7 100644
--- a/src/libcharon/sa/ikev2/tasks/child_delete.h
+++ b/src/libcharon/sa/ikev2/tasks/child_delete.h
@@ -56,6 +56,6 @@ struct child_delete_t {
* @return child_delete task to handle by the task_manager
*/
child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
- u_int32_t spi, bool expired);
+ uint32_t spi, bool expired);
#endif /** CHILD_DELETE_H_ @}*/
diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c
index 6f0c2b2c7..c04ec141f 100644
--- a/src/libcharon/sa/ikev2/tasks/child_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c
@@ -1,7 +1,8 @@
/*
+ * Copyright (C) 2009-2016 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -54,7 +55,7 @@ struct private_child_rekey_t {
/**
* Inbound SPI of CHILD_SA to rekey
*/
- u_int32_t spi;
+ uint32_t spi;
/**
* the CHILD_CREATE task which is reused to simplify rekeying
@@ -91,7 +92,7 @@ struct private_child_rekey_t {
*/
static void schedule_delayed_rekey(private_child_rekey_t *this)
{
- u_int32_t retry;
+ uint32_t retry;
job_t *job;
retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
@@ -130,7 +131,7 @@ static void find_child(private_child_rekey_t *this, message_t *message)
{
notify_payload_t *notify;
protocol_id_t protocol;
- u_int32_t spi;
+ uint32_t spi;
notify = message->get_notify(message, REKEY_SA);
if (notify)
@@ -150,7 +151,7 @@ METHOD(task_t, build_i, status_t,
private_child_rekey_t *this, message_t *message)
{
notify_payload_t *notify;
- u_int32_t reqid;
+ uint32_t reqid;
child_cfg_t *config;
this->child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol,
@@ -159,14 +160,21 @@ METHOD(task_t, build_i, status_t,
{ /* check if it is an outbound CHILD_SA */
this->child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol,
this->spi, FALSE);
- if (!this->child_sa)
- { /* CHILD_SA is gone, unable to rekey. As an empty CREATE_CHILD_SA
- * exchange is invalid, we fall back to an INFORMATIONAL exchange.*/
- message->set_exchange_type(message, INFORMATIONAL);
- return SUCCESS;
+ if (this->child_sa)
+ {
+ /* we work only with the inbound SPI */
+ this->spi = this->child_sa->get_spi(this->child_sa, TRUE);
}
- /* we work only with the inbound SPI */
- this->spi = this->child_sa->get_spi(this->child_sa, TRUE);
+ }
+ if (!this->child_sa ||
+ (!this->child_create &&
+ this->child_sa->get_state(this->child_sa) != CHILD_INSTALLED) ||
+ (this->child_create &&
+ this->child_sa->get_state(this->child_sa) != CHILD_REKEYING))
+ {
+ /* CHILD_SA is gone or in the wrong state, unable to rekey */
+ message->set_exchange_type(message, EXCHANGE_TYPE_UNDEFINED);
+ return SUCCESS;
}
config = this->child_sa->get_config(this->child_sa);
@@ -217,13 +225,19 @@ METHOD(task_t, build_r, status_t,
private_child_rekey_t *this, message_t *message)
{
child_cfg_t *config;
- u_int32_t reqid;
+ uint32_t reqid;
+ child_sa_state_t state;
- if (this->child_sa == NULL ||
- this->child_sa->get_state(this->child_sa) == CHILD_DELETING)
+ if (!this->child_sa)
{
DBG1(DBG_IKE, "unable to rekey, CHILD_SA not found");
- message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
+ message->add_notify(message, TRUE, CHILD_SA_NOT_FOUND, chunk_empty);
+ return SUCCESS;
+ }
+ if (this->child_sa->get_state(this->child_sa) == CHILD_DELETING)
+ {
+ DBG1(DBG_IKE, "unable to rekey, we are deleting the CHILD_SA");
+ message->add_notify(message, TRUE, TEMPORARY_FAILURE, chunk_empty);
return SUCCESS;
}
@@ -237,14 +251,16 @@ METHOD(task_t, build_r, status_t,
this->child_create->set_config(this->child_create, config->get_ref(config));
this->child_create->task.build(&this->child_create->task, message);
+ state = this->child_sa->get_state(this->child_sa);
+ this->child_sa->set_state(this->child_sa, CHILD_REKEYING);
+
if (message->get_payload(message, PLV2_SECURITY_ASSOCIATION) == NULL)
- {
- /* rekeying failed, reuse old child */
- this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
+ { /* rekeying failed, reuse old child */
+ this->child_sa->set_state(this->child_sa, state);
return SUCCESS;
}
- this->child_sa->set_state(this->child_sa, CHILD_REKEYING);
+ this->child_sa->set_state(this->child_sa, CHILD_REKEYED);
/* invoke rekey hook */
charon->bus->child_rekey(charon->bus, this->child_sa,
@@ -284,9 +300,9 @@ static child_sa_t *handle_collision(private_child_rekey_t *this)
if (child_sa)
{
child_sa->set_close_action(child_sa, ACTION_NONE);
- if (child_sa->get_state(child_sa) != CHILD_REKEYING)
+ if (child_sa->get_state(child_sa) != CHILD_REKEYED)
{
- child_sa->set_state(child_sa, CHILD_REKEYING);
+ child_sa->set_state(child_sa, CHILD_REKEYED);
}
}
}
@@ -324,7 +340,7 @@ METHOD(task_t, process_i, status_t,
private_child_rekey_t *this, message_t *message)
{
protocol_id_t protocol;
- u_int32_t spi;
+ uint32_t spi;
child_sa_t *to_delete;
if (message->get_notify(message, NO_ADDITIONAL_SAS))
@@ -337,6 +353,34 @@ METHOD(task_t, process_i, status_t,
this->ike_sa->get_id(this->ike_sa), TRUE));
return SUCCESS;
}
+ if (message->get_notify(message, CHILD_SA_NOT_FOUND))
+ {
+ child_cfg_t *child_cfg;
+ uint32_t reqid;
+
+ if (this->collision &&
+ this->collision->get_type(this->collision) == TASK_CHILD_DELETE)
+ { /* ignore this error if we already deleted the CHILD_SA on the
+ * peer's behalf (could happen if the other peer does not detect
+ * the collision and did not respond with TEMPORARY_FAILURE) */
+ return SUCCESS;
+ }
+ DBG1(DBG_IKE, "peer didn't find the CHILD_SA we tried to rekey");
+ /* FIXME: according to RFC 7296 we should only create a new CHILD_SA if
+ * it does not exist yet, we currently have no good way of checking for
+ * that (we could go by name, but that might be tricky e.g. due to
+ * narrowing) */
+ spi = this->child_sa->get_spi(this->child_sa, TRUE);
+ reqid = this->child_sa->get_reqid(this->child_sa);
+ protocol = this->child_sa->get_protocol(this->child_sa);
+ child_cfg = this->child_sa->get_config(this->child_sa);
+ child_cfg->get_ref(child_cfg);
+ charon->bus->child_updown(charon->bus, this->child_sa, FALSE);
+ this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
+ return this->ike_sa->initiate(this->ike_sa,
+ child_cfg->get_ref(child_cfg), reqid,
+ NULL, NULL);
+ }
if (this->child_create->task.process(&this->child_create->task,
message) == NEED_MORE)
@@ -346,10 +390,10 @@ METHOD(task_t, process_i, status_t,
}
if (message->get_payload(message, PLV2_SECURITY_ASSOCIATION) == NULL)
{
- /* establishing new child failed, reuse old. but not when we
- * received a delete in the meantime */
- if (!(this->collision &&
- this->collision->get_type(this->collision) == TASK_CHILD_DELETE))
+ /* establishing new child failed, reuse old and try again. but not when
+ * we received a delete in the meantime */
+ if (!this->collision ||
+ this->collision->get_type(this->collision) != TASK_CHILD_DELETE)
{
schedule_delayed_rekey(this);
}
@@ -377,9 +421,9 @@ METHOD(task_t, process_i, status_t,
return SUCCESS;
}
/* disable updown event for redundant CHILD_SA */
- if (to_delete->get_state(to_delete) != CHILD_REKEYING)
+ if (to_delete->get_state(to_delete) != CHILD_REKEYED)
{
- to_delete->set_state(to_delete, CHILD_REKEYING);
+ to_delete->set_state(to_delete, CHILD_REKEYED);
}
spi = to_delete->get_spi(to_delete, TRUE);
protocol = to_delete->get_protocol(to_delete);
@@ -398,6 +442,18 @@ METHOD(task_t, get_type, task_type_t,
return TASK_CHILD_REKEY;
}
+METHOD(child_rekey_t, is_redundant, bool,
+ private_child_rekey_t *this, child_sa_t *child)
+{
+ if (this->collision &&
+ this->collision->get_type(this->collision) == TASK_CHILD_REKEY)
+ {
+ private_child_rekey_t *rekey = (private_child_rekey_t*)this->collision;
+ return child == rekey->child_create->get_child(rekey->child_create);
+ }
+ return FALSE;
+}
+
METHOD(child_rekey_t, collide, void,
private_child_rekey_t *this, task_t *other)
{
@@ -406,9 +462,18 @@ METHOD(child_rekey_t, collide, void,
if (other->get_type(other) == TASK_CHILD_REKEY)
{
private_child_rekey_t *rekey = (private_child_rekey_t*)other;
+ child_sa_t *other_child;
+
if (rekey->child_sa != this->child_sa)
+ { /* not the same child => no collision */
+ other->destroy(other);
+ return;
+ }
+ /* ignore passive tasks that did not successfully create a CHILD_SA */
+ other_child = rekey->child_create->get_child(rekey->child_create);
+ if (!other_child ||
+ other_child->get_state(other_child) != CHILD_INSTALLED)
{
- /* not the same child => no collision */
other->destroy(other);
return;
}
@@ -416,19 +481,11 @@ METHOD(child_rekey_t, collide, void,
else if (other->get_type(other) == TASK_CHILD_DELETE)
{
child_delete_t *del = (child_delete_t*)other;
- if (this->collision &&
- this->collision->get_type(this->collision) == TASK_CHILD_REKEY)
+ if (is_redundant(this, del->get_child(del)))
{
- private_child_rekey_t *rekey;
-
- rekey = (private_child_rekey_t*)this->collision;
- if (del->get_child(del) == rekey->child_create->get_child(rekey->child_create))
- {
- /* peer deletes redundant child created in collision */
- this->other_child_destroyed = TRUE;
- other->destroy(other);
- return;
- }
+ this->other_child_destroyed = TRUE;
+ other->destroy(other);
+ return;
}
if (del->get_child(del) != this->child_sa)
{
@@ -439,7 +496,7 @@ METHOD(child_rekey_t, collide, void,
}
else
{
- /* any other task is not critical for collisisions, ignore */
+ /* any other task is not critical for collisions, ignore */
other->destroy(other);
return;
}
@@ -485,7 +542,7 @@ METHOD(task_t, destroy, void,
* Described in header.
*/
child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, protocol_id_t protocol,
- u_int32_t spi)
+ uint32_t spi)
{
private_child_rekey_t *this;
@@ -496,6 +553,7 @@ child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, protocol_id_t protocol,
.migrate = _migrate,
.destroy = _destroy,
},
+ .is_redundant = _is_redundant,
.collide = _collide,
},
.ike_sa = ike_sa,
diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.h b/src/libcharon/sa/ikev2/tasks/child_rekey.h
index 23384653d..0ad1a062d 100644
--- a/src/libcharon/sa/ikev2/tasks/child_rekey.h
+++ b/src/libcharon/sa/ikev2/tasks/child_rekey.h
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2016 Tobias Brunner
* Copyright (C) 2007 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -39,13 +40,25 @@ struct child_rekey_t {
task_t task;
/**
- * Register a rekeying task which collides with this one
+ * Check if the given SA is the redundant CHILD_SA created during a rekey
+ * collision.
+ *
+ * This is called if the other peer deletes the redundant SA before we were
+ * able to handle the CREATE_CHILD_SA response.
+ *
+ * @param child CHILD_SA to check
+ * @return TRUE if the SA is the redundant CHILD_SA
+ */
+ bool (*is_redundant)(child_rekey_t *this, child_sa_t *child);
+
+ /**
+ * Register a rekeying/delete task which collides with this one
*
* If two peers initiate rekeying at the same time, the collision must
* be handled gracefully. The task manager is aware of what exchanges
- * are going on and notifies the outgoing task by passing the incoming.
+ * are going on and notifies the active task by passing the passive.
*
- * @param other incoming task
+ * @param other passive task (adopted)
*/
void (*collide)(child_rekey_t* this, task_t *other);
};
@@ -59,6 +72,6 @@ struct child_rekey_t {
* @return child_rekey task to handle by the task_manager
*/
child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, protocol_id_t protocol,
- u_int32_t spi);
+ uint32_t spi);
#endif /** CHILD_REKEY_H_ @}*/
diff --git a/src/libcharon/sa/ikev2/tasks/ike_auth.c b/src/libcharon/sa/ikev2/tasks/ike_auth.c
index 79a436fbf..036910d0e 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_auth.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_auth.c
@@ -186,7 +186,7 @@ static status_t collect_other_init_data(private_ike_auth_t *this,
*/
static void get_reserved_id_bytes(private_ike_auth_t *this, id_payload_t *id)
{
- u_int8_t *byte;
+ uint8_t *byte;
int i;
for (i = 0; i < countof(this->reserved); i++)
@@ -564,6 +564,10 @@ METHOD(task_t, process_r, status_t,
this->ike_sa->enable_extension(this->ike_sa,
EXT_EAP_ONLY_AUTHENTICATION);
}
+ if (message->get_notify(message, INITIAL_CONTACT))
+ {
+ this->initial_contact = TRUE;
+ }
}
if (this->other_auth == NULL)
@@ -652,14 +656,6 @@ METHOD(task_t, process_r, status_t,
return NEED_MORE;
}
- /* If authenticated (with non-EAP) and received INITIAL_CONTACT,
- * delete any existing IKE_SAs with that peer. */
- if (message->get_message_id(message) == 1 &&
- message->get_notify(message, INITIAL_CONTACT))
- {
- this->initial_contact = TRUE;
- }
-
/* another auth round done, invoke authorize hook */
if (!charon->bus->authorize(charon->bus, FALSE))
{
@@ -749,13 +745,6 @@ METHOD(task_t, build_r, status_t,
get_reserved_id_bytes(this, id_payload);
message->add_payload(message, (payload_t*)id_payload);
- if (this->initial_contact)
- {
- charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
- this->ike_sa, TRUE);
- this->initial_contact = FALSE;
- }
-
if ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS) == AUTH_CLASS_EAP)
{ /* EAP-only authentication */
if (!this->ike_sa->supports_extension(this->ike_sa,
@@ -830,7 +819,7 @@ METHOD(task_t, build_r, status_t,
}
if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
- this->ike_sa, FALSE))
+ this->ike_sa, this->initial_contact))
{
DBG1(DBG_IKE, "cancelling IKE_SA setup due to uniqueness policy");
charon->bus->alert(charon->bus, ALERT_UNIQUE_KEEP);
diff --git a/src/libcharon/sa/ikev2/tasks/ike_auth_lifetime.c b/src/libcharon/sa/ikev2/tasks/ike_auth_lifetime.c
index a7d162e68..47b0a3ed1 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_auth_lifetime.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_auth_lifetime.c
@@ -45,14 +45,14 @@ struct private_ike_auth_lifetime_t {
static void add_auth_lifetime(private_ike_auth_lifetime_t *this, message_t *message)
{
chunk_t chunk;
- u_int32_t lifetime;
+ uint32_t lifetime;
lifetime = this->ike_sa->get_statistic(this->ike_sa, STAT_REAUTH);
if (lifetime)
{
lifetime -= time_monotonic(NULL);
chunk = chunk_from_thing(lifetime);
- *(u_int32_t*)chunk.ptr = htonl(lifetime);
+ *(uint32_t*)chunk.ptr = htonl(lifetime);
message->add_notify(message, FALSE, AUTH_LIFETIME, chunk);
}
}
@@ -64,13 +64,13 @@ static void process_payloads(private_ike_auth_lifetime_t *this, message_t *messa
{
notify_payload_t *notify;
chunk_t data;
- u_int32_t lifetime;
+ uint32_t lifetime;
notify = message->get_notify(message, AUTH_LIFETIME);
if (notify)
{
data = notify->get_notification_data(notify);
- lifetime = ntohl(*(u_int32_t*)data.ptr);
+ lifetime = ntohl(*(uint32_t*)data.ptr);
this->ike_sa->set_auth_lifetime(this->ike_sa, lifetime);
}
}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_delete.c b/src/libcharon/sa/ikev2/tasks/ike_delete.c
index e972dba07..fd36b144a 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_delete.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_delete.c
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2016 Tobias Brunner
* Copyright (C) 2006-2007 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -17,7 +18,7 @@
#include <daemon.h>
#include <encoding/payloads/delete_payload.h>
-
+#include <sa/ikev2/tasks/ike_rekey.h>
typedef struct private_ike_delete_t private_ike_delete_t;
@@ -45,11 +46,6 @@ struct private_ike_delete_t {
* are we deleting a rekeyed SA?
*/
bool rekeyed;
-
- /**
- * are we responding to a delete, but have initated our own?
- */
- bool simultaneous;
};
METHOD(task_t, build_i, status_t,
@@ -68,7 +64,8 @@ METHOD(task_t, build_i, status_t,
delete_payload = delete_payload_create(PLV2_DELETE, PROTO_IKE);
message->add_payload(message, (payload_t*)delete_payload);
- if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING ||
+ this->ike_sa->get_state(this->ike_sa) == IKE_REKEYED)
{
this->rekeyed = TRUE;
}
@@ -93,6 +90,33 @@ METHOD(task_t, process_i, status_t,
return DESTROY_ME;
}
+/**
+ * Check if this delete happened after a rekey collsion
+ */
+static bool after_rekey_collision(private_ike_delete_t *this)
+{
+ enumerator_t *tasks;
+ task_t *task;
+
+ tasks = this->ike_sa->create_task_enumerator(this->ike_sa,
+ TASK_QUEUE_ACTIVE);
+ while (tasks->enumerate(tasks, &task))
+ {
+ if (task->get_type(task) == TASK_IKE_REKEY)
+ {
+ ike_rekey_t *rekey = (ike_rekey_t*)task;
+
+ if (rekey->did_collide(rekey))
+ {
+ tasks->destroy(tasks);
+ return TRUE;
+ }
+ }
+ }
+ tasks->destroy(tasks);
+ return FALSE;
+}
+
METHOD(task_t, process_r, status_t,
private_ike_delete_t *this, message_t *message)
{
@@ -119,16 +143,24 @@ METHOD(task_t, process_r, status_t,
switch (this->ike_sa->get_state(this->ike_sa))
{
+ case IKE_REKEYING:
+ /* if the peer concurrently deleted the IKE_SA we treat this as
+ * regular delete. however, in case the peer did not detect a rekey
+ * collision it will delete the replaced IKE_SA if we are still in
+ * state IKE_REKEYING */
+ if (after_rekey_collision(this))
+ {
+ this->rekeyed = TRUE;
+ break;
+ }
+ /* fall-through */
case IKE_ESTABLISHED:
this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
this->ike_sa->reestablish(this->ike_sa);
return NEED_MORE;
- case IKE_REKEYING:
+ case IKE_REKEYED:
this->rekeyed = TRUE;
break;
- case IKE_DELETING:
- this->simultaneous = TRUE;
- break;
default:
break;
}
@@ -141,11 +173,6 @@ METHOD(task_t, build_r, status_t,
{
DBG0(DBG_IKE, "IKE_SA deleted");
- if (this->simultaneous)
- {
- /* wait for peer's response for our delete request */
- return SUCCESS;
- }
if (!this->rekeyed)
{ /* invoke ike_down() hook if SA has not been rekeyed */
charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
@@ -164,7 +191,6 @@ METHOD(task_t, migrate, void,
private_ike_delete_t *this, ike_sa_t *ike_sa)
{
this->ike_sa = ike_sa;
- this->simultaneous = FALSE;
}
METHOD(task_t, destroy, void,
diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c
index 78579be95..801b6d8f3 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_init.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.c
@@ -221,7 +221,7 @@ static void handle_supported_hash_algorithms(private_ike_init_t *this,
notify_payload_t *notify)
{
bio_reader_t *reader;
- u_int16_t algo;
+ uint16_t algo;
bool added = FALSE;
reader = bio_reader_create(notify->get_notification_data(notify));
@@ -373,13 +373,15 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
{
sa_payload_t *sa_payload = (sa_payload_t*)payload;
linked_list_t *proposal_list;
- bool private;
+ bool private, prefer_configured;
proposal_list = sa_payload->get_proposals(sa_payload);
private = this->ike_sa->supports_extension(this->ike_sa,
EXT_STRONGSWAN);
+ prefer_configured = lib->settings->get_bool(lib->settings,
+ "%s.prefer_configured_proposals", TRUE, lib->ns);
this->proposal = this->config->select_proposal(this->config,
- proposal_list, private);
+ proposal_list, private, prefer_configured);
if (!this->proposal)
{
charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_IKE,
@@ -633,7 +635,7 @@ METHOD(task_t, build_r, status_t,
if (this->dh == NULL ||
!this->proposal->has_dh_group(this->proposal, this->dh_group))
{
- u_int16_t group;
+ uint16_t group;
if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
&group, NULL))
@@ -765,7 +767,7 @@ METHOD(task_t, process_i, status_t,
bad_group = this->dh_group;
data = notify->get_notification_data(notify);
- this->dh_group = ntohs(*((u_int16_t*)data.ptr));
+ this->dh_group = ntohs(*((uint16_t*)data.ptr));
DBG1(DBG_IKE, "peer didn't accept DH group %N, "
"it requested %N", diffie_hellman_group_names,
bad_group, diffie_hellman_group_names, this->dh_group);
diff --git a/src/libcharon/sa/ikev2/tasks/ike_me.c b/src/libcharon/sa/ikev2/tasks/ike_me.c
index 10d412ffd..f077ccfb5 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_me.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_me.c
@@ -128,7 +128,7 @@ static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message)
{
enumerator_t *enumerator;
host_t *addr, *host;
- u_int16_t port;
+ uint16_t port;
/* get the port that is used to communicate with the ms */
host = this->ike_sa->get_my_host(this->ike_sa);
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
index 3f7bb175f..dc0f24fb8 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
@@ -299,7 +299,7 @@ static void update_children(private_ike_mobike_t *this)
/**
* Apply the port of the old host, if its ip equals the new, use port otherwise.
*/
-static void apply_port(host_t *host, host_t *old, u_int16_t port, bool local)
+static void apply_port(host_t *host, host_t *old, uint16_t port, bool local)
{
if (host->ip_equals(host, old))
{
diff --git a/src/libcharon/sa/ikev2/tasks/ike_natd.c b/src/libcharon/sa/ikev2/tasks/ike_natd.c
index 4bf5264dd..f3f32d7af 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_natd.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_natd.c
@@ -99,8 +99,8 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this,
{
chunk_t natd_chunk, spi_i_chunk, spi_r_chunk, addr_chunk, port_chunk;
chunk_t natd_hash;
- u_int64_t spi_i, spi_r;
- u_int16_t port;
+ uint64_t spi_i, spi_r;
+ uint16_t port;
/* prepare all required chunks */
spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
@@ -142,7 +142,7 @@ static notify_payload_t *build_natd_payload(private_ike_natd_t *this,
config = this->ike_sa->get_ike_cfg(this->ike_sa);
if (force_encap(config) && type == NAT_DETECTION_SOURCE_IP)
{
- u_int32_t addr;
+ uint32_t addr;
/* chunk_hash() is randomly keyed so this produces a random IPv4 address
* that changes with every restart but otherwise stays the same */
diff --git a/src/libcharon/sa/ikev2/tasks/ike_rekey.c b/src/libcharon/sa/ikev2/tasks/ike_rekey.c
index eaba04e3a..2f0552a33 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.c
@@ -1,7 +1,8 @@
/*
+ * Copyright (C) 2015-2016 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -66,9 +67,30 @@ struct private_ike_rekey_t {
* colliding task detected by the task manager
*/
task_t *collision;
+
+ /**
+ * TRUE if rekeying can't be handled temporarily
+ */
+ bool failed_temporarily;
};
/**
+ * Schedule a retry if rekeying temporary failed
+ */
+static void schedule_delayed_rekey(private_ike_rekey_t *this)
+{
+ uint32_t retry;
+ job_t *job;
+
+ retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
+ job = (job_t*)rekey_ike_sa_job_create(
+ this->ike_sa->get_id(this->ike_sa), FALSE);
+ DBG1(DBG_IKE, "IKE_SA rekeying failed, trying again in %d seconds", retry);
+ this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
+ lib->scheduler->schedule_job(lib->scheduler, job, retry);
+}
+
+/**
* Check if an IKE_SA has any queued tasks, return initiation job
*/
static job_t* check_queued_tasks(ike_sa_t *ike_sa)
@@ -83,7 +105,6 @@ static job_t* check_queued_tasks(ike_sa_t *ike_sa)
job = (job_t*)initiate_tasks_job_create(ike_sa->get_id(ike_sa));
}
enumerator->destroy(enumerator);
-
return job;
}
@@ -117,20 +138,9 @@ static void establish_new(private_ike_rekey_t *this)
}
this->new_sa = NULL;
charon->bus->set_sa(charon->bus, this->ike_sa);
- }
-}
-METHOD(task_t, process_r_delete, status_t,
- private_ike_rekey_t *this, message_t *message)
-{
- establish_new(this);
- return this->ike_delete->task.process(&this->ike_delete->task, message);
-}
-
-METHOD(task_t, build_r_delete, status_t,
- private_ike_rekey_t *this, message_t *message)
-{
- return this->ike_delete->task.build(&this->ike_delete->task, message);
+ this->ike_sa->set_state(this->ike_sa, IKE_REKEYED);
+ }
}
METHOD(task_t, build_i_delete, status_t,
@@ -172,36 +182,59 @@ METHOD(task_t, build_i, status_t,
return NEED_MORE;
}
-METHOD(task_t, process_r, status_t,
- private_ike_rekey_t *this, message_t *message)
+/**
+ * Check if there are any half-open children
+ */
+static bool have_half_open_children(private_ike_rekey_t *this)
{
enumerator_t *enumerator;
child_sa_t *child_sa;
-
- if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
- {
- DBG1(DBG_IKE, "peer initiated rekeying, but we are deleting");
- return NEED_MORE;
- }
+ task_t *task;
enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
switch (child_sa->get_state(child_sa))
{
- case CHILD_CREATED:
case CHILD_REKEYING:
case CHILD_RETRYING:
case CHILD_DELETING:
- /* we do not allow rekeying while we have children in-progress */
- DBG1(DBG_IKE, "peer initiated rekeying, but a child is half-open");
enumerator->destroy(enumerator);
- return NEED_MORE;
+ return TRUE;
default:
break;
}
}
enumerator->destroy(enumerator);
+ enumerator = this->ike_sa->create_task_enumerator(this->ike_sa,
+ TASK_QUEUE_ACTIVE);
+ while (enumerator->enumerate(enumerator, (void**)&task))
+ {
+ if (task->get_type(task) == TASK_CHILD_CREATE)
+ {
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return FALSE;
+}
+
+METHOD(task_t, process_r, status_t,
+ private_ike_rekey_t *this, message_t *message)
+{
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
+ {
+ DBG1(DBG_IKE, "peer initiated rekeying, but we are deleting");
+ this->failed_temporarily = TRUE;
+ return NEED_MORE;
+ }
+ if (have_half_open_children(this))
+ {
+ DBG1(DBG_IKE, "peer initiated rekeying, but a child is half-open");
+ this->failed_temporarily = TRUE;
+ return NEED_MORE;
+ }
this->new_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
this->ike_sa->get_version(this->ike_sa), FALSE);
@@ -219,33 +252,57 @@ METHOD(task_t, process_r, status_t,
METHOD(task_t, build_r, status_t,
private_ike_rekey_t *this, message_t *message)
{
+ if (this->failed_temporarily)
+ {
+ message->add_notify(message, TRUE, TEMPORARY_FAILURE, chunk_empty);
+ return SUCCESS;
+ }
if (this->new_sa == NULL)
{
/* IKE_SA/a CHILD_SA is in an inacceptable state, deny rekeying */
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
return SUCCESS;
}
-
if (this->ike_init->task.build(&this->ike_init->task, message) == FAILED)
{
+ this->ike_init->task.destroy(&this->ike_init->task);
+ this->ike_init = NULL;
charon->bus->set_sa(charon->bus, this->ike_sa);
return SUCCESS;
}
charon->bus->set_sa(charon->bus, this->ike_sa);
- this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
- /* rekeying successful, delete the IKE_SA using a subtask */
- this->ike_delete = ike_delete_create(this->ike_sa, FALSE);
- this->public.task.build = _build_r_delete;
- this->public.task.process = _process_r_delete;
-
- /* the peer does have to delete the IKE_SA. If it does not, we get a
- * unusable IKE_SA in REKEYING state without a replacement. We consider
- * this a timeout condition by the peer, and trigger a delete actively. */
- lib->scheduler->schedule_job(lib->scheduler, (job_t*)
- delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE), 90);
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_REKEYING)
+ { /* in case of a collision we let the initiating task handle this */
+ establish_new(this);
+ /* make sure the IKE_SA is gone in case the peer fails to delete it */
+ lib->scheduler->schedule_job(lib->scheduler, (job_t*)
+ delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
+ 90);
+ }
+ return SUCCESS;
+}
- return NEED_MORE;
+/**
+ * Conclude any undetected rekey collision.
+ *
+ * If the peer does not detect the collision it will delete this IKE_SA.
+ * Depending on when our request reaches the peer and we receive the delete
+ * this may get called at different times.
+ *
+ * Returns TRUE if there was a collision, FALSE otherwise.
+ */
+static bool conclude_undetected_collision(private_ike_rekey_t *this)
+{
+ if (this->collision &&
+ this->collision->get_type(this->collision) == TASK_IKE_REKEY)
+ {
+ DBG1(DBG_IKE, "peer did not notice IKE_SA rekey collision, abort "
+ "active rekeying");
+ establish_new((private_ike_rekey_t*)this->collision);
+ return TRUE;
+ }
+ return FALSE;
}
METHOD(task_t, process_i, status_t,
@@ -266,18 +323,9 @@ METHOD(task_t, process_i, status_t,
{
case FAILED:
/* rekeying failed, fallback to old SA */
- if (!(this->collision && (
- this->collision->get_type(this->collision) == TASK_IKE_DELETE ||
- this->collision->get_type(this->collision) == TASK_IKE_REAUTH)))
+ if (!conclude_undetected_collision(this))
{
- job_t *job;
- u_int32_t retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
- job = (job_t*)rekey_ike_sa_job_create(
- this->ike_sa->get_id(this->ike_sa), FALSE);
- DBG1(DBG_IKE, "IKE_SA rekeying failed, "
- "trying again in %d seconds", retry);
- this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- lib->scheduler->schedule_job(lib->scheduler, job, retry);
+ schedule_delayed_rekey(this);
}
return SUCCESS;
case NEED_MORE:
@@ -293,55 +341,53 @@ METHOD(task_t, process_i, status_t,
this->collision->get_type(this->collision) == TASK_IKE_REKEY)
{
private_ike_rekey_t *other = (private_ike_rekey_t*)this->collision;
+ host_t *host;
+ chunk_t this_nonce, other_nonce;
- /* ike_init can be NULL, if child_sa is half-open */
- if (other->ike_init)
- {
- host_t *host;
- chunk_t this_nonce, other_nonce;
-
- this_nonce = this->ike_init->get_lower_nonce(this->ike_init);
- other_nonce = other->ike_init->get_lower_nonce(other->ike_init);
+ this_nonce = this->ike_init->get_lower_nonce(this->ike_init);
+ other_nonce = other->ike_init->get_lower_nonce(other->ike_init);
- /* if we have the lower nonce, delete rekeyed SA. If not, delete
- * the redundant. */
- if (memcmp(this_nonce.ptr, other_nonce.ptr,
- min(this_nonce.len, other_nonce.len)) > 0)
+ /* if we have the lower nonce, delete rekeyed SA. If not, delete
+ * the redundant. */
+ if (memcmp(this_nonce.ptr, other_nonce.ptr,
+ min(this_nonce.len, other_nonce.len)) < 0)
+ {
+ DBG1(DBG_IKE, "IKE_SA rekey collision lost, deleting redundant "
+ "IKE_SA %s[%d]", this->new_sa->get_name(this->new_sa),
+ this->new_sa->get_unique_id(this->new_sa));
+ /* apply host for a proper delete */
+ host = this->ike_sa->get_my_host(this->ike_sa);
+ this->new_sa->set_my_host(this->new_sa, host->clone(host));
+ host = this->ike_sa->get_other_host(this->ike_sa);
+ this->new_sa->set_other_host(this->new_sa, host->clone(host));
+ /* IKE_SAs in state IKE_REKEYED are silently deleted, so we use
+ * IKE_REKEYING */
+ this->new_sa->set_state(this->new_sa, IKE_REKEYING);
+ if (this->new_sa->delete(this->new_sa) == DESTROY_ME)
{
- /* peer should delete this SA. Add a timeout just in case. */
- job_t *job = (job_t*)delete_ike_sa_job_create(
- other->new_sa->get_id(other->new_sa), TRUE);
- lib->scheduler->schedule_job(lib->scheduler, job, 10);
- DBG1(DBG_IKE, "IKE_SA rekey collision won, waiting for delete");
- charon->ike_sa_manager->checkin(charon->ike_sa_manager, other->new_sa);
- other->new_sa = NULL;
+ this->new_sa->destroy(this->new_sa);
}
else
{
- DBG1(DBG_IKE, "IKE_SA rekey collision lost, "
- "deleting redundant IKE_SA");
- /* apply host for a proper delete */
- host = this->ike_sa->get_my_host(this->ike_sa);
- this->new_sa->set_my_host(this->new_sa, host->clone(host));
- host = this->ike_sa->get_other_host(this->ike_sa);
- this->new_sa->set_other_host(this->new_sa, host->clone(host));
- this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- this->new_sa->set_state(this->new_sa, IKE_REKEYING);
- if (this->new_sa->delete(this->new_sa) == DESTROY_ME)
- {
- this->new_sa->destroy(this->new_sa);
- }
- else
- {
- charon->ike_sa_manager->checkin(
- charon->ike_sa_manager, this->new_sa);
- }
- charon->bus->set_sa(charon->bus, this->ike_sa);
- this->new_sa = NULL;
- establish_new(other);
- return SUCCESS;
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager,
+ this->new_sa);
}
+ charon->bus->set_sa(charon->bus, this->ike_sa);
+ this->new_sa = NULL;
+ establish_new(other);
+ return SUCCESS;
}
+ /* peer should delete this SA. Add a timeout just in case. */
+ job_t *job = (job_t*)delete_ike_sa_job_create(
+ other->new_sa->get_id(other->new_sa), TRUE);
+ lib->scheduler->schedule_job(lib->scheduler, job,
+ HALF_OPEN_IKE_SA_TIMEOUT);
+ DBG1(DBG_IKE, "IKE_SA rekey collision won, waiting for delete for "
+ "redundant IKE_SA %s[%d]", other->new_sa->get_name(other->new_sa),
+ other->new_sa->get_unique_id(other->new_sa));
+ other->new_sa->set_state(other->new_sa, IKE_REKEYED);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, other->new_sa);
+ other->new_sa = NULL;
charon->bus->set_sa(charon->bus, this->ike_sa);
}
@@ -361,11 +407,41 @@ METHOD(task_t, get_type, task_type_t,
return TASK_IKE_REKEY;
}
+METHOD(ike_rekey_t, did_collide, bool,
+ private_ike_rekey_t *this)
+{
+ return this->collision &&
+ this->collision->get_type(this->collision) == TASK_IKE_REKEY;
+}
+
METHOD(ike_rekey_t, collide, void,
private_ike_rekey_t* this, task_t *other)
{
DBG1(DBG_IKE, "detected %N collision with %N", task_type_names,
TASK_IKE_REKEY, task_type_names, other->get_type(other));
+
+ switch (other->get_type(other))
+ {
+ case TASK_IKE_DELETE:
+ conclude_undetected_collision(this);
+ other->destroy(other);
+ return;
+ case TASK_IKE_REKEY:
+ {
+ private_ike_rekey_t *rekey = (private_ike_rekey_t*)other;
+
+ if (!rekey->ike_init)
+ {
+ DBG1(DBG_IKE, "colliding exchange did not result in an IKE_SA, "
+ "ignore");
+ other->destroy(other);
+ return;
+ }
+ break;
+ }
+ default:
+ break;
+ }
DESTROY_IF(this->collision);
this->collision = other;
}
@@ -425,6 +501,7 @@ ike_rekey_t *ike_rekey_create(ike_sa_t *ike_sa, bool initiator)
.migrate = _migrate,
.destroy = _destroy,
},
+ .did_collide = _did_collide,
.collide = _collide,
},
.ike_sa = ike_sa,
diff --git a/src/libcharon/sa/ikev2/tasks/ike_rekey.h b/src/libcharon/sa/ikev2/tasks/ike_rekey.h
index 6a12e9034..86b512c92 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_rekey.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.h
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2016 Tobias Brunner
* Copyright (C) 2007 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -38,6 +39,13 @@ struct ike_rekey_t {
task_t task;
/**
+ * Check if there was a rekey collision.
+ *
+ * @return TRUE if there was a rekey collision before
+ */
+ bool (*did_collide)(ike_rekey_t *this);
+
+ /**
* Register a rekeying task which collides with this one.
*
* If two peers initiate rekeying at the same time, the collision must
diff --git a/src/libcharon/sa/redirect_manager.c b/src/libcharon/sa/redirect_manager.c
index ff92ac29f..45b7e79df 100644
--- a/src/libcharon/sa/redirect_manager.c
+++ b/src/libcharon/sa/redirect_manager.c
@@ -248,7 +248,7 @@ identification_t *redirect_data_parse(chunk_t data, chunk_t *nonce)
bio_reader_t *reader;
id_type_t id_type;
chunk_t gateway;
- u_int8_t type;
+ uint8_t type;
reader = bio_reader_create(data);
if (!reader->read_uint8(reader, &type) ||
diff --git a/src/libcharon/sa/shunt_manager.c b/src/libcharon/sa/shunt_manager.c
index 0e9cf6e1f..40e291be5 100644
--- a/src/libcharon/sa/shunt_manager.c
+++ b/src/libcharon/sa/shunt_manager.c
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2015 Tobias Brunner
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2015-2016 Tobias Brunner
+ * Copyright (C) 2011-2016 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -68,6 +68,8 @@ static bool install_shunt_policy(child_cfg_t *child)
policy_type_t policy_type;
policy_priority_t policy_prio;
status_t status = SUCCESS;
+ uint32_t manual_prio;
+ char *interface;
ipsec_sa_cfg_t sa = { .mode = MODE_TRANSPORT };
switch (child->get_mode(child))
@@ -92,6 +94,9 @@ static bool install_shunt_policy(child_cfg_t *child)
other_ts_list = child->get_traffic_selectors(child, FALSE, NULL, hosts);
hosts->destroy(hosts);
+ manual_prio = child->get_manual_prio(child);
+ interface = child->get_interface(child);
+
/* enumerate pairs of traffic selectors */
e_my_ts = my_ts_list->create_enumerator(my_ts_list);
while (e_my_ts->enumerate(e_my_ts, &my_ts))
@@ -110,25 +115,37 @@ static bool install_shunt_policy(child_cfg_t *child)
continue;
}
/* install out policy */
- status |= charon->kernel->add_policy(charon->kernel,
- host_any, host_any,
- my_ts, other_ts, POLICY_OUT, policy_type,
- &sa, child->get_mark(child, FALSE),
- policy_prio);
-
+ kernel_ipsec_policy_id_t id = {
+ .dir = POLICY_OUT,
+ .src_ts = my_ts,
+ .dst_ts = other_ts,
+ .mark = child->get_mark(child, FALSE),
+ .interface = interface,
+ };
+ kernel_ipsec_manage_policy_t policy = {
+ .type = policy_type,
+ .prio = policy_prio,
+ .manual_prio = manual_prio,
+ .src = host_any,
+ .dst = host_any,
+ .sa = &sa,
+ };
+ status |= charon->kernel->add_policy(charon->kernel, &id, &policy);
+ /* install "outbound" forward policy */
+ id.dir = POLICY_FWD;
+ status |= charon->kernel->add_policy(charon->kernel, &id, &policy);
/* install in policy */
- status |= charon->kernel->add_policy(charon->kernel,
- host_any, host_any,
- other_ts, my_ts, POLICY_IN, policy_type,
- &sa, child->get_mark(child, TRUE),
- policy_prio);
-
- /* install forward policy */
- status |= charon->kernel->add_policy(charon->kernel,
- host_any, host_any,
- other_ts, my_ts, POLICY_FWD, policy_type,
- &sa, child->get_mark(child, TRUE),
- policy_prio);
+ id = (kernel_ipsec_policy_id_t){
+ .dir = POLICY_IN,
+ .src_ts = other_ts,
+ .dst_ts = my_ts,
+ .mark = child->get_mark(child, TRUE),
+ .interface = interface,
+ };
+ status |= charon->kernel->add_policy(charon->kernel, &id, &policy);
+ /* install "inbound" forward policy */
+ id.dir = POLICY_FWD;
+ status |= charon->kernel->add_policy(charon->kernel, &id, &policy);
}
e_other_ts->destroy(e_other_ts);
}
@@ -205,6 +222,8 @@ static void uninstall_shunt_policy(child_cfg_t *child)
policy_type_t policy_type;
policy_priority_t policy_prio;
status_t status = SUCCESS;
+ uint32_t manual_prio;
+ char *interface;
ipsec_sa_cfg_t sa = { .mode = MODE_TRANSPORT };
switch (child->get_mode(child))
@@ -229,6 +248,9 @@ static void uninstall_shunt_policy(child_cfg_t *child)
other_ts_list = child->get_traffic_selectors(child, FALSE, NULL, hosts);
hosts->destroy(hosts);
+ manual_prio = child->get_manual_prio(child);
+ interface = child->get_interface(child);
+
/* enumerate pairs of traffic selectors */
e_my_ts = my_ts_list->create_enumerator(my_ts_list);
while (e_my_ts->enumerate(e_my_ts, &my_ts))
@@ -247,25 +269,37 @@ static void uninstall_shunt_policy(child_cfg_t *child)
continue;
}
/* uninstall out policy */
- status |= charon->kernel->del_policy(charon->kernel,
- host_any, host_any,
- my_ts, other_ts, POLICY_OUT, policy_type,
- &sa, child->get_mark(child, FALSE),
- policy_prio);
-
+ kernel_ipsec_policy_id_t id = {
+ .dir = POLICY_OUT,
+ .src_ts = my_ts,
+ .dst_ts = other_ts,
+ .mark = child->get_mark(child, FALSE),
+ .interface = interface,
+ };
+ kernel_ipsec_manage_policy_t policy = {
+ .type = policy_type,
+ .prio = policy_prio,
+ .manual_prio = manual_prio,
+ .src = host_any,
+ .dst = host_any,
+ .sa = &sa,
+ };
+ status |= charon->kernel->del_policy(charon->kernel, &id, &policy);
+ /* uninstall "outbound" forward policy */
+ id.dir = POLICY_FWD;
+ status |= charon->kernel->del_policy(charon->kernel, &id, &policy);
/* uninstall in policy */
- status |= charon->kernel->del_policy(charon->kernel,
- host_any, host_any,
- other_ts, my_ts, POLICY_IN, policy_type,
- &sa, child->get_mark(child, TRUE),
- policy_prio);
-
- /* uninstall forward policy */
- status |= charon->kernel->del_policy(charon->kernel,
- host_any, host_any,
- other_ts, my_ts, POLICY_FWD, policy_type,
- &sa, child->get_mark(child, TRUE),
- policy_prio);
+ id = (kernel_ipsec_policy_id_t){
+ .dir = POLICY_IN,
+ .src_ts = other_ts,
+ .dst_ts = my_ts,
+ .mark = child->get_mark(child, TRUE),
+ .interface = interface,
+ };
+ status |= charon->kernel->del_policy(charon->kernel, &id, &policy);
+ /* uninstall "inbound" forward policy */
+ id.dir = POLICY_FWD;
+ status |= charon->kernel->del_policy(charon->kernel, &id, &policy);
}
e_other_ts->destroy(e_other_ts);
}
diff --git a/src/libcharon/sa/task_manager.h b/src/libcharon/sa/task_manager.h
index e7a6bf463..86077d373 100644
--- a/src/libcharon/sa/task_manager.h
+++ b/src/libcharon/sa/task_manager.h
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2013-2016 Tobias Brunner
* Copyright (C) 2006 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -122,7 +123,17 @@ struct task_manager_t {
*
* @param task task to queue
*/
- void (*queue_task) (task_manager_t *this, task_t *task);
+ void (*queue_task)(task_manager_t *this, task_t *task);
+
+ /**
+ * Queue a task in the manager, but delay its initiation for at least the
+ * given number of seconds.
+ *
+ * @param task task to queue
+ * @param delay minimum delay in s before initiating the task
+ */
+ void (*queue_task_delayed)(task_manager_t *this, task_t *task,
+ uint32_t delay);
/**
* Queue IKE_SA establishing tasks.
@@ -160,7 +171,7 @@ struct task_manager_t {
* @param tsi initiator traffic selector, if packet-triggered
* @param tsr responder traffic selector, if packet-triggered
*/
- void (*queue_child)(task_manager_t *this, child_cfg_t *cfg, u_int32_t reqid,
+ void (*queue_child)(task_manager_t *this, child_cfg_t *cfg, uint32_t reqid,
traffic_selector_t *tsi, traffic_selector_t *tsr);
/**
@@ -170,7 +181,7 @@ struct task_manager_t {
* @param spi CHILD_SA SPI to rekey
*/
void (*queue_child_rekey)(task_manager_t *this, protocol_id_t protocol,
- u_int32_t spi);
+ uint32_t spi);
/**
* Queue CHILD_SA delete tasks.
@@ -180,7 +191,7 @@ struct task_manager_t {
* @param expired TRUE if SA already expired
*/
void (*queue_child_delete)(task_manager_t *this, protocol_id_t protocol,
- u_int32_t spi, bool expired);
+ uint32_t spi, bool expired);
/**
* Queue liveness checking tasks.
@@ -199,7 +210,7 @@ struct task_manager_t {
* - INVALID_STATE if retransmission not required
* - SUCCESS if retransmission sent
*/
- status_t (*retransmit) (task_manager_t *this, u_int32_t message_id);
+ status_t (*retransmit) (task_manager_t *this, uint32_t message_id);
/**
* Migrate all queued tasks from other to this.
@@ -242,7 +253,7 @@ struct task_manager_t {
* @param initiate message ID / DPD seq to initiate exchanges (send)
* @param respond message ID / DPD seq to respond to exchanges (expect)
*/
- void (*reset) (task_manager_t *this, u_int32_t initiate, u_int32_t respond);
+ void (*reset) (task_manager_t *this, uint32_t initiate, uint32_t respond);
/**
* Check if we are currently waiting for a reply.
diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c
index 85e220775..40a0682f2 100644
--- a/src/libcharon/sa/trap_manager.c
+++ b/src/libcharon/sa/trap_manager.c
@@ -115,7 +115,7 @@ typedef struct {
/** pending IKE_SA connecting upon acquire */
ike_sa_t *ike_sa;
/** reqid of pending trap policy */
- u_int32_t reqid;
+ uint32_t reqid;
/** destination address (wildcard case) */
host_t *dst;
} acquire_t;
@@ -143,7 +143,7 @@ static void destroy_acquire(acquire_t *this)
/**
* match an acquire entry by reqid
*/
-static bool acquire_by_reqid(acquire_t *this, u_int32_t *reqid)
+static bool acquire_by_reqid(acquire_t *this, uint32_t *reqid)
{
return this->reqid == *reqid;
}
@@ -156,9 +156,9 @@ static bool acquire_by_dst(acquire_t *this, host_t *dst)
return this->dst && this->dst->ip_equals(this->dst, dst);
}
-METHOD(trap_manager_t, install, u_int32_t,
+METHOD(trap_manager_t, install, uint32_t,
private_trap_manager_t *this, peer_cfg_t *peer, child_cfg_t *child,
- u_int32_t reqid)
+ uint32_t reqid)
{
entry_t *entry, *found = NULL;
ike_cfg_t *ike_cfg;
@@ -197,9 +197,7 @@ METHOD(trap_manager_t, install, u_int32_t,
me = charon->kernel->get_source_addr(charon->kernel, other, NULL);
if (!me)
{
- DBG1(DBG_CFG, "installing trap failed, local address unknown");
- other->destroy(other);
- return 0;
+ me = host_create_any(other->get_family(other));
}
me->set_port(me, ike_cfg->get_my_port(ike_cfg));
}
@@ -307,7 +305,7 @@ METHOD(trap_manager_t, install, u_int32_t,
}
METHOD(trap_manager_t, uninstall, bool,
- private_trap_manager_t *this, u_int32_t reqid)
+ private_trap_manager_t *this, uint32_t reqid)
{
enumerator_t *enumerator;
entry_t *entry, *found = NULL;
@@ -366,12 +364,12 @@ METHOD(trap_manager_t, create_enumerator, enumerator_t*,
(void*)this->lock->unlock);
}
-METHOD(trap_manager_t, find_reqid, u_int32_t,
+METHOD(trap_manager_t, find_reqid, uint32_t,
private_trap_manager_t *this, child_cfg_t *child)
{
enumerator_t *enumerator;
entry_t *entry;
- u_int32_t reqid = 0;
+ uint32_t reqid = 0;
this->lock->read_lock(this->lock);
enumerator = this->traps->create_enumerator(this->traps);
@@ -392,7 +390,7 @@ METHOD(trap_manager_t, find_reqid, u_int32_t,
}
METHOD(trap_manager_t, acquire, void,
- private_trap_manager_t *this, u_int32_t reqid,
+ private_trap_manager_t *this, uint32_t reqid,
traffic_selector_t *src, traffic_selector_t *dst)
{
enumerator_t *enumerator;
@@ -430,7 +428,7 @@ METHOD(trap_manager_t, acquire, void,
if (wildcard)
{ /* for wildcard acquires we check that we don't have a pending acquire
* with the same peer */
- u_int8_t mask;
+ uint8_t mask;
dst->to_subnet(dst, &host, &mask);
if (this->acquires->find_first(this->acquires, (void*)acquire_by_dst,
@@ -483,8 +481,8 @@ METHOD(trap_manager_t, acquire, void,
if (ike_sa)
{
ike_cfg_t *ike_cfg;
- u_int16_t port;
- u_int8_t mask;
+ uint16_t port;
+ uint8_t mask;
ike_sa->set_peer_cfg(ike_sa, peer);
ike_cfg = ike_sa->get_ike_cfg(ike_sa);
diff --git a/src/libcharon/sa/trap_manager.h b/src/libcharon/sa/trap_manager.h
index 0491107fd..083ea3dbf 100644
--- a/src/libcharon/sa/trap_manager.h
+++ b/src/libcharon/sa/trap_manager.h
@@ -40,8 +40,8 @@ struct trap_manager_t {
* @param reqid optional reqid to use
* @return reqid of installed CHILD_SA, 0 if failed
*/
- u_int32_t (*install)(trap_manager_t *this, peer_cfg_t *peer,
- child_cfg_t *child, u_int32_t reqid);
+ uint32_t (*install)(trap_manager_t *this, peer_cfg_t *peer,
+ child_cfg_t *child, uint32_t reqid);
/**
* Uninstall a trap policy.
@@ -49,7 +49,7 @@ struct trap_manager_t {
* @param id reqid of CHILD_SA to uninstall, returned by install()
* @return TRUE if uninstalled successfully
*/
- bool (*uninstall)(trap_manager_t *this, u_int32_t reqid);
+ bool (*uninstall)(trap_manager_t *this, uint32_t reqid);
/**
* Create an enumerator over all installed traps.
@@ -64,7 +64,7 @@ struct trap_manager_t {
* @param child CHILD_SA config to get the reqid for
* @return reqid of trap, 0 if not found
*/
- u_int32_t (*find_reqid)(trap_manager_t *this, child_cfg_t *child);
+ uint32_t (*find_reqid)(trap_manager_t *this, child_cfg_t *child);
/**
* Acquire an SA triggered by an installed trap.
@@ -73,7 +73,7 @@ struct trap_manager_t {
* @param src source of the triggering packet
* @param dst destination of the triggering packet
*/
- void (*acquire)(trap_manager_t *this, u_int32_t reqid,
+ void (*acquire)(trap_manager_t *this, uint32_t reqid,
traffic_selector_t *src, traffic_selector_t *dst);
/**