[network-manager-openvpn: 1/4] core/properties: allow custom TUN/TAP device names



commit 67a73b8bb729cf5cb1365f049e21f7894d75636c
Author: Jiří Klimeš <jklimes redhat com>
Date:   Thu Mar 20 16:32:34 2014 +0100

    core/properties: allow custom TUN/TAP device names
    
    OpenVPN offers '--dev' option for specifying interface name. It accepts "tun"
    or "tap", or a custom interface name. The device type (TUN vs. TAP) is either
    guessed from the interface name, or it can be provided with '--dev-type'.
    
    This commit changes the code to accept custom names for '--dev' and introduces
    support for '-dev-type'. The backwards compatibility has been preserved.
    
    Links:
      http://openvpn.net/archive/openvpn-devel/2003-06/msg00000.html
      http://www.depesz.com/2010/12/06/named-interfaces-for-openvpn-and-cisco-vpn/

 properties/import-export.c               |   39 ++++++++++---
 properties/tests/conf/Makefile.am        |    4 +-
 properties/tests/conf/device-notype.ovpn |   26 +++++++++
 properties/tests/conf/device.ovpn        |   27 +++++++++
 properties/tests/test-import-export.c    |   89 +++++++++++++++++++++++++++--
 src/nm-openvpn-service.c                 |   29 ++++++++-
 src/nm-openvpn-service.h                 |    2 +
 7 files changed, 196 insertions(+), 20 deletions(-)
---
diff --git a/properties/import-export.c b/properties/import-export.c
index a4b2560..6b1dad7 100644
--- a/properties/import-export.c
+++ b/properties/import-export.c
@@ -53,6 +53,7 @@
 #define CLIENT_TAG "client"
 #define COMP_TAG "comp-lzo"
 #define DEV_TAG "dev "
+#define DEV_TYPE_TAG "dev-type "
 #define FRAGMENT_TAG "fragment "
 #define IFCONFIG_TAG "ifconfig "
 #define KEY_TAG "key "
@@ -325,12 +326,21 @@ do_import (const char *path, char **lines, GError **error)
                if (!strncmp (*line, DEV_TAG, strlen (DEV_TAG))) {
                        items = get_args (*line + strlen (DEV_TAG), &nitems);
                        if (nitems == 1) {
-                               if (g_str_has_prefix (items[0], "tun")) {
-                                       /* ignore; default is tun */
-                               } else if (g_str_has_prefix (items[0], "tap"))
-                                       nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_TAP_DEV, "yes");
+                               nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_DEV, items[0]);
+                       } else
+                               g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
+
+                       g_strfreev (items);
+                       continue;
+               }
+
+               if (!strncmp (*line, DEV_TYPE_TAG, strlen (DEV_TYPE_TAG))) {
+                       items = get_args (*line + strlen (DEV_TYPE_TAG), &nitems);
+                       if (nitems == 1) {
+                               if (!strcmp (items[0], "tun") || !strcmp (items[0], "tap"))
+                                       nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_DEV_TYPE, 
items[0]);
                                else
-                                       g_warning ("%s: unknown %s option '%s'", __func__, DEV_TAG, *line);
+                                       g_warning ("%s: unknown %s option '%s'", __func__, DEV_TYPE_TAG, 
*line);
                        } else
                                g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
 
@@ -766,8 +776,10 @@ do_export (const char *path, NMConnection *connection, GError **error)
        const char *remote_cert_tls = NULL;
        const char *tls_auth = NULL;
        const char *tls_auth_dir = NULL;
+       const char *device = NULL;
+       const char *device_type = NULL;
+       const char *device_default = "tun";
        gboolean success = FALSE;
-       gboolean device_tun = TRUE;
        gboolean proto_udp = TRUE;
        gboolean use_lzo = FALSE;
        gboolean reneg_exists = FALSE;
@@ -853,9 +865,18 @@ do_export (const char *path, NMConnection *connection, GError **error)
        if (value && !strcmp (value, "yes"))
                proto_udp = FALSE;
 
+       value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_DEV);
+       if (value && strlen (value))
+               device = value;
+
+       value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_DEV_TYPE);
+       if (value && strlen (value))
+               device_type = value;
+
+       /* Read legacy 'tap-dev' property for backwards compatibility. */
        value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_TAP_DEV);
        if (value && !strcmp (value, "yes"))
-               device_tun = FALSE;
+               device_default = "tap";
 
        value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_COMP_LZO);
        if (value && !strcmp (value, "yes"))
@@ -959,7 +980,9 @@ do_export (const char *path, NMConnection *connection, GError **error)
        if (value && strlen (value))
                fprintf (f, FRAGMENT_TAG " %d\n", (int) strtol (value, NULL, 10));
 
-       fprintf (f, "dev %s\n", device_tun ? "tun" : "tap");
+       fprintf (f, "dev %s\n", device ? device : (device_type ? device_type : device_default));
+       if (device_type)
+               fprintf (f, "dev-type %s\n", device_type);
        fprintf (f, "proto %s\n", proto_udp ? "udp" : "tcp");
 
        if (local_ip && remote_ip)
diff --git a/properties/tests/conf/Makefile.am b/properties/tests/conf/Makefile.am
index 7d6e8ea..7d1858a 100644
--- a/properties/tests/conf/Makefile.am
+++ b/properties/tests/conf/Makefile.am
@@ -12,5 +12,7 @@ EXTRA_DIST = \
        httpauthfile \
        proxy-socks.ovpn \
        proxy-http-with-auth.ovpn \
-       keysize.ovpn
+       keysize.ovpn \
+       device.ovpn \
+       device-notype.ovpn
 
diff --git a/properties/tests/conf/device-notype.ovpn b/properties/tests/conf/device-notype.ovpn
new file mode 100644
index 0000000..1236323
--- /dev/null
+++ b/properties/tests/conf/device-notype.ovpn
@@ -0,0 +1,26 @@
+client
+dev tap
+proto tcp
+topology subnet
+remote miami.proxpn.com 443
+resolv-retry infinite
+nobind
+persist-key
+persist-tun
+user openvpn
+group openvpn
+comp-lzo
+tun-mtu 1500
+mssfix 1450
+auth-user-pass
+auth-nocache
+reneg-sec 0
+
+cd /etc/openvpn
+ca CompanyISCA.pem
+cipher AES-256-CBC
+reneg-sec 0
+
+ping 30
+ping-exit 120
+verb 4
diff --git a/properties/tests/conf/device.ovpn b/properties/tests/conf/device.ovpn
new file mode 100644
index 0000000..ffc5898
--- /dev/null
+++ b/properties/tests/conf/device.ovpn
@@ -0,0 +1,27 @@
+client
+dev company0
+dev-type tun
+proto tcp
+topology subnet
+remote miami.proxpn.com 443
+resolv-retry infinite
+nobind
+persist-key
+persist-tun
+user openvpn
+group openvpn
+comp-lzo
+tun-mtu 1500
+mssfix 1450
+auth-user-pass
+auth-nocache
+reneg-sec 0
+
+cd /etc/openvpn
+ca CompanyISCA.pem
+cipher AES-256-CBC
+reneg-sec 0
+
+ping 30
+ping-exit 120
+verb 4
diff --git a/properties/tests/test-import-export.c b/properties/tests/test-import-export.c
index 0232c91..4ab8b1e 100644
--- a/properties/tests/test-import-export.c
+++ b/properties/tests/test-import-export.c
@@ -141,7 +141,7 @@ test_password_import (NMVpnPluginUiInterface *plugin, const char *dir)
 
        /* Data items */
        test_item ("password-import-data", s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE, 
NM_OPENVPN_CONTYPE_PASSWORD);
-       test_item ("password-import-data", s_vpn, NM_OPENVPN_KEY_TAP_DEV, NULL);
+       test_item ("password-import-data", s_vpn, NM_OPENVPN_KEY_DEV, "tun");
        test_item ("password-import-data", s_vpn, NM_OPENVPN_KEY_PROTO_TCP, NULL);
        test_item ("password-import-data", s_vpn, NM_OPENVPN_KEY_COMP_LZO, NULL);
        test_item ("password-import-data", s_vpn, NM_OPENVPN_KEY_RENEG_SECONDS, "0");
@@ -271,7 +271,7 @@ test_tls_import (NMVpnPluginUiInterface *plugin, const char *dir)
 
        /* Data items */
        test_item ("tls-import-data", s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE, NM_OPENVPN_CONTYPE_TLS);
-       test_item ("tls-import-data", s_vpn, NM_OPENVPN_KEY_TAP_DEV, NULL);
+       test_item ("tls-import-data", s_vpn, NM_OPENVPN_KEY_DEV, "tun");
        test_item ("tls-import-data", s_vpn, NM_OPENVPN_KEY_PROTO_TCP, NULL);
        test_item ("tls-import-data", s_vpn, NM_OPENVPN_KEY_COMP_LZO, "yes");
        test_item ("tls-import-data", s_vpn, NM_OPENVPN_KEY_RENEG_SECONDS, NULL);
@@ -386,7 +386,7 @@ test_pkcs12_import (NMVpnPluginUiInterface *plugin, const char *dir)
 
        /* Data items */
        test_item ("pkcs12-import-data", s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE, NM_OPENVPN_CONTYPE_TLS);
-       test_item ("pkcs12-import-data", s_vpn, NM_OPENVPN_KEY_TAP_DEV, NULL);
+       test_item ("pkcs12-import-data", s_vpn, NM_OPENVPN_KEY_DEV, "tun");
        test_item ("pkcs12-import-data", s_vpn, NM_OPENVPN_KEY_PROTO_TCP, NULL);
        test_item ("pkcs12-import-data", s_vpn, NM_OPENVPN_KEY_COMP_LZO, "yes");
        test_item ("pkcs12-import-data", s_vpn, NM_OPENVPN_KEY_RENEG_SECONDS, NULL);
@@ -535,7 +535,7 @@ test_static_key_import (NMVpnPluginUiInterface *plugin, const char *dir)
 
        /* Data items */
        test_item ("static-key-import-data", s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE, 
NM_OPENVPN_CONTYPE_STATIC_KEY);
-       test_item ("static-key-import-data", s_vpn, NM_OPENVPN_KEY_TAP_DEV, NULL);
+       test_item ("static-key-import-data", s_vpn, NM_OPENVPN_KEY_DEV, "tun");
        test_item ("static-key-import-data", s_vpn, NM_OPENVPN_KEY_PROTO_TCP, NULL);
        test_item ("static-key-import-data", s_vpn, NM_OPENVPN_KEY_COMP_LZO, NULL);
        test_item ("static-key-import-data", s_vpn, NM_OPENVPN_KEY_RENEG_SECONDS, NULL);
@@ -757,7 +757,7 @@ test_proxy_http_import (NMVpnPluginUiInterface *plugin, const char *dir)
 
        /* Data items */
        test_item ("proxy-http-import-data", s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE, 
NM_OPENVPN_CONTYPE_PASSWORD);
-       test_item ("proxy-http-import-data", s_vpn, NM_OPENVPN_KEY_TAP_DEV, NULL);
+       test_item ("proxy-http-import-data", s_vpn, NM_OPENVPN_KEY_DEV, "tun");
        test_item ("proxy-http-import-data", s_vpn, NM_OPENVPN_KEY_PROTO_TCP, "yes");
        test_item ("proxy-http-import-data", s_vpn, NM_OPENVPN_KEY_COMP_LZO, NULL);
        test_item ("proxy-http-import-data", s_vpn, NM_OPENVPN_KEY_RENEG_SECONDS, "0");
@@ -839,7 +839,7 @@ test_proxy_http_with_auth_import (NMVpnPluginUiInterface *plugin, const char *di
 
        /* Data items */
        test_item ("proxy-http-with-auth-import-data", s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE, 
NM_OPENVPN_CONTYPE_PASSWORD);
-       test_item ("proxy-http-with-auth-import-data", s_vpn, NM_OPENVPN_KEY_TAP_DEV, NULL);
+       test_item ("proxy-http-with-auth-import-data", s_vpn, NM_OPENVPN_KEY_DEV, "tun");
        test_item ("proxy-http-with-auth-import-data", s_vpn, NM_OPENVPN_KEY_PROTO_TCP, "yes");
        test_item ("proxy-http-with-auth-import-data", s_vpn, NM_OPENVPN_KEY_COMP_LZO, NULL);
        test_item ("proxy-http-with-auth-import-data", s_vpn, NM_OPENVPN_KEY_RENEG_SECONDS, "0");
@@ -881,7 +881,7 @@ test_proxy_socks_import (NMVpnPluginUiInterface *plugin, const char *dir)
 
        /* Data items */
        test_item ("proxy-socks-import-data", s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE, 
NM_OPENVPN_CONTYPE_PASSWORD);
-       test_item ("proxy-socks-import-data", s_vpn, NM_OPENVPN_KEY_TAP_DEV, NULL);
+       test_item ("proxy-socks-import-data", s_vpn, NM_OPENVPN_KEY_DEV, "tun");
        test_item ("proxy-socks-import-data", s_vpn, NM_OPENVPN_KEY_PROTO_TCP, "yes");
        test_item ("proxy-socks-import-data", s_vpn, NM_OPENVPN_KEY_COMP_LZO, NULL);
        test_item ("proxy-socks-import-data", s_vpn, NM_OPENVPN_KEY_RENEG_SECONDS, "0");
@@ -1005,6 +1005,75 @@ test_keysize_export (NMVpnPluginUiInterface *plugin, const char *dir, const char
        g_free (path);
 }
 
+static void
+test_device_import (NMVpnPluginUiInterface *plugin,
+                    const char *detail,
+                    const char *dir,
+                    const char *file,
+                    const char *expected_dev,
+                    const char *expected_devtype)
+{
+       NMConnection *connection;
+       NMSettingVPN *s_vpn;
+
+       connection = get_basic_connection (detail, plugin, dir, file);
+       ASSERT (connection != NULL, detail, "failed to import connection");
+
+       /* VPN setting */
+       s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
+       ASSERT (s_vpn != NULL, detail, "missing 'vpn' setting");
+
+       /* Data items */
+       test_item (detail, s_vpn, NM_OPENVPN_KEY_DEV, expected_dev);
+       test_item (detail, s_vpn, NM_OPENVPN_KEY_DEV_TYPE, expected_devtype);
+
+       g_object_unref (connection);
+}
+
+static void
+test_device_export (NMVpnPluginUiInterface *plugin,
+                    const char *detail,
+                    const char *dir,
+                    const char *tmpdir,
+                    const char *file,
+                    const char *exported_name)
+{
+       NMConnection *connection;
+       NMConnection *reimported;
+       char *path;
+       gboolean success;
+       GError *error = NULL;
+
+       connection = get_basic_connection (detail, plugin, dir, file);
+       ASSERT (connection != NULL, detail, "failed to import connection");
+
+       path = g_build_path ("/", tmpdir, exported_name, NULL);
+       success = nm_vpn_plugin_ui_interface_export (plugin, path, connection, &error);
+       if (!success) {
+               if (!error)
+                       FAIL (detail, "export failed with missing error");
+               else
+                       FAIL (detail, "export failed: %s", error->message);
+       }
+
+       /* Now re-import it and compare the connections to ensure they are the same */
+       reimported = get_basic_connection (detail, plugin, tmpdir, exported_name);
+       (void) unlink (path);
+       ASSERT (reimported != NULL, detail, "failed to re-import connection");
+
+       /* Clear secrets first, since they don't get exported, and thus would
+        * make the connection comparison below fail.
+        */
+       remove_secrets (connection);
+
+       ASSERT (nm_connection_compare (connection, reimported, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
+               detail, "original and reimported connection differ");
+
+       g_object_unref (reimported);
+       g_object_unref (connection);
+       g_free (path);
+}
+
 int main (int argc, char **argv)
 {
        GError *error = NULL;
@@ -1076,6 +1145,12 @@ int main (int argc, char **argv)
        test_keysize_import (plugin, test_dir);
        test_keysize_export (plugin, test_dir, argv[2]);
 
+       test_device_import (plugin, "device-import", test_dir, "device.ovpn", "company0", "tun");
+       test_device_export (plugin, "device-export", test_dir, argv[2], "device.ovpn", "device.ovpntest");
+
+       test_device_import (plugin, "device-import", test_dir, "device-notype.ovpn", "tap", NULL);
+       test_device_export (plugin, "device-export", test_dir, argv[2], "device-notype.ovpn", 
"device-notype.ovpntest");
+
        g_object_unref (plugin);
 
        basename = g_path_get_basename (argv[0]);
diff --git a/src/nm-openvpn-service.c b/src/nm-openvpn-service.c
index f2f013c..84968e8 100644
--- a/src/nm-openvpn-service.c
+++ b/src/nm-openvpn-service.c
@@ -124,6 +124,8 @@ static ValidProperty valid_properties[] = {
        { NM_OPENVPN_KEY_TA,                   G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_TA_DIR,               G_TYPE_INT, 0, 1, FALSE },
        { NM_OPENVPN_KEY_TAP_DEV,              G_TYPE_BOOLEAN, 0, 0, FALSE },
+       { NM_OPENVPN_KEY_DEV,                  G_TYPE_STRING, 0, 0, FALSE },
+       { NM_OPENVPN_KEY_DEV_TYPE,             G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_TLS_REMOTE,           G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_REMOTE_CERT_TLS,      G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_TUNNEL_MTU,           G_TYPE_INT, 0, G_MAXINT, FALSE },
@@ -955,11 +957,30 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
 
        add_openvpn_arg (args, "--nobind");
 
-       /* Device, either tun or tap */
+       /* Device and device type, defaults to tun */
+       tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_DEV);
+       tmp2 = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_DEV_TYPE);
+       tmp3 = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_TAP_DEV);
        add_openvpn_arg (args, "--dev");
-       tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_TAP_DEV);
-       dev_type_is_tap = !g_strcmp0 (tmp, "yes");
-       add_openvpn_arg (args, dev_type_is_tap ? "tap" : "tun");
+       if (tmp) {
+               add_openvpn_arg (args, tmp);
+               dev_type_is_tap = g_str_has_prefix (tmp, "tap");
+       } else if (tmp2) {
+               add_openvpn_arg (args, tmp2);
+       } else if (tmp3 && !strcmp (tmp3, "yes")) {
+               add_openvpn_arg (args, "tap");
+               dev_type_is_tap = TRUE;
+       } else {
+               add_openvpn_arg (args, "tun");
+               dev_type_is_tap = FALSE;
+       }
+
+       /* Add '--dev-type' if the type was explicitly set */
+       if (tmp2) {
+               add_openvpn_arg (args, "--dev-type");
+               add_openvpn_arg (args, tmp2);
+               dev_type_is_tap = (g_strcmp0 (tmp2, "tap") == 0);
+       }
 
        /* Protocol, either tcp or udp */
        add_openvpn_arg (args, "--proto");
diff --git a/src/nm-openvpn-service.h b/src/nm-openvpn-service.h
index 09e7e63..5493cf5 100644
--- a/src/nm-openvpn-service.h
+++ b/src/nm-openvpn-service.h
@@ -66,6 +66,8 @@
 #define NM_OPENVPN_KEY_TUNNEL_MTU "tunnel-mtu"
 #define NM_OPENVPN_KEY_USERNAME "username"
 #define NM_OPENVPN_KEY_TAP_DEV "tap-dev"
+#define NM_OPENVPN_KEY_DEV "dev"
+#define NM_OPENVPN_KEY_DEV_TYPE "dev-type"
 #define NM_OPENVPN_KEY_TLS_REMOTE "tls-remote"
 #define NM_OPENVPN_KEY_REMOTE_CERT_TLS "remote-cert-tls"
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]