aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2013-07-03 18:28:37 +0200
committerTobias Brunner <tobias@strongswan.org>2013-07-17 18:16:58 +0200
commit68db844f99d7221e5336c93b13765a395980ba81 (patch)
tree8d96f64feaaba87cd14cc3a4363953e197faafe6 /src
parentb79fdab87853962e645cca1ea04650b845868caf (diff)
downloadstrongswan-68db844f99d7221e5336c93b13765a395980ba81.tar.bz2
strongswan-68db844f99d7221e5336c93b13765a395980ba81.tar.xz
ike: Migrate queued CHILD_SA-creating tasks when reestablishing an IKE_SA
Diffstat (limited to 'src')
-rw-r--r--src/libcharon/sa/ike_sa.c40
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c34
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c34
-rw-r--r--src/libcharon/sa/task_manager.h9
4 files changed, 115 insertions, 2 deletions
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 50d969430..aa04d15d4 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2012 Tobias Brunner
+ * Copyright (C) 2006-2013 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -1535,6 +1535,30 @@ METHOD(ike_sa_t, reauth, status_t,
return this->task_manager->initiate(this->task_manager);
}
+/**
+ * Check if tasks to create CHILD_SAs are queued in the given queue
+ */
+static bool is_child_queued(private_ike_sa_t *this, task_queue_t queue)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+ bool found = FALSE;
+
+ enumerator = this->task_manager->create_task_enumerator(this->task_manager,
+ queue);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ if (task->get_type(task) == TASK_CHILD_CREATE ||
+ task->get_type(task) == TASK_QUICK_MODE)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
METHOD(ike_sa_t, reestablish, status_t,
private_ike_sa_t *this)
{
@@ -1592,6 +1616,9 @@ METHOD(ike_sa_t, reestablish, status_t,
}
}
enumerator->destroy(enumerator);
+ /* check if we have tasks that recreate children */
+ restart = is_child_queued(this, TASK_QUEUE_ACTIVE) ||
+ is_child_queued(this, TASK_QUEUE_QUEUED);
#ifdef ME
/* mediation connections have no children, keep them up anyway */
if (this->peer_cfg->is_mediation(this->peer_cfg))
@@ -1645,6 +1672,7 @@ METHOD(ike_sa_t, reestablish, status_t,
else
#endif /* ME */
{
+ /* handle existing CHILD_SAs */
enumerator = array_create_enumerator(this->child_sas);
while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
@@ -1696,6 +1724,16 @@ METHOD(ike_sa_t, reestablish, status_t,
}
}
enumerator->destroy(enumerator);
+ /* adopt any active or queued CHILD-creating tasks */
+ if (status != DESTROY_ME)
+ {
+ task_manager_t *other_tasks = ((private_ike_sa_t*)new)->task_manager;
+ other_tasks->adopt_child_tasks(other_tasks, this->task_manager);
+ if (new->get_state(new) == IKE_CREATED)
+ {
+ status = new->initiate(new, NULL, 0, NULL, NULL);
+ }
+ }
}
if (status == DESTROY_ME)
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index bfa6fc81e..857cb027e 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -1900,6 +1900,39 @@ METHOD(task_manager_t, adopt_tasks, void,
}
}
+/**
+ * Migrates child-creating tasks from src to dst
+ */
+static void migrate_child_tasks(private_task_manager_t *this,
+ linked_list_t *src, linked_list_t *dst)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+
+ enumerator = src->create_enumerator(src);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ if (task->get_type(task) == TASK_QUICK_MODE)
+ {
+ src->remove_at(src, enumerator);
+ task->migrate(task, this->ike_sa);
+ dst->insert_last(dst, task);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(task_manager_t, adopt_child_tasks, void,
+ private_task_manager_t *this, task_manager_t *other_public)
+{
+ 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);
+ /* do the same for queued tasks */
+ migrate_child_tasks(this, other->queued_tasks, this->queued_tasks);
+}
+
METHOD(task_manager_t, busy, bool,
private_task_manager_t *this)
{
@@ -2014,6 +2047,7 @@ task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
.incr_mid = _incr_mid,
.reset = _reset,
.adopt_tasks = _adopt_tasks,
+ .adopt_child_tasks = _adopt_child_tasks,
.busy = _busy,
.create_task_enumerator = _create_task_enumerator,
.flush_queue = _flush_queue,
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index 79a9aa5a0..a2a968b46 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -1426,6 +1426,39 @@ METHOD(task_manager_t, adopt_tasks, void,
}
}
+/**
+ * Migrates child-creating tasks from src to dst
+ */
+static void migrate_child_tasks(private_task_manager_t *this,
+ array_t *src, array_t *dst)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+
+ enumerator = array_create_enumerator(src);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ if (task->get_type(task) == TASK_CHILD_CREATE)
+ {
+ array_remove_at(src, enumerator);
+ task->migrate(task, this->ike_sa);
+ array_insert(dst, ARRAY_TAIL, task);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(task_manager_t, adopt_child_tasks, void,
+ private_task_manager_t *this, task_manager_t *other_public)
+{
+ 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);
+ /* do the same for queued tasks */
+ migrate_child_tasks(this, other->queued_tasks, this->queued_tasks);
+}
+
METHOD(task_manager_t, busy, bool,
private_task_manager_t *this)
{
@@ -1527,6 +1560,7 @@ task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa)
.incr_mid = _incr_mid,
.reset = _reset,
.adopt_tasks = _adopt_tasks,
+ .adopt_child_tasks = _adopt_child_tasks,
.busy = _busy,
.create_task_enumerator = _create_task_enumerator,
.flush_queue = _flush_queue,
diff --git a/src/libcharon/sa/task_manager.h b/src/libcharon/sa/task_manager.h
index c649cf78e..a1ebb4117 100644
--- a/src/libcharon/sa/task_manager.h
+++ b/src/libcharon/sa/task_manager.h
@@ -202,7 +202,7 @@ struct task_manager_t {
status_t (*retransmit) (task_manager_t *this, u_int32_t message_id);
/**
- * Migrate all tasks from other to this.
+ * Migrate all queued tasks from other to this.
*
* To rekey or reestablish an IKE_SA completely, all queued or active
* tasks should get migrated to the new IKE_SA.
@@ -212,6 +212,13 @@ struct task_manager_t {
void (*adopt_tasks) (task_manager_t *this, task_manager_t *other);
/**
+ * Migrate all active or queued CHILD_SA-creating tasks from other to this.
+ *
+ * @param other manager which gives away its tasks
+ */
+ void (*adopt_child_tasks) (task_manager_t *this, task_manager_t *other);
+
+ /**
* Increment a message ID counter, in- or outbound.
*
* If a message is processed outside of the manager, this call increments