[RFC PATCH 7/8] settings: Add an IWD plugin



The plugin listens to NMIwdManager signals to add and remove connections
for IWD's KnownNetworks.  The connections are currently read-only and
contain the minimum settings to mirror the information provided by IWD:
the SSID and the security type.

If this approach is taken the connections will probably still need an
additional NM keyfile to save any settings related to proxies, dhcp,
autoconnect and more (autoconnect and dhcp may eventually end up being
managed by IWD)
---
 src/settings/plugins/iwd/nms-iwd-connection.c | 173 +++++++++++++++++++++++++
 src/settings/plugins/iwd/nms-iwd-connection.h |  43 +++++++
 src/settings/plugins/iwd/nms-iwd-plugin.c     | 176 ++++++++++++++++++++++++++
 src/settings/plugins/iwd/nms-iwd-plugin.h     |  37 ++++++
 4 files changed, 429 insertions(+)
 create mode 100644 src/settings/plugins/iwd/nms-iwd-connection.c
 create mode 100644 src/settings/plugins/iwd/nms-iwd-connection.h
 create mode 100644 src/settings/plugins/iwd/nms-iwd-plugin.c
 create mode 100644 src/settings/plugins/iwd/nms-iwd-plugin.h

diff --git a/src/settings/plugins/iwd/nms-iwd-connection.c b/src/settings/plugins/iwd/nms-iwd-connection.c
new file mode 100644
index 000000000..5f784de58
--- /dev/null
+++ b/src/settings/plugins/iwd/nms-iwd-connection.c
@@ -0,0 +1,173 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service - IWD plugin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2018 Intel Corporation
+ */
+
+#include "nm-default.h"
+
+#include "nms-iwd-connection.h"
+
+#include "nm-setting-connection.h"
+#include "nm-core-internal.h"
+#include "nm-utils.h"
+#include "devices/wifi/nm-wifi-utils.h"
+
+#include "settings/nm-settings-plugin.h"
+
+/*****************************************************************************/
+
+typedef struct {
+       NMIwdKnownNetworkData known_network_data;
+} NMSIwdConnectionPrivate;
+
+struct _NMSIwdConnection {
+       NMSettingsConnection parent;
+       NMSIwdConnectionPrivate _priv;
+};
+
+struct _NMSIwdConnectionClass {
+       NMSettingsConnectionClass parent;
+};
+
+G_DEFINE_TYPE (NMSIwdConnection, nms_iwd_connection, NM_TYPE_SETTINGS_CONNECTION)
+
+#define NMS_IWD_CONNECTION_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSIwdConnection, NMS_IS_IWD_CONNECTION)
+
+/*****************************************************************************/
+
+static gboolean
+delete (NMSettingsConnection *connection,
+        GError **error)
+{
+       NMSettingWireless *s_wireless;
+       GBytes *ssid;
+       gs_free gchar *str_ssid = NULL;
+
+       s_wireless = nm_connection_get_setting_wireless (NM_CONNECTION (connection));
+       if (!s_wireless) {
+               g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
+                            "Connection has no Wireless setting");
+               return FALSE;
+       }
+
+       ssid = nm_setting_wireless_get_ssid (s_wireless);
+       if (!ssid) {
+               g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
+                            "Connection has no SSID in the Wireless setting");
+               return FALSE;
+       }
+
+       str_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL),
+                                         g_bytes_get_size (ssid));
+
+       nm_iwd_manager_forget_network (nm_iwd_manager_get (),
+                                      str_ssid,
+                                      nm_wifi_connection_get_iwd_security (NM_CONNECTION (connection)));
+
+       return TRUE;
+}
+
+/*****************************************************************************/
+
+const NMIwdKnownNetworkData *
+nms_iwd_get_known_network_data (NMSIwdConnection *connection)
+{
+       NMSIwdConnectionPrivate *priv = NMS_IWD_CONNECTION_GET_PRIVATE (connection);
+
+       return &priv->known_network_data;
+}
+
+/*****************************************************************************/
+
+static void
+nms_iwd_connection_init (NMSIwdConnection *connection)
+{
+}
+
+NMSIwdConnection *
+nms_iwd_connection_new (const NMIwdKnownNetworkData *network)
+{
+       NMSIwdConnectionPrivate *priv;
+       GObject *object;
+       char uuid[37];
+       NMSetting *setting;
+       GBytes *ssid = g_bytes_new (network->name, strlen (network->name));
+
+       object = (GObject *) g_object_new (NMS_TYPE_IWD_CONNECTION, NULL);
+       nm_settings_connection_set_flags (NM_SETTINGS_CONNECTION (object),
+                                         NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED,
+                                         TRUE);
+
+       setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_CONNECTION,
+                                           NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
+                                           NM_SETTING_CONNECTION_ID, network->name,
+                                           NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_buf (uuid),
+                                           NM_SETTING_CONNECTION_READ_ONLY, TRUE,
+                                           NULL));
+       nm_connection_add_setting (NM_CONNECTION (object), setting);
+
+       setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_WIRELESS,
+                                           NM_SETTING_WIRELESS_SSID, ssid,
+                                           NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
+                                           NULL));
+       nm_connection_add_setting (NM_CONNECTION (object), setting);
+
+       if (NM_IN_SET (network->security, NM_IWD_NETWORK_SECURITY_PSK, NM_IWD_NETWORK_SECURITY_8021X)) {
+               const char *key_mgmt =
+                   network->security == NM_IWD_NETWORK_SECURITY_8021X ? "wpa-eap" : "wpa-psk";
+
+               setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_WIRELESS_SECURITY,
+                                                   NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open",
+                                                   NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, key_mgmt,
+                                                   NULL));
+               nm_connection_add_setting (NM_CONNECTION (object), setting);
+       }
+
+       if (network->security == NM_IWD_NETWORK_SECURITY_8021X) {
+               setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_802_1X, NULL));
+               nm_setting_802_1x_add_eap_method (NM_SETTING_802_1X (setting), "extern");
+               nm_connection_add_setting (NM_CONNECTION (object), setting);
+       }
+
+       priv = NMS_IWD_CONNECTION_GET_PRIVATE (object);
+       priv->known_network_data.name = g_strdup (network->name);
+       priv->known_network_data.security = network->security;
+
+       return (NMSIwdConnection *) object;
+}
+
+static void
+dispose (GObject *object)
+{
+       NMSIwdConnectionPrivate *priv = NMS_IWD_CONNECTION_GET_PRIVATE (object);
+
+       g_clear_pointer (&priv->known_network_data.name, g_free);
+
+       G_OBJECT_CLASS (nms_iwd_connection_parent_class)->dispose (object);
+}
+
+static void
+nms_iwd_connection_class_init (NMSIwdConnectionClass *iwd_connection_class)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (iwd_connection_class);
+       NMSettingsConnectionClass *settings_class = NM_SETTINGS_CONNECTION_CLASS (iwd_connection_class);
+
+       object_class->dispose = dispose;
+
+       settings_class->delete = delete;
+}
diff --git a/src/settings/plugins/iwd/nms-iwd-connection.h b/src/settings/plugins/iwd/nms-iwd-connection.h
new file mode 100644
index 000000000..caf6e30ff
--- /dev/null
+++ b/src/settings/plugins/iwd/nms-iwd-connection.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service - IWD plugin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2018 Intel Corporation
+ */
+
+#ifndef __NMS_IWD_CONNECTION_H__
+#define __NMS_IWD_CONNECTION_H__
+
+#include "settings/nm-settings-connection.h"
+#include "devices/wifi/nm-iwd-manager.h"
+
+#define NMS_TYPE_IWD_CONNECTION            (nms_iwd_connection_get_type ())
+#define NMS_IWD_CONNECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMS_TYPE_IWD_CONNECTION, 
NMSIwdConnection))
+#define NMS_IWD_CONNECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NMS_TYPE_IWD_CONNECTION, 
NMSIwdConnectionClass))
+#define NMS_IS_IWD_CONNECTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMS_TYPE_IWD_CONNECTION))
+#define NMS_IS_IWD_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMS_TYPE_IWD_CONNECTION))
+#define NMS_IWD_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NMS_TYPE_IWD_CONNECTION, 
NMSIwdConnectionClass))
+
+typedef struct _NMSIwdConnection NMSIwdConnection;
+typedef struct _NMSIwdConnectionClass NMSIwdConnectionClass;
+
+GType nms_iwd_connection_get_type (void);
+
+NMSIwdConnection *nms_iwd_connection_new (const NMIwdKnownNetworkData *network);
+
+const NMIwdKnownNetworkData *nms_iwd_get_known_network_data (NMSIwdConnection *connection);
+
+#endif /* __NMS_IWD_CONNECTION_H__ */
diff --git a/src/settings/plugins/iwd/nms-iwd-plugin.c b/src/settings/plugins/iwd/nms-iwd-plugin.c
new file mode 100644
index 000000000..5eb60165c
--- /dev/null
+++ b/src/settings/plugins/iwd/nms-iwd-plugin.c
@@ -0,0 +1,176 @@
+/* NetworkManager system settings service - IWD plugin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2018 Intel Corporation
+ */
+
+#include "nm-default.h"
+
+#include "nms-iwd-plugin.h"
+
+#include "nm-connection.h"
+#include "nm-setting.h"
+#include "nm-setting-connection.h"
+#include "nm-utils.h"
+#include "nm-core-internal.h"
+
+#include "settings/nm-settings-plugin.h"
+
+#include "nms-iwd-connection.h"
+
+/*****************************************************************************/
+
+typedef struct {
+       GHashTable *connections;  /* uuid::connection */
+       GSList *networks_tmp;
+
+       gboolean initialized;
+} NMSIwdPluginPrivate;
+
+struct _NMSIwdPlugin {
+       GObject parent;
+       NMSIwdPluginPrivate _priv;
+};
+
+struct _NMSIwdPluginClass {
+       GObjectClass parent;
+};
+
+static void settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface);
+
+G_DEFINE_TYPE_EXTENDED (NMSIwdPlugin, nms_iwd_plugin, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_PLUGIN,
+                                               settings_plugin_interface_init))
+
+#define NMS_IWD_PLUGIN_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSIwdPlugin, NMS_IS_IWD_PLUGIN)
+
+/*****************************************************************************/
+
+NM_DEFINE_SINGLETON_GETTER (NMSIwdPlugin, nms_iwd_plugin_get, NMS_TYPE_IWD_PLUGIN);
+
+/*****************************************************************************/
+
+static GSList *
+get_connections (NMSettingsPlugin *config)
+{
+       NMSIwdPluginPrivate *priv = NMS_IWD_PLUGIN_GET_PRIVATE ((NMSIwdPlugin *) config);
+
+       return _nm_utils_hash_values_to_slist (priv->connections);
+}
+
+static gboolean
+check_connection_gone (gpointer key, gpointer value, gpointer user_data)
+{
+       NMSIwdConnection *connection = value;
+       const NMIwdKnownNetworkData *data = nms_iwd_get_known_network_data (connection);
+       NMSIwdPluginPrivate *priv = user_data;
+       GSList *iter;
+
+       for (iter = priv->networks_tmp; iter; iter = iter->next) {
+               const NMIwdKnownNetworkData *iter_data = iter->data;
+
+               if (!strcmp (data->name, iter_data->name) && data->security == iter_data->security) {
+                       priv->networks_tmp = g_slist_delete_link (priv->networks_tmp, iter);
+                       return FALSE;
+               }
+       }
+
+       /* Remove network if not present in the current list */
+
+       nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection));
+
+       return TRUE;
+}
+
+static void
+nms_iwd_plugin_networks_cb (NMIwdManager *manager,
+                            gpointer networks,
+                            gpointer user_data)
+{
+       NMSIwdPlugin *plugin = NMS_IWD_PLUGIN (user_data);
+       NMSIwdPluginPrivate *priv = NMS_IWD_PLUGIN_GET_PRIVATE (plugin);
+       NMSIwdConnection *connection_new;
+       const GSList *iter;
+
+       priv->networks_tmp = g_slist_copy (networks);
+       g_hash_table_foreach_remove (priv->connections, check_connection_gone, priv);
+
+       /* Add any Known Networks that don't have a Connection yet */
+       for (iter = priv->networks_tmp; iter; iter = iter->next) {
+               const NMIwdKnownNetworkData *network = iter->data;
+
+               connection_new = nms_iwd_connection_new (network);
+
+               g_hash_table_insert (priv->connections,
+                                    g_strdup (nm_connection_get_uuid (NM_CONNECTION (connection_new))),
+                                    connection_new);
+
+               g_signal_emit_by_name (plugin, NM_SETTINGS_PLUGIN_CONNECTION_ADDED, connection_new);
+       }
+
+       g_slist_free (priv->networks_tmp);
+}
+
+/*****************************************************************************/
+
+static void
+nms_iwd_plugin_init (NMSIwdPlugin *plugin)
+{
+       NMSIwdPluginPrivate *priv = NMS_IWD_PLUGIN_GET_PRIVATE (plugin);
+       NMIwdManager *manager = nm_iwd_manager_get ();
+
+       priv->connections = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref);
+
+       g_signal_connect (manager,
+                         NM_IWD_MANAGER_KNOWN_NETWORKS_CHANGED,
+                         G_CALLBACK (nms_iwd_plugin_networks_cb),
+                         plugin);
+}
+
+static void
+dispose (GObject *object)
+{
+       NMSIwdPluginPrivate *priv = NMS_IWD_PLUGIN_GET_PRIVATE ((NMSIwdPlugin *) object);
+
+       if (priv->connections) {
+               g_hash_table_destroy (priv->connections);
+               priv->connections = NULL;
+       }
+
+       G_OBJECT_CLASS (nms_iwd_plugin_parent_class)->dispose (object);
+}
+
+static void
+nms_iwd_plugin_class_init (NMSIwdPluginClass *req_class)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (req_class);
+
+       object_class->dispose = dispose;
+}
+
+static void
+settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface)
+{
+       plugin_iface->get_connections = get_connections;
+}
+
+/*****************************************************************************/
+
+G_MODULE_EXPORT GObject *
+nm_settings_plugin_factory (void)
+{
+       return G_OBJECT (g_object_ref (nms_iwd_plugin_get ()));
+}
diff --git a/src/settings/plugins/iwd/nms-iwd-plugin.h b/src/settings/plugins/iwd/nms-iwd-plugin.h
new file mode 100644
index 000000000..03ee02899
--- /dev/null
+++ b/src/settings/plugins/iwd/nms-iwd-plugin.h
@@ -0,0 +1,37 @@
+/* NetworkManager system settings service - IWD plugin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2018 Intel Corporation
+ */
+
+#ifndef __NMS_IWD_PLUGIN_H__
+#define __NMS_IWD_PLUGIN_H__
+
+#define NMS_TYPE_IWD_PLUGIN            (nms_iwd_plugin_get_type ())
+#define NMS_IWD_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMS_TYPE_IWD_PLUGIN, 
NMSIwdPlugin))
+#define NMS_IWD_PLUGIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NMS_TYPE_IWD_PLUGIN, 
NMSIwdPluginClass))
+#define NMS_IS_IWD_PLUGIN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMS_TYPE_IWD_PLUGIN))
+#define NMS_IS_IWD_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMS_TYPE_IWD_PLUGIN))
+#define NMS_IWD_PLUGIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NMS_TYPE_IWD_PLUGIN, 
NMSIwdPluginClass))
+
+typedef struct _NMSIwdPlugin NMSIwdPlugin;
+typedef struct _NMSIwdPluginClass NMSIwdPluginClass;
+
+GType nms_iwd_plugin_get_type (void);
+
+NMSIwdPlugin *nms_iwd_plugin_get (void);
+
+#endif /* __NMS_IWD_PLUGIN_H__ */
-- 
2.14.1



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