From fb6c8591a35c118df9506b67cb96170a94b29cd9 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Fri, 14 Nov 2008 13:04:22 +0000 Subject: [PATCH] do not use a route if outgoing interface is down other cleanups --- src/charon/kernel/kernel_interface.c | 2 +- .../plugins/kernel_netlink/kernel_netlink_net.c | 135 ++++++++++++--------- 2 files changed, 82 insertions(+), 55 deletions(-) diff --git a/src/charon/kernel/kernel_interface.c b/src/charon/kernel/kernel_interface.c index 2c515b0..fca1496 100644 --- a/src/charon/kernel/kernel_interface.c +++ b/src/charon/kernel/kernel_interface.c @@ -256,7 +256,7 @@ static status_t get_address_by_ts(private_kernel_interface_t *this, } host->destroy(host); - addrs = this->public.create_address_enumerator(&this->public, TRUE, TRUE); + addrs = create_address_enumerator(this, TRUE, TRUE); while (addrs->enumerate(addrs, (void**)&host)) { if (ts->includes(ts, host)) diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_net.c b/src/charon/plugins/kernel_netlink/kernel_netlink_net.c index 6efba85..10858ea 100644 --- a/src/charon/plugins/kernel_netlink/kernel_netlink_net.c +++ b/src/charon/plugins/kernel_netlink/kernel_netlink_net.c @@ -158,7 +158,7 @@ struct private_kernel_netlink_net_t { * priority of used routing table */ int routing_table_prio; - + /** * whether to react to RTM_NEWROUTE or RTM_DELROUTE events */ @@ -207,7 +207,7 @@ static int get_vip_refcount(private_kernel_netlink_net_t *this, host_t* ip) static void fire_roam_job(private_kernel_netlink_net_t *this, bool address) { struct timeval now; - + if (gettimeofday(&now, NULL) == 0) { if (timercmp(&now, &this->last_roam, >)) @@ -701,6 +701,28 @@ static int get_interface_index(private_kernel_netlink_net_t *this, char* name) } /** + * Check if an interface with a given index is up + */ +static bool is_interface_up(private_kernel_netlink_net_t *this, int index) +{ + enumerator_t *ifaces; + iface_entry_t *iface; + bool up = FALSE; + + ifaces = this->ifaces->create_enumerator(this->ifaces); + while (ifaces->enumerate(ifaces, &iface)) + { + if (iface->ifindex == index) + { + up = iface->flags & IFF_UP; + break; + } + } + ifaces->destroy(ifaces); + return up; +} + +/** * check if an address (chunk) addr is in subnet (net with net_len net bits) */ static bool addr_in_subnet(chunk_t addr, chunk_t net, int net_len) @@ -786,6 +808,9 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest, size_t rtasize; chunk_t rta_gtw, rta_src, rta_dst; u_int32_t rta_oif = 0; + enumerator_t *ifaces, *addrs; + iface_entry_t *iface; + addr_entry_t *addr; rta_gtw = rta_src = rta_dst = chunk_empty; msg = (struct rtmsg*)(NLMSG_DATA(current)); @@ -813,71 +838,73 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest, } rta = RTA_NEXT(rta, rtasize); } + if (rta_oif && !is_interface_up(this, rta_oif)) + { /* interface is down */ + goto next; + } + if (this->routing_table != 0 && + msg->rtm_table == this->routing_table) + { /* route is from our own ipsec routing table */ + goto next; + } + if (msg->rtm_dst_len <= best) + { /* not better than a previous one */ + goto next; + } + if (msg->rtm_dst_len != 0 && + (!rta_dst.ptr || + !addr_in_subnet(chunk, rta_dst, msg->rtm_dst_len))) + { /* is not the default route and not contained in our dst */ + goto next; + } - /* apply the route if: - * - it is not from our own ipsec routing table - * - is better than a previous one - * - is the default route or - * - its destination net contains our destination - */ - if ((this->routing_table == 0 ||msg->rtm_table != this->routing_table) - && msg->rtm_dst_len > best - && (msg->rtm_dst_len == 0 || /* default route */ - (rta_dst.ptr && addr_in_subnet(chunk, rta_dst, msg->rtm_dst_len)))) + best = msg->rtm_dst_len; + if (nexthop) { - enumerator_t *ifaces, *addrs; - iface_entry_t *iface; - addr_entry_t *addr; - - best = msg->rtm_dst_len; - if (nexthop) - { - DESTROY_IF(gtw); - gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0); - } - else if (rta_src.ptr) - { + DESTROY_IF(gtw); + gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0); + goto next; + } + if (rta_src.ptr) + { + DESTROY_IF(src); + src = host_create_from_chunk(msg->rtm_family, rta_src, 0); + if (get_vip_refcount(this, src)) + { /* skip source address if it is installed by us */ DESTROY_IF(src); - src = host_create_from_chunk(msg->rtm_family, rta_src, 0); - if (get_vip_refcount(this, src)) - { /* skip source address if it is installed by us */ - DESTROY_IF(src); - src = NULL; - current = NLMSG_NEXT(current, len); - continue; - } + src = NULL; } - else + goto next; + } + /* no source addr, get one from the interfaces */ + ifaces = this->ifaces->create_enumerator(this->ifaces); + while (ifaces->enumerate(ifaces, &iface)) + { + if (iface->ifindex == rta_oif && + iface->flags & IFF_UP) { - /* no source addr, get one from the interfaces */ - ifaces = this->ifaces->create_enumerator(this->ifaces); - while (ifaces->enumerate(ifaces, &iface)) + addrs = iface->addrs->create_enumerator(iface->addrs); + while (addrs->enumerate(addrs, &addr)) { - if (iface->ifindex == rta_oif) + chunk_t ip = addr->ip->get_address(addr->ip); + if ((msg->rtm_dst_len == 0 && + addr->ip->get_family(addr->ip) == + dest->get_family(dest)) || + addr_in_subnet(ip, rta_dst, msg->rtm_dst_len)) { - addrs = iface->addrs->create_enumerator(iface->addrs); - while (addrs->enumerate(addrs, &addr)) - { - chunk_t ip = addr->ip->get_address(addr->ip); - if ((msg->rtm_dst_len == 0 && - addr->ip->get_family(addr->ip) == - dest->get_family(dest)) || - addr_in_subnet(ip, rta_dst, msg->rtm_dst_len)) - { - DESTROY_IF(src); - src = addr->ip->clone(addr->ip); - break; - } - } - addrs->destroy(addrs); + DESTROY_IF(src); + src = addr->ip->clone(addr->ip); + break; } } - ifaces->destroy(ifaces); + addrs->destroy(addrs); } } - /* FALL through */ + ifaces->destroy(ifaces); + goto next; } default: + next: current = NLMSG_NEXT(current, len); continue; } -- 2.7.4