[Openvpn-devel,3/8] tun.c: use new networking API to handle tun interface on Linux

Message ID 20180420111624.7230-4-a@unstable.cc
State Superseded
Headers show
Series
  • add netlink support for Linux
Related show

Commit Message

Antonio Quartulli April 20, 2018, 11:16 a.m.
By switching to the networking API (for Linux) openvpn will
now use any of the available implementations to handle the tun
interface.

At the moment only iproute2 is implemented.

Signed-off-by: Antonio Quartulli <a@unstable.cc>
---
 src/openvpn/tun.c | 199 ++++++++++++++--------------------------------
 1 file changed, 58 insertions(+), 141 deletions(-)

Patch

diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index 263cacdf..3eec6899 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -46,6 +46,7 @@ 
 #include "route.h"
 #include "win32.h"
 #include "block_dns.h"
+#include "networking.h"
 
 #include "memdbg.h"
 
@@ -883,10 +884,12 @@  do_ifconfig(struct tuntap *tt,
     if (tt->did_ifconfig_setup)
     {
         bool tun = false;
+#if !defined(TARGET_LINUX)
         const char *ifconfig_local = NULL;
         const char *ifconfig_remote_netmask = NULL;
         const char *ifconfig_broadcast = NULL;
         const char *ifconfig_ipv6_local = NULL;
+#endif
         bool do_ipv6 = false;
         struct argv argv = argv_new();
 
@@ -898,18 +901,23 @@  do_ifconfig(struct tuntap *tt,
          */
         tun = is_tun_p2p(tt);
 
+#if !defined(TARGET_LINUX)
         /*
          * Set ifconfig parameters
          */
         ifconfig_local = print_in_addr_t(tt->local, 0, &gc);
         ifconfig_remote_netmask = print_in_addr_t(tt->remote_netmask, 0, &gc);
+#endif
 
         if (tt->did_ifconfig_ipv6_setup)
         {
+#if !defined(TARGET_LINUX)
             ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc);
+#endif
             do_ipv6 = true;
         }
 
+#if !defined(TARGET_LINUX)
         /*
          * If TAP-style device, generate broadcast address.
          */
@@ -917,6 +925,7 @@  do_ifconfig(struct tuntap *tt,
         {
             ifconfig_broadcast = print_in_addr_t(tt->broadcast, 0, &gc);
         }
+#endif
 
 #ifdef ENABLE_MANAGEMENT
         if (management)
@@ -933,102 +942,42 @@  do_ifconfig(struct tuntap *tt,
 
 
 #if defined(TARGET_LINUX)
-#ifdef ENABLE_IPROUTE
-        /*
-         * Set the MTU for the device
-         */
-        argv_printf(&argv,
-                    "%s link set dev %s up mtu %d",
-                    iproute_path,
-                    actual,
-                    tun_mtu
-                    );
-        argv_msg(M_INFO, &argv);
-        openvpn_execve_check(&argv, es, S_FATAL, "Linux ip link set failed");
-
-        if (tun)
-        {
-
-            /*
-             * Set the address for the device
-             */
-            argv_printf(&argv,
-                        "%s addr add dev %s local %s peer %s",
-                        iproute_path,
-                        actual,
-                        ifconfig_local,
-                        ifconfig_remote_netmask
-                        );
-            argv_msg(M_INFO, &argv);
-            openvpn_execve_check(&argv, es, S_FATAL, "Linux ip addr add failed");
-        }
-        else
+        if (net_iface_mtu_set(actual, tun_mtu) < 0)
         {
-            argv_printf(&argv,
-                        "%s addr add dev %s %s/%d broadcast %s",
-                        iproute_path,
-                        actual,
-                        ifconfig_local,
-                        netmask_to_netbits2(tt->remote_netmask),
-                        ifconfig_broadcast
-                        );
-            argv_msg(M_INFO, &argv);
-            openvpn_execve_check(&argv, es, S_FATAL, "Linux ip addr add failed");
+            msg(M_FATAL, "Linux can't set mtu (%d) on %s", tun_mtu, actual);
         }
-        if (do_ipv6)
+
+        if (net_iface_up(actual, true) < 0)
         {
-            argv_printf( &argv,
-                         "%s -6 addr add %s/%d dev %s",
-                         iproute_path,
-                         ifconfig_ipv6_local,
-                         tt->netbits_ipv6,
-                         actual
-                         );
-            argv_msg(M_INFO, &argv);
-            openvpn_execve_check(&argv, es, S_FATAL, "Linux ip -6 addr add failed");
+            msg(M_FATAL, "Linux can't bring %s up", actual);
         }
-        tt->did_ifconfig = true;
-#else  /* ifdef ENABLE_IPROUTE */
+
         if (tun)
         {
-            argv_printf(&argv,
-                        "%s %s %s pointopoint %s mtu %d",
-                        IFCONFIG_PATH,
-                        actual,
-                        ifconfig_local,
-                        ifconfig_remote_netmask,
-                        tun_mtu
-                        );
+            if (net_addr_ptp_v4_add(actual, &tt->local,
+                                    &tt->remote_netmask) < 0)
+            {
+                msg(M_FATAL, "Linux can't add IP to TUN interface %s", actual);
+            }
         }
         else
         {
-            argv_printf(&argv,
-                        "%s %s %s netmask %s mtu %d broadcast %s",
-                        IFCONFIG_PATH,
-                        actual,
-                        ifconfig_local,
-                        ifconfig_remote_netmask,
-                        tun_mtu,
-                        ifconfig_broadcast
-                        );
+            if (net_addr_v4_add(actual, &tt->local,
+                                netmask_to_netbits2(tt->remote_netmask),
+                                &tt->remote_netmask) < 0)
+            {
+                msg(M_FATAL, "Linux can't add IP to TAP interface %s", actual);
+            }
         }
-        argv_msg(M_INFO, &argv);
-        openvpn_execve_check(&argv, es, S_FATAL, "Linux ifconfig failed");
         if (do_ipv6)
         {
-            argv_printf(&argv,
-                        "%s %s add %s/%d",
-                        IFCONFIG_PATH,
-                        actual,
-                        ifconfig_ipv6_local,
-                        tt->netbits_ipv6
-                        );
-            argv_msg(M_INFO, &argv);
-            openvpn_execve_check(&argv, es, S_FATAL, "Linux ifconfig inet6 failed");
+            if (net_addr_v6_add(actual, &tt->local_ipv6, tt->netbits_ipv6) < 0)
+            {
+                msg(M_FATAL, "Linux can't add IPv6 to interface %s", actual);
+            }
         }
         tt->did_ifconfig = true;
 
-#endif /*ENABLE_IPROUTE*/
 #elif defined(TARGET_ANDROID)
 
         if (do_ipv6)
@@ -2103,77 +2052,45 @@  tuncfg(const char *dev, const char *dev_type, const char *dev_node, int persist_
 void
 close_tun(struct tuntap *tt)
 {
-    if (tt)
+    if (!tt)
     {
-        if (tt->type != DEV_TYPE_NULL && tt->did_ifconfig)
-        {
-            struct argv argv = argv_new();
-            struct gc_arena gc = gc_new();
+        return;
+    }
 
-#ifdef ENABLE_IPROUTE
-            if (is_tun_p2p(tt))
+    if (tt->type != DEV_TYPE_NULL && tt->did_ifconfig)
+    {
+        int netbits = netmask_to_netbits2(tt->remote_netmask);
+        if (is_tun_p2p(tt))
+        {
+            if (net_addr_ptp_v4_del(tt->actual_name, &tt->local,
+                                    &tt->remote_netmask) < 0)
             {
-                argv_printf(&argv,
-                            "%s addr del dev %s local %s peer %s",
-                            iproute_path,
-                            tt->actual_name,
-                            print_in_addr_t(tt->local, 0, &gc),
-                            print_in_addr_t(tt->remote_netmask, 0, &gc)
-                            );
+                msg(M_WARN, "Linux can't del IP from TUN iface %s",
+                    tt->actual_name);
             }
-            else
+        }
+        else
+        {
+            if (net_addr_v4_del(tt->actual_name, &tt->local, netbits) < 0)
             {
-                argv_printf(&argv,
-                            "%s addr del dev %s %s/%d",
-                            iproute_path,
-                            tt->actual_name,
-                            print_in_addr_t(tt->local, 0, &gc),
-                            netmask_to_netbits2(tt->remote_netmask)
-                            );
+                msg(M_WARN, "Linux can't del IP from TAP iface %s",
+                    tt->actual_name);
             }
-#else  /* ifdef ENABLE_IPROUTE */
-            argv_printf(&argv,
-                        "%s %s 0.0.0.0",
-                        IFCONFIG_PATH,
-                        tt->actual_name
-                        );
-#endif /* ifdef ENABLE_IPROUTE */
-
-            argv_msg(M_INFO, &argv);
-            openvpn_execve_check(&argv, NULL, 0, "Linux ip addr del failed");
+        }
 
-            if (tt->did_ifconfig_ipv6_setup)
+        if (tt->did_ifconfig_ipv6_setup)
+        {
+            if (net_addr_v6_del(tt->actual_name, &tt->local_ipv6,
+                                tt->netbits_ipv6) < 0)
             {
-                const char *ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc);
-
-#ifdef ENABLE_IPROUTE
-                argv_printf(&argv, "%s -6 addr del %s/%d dev %s",
-                            iproute_path,
-                            ifconfig_ipv6_local,
-                            tt->netbits_ipv6,
-                            tt->actual_name
-                            );
-                argv_msg(M_INFO, &argv);
-                openvpn_execve_check(&argv, NULL, 0, "Linux ip -6 addr del failed");
-#else  /* ifdef ENABLE_IPROUTE */
-                argv_printf(&argv,
-                            "%s %s del %s/%d",
-                            IFCONFIG_PATH,
-                            tt->actual_name,
-                            ifconfig_ipv6_local,
-                            tt->netbits_ipv6
-                            );
-                argv_msg(M_INFO, &argv);
-                openvpn_execve_check(&argv, NULL, 0, "Linux ifconfig inet6 del failed");
-#endif
+                msg(M_WARN, "Linux can't del IPv6 from iface %s",
+                    tt->actual_name);
             }
-
-            argv_reset(&argv);
-            gc_free(&gc);
         }
-        close_tun_generic(tt);
-        free(tt);
     }
+
+    close_tun_generic(tt);
+    free(tt);
 }
 
 int