]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
kernel-net: Let get_nexthop() return an optional interface name
authorTobias Brunner <tobias@strongswan.org>
Fri, 11 Mar 2016 17:54:31 +0000 (18:54 +0100)
committerTobias Brunner <tobias@strongswan.org>
Fri, 10 Jun 2016 11:54:18 +0000 (13:54 +0200)
The returned name should be the interface over which the destination
address/net is reachable.

src/libcharon/kernel/kernel_interface.c
src/libcharon/kernel/kernel_interface.h
src/libcharon/kernel/kernel_net.h
src/libcharon/plugins/kernel_iph/kernel_iph_net.c
src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c

index 0a0081c2231d9b6e1b075342518fcd30d672954a..7b39a020c82ab1f4013b9304f7556e2c2a0bd5ae 100644 (file)
@@ -524,13 +524,14 @@ METHOD(kernel_interface_t, get_source_addr, host_t*,
 }
 
 METHOD(kernel_interface_t, get_nexthop, host_t*,
-       private_kernel_interface_t *this, host_t *dest, int prefix, host_t *src)
+       private_kernel_interface_t *this, host_t *dest, int prefix, host_t *src,
+       char **iface)
 {
        if (!this->net)
        {
                return NULL;
        }
-       return this->net->get_nexthop(this->net, dest, prefix, src);
+       return this->net->get_nexthop(this->net, dest, prefix, src, iface);
 }
 
 METHOD(kernel_interface_t, get_interface, bool,
index 50f6d982940eb554e7f9f8b07b6ed1ecff9ed625..225b40932a3ea7f9ac004cd5628619ad9a3483d7 100644 (file)
@@ -285,10 +285,12 @@ struct kernel_interface_t {
         * @param dest                  target destination address
         * @param prefix                prefix length if dest is a subnet, -1 for auto
         * @param src                   source address to check, or NULL
+        * @param[out] iface    allocated name of the interface to reach dest, if
+        *                                              available (optional)
         * @return                              next hop address, NULL if unreachable
         */
        host_t* (*get_nexthop)(kernel_interface_t *this, host_t *dest,
-                                                  int prefix, host_t *src);
+                                                  int prefix, host_t *src, char **iface);
 
        /**
         * Get the interface name of a local address. Interfaces that are down or
index 4f3063deb3c5152e1872ab9f59d2f1347be6d33b..1d78d6edd7691535057551cc3de4593c602dd838 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Copyright (C) 2008-2012 Tobias Brunner
+ * Copyright (C) 2008-2016 Tobias Brunner
  * Copyright (C) 2007 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
@@ -88,10 +88,12 @@ struct kernel_net_t {
         * @param dest                  target destination address
         * @param prefix                prefix length if dest is a subnet, -1 for auto
         * @param src                   source address to check, or NULL
+        * @param[out] iface    allocated name of the interface to reach dest, if
+        *                                              available (optional)
         * @return                              next hop address, NULL if unreachable
         */
        host_t* (*get_nexthop)(kernel_net_t *this, host_t *dest, int prefix,
-                                                  host_t *src);
+                                                  host_t *src, char **iface);
 
        /**
         * Get the interface name of a local address. Interfaces that are down or
index 3633213f3d9ee6899315c2f489d0da57b25b4f5a..efeb9804575ee3cda37b42b15d00277e01d17da9 100644 (file)
@@ -562,7 +562,8 @@ METHOD(kernel_net_t, get_source_addr, host_t*,
 }
 
 METHOD(kernel_net_t, get_nexthop, host_t*,
-       private_kernel_iph_net_t *this, host_t *dest, int prefix, host_t *src)
+       private_kernel_iph_net_t *this, host_t *dest, int prefix, host_t *src,
+       char **iface)
 {
        MIB_IPFORWARD_ROW2 route;
        SOCKADDR_INET best, *sai_dst, *sai_src = NULL;
@@ -592,6 +593,10 @@ METHOD(kernel_net_t, get_nexthop, host_t*,
        {
                if (!nexthop->is_anyaddr(nexthop))
                {
+                       if (iface)
+                       {
+                               *iface = NULL;
+                       }
                        return nexthop;
                }
                nexthop->destroy(nexthop);
index f1340320ad4e7c2d20d46d11de4b3546623406bd..77e37e249b89ee02f6e393b4633d11f0f50cff9d 100644 (file)
@@ -308,7 +308,7 @@ static void add_exclude_route(private_kernel_libipsec_ipsec_t *this,
        if (!route->exclude)
        {
                DBG2(DBG_KNL, "installing new exclude route for %H src %H", dst, src);
-               gtw = charon->kernel->get_nexthop(charon->kernel, dst, -1, NULL);
+               gtw = charon->kernel->get_nexthop(charon->kernel, dst, -1, NULL, NULL);
                if (gtw)
                {
                        char *if_name = NULL;
@@ -434,7 +434,8 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
        );
 #ifndef __linux__
        /* on Linux we cant't install a gateway */
-       route->gateway = charon->kernel->get_nexthop(charon->kernel, dst, -1, src);
+       route->gateway = charon->kernel->get_nexthop(charon->kernel, dst, -1, src,
+                                                                                                NULL);
 #endif
 
        if (policy->route)
index e78e13e40815dbc900c7c694cd098f3a0d14c8b8..be0756d6ffb0f3450dbe00bb6bfb42e92f2dc963 100644 (file)
@@ -2320,14 +2320,14 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
                        if (!ipsec->src->is_anyaddr(ipsec->src))
                        {
                                route->gateway = charon->kernel->get_nexthop(charon->kernel,
-                                                                                                       ipsec->src, -1, ipsec->dst);
+                                                                                       ipsec->src, -1, ipsec->dst, NULL);
                        }
                        else
                        {       /* for shunt policies */
                                iface = xfrm2host(policy->sel.family, &policy->sel.saddr, 0);
                                route->gateway = charon->kernel->get_nexthop(charon->kernel,
                                                                                                iface, policy->sel.prefixlen_s,
-                                                                                               route->src_ip);
+                                                                                               route->src_ip, NULL);
                                iface->destroy(iface);
                        }
                        route->dst_net = chunk_alloc(policy->sel.family == AF_INET ? 4 : 16);
index bde0e775d1e64269a6c8b593f9c15663839999fd..e9308690fb8962084013ede1dbcfae8f135627a8 100644 (file)
@@ -1659,7 +1659,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 +1861,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)
@@ -1880,6 +1880,10 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
 
        if (nexthop)
        {       /* nexthop lookup, return gateway 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);
@@ -1916,13 +1920,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);
 }
 
 /**
index a0fd42995419a7ce7d117c94c046872d37328879..d54a96eb50d610bebc1e50aff8395f7384fdc83c 100644 (file)
@@ -2199,7 +2199,7 @@ static void add_exclude_route(private_kernel_pfkey_ipsec_t *this,
        if (!route->exclude)
        {
                DBG2(DBG_KNL, "installing new exclude route for %H src %H", dst, src);
-               gtw = charon->kernel->get_nexthop(charon->kernel, dst, -1, NULL);
+               gtw = charon->kernel->get_nexthop(charon->kernel, dst, -1, NULL, NULL);
                if (gtw)
                {
                        char *if_name = NULL;
@@ -2315,7 +2315,7 @@ static bool install_route(private_kernel_pfkey_ipsec_t *this,
        if (!dst->is_anyaddr(dst))
        {
                route->gateway = charon->kernel->get_nexthop(charon->kernel, dst, -1,
-                                                                                                        src);
+                                                                                                        src, NULL);
 
                /* if the IP is virtual, we install the route over the interface it has
                 * been installed on. Otherwise we use the interface we use for IKE, as
@@ -2329,7 +2329,7 @@ static bool install_route(private_kernel_pfkey_ipsec_t *this,
        {       /* for shunt policies */
                route->gateway = charon->kernel->get_nexthop(charon->kernel,
                                                                                        policy->src.net, policy->src.mask,
-                                                                                       route->src_ip);
+                                                                                       route->src_ip, NULL);
 
                /* we don't have a source address, use the address we found */
                src = route->src_ip;
index 5ab39bbfec282ea050bea4c795bc0b0876066bf6..b2b6d9758d3e5d3001831e81b22901d7c30f1122 100644 (file)
@@ -1684,8 +1684,13 @@ METHOD(kernel_net_t, get_source_addr, host_t*,
 }
 
 METHOD(kernel_net_t, get_nexthop, host_t*,
-       private_kernel_pfroute_net_t *this, host_t *dest, int prefix, host_t *src)
+       private_kernel_pfroute_net_t *this, host_t *dest, int prefix, host_t *src,
+       char **iface)
 {
+       if (iface)
+       {
+               *iface = NULL;
+       }
        return get_route(this, TRUE, dest, src);
 }
 
index c12d38430f50d9cc1e8148102d354f9617499995..6ad26b72fc83b05016b79493d0923cc73970457c 100644 (file)
@@ -1489,7 +1489,7 @@ static bool manage_route(private_kernel_wfp_ipsec_t *this,
                dst->destroy(dst);
                return FALSE;
        }
-       gtw = charon->kernel->get_nexthop(charon->kernel, remote, -1, local);
+       gtw = charon->kernel->get_nexthop(charon->kernel, remote, -1, local, NULL);
        if (add)
        {
                done = install_route(this, dst, mask, src, gtw);