aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2010-10-05 18:41:06 +0200
committerTobias Brunner <tobias@strongswan.org>2010-10-12 11:11:04 +0200
commit29607690a8dc97c405c358f2631d02d61213e28b (patch)
tree510c32546484e75b8016f000fc4f065d175f96a9 /src
parent0ac6d2e6586240f11ae43de1cf652989c916ef4e (diff)
downloadstrongswan-29607690a8dc97c405c358f2631d02d61213e28b.tar.bz2
strongswan-29607690a8dc97c405c358f2631d02d61213e28b.tar.xz
If a changed route has no src, try to find it via interface.
Diffstat (limited to 'src')
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c85
1 files changed, 48 insertions, 37 deletions
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
index 4956ddb90..d6fb21c58 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
@@ -223,6 +223,42 @@ static int get_vip_refcount(private_kernel_netlink_net_t *this, host_t* ip)
}
/**
+ * get the first non-virtual ip address on the given interface.
+ * returned host is a clone, has to be freed by caller.
+ */
+static host_t *get_interface_address(private_kernel_netlink_net_t *this,
+ int ifindex, int family)
+{
+ enumerator_t *ifaces, *addrs;
+ iface_entry_t *iface;
+ addr_entry_t *addr;
+ host_t *ip = NULL;
+
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ if (iface->ifindex == ifindex)
+ {
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, &addr))
+ {
+ if (!addr->virtual && addr->ip->get_family(addr->ip) == family)
+ {
+ ip = addr->ip->clone(addr->ip);
+ break;
+ }
+ }
+ addrs->destroy(addrs);
+ break;
+ }
+ }
+ ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
+ return ip;
+}
+
+/**
* callback function that raises the delayed roam event
*/
static job_requeue_t roam_event(uintptr_t address)
@@ -483,6 +519,7 @@ static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *h
struct rtmsg* msg = (struct rtmsg*)(NLMSG_DATA(hdr));
struct rtattr *rta = RTM_RTA(msg);
size_t rtasize = RTM_PAYLOAD(hdr);
+ u_int32_t rta_oif = 0;
host_t *host = NULL;
/* ignore routes added by us */
@@ -499,9 +536,19 @@ static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *h
host = host_create_from_chunk(msg->rtm_family,
chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)), 0);
break;
+ case RTA_OIF:
+ if (RTA_PAYLOAD(rta) == sizeof(rta_oif))
+ {
+ rta_oif = *(u_int32_t*)RTA_DATA(rta);
+ }
+ break;
}
rta = RTA_NEXT(rta, rtasize);
}
+ if (!host && rta_oif)
+ {
+ host = get_interface_address(this, rta_oif, msg->rtm_family);
+ }
if (host)
{
this->mutex->lock(this->mutex);
@@ -735,42 +782,6 @@ static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
}
/**
- * get the first non-virtual ip address on the given interface.
- * returned host is a clone, has to be freed by caller.
- */
-static host_t *get_interface_address(private_kernel_netlink_net_t *this,
- int ifindex, int family)
-{
- enumerator_t *ifaces, *addrs;
- iface_entry_t *iface;
- addr_entry_t *addr;
- host_t *ip = NULL;
-
- this->mutex->lock(this->mutex);
- ifaces = this->ifaces->create_enumerator(this->ifaces);
- while (ifaces->enumerate(ifaces, &iface))
- {
- if (iface->ifindex == ifindex)
- {
- addrs = iface->addrs->create_enumerator(iface->addrs);
- while (addrs->enumerate(addrs, &addr))
- {
- if (!addr->virtual && addr->ip->get_family(addr->ip) == family)
- {
- ip = addr->ip->clone(addr->ip);
- break;
- }
- }
- addrs->destroy(addrs);
- break;
- }
- }
- ifaces->destroy(ifaces);
- this->mutex->unlock(this->mutex);
- return ip;
-}
-
-/**
* Check if an interface with a given index is up
*/
static bool is_interface_up(private_kernel_netlink_net_t *this, int index)
@@ -979,7 +990,7 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
continue;
}
if (rta_oif)
- { /* no source, but an interface. Get address from it. */
+ { /* no src or gtw, but an interface. Get address from it. */
new_src = get_interface_address(this, rta_oif,
msg->rtm_family);
if (new_src)