diff options
author | Martin Willi <martin@strongswan.org> | 2008-10-08 08:23:46 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2008-10-08 08:23:46 +0000 |
commit | ce5b17082d1f7d03653f068bc81e9f68e8f738e6 (patch) | |
tree | 188f3f0ce6d0573c2d5eef02e8cc4c6c3518a764 /src | |
parent | e39b271b1791d852b38632a5e9e36911a1f55883 (diff) | |
download | strongswan-ce5b17082d1f7d03653f068bc81e9f68e8f738e6.tar.bz2 strongswan-ce5b17082d1f7d03653f068bc81e9f68e8f738e6.tar.xz |
mobike: try to keep existing source address before switching to another
Diffstat (limited to 'src')
-rw-r--r-- | src/charon/kernel/kernel_interface.c | 7 | ||||
-rw-r--r-- | src/charon/kernel/kernel_interface.h | 6 | ||||
-rw-r--r-- | src/charon/kernel/kernel_net.h | 5 | ||||
-rw-r--r-- | src/charon/plugins/kernel_netlink/kernel_netlink_net.c | 19 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.c | 26 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_mobike.c | 4 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_natd.c | 5 |
7 files changed, 43 insertions, 29 deletions
diff --git a/src/charon/kernel/kernel_interface.c b/src/charon/kernel/kernel_interface.c index 4e56a0762..7a0ffa1da 100644 --- a/src/charon/kernel/kernel_interface.c +++ b/src/charon/kernel/kernel_interface.c @@ -160,9 +160,10 @@ static status_t del_policy(private_kernel_interface_t *this, /** * Implementation of kernel_interface_t.get_source_addr */ -static host_t *get_source_addr(private_kernel_interface_t *this, host_t *dest) +static host_t *get_source_addr(private_kernel_interface_t *this, + host_t *dest, host_t *src) { - return this->net->get_source_addr(this->net, dest); + return this->net->get_source_addr(this->net, dest, src); } /** @@ -329,7 +330,7 @@ kernel_interface_t *kernel_interface_create() this->public.query_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy; this->public.del_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t))del_policy; - this->public.get_source_addr = (host_t*(*)(kernel_interface_t*, host_t *dest))get_source_addr; + this->public.get_source_addr = (host_t*(*)(kernel_interface_t*, host_t *dest, host_t *src))get_source_addr; this->public.get_nexthop = (host_t*(*)(kernel_interface_t*, host_t *dest))get_nexthop; this->public.get_interface = (char*(*)(kernel_interface_t*,host_t*))get_interface; this->public.create_address_enumerator = (enumerator_t*(*)(kernel_interface_t*,bool,bool))create_address_enumerator; diff --git a/src/charon/kernel/kernel_interface.h b/src/charon/kernel/kernel_interface.h index 49faf7c0c..c87e82526 100644 --- a/src/charon/kernel/kernel_interface.h +++ b/src/charon/kernel/kernel_interface.h @@ -235,11 +235,15 @@ struct kernel_interface_t { * * Does a route lookup to get the source address used to reach dest. * The returned host is allocated and must be destroyed. + * An optional src address can be used to check if a route is available + * for given source to dest. * * @param dest target destination address + * @param src source address to check, or NULL * @return outgoing source address, NULL if unreachable */ - host_t* (*get_source_addr)(kernel_interface_t *this, host_t *dest); + host_t* (*get_source_addr)(kernel_interface_t *this, + host_t *dest, host_t *src); /** * Get the next hop for a destination. diff --git a/src/charon/kernel/kernel_net.h b/src/charon/kernel/kernel_net.h index 998fef0f1..525a9de0f 100644 --- a/src/charon/kernel/kernel_net.h +++ b/src/charon/kernel/kernel_net.h @@ -42,11 +42,14 @@ struct kernel_net_t { * * Does a route lookup to get the source address used to reach dest. * The returned host is allocated and must be destroyed. + * An optional src address can be used to check if a route is available + * for given source to dest. * * @param dest target destination address + * @param src source address to check, or NULL * @return outgoing source address, NULL if unreachable */ - host_t* (*get_source_addr)(kernel_net_t *this, host_t *dest); + host_t* (*get_source_addr)(kernel_net_t *this, host_t *dest, host_t *src); /** * Get the next hop for a destination. diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_net.c b/src/charon/plugins/kernel_netlink/kernel_netlink_net.c index ea59541c7..bef136271 100644 --- a/src/charon/plugins/kernel_netlink/kernel_netlink_net.c +++ b/src/charon/plugins/kernel_netlink/kernel_netlink_net.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2005-2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -720,7 +721,7 @@ static bool addr_in_subnet(chunk_t addr, chunk_t net, int net_len) * Get a route: If "nexthop", the nexthop is returned. source addr otherwise. */ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest, - bool nexthop) + bool nexthop, host_t *candidate) { unsigned char request[NETLINK_BUFFER_SIZE]; struct nlmsghdr *hdr, *out, *current; @@ -744,7 +745,12 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest, chunk = dest->get_address(dest); netlink_add_attribute(hdr, RTA_DST, chunk, sizeof(request)); - + if (candidate) + { + chunk = candidate->get_address(candidate); + netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request)); + } + if (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS) { DBG1(DBG_KNL, "getting address to %H failed", dest); @@ -878,9 +884,10 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest, /** * Implementation of kernel_net_t.get_source_addr. */ -static host_t* get_source_addr(private_kernel_netlink_net_t *this, host_t *dest) +static host_t* get_source_addr(private_kernel_netlink_net_t *this, + host_t *dest, host_t *src) { - return get_route(this, dest, FALSE); + return get_route(this, dest, FALSE, src); } /** @@ -888,7 +895,7 @@ static host_t* get_source_addr(private_kernel_netlink_net_t *this, host_t *dest) */ static host_t* get_nexthop(private_kernel_netlink_net_t *this, host_t *dest) { - return get_route(this, dest, TRUE); + return get_route(this, dest, TRUE, NULL); } /** @@ -1284,7 +1291,7 @@ kernel_netlink_net_t *kernel_netlink_net_create() /* public functions */ this->public.interface.get_interface = (char*(*)(kernel_net_t*,host_t*))get_interface_name; this->public.interface.create_address_enumerator = (enumerator_t*(*)(kernel_net_t*,bool,bool))create_address_enumerator; - this->public.interface.get_source_addr = (host_t*(*)(kernel_net_t*, host_t *dest))get_source_addr; + this->public.interface.get_source_addr = (host_t*(*)(kernel_net_t*, host_t *dest, host_t *src))get_source_addr; this->public.interface.get_nexthop = (host_t*(*)(kernel_net_t*, host_t *dest))get_nexthop; this->public.interface.add_ip = (status_t(*)(kernel_net_t*,host_t*,host_t*)) add_ip; this->public.interface.del_ip = (status_t(*)(kernel_net_t*,host_t*)) del_ip; diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 575ae4db7..12f4ebe03 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -1098,7 +1098,7 @@ static void resolve_hosts(private_ike_sa_t *this) { host->destroy(host); host = charon->kernel_interface->get_source_addr( - charon->kernel_interface, this->other_host); + charon->kernel_interface, this->other_host, NULL); if (host) { host->set_port(host, IKEV2_UDP_PORT); @@ -2206,7 +2206,7 @@ static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime) */ static status_t roam(private_ike_sa_t *this, bool address) { - host_t *me, *other; + host_t *src; ike_mobike_t *mobike; switch (this->state) @@ -2230,21 +2230,21 @@ static status_t roam(private_ike_sa_t *this, bool address) return SUCCESS; } - /* get best address pair to use */ - other = this->other_host; - me = charon->kernel_interface->get_source_addr(charon->kernel_interface, - other); - - if (me) + /* keep existing path if possible */ + src = charon->kernel_interface->get_source_addr(charon->kernel_interface, + this->other_host, this->my_host); + if (src) { - if (me->ip_equals(me, this->my_host) && - other->ip_equals(other, this->other_host)) + if (src->ip_equals(src, this->my_host)) { - DBG2(DBG_IKE, "keeping connection path %H - %H", this->other_host, me); - me->destroy(me); + DBG2(DBG_IKE, "keeping connection path %H - %H", + src, this->other_host); + src->destroy(src); return SUCCESS; } - me->destroy(me); + /* old address is not valid anymore, try with new one */ + src->set_port(src, this->my_host->get_port(this->my_host)); + set_my_host(this, src); } /* update addresses with mobike, if supported ... */ diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c index 450149f1c..a5fe74afd 100644 --- a/src/charon/sa/tasks/ike_mobike.c +++ b/src/charon/sa/tasks/ike_mobike.c @@ -277,7 +277,7 @@ static void transmit(private_ike_mobike_t *this, packet_t *packet) other_old = this->ike_sa->get_other_host(this->ike_sa); me = charon->kernel_interface->get_source_addr( - charon->kernel_interface, other_old); + charon->kernel_interface, other_old, NULL); if (me) { me->set_port(me, me->ip_equals(me, me_old) ? @@ -289,7 +289,7 @@ static void transmit(private_ike_mobike_t *this, packet_t *packet) while (iterator->iterate(iterator, (void**)&other)) { me = charon->kernel_interface->get_source_addr( - charon->kernel_interface, other); + charon->kernel_interface, other, NULL); if (me) { if (me->get_family(me) != other->get_family(other)) diff --git a/src/charon/sa/tasks/ike_natd.c b/src/charon/sa/tasks/ike_natd.c index de0cfce1b..b35ddf47f 100644 --- a/src/charon/sa/tasks/ike_natd.c +++ b/src/charon/sa/tasks/ike_natd.c @@ -341,9 +341,8 @@ static status_t build_i(private_ike_natd_t *this, message_t *message) } else { - host = charon->kernel_interface->get_source_addr( - charon->kernel_interface, - this->ike_sa->get_other_host(this->ike_sa)); + host = charon->kernel_interface->get_source_addr(charon->kernel_interface, + this->ike_sa->get_other_host(this->ike_sa), NULL); if (host) { /* 2. */ host->set_port(host, IKEV2_UDP_PORT); |