diff options
Diffstat (limited to 'src/charon/sa/tasks/ike_mobike.c')
-rw-r--r-- | src/charon/sa/tasks/ike_mobike.c | 126 |
1 files changed, 111 insertions, 15 deletions
diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c index 8d4dce36c..d1fc8c695 100644 --- a/src/charon/sa/tasks/ike_mobike.c +++ b/src/charon/sa/tasks/ike_mobike.c @@ -64,7 +64,12 @@ struct private_ike_mobike_t { /** * use task to update addresses */ - bool roam; + bool update; + + /** + * do routability check + */ + bool check; /** * include address list update @@ -140,7 +145,7 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message) } case UPDATE_SA_ADDRESSES: { - this->roam = TRUE; + this->update = TRUE; break; } case NO_ADDITIONAL_ADDRESSES: @@ -225,6 +230,58 @@ static void update_children(private_ike_mobike_t *this) } /** + * Implementation of ike_mobike_t.transmit + */ +static void transmit(private_ike_mobike_t *this, packet_t *packet) +{ + host_t *me, *other, *me_old, *other_old; + iterator_t *iterator; + packet_t *copy; + + if (!this->check) + { + return; + } + + me_old = this->ike_sa->get_my_host(this->ike_sa); + other_old = this->ike_sa->get_other_host(this->ike_sa); + + me = charon->kernel_interface->get_source_addr( + charon->kernel_interface, other_old); + if (me) + { + me->set_port(me, me->ip_equals(me, me_old) ? + me_old->get_port(me_old) : IKEV2_NATT_PORT); + packet->set_source(packet, me); + } + + iterator = this->ike_sa->create_additional_address_iterator(this->ike_sa); + while (iterator->iterate(iterator, (void**)&other)) + { + me = charon->kernel_interface->get_source_addr( + charon->kernel_interface, other); + if (me) + { + /* reuse port for an active address, 4500 otherwise */ + me->set_port(me, me->ip_equals(me, me_old) ? + me_old->get_port(me_old) : IKEV2_NATT_PORT); + other = other->clone(other); + other->set_port(other, other->ip_equals(other, other_old) ? + other_old->get_port(other_old) : IKEV2_NATT_PORT); + DBG1(DBG_IKE, "checking path %#H - %#H", me, other); + copy = packet->clone(packet); + copy->set_source(copy, me); + copy->set_destination(copy, other); + charon->sender->send(charon->sender, copy); + } + } + iterator->destroy(iterator); + me = packet->get_source(packet); + other = packet->get_destination(packet); + DBG1(DBG_IKE, "checking path %#H - %#H", me, other); +} + +/** * Implementation of task_t.process for initiator */ static status_t build_i(private_ike_mobike_t *this, message_t *message) @@ -235,22 +292,22 @@ 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 + else if (message->get_exchange_type(message) == INFORMATIONAL) { - if (this->roam) + if (this->update) { message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES, chunk_empty); + update_children(this); } 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); + if (this->natd) + { + this->natd->task.build(&this->natd->task, message); + } } - return NEED_MORE; } @@ -267,7 +324,7 @@ 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) + if (this->update) { host_t *me, *other; @@ -306,7 +363,7 @@ static status_t build_r(private_ike_mobike_t *this, message_t *message) { this->natd->task.build(&this->natd->task, message); } - if (this->roam) + if (this->update) { update_children(this); } @@ -324,7 +381,6 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) message->get_payload(message, SECURITY_ASSOCIATION)) { process_payloads(this, message); - return SUCCESS; } else if (message->get_exchange_type(message) == INFORMATIONAL) @@ -341,11 +397,40 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) { this->natd->task.process(&this->natd->task, message); } - if (this->roam) + if (this->update) { /* update again, as NAT state may have changed */ update_children(this); } + if (this->check) + { + host_t *me_new, *me_old, *other_new, *other_old; + + me_new = message->get_destination(message); + other_new = message->get_source(message); + me_old = this->ike_sa->get_my_host(this->ike_sa); + other_old = this->ike_sa->get_other_host(this->ike_sa); + + if (!me_new->equals(me_new, me_old)) + { + this->update = TRUE; + this->ike_sa->set_my_host(this->ike_sa, me_new->clone(me_new)); + } + if (!other_new->equals(other_new, other_old)) + { + this->update = TRUE; + this->ike_sa->set_other_host(this->ike_sa, other_new->clone(other_new)); + } + if (this->update) + { + /* start the update with the same task */ + this->check = FALSE; + this->address = FALSE; + this->natd = ike_natd_create(this->ike_sa, this->initiator); + this->ike_sa->set_pending_updates(this->ike_sa, 1); + return NEED_MORE; + } + } return SUCCESS; } return NEED_MORE; @@ -356,13 +441,21 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) */ static void roam(private_ike_mobike_t *this, bool address) { - this->roam = TRUE; + this->check = TRUE; this->address = address; this->ike_sa->set_pending_updates(this->ike_sa, this->ike_sa->get_pending_updates(this->ike_sa) + 1); } /** + * 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) @@ -404,6 +497,8 @@ 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*,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; @@ -421,7 +516,8 @@ ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator) this->ike_sa = ike_sa; this->initiator = initiator; - this->roam = FALSE; + this->update = FALSE; + this->check = FALSE; this->address = TRUE; this->cookie2 = chunk_empty; this->natd = NULL; |