aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c3
-rw-r--r--src/libcharon/sa/child_sa.c31
-rw-r--r--src/libcharon/sa/child_sa.h5
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c2
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c30
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.h8
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.c26
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.h8
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_rekey.c6
-rw-r--r--src/libcharon/sa/trap_manager.c2
-rw-r--r--src/libhydra/kernel/kernel_interface.c70
-rw-r--r--src/libhydra/kernel/kernel_interface.h5
-rw-r--r--src/libstrongswan/ipsec/ipsec_types.h4
13 files changed, 126 insertions, 74 deletions
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
index e20e872c1..6e02733f9 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -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);
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 7625be1d6..fdeb605ee 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -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
diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
index f0ec01658..83b8c096c 100644
--- a/src/libcharon/sa/child_sa.h
+++ b/src/libcharon/sa/child_sa.h
@@ -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_ @}*/
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index 0f8e8bc6d..3184db4ee 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -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);
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index 1133aab65..5fe04c036 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -156,6 +156,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
*/
u_int32_t 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,
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.h b/src/libcharon/sa/ikev1/tasks/quick_mode.h
index 0b80cb836..ee9b64d13 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.h
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.h
@@ -45,6 +45,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.
*
* @param spi spi of SA to rekey
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index e7a914875..5ec05376c 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -160,6 +160,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
*/
child_sa_t *child_sa;
@@ -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,
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.h b/src/libcharon/sa/ikev2/tasks/child_create.h
index d29ba3d98..46d9403ee 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.h
+++ b/src/libcharon/sa/ikev2/tasks/child_create.h
@@ -52,6 +52,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.
*
* @return lower nonce
diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c
index db872827d..213155a29 100644
--- a/src/libcharon/sa/ikev2/tasks/child_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c
@@ -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);
diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c
index 7e55d6b0f..534d4d5ff 100644
--- a/src/libcharon/sa/trap_manager.c
+++ b/src/libcharon/sa/trap_manager.c
@@ -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);
diff --git a/src/libhydra/kernel/kernel_interface.c b/src/libhydra/kernel/kernel_interface.c
index 9452b8f84..28821fc15 100644
--- a/src/libhydra/kernel/kernel_interface.c
+++ b/src/libhydra/kernel/kernel_interface.c
@@ -260,7 +260,9 @@ static u_int hash_ts_array(array_t *array, u_int hash)
*/
static u_int hash_reqid_by_ts(reqid_entry_t *entry)
{
- return hash_ts_array(entry->local, hash_ts_array(entry->remote, 0));
+ return hash_ts_array(entry->local, hash_ts_array(entry->remote,
+ chunk_hash_inc(chunk_from_thing(entry->mark_in),
+ chunk_hash(chunk_from_thing(entry->mark_out)))));
}
/**
@@ -290,43 +292,16 @@ static bool ts_array_equals(array_t *a, array_t *b)
}
/**
- * Check if mark b matches to a, optionally with reqid match
- */
-static bool mark_matches(mark_t a, mark_t b, u_int32_t reqid)
-{
- if (a.value == b.value)
- {
- return TRUE;
- }
- if (a.value == MARK_REQID && b.value == reqid)
- {
- return TRUE;
- }
- return FALSE;
-}
-
-/**
* Hashtable equals function for reqid entries using traffic selectors as key
*/
static bool equals_reqid_by_ts(reqid_entry_t *a, reqid_entry_t *b)
{
- if (ts_array_equals(a->local, b->local) &&
- ts_array_equals(a->remote, b->remote) &&
- a->mark_in.mask == b->mark_in.mask &&
- a->mark_out.mask == b->mark_out.mask)
- {
- if (mark_matches(a->mark_in, b->mark_in, a->reqid) &&
- mark_matches(a->mark_out, b->mark_out, a->reqid))
- {
- return TRUE;
- }
- if (mark_matches(b->mark_in, a->mark_in, b->reqid) &&
- mark_matches(b->mark_out, a->mark_out, b->reqid))
- {
- return TRUE;
- }
- }
- return FALSE;
+ return ts_array_equals(a->local, b->local) &&
+ ts_array_equals(a->remote, b->remote) &&
+ a->mark_in.value == b->mark_in.value &&
+ a->mark_in.mask == b->mark_in.mask &&
+ a->mark_out.value == b->mark_out.value &&
+ a->mark_out.mask == b->mark_out.mask;
}
/**
@@ -353,7 +328,7 @@ static array_t *array_from_ts_list(linked_list_t *list)
METHOD(kernel_interface_t, alloc_reqid, status_t,
private_kernel_interface_t *this,
linked_list_t *local_ts, linked_list_t *remote_ts,
- mark_t *mark_in, mark_t *mark_out, u_int32_t *reqid)
+ mark_t mark_in, mark_t mark_out, u_int32_t *reqid)
{
static u_int32_t counter = 0;
reqid_entry_t *entry = NULL, *tmpl;
@@ -362,8 +337,8 @@ METHOD(kernel_interface_t, alloc_reqid, status_t,
INIT(tmpl,
.local = array_from_ts_list(local_ts),
.remote = array_from_ts_list(remote_ts),
- .mark_in = *mark_in,
- .mark_out = *mark_out,
+ .mark_in = mark_in,
+ .mark_out = mark_out,
.reqid = *reqid,
);
@@ -371,14 +346,6 @@ METHOD(kernel_interface_t, alloc_reqid, status_t,
if (tmpl->reqid)
{
/* search by reqid if given */
- if (tmpl->mark_in.value == MARK_REQID)
- {
- tmpl->mark_in.value = tmpl->reqid;
- }
- if (tmpl->mark_out.value == MARK_REQID)
- {
- tmpl->mark_out.value = tmpl->reqid;
- }
entry = this->reqids->get(this->reqids, tmpl);
}
if (entry)
@@ -390,8 +357,7 @@ METHOD(kernel_interface_t, alloc_reqid, status_t,
}
else
{
- /* search by traffic selectors. We do the search with MARK_REQID
- * wildcards (if any), and update the marks if we find any match */
+ /* search by traffic selectors */
entry = this->reqids_by_ts->get(this->reqids_by_ts, tmpl);
if (entry)
{
@@ -402,21 +368,11 @@ METHOD(kernel_interface_t, alloc_reqid, status_t,
/* none found, create a new entry, allocating a reqid */
entry = tmpl;
entry->reqid = ++counter;
- if (entry->mark_in.value == MARK_REQID)
- {
- entry->mark_in.value = entry->reqid;
- }
- if (entry->mark_out.value == MARK_REQID)
- {
- entry->mark_out.value = entry->reqid;
- }
this->reqids_by_ts->put(this->reqids_by_ts, entry, entry);
this->reqids->put(this->reqids, entry, entry);
}
*reqid = entry->reqid;
}
- *mark_in = entry->mark_in;
- *mark_out = entry->mark_out;
entry->refs++;
this->mutex->unlock(this->mutex);
diff --git a/src/libhydra/kernel/kernel_interface.h b/src/libhydra/kernel/kernel_interface.h
index f25c10830..9a86e78d6 100644
--- a/src/libhydra/kernel/kernel_interface.h
+++ b/src/libhydra/kernel/kernel_interface.h
@@ -131,9 +131,6 @@ struct kernel_interface_t {
* the reqid is confirmed and registered for use. If it points to zero,
* a reqid is allocated for the given selectors, and returned to reqid.
*
- * The passed mark values get updated to the reqid value if they are set
- * to the magic value MARK_REQID.
- *
* @param local_ts traffic selectors of local side for SA
* @param remote_ts traffic selectors of remote side for SA
* @param mark_in inbound mark on SA
@@ -143,7 +140,7 @@ struct kernel_interface_t {
*/
status_t (*alloc_reqid)(kernel_interface_t *this,
linked_list_t *local_ts, linked_list_t *remote_ts,
- mark_t *mark_in, mark_t *mark_out,
+ mark_t mark_in, mark_t mark_out,
u_int32_t *reqid);
/**
diff --git a/src/libstrongswan/ipsec/ipsec_types.h b/src/libstrongswan/ipsec/ipsec_types.h
index c1465e097..fa122af30 100644
--- a/src/libstrongswan/ipsec/ipsec_types.h
+++ b/src/libstrongswan/ipsec/ipsec_types.h
@@ -169,9 +169,9 @@ struct mark_t {
};
/**
- * Special mark value that uses the reqid of the CHILD_SA as mark
+ * Special mark value that uses a unique mark for each CHILD_SA
*/
-#define MARK_REQID (0xFFFFFFFF)
+#define MARK_UNIQUE (0xFFFFFFFF)
/**
* Try to parse a mark_t from the given string of the form mark[/mask].