From: Martin Willi Date: Thu, 15 Jan 2015 14:05:42 +0000 (+0100) Subject: kernel-netlink: Respect kernel routing priorities for IKE routes X-Git-Tag: 5.3.0dr1~51 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6b57790270fb07c579315c70ecce34f8ad9a4d63;p=thirdparty%2Fstrongswan.git kernel-netlink: Respect kernel routing priorities for IKE routes If a system uses routing metrics, we should honor them when doing (manual) routing lookups for IKE. When enumerating routes, the kernel reports priorities with the RTA_PRIORITY attribute, not RTA_METRICS. We prefer routes with a lower priority value, and fall back to longest prefix match priorities if the priority value is equal. --- diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c index b8cd3977d1..a431e49b70 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c @@ -1538,6 +1538,7 @@ typedef struct { u_int8_t dst_len; u_int32_t table; u_int32_t oif; + u_int32_t priority; } rt_entry_t; /** @@ -1573,6 +1574,7 @@ static rt_entry_t *parse_route(struct nlmsghdr *hdr, rt_entry_t *route) route->dst_len = msg->rtm_dst_len; route->table = msg->rtm_table; route->oif = 0; + route->priority = 0; } else { @@ -1601,6 +1603,12 @@ static rt_entry_t *parse_route(struct nlmsghdr *hdr, rt_entry_t *route) route->oif = *(u_int32_t*)RTA_DATA(rta); } break; + case RTA_PRIORITY: + if (RTA_PAYLOAD(rta) == sizeof(route->priority)) + { + route->priority = *(u_int32_t*)RTA_DATA(rta); + } + break; #ifdef HAVE_RTA_TABLE case RTA_TABLE: if (RTA_PAYLOAD(rta) == sizeof(route->table)) @@ -1724,11 +1732,16 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest, } route->src_host = src; } - /* insert route, sorted by decreasing network prefix */ + /* insert route, sorted by priority and network prefix */ enumerator = routes->create_enumerator(routes); while (enumerator->enumerate(enumerator, &other)) { - if (route->dst_len > other->dst_len) + if (route->priority < other->priority) + { + break; + } + if (route->priority == other->priority && + route->dst_len > other->dst_len) { break; }