[NetworkManager-openvpn/th/rework-detect-version] service: rework detection of openvpn version




commit b7fed633f733399405e2f2d231d71b9db435832a
Author: Thomas Haller <thaller redhat com>
Date:   Fri Sep 30 16:31:08 2022 +0200

    service: rework detection of openvpn version
    
    Don't only detect a few enum values, instead try to parse the version
    number (at least, as must as we care about).
    
    The enums are not flexible enough and require code changes to support a
    new version.

 src/nm-openvpn-service.c | 103 ++++++++++++++++++++++++++++-------------------
 1 file changed, 62 insertions(+), 41 deletions(-)
---
diff --git a/src/nm-openvpn-service.c b/src/nm-openvpn-service.c
index c5c6eee..609e44e 100644
--- a/src/nm-openvpn-service.c
+++ b/src/nm-openvpn-service.c
@@ -85,13 +85,19 @@ NMOpenvpnPlugin *nm_openvpn_plugin_new (const char *bus_name);
 
 /*****************************************************************************/
 
-typedef enum {
-       OPENVPN_BINARY_VERSION_INVALID,
-       OPENVPN_BINARY_VERSION_UNKNOWN,
-       OPENVPN_BINARY_VERSION_2_3_OR_OLDER,
-       OPENVPN_BINARY_VERSION_2_4_OR_OLDER,
-       OPENVPN_BINARY_VERSION_2_4_OR_NEWER,
-} OpenvpnBinaryVersion;
+#define OPENVPN_BINARY_VERSION_MAX     999999u
+#define OPENVPN_BINARY_VERSION_UNKNOWN (OPENVPN_BINARY_VERSION_MAX+1u)
+#define OPENVPN_BINARY_VERSION_INVALID (OPENVPN_BINARY_VERSION_MAX+2u)
+
+static guint
+_openvpn_binary_version (guint x, guint y, guint z)
+{
+       nm_assert(x <= 99);
+       nm_assert(y <= 99);
+       nm_assert(z <= 99);
+
+       return ((x * 100u + y) * 100u) + z;
+}
 
 typedef struct {
        GPid pid;
@@ -530,13 +536,15 @@ openvpn_binary_find_exepath (void)
        return NULL;
 }
 
-static OpenvpnBinaryVersion
+static guint
 openvpn_binary_detect_version (const char *exepath)
 {
        gs_free char *s_stdout = NULL;
        const char *s;
        int exit_code;
-       int n;
+       guint v_x;
+       guint v_y;
+       guint v_z;
 
        g_return_val_if_fail (exepath && exepath[0] == '/', OPENVPN_BINARY_VERSION_UNKNOWN);
 
@@ -569,42 +577,55 @@ openvpn_binary_detect_version (const char *exepath)
        if (!g_ascii_isdigit (s[0]))
                return OPENVPN_BINARY_VERSION_UNKNOWN;
 
-       n = 0;
+       v_x = 2;
+
+       v_y = 0;
        do {
-               if (n > G_MAXINT / 100)
+               if (v_y > G_MAXINT / 100)
                        return OPENVPN_BINARY_VERSION_UNKNOWN;
-               n = (n * 10) + (s[0] - '0');
+               v_y = (v_y * 10) + (s[0] - '0');
        } while (g_ascii_isdigit ((++s)[0]));
+       if (v_y > 99)
+               return OPENVPN_BINARY_VERSION_UNKNOWN;
 
-       if (n <= 3)
-               return OPENVPN_BINARY_VERSION_2_3_OR_OLDER;
-       if (n <= 4)
-               return OPENVPN_BINARY_VERSION_2_4_OR_OLDER;
+       v_z = 0;
+       if (s[0] == '.') {
+               s++;
+               do {
+                       if (v_z > G_MAXINT / 100)
+                               break;
+                       v_z = (v_z * 10) + (s[0] - '0');
+               } while (g_ascii_isdigit ((++s)[0]));
+       }
+       if (v_z > 99)
+               v_z = 0;
 
-       return OPENVPN_BINARY_VERSION_2_4_OR_NEWER;
+       return _openvpn_binary_version (v_x, v_y, v_z);
 }
 
-static OpenvpnBinaryVersion
-openvpn_binary_detect_version_cached (const char *exepath, OpenvpnBinaryVersion *cached)
+static guint
+openvpn_binary_detect_version_cached (const char *exepath, guint *cached)
 {
-       if (G_UNLIKELY (*cached == OPENVPN_BINARY_VERSION_INVALID)) {
-               const char *str;
-
-               *cached = openvpn_binary_detect_version (exepath);
-               switch (*cached) {
-               case OPENVPN_BINARY_VERSION_2_3_OR_OLDER:
-                       str = "2.3 or older";
-                       break;
-               case OPENVPN_BINARY_VERSION_2_4_OR_NEWER:
-                       str = "2.4 or newer";
-                       break;
-               default:
-                       str = "unknown";
-                       break;
+       guint v_x;
+       guint v_y;
+       guint v_z;
+       guint v;
+
+       v = *cached;
+       if (G_UNLIKELY (v == OPENVPN_BINARY_VERSION_INVALID)) {
+               v = openvpn_binary_detect_version (exepath);
+               if (v >= OPENVPN_BINARY_VERSION_UNKNOWN) {
+                       *cached = OPENVPN_BINARY_VERSION_UNKNOWN;
+                       _LOGI ("detected openvpn version UNKNOWN, assume max");
+               } else {
+                       *cached = v;
+                       v_z = v % 100u;
+                       v_y = (v % 10000u) / 100u;
+                       v_x = (v % 1000000u) / 10000u;
+                       _LOGI ("detected openvpn version %u.%u.%u", v_x, v_y, v_z);
                }
-               _LOGI ("detected openvpn version %s", str);
        }
-       return *cached;
+       return v;
 }
 
 /*****************************************************************************/
@@ -1352,7 +1373,7 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
        NMSettingVpn *s_vpn;
        const char *connection_type;
        gint64 v_int64;
-       OpenvpnBinaryVersion openvpn_binary_version = OPENVPN_BINARY_VERSION_INVALID;
+       guint openvpn_binary_version = OPENVPN_BINARY_VERSION_INVALID;
        guint num_remotes = 0;
        gs_free char *cmd_log = NULL;
        NMOvpnComp comp;
@@ -1547,7 +1568,7 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
        openvpn_binary_detect_version_cached (openvpn_binary, &openvpn_binary_version);
 
        if (nmovpn_arg_is_set (allow_compression)) {
-               if (openvpn_binary_version == OPENVPN_BINARY_VERSION_2_4_OR_OLDER) {
+               if (openvpn_binary_version < _openvpn_binary_version (2, 5, 0)) {
                        _LOGW ("\"allow-compression\" is only supported in OpenVPN 2.5 and later versions");
                } else {
                        args_add_strv (args, "--allow-compression", allow_compression);
@@ -1559,7 +1580,7 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
                case NMOVPN_COMP_DISABLED:
                        break;
                case NMOVPN_COMP_LZO:
-                       if (openvpn_binary_version == OPENVPN_BINARY_VERSION_2_3_OR_OLDER)
+                       if (openvpn_binary_version < _openvpn_binary_version (2, 4, 0))
                                args_add_strv (args, "--comp-lzo", "yes");
                        else
                                args_add_strv (args, "--compress", "lzo");
@@ -1567,7 +1588,7 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
                case NMOVPN_COMP_LZ4:
                case NMOVPN_COMP_LZ4_V2:
                case NMOVPN_COMP_AUTO:
-                       if (openvpn_binary_version == OPENVPN_BINARY_VERSION_2_3_OR_OLDER)
+                       if (openvpn_binary_version < _openvpn_binary_version (2, 4, 0))
                                _LOGW ("\"compress\" option supported only by OpenVPN >= 2.4");
 
                        if (comp == NMOVPN_COMP_LZ4)
@@ -1579,7 +1600,7 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
                        break;
                case NMOVPN_COMP_LEGACY_LZO_DISABLED:
                case NMOVPN_COMP_LEGACY_LZO_ADAPTIVE:
-                       if (openvpn_binary_version != OPENVPN_BINARY_VERSION_2_3_OR_OLDER)
+                       if (openvpn_binary_version >= _openvpn_binary_version (2, 4, 0))
                                _LOGW ("\"comp-lzo\" is deprecated and will be removed in future OpenVPN 
releases");
 
                        args_add_strv (args, "--comp-lzo",
@@ -1767,7 +1788,7 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
 
        tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_TLS_REMOTE);
        if (nmovpn_arg_is_set (tmp)) {
-               if (openvpn_binary_detect_version_cached (openvpn_binary, &openvpn_binary_version) == 
OPENVPN_BINARY_VERSION_2_3_OR_OLDER) {
+               if (openvpn_binary_detect_version_cached (openvpn_binary, &openvpn_binary_version) < 
_openvpn_binary_version (2, 4, 0)) {
                        _LOGW ("the tls-remote option is deprecated and removed from OpenVPN 2.4. Update your 
connection to use verify-x509-name (for example, \"verify-x509-name=name:%s\")", tmp);
                        args_add_strv (args, "--tls-remote", tmp);
                } else {


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