ike: Migrate queued CHILD_SA-creating tasks when reestablishing an IKE_SA
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2006-2012 Tobias Brunner
|
* Copyright (C) 2006-2013 Tobias Brunner
|
||||||
* Copyright (C) 2006 Daniel Roethlisberger
|
* Copyright (C) 2006 Daniel Roethlisberger
|
||||||
* Copyright (C) 2005-2009 Martin Willi
|
* Copyright (C) 2005-2009 Martin Willi
|
||||||
* Copyright (C) 2005 Jan Hutter
|
* Copyright (C) 2005 Jan Hutter
|
||||||
@@ -1535,6 +1535,30 @@ METHOD(ike_sa_t, reauth, status_t,
|
|||||||
return this->task_manager->initiate(this->task_manager);
|
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,
|
METHOD(ike_sa_t, reestablish, status_t,
|
||||||
private_ike_sa_t *this)
|
private_ike_sa_t *this)
|
||||||
{
|
{
|
||||||
@@ -1592,6 +1616,9 @@ METHOD(ike_sa_t, reestablish, status_t,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
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
|
#ifdef ME
|
||||||
/* mediation connections have no children, keep them up anyway */
|
/* mediation connections have no children, keep them up anyway */
|
||||||
if (this->peer_cfg->is_mediation(this->peer_cfg))
|
if (this->peer_cfg->is_mediation(this->peer_cfg))
|
||||||
@@ -1645,6 +1672,7 @@ METHOD(ike_sa_t, reestablish, status_t,
|
|||||||
else
|
else
|
||||||
#endif /* ME */
|
#endif /* ME */
|
||||||
{
|
{
|
||||||
|
/* handle existing CHILD_SAs */
|
||||||
enumerator = array_create_enumerator(this->child_sas);
|
enumerator = array_create_enumerator(this->child_sas);
|
||||||
while (enumerator->enumerate(enumerator, (void**)&child_sa))
|
while (enumerator->enumerate(enumerator, (void**)&child_sa))
|
||||||
{
|
{
|
||||||
@@ -1696,6 +1724,16 @@ METHOD(ike_sa_t, reestablish, status_t,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
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)
|
if (status == DESTROY_ME)
|
||||||
|
|||||||
@@ -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,
|
METHOD(task_manager_t, busy, bool,
|
||||||
private_task_manager_t *this)
|
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,
|
.incr_mid = _incr_mid,
|
||||||
.reset = _reset,
|
.reset = _reset,
|
||||||
.adopt_tasks = _adopt_tasks,
|
.adopt_tasks = _adopt_tasks,
|
||||||
|
.adopt_child_tasks = _adopt_child_tasks,
|
||||||
.busy = _busy,
|
.busy = _busy,
|
||||||
.create_task_enumerator = _create_task_enumerator,
|
.create_task_enumerator = _create_task_enumerator,
|
||||||
.flush_queue = _flush_queue,
|
.flush_queue = _flush_queue,
|
||||||
|
|||||||
@@ -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,
|
METHOD(task_manager_t, busy, bool,
|
||||||
private_task_manager_t *this)
|
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,
|
.incr_mid = _incr_mid,
|
||||||
.reset = _reset,
|
.reset = _reset,
|
||||||
.adopt_tasks = _adopt_tasks,
|
.adopt_tasks = _adopt_tasks,
|
||||||
|
.adopt_child_tasks = _adopt_child_tasks,
|
||||||
.busy = _busy,
|
.busy = _busy,
|
||||||
.create_task_enumerator = _create_task_enumerator,
|
.create_task_enumerator = _create_task_enumerator,
|
||||||
.flush_queue = _flush_queue,
|
.flush_queue = _flush_queue,
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ struct task_manager_t {
|
|||||||
status_t (*retransmit) (task_manager_t *this, u_int32_t message_id);
|
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
|
* To rekey or reestablish an IKE_SA completely, all queued or active
|
||||||
* tasks should get migrated to the new IKE_SA.
|
* tasks should get migrated to the new IKE_SA.
|
||||||
@@ -211,6 +211,13 @@ struct task_manager_t {
|
|||||||
*/
|
*/
|
||||||
void (*adopt_tasks) (task_manager_t *this, task_manager_t *other);
|
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.
|
* Increment a message ID counter, in- or outbound.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user