aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2016-06-10 18:15:42 +0200
committerTobias Brunner <tobias@strongswan.org>2016-06-10 18:15:42 +0200
commit96b1fab53ce7f7b4b6c5e2a0bb85c3f3f14be62c (patch)
tree1b19c6494e2142a8faacd3c87c8cb67e67d03fc4 /src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
parent436f64d5bcc3946387dd95265d83d8764fe37797 (diff)
parentb52e540f43c8a97ea3343e12a1cc33b6dc3d3fbc (diff)
downloadstrongswan-96b1fab53ce7f7b4b6c5e2a0bb85c3f3f14be62c.tar.bz2
strongswan-96b1fab53ce7f7b4b6c5e2a0bb85c3f3f14be62c.tar.xz
Merge branch 'interface-for-routes'
Changes how the interface for routes installed with policies is determined. In most cases we now use the interface over which we reach the other peer, not the interface on which the local address (or the source IP) is installed. However, that might be the same interface depending on the configuration (i.e. in practice there will often not be a change). Routes are not installed anymore for drop policies and for policies with protocol/port selectors. Fixes #809, #824, #1347.
Diffstat (limited to 'src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c')
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
index bde0e775d..93c2ccccb 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008-2016 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -1502,6 +1502,32 @@ static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
}
/**
+ * get the name of an interface by index (allocated)
+ */
+static char *get_interface_name_by_index(private_kernel_netlink_net_t *this,
+ int index)
+{
+ iface_entry_t *iface;
+ char *name = NULL;
+
+ DBG2(DBG_KNL, "getting iface name for index %d", index);
+
+ this->lock->read_lock(this->lock);
+ if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
+ (void**)&iface, &index) == SUCCESS)
+ {
+ name = strdup(iface->ifname);
+ }
+ this->lock->unlock(this->lock);
+
+ if (!name)
+ {
+ DBG1(DBG_KNL, "unable to get interface name for %d", index);
+ }
+ return name;
+}
+
+/**
* check if an address or net (addr with prefix net bits) is in
* subnet (net with net_len net bits)
*/
@@ -1659,7 +1685,7 @@ static rt_entry_t *parse_route(struct nlmsghdr *hdr, rt_entry_t *route)
*/
static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
int prefix, bool nexthop, host_t *candidate,
- u_int recursion)
+ char **iface, u_int recursion)
{
netlink_buf_t request;
struct nlmsghdr *hdr, *out, *current;
@@ -1861,7 +1887,7 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
if (gtw && !gtw->ip_equals(gtw, dest))
{
route->src_host = get_route(this, gtw, -1, FALSE, candidate,
- recursion + 1);
+ iface, recursion + 1);
}
DESTROY_IF(gtw);
if (route->src_host)
@@ -1879,10 +1905,18 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
enumerator->destroy(enumerator);
if (nexthop)
- { /* nexthop lookup, return gateway if any */
+ { /* nexthop lookup, return gateway and oif if any */
+ if (iface)
+ {
+ *iface = NULL;
+ }
if (best || routes->get_first(routes, (void**)&best) == SUCCESS)
{
addr = host_create_from_chunk(msg->rtm_family, best->gtw, 0);
+ if (iface && route->oif)
+ {
+ *iface = get_interface_name_by_index(this, route->oif);
+ }
}
if (!addr && !match_net)
{ /* fallback to destination address */
@@ -1902,8 +1936,16 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
if (addr)
{
- DBG2(DBG_KNL, "using %H as %s to reach %H/%d", addr,
- nexthop ? "nexthop" : "address", dest, prefix);
+ if (nexthop && iface && *iface)
+ {
+ DBG2(DBG_KNL, "using %H as nexthop and %s as dev to reach %H/%d",
+ addr, *iface, dest, prefix);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "using %H as %s to reach %H/%d", addr,
+ nexthop ? "nexthop" : "address", dest, prefix);
+ }
}
else if (!recursion)
{
@@ -1916,13 +1958,14 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
METHOD(kernel_net_t, get_source_addr, host_t*,
private_kernel_netlink_net_t *this, host_t *dest, host_t *src)
{
- return get_route(this, dest, -1, FALSE, src, 0);
+ return get_route(this, dest, -1, FALSE, src, NULL, 0);
}
METHOD(kernel_net_t, get_nexthop, host_t*,
- private_kernel_netlink_net_t *this, host_t *dest, int prefix, host_t *src)
+ private_kernel_netlink_net_t *this, host_t *dest, int prefix, host_t *src,
+ char **iface)
{
- return get_route(this, dest, prefix, TRUE, src, 0);
+ return get_route(this, dest, prefix, TRUE, src, iface, 0);
}
/**