diff options
author | Tobias Brunner <tobias@strongswan.org> | 2013-07-03 18:28:37 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2013-07-17 18:16:58 +0200 |
commit | 68db844f99d7221e5336c93b13765a395980ba81 (patch) | |
tree | 8d96f64feaaba87cd14cc3a4363953e197faafe6 /src | |
parent | b79fdab87853962e645cca1ea04650b845868caf (diff) | |
download | strongswan-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.c | 40 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/task_manager_v1.c | 34 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/task_manager_v2.c | 34 | ||||
-rw-r--r-- | src/libcharon/sa/task_manager.h | 9 |
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 |