summaryrefslogtreecommitdiff
path: root/src/charon/sa/task_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/sa/task_manager.c')
-rw-r--r--src/charon/sa/task_manager.c168
1 files changed, 138 insertions, 30 deletions
diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c
index 55592f437..f4484774e 100644
--- a/src/charon/sa/task_manager.c
+++ b/src/charon/sa/task_manager.c
@@ -6,6 +6,7 @@
*/
/*
+ * Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -40,6 +41,10 @@
#include <encoding/payloads/delete_payload.h>
#include <processing/jobs/retransmit_job.h>
+#ifdef P2P
+#include <sa/tasks/ike_p2p.h>
+#endif
+
typedef struct exchange_t exchange_t;
/**
@@ -217,28 +222,73 @@ static status_t retransmit(private_task_manager_t *this, u_int32_t message_id)
{
u_int32_t timeout;
job_t *job;
+ iterator_t *iterator;
+ packet_t *packet;
+ task_t *task;
+ ike_mobike_t *mobike = NULL;
+
+ /* check if we are retransmitting a MOBIKE routability check */
+ iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
+ while (iterator->iterate(iterator, (void*)&task))
+ {
+ if (task->get_type(task) == IKE_MOBIKE)
+ {
+ mobike = (ike_mobike_t*)task;
+ if (!mobike->is_probing(mobike))
+ {
+ mobike = NULL;
+ }
+ break;
+ }
+ }
+ iterator->destroy(iterator);
- if (this->initiating.retransmitted <= RETRANSMIT_TRIES)
+ if (mobike == NULL)
{
- timeout = (u_int32_t)(RETRANSMIT_TIMEOUT *
- pow(RETRANSMIT_BASE, this->initiating.retransmitted));
+ if (this->initiating.retransmitted <= RETRANSMIT_TRIES)
+ {
+ timeout = (u_int32_t)(RETRANSMIT_TIMEOUT *
+ pow(RETRANSMIT_BASE, this->initiating.retransmitted));
+ }
+ else
+ {
+ DBG1(DBG_IKE, "giving up after %d retransmits",
+ this->initiating.retransmitted - 1);
+ return DESTROY_ME;
+ }
+
+ if (this->initiating.retransmitted)
+ {
+ DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
+ this->initiating.retransmitted, message_id);
+ }
+ packet = this->initiating.packet->clone(this->initiating.packet);
}
else
- {
- DBG1(DBG_IKE, "giving up after %d retransmits",
- this->initiating.retransmitted - 1);
- return DESTROY_ME;
+ { /* for routeability checks, we use a more aggressive behavior */
+ if (this->initiating.retransmitted <= ROUTEABILITY_CHECK_TRIES)
+ {
+ timeout = ROUTEABILITY_CHECK_INTERVAL;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "giving up after %d path probings",
+ this->initiating.retransmitted - 1);
+ return DESTROY_ME;
+ }
+
+ if (this->initiating.retransmitted)
+ {
+ DBG1(DBG_IKE, "path probing attempt %d",
+ this->initiating.retransmitted);
+ }
+ packet = this->initiating.packet->clone(this->initiating.packet);
+ mobike->transmit(mobike, packet);
}
- if (this->initiating.retransmitted)
- {
- DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
- this->initiating.retransmitted, message_id);
- }
- this->initiating.retransmitted++;
+ charon->sender->send(charon->sender, packet);
- charon->sender->send(charon->sender,
- this->initiating.packet->clone(this->initiating.packet));
+ this->initiating.retransmitted++;
job = (job_t*)retransmit_job_create(this->initiating.mid,
this->ike_sa->get_id(this->ike_sa));
charon->scheduler->schedule_job(charon->scheduler, job, timeout);
@@ -255,6 +305,7 @@ static status_t build_request(private_task_manager_t *this)
iterator_t *iterator;
task_t *task;
message_t *message;
+ host_t *me, *other;
status_t status;
exchange_type_t exchange = 0;
@@ -277,6 +328,13 @@ static status_t build_request(private_task_manager_t *this)
exchange = IKE_SA_INIT;
activate_task(this, IKE_NATD);
activate_task(this, IKE_CERT);
+#ifdef P2P
+ /* this task has to be activated before the IKE_AUTHENTICATE
+ * task, because that task pregenerates the packet after
+ * which no payloads can be added to the message anymore.
+ */
+ activate_task(this, IKE_P2P);
+#endif /* P2P */
activate_task(this, IKE_AUTHENTICATE);
activate_task(this, IKE_CONFIG);
activate_task(this, CHILD_CREATE);
@@ -324,6 +382,13 @@ static status_t build_request(private_task_manager_t *this)
exchange = INFORMATIONAL;
break;
}
+#ifdef P2P
+ if (activate_task(this, IKE_P2P))
+ {
+ exchange = P2P_CONNECT;
+ break;
+ }
+#endif /* P2P */
case IKE_REKEYING:
if (activate_task(this, IKE_DELETE))
{
@@ -372,8 +437,13 @@ static status_t build_request(private_task_manager_t *this)
return SUCCESS;
}
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
+
message = message_create();
message->set_message_id(message, this->initiating.mid);
+ message->set_source(message, me->clone(me));
+ message->set_destination(message, other->clone(other));
message->set_exchange_type(message, exchange);
this->initiating.type = exchange;
this->initiating.retransmitted = 0;
@@ -412,7 +482,7 @@ static status_t build_request(private_task_manager_t *this)
* close the SA */
flush(this);
return DESTROY_ME;
- }
+ }
return retransmit(this, this->initiating.mid);
}
@@ -523,17 +593,23 @@ static void handle_collisions(private_task_manager_t *this, task_t *task)
/**
* build a response depending on the "passive" task list
*/
-static status_t build_response(private_task_manager_t *this,
- exchange_type_t exchange)
+static status_t build_response(private_task_manager_t *this, message_t *request)
{
iterator_t *iterator;
task_t *task;
message_t *message;
+ host_t *me, *other;
bool delete = FALSE;
status_t status;
+ me = request->get_destination(request);
+ other = request->get_source(request);
+
message = message_create();
- message->set_exchange_type(message, exchange);
+ message->set_exchange_type(message, request->get_exchange_type(request));
+ /* send response along the path the request came in */
+ message->set_source(message, me->clone(me));
+ message->set_destination(message, other->clone(other));
message->set_message_id(message, this->responding.mid);
message->set_request(message, FALSE);
@@ -563,7 +639,7 @@ static status_t build_response(private_task_manager_t *this,
iterator->destroy(iterator);
/* remove resonder SPI if IKE_SA_INIT failed */
- if (delete && exchange == IKE_SA_INIT)
+ if (delete && request->get_exchange_type(request) == IKE_SA_INIT)
{
ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa);
id->set_responder_spi(id, 0);
@@ -596,15 +672,12 @@ static status_t process_request(private_task_manager_t *this,
{
iterator_t *iterator;
task_t *task = NULL;
- exchange_type_t exchange;
payload_t *payload;
notify_payload_t *notify;
delete_payload_t *delete;
- exchange = message->get_exchange_type(message);
-
/* create tasks depending on request type */
- switch (exchange)
+ switch (message->get_exchange_type(message))
{
case IKE_SA_INIT:
{
@@ -614,6 +687,10 @@ static status_t process_request(private_task_manager_t *this,
this->passive_tasks->insert_last(this->passive_tasks, task);
task = (task_t*)ike_cert_create(this->ike_sa, FALSE);
this->passive_tasks->insert_last(this->passive_tasks, task);
+#ifdef P2P
+ task = (task_t*)ike_p2p_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+#endif /* P2P */
task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
this->passive_tasks->insert_last(this->passive_tasks, task);
task = (task_t*)ike_config_create(this->ike_sa, FALSE);
@@ -625,7 +702,7 @@ static status_t process_request(private_task_manager_t *this,
break;
}
case CREATE_CHILD_SA:
- {
+ {//FIXME: we should prevent this on mediation connections
bool notify_found = FALSE, ts_found = FALSE;
iterator = message->get_payload_iterator(message);
while (iterator->iterate(iterator, (void**)&payload))
@@ -733,6 +810,13 @@ static status_t process_request(private_task_manager_t *this,
this->passive_tasks->insert_last(this->passive_tasks, task);
break;
}
+#ifdef P2P
+ case P2P_CONNECT:
+ {
+ task = (task_t*)ike_p2p_create(this->ike_sa, FALSE);
+ this->passive_tasks->insert_last(this->passive_tasks, task);
+ }
+#endif /* P2P */
default:
break;
}
@@ -760,7 +844,7 @@ static status_t process_request(private_task_manager_t *this,
}
iterator->destroy(iterator);
- return build_response(this, exchange);
+ return build_response(this, message);
}
/**
@@ -783,14 +867,21 @@ static status_t process_message(private_task_manager_t *this, message_t *msg)
}
else if ((mid == this->responding.mid - 1) && this->responding.packet)
{
+ packet_t *clone;
+ host_t *me, *other;
+
DBG1(DBG_IKE, "received retransmit of request with ID %d, "
"retransmitting response", mid);
- charon->sender->send(charon->sender,
- this->responding.packet->clone(this->responding.packet));
+ clone = this->responding.packet->clone(this->responding.packet);
+ me = msg->get_destination(msg);
+ other = msg->get_source(msg);
+ clone->set_source(clone, me->clone(me));
+ clone->set_destination(clone, other->clone(other));
+ charon->sender->send(charon->sender, clone);
}
else
{
- DBG1(DBG_IKE, "received message ID %d, excepted %d. Ignored",
+ DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
mid, this->responding.mid);
}
}
@@ -806,7 +897,7 @@ static status_t process_message(private_task_manager_t *this, message_t *msg)
}
else
{
- DBG1(DBG_IKE, "received message ID %d, excepted %d. Ignored",
+ DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
mid, this->initiating.mid);
return SUCCESS;
}
@@ -819,6 +910,23 @@ static status_t process_message(private_task_manager_t *this, message_t *msg)
*/
static void queue_task(private_task_manager_t *this, task_t *task)
{
+ if (task->get_type(task) == IKE_MOBIKE)
+ { /* there is no need to queue more than one mobike task */
+ iterator_t *iterator;
+ task_t *current;
+
+ iterator = this->queued_tasks->create_iterator(this->queued_tasks, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ if (current->get_type(current) == IKE_MOBIKE)
+ {
+ iterator->destroy(iterator);
+ task->destroy(task);
+ return;
+ }
+ }
+ iterator->destroy(iterator);
+ }
DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
this->queued_tasks->insert_last(this->queued_tasks, task);
}