aboutsummaryrefslogtreecommitdiffstats
path: root/src/charon/sa/tasks/ike_mobike.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/sa/tasks/ike_mobike.c')
-rw-r--r--src/charon/sa/tasks/ike_mobike.c109
1 files changed, 78 insertions, 31 deletions
diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c
index 096199c7a..8d4dce36c 100644
--- a/src/charon/sa/tasks/ike_mobike.c
+++ b/src/charon/sa/tasks/ike_mobike.c
@@ -52,24 +52,24 @@ struct private_ike_mobike_t {
bool initiator;
/**
- * local host to roam to
+ * cookie2 value to verify new addresses
*/
- host_t *me;
+ chunk_t cookie2;
/**
- * remote host to roam to
+ * NAT discovery reusing the IKE_NATD task
*/
- host_t *other;
+ ike_natd_t *natd;
/**
- * cookie2 value to verify new addresses
+ * use task to update addresses
*/
- chunk_t cookie2;
+ bool roam;
/**
- * NAT discovery reusing the IKE_NATD task
+ * include address list update
*/
- ike_natd_t *natd;
+ bool address;
};
/**
@@ -138,6 +138,11 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message)
this->ike_sa->add_additional_address(this->ike_sa, host);
break;
}
+ case UPDATE_SA_ADDRESSES:
+ {
+ this->roam = TRUE;
+ break;
+ }
case NO_ADDITIONAL_ADDRESSES:
{
flush_additional_addresses(this);
@@ -201,6 +206,25 @@ static void build_address_list(private_ike_mobike_t *this, message_t *message)
}
/**
+ * update addresses of associated CHILD_SAs
+ */
+static void update_children(private_ike_mobike_t *this)
+{
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+
+ iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ child_sa->update_hosts(child_sa,
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
+ }
+ iterator->destroy(iterator);
+}
+
+/**
* Implementation of task_t.process for initiator
*/
static status_t build_i(private_ike_mobike_t *this, message_t *message)
@@ -211,16 +235,20 @@ static status_t build_i(private_ike_mobike_t *this, message_t *message)
message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
build_address_list(this, message);
}
- else if (this->me || this->other)
- { /* address change */
- message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES, chunk_empty);
- build_address_list(this, message);
- /* set new addresses */
- this->ike_sa->update_hosts(this->ike_sa, this->me, this->other);
- if (this->natd)
+ else
+ {
+ if (this->roam)
{
- this->natd->task.build(&this->natd->task, message);
+ message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES, chunk_empty);
}
+ if (this->address)
+ {
+ build_address_list(this, message);
+ }
+
+ this->natd = ike_natd_create(this->ike_sa, this->initiator);
+ this->natd->task.build(&this->natd->task, message);
+ update_children(this);
}
return NEED_MORE;
@@ -239,6 +267,16 @@ static status_t process_r(private_ike_mobike_t *this, message_t *message)
else if (message->get_exchange_type(message) == INFORMATIONAL)
{
process_payloads(this, message);
+ if (this->roam)
+ {
+ host_t *me, *other;
+
+ me = message->get_destination(message);
+ other = message->get_source(message);
+ this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
+ this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
+ }
+
if (this->natd)
{
this->natd->task.process(&this->natd->task, message);
@@ -268,6 +306,10 @@ static status_t build_r(private_ike_mobike_t *this, message_t *message)
{
this->natd->task.build(&this->natd->task, message);
}
+ if (this->roam)
+ {
+ update_children(this);
+ }
return SUCCESS;
}
return NEED_MORE;
@@ -287,11 +329,23 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message)
}
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)
+ {
+ /* newer update queued, ignore this one */
+ return SUCCESS;
+ }
process_payloads(this, message);
if (this->natd)
{
this->natd->task.process(&this->natd->task, message);
}
+ if (this->roam)
+ {
+ /* update again, as NAT state may have changed */
+ update_children(this);
+ }
return SUCCESS;
}
return NEED_MORE;
@@ -300,13 +354,12 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message)
/**
* Implementation of ike_mobike_t.roam.
*/
-static void roam(private_ike_mobike_t *this, host_t *me, host_t *other)
+static void roam(private_ike_mobike_t *this, bool address)
{
- this->me = me;
- this->other = other;
-
- /* include NAT detection when roaming */
- this->natd = ike_natd_create(this->ike_sa, this->initiator);
+ this->roam = TRUE;
+ this->address = address;
+ this->ike_sa->set_pending_updates(this->ike_sa,
+ this->ike_sa->get_pending_updates(this->ike_sa) + 1);
}
/**
@@ -322,12 +375,8 @@ static task_type_t get_type(private_ike_mobike_t *this)
*/
static void migrate(private_ike_mobike_t *this, ike_sa_t *ike_sa)
{
- DESTROY_IF(this->me);
- DESTROY_IF(this->other);
chunk_free(&this->cookie2);
this->ike_sa = ike_sa;
- this->me = NULL;
- this->other = NULL;
if (this->natd)
{
this->natd->task.migrate(&this->natd->task, ike_sa);
@@ -339,8 +388,6 @@ static void migrate(private_ike_mobike_t *this, ike_sa_t *ike_sa)
*/
static void destroy(private_ike_mobike_t *this)
{
- DESTROY_IF(this->me);
- DESTROY_IF(this->other);
chunk_free(&this->cookie2);
if (this->natd)
{
@@ -356,7 +403,7 @@ ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
{
private_ike_mobike_t *this = malloc_thing(private_ike_mobike_t);
- this->public.roam = (void(*)(ike_mobike_t*, host_t *, host_t *))roam;
+ this->public.roam = (void(*)(ike_mobike_t*,bool))roam;
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;
@@ -374,8 +421,8 @@ ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
this->ike_sa = ike_sa;
this->initiator = initiator;
- this->me = NULL;
- this->other = NULL;
+ this->roam = FALSE;
+ this->address = TRUE;
this->cookie2 = chunk_empty;
this->natd = NULL;