summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/ikev2/task_manager_v2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/ikev2/task_manager_v2.c')
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c210
1 files changed, 132 insertions, 78 deletions
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index 5298abf79..a6af744fc 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -18,6 +18,7 @@
#include <math.h>
+#include <collections/array.h>
#include <daemon.h>
#include <sa/ikev2/tasks/ike_init.h>
#include <sa/ikev2/tasks/ike_natd.h>
@@ -122,19 +123,19 @@ struct private_task_manager_t {
} initiating;
/**
- * List of queued tasks not yet in action
+ * Array of queued tasks not yet in action
*/
- linked_list_t *queued_tasks;
+ array_t *queued_tasks;
/**
- * List of active tasks, initiated by ourselve
+ * Array of active tasks, initiated by ourselve
*/
- linked_list_t *active_tasks;
+ array_t *active_tasks;
/**
- * List of tasks initiated by peer
+ * Array of tasks initiated by peer
*/
- linked_list_t *passive_tasks;
+ array_t *passive_tasks;
/**
* the task manager has been reset
@@ -160,24 +161,24 @@ struct private_task_manager_t {
METHOD(task_manager_t, flush_queue, void,
private_task_manager_t *this, task_queue_t queue)
{
- linked_list_t *list;
+ array_t *array;
task_t *task;
switch (queue)
{
case TASK_QUEUE_ACTIVE:
- list = this->active_tasks;
+ array = this->active_tasks;
break;
case TASK_QUEUE_PASSIVE:
- list = this->passive_tasks;
+ array = this->passive_tasks;
break;
case TASK_QUEUE_QUEUED:
- list = this->queued_tasks;
+ array = this->queued_tasks;
break;
default:
return;
}
- while (list->remove_last(list, (void**)&task) == SUCCESS)
+ while (array_remove(array, ARRAY_TAIL, &task))
{
task->destroy(task);
}
@@ -202,14 +203,14 @@ static bool activate_task(private_task_manager_t *this, task_type_t type)
task_t *task;
bool found = FALSE;
- enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ enumerator = array_create_enumerator(this->queued_tasks);
while (enumerator->enumerate(enumerator, (void**)&task))
{
if (task->get_type(task) == type)
{
DBG2(DBG_IKE, " activating %N task", task_type_names, type);
- this->queued_tasks->remove_at(this->queued_tasks, enumerator);
- this->active_tasks->insert_last(this->active_tasks, task);
+ array_remove_at(this->queued_tasks, enumerator);
+ array_insert(this->active_tasks, ARRAY_TAIL, task);
found = TRUE;
break;
}
@@ -231,7 +232,7 @@ METHOD(task_manager_t, retransmit, status_t,
ike_mobike_t *mobike = NULL;
/* check if we are retransmitting a MOBIKE routability check */
- enumerator = this->active_tasks->create_enumerator(this->active_tasks);
+ enumerator = array_create_enumerator(this->active_tasks);
while (enumerator->enumerate(enumerator, (void*)&task))
{
if (task->get_type(task) == TASK_IKE_MOBIKE)
@@ -319,7 +320,7 @@ METHOD(task_manager_t, initiate, status_t,
return SUCCESS;
}
- if (this->active_tasks->get_count(this->active_tasks) == 0)
+ if (array_count(this->active_tasks) == 0)
{
DBG2(DBG_IKE, "activating new tasks");
switch (this->ike_sa->get_state(this->ike_sa))
@@ -414,8 +415,8 @@ METHOD(task_manager_t, initiate, status_t,
else
{
DBG2(DBG_IKE, "reinitiating already active tasks");
- enumerator = this->active_tasks->create_enumerator(this->active_tasks);
- while (enumerator->enumerate(enumerator, (void**)&task))
+ enumerator = array_create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, &task))
{
DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
switch (task->get_type(task))
@@ -460,14 +461,14 @@ METHOD(task_manager_t, initiate, status_t,
this->initiating.type = exchange;
this->initiating.retransmitted = 0;
- enumerator = this->active_tasks->create_enumerator(this->active_tasks);
- while (enumerator->enumerate(enumerator, (void*)&task))
+ enumerator = array_create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, &task))
{
switch (task->build(task, message))
{
case SUCCESS:
/* task completed, remove it */
- this->active_tasks->remove_at(this->active_tasks, enumerator);
+ array_remove_at(this->active_tasks, enumerator);
task->destroy(task);
break;
case NEED_MORE:
@@ -507,6 +508,9 @@ METHOD(task_manager_t, initiate, status_t,
}
message->destroy(message);
+ array_compress(this->active_tasks);
+ array_compress(this->queued_tasks);
+
return retransmit(this, this->initiating.mid);
}
@@ -530,14 +534,14 @@ static status_t process_response(private_task_manager_t *this,
/* catch if we get resetted while processing */
this->reset = FALSE;
- enumerator = this->active_tasks->create_enumerator(this->active_tasks);
- while (enumerator->enumerate(enumerator, (void*)&task))
+ enumerator = array_create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, &task))
{
switch (task->process(task, message))
{
case SUCCESS:
/* task completed, remove it */
- this->active_tasks->remove_at(this->active_tasks, enumerator);
+ array_remove_at(this->active_tasks, enumerator);
task->destroy(task);
break;
case NEED_MORE:
@@ -549,7 +553,7 @@ static status_t process_response(private_task_manager_t *this,
/* FALL */
case DESTROY_ME:
/* critical failure, destroy IKE_SA */
- this->active_tasks->remove_at(this->active_tasks, enumerator);
+ array_remove_at(this->active_tasks, enumerator);
enumerator->destroy(enumerator);
task->destroy(task);
return DESTROY_ME;
@@ -568,6 +572,8 @@ static status_t process_response(private_task_manager_t *this,
this->initiating.packet->destroy(this->initiating.packet);
this->initiating.packet = NULL;
+ array_compress(this->active_tasks);
+
return initiate(this);
}
@@ -588,8 +594,8 @@ static bool handle_collisions(private_task_manager_t *this, task_t *task)
type == TASK_IKE_REAUTH)
{
/* find an exchange collision, and notify these tasks */
- enumerator = this->active_tasks->create_enumerator(this->active_tasks);
- while (enumerator->enumerate(enumerator, (void**)&active))
+ enumerator = array_create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, &active))
{
switch (active->get_type(active))
{
@@ -646,14 +652,14 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
message->set_message_id(message, this->responding.mid);
message->set_request(message, FALSE);
- enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
+ enumerator = array_create_enumerator(this->passive_tasks);
while (enumerator->enumerate(enumerator, (void*)&task))
{
switch (task->build(task, message))
{
case SUCCESS:
/* task completed, remove it */
- this->passive_tasks->remove_at(this->passive_tasks, enumerator);
+ array_remove_at(this->passive_tasks, enumerator);
if (!handle_collisions(this, task))
{
task->destroy(task);
@@ -663,8 +669,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
/* processed, but task needs another exchange */
if (handle_collisions(this, task))
{
- this->passive_tasks->remove_at(this->passive_tasks,
- enumerator);
+ array_remove_at(this->passive_tasks, enumerator);
}
break;
case FAILED:
@@ -721,6 +726,9 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
}
return DESTROY_ME;
}
+
+ array_compress(this->passive_tasks);
+
return SUCCESS;
}
@@ -736,37 +744,37 @@ static status_t process_request(private_task_manager_t *this,
notify_payload_t *notify;
delete_payload_t *delete;
- if (this->passive_tasks->get_count(this->passive_tasks) == 0)
+ if (array_count(this->passive_tasks) == 0)
{ /* create tasks depending on request type, if not already some queued */
switch (message->get_exchange_type(message))
{
case IKE_SA_INIT:
{
task = (task_t*)ike_vendor_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL);
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
task = (task_t*)ike_natd_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
task = (task_t*)ike_cert_pre_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
#ifdef ME
task = (task_t*)ike_me_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
#endif /* ME */
task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
task = (task_t*)ike_cert_post_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
task = (task_t*)ike_config_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
task = (task_t*)child_create_create(this->ike_sa, NULL, FALSE,
NULL, NULL);
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
task = (task_t*)ike_auth_lifetime_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
task = (task_t*)ike_mobike_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
break;
}
case CREATE_CHILD_SA:
@@ -817,7 +825,7 @@ static status_t process_request(private_task_manager_t *this,
{
task = (task_t*)ike_rekey_create(this->ike_sa, FALSE);
}
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
break;
}
case INFORMATIONAL:
@@ -849,6 +857,12 @@ static status_t process_request(private_task_manager_t *this,
task = (task_t*)ike_auth_lifetime_create(
this->ike_sa, FALSE);
break;
+ case AUTHENTICATION_FAILED:
+ /* initiator failed to authenticate us.
+ * We use ike_delete to handle this, which
+ * invokes all the required hooks. */
+ task = (task_t*)ike_delete_create(
+ this->ike_sa, FALSE);
default:
break;
}
@@ -883,14 +897,14 @@ static status_t process_request(private_task_manager_t *this,
{
task = (task_t*)ike_dpd_create(FALSE);
}
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
break;
}
#ifdef ME
case ME_CONNECT:
{
task = (task_t*)ike_me_create(this->ike_sa, FALSE);
- this->passive_tasks->insert_last(this->passive_tasks, task);
+ array_insert(this->passive_tasks, ARRAY_TAIL, task);
}
#endif /* ME */
default:
@@ -899,14 +913,14 @@ static status_t process_request(private_task_manager_t *this,
}
/* let the tasks process the message */
- enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
+ enumerator = array_create_enumerator(this->passive_tasks);
while (enumerator->enumerate(enumerator, (void*)&task))
{
switch (task->process(task, message))
{
case SUCCESS:
/* task completed, remove it */
- this->passive_tasks->remove_at(this->passive_tasks, enumerator);
+ array_remove_at(this->passive_tasks, enumerator);
task->destroy(task);
break;
case NEED_MORE:
@@ -918,7 +932,7 @@ static status_t process_request(private_task_manager_t *this,
/* FALL */
case DESTROY_ME:
/* critical failure, destroy IKE_SA */
- this->passive_tasks->remove_at(this->passive_tasks, enumerator);
+ array_remove_at(this->passive_tasks, enumerator);
enumerator->destroy(enumerator);
task->destroy(task);
return DESTROY_ME;
@@ -1078,6 +1092,7 @@ METHOD(task_manager_t, process_message, status_t,
host_t *me, *other;
status_t status;
u_int32_t mid;
+ bool schedule_delete_job = FALSE;
charon->bus->message(charon->bus, msg, TRUE, FALSE);
status = parse_message(this, msg);
@@ -1092,9 +1107,8 @@ METHOD(task_manager_t, process_message, status_t,
/* if this IKE_SA is virgin, we check for a config */
if (this->ike_sa->get_ike_cfg(this->ike_sa) == NULL)
{
- ike_sa_id_t *ike_sa_id;
ike_cfg_t *ike_cfg;
- job_t *job;
+
ike_cfg = charon->backends->get_ike_cfg(charon->backends,
me, other, IKEV2);
if (ike_cfg == NULL)
@@ -1109,12 +1123,7 @@ METHOD(task_manager_t, process_message, status_t,
this->ike_sa->set_ike_cfg(this->ike_sa, ike_cfg);
ike_cfg->destroy(ike_cfg);
/* add a timeout if peer does not establish it completely */
- ike_sa_id = this->ike_sa->get_id(this->ike_sa);
- job = (job_t*)delete_ike_sa_job_create(ike_sa_id, FALSE);
- lib->scheduler->schedule_job(lib->scheduler, job,
- lib->settings->get_int(lib->settings,
- "%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
- charon->name));
+ schedule_delete_job = TRUE;
}
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
time_monotonic(NULL));
@@ -1213,6 +1222,19 @@ METHOD(task_manager_t, process_message, status_t,
return SUCCESS;
}
}
+
+ if (schedule_delete_job)
+ {
+ ike_sa_id_t *ike_sa_id;
+ job_t *job;
+
+ ike_sa_id = this->ike_sa->get_id(this->ike_sa);
+ job = (job_t*)delete_ike_sa_job_create(ike_sa_id, FALSE);
+ lib->scheduler->schedule_job(lib->scheduler, job,
+ lib->settings->get_int(lib->settings,
+ "%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
+ charon->name));
+ }
return SUCCESS;
}
@@ -1224,8 +1246,8 @@ METHOD(task_manager_t, queue_task, void,
enumerator_t *enumerator;
task_t *current;
- enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
- while (enumerator->enumerate(enumerator, (void**)&current))
+ enumerator = array_create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, &current))
{
if (current->get_type(current) == TASK_IKE_MOBIKE)
{
@@ -1237,7 +1259,7 @@ METHOD(task_manager_t, queue_task, void,
enumerator->destroy(enumerator);
}
DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
- this->queued_tasks->insert_last(this->queued_tasks, task);
+ array_insert(this->queued_tasks, ARRAY_TAIL, task);
}
/**
@@ -1249,7 +1271,7 @@ static bool has_queued(private_task_manager_t *this, task_type_t type)
bool found = FALSE;
task_t *task;
- enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ enumerator = array_create_enumerator(this->queued_tasks);
while (enumerator->enumerate(enumerator, &task))
{
if (task->get_type(task) == type)
@@ -1404,19 +1426,51 @@ METHOD(task_manager_t, adopt_tasks, void,
task_t *task;
/* move queued tasks from other to this */
- while (other->queued_tasks->remove_last(other->queued_tasks,
- (void**)&task) == SUCCESS)
+ while (array_remove(other->queued_tasks, ARRAY_TAIL, &task))
{
DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
task->migrate(task, this->ike_sa);
- this->queued_tasks->insert_first(this->queued_tasks, task);
+ array_insert(this->queued_tasks, ARRAY_HEAD, task);
+ }
+}
+
+/**
+ * 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)
{
- return (this->active_tasks->get_count(this->active_tasks) > 0);
+ return array_count(this->active_tasks) > 0;
}
METHOD(task_manager_t, reset, void,
@@ -1441,7 +1495,7 @@ METHOD(task_manager_t, reset, void,
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
/* reset queued tasks */
- enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ enumerator = array_create_enumerator(this->queued_tasks);
while (enumerator->enumerate(enumerator, &task))
{
task->migrate(task, this->ike_sa);
@@ -1449,11 +1503,10 @@ METHOD(task_manager_t, reset, void,
enumerator->destroy(enumerator);
/* reset active tasks */
- while (this->active_tasks->remove_last(this->active_tasks,
- (void**)&task) == SUCCESS)
+ while (array_remove(this->active_tasks, ARRAY_TAIL, &task))
{
task->migrate(task, this->ike_sa);
- this->queued_tasks->insert_first(this->queued_tasks, task);
+ array_insert(this->queued_tasks, ARRAY_HEAD, task);
}
this->reset = TRUE;
@@ -1465,11 +1518,11 @@ METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
switch (queue)
{
case TASK_QUEUE_ACTIVE:
- return this->active_tasks->create_enumerator(this->active_tasks);
+ return array_create_enumerator(this->active_tasks);
case TASK_QUEUE_PASSIVE:
- return this->passive_tasks->create_enumerator(this->passive_tasks);
+ return array_create_enumerator(this->passive_tasks);
case TASK_QUEUE_QUEUED:
- return this->queued_tasks->create_enumerator(this->queued_tasks);
+ return array_create_enumerator(this->queued_tasks);
default:
return enumerator_create_empty();
}
@@ -1480,9 +1533,9 @@ METHOD(task_manager_t, destroy, void,
{
flush(this);
- this->active_tasks->destroy(this->active_tasks);
- this->queued_tasks->destroy(this->queued_tasks);
- this->passive_tasks->destroy(this->passive_tasks);
+ array_destroy(this->active_tasks);
+ array_destroy(this->queued_tasks);
+ array_destroy(this->passive_tasks);
DESTROY_IF(this->responding.packet);
DESTROY_IF(this->initiating.packet);
@@ -1515,6 +1568,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,
@@ -1523,9 +1577,9 @@ task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa)
},
.ike_sa = ike_sa,
.initiating.type = EXCHANGE_TYPE_UNDEFINED,
- .queued_tasks = linked_list_create(),
- .active_tasks = linked_list_create(),
- .passive_tasks = linked_list_create(),
+ .queued_tasks = array_create(0, 0),
+ .active_tasks = array_create(0, 0),
+ .passive_tasks = array_create(0, 0),
.retransmit_tries = lib->settings->get_int(lib->settings,
"%s.retransmit_tries", RETRANSMIT_TRIES, charon->name),
.retransmit_timeout = lib->settings->get_double(lib->settings,