child-sa: Replace reqid based marks by "unique" marks

As we now use the same reqid for multiple CHILD_SAs with the same selectors,
having marks based on the reqid makes not that much sense anymore. Instead we
use unique marks that use a custom identifier. This identifier is reused during
rekeying, keeping the marks constant for any rule relying on it (for example
installed by updown).

This also simplifies handling of reqid allocation, as we do not have to query
the marks that is not yet assigned for an unknown reqid.
This commit is contained in:
Martin Willi
2015-02-20 13:34:49 +01:00
parent 4ec397b894
commit 85b238887d
13 changed files with 126 additions and 74 deletions
+2 -1
View File
@@ -718,7 +718,8 @@ static void process_child_add(private_ha_dispatcher_t *this,
child_sa = child_sa_create(ike_sa->get_my_host(ike_sa),
ike_sa->get_other_host(ike_sa), config, 0,
ike_sa->has_condition(ike_sa, COND_NAT_ANY));
ike_sa->has_condition(ike_sa, COND_NAT_ANY),
0, 0);
child_sa->set_mode(child_sa, mode);
child_sa->set_protocol(child_sa, PROTO_ESP);
child_sa->set_ipcomp(child_sa, ipcomp);
+27 -4
View File
@@ -695,7 +695,7 @@ METHOD(child_sa_t, install, status_t,
if (!this->reqid_allocated)
{
status = hydra->kernel_interface->alloc_reqid(hydra->kernel_interface,
my_ts, other_ts, &this->mark_in, &this->mark_out,
my_ts, other_ts, this->mark_in, this->mark_out,
&this->reqid);
if (status != SUCCESS)
{
@@ -825,7 +825,7 @@ METHOD(child_sa_t, add_policies, status_t,
/* trap policy, get or confirm reqid */
status = hydra->kernel_interface->alloc_reqid(
hydra->kernel_interface, my_ts_list, other_ts_list,
&this->mark_in, &this->mark_out, &this->reqid);
this->mark_in, this->mark_out, &this->reqid);
if (status != SUCCESS)
{
return status;
@@ -1198,10 +1198,11 @@ 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, u_int32_t rekey, bool encap,
u_int mark_in, u_int mark_out)
{
private_child_sa_t *this;
static refcount_t unique_id = 0;
static refcount_t unique_id = 0, unique_mark = 0, mark;
INIT(this,
.public = {
@@ -1258,6 +1259,28 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->config = config;
config->get_ref(config);
if (mark_in)
{
this->mark_in.value = mark_in;
}
if (mark_out)
{
this->mark_out.value = mark_out;
}
if (this->mark_in.value == MARK_UNIQUE ||
this->mark_out.value == MARK_UNIQUE)
{
mark = ref_get(&unique_mark);
if (this->mark_in.value == MARK_UNIQUE)
{
this->mark_in.value = mark;
}
if (this->mark_out.value == MARK_UNIQUE)
{
this->mark_out.value = mark;
}
}
if (!this->reqid)
{
/* reuse old reqid if we are rekeying an existing CHILD_SA. While the
+4 -1
View File
@@ -394,9 +394,12 @@ struct child_sa_t {
* @param config config to use for this CHILD_SA
* @param reqid reqid of old CHILD_SA when rekeying, 0 otherwise
* @param encap TRUE to enable UDP encapsulation (NAT traversal)
* @param mark_in explicit inbound mark value to use, 0 for config
* @param mark_out explicit outbound mark value to use, 0 for config
* @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);
u_int32_t reqid, bool encap,
u_int mark_in, u_int mark_out);
#endif /** CHILD_SA_H_ @}*/
+2
View File
@@ -1647,6 +1647,8 @@ METHOD(task_manager_t, queue_child_rekey, void,
task = quick_mode_create(this->ike_sa, cfg->get_ref(cfg),
get_first_ts(child_sa, TRUE), get_first_ts(child_sa, FALSE));
task->use_reqid(task, child_sa->get_reqid(child_sa));
task->use_marks(task, child_sa->get_mark(child_sa, TRUE).value,
child_sa->get_mark(child_sa, FALSE).value);
task->rekey(task, child_sa->get_spi(child_sa, TRUE));
queue_task(this, &task->task);
+28 -2
View File
@@ -155,6 +155,16 @@ struct private_quick_mode_t {
*/
u_int32_t reqid;
/**
* Explicit inbound mark value to use, if any
*/
u_int mark_in;
/**
* Explicit inbound mark value to use, if any
*/
u_int mark_out;
/**
* SPI of SA we rekey
*/
@@ -788,7 +798,8 @@ METHOD(task_t, build_i, status_t,
this->child_sa = child_sa_create(
this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa),
this->config, this->reqid, this->udp);
this->config, this->reqid, this->udp,
this->mark_in, this->mark_out);
if (this->udp && this->mode == MODE_TRANSPORT)
{
@@ -972,6 +983,10 @@ static void check_for_rekeyed_child(private_quick_mode_t *this)
{
this->reqid = child_sa->get_reqid(child_sa);
this->rekey = child_sa->get_spi(child_sa, TRUE);
this->mark_in = child_sa->get_mark(child_sa,
TRUE).value;
this->mark_out = child_sa->get_mark(child_sa,
FALSE).value;
child_sa->set_state(child_sa, CHILD_REKEYING);
DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}",
child_sa->get_name(child_sa), this->reqid);
@@ -1097,7 +1112,8 @@ METHOD(task_t, process_r, status_t,
this->child_sa = child_sa_create(
this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa),
this->config, this->reqid, this->udp);
this->config, this->reqid, this->udp,
this->mark_in, this->mark_out);
tsi = linked_list_create_with_items(this->tsi, NULL);
tsr = linked_list_create_with_items(this->tsr, NULL);
@@ -1307,6 +1323,13 @@ METHOD(quick_mode_t, use_reqid, void,
this->reqid = reqid;
}
METHOD(quick_mode_t, use_marks, void,
private_quick_mode_t *this, u_int in, u_int out)
{
this->mark_in = in;
this->mark_out = out;
}
METHOD(quick_mode_t, rekey, void,
private_quick_mode_t *this, u_int32_t spi)
{
@@ -1334,6 +1357,8 @@ METHOD(task_t, migrate, void,
this->dh = NULL;
this->spi_i = 0;
this->spi_r = 0;
this->mark_in = 0;
this->mark_out = 0;
if (!this->initiator)
{
@@ -1372,6 +1397,7 @@ quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
.destroy = _destroy,
},
.use_reqid = _use_reqid,
.use_marks = _use_marks,
.rekey = _rekey,
},
.ike_sa = ike_sa,
@@ -44,6 +44,14 @@ struct quick_mode_t {
*/
void (*use_reqid)(quick_mode_t *this, u_int32_t reqid);
/**
* Use specific mark values, overriding configuration.
*
* @param in inbound mark value
* @param out outbound mark value
*/
void (*use_marks)(quick_mode_t *this, u_int in, u_int out);
/**
* Set the SPI of the old SA, if rekeying.
*
+24 -2
View File
@@ -159,6 +159,16 @@ struct private_child_create_t {
*/
u_int32_t reqid;
/**
* Explicit inbound mark value
*/
u_int mark_in;
/**
* Explicit outbound mark value
*/
u_int mark_out;
/**
* CHILD_SA which gets established
*/
@@ -996,7 +1006,8 @@ METHOD(task_t, build_i, status_t,
this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY),
this->mark_in, this->mark_out);
if (!allocate_spi(this))
{
@@ -1241,7 +1252,8 @@ METHOD(task_t, build_r, status_t,
this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY),
this->mark_in, this->mark_out);
if (this->ipcomp_received != IPCOMP_NONE)
{
@@ -1478,6 +1490,13 @@ METHOD(child_create_t, use_reqid, void,
this->reqid = reqid;
}
METHOD(child_create_t, use_marks, void,
private_child_create_t *this, u_int in, u_int out)
{
this->mark_in = in;
this->mark_out = out;
}
METHOD(child_create_t, get_child, child_sa_t*,
private_child_create_t *this)
{
@@ -1545,6 +1564,8 @@ METHOD(task_t, migrate, void,
this->ipcomp_received = IPCOMP_NONE;
this->other_cpi = 0;
this->reqid = 0;
this->mark_in = 0;
this->mark_out = 0;
this->established = FALSE;
}
@@ -1593,6 +1614,7 @@ child_create_t *child_create_create(ike_sa_t *ike_sa,
.set_config = _set_config,
.get_lower_nonce = _get_lower_nonce,
.use_reqid = _use_reqid,
.use_marks = _use_marks,
.task = {
.get_type = _get_type,
.migrate = _migrate,
@@ -51,6 +51,14 @@ struct child_create_t {
*/
void (*use_reqid) (child_create_t *this, u_int32_t reqid);
/**
* Use specific mark values to override configuration.
*
* @param in inbound mark value
* @param out outbound mark value
*/
void (*use_marks)(child_create_t *this, u_int in, u_int out);
/**
* Get the lower of the two nonces, used for rekey collisions.
*
@@ -184,6 +184,9 @@ METHOD(task_t, build_i, status_t,
}
reqid = this->child_sa->get_reqid(this->child_sa);
this->child_create->use_reqid(this->child_create, reqid);
this->child_create->use_marks(this->child_create,
this->child_sa->get_mark(this->child_sa, TRUE).value,
this->child_sa->get_mark(this->child_sa, FALSE).value);
if (this->child_create->task.build(&this->child_create->task,
message) != NEED_MORE)
@@ -224,6 +227,9 @@ METHOD(task_t, build_r, status_t,
/* let the CHILD_CREATE task build the response */
reqid = this->child_sa->get_reqid(this->child_sa);
this->child_create->use_reqid(this->child_create, reqid);
this->child_create->use_marks(this->child_create,
this->child_sa->get_mark(this->child_sa, TRUE).value,
this->child_sa->get_mark(this->child_sa, FALSE).value);
config = this->child_sa->get_config(this->child_sa);
this->child_create->set_config(this->child_create, config->get_ref(config));
this->child_create->task.build(&this->child_create->task, message);
+1 -1
View File
@@ -171,7 +171,7 @@ METHOD(trap_manager_t, install, u_int32_t,
this->lock->unlock(this->lock);
/* create and route CHILD_SA */
child_sa = child_sa_create(me, other, child, reqid, FALSE);
child_sa = child_sa_create(me, other, child, reqid, FALSE, 0, 0);
list = linked_list_create_with_items(me, NULL);
my_ts = child->get_traffic_selectors(child, TRUE, NULL, list);