diff options
author | Martin Willi <martin@revosec.ch> | 2015-01-15 15:05:42 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2015-03-03 13:42:41 +0100 |
commit | 6b57790270fb07c579315c70ecce34f8ad9a4d63 (patch) | |
tree | f3a57502ea8e5c1cf6b08b3be0020acd11ff4873 /src | |
parent | 4dc72f5e575aba18bf8ddfbb6574e07474bc3948 (diff) | |
download | strongswan-6b57790270fb.tar.bz2 strongswan-6b57790270fb.tar.xz |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c | 17 |
1 files changed, 15 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 b8cd3977d..a431e49b7 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; } |