From 29607690a8dc97c405c358f2631d02d61213e28b Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 5 Oct 2010 18:41:06 +0200 Subject: If a changed route has no src, try to find it via interface. --- .../plugins/kernel_netlink/kernel_netlink_net.c | 85 ++++++++++++---------- 1 file changed, 48 insertions(+), 37 deletions(-) (limited to 'src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c') 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 @@ -222,6 +222,42 @@ static int get_vip_refcount(private_kernel_netlink_net_t *this, host_t* ip) return refcount; } +/** + * 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 */ @@ -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); @@ -734,42 +781,6 @@ static int get_interface_index(private_kernel_netlink_net_t *this, char* name) return ifindex; } -/** - * 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 */ @@ -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) -- cgit v1.2.3