diff options
author | Martin Willi <martin@strongswan.org> | 2008-08-18 11:07:26 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2008-08-18 11:07:26 +0000 |
commit | 475814ce5ffe255cb22c21529b43c2fec0e9f384 (patch) | |
tree | d82a0e4eb82ec8aec5ff18a638cd6d8573eff706 /src/charon/kernel | |
parent | 7cdf728586e72d331ccc1bc323c1d766013afdcd (diff) | |
download | strongswan-475814ce5ffe255cb22c21529b43c2fec0e9f384.tar.bz2 strongswan-475814ce5ffe255cb22c21529b43c2fec0e9f384.tar.xz |
roam jobs for routing table changes not fired for virtual IP routes
Diffstat (limited to 'src/charon/kernel')
-rw-r--r-- | src/charon/kernel/kernel_interface.c | 102 |
1 files changed, 66 insertions, 36 deletions
diff --git a/src/charon/kernel/kernel_interface.c b/src/charon/kernel/kernel_interface.c index 96d3001a4..0b9d44806 100644 --- a/src/charon/kernel/kernel_interface.c +++ b/src/charon/kernel/kernel_interface.c @@ -653,6 +653,40 @@ static void fire_roam_job(private_kernel_interface_t *this, bool address) } /** + * get the refcount of a virtual ip + */ +static int get_vip_refcount(private_kernel_interface_t *this, host_t* ip) +{ + iterator_t *ifaces, *addrs; + iface_entry_t *iface; + addr_entry_t *addr; + int refcount = 0; + + ifaces = this->ifaces->create_iterator(this->ifaces, TRUE); + while (ifaces->iterate(ifaces, (void**)&iface)) + { + addrs = iface->addrs->create_iterator(iface->addrs, TRUE); + while (addrs->iterate(addrs, (void**)&addr)) + { + if (addr->virtual && (iface->flags & IFF_UP) && + ip->ip_equals(ip, addr->ip)) + { + refcount = addr->refcount; + break; + } + } + addrs->destroy(addrs); + if (refcount) + { + break; + } + } + ifaces->destroy(ifaces); + + return refcount; +} + +/** * process RTM_NEWLINK/RTM_DELLINK from kernel */ static void process_link(private_kernel_interface_t *this, @@ -868,6 +902,37 @@ static void process_addr(private_kernel_interface_t *this, } /** + * process RTM_NEWROUTE from kernel + */ +static void process_route(private_kernel_interface_t *this, struct nlmsghdr *hdr) +{ + struct rtmsg* msg = (struct rtmsg*)(NLMSG_DATA(hdr)); + struct rtattr *rta = RTM_RTA(msg); + size_t rtasize = RTM_PAYLOAD(hdr); + host_t *host = NULL; + + while(RTA_OK(rta, rtasize)) + { + switch (rta->rta_type) + { + case RTA_PREFSRC: + host = host_create_from_chunk(msg->rtm_family, + chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)), 0); + break; + } + rta = RTA_NEXT(rta, rtasize); + } + if (host) + { + if (!get_vip_refcount(this, host)) + { /* ignore routes added for virtual IPs */ + fire_roam_job(this, FALSE); + } + host->destroy(host); + } +} + +/** * Receives events from kernel */ static job_requeue_t receive_events(private_kernel_interface_t *this) @@ -961,8 +1026,7 @@ static job_requeue_t receive_events(private_kernel_interface_t *this) break; case RTM_NEWROUTE: case RTM_DELROUTE: - /* TODO: ignore route changes due to virtual IPs */ - /* fire_roam_job(this, FALSE); */ + process_route(this, hdr); break; default: break; @@ -1434,40 +1498,6 @@ static int get_interface_index(private_kernel_interface_t *this, host_t* ip) } /** - * get the refcount of a virtual ip - */ -static int get_vip_refcount(private_kernel_interface_t *this, host_t* ip) -{ - iterator_t *ifaces, *addrs; - iface_entry_t *iface; - addr_entry_t *addr; - int refcount = 0; - - ifaces = this->ifaces->create_iterator(this->ifaces, TRUE); - while (ifaces->iterate(ifaces, (void**)&iface)) - { - addrs = iface->addrs->create_iterator(iface->addrs, TRUE); - while (addrs->iterate(addrs, (void**)&addr)) - { - if (addr->virtual && (iface->flags & IFF_UP) && - ip->ip_equals(ip, addr->ip)) - { - refcount = addr->refcount; - break; - } - } - addrs->destroy(addrs); - if (refcount) - { - break; - } - } - ifaces->destroy(ifaces); - - return refcount; -} - -/** * Manages the creation and deletion of ip addresses on an interface. * By setting the appropriate nlmsg_type, the ip will be set or unset. */ |