Skip to contentSkip to conversation

add netlink support for Linux

PATCH New Antonio Quartulli 1 participant 11 messages Apr 20, 2018 – May 18, 2018

lore
Share & tools
lore
#0 lore raw

cover add netlink support for Linux

Hi all,

finally this is the first "real" patchset that introduces native netlink support for the Linux platform.

- Description:

At the moment openvpn operates on the tun interface and on the routing table by directly invoking the "ip" command (or ifconfig/route if nettools is selected at compile time).

With this patchset, openvpn would not need to fork new processes to run the "ip" binary any longer, but would directly talk to the kernel by means of the netlink interface.
This means simpler/cleaner code and, possibly, faster execution.

Another important advantage of this change is that the openvpn process will be in charge of directly working with the kernel, thus it can be granted special capabilities so that interfaces/routes operations can be carried out even when running as non-root.

Christian Hesse is working on a follow-up patch to properly allow the above.

This patchset also offers a first step towards a refactoring of the tun.c and route.c code.

The idea moving forward is to drop nettools support once this patchset is merged, but to retain support for ip and the --ifconfig/route-noexec options.

The last patch implements a little framework to test sitnl functionalities. Some functions are actually tested in the framework, but more should be added in the future.

- Git:

This code can also be found on GitHub (based on latest master) at:
https://github.com/ordex/openvpn/tree/sitnl

Regards,

Antonio Quartulli (8):
implement platform generic networking API
implement networking API for iproute2
tun.c: use new networking API to handle tun interface on Linux route.c: use new networking API to handle routing table on Linux introduce sitnl: Simplified Interface To NetLink
configure: don't check for route/ifconfig on linux route.c: use sitnl to implement get_default_gateway_ipv6() unit tests: implement test for sitnl

 configure.ac                               |    5 +-
 src/openvpn/Makefile.am                    |    1 +
 src/openvpn/errlevel.h                     |    1 +
 src/openvpn/networking.h                   |  225 ++++
 src/openvpn/networking_ip.c                |  368 ++++++
 src/openvpn/networking_sitnl.c             | 1206 ++++++++++++++++++++
 src/openvpn/route.c                        |  364 ++----
 src/openvpn/sitnl.h                        |  217 ++++
 src/openvpn/tun.c                          |  199 +---
 tests/Makefile.am                          |    3 +-
 tests/t_net.sh                             |  170 +++
 tests/unit_tests/openvpn/Makefile.am       |   23 +-
 tests/unit_tests/openvpn/test_networking.c |  217 ++++
 13 files changed, 2559 insertions(+), 440 deletions(-)
 create mode 100644 src/openvpn/networking.h
 create mode 100644 src/openvpn/networking_ip.c
 create mode 100644 src/openvpn/networking_sitnl.c
 create mode 100644 src/openvpn/sitnl.h
 create mode 100755 tests/t_net.sh
 create mode 100644 tests/unit_tests/openvpn/test_networking.c
Signature · 1 line
2.17.0
#1 lore raw

PATCH 1/8 implement platform generic networking API

tun.c and route.c contain all the code used by openvpn to manage the tun interface and the routing table on all the supported platforms.

Across the years, this resulted in a longer functions and series of ifdefs.

This patch introduces a new "networking API" which aims at creating a simple abstraction between the tun/route logic and the platform dependent code.

The is API expected to be implemented outside of tun.c/route.c by using platform specific functionalities.

---
 src/openvpn/Makefile.am  |   1 +
 src/openvpn/networking.h | 225 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 226 insertions(+)
 create mode 100644 src/openvpn/networking.h
src/openvpn/Makefile.am +1 -0
index eda08351..c94296d3 100644
@@ -80,6 +80,7 @@ openvpn_SOURCES = \
 	mtu.c mtu.h \
 	mudp.c mudp.h \
 	multi.c multi.h \
+	networking.h \
 	ntlm.c ntlm.h \
 	occ.c occ.h occ-inline.h \
 	openssl_compat.h \
src/openvpn/networking.h new file +225 -0

225 lines not on this page · raw message

Signature · 1 line
2.17.0
#3 lore raw

PATCH 2/8 implement networking API for iproute2

In reply to Antonio Quartulli

iproute2 is the first user of the new networking API and its one of the two currently supported functionalities on Linux (the other being net-tools).

This patch simply copies the current code from tun.c/route.c to networking_ip.c without introducing any funcional change to the code.

---
 src/openvpn/Makefile.am     |   2 +-
 src/openvpn/networking_ip.c | 369 ++++++++++++++++++++++++++++++++++++
 2 files changed, 370 insertions(+), 1 deletion(-)
 create mode 100644 src/openvpn/networking_ip.c
src/openvpn/Makefile.am +1 -1
index c94296d3..6d9cde3e 100644
@@ -80,7 +80,7 @@ openvpn_SOURCES = \
 	mtu.c mtu.h \
 	mudp.c mudp.h \
 	multi.c multi.h \
-	networking.h \
+	networking_ip.c networking.h \
 	ntlm.c ntlm.h \
 	occ.c occ.h occ-inline.h \
 	openssl_compat.h \
src/openvpn/networking_ip.c new file +369 -0

369 lines not on this page · raw message

Signature · 1 line
2.17.0
#5 lore raw

PATCH 3/8 tun.c: use new networking API to handle tun interface on Linux

In reply to Antonio Quartulli

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.

---
 src/openvpn/tun.c | 199 ++++++++++++++--------------------------------
 1 file changed, 58 insertions(+), 141 deletions(-)
src/openvpn/tun.c +58 -141
index 263cacdf..3eec6899 100644
@@ -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
Signature · 1 line
2.17.0
#6 lore raw

PATCH 4/8 route.c: use new networking API to handle routing table on Linux

In reply to Antonio Quartulli

By switching to the networking API (for Linux) openvpn will now use any of the available implementations to handle the routing table.

At the moment only iproute2 is implemented.

---
 src/openvpn/networking_ip.c |   1 -
 src/openvpn/route.c         | 214 ++++++++++--------------------------
 2 files changed, 60 insertions(+), 155 deletions(-)
src/openvpn/networking_ip.c +0 -1
index bfe7b459..0f8a6cd3 100644
@@ -29,7 +29,6 @@
 #include "syshead.h"
 
 #include "networking.h"
-#include "networking_ip.h"
 #include "misc.h"
 #include "socket.h"
 
src/openvpn/route.c +60 -154

349 lines not on this page · raw message

Signature · 1 line
2.17.0
#7 lore raw

PATCH 5/8 introduce sitnl: Simplified Interface To NetLink

In reply to Antonio Quartulli

This patch introduces a tiny netlink interface, optimized for the openvpn use case.

It basically exposes all those operations that are currently handled by directly calling the /sbin/ip command (or even ifconfig/route, if configured).

By using netlink, openvpn won't need to spawn new processes when configuring the tun interface or routes.
This new approach will also allow openvpn to be granted CAP_NET_ADMIN and be able to properly work even though it dropped the root privileges (currently handled via workarounds).

By moving this logic into the sitnl module, tun.c and route.c also benefit from some code simplification

---
 src/openvpn/Makefile.am        |    2 +-
 src/openvpn/errlevel.h         |    1 +
 src/openvpn/networking_sitnl.c | 1206 ++++++++++++++++++++++++++++++++
 src/openvpn/sitnl.h            |  217 ++++++
 4 files changed, 1425 insertions(+), 1 deletion(-)
 create mode 100644 src/openvpn/networking_sitnl.c
 create mode 100644 src/openvpn/sitnl.h
src/openvpn/Makefile.am +1 -1
index 6d9cde3e..2e4c70ef 100644
@@ -80,7 +80,7 @@ openvpn_SOURCES = \
 	mtu.c mtu.h \
 	mudp.c mudp.h \
 	multi.c multi.h \
-	networking_ip.c networking.h \
+	networking_ip.c networking_sitnl.c networking.h \
 	ntlm.c ntlm.h \
 	occ.c occ.h occ-inline.h \
 	openssl_compat.h \
src/openvpn/errlevel.h +1 -0
index 5ca4fa8f..3f2a0f1b 100644
@@ -109,6 +109,7 @@
 
 #define D_LOG_RW             LOGLEV(5, 0,  0)        /* Print 'R' or 'W' to stdout for read/write */
 
+#define D_RTNL               LOGLEV(6, 68, M_DEBUG)  /* show RTNL low level operations */
 #define D_LINK_RW            LOGLEV(6, 69, M_DEBUG)  /* show TCP/UDP reads/writes (terse) */
 #define D_TUN_RW             LOGLEV(6, 69, M_DEBUG)  /* show TUN/TAP reads/writes */
 #define D_TAP_WIN_DEBUG      LOGLEV(6, 69, M_DEBUG)  /* show TAP-Windows driver debug info */
src/openvpn/networking_sitnl.c new file +1206 -0

1,206 lines not on this page · raw message

src/openvpn/sitnl.h new file +217 -0

217 lines not on this page · raw message

Signature · 1 line
2.17.0
#8 lore raw

PATCH 6/8 configure: don't check for route/ifconfig on linux

In reply to Antonio Quartulli
---
 configure.ac | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
configure.ac +2 -1
index 626b4dd4..98be7243 100644
@@ -298,6 +298,7 @@ case "$host" in
 	*-*-linux*)
 		AC_DEFINE([TARGET_LINUX], [1], [Are we running on Linux?])
 		AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["L"], [Target prefix])
+		have_sitnl="yes"
 		;;
 	*-*-solaris*)
 		AC_DEFINE([TARGET_SOLARIS], [1], [Are we running on Solaris?])
@@ -1254,7 +1255,7 @@ if test "${enable_iproute2}" = "yes"; then
 	test -z "${IPROUTE}" && AC_MSG_ERROR([ip utility is required but missing])
 	AC_DEFINE([ENABLE_IPROUTE], [1], [enable iproute2 support])
 else
-	if test "${WIN32}" != "yes"; then
+	if test "${WIN32}" != "yes" -a "${have_sitnl}" != "yes"; then
 		test -z "${ROUTE}" && AC_MSG_ERROR([route utility is required but missing])
 		test -z "${IFCONFIG}" && AC_MSG_ERROR([ifconfig utility is required but missing])
 	fi
Signature · 1 line
2.17.0
#9 lore raw

PATCH 7/8 route.c: use sitnl to implement get_default_gateway_ipv6()

In reply to Antonio Quartulli

get_default_gateway_ipv6() has always been implemented using netlink, however, now that we have sitnl, we can re-use the latter and get rid of the netlink code from route.c.

---
 src/openvpn/networking_ip.c |   2 +-
 src/openvpn/route.c         | 150 +++---------------------------------
 2 files changed, 12 insertions(+), 140 deletions(-)
src/openvpn/networking_ip.c +1 -1
index 0f8a6cd3..7f27f375 100644
@@ -358,7 +358,7 @@ net_route_v4_best_gw(const in_addr_t *dst, int prefixlen,
 
 /*
  * The following function is not implemented in the iproute backend as it
- * already uses netlink in route.c.
+ * uses the sitnl implementation from networking_sitnl.c.
  *
  * int
  * net_route_v6_best_gw(const struct in6_addr *dst, int prefixlen,
src/openvpn/route.c +11 -139

173 lines not on this page · raw message

Signature · 1 line
2.17.0
#10 lore raw

PATCH 8/8 unit tests: implement test for sitnl

In reply to Antonio Quartulli

This patch introduces a new unit test that is not executed by the cmocka framework, but rather used by a new t_net.sh bash script.

The idea behind this test is to ensure that invoking sitnl functions or running iproute commands leads to the same networking (interface and routing table) state.

To achieve this, the t_net.sh script first runs a binary implemented invoking sitnl functions and then takes a "screenshot" of the state. Subsequently a series of iproute commands, expected to mimic exactly the same behaviour as the sitnl functions invoked before, are executed. The final state is then compared with the screenshot previously taken.

If no mismatching is found, the test is passed.

The current unit_test, however, does not cover all the sitnl functionalities and it is expected to be extended in the future.

---
 configure.ac                               |   2 +
 tests/Makefile.am                          |   3 +-
 tests/t_net.sh                             | 170 ++++++++++++++++
 tests/unit_tests/openvpn/Makefile.am       |  23 ++-
 tests/unit_tests/openvpn/test_networking.c | 217 +++++++++++++++++++++
 5 files changed, 410 insertions(+), 5 deletions(-)
 create mode 100755 tests/t_net.sh
 create mode 100644 tests/unit_tests/openvpn/test_networking.c
configure.ac +2 -0
index 98be7243..251cb9a2 100644
@@ -294,9 +294,11 @@ else
 fi
 
 AC_DEFINE_UNQUOTED([TARGET_ALIAS], ["${host}"], [A string representing our host])
+AM_CONDITIONAL([TARGET_LINUX], [false])
 case "$host" in
 	*-*-linux*)
 		AC_DEFINE([TARGET_LINUX], [1], [Are we running on Linux?])
+		AM_CONDITIONAL([TARGET_LINUX], [true])
 		AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["L"], [Target prefix])
 		have_sitnl="yes"
 		;;
tests/Makefile.am +2 -1
index e6803864..67acf7e3 100644
@@ -14,7 +14,8 @@ MAINTAINERCLEANFILES = \
 
 SUBDIRS = unit_tests
 
-test_scripts = t_client.sh
+test_scripts = t_net.sh
+test_scripts += t_client.sh
 test_scripts += t_lpback.sh t_cltsrv.sh
 
 TESTS_ENVIRONMENT = top_srcdir="$(top_srcdir)"
tests/t_net.sh new file +170 -0

170 lines not on this page · raw message

tests/unit_tests/openvpn/Makefile.am +19 -4
index 23d758b7..009ea27c 100644
@@ -1,14 +1,19 @@
 AUTOMAKE_OPTIONS = foreign
 
-check_PROGRAMS=
+test_binaries=
 
 if HAVE_LD_WRAP_SUPPORT
-check_PROGRAMS += argv_testdriver buffer_testdriver
+test_binaries += argv_testdriver buffer_testdriver
 endif
 
-check_PROGRAMS += packet_id_testdriver tls_crypt_testdriver
+test_binaries += packet_id_testdriver tls_crypt_testdriver
 
-TESTS = $(check_PROGRAMS)
+TESTS = $(test_binaries)
+check_PROGRAMS = $(test_binaries)
+
+if TARGET_LINUX
+check_PROGRAMS += networking_testdriver
+endif
 
 openvpn_includedir = $(top_srcdir)/include
 openvpn_srcdir = $(top_srcdir)/src/openvpn
@@ -53,3 +58,13 @@ tls_crypt_testdriver_SOURCES = test_tls_crypt.c mock_msg.c \
 	$(openvpn_srcdir)/otime.c \
 	$(openvpn_srcdir)/packet_id.c \
 	$(openvpn_srcdir)/platform.c
+
+networking_testdriver_CFLAGS = @TEST_CFLAGS@ \
+	-I$(openvpn_includedir) -I$(compat_srcdir) -I$(openvpn_srcdir) \
+	$(OPTIONAL_CRYPTO_CFLAGS)
+networking_testdriver_LDFLAGS = @TEST_LDFLAGS@ -L$(openvpn_srcdir) \
+	$(OPTIONAL_CRYPTO_LIBS)
+networking_testdriver_SOURCES = test_networking.c mock_msg.c \
+	$(openvpn_srcdir)/networking_sitnl.c \
+	$(openvpn_srcdir)/buffer.c \
+	$(openvpn_srcdir)/platform.c
tests/unit_tests/openvpn/test_networking.c new file +217 -0

217 lines not on this page · raw message

Signature · 1 line
2.17.0
#4 lore raw

Re: [Openvpn-devel] [PATCH 2/8] implement networking API for iproute2

In reply to Antonio Quartulli

Hi,

there is one little "open" thing in this patch that I wanted to highlight. See below:

Quoted 2 lines · Antonio Quartulli
(quoted diff) +2 -0
+static struct env_set *es = NULL;
+

.....

Quoted 1 line

+ openvpn_execve_check(&argv, es, S_FATAL, "Linux ip link set failed");

Right now the code initializing the environment set to be passed to openvpn_execve() with NULL.
This means that not ENV is passed to the iproute commands.

This behaviour does not reflect the original one as in the current code we always pass the complete ENV coming from the openvpn context.

This begs two questions:

1) how can we pass the env_set without making the API dependent on that? (this is really just an iproute thing, unlreated to the networking side of things)

2) do we really need to pass the entire ENV to iproute commands?

I understand it is needed for the scripts, but why passing it to these commands too?
Shouldn't we expect them to work by using only the commandline arguments?

Cheers,

Signature · 1 line
Antonio Quartulli
#2 lore raw

Re: [Openvpn-devel] [PATCH 1/8] implement platform generic networking API

In reply to Antonio Quartulli

for the records:

the new networking API has been discussed during our latest community meeting and some changes have been suggested by other developers.

A new patchset will be sent soonish.

Cheers,

Quoted 265 lines · Antonio Quartulli

tun.c and route.c contain all the code used by openvpn to manage the tun interface and the routing table on all the supported platforms.

Across the years, this resulted in a longer functions and series of ifdefs.

This patch introduces a new "networking API" which aims at creating a simple abstraction between the tun/route logic and the platform dependent code.

The is API expected to be implemented outside of tun.c/route.c by using platform specific functionalities.

---
 src/openvpn/Makefile.am  |   1 +
 src/openvpn/networking.h | 225 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 226 insertions(+)
 create mode 100644 src/openvpn/networking.h
src/openvpn/Makefile.am +1 -0
index eda08351..c94296d3 100644
@@ -80,6 +80,7 @@ openvpn_SOURCES = \
 	mtu.c mtu.h \
 	mudp.c mudp.h \
 	multi.c multi.h \
+	networking.h \
 	ntlm.c ntlm.h \
 	occ.c occ.h occ-inline.h \
 	openssl_compat.h \
src/openvpn/networking.h new file +225 -0
new file mode 100644
index 00000000..87157dea
@@ -0,0 +1,225 @@
+/*
+ *  Generic interface to platform specific networking code
+ *
+ *  Copyright (C) 2016-2018 Antonio Quartulli <[email protected]...>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program (see the file COPYING included with this
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef NETWORKING_H_
+#define NETWORKING_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#elif defined(_MSC_VER)
+#include "config-msvc.h"
+#endif
+
+#ifdef TARGET_LINUX
+
+#include <stdbool.h>
+#include <netinet/in.h>
+
+/**
+ * Bring interface up or down.
+ *
+ * @param iface     the interface to modify
+ * @param up        true if the interface has to be brought up, false otherwise
+ *
+ * @return          0 on success, a negative error code otherwise
+ */
+int net_iface_up(const char *iface, bool up);
+
+/**
+ * Set the MTU for an interface
+ *
+ * @param iface     the interface to modify
+ * @param mtru      the new MTU
+ *
+ * @return          0 on success, a negative error code otherwise
+ */
+int net_iface_mtu_set(const char *iface, uint32_t mtu);
+
+/**
+ * Add an IPv4 address to an interface
+ *
+ * @param iface     the interface where the address has to be added
+ * @param addr      the address to add
+ * @param prefixlen the prefix length of the network associated with the address
+ * @param broadcast the broadcast address to configure on the interface
+ *
+ * @return          0 on success, a negative error code otherwise
+ */
+int net_addr_v4_add(const char *iface, const in_addr_t *addr, int prefixlen,
+                    const in_addr_t *broadcast);
+
+/**
+ * Add an IPv6 address to an interface
+ *
+ * @param iface     the interface where the address has to be added
+ * @param addr      the address to add
+ * @param prefixlen the prefix length of the network associated with the address
+ *
+ * @return          0 on success, a negative error code otherwise
+ */
+
+int net_addr_v6_add(const char *iface, const struct in6_addr *addr,
+                    int prefixlen);
+
+/**
+ * Remove an IPv4 from an interface
+ *
+ * @param iface     the interface to remove the address from
+ * @param prefixlen the prefix length of the network associated with the address
+ *
+ * @return          0 on success, a negative error code otherwise
+ */
+int net_addr_v4_del(const char *iface, const in_addr_t *addr, int prefixlen);
+
+/**
+ * Remove an IPv6 from an interface
+ *
+ * @param iface     the interface to remove the address from
+ * @param prefixlen the prefix length of the network associated with the address
+ *
+ * @return          0 on success, a negative error code otherwise
+ */
+int net_addr_v6_del(const char *iface, const struct in6_addr *addr,
+                    int prefixlen);
+
+/**
+ * Add a point-to-point IPv4 address to an interface
+ *
+ * @param iface     the interface where the address has to be added
+ * @param local     the address to add
+ * @param remote    the associated p-t-p remote address
+ *
+ * @return          0 on success, a negative error code otherwise
+ */
+int net_addr_ptp_v4_add(const char *iface, const in_addr_t *local,
+                        const in_addr_t *remote);
+
+/**
+ * Remove a point-to-point IPv4 address from an interface
+ *
+ * @param iface     the interface to remove the address from
+ * @param local     the address to remove
+ * @param remote    the associated p-t-p remote address
+ *
+ * @return          0 on success, a negative error code otherwise
+ */
+int net_addr_ptp_v4_del(const char *iface, const in_addr_t *local,
+                        const in_addr_t *remote);
+
+
+/**
+ * Add a route for an IPv4 address/network
+ *
+ * @param dst       the destination of the route
+ * @param prefixlen the length of the prefix of the destination
+ * @param gw        the gateway for this route
+ * @param iface     the interface for this route (can be NULL)
+ * @param table     the table to add this route to (if 0, will be added to the
+ *                  main table)
+ * @param metric    the metric associated with the route
+ *
+ * @return          0 on success, a negative error code otherwise
+ */
+int net_route_v4_add(const in_addr_t *dst, int prefixlen,
+                     const in_addr_t *gw, const char *iface, uint32_t table,
+                     int metric);
+
+/**
+ * Add a route for an IPv6 address/network
+ *
+ * @param dst       the destination of the route
+ * @param prefixlen the length of the prefix of the destination
+ * @param gw        the gateway for this route
+ * @param iface     the interface for this route (can be NULL)
+ * @param table     the table to add this route to (if 0, will be added to the
+ *                  main table)
+ * @param metric    the metric associated with the route
+ *
+ * @return          0 on success, a negative error code otherwise
+ */
+int net_route_v6_add(const struct in6_addr *dst, int prefixlen,
+                     const struct in6_addr *gw, const char *iface,
+                     uint32_t table, int metric);
+
+/**
+ * Delete a route for an IPv4 address/network
+ *
+ * @param dst       the destination of the route
+ * @param prefixlen the length of the prefix of the destination
+ * @param gw        the gateway for this route
+ * @param iface     the interface for this route (can be NULL)
+ * @param table     the table to add this route to (if 0, will be added to the
+ *                  main table)
+ * @param metric    the metric associated with the route
+ *
+ * @return          0 on success, a negative error code otherwise
+ */
+int net_route_v4_del(const in_addr_t *dst, int prefixlen,
+                     const in_addr_t *gw, const char *iface, uint32_t table,
+                     int metric);
+
+/**
+ * Delete a route for an IPv4 address/network
+ *
+ * @param dst       the destination of the route
+ * @param prefixlen the length of the prefix of the destination
+ * @param gw        the gateway for this route
+ * @param iface     the interface for this route (can be NULL)
+ * @param table     the table to add this route to (if 0, will be added to the
+ *                  main table)
+ * @param metric    the metric associated with the route
+ *
+ * @return          0 on success, a negative error code otherwise
+ */
+int net_route_v6_del(const struct in6_addr *dst, int prefixlen,
+                     const struct in6_addr *gw, const char *iface,
+                     uint32_t table, int metric);
+
+/**
+ * Retrieve the gateway and outgoing interface for the specified IPv4
+ * address/network
+ *
+ * @param dst           The destination to lookup
+ * @param prefixlen     The length of the prefix of the destination
+ * @param best_gw       Location where the retrieved GW has to be stored
+ * @param best_iface    Location where the retrieved interface has to be stored
+ *
+ * @return              0 on success, a negative error code otherwise
+ */
+int net_route_v4_best_gw(const in_addr_t *dst, int prefixlen,
+                         in_addr_t *best_gw, char *best_iface);
+
+/**
+ * Retrieve the gateway and outgoing interface for the specified IPv6
+ * address/network
+ *
+ * @param dst           The destination to lookup
+ * @param prefixlen     The length of the prefix of the destination
+ * @param best_gw       Location where the retrieved GW has to be stored
+ * @param best_iface    Location where the retrieved interface has to be stored
+ *
+ * @return              0 on success, a negative error code otherwise
+ */
+int net_route_v6_best_gw(const struct in6_addr *dst, int prefixlen,
+                         struct in6_addr *best_gw, char *best_iface);
+
+#endif /* TARGET_LINUX */
+
+#endif /* NETWORKING_H_ */
Signature · 1 line
Antonio Quartulli