aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/charon/sa/task_manager.c93
-rw-r--r--src/charon/sa/task_manager.h14
-rw-r--r--src/charon/sa/tasks/ike_mobike.c9
-rw-r--r--src/charon/sa/tasks/ike_mobike.h8
4 files changed, 100 insertions, 24 deletions
diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c
index a8f662263..1b2c0f590 100644
--- a/src/charon/sa/task_manager.c
+++ b/src/charon/sa/task_manager.c
@@ -220,42 +220,70 @@ static status_t retransmit(private_task_manager_t *this, u_int32_t message_id)
iterator_t *iterator;
packet_t *packet;
task_t *task;
-
- 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;
- }
+ ike_mobike_t *mobike = NULL;
- if (this->initiating.retransmitted)
- {
- DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
- this->initiating.retransmitted, message_id);
- }
- this->initiating.retransmitted++;
-
- packet = this->initiating.packet->clone(this->initiating.packet);
-
- /* mobike needs to now when we retransmit, so we call it here */
+ /* 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)
{
- ike_mobike_t *mobike = (ike_mobike_t*)task;
- mobike->transmit(mobike, packet);
+ mobike = (ike_mobike_t*)task;
+ if (!mobike->is_probing(mobike))
+ {
+ mobike = NULL;
+ }
break;
}
}
iterator->destroy(iterator);
+
+ if (mobike == NULL)
+ {
+ 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
+ { /* 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);
+ }
charon->sender->send(charon->sender, 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);
@@ -852,6 +880,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);
}
diff --git a/src/charon/sa/task_manager.h b/src/charon/sa/task_manager.h
index fb34aab6a..38c63c1a9 100644
--- a/src/charon/sa/task_manager.h
+++ b/src/charon/sa/task_manager.h
@@ -51,6 +51,20 @@ typedef struct task_manager_t task_manager_t;
*/
#define RETRANSMIT_TRIES 5
+/**
+ * Interval for mobike routability checks in ms.
+ *
+ * @ingroup sa
+ */
+#define ROUTEABILITY_CHECK_INTERVAL 2500
+
+/**
+ * Number of routability checks before giving up
+ *
+ * @ingroup sa
+ */
+#define ROUTEABILITY_CHECK_TRIES 10
+
/**
* @brief The task manager, juggles task and handles message exchanges.
diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c
index a32f7e5e0..d1fc8c695 100644
--- a/src/charon/sa/tasks/ike_mobike.c
+++ b/src/charon/sa/tasks/ike_mobike.c
@@ -448,6 +448,14 @@ static void roam(private_ike_mobike_t *this, bool address)
}
/**
+ * Implementation of ike_mobike_t.is_probing.
+ */
+static bool is_probing(private_ike_mobike_t *this)
+{
+ return this->check;
+}
+
+/**
* Implementation of task_t.get_type
*/
static task_type_t get_type(private_ike_mobike_t *this)
@@ -490,6 +498,7 @@ ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
this->public.roam = (void(*)(ike_mobike_t*,bool))roam;
this->public.transmit = (void(*)(ike_mobike_t*,packet_t*))transmit;
+ this->public.is_probing = (bool(*)(ike_mobike_t*))is_probing;
this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
this->public.task.destroy = (void(*)(task_t*))destroy;
diff --git a/src/charon/sa/tasks/ike_mobike.h b/src/charon/sa/tasks/ike_mobike.h
index cee9da047..bb5150723 100644
--- a/src/charon/sa/tasks/ike_mobike.h
+++ b/src/charon/sa/tasks/ike_mobike.h
@@ -71,6 +71,14 @@ struct ike_mobike_t {
* @param packet the packet to transmit
*/
void (*transmit)(ike_mobike_t *this, packet_t *packet);
+
+ /**
+ * @brief Check if this task is probing for routability.
+ *
+ * @param this calling object
+ * @return TRUE if task is probing
+ */
+ bool (*is_probing)(ike_mobike_t *this);
};
/**