summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/ikev2
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/ikev2')
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c307
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_init.c23
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_mobike.c95
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_mobike.h8
4 files changed, 351 insertions, 82 deletions
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index ada798bdc..eb7df3516 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2011 Tobias Brunner
+ * Copyright (C) 2007-2014 Tobias Brunner
* Copyright (C) 2007-2010 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -90,9 +90,14 @@ struct private_task_manager_t {
u_int32_t mid;
/**
- * packet for retransmission
+ * packet(s) for retransmission
*/
- packet_t *packet;
+ array_t *packets;
+
+ /**
+ * Helper to defragment the request
+ */
+ message_t *defrag;
} responding;
@@ -111,15 +116,25 @@ struct private_task_manager_t {
u_int retransmitted;
/**
- * packet for retransmission
+ * packet(s) for retransmission
*/
- packet_t *packet;
+ array_t *packets;
/**
* type of the initated exchange
*/
exchange_type_t type;
+ /**
+ * TRUE if exchange was deferred because no path was available
+ */
+ bool deferred;
+
+ /**
+ * Helper to defragment the response
+ */
+ message_t *defrag;
+
} initiating;
/**
@@ -158,6 +173,19 @@ struct private_task_manager_t {
double retransmit_base;
};
+/**
+ * Reset retransmission packet list
+ */
+static void clear_packets(array_t *array)
+{
+ packet_t *packet;
+
+ while (array_remove(array, ARRAY_TAIL, &packet))
+ {
+ packet->destroy(packet);
+ }
+}
+
METHOD(task_manager_t, flush_queue, void,
private_task_manager_t *this, task_queue_t queue)
{
@@ -217,10 +245,60 @@ static bool activate_task(private_task_manager_t *this, task_type_t type)
return found;
}
+/**
+ * Send packets in the given array (they get cloned). Optionally, the
+ * source and destination addresses are changed before sending it.
+ */
+static void send_packets(private_task_manager_t *this, array_t *packets,
+ host_t *src, host_t *dst)
+{
+ packet_t *packet, *clone;
+ int i;
+
+ for (i = 0; i < array_count(packets); i++)
+ {
+ array_get(packets, i, &packet);
+ clone = packet->clone(packet);
+ if (src)
+ {
+ clone->set_source(clone, src->clone(src));
+ }
+ if (dst)
+ {
+ clone->set_destination(clone, dst->clone(dst));
+ }
+ charon->sender->send(charon->sender, clone);
+ }
+}
+
+/**
+ * Generates the given message and stores packet(s) in the given array
+ */
+static bool generate_message(private_task_manager_t *this, message_t *message,
+ array_t **packets)
+{
+ enumerator_t *fragments;
+ packet_t *fragment;
+
+ if (this->ike_sa->generate_message_fragmented(this->ike_sa, message,
+ &fragments) != SUCCESS)
+ {
+ return FALSE;
+ }
+ while (fragments->enumerate(fragments, &fragment))
+ {
+ array_insert_create(packets, ARRAY_TAIL, fragment);
+ }
+ fragments->destroy(fragments);
+ array_compress(*packets);
+ return TRUE;
+}
+
METHOD(task_manager_t, retransmit, status_t,
private_task_manager_t *this, u_int32_t message_id)
{
- if (this->initiating.packet && message_id == this->initiating.mid)
+ if (message_id == this->initiating.mid &&
+ array_count(this->initiating.packets))
{
u_int32_t timeout;
job_t *job;
@@ -229,23 +307,24 @@ METHOD(task_manager_t, retransmit, status_t,
task_t *task;
ike_mobike_t *mobike = NULL;
+ array_get(this->initiating.packets, 0, &packet);
+
/* check if we are retransmitting a MOBIKE routability check */
- enumerator = array_create_enumerator(this->active_tasks);
- while (enumerator->enumerate(enumerator, (void*)&task))
+ if (this->initiating.type == INFORMATIONAL)
{
- if (task->get_type(task) == TASK_IKE_MOBIKE)
+ enumerator = array_create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
{
- mobike = (ike_mobike_t*)task;
- if (!mobike->is_probing(mobike))
+ if (task->get_type(task) == TASK_IKE_MOBIKE)
{
- mobike = NULL;
+ mobike = (ike_mobike_t*)task;
+ break;
}
- break;
}
+ enumerator->destroy(enumerator);
}
- enumerator->destroy(enumerator);
- if (mobike == NULL)
+ if (!mobike || !mobike->is_probing(mobike))
{
if (this->initiating.retransmitted <= this->retransmit_tries)
{
@@ -257,7 +336,7 @@ METHOD(task_manager_t, retransmit, status_t,
DBG1(DBG_IKE, "giving up after %d retransmits",
this->initiating.retransmitted - 1);
charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_TIMEOUT,
- this->initiating.packet);
+ packet);
return DESTROY_ME;
}
@@ -265,11 +344,29 @@ METHOD(task_manager_t, retransmit, status_t,
{
DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
this->initiating.retransmitted, message_id);
- charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND,
- this->initiating.packet);
+ charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, packet);
+ }
+ if (!mobike)
+ {
+ send_packets(this, this->initiating.packets,
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa));
+ }
+ else
+ {
+ if (!mobike->transmit(mobike, 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;
+ }
}
- packet = this->initiating.packet->clone(this->initiating.packet);
- charon->sender->send(charon->sender, packet);
}
else
{ /* for routeability checks, we use a more aggressive behavior */
@@ -289,7 +386,16 @@ METHOD(task_manager_t, retransmit, status_t,
DBG1(DBG_IKE, "path probing attempt %d",
this->initiating.retransmitted);
}
- mobike->transmit(mobike, this->initiating.packet);
+ /* TODO-FRAG: presumably these small packets are not fragmented,
+ * we should maybe ensure this is the case when generating them */
+ if (!mobike->transmit(mobike, 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++;
@@ -307,7 +413,6 @@ METHOD(task_manager_t, initiate, status_t,
task_t *task;
message_t *message;
host_t *me, *other;
- status_t status;
exchange_type_t exchange = 0;
if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
@@ -315,6 +420,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;
}
@@ -347,39 +458,39 @@ METHOD(task_manager_t, initiate, status_t,
}
break;
case IKE_ESTABLISHED:
- if (activate_task(this, TASK_CHILD_CREATE))
+ if (activate_task(this, TASK_IKE_MOBIKE))
{
- exchange = CREATE_CHILD_SA;
+ exchange = INFORMATIONAL;
break;
}
- if (activate_task(this, TASK_CHILD_DELETE))
+ if (activate_task(this, TASK_IKE_DELETE))
{
exchange = INFORMATIONAL;
break;
}
- if (activate_task(this, TASK_CHILD_REKEY))
+ if (activate_task(this, TASK_CHILD_DELETE))
{
- exchange = CREATE_CHILD_SA;
+ exchange = INFORMATIONAL;
break;
}
- if (activate_task(this, TASK_IKE_DELETE))
+ if (activate_task(this, TASK_IKE_REAUTH))
{
exchange = INFORMATIONAL;
break;
}
- if (activate_task(this, TASK_IKE_REKEY))
+ if (activate_task(this, TASK_CHILD_CREATE))
{
exchange = CREATE_CHILD_SA;
break;
}
- if (activate_task(this, TASK_IKE_REAUTH))
+ if (activate_task(this, TASK_CHILD_REKEY))
{
- exchange = INFORMATIONAL;
+ exchange = CREATE_CHILD_SA;
break;
}
- if (activate_task(this, TASK_IKE_MOBIKE))
+ if (activate_task(this, TASK_IKE_REKEY))
{
- exchange = INFORMATIONAL;
+ exchange = CREATE_CHILD_SA;
break;
}
if (activate_task(this, TASK_IKE_DPD))
@@ -458,6 +569,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))
@@ -493,9 +605,7 @@ METHOD(task_manager_t, initiate, status_t,
/* update exchange type if a task changed it */
this->initiating.type = message->get_exchange_type(message);
- status = this->ike_sa->generate_message(this->ike_sa, message,
- &this->initiating.packet);
- if (status != SUCCESS)
+ if (!generate_message(this, message, &this->initiating.packets))
{
/* message generation failed. There is nothing more to do than to
* close the SA */
@@ -567,8 +677,7 @@ static status_t process_response(private_task_manager_t *this,
this->initiating.mid++;
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
- this->initiating.packet->destroy(this->initiating.packet);
- this->initiating.packet = NULL;
+ clear_packets(this->initiating.packets);
array_compress(this->active_tasks);
@@ -636,8 +745,8 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
host_t *me, *other;
bool delete = FALSE, hook = FALSE;
ike_sa_id_t *id = NULL;
- u_int64_t responder_spi;
- status_t status;
+ u_int64_t responder_spi = 0;
+ bool result;
me = request->get_destination(request);
other = request->get_source(request);
@@ -699,23 +808,20 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
}
/* message complete, send it */
- DESTROY_IF(this->responding.packet);
- this->responding.packet = NULL;
- status = this->ike_sa->generate_message(this->ike_sa, message,
- &this->responding.packet);
+ clear_packets(this->responding.packets);
+ result = generate_message(this, message, &this->responding.packets);
message->destroy(message);
if (id)
{
id->set_responder_spi(id, responder_spi);
}
- if (status != SUCCESS)
+ if (!result)
{
charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
return DESTROY_ME;
}
- charon->sender->send(charon->sender,
- this->responding.packet->clone(this->responding.packet));
+ send_packets(this, this->responding.packets, NULL, NULL);
if (delete)
{
if (hook)
@@ -964,6 +1070,48 @@ METHOD(task_manager_t, incr_mid, void,
}
/**
+ * Handle the given IKE fragment, if it is one.
+ *
+ * Returns SUCCESS if the message is not a fragment, and NEED_MORE if it was
+ * handled properly. Error states are returned if the fragment was invalid or
+ * the reassembled message could not have been processed properly.
+ */
+static status_t handle_fragment(private_task_manager_t *this,
+ message_t **defrag, message_t *msg)
+{
+ message_t *reassembled;
+ status_t status;
+
+ if (!msg->get_payload(msg, PLV2_FRAGMENT))
+ {
+ return SUCCESS;
+ }
+ if (!*defrag)
+ {
+ *defrag = message_create_defrag(msg);
+ if (!*defrag)
+ {
+ return FAILED;
+ }
+ }
+ status = (*defrag)->add_fragment(*defrag, msg);
+ if (status == SUCCESS)
+ {
+ /* reinject the reassembled message */
+ reassembled = *defrag;
+ *defrag = NULL;
+ status = this->ike_sa->process_message(this->ike_sa, reassembled);
+ if (status == SUCCESS)
+ {
+ /* avoid processing the last fragment */
+ status = NEED_MORE;
+ }
+ reassembled->destroy(reassembled);
+ }
+ return status;
+}
+
+/**
* Send a notify back to the sender
*/
static void send_notify_response(private_task_manager_t *this,
@@ -1156,6 +1304,11 @@ METHOD(task_manager_t, process_message, status_t,
{ /* with MOBIKE, we do no implicit updates */
this->ike_sa->update_hosts(this->ike_sa, me, other, mid == 1);
}
+ status = handle_fragment(this, &this->responding.defrag, msg);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
charon->bus->message(charon->bus, msg, TRUE, TRUE);
if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
{ /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
@@ -1168,20 +1321,19 @@ METHOD(task_manager_t, process_message, status_t,
}
this->responding.mid++;
}
- else if ((mid == this->responding.mid - 1) && this->responding.packet)
+ else if ((mid == this->responding.mid - 1) &&
+ array_count(this->responding.packets))
{
- packet_t *clone;
- host_t *host;
-
+ status = handle_fragment(this, &this->responding.defrag, msg);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
DBG1(DBG_IKE, "received retransmit of request with ID %d, "
"retransmitting response", mid);
charon->bus->alert(charon->bus, ALERT_RETRANSMIT_RECEIVE, msg);
- clone = this->responding.packet->clone(this->responding.packet);
- host = msg->get_destination(msg);
- clone->set_source(clone, host->clone(host));
- host = msg->get_source(msg);
- clone->set_destination(clone, host->clone(host));
- charon->sender->send(charon->sender, clone);
+ send_packets(this, this->responding.packets,
+ msg->get_destination(msg), msg->get_source(msg));
}
else
{
@@ -1209,6 +1361,11 @@ METHOD(task_manager_t, process_message, status_t,
this->ike_sa->update_hosts(this->ike_sa, NULL, other, FALSE);
}
}
+ status = handle_fragment(this, &this->initiating.defrag, msg);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
charon->bus->message(charon->bus, msg, TRUE, TRUE);
if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
{ /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
@@ -1368,7 +1525,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
{
@@ -1485,10 +1660,12 @@ METHOD(task_manager_t, reset, void,
task_t *task;
/* reset message counters and retransmit packets */
- DESTROY_IF(this->responding.packet);
- DESTROY_IF(this->initiating.packet);
- this->responding.packet = NULL;
- this->initiating.packet = NULL;
+ clear_packets(this->responding.packets);
+ clear_packets(this->initiating.packets);
+ DESTROY_IF(this->responding.defrag);
+ DESTROY_IF(this->initiating.defrag);
+ this->responding.defrag = NULL;
+ this->initiating.defrag = NULL;
if (initiate != UINT_MAX)
{
this->initiating.mid = initiate;
@@ -1542,8 +1719,12 @@ METHOD(task_manager_t, destroy, void,
array_destroy(this->queued_tasks);
array_destroy(this->passive_tasks);
- DESTROY_IF(this->responding.packet);
- DESTROY_IF(this->initiating.packet);
+ clear_packets(this->responding.packets);
+ array_destroy(this->responding.packets);
+ clear_packets(this->initiating.packets);
+ array_destroy(this->initiating.packets);
+ DESTROY_IF(this->responding.defrag);
+ DESTROY_IF(this->initiating.defrag);
free(this);
}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c
index e3c18ea0f..71c5f22fa 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_init.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.c
@@ -161,6 +161,19 @@ static void build_payloads(private_ike_init_t *this, message_t *message)
message->add_payload(message, (payload_t*)ke_payload);
message->add_payload(message, (payload_t*)nonce_payload);
}
+
+ /* negotiate fragmentation if we are not rekeying */
+ if (!this->old_sa &&
+ this->config->fragmentation(this->config) != FRAGMENTATION_NO)
+ {
+ if (this->initiator ||
+ this->ike_sa->supports_extension(this->ike_sa,
+ EXT_IKE_FRAGMENTATION))
+ {
+ message->add_notify(message, FALSE, FRAGMENTATION_SUPPORTED,
+ chunk_empty);
+ }
+ }
}
/**
@@ -220,6 +233,16 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
this->other_nonce = nonce_payload->get_nonce(nonce_payload);
break;
}
+ case PLV2_NOTIFY:
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+
+ if (notify->get_notify_type(notify) == FRAGMENTATION_SUPPORTED)
+ {
+ this->ike_sa->enable_extension(this->ike_sa,
+ EXT_IKE_FRAGMENTATION);
+ }
+ }
default:
break;
}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
index 00ca615d8..d91fa5862 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 Tobias Brunner
+ * Copyright (C) 2010-2014 Tobias Brunner
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -77,6 +77,11 @@ struct private_ike_mobike_t {
* additional addresses got updated
*/
bool addresses_updated;
+
+ /**
+ * whether the pending updates counter was increased
+ */
+ bool pending_update;
};
/**
@@ -301,35 +306,61 @@ static void apply_port(host_t *host, host_t *old, u_int16_t port, bool local)
host->set_port(host, port);
}
-METHOD(ike_mobike_t, transmit, void,
+METHOD(ike_mobike_t, transmit, bool,
private_ike_mobike_t *this, packet_t *packet)
{
host_t *me, *other, *me_old, *other_old;
enumerator_t *enumerator;
ike_cfg_t *ike_cfg;
packet_t *copy;
+ int family = AF_UNSPEC;
+ bool found = FALSE;
+
+ me_old = this->ike_sa->get_my_host(this->ike_sa);
+ other_old = this->ike_sa->get_other_host(this->ike_sa);
+ ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
if (!this->check)
{
- return;
+ me = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
+ other_old, me_old);
+ if (me)
+ {
+ if (me->ip_equals(me, me_old))
+ {
+ charon->sender->send(charon->sender, packet->clone(packet));
+ me->destroy(me);
+ return TRUE;
+ }
+ me->destroy(me);
+ }
+ this->check = TRUE;
}
- me_old = this->ike_sa->get_my_host(this->ike_sa);
- other_old = this->ike_sa->get_other_host(this->ike_sa);
- ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
+ switch (charon->socket->supported_families(charon->socket))
+ {
+ case SOCKET_FAMILY_IPV4:
+ family = AF_INET;
+ break;
+ case SOCKET_FAMILY_IPV6:
+ family = AF_INET6;
+ break;
+ case SOCKET_FAMILY_BOTH:
+ case SOCKET_FAMILY_NONE:
+ break;
+ }
enumerator = this->ike_sa->create_peer_address_enumerator(this->ike_sa);
while (enumerator->enumerate(enumerator, (void**)&other))
{
+ if (family != AF_UNSPEC && other->get_family(other) != family)
+ {
+ continue;
+ }
me = hydra->kernel_interface->get_source_addr(
hydra->kernel_interface, other, NULL);
if (me)
{
- if (me->get_family(me) != other->get_family(other))
- {
- me->destroy(me);
- continue;
- }
/* reuse port for an active address, 4500 otherwise */
apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg), TRUE);
other = other->clone(other);
@@ -339,9 +370,11 @@ METHOD(ike_mobike_t, transmit, void,
copy->set_source(copy, me);
copy->set_destination(copy, other);
charon->sender->send(charon->sender, copy);
+ found = TRUE;
}
}
enumerator->destroy(enumerator);
+ return found;
}
METHOD(task_t, build_i, status_t,
@@ -481,9 +514,7 @@ METHOD(task_t, process_i, status_t,
}
else if (message->get_exchange_type(message) == INFORMATIONAL)
{
- u_int32_t updates = this->ike_sa->get_pending_updates(this->ike_sa) - 1;
- this->ike_sa->set_pending_updates(this->ike_sa, updates);
- if (updates > 0)
+ if (this->ike_sa->get_pending_updates(this->ike_sa) > 1)
{
/* newer update queued, ignore this one */
return SUCCESS;
@@ -560,7 +591,6 @@ METHOD(task_t, process_i, status_t,
this->natd = ike_natd_create(this->ike_sa, this->initiator);
}
this->check = FALSE;
- this->ike_sa->set_pending_updates(this->ike_sa, 1);
return NEED_MORE;
}
}
@@ -573,8 +603,12 @@ METHOD(ike_mobike_t, addresses, void,
private_ike_mobike_t *this)
{
this->address = TRUE;
- this->ike_sa->set_pending_updates(this->ike_sa,
+ if (!this->pending_update)
+ {
+ this->pending_update = TRUE;
+ this->ike_sa->set_pending_updates(this->ike_sa,
this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+ }
}
METHOD(ike_mobike_t, roam, void,
@@ -582,8 +616,12 @@ METHOD(ike_mobike_t, roam, void,
{
this->check = TRUE;
this->address = address;
- this->ike_sa->set_pending_updates(this->ike_sa,
+ if (!this->pending_update)
+ {
+ this->pending_update = TRUE;
+ this->ike_sa->set_pending_updates(this->ike_sa,
this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+ }
}
METHOD(ike_mobike_t, dpd, void,
@@ -593,8 +631,12 @@ METHOD(ike_mobike_t, dpd, void,
{
this->natd = ike_natd_create(this->ike_sa, this->initiator);
}
- this->ike_sa->set_pending_updates(this->ike_sa,
+ if (!this->pending_update)
+ {
+ this->pending_update = TRUE;
+ this->ike_sa->set_pending_updates(this->ike_sa,
this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+ }
}
METHOD(ike_mobike_t, is_probing, bool,
@@ -603,6 +645,12 @@ METHOD(ike_mobike_t, is_probing, bool,
return this->check;
}
+METHOD(ike_mobike_t, enable_probing, void,
+ private_ike_mobike_t *this)
+{
+ this->check = TRUE;
+}
+
METHOD(task_t, get_type, task_type_t,
private_ike_mobike_t *this)
{
@@ -618,11 +666,21 @@ METHOD(task_t, migrate, void,
{
this->natd->task.migrate(&this->natd->task, ike_sa);
}
+ if (this->pending_update)
+ {
+ this->ike_sa->set_pending_updates(this->ike_sa,
+ this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+ }
}
METHOD(task_t, destroy, void,
private_ike_mobike_t *this)
{
+ if (this->pending_update)
+ {
+ this->ike_sa->set_pending_updates(this->ike_sa,
+ this->ike_sa->get_pending_updates(this->ike_sa) - 1);
+ }
chunk_free(&this->cookie2);
if (this->natd)
{
@@ -650,6 +708,7 @@ ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
.dpd = _dpd,
.transmit = _transmit,
.is_probing = _is_probing,
+ .enable_probing = _enable_probing,
},
.ike_sa = ike_sa,
.initiator = initiator,
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.h b/src/libcharon/sa/ikev2/tasks/ike_mobike.h
index b145a9a8b..bb2318c9c 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_mobike.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.h
@@ -70,8 +70,9 @@ struct ike_mobike_t {
* probing.
*
* @param packet the packet to transmit
+ * @return TRUE if transmitted, FALSE if no path found
*/
- void (*transmit)(ike_mobike_t *this, packet_t *packet);
+ bool (*transmit)(ike_mobike_t *this, packet_t *packet);
/**
* Check if this task is probing for routability.
@@ -79,6 +80,11 @@ struct ike_mobike_t {
* @return TRUE if task is probing
*/
bool (*is_probing)(ike_mobike_t *this);
+
+ /**
+ * Enable probing for routability.
+ */
+ void (*enable_probing)(ike_mobike_t *this);
};
/**