aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/sa/ikev2/task_manager_v2.c
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2014-09-12 10:35:06 +0200
committerTobias Brunner <tobias@strongswan.org>2014-09-12 10:40:07 +0200
commit5dec7d2f9d3bf93aa9002fbb6ae9f119a7ec2dd8 (patch)
tree9cbfe4387a759a4ebe624c41e126ebdc07a143df /src/libcharon/sa/ikev2/task_manager_v2.c
parentf640af5b7a68bd5230e07eb54fe7432a240192d8 (diff)
parentacd69fc291bea4f8e85680505af0bd751e8b36a9 (diff)
downloadstrongswan-5dec7d2f9d3bf93aa9002fbb6ae9f119a7ec2dd8.tar.bz2
strongswan-5dec7d2f9d3bf93aa9002fbb6ae9f119a7ec2dd8.tar.xz
Merge branch 'mobike-fixes'
These changes improve the handling of MOBIKE tasks, for instance, when retransmitting and no path is available. Fixes #632.
Diffstat (limited to 'src/libcharon/sa/ikev2/task_manager_v2.c')
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c74
1 files changed, 65 insertions, 9 deletions
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index ada798bdc..58f6bc61d 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -120,6 +120,11 @@ struct private_task_manager_t {
*/
exchange_type_t type;
+ /**
+ * TRUE if exchange was deferred because no path was available
+ */
+ bool deferred;
+
} initiating;
/**
@@ -236,16 +241,12 @@ METHOD(task_manager_t, retransmit, status_t,
if (task->get_type(task) == TASK_IKE_MOBIKE)
{
mobike = (ike_mobike_t*)task;
- if (!mobike->is_probing(mobike))
- {
- mobike = NULL;
- }
break;
}
}
enumerator->destroy(enumerator);
- if (mobike == NULL)
+ if (!mobike || !mobike->is_probing(mobike))
{
if (this->initiating.retransmitted <= this->retransmit_tries)
{
@@ -268,8 +269,26 @@ METHOD(task_manager_t, retransmit, status_t,
charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND,
this->initiating.packet);
}
- packet = this->initiating.packet->clone(this->initiating.packet);
- charon->sender->send(charon->sender, packet);
+ if (!mobike)
+ {
+ packet = this->initiating.packet->clone(this->initiating.packet);
+ charon->sender->send(charon->sender, packet);
+ }
+ else
+ {
+ if (!mobike->transmit(mobike, this->initiating.packet))
+ {
+ DBG1(DBG_IKE, "no route found to reach peer, MOBIKE update "
+ "deferred");
+ this->ike_sa->set_condition(this->ike_sa, COND_STALE, TRUE);
+ this->initiating.deferred = TRUE;
+ return SUCCESS;
+ }
+ else if (mobike->is_probing(mobike))
+ {
+ timeout = ROUTEABILITY_CHECK_INTERVAL;
+ }
+ }
}
else
{ /* for routeability checks, we use a more aggressive behavior */
@@ -289,7 +308,14 @@ METHOD(task_manager_t, retransmit, status_t,
DBG1(DBG_IKE, "path probing attempt %d",
this->initiating.retransmitted);
}
- mobike->transmit(mobike, this->initiating.packet);
+ if (!mobike->transmit(mobike, this->initiating.packet))
+ {
+ DBG1(DBG_IKE, "no route found to reach peer, path probing "
+ "deferred");
+ this->ike_sa->set_condition(this->ike_sa, COND_STALE, TRUE);
+ this->initiating.deferred = TRUE;
+ return SUCCESS;
+ }
}
this->initiating.retransmitted++;
@@ -315,6 +341,12 @@ METHOD(task_manager_t, initiate, status_t,
DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
exchange_type_names, this->initiating.type);
/* do not initiate if we already have a message in the air */
+ if (this->initiating.deferred)
+ { /* re-initiate deferred exchange */
+ this->initiating.deferred = FALSE;
+ this->initiating.retransmitted = 0;
+ return retransmit(this, this->initiating.mid);
+ }
return SUCCESS;
}
@@ -458,6 +490,7 @@ METHOD(task_manager_t, initiate, status_t,
message->set_exchange_type(message, exchange);
this->initiating.type = exchange;
this->initiating.retransmitted = 0;
+ this->initiating.deferred = FALSE;
enumerator = array_create_enumerator(this->active_tasks);
while (enumerator->enumerate(enumerator, &task))
@@ -1246,6 +1279,8 @@ METHOD(task_manager_t, process_message, status_t,
METHOD(task_manager_t, queue_task, void,
private_task_manager_t *this, task_t *task)
{
+ int pos = ARRAY_TAIL;
+
if (task->get_type(task) == TASK_IKE_MOBIKE)
{ /* there is no need to queue more than one mobike task */
enumerator_t *enumerator;
@@ -1262,9 +1297,12 @@ METHOD(task_manager_t, queue_task, void,
}
}
enumerator->destroy(enumerator);
+ /* insert MOBIKE tasks first as we currently might not have a usable
+ * path to initiate any other tasks */
+ pos = ARRAY_HEAD;
}
DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
- array_insert(this->queued_tasks, ARRAY_TAIL, task);
+ array_insert(this->queued_tasks, pos, task);
}
/**
@@ -1368,7 +1406,25 @@ METHOD(task_manager_t, queue_mobike, void,
mobike = ike_mobike_create(this->ike_sa, TRUE);
if (roam)
{
+ enumerator_t *enumerator;
+ task_t *current;
+
mobike->roam(mobike, address);
+
+ /* enable path probing for a currently active MOBIKE task. This might
+ * not be the case if an address appeared on a new interface while the
+ * current address is not working but has not yet disappeared. */
+ enumerator = array_create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->get_type(current) == TASK_IKE_MOBIKE)
+ {
+ ike_mobike_t *active = (ike_mobike_t*)current;
+ active->enable_probing(active);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
}
else
{