diff options
Diffstat (limited to 'src/libcharon/sa/tasks/ike_mobike.c')
-rw-r--r-- | src/libcharon/sa/tasks/ike_mobike.c | 215 |
1 files changed, 113 insertions, 102 deletions
diff --git a/src/libcharon/sa/tasks/ike_mobike.c b/src/libcharon/sa/tasks/ike_mobike.c index a62886f02..5b12eaaac 100644 --- a/src/libcharon/sa/tasks/ike_mobike.c +++ b/src/libcharon/sa/tasks/ike_mobike.c @@ -17,6 +17,7 @@ #include <string.h> +#include <hydra.h> #include <daemon.h> #include <sa/tasks/ike_natd.h> #include <encoding/payloads/notify_payload.h> @@ -70,6 +71,11 @@ struct private_ike_mobike_t { * include address list update */ bool address; + + /** + * additional addresses got updated + */ + bool addresses_updated; }; /** @@ -153,6 +159,7 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message) host = host_create_from_chunk(family, data, 0); DBG2(DBG_IKE, "got additional MOBIKE peer address: %H", host); this->ike_sa->add_additional_address(this->ike_sa, host); + this->addresses_updated = TRUE; break; } case UPDATE_SA_ADDRESSES: @@ -163,6 +170,7 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message) case NO_ADDITIONAL_ADDRESSES: { flush_additional_addresses(this); + this->addresses_updated = TRUE; break; } case NAT_DETECTION_SOURCE_IP: @@ -193,8 +201,8 @@ static void build_address_list(private_ike_mobike_t *this, message_t *message) int added = 0; me = this->ike_sa->get_my_host(this->ike_sa); - enumerator = charon->kernel_interface->create_address_enumerator( - charon->kernel_interface, FALSE, FALSE); + enumerator = hydra->kernel_interface->create_address_enumerator( + hydra->kernel_interface, FALSE, FALSE); while (enumerator->enumerate(enumerator, (void**)&host)) { if (me->ip_equals(me, host)) @@ -269,32 +277,23 @@ static void update_children(private_ike_mobike_t *this) } /** - * Apply port of old address if it equals new, port otherwise + * Apply the port of the old host, if its ip equals the new, use port otherwise. */ -static void apply_port(private_ike_mobike_t *this, host_t *host, host_t *old, - u_int16_t port) +static void apply_port(host_t *host, host_t *old, u_int16_t port) { if (host->ip_equals(host, old)) { - host->set_port(host, old->get_port(old)); + port = old->get_port(old); } - else + else if (port == IKEV2_UDP_PORT) { - if (port == IKEV2_UDP_PORT) - { - host->set_port(host, IKEV2_NATT_PORT); - } - else - { - host->set_port(host, port); - } + port = IKEV2_NATT_PORT; } + host->set_port(host, port); } -/** - * Implementation of ike_mobike_t.transmit - */ -static void transmit(private_ike_mobike_t *this, packet_t *packet) +METHOD(ike_mobike_t, transmit, void, + private_ike_mobike_t *this, packet_t *packet) { host_t *me, *other, *me_old, *other_old; iterator_t *iterator; @@ -310,11 +309,11 @@ static void transmit(private_ike_mobike_t *this, packet_t *packet) other_old = this->ike_sa->get_other_host(this->ike_sa); ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa); - me = charon->kernel_interface->get_source_addr( - charon->kernel_interface, other_old, NULL); + me = hydra->kernel_interface->get_source_addr( + hydra->kernel_interface, other_old, NULL); if (me) { - apply_port(this, me, me_old, ike_cfg->get_my_port(ike_cfg)); + apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg)); DBG1(DBG_IKE, "checking original path %#H - %#H", me, other_old); copy = packet->clone(packet); copy->set_source(copy, me); @@ -324,8 +323,8 @@ static void transmit(private_ike_mobike_t *this, packet_t *packet) 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, NULL); + me = hydra->kernel_interface->get_source_addr( + hydra->kernel_interface, other, NULL); if (me) { if (me->get_family(me) != other->get_family(other)) @@ -334,9 +333,9 @@ static void transmit(private_ike_mobike_t *this, packet_t *packet) continue; } /* reuse port for an active address, 4500 otherwise */ - apply_port(this, me, me_old, ike_cfg->get_my_port(ike_cfg)); + apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg)); other = other->clone(other); - apply_port(this, other, other_old, ike_cfg->get_other_port(ike_cfg)); + apply_port(other, other_old, ike_cfg->get_other_port(ike_cfg)); DBG1(DBG_IKE, "checking path %#H - %#H", me, other); copy = packet->clone(packet); copy->set_source(copy, me); @@ -347,12 +346,11 @@ static void transmit(private_ike_mobike_t *this, packet_t *packet) iterator->destroy(iterator); } -/** - * Implementation of task_t.process for initiator - */ -static status_t build_i(private_ike_mobike_t *this, message_t *message) +METHOD(task_t, build_i, status_t, + private_ike_mobike_t *this, message_t *message) { - if (message->get_message_id(message) == 1) + if (message->get_exchange_type(message) == IKE_AUTH && + message->get_message_id(message) == 1) { /* only in first IKE_AUTH */ message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty); build_address_list(this, message); @@ -363,7 +361,7 @@ static status_t build_i(private_ike_mobike_t *this, message_t *message) /* we check if the existing address is still valid */ old = message->get_source(message); - new = charon->kernel_interface->get_source_addr(charon->kernel_interface, + new = hydra->kernel_interface->get_source_addr(hydra->kernel_interface, message->get_destination(message), old); if (new) { @@ -379,11 +377,12 @@ static status_t build_i(private_ike_mobike_t *this, message_t *message) } if (this->update) { - message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES, chunk_empty); + message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES, + chunk_empty); build_cookie(this, message); update_children(this); } - if (this->address) + if (this->address && !this->check) { build_address_list(this, message); } @@ -395,12 +394,11 @@ static status_t build_i(private_ike_mobike_t *this, message_t *message) return NEED_MORE; } -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_mobike_t *this, message_t *message) +METHOD(task_t, process_r, status_t, + private_ike_mobike_t *this, message_t *message) { - if (message->get_message_id(message) == 1) + if (message->get_exchange_type(message) == IKE_AUTH && + message->get_message_id(message) == 1) { /* only first IKE_AUTH */ process_payloads(this, message); } @@ -421,14 +419,25 @@ static status_t process_r(private_ike_mobike_t *this, message_t *message) { this->natd->task.process(&this->natd->task, message); } + if (this->addresses_updated && this->ike_sa->has_condition(this->ike_sa, + COND_ORIGINAL_INITIATOR)) + { + host_t *other = message->get_source(message); + host_t *other_old = this->ike_sa->get_other_host(this->ike_sa); + if (!other->equals(other, other_old)) + { + DBG1(DBG_IKE, "remote address changed from %H to %H", other_old, + other); + this->ike_sa->set_other_host(this->ike_sa, other->clone(other)); + this->update = TRUE; + } + } } return NEED_MORE; } -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_mobike_t *this, message_t *message) +METHOD(task_t, build_r, status_t, + private_ike_mobike_t *this, message_t *message) { if (message->get_exchange_type(message) == IKE_AUTH && this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED) @@ -460,10 +469,8 @@ static status_t build_r(private_ike_mobike_t *this, message_t *message) return NEED_MORE; } -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_mobike_t *this, message_t *message) +METHOD(task_t, process_i, status_t, + private_ike_mobike_t *this, message_t *message) { if (message->get_exchange_type(message) == IKE_AUTH && this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED) @@ -536,14 +543,22 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) } if (this->update) { - /* start the update with the same task */ - this->check = FALSE; - this->address = FALSE; - if (this->natd) - { - this->natd->task.destroy(&this->natd->task); + /* use the same task to ... */ + if (!this->ike_sa->has_condition(this->ike_sa, + COND_ORIGINAL_INITIATOR)) + { /*... send an updated list of addresses as responder */ + update_children(this); + this->update = FALSE; + } + else + { /* ... send the update as original initiator */ + if (this->natd) + { + this->natd->task.destroy(&this->natd->task); + } + this->natd = ike_natd_create(this->ike_sa, this->initiator); } - 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; } @@ -553,51 +568,48 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) return NEED_MORE; } -/** - * Implementation of ike_mobike_t.roam. - */ -static void roam(private_ike_mobike_t *this, bool address) +METHOD(ike_mobike_t, addresses, void, + private_ike_mobike_t *this) +{ + this->address = 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, + private_ike_mobike_t *this, bool address) { 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); + this->ike_sa->get_pending_updates(this->ike_sa) + 1); } -/** - * Implementation of ike_mobike_t.dpd - */ -static void dpd(private_ike_mobike_t *this) +METHOD(ike_mobike_t, dpd, void, + private_ike_mobike_t *this) { if (!this->natd) { this->natd = ike_natd_create(this->ike_sa, this->initiator); } - this->address = FALSE; this->ike_sa->set_pending_updates(this->ike_sa, - this->ike_sa->get_pending_updates(this->ike_sa) + 1); + 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) +METHOD(ike_mobike_t, is_probing, bool, + 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) +METHOD(task_t, get_type, task_type_t, + private_ike_mobike_t *this) { return IKE_MOBIKE; } -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_mobike_t *this, ike_sa_t *ike_sa) +METHOD(task_t, migrate, void, + private_ike_mobike_t *this, ike_sa_t *ike_sa) { chunk_free(&this->cookie2); this->ike_sa = ike_sa; @@ -607,10 +619,8 @@ static void migrate(private_ike_mobike_t *this, ike_sa_t *ike_sa) } } -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_mobike_t *this) +METHOD(task_t, destroy, void, + private_ike_mobike_t *this) { chunk_free(&this->cookie2); if (this->natd) @@ -625,35 +635,36 @@ static void destroy(private_ike_mobike_t *this) */ 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.dpd = (void(*)(ike_mobike_t*))dpd; - 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; + private_ike_mobike_t *this; + + INIT(this, + .public = { + .task = { + .get_type = _get_type, + .migrate = _migrate, + .destroy = _destroy, + }, + .addresses = _addresses, + .roam = _roam, + .dpd = _dpd, + .transmit = _transmit, + .is_probing = _is_probing, + }, + .ike_sa = ike_sa, + .initiator = initiator, + ); if (initiator) { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; + this->public.task.build = _build_i; + this->public.task.process = _process_i; } else { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_r; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_r; + this->public.task.build = _build_r; + this->public.task.process = _process_r; } - this->ike_sa = ike_sa; - this->initiator = initiator; - this->update = FALSE; - this->check = FALSE; - this->address = TRUE; - this->cookie2 = chunk_empty; - this->natd = NULL; - return &this->public; } |