diff options
author | Tobias Brunner <tobias@strongswan.org> | 2010-10-05 09:36:31 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2010-10-12 11:11:04 +0200 |
commit | 0ac6d2e6586240f11ae43de1cf652989c916ef4e (patch) | |
tree | 6c730f90f6fd1543fc672ea09edabb8bfe5abc8b /src/libhydra/plugins/kernel_netlink | |
parent | cd26eedc5c69402c7aa837a672e04476f11ba388 (diff) | |
download | strongswan-0ac6d2e6586240f11ae43de1cf652989c916ef4e.tar.bz2 strongswan-0ac6d2e6586240f11ae43de1cf652989c916ef4e.tar.xz |
Get source address from interface if the route does not provide one.
Diffstat (limited to 'src/libhydra/plugins/kernel_netlink')
-rw-r--r-- | src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c index 90e97899d..4956ddb90 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c @@ -735,6 +735,42 @@ 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) @@ -925,8 +961,7 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest, continue; } if (rta_src.ptr) - { - /* got a source address */ + { /* got a source address */ new_src = host_create_from_chunk(msg->rtm_family, rta_src, 0); if (new_src) { @@ -943,6 +978,18 @@ 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. */ + new_src = get_interface_address(this, rta_oif, + msg->rtm_family); + if (new_src) + { + DESTROY_IF(src); + src = new_src; + best = msg->rtm_dst_len; + } + continue; + } if (rta_gtw.ptr) { /* no source, but a gateway. Lookup source to reach gtw. */ new_gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0); |