child-sa: Use flags to track installation of outbound SA and policies separately

This commit is contained in:
Tobias Brunner
2017-08-07 10:44:05 +02:00
parent 2699c8387a
commit 2c116ef589
3 changed files with 46 additions and 29 deletions
+28 -23
View File
@@ -40,10 +40,10 @@ ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
"DESTROYING", "DESTROYING",
); );
ENUM(child_sa_outbound_state_names, CHILD_OUTBOUND_NONE, CHILD_OUTBOUND_INSTALLED, ENUM_FLAGS(child_sa_outbound_state_names, CHILD_OUTBOUND_REGISTERED, CHILD_OUTBOUND_POLICIES,
"NONE",
"REGISTERED", "REGISTERED",
"INSTALLED", "SA",
"POLICIES",
); );
typedef struct private_child_sa_t private_child_sa_t; typedef struct private_child_sa_t private_child_sa_t;
@@ -547,7 +547,7 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
} }
else else
{ {
if (this->other_spi && this->outbound_state == CHILD_OUTBOUND_INSTALLED) if (this->other_spi && (this->outbound_state & CHILD_OUTBOUND_SA))
{ {
kernel_ipsec_sa_id_t id = { kernel_ipsec_sa_id_t id = {
.src = this->my_addr, .src = this->my_addr,
@@ -788,7 +788,7 @@ static status_t install_internal(private_child_sa_t *this, chunk_t encr,
{ {
tfc = this->config->get_tfc(this->config); tfc = this->config->get_tfc(this->config);
} }
this->outbound_state = CHILD_OUTBOUND_INSTALLED; this->outbound_state |= CHILD_OUTBOUND_SA;
} }
DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound", DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
@@ -1188,6 +1188,7 @@ METHOD(child_sa_t, install_policies, status_t,
linked_list_t *my_ts_list, *other_ts_list; linked_list_t *my_ts_list, *other_ts_list;
traffic_selector_t *my_ts, *other_ts; traffic_selector_t *my_ts, *other_ts;
status_t status = SUCCESS; status_t status = SUCCESS;
bool install_outbound = FALSE;
if (!this->reqid_allocated && !this->static_reqid) if (!this->reqid_allocated && !this->static_reqid)
{ {
@@ -1207,12 +1208,17 @@ METHOD(child_sa_t, install_policies, status_t,
this->reqid_allocated = TRUE; this->reqid_allocated = TRUE;
} }
if (!(this->outbound_state & CHILD_OUTBOUND_REGISTERED))
{
install_outbound = TRUE;
this->outbound_state |= CHILD_OUTBOUND_POLICIES;
}
if (!this->config->has_option(this->config, OPT_NO_POLICIES)) if (!this->config->has_option(this->config, OPT_NO_POLICIES))
{ {
policy_priority_t priority; policy_priority_t priority;
ipsec_sa_cfg_t my_sa, other_sa; ipsec_sa_cfg_t my_sa, other_sa;
uint32_t manual_prio; uint32_t manual_prio;
bool install_outbound;
prepare_sa_cfg(this, &my_sa, &other_sa); prepare_sa_cfg(this, &my_sa, &other_sa);
manual_prio = this->config->get_manual_prio(this->config); manual_prio = this->config->get_manual_prio(this->config);
@@ -1222,7 +1228,6 @@ METHOD(child_sa_t, install_policies, status_t,
this->trap = this->state == CHILD_CREATED; this->trap = this->state == CHILD_CREATED;
priority = this->trap ? POLICY_PRIORITY_ROUTED priority = this->trap ? POLICY_PRIORITY_ROUTED
: POLICY_PRIORITY_DEFAULT; : POLICY_PRIORITY_DEFAULT;
install_outbound = this->outbound_state != CHILD_OUTBOUND_REGISTERED;
/* enumerate pairs of traffic selectors */ /* enumerate pairs of traffic selectors */
enumerator = create_policy_enumerator(this); enumerator = create_policy_enumerator(this);
@@ -1250,7 +1255,6 @@ METHOD(child_sa_t, install_policies, status_t,
this->other_addr, my_ts, other_ts, this->other_addr, my_ts, other_ts,
&my_sa, &other_sa, POLICY_IPSEC, &my_sa, &other_sa, POLICY_IPSEC,
priority, manual_prio); priority, manual_prio);
} }
if (status != SUCCESS) if (status != SUCCESS)
{ {
@@ -1281,7 +1285,7 @@ METHOD(child_sa_t, register_outbound, void,
this->encr_r = chunk_clone(encr); this->encr_r = chunk_clone(encr);
this->integ_r = chunk_clone(integ); this->integ_r = chunk_clone(integ);
this->tfcv3 = tfcv3; this->tfcv3 = tfcv3;
this->outbound_state = CHILD_OUTBOUND_REGISTERED; this->outbound_state |= CHILD_OUTBOUND_REGISTERED;
} }
METHOD(child_sa_t, install_outbound, status_t, METHOD(child_sa_t, install_outbound, status_t,
@@ -1289,17 +1293,19 @@ METHOD(child_sa_t, install_outbound, status_t,
{ {
enumerator_t *enumerator; enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts; traffic_selector_t *my_ts, *other_ts;
status_t status; status_t status = SUCCESS;
status = install_internal(this, this->encr_r, this->integ_r, status = install_internal(this, this->encr_r, this->integ_r,
this->other_spi, this->other_cpi, FALSE, FALSE, this->other_spi, this->other_cpi, FALSE,
this->tfcv3); FALSE, this->tfcv3);
chunk_clear(&this->encr_r); chunk_clear(&this->encr_r);
chunk_clear(&this->integ_r); chunk_clear(&this->integ_r);
this->outbound_state &= ~CHILD_OUTBOUND_REGISTERED;
if (status != SUCCESS) if (status != SUCCESS)
{ {
return status; return status;
} }
this->outbound_state |= CHILD_OUTBOUND_POLICIES;
if (!this->config->has_option(this->config, OPT_NO_POLICIES)) if (!this->config->has_option(this->config, OPT_NO_POLICIES))
{ {
ipsec_sa_cfg_t my_sa, other_sa; ipsec_sa_cfg_t my_sa, other_sa;
@@ -1340,20 +1346,19 @@ METHOD(child_sa_t, remove_outbound, void,
enumerator_t *enumerator; enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts; traffic_selector_t *my_ts, *other_ts;
switch (this->outbound_state) if (!(this->outbound_state & CHILD_OUTBOUND_SA))
{ {
case CHILD_OUTBOUND_INSTALLED: if (this->outbound_state & CHILD_OUTBOUND_REGISTERED)
break; {
case CHILD_OUTBOUND_REGISTERED:
chunk_clear(&this->encr_r); chunk_clear(&this->encr_r);
chunk_clear(&this->integ_r); chunk_clear(&this->integ_r);
this->outbound_state = CHILD_OUTBOUND_NONE; this->outbound_state = CHILD_OUTBOUND_NONE;
/* fall-through */ }
case CHILD_OUTBOUND_NONE: return;
return;
} }
if (!this->config->has_option(this->config, OPT_NO_POLICIES)) if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
(this->outbound_state & CHILD_OUTBOUND_POLICIES))
{ {
ipsec_sa_cfg_t my_sa, other_sa; ipsec_sa_cfg_t my_sa, other_sa;
uint32_t manual_prio; uint32_t manual_prio;
@@ -1598,8 +1603,8 @@ METHOD(child_sa_t, destroy, void,
prepare_sa_cfg(this, &my_sa, &other_sa); prepare_sa_cfg(this, &my_sa, &other_sa);
manual_prio = this->config->get_manual_prio(this->config); manual_prio = this->config->get_manual_prio(this->config);
del_outbound = this->trap || del_outbound = (this->outbound_state & CHILD_OUTBOUND_POLICIES) ||
this->outbound_state == CHILD_OUTBOUND_INSTALLED; this->trap;
/* delete all policies in the kernel */ /* delete all policies in the kernel */
enumerator = create_policy_enumerator(this); enumerator = create_policy_enumerator(this);
@@ -1640,7 +1645,7 @@ METHOD(child_sa_t, destroy, void,
}; };
charon->kernel->del_sa(charon->kernel, &id, &sa); charon->kernel->del_sa(charon->kernel, &id, &sa);
} }
if (this->other_spi && this->outbound_state == CHILD_OUTBOUND_INSTALLED) if (this->other_spi && (this->outbound_state & CHILD_OUTBOUND_SA))
{ {
kernel_ipsec_sa_id_t id = { kernel_ipsec_sa_id_t id = {
.src = this->my_addr, .src = this->my_addr,
+16 -5
View File
@@ -102,17 +102,28 @@ enum child_sa_outbound_state_t {
/** /**
* Outbound SA is not installed * Outbound SA is not installed
*/ */
CHILD_OUTBOUND_NONE, CHILD_OUTBOUND_NONE = 0,
/** /**
* Data for the outbound SA has been registered, but not installed yet * Data for the outbound SA has been registered during a rekeying (not set
* once the SA and policies are both installed)
*/ */
CHILD_OUTBOUND_REGISTERED, CHILD_OUTBOUND_REGISTERED = (1<<0),
/** /**
* The outbound SA is currently installed * The outbound SA has been installed
*/ */
CHILD_OUTBOUND_INSTALLED, CHILD_OUTBOUND_SA = (1<<1),
/**
* The outbound policies have been installed
*/
CHILD_OUTBOUND_POLICIES = (1<<2),
/**
* The outbound SA and policies are both installed
*/
CHILD_OUTBOUND_INSTALLED = (CHILD_OUTBOUND_SA|CHILD_OUTBOUND_POLICIES),
}; };
/** /**
+2 -1
View File
@@ -121,7 +121,8 @@
test_assert_msg(_state == _child->get_state(_child), "%N != %N", \ test_assert_msg(_state == _child->get_state(_child), "%N != %N", \
child_sa_state_names, _state, \ child_sa_state_names, _state, \
child_sa_state_names, _child->get_state(_child)); \ child_sa_state_names, _child->get_state(_child)); \
test_assert_msg(_outbound == _child->get_outbound_state(_child), "%N != %N", \ typeof(outbound) _cur_out = _child->get_outbound_state(_child); \
test_assert_msg(_outbound == _cur_out || _outbound & _cur_out, "%N != %N", \
child_sa_outbound_state_names, _outbound, \ child_sa_outbound_state_names, _outbound, \
child_sa_outbound_state_names, _child->get_outbound_state(_child)); \ child_sa_outbound_state_names, _child->get_outbound_state(_child)); \
}) })