charon-nm: Port to libnm
authorLubomir Rintel <lkundrak@v3.sk>
Thu, 30 Nov 2017 12:02:02 +0000 (13:02 +0100)
committerTobias Brunner <tobias@strongswan.org>
Fri, 22 Dec 2017 09:05:10 +0000 (10:05 +0100)
libnm-glib is deprecated for several years and reaching the end of its
life. Let's switch to the more up-to-date library.

Closes strongswan/strongswan#85.

configure.ac
src/charon-nm/nm/nm_backend.c
src/charon-nm/nm/nm_service.c
src/charon-nm/nm/nm_service.h

index a520b7c..d04dbb5 100644 (file)
@@ -1174,10 +1174,7 @@ if test x$eap_sim_pcsc = xtrue; then
 fi
 
 if test x$nm = xtrue; then
-       PKG_CHECK_EXISTS([libnm-glib],
-               [PKG_CHECK_MODULES(nm, [NetworkManager gthread-2.0 libnm-util libnm-glib libnm-glib-vpn])],
-               [PKG_CHECK_MODULES(nm, [NetworkManager gthread-2.0 libnm_util libnm_glib libnm_glib_vpn])]
-       )
+       PKG_CHECK_MODULES(nm, [gthread-2.0 libnm])
        AC_SUBST(nm_CFLAGS)
        AC_SUBST(nm_LIBS)
 fi
index 601daca..e4845e7 100644 (file)
@@ -55,7 +55,7 @@ struct nm_backend_t {
 static nm_backend_t *nm_backend = NULL;
 
 /**
- * NM plugin processing routine, creates and handles NMVPNPlugin
+ * NM plugin processing routine, creates and handles NMVpnServicePlugin
  */
 static job_requeue_t run(nm_backend_t *this)
 {
index 3e8392a..e64a6c6 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2017 Lubomir Rintel
+ *
  * Copyright (C) 2013 Tobias Brunner
  * Copyright (C) 2008-2009 Martin Willi
  * Hochschule fuer Technik Rapperswil
@@ -14,8 +16,6 @@
  * for more details.
  */
 
-#include <nm-setting-vpn.h>
-#include <nm-setting-connection.h>
 #include "nm_service.h"
 
 #include <daemon.h>
@@ -26,7 +26,7 @@
 
 #include <stdio.h>
 
-G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_PLUGIN)
+G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_SERVICE_PLUGIN)
 
 /**
  * Private data of NMStrongswanPlugin
@@ -37,7 +37,7 @@ typedef struct {
        /* IKE_SA we are listening on */
        ike_sa_t *ike_sa;
        /* backref to public plugin */
-       NMVPNPlugin *plugin;
+       NMVpnServicePlugin *plugin;
        /* credentials to use for authentication */
        nm_creds_t *creds;
        /* attribute handler for DNS/NBNS server information */
@@ -53,50 +53,46 @@ typedef struct {
 /**
  * convert enumerated handler chunks to a UINT_ARRAY GValue
  */
-static GValue* handler_to_val(nm_handler_t *handler,
+static GVariant* handler_to_variant(nm_handler_t *handler,
                                                         configuration_attribute_type_t type)
 {
-       GValue *val;
-       GArray *array;
+       GVariantBuilder builder;
        enumerator_t *enumerator;
        chunk_t chunk;
 
+       g_variant_builder_init (&builder, G_VARIANT_TYPE ("au"));
+
        enumerator = handler->create_enumerator(handler, type);
-       array = g_array_new (FALSE, TRUE, sizeof (guint32));
        while (enumerator->enumerate(enumerator, &chunk))
        {
-               g_array_append_val (array, *(uint32_t*)chunk.ptr);
+               g_variant_builder_add (&builder, "u",
+                                                          g_variant_new_uint32 (*(uint32_t*)chunk.ptr));
        }
        enumerator->destroy(enumerator);
-       val = g_slice_new0 (GValue);
-       g_value_init (val, DBUS_TYPE_G_UINT_ARRAY);
-       g_value_set_boxed (val, array);
 
-       return val;
+       return g_variant_builder_end (&builder);
 }
 
 /**
  * signal IPv4 config to NM, set connection as established
  */
-static void signal_ipv4_config(NMVPNPlugin *plugin,
+static void signal_ipv4_config(NMVpnServicePlugin *plugin,
                                                           ike_sa_t *ike_sa, child_sa_t *child_sa)
 {
        NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
-       GValue *val;
-       GHashTable *config;
+       GVariantBuilder builder;
        enumerator_t *enumerator;
        host_t *me, *other;
        nm_handler_t *handler;
 
-       config = g_hash_table_new(g_str_hash, g_str_equal);
+       g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+
        handler = priv->handler;
 
        /* NM apparently requires to know the gateway */
-       val = g_slice_new0 (GValue);
-       g_value_init (val, G_TYPE_UINT);
        other = ike_sa->get_other_host(ike_sa);
-       g_value_set_uint (val, *(uint32_t*)other->get_address(other).ptr);
-       g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY, val);
+       g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY,
+                              g_variant_new_uint32 (*(uint32_t*)other->get_address(other).ptr));
 
        /* NM installs this IP address on the interface above, so we use the VIP if
         * we got one.
@@ -107,47 +103,40 @@ static void signal_ipv4_config(NMVPNPlugin *plugin,
                me = ike_sa->get_my_host(ike_sa);
        }
        enumerator->destroy(enumerator);
-       val = g_slice_new0(GValue);
-       g_value_init(val, G_TYPE_UINT);
-       g_value_set_uint(val, *(uint32_t*)me->get_address(me).ptr);
-       g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val);
+       g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS,
+                              g_variant_new_uint32 (*(uint32_t*)other->get_address(me).ptr));
 
-       val = g_slice_new0(GValue);
-       g_value_init(val, G_TYPE_UINT);
-       g_value_set_uint(val, me->get_address(me).len * 8);
-       g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
+       g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PREFIX,
+                              g_variant_new_uint32 (me->get_address(me).len * 8));
 
        /* prevent NM from changing the default route. we set our own route in our
         * own routing table
         */
-       val = g_slice_new0(GValue);
-       g_value_init(val, G_TYPE_BOOLEAN);
-       g_value_set_boolean(val, TRUE);
-       g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT, val);
+       g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT,
+                              g_variant_new_boolean (TRUE));
 
-       val = handler_to_val(handler, INTERNAL_IP4_DNS);
-       g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_DNS, val);
 
-       val = handler_to_val(handler, INTERNAL_IP4_NBNS);
-       g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_NBNS, val);
+       g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_DNS,
+                              handler_to_variant(handler, INTERNAL_IP4_DNS));
+
+       g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NBNS,
+                              handler_to_variant(handler, INTERNAL_IP4_NBNS));
 
        handler->reset(handler);
 
-       nm_vpn_plugin_set_ip4_config(plugin, config);
+       nm_vpn_service_plugin_set_ip4_config(plugin, g_variant_builder_end (&builder));
 }
 
 /**
  * signal failure to NM, connecting failed
  */
-static void signal_failure(NMVPNPlugin *plugin, NMVPNPluginFailure failure)
+static void signal_failure(NMVpnServicePlugin *plugin, NMVpnPluginFailure failure)
 {
        nm_handler_t *handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler;
 
        handler->reset(handler);
 
-       /* TODO: NM does not handle this failure!? */
-       nm_vpn_plugin_failure(plugin, failure);
-       nm_vpn_plugin_set_state(plugin, NM_VPN_SERVICE_STATE_STOPPED);
+       nm_vpn_service_plugin_failure(plugin, failure);
 }
 
 /**
@@ -277,12 +266,12 @@ static identification_t *find_smartcard_key(NMStrongswanPluginPrivate *priv,
 /**
  * Connect function called from NM via DBUS
  */
-static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
+static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
                                                 GError **err)
 {
        NMStrongswanPluginPrivate *priv;
        NMSettingConnection *conn;
-       NMSettingVPN *vpn;
+       NMSettingVpn *vpn;
        enumerator_t *enumerator;
        identification_t *user = NULL, *gateway = NULL;
        const char *address, *str;
@@ -676,10 +665,10 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
 /**
  * NeedSecrets called from NM via DBUS
  */
-static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection,
-                                                        char **setting_name, GError **error)
+static gboolean need_secrets(NMVpnServicePlugin *plugin, NMConnection *connection,
+                                                        const char **setting_name, GError **error)
 {
-       NMSettingVPN *settings;
+       NMSettingVpn *settings;
        const char *method, *path;
 
        settings = NM_SETTING_VPN(nm_connection_get_setting(connection,
@@ -735,9 +724,9 @@ static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection,
 }
 
 /**
- * Disconnect called from NM via DBUS
+ * The actual disconnection
  */
-static gboolean disconnect(NMVPNPlugin *plugin, GError **err)
+static gboolean do_disconnect(gpointer plugin)
 {
        NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
        enumerator_t *enumerator;
@@ -755,17 +744,31 @@ static gboolean disconnect(NMVPNPlugin *plugin, GError **err)
                        enumerator->destroy(enumerator);
                        charon->controller->terminate_ike(charon->controller, id,
                                                                                          controller_cb_empty, NULL, 0);
-                       return TRUE;
+                       return FALSE;
                }
        }
        enumerator->destroy(enumerator);
 
-       g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL,
-                               "Connection not found.");
+       g_debug("Connection not found.");
        return FALSE;
 }
 
 /**
+ * Disconnect called from NM via DBUS
+ */
+static gboolean disconnect(NMVpnServicePlugin *plugin, GError **err)
+{
+       NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
+
+       /* enqueue the actual disconnection, because we may be called in
+        * response to a listener_t callback and the SA enumeration would
+        * possibly deadlock. */
+       g_idle_add(do_disconnect, plugin);
+
+       return TRUE;
+}
+
+/**
  * Initializer
  */
 static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
@@ -773,7 +776,7 @@ static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
        NMStrongswanPluginPrivate *priv;
 
        priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
-       priv->plugin = NM_VPN_PLUGIN(plugin);
+       priv->plugin = NM_VPN_SERVICE_PLUGIN(plugin);
        memset(&priv->listener, 0, sizeof(listener_t));
        priv->listener.child_updown = child_updown;
        priv->listener.ike_rekey = ike_rekey;
@@ -786,7 +789,7 @@ static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
 static void nm_strongswan_plugin_class_init(
                                                                        NMStrongswanPluginClass *strongswan_class)
 {
-       NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS(strongswan_class);
+       NMVpnServicePluginClass *parent_class = NM_VPN_SERVICE_PLUGIN_CLASS(strongswan_class);
 
        g_type_class_add_private(G_OBJECT_CLASS(strongswan_class),
                                                         sizeof(NMStrongswanPluginPrivate));
@@ -801,10 +804,15 @@ static void nm_strongswan_plugin_class_init(
 NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
                                                                                         nm_handler_t *handler)
 {
-       NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_object_new (
+       GError *error = NULL;
+
+       NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_initable_new (
                                        NM_TYPE_STRONGSWAN_PLUGIN,
-                                       NM_VPN_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_STRONGSWAN,
+                                       NULL,
+                                       &error,
+                                       NM_VPN_SERVICE_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_STRONGSWAN,
                                        NULL);
+
        if (plugin)
        {
                NMStrongswanPluginPrivate *priv;
@@ -814,5 +822,11 @@ NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
                priv->creds = creds;
                priv->handler = handler;
        }
+       else
+       {
+               g_warning ("Failed to initialize a plugin instance: %s", error->message);
+               g_error_free (error);
+       }
+
        return plugin;
 }
index 0cb23e1..74ab38b 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <glib.h>
 #include <glib-object.h>
-#include <nm-vpn-plugin.h>
+#include <NetworkManager.h>
 
 #include "nm_creds.h"
 #include "nm_handler.h"
 #define NM_DBUS_PATH_STRONGSWAN       "/org/freedesktop/NetworkManager/strongswan"
 
 typedef struct {
-       NMVPNPlugin parent;
+       NMVpnServicePlugin parent;
 } NMStrongswanPlugin;
 
 typedef struct {
-       NMVPNPluginClass parent;
+       NMVpnServicePluginClass parent;
 } NMStrongswanPluginClass;
 
 GType nm_strongswan_plugin_get_type(void);