NetworkManager r3656 - in trunk: . system-settings/plugins/ifcfg-fedora system-settings/src
- From: dcbw svn gnome org
- To: svn-commits-list gnome org
- Subject: NetworkManager r3656 - in trunk: . system-settings/plugins/ifcfg-fedora system-settings/src
- Date: Sun, 11 May 2008 21:20:53 +0100 (BST)
Author: dcbw
Date: Sun May 11 20:20:52 2008
New Revision: 3656
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=3656&view=rev
Log:
2008-05-11 Dan Williams <dcbw redhat com>
Update Fedora system-settings plugin to support latest API and use
GFileMonitor rather than home-rolled inotify code.
* system-settings/plugins/ifcfg-fedora/Makefile.am
system-settings/plugins/ifcfg-fedora/common.h
system-settings/plugins/ifcfg-fedora/plugin.c
- Update to latest system settings plugin API; use GIO instead of
custom inotify code; use NMIfcfgConnection objects instead of
ConnectionData structures tacked onto NMConnection objects
* system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.c
system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.h
- Implement an NMExportedConnection subclass mapping ifcfg files to
connections
* system-settings/plugins/ifcfg-fedora/reader.c
system-settings/plugins/ifcfg-fedora/reader.h
- Move ifcfg parsing bits here from parser.c
* system-settings/plugins/ifcfg-fedora/parser.c
system-settings/plugins/ifcfg-fedora/parser.h
- Remove; most code moved to reader.c
Added:
trunk/system-settings/plugins/ifcfg-fedora/common.h
trunk/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.c
trunk/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.h
trunk/system-settings/plugins/ifcfg-fedora/reader.c
trunk/system-settings/plugins/ifcfg-fedora/reader.h
Removed:
trunk/system-settings/plugins/ifcfg-fedora/parser.c
trunk/system-settings/plugins/ifcfg-fedora/parser.h
Modified:
trunk/ChangeLog
trunk/system-settings/plugins/ifcfg-fedora/Makefile.am
trunk/system-settings/plugins/ifcfg-fedora/plugin.c
trunk/system-settings/src/dbus-settings.c
Modified: trunk/system-settings/plugins/ifcfg-fedora/Makefile.am
==============================================================================
--- trunk/system-settings/plugins/ifcfg-fedora/Makefile.am (original)
+++ trunk/system-settings/plugins/ifcfg-fedora/Makefile.am Sun May 11 20:20:52 2008
@@ -4,10 +4,13 @@
libnm_settings_plugin_ifcfg_fedora_la_SOURCES = \
shvar.c \
shvar.h \
- parser.c \
- parser.h \
plugin.c \
- plugin.h
+ plugin.h \
+ nm-ifcfg-connection.c \
+ nm-ifcfg-connection.h \
+ reader.c \
+ reader.h \
+ common.h
libnm_settings_plugin_ifcfg_fedora_la_CPPFLAGS = \
$(GLIB_CFLAGS) \
@@ -16,6 +19,7 @@
-DG_DISABLE_DEPRECATED \
-I${top_srcdir}/system-settings/src \
-I$(top_srcdir)/include \
+ -I$(top_srcdir)/libnm-glib \
-I$(top_srcdir)/libnm-util \
-DSYSCONFDIR=\"$(sysconfdir)\"
@@ -23,5 +27,14 @@
libnm_settings_plugin_ifcfg_fedora_la_LIBADD = \
$(GLIB_LIBS) \
$(GMODULE_LIBS) \
- $(top_builddir)/libnm-util/libnm-util.la
+ $(top_builddir)/libnm-util/libnm-util.la \
+ $(top_builddir)/libnm-glib/libnm_glib.la
+
+if NO_GIO
+libnm_settings_plugin_ifcfg_fedora_la_LIBADD += \
+ $(top_builddir)/gfilemonitor/libgfilemonitor.la
+else
+libnm_settings_plugin_ifcfg_fedora_la_LIBADD += \
+ $(GIO_LIBS)
+endif
Added: trunk/system-settings/plugins/ifcfg-fedora/common.h
==============================================================================
--- (empty file)
+++ trunk/system-settings/plugins/ifcfg-fedora/common.h Sun May 11 20:20:52 2008
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+#define IFCFG_TAG "ifcfg-"
+#define KEYS_TAG "keys-"
+#define BAK_TAG ".bak"
+#define TILDE_TAG "~"
+#define ORIG_TAG ".orig"
+#define REJ_TAG ".rej"
+
+#include <glib.h>
+
+GQuark ifcfg_plugin_error_quark (void);
+
+
+#endif /* __COMMON_H__ */
+
Added: trunk/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.c
==============================================================================
--- (empty file)
+++ trunk/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.c Sun May 11 20:20:52 2008
@@ -0,0 +1,422 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <net/ethernet.h>
+#include <netinet/ether.h>
+
+#include <glib/gstdio.h>
+
+#include <NetworkManager.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-wireless.h>
+#include <nm-setting-gsm.h>
+#include <nm-setting-cdma.h>
+#include <nm-setting-pppoe.h>
+#include <nm-setting-wireless-security.h>
+#include <nm-setting-8021x.h>
+
+#include "common.h"
+#include "nm-ifcfg-connection.h"
+#include "nm-system-config-hal-manager.h"
+#include "reader.h"
+
+G_DEFINE_TYPE (NMIfcfgConnection, nm_ifcfg_connection, NM_TYPE_EXPORTED_CONNECTION)
+
+#define NM_IFCFG_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnectionPrivate))
+
+typedef struct {
+ char *filename;
+ char *keyfile;
+
+ char *udi;
+ gboolean unmanaged;
+
+ NMSystemConfigHalManager *hal_mgr;
+ DBusGConnection *g_connection;
+ gulong daid;
+} NMIfcfgConnectionPrivate;
+
+enum {
+ PROP_0,
+ PROP_FILENAME,
+ PROP_UNMANAGED,
+ PROP_UDI,
+
+ LAST_PROP
+};
+
+static char *
+get_ether_device_udi (DBusGConnection *g_connection, GByteArray *mac, GSList *devices)
+{
+ GError *error = NULL;
+ GSList *iter;
+ char *udi = NULL;
+
+ if (!g_connection || !mac)
+ return NULL;
+
+ for (iter = devices; !udi && iter; iter = g_slist_next (iter)) {
+ DBusGProxy *dev_proxy;
+ char *address = NULL;
+
+ dev_proxy = dbus_g_proxy_new_for_name (g_connection,
+ "org.freedesktop.Hal",
+ iter->data,
+ "org.freedesktop.Hal.Device");
+ if (!dev_proxy)
+ continue;
+
+ if (dbus_g_proxy_call_with_timeout (dev_proxy,
+ "GetPropertyString", 10000, &error,
+ G_TYPE_STRING, "net.address", G_TYPE_INVALID,
+ G_TYPE_STRING, &address, G_TYPE_INVALID)) {
+ struct ether_addr *dev_mac;
+
+ if (address && strlen (address)) {
+ dev_mac = ether_aton (address);
+ if (!memcmp (dev_mac->ether_addr_octet, mac->data, ETH_ALEN))
+ udi = g_strdup (iter->data);
+ }
+ } else {
+ g_error_free (error);
+ error = NULL;
+ }
+ g_free (address);
+ g_object_unref (dev_proxy);
+ }
+
+ return udi;
+}
+
+static NMDeviceType
+get_device_type_for_connection (NMConnection *connection)
+{
+ NMDeviceType devtype = DEVICE_TYPE_UNKNOWN;
+ NMSettingConnection *s_con;
+
+ s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+ if (!s_con)
+ return DEVICE_TYPE_UNKNOWN;
+
+ if ( !strcmp (s_con->type, NM_SETTING_WIRED_SETTING_NAME)
+ || !strcmp (s_con->type, NM_SETTING_PPPOE_SETTING_NAME)) {
+ if (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED))
+ devtype = DEVICE_TYPE_802_3_ETHERNET;
+ } else if (!strcmp (s_con->type, NM_SETTING_WIRELESS_SETTING_NAME)) {
+ if (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS))
+ devtype = DEVICE_TYPE_802_11_WIRELESS;
+ } else if (!strcmp (s_con->type, NM_SETTING_GSM_SETTING_NAME)) {
+ if (nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM))
+ devtype = DEVICE_TYPE_GSM;
+ } else if (!strcmp (s_con->type, NM_SETTING_CDMA_SETTING_NAME)) {
+ if (nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA))
+ devtype = DEVICE_TYPE_CDMA;
+ }
+
+ return devtype;
+}
+
+static char *
+get_udi_for_connection (NMConnection *connection,
+ DBusGConnection *g_connection,
+ NMSystemConfigHalManager *hal_mgr,
+ NMDeviceType devtype)
+{
+ NMSettingWired *s_wired;
+ NMSettingWireless *s_wireless;
+ char *udi = NULL;
+ GSList *devices = NULL;
+
+ if (devtype == DEVICE_TYPE_UNKNOWN)
+ devtype = get_device_type_for_connection (connection);
+
+ switch (devtype) {
+ case DEVICE_TYPE_802_3_ETHERNET:
+ s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
+ if (s_wired) {
+ devices = nm_system_config_hal_manager_get_devices_of_type (hal_mgr, DEVICE_TYPE_802_3_ETHERNET);
+ udi = get_ether_device_udi (g_connection, s_wired->mac_address, devices);
+ }
+ break;
+
+ case DEVICE_TYPE_802_11_WIRELESS:
+ s_wireless = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
+ if (s_wireless) {
+ devices = nm_system_config_hal_manager_get_devices_of_type (hal_mgr, DEVICE_TYPE_802_11_WIRELESS);
+ udi = get_ether_device_udi (g_connection, s_wireless->mac_address, devices);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ g_slist_foreach (devices, (GFunc) g_free, NULL);
+ g_slist_free (devices);
+
+ return udi;
+}
+
+static void
+device_added_cb (NMSystemConfigHalManager *hal_mgr,
+ const char *udi,
+ NMDeviceType devtype,
+ gpointer user_data)
+{
+ NMIfcfgConnection *connection = NM_IFCFG_CONNECTION (user_data);
+ NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (connection);
+ NMConnection *wrapped;
+
+ /* Should only be called when udi is NULL */
+ g_return_if_fail (priv->udi == NULL);
+
+ wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection));
+ if (devtype != get_device_type_for_connection (wrapped))
+ return;
+
+ priv->udi = get_udi_for_connection (wrapped, priv->g_connection, priv->hal_mgr, devtype);
+ if (!priv->udi)
+ return;
+
+ /* If the connection is unmanaged we have to tell the plugin */
+ if (priv->unmanaged)
+ g_object_notify (G_OBJECT (connection), NM_IFCFG_CONNECTION_UNMANAGED);
+
+ g_signal_handler_disconnect (G_OBJECT (hal_mgr), priv->daid);
+ priv->daid = 0;
+}
+
+NMIfcfgConnection *
+nm_ifcfg_connection_new (const char *filename,
+ DBusGConnection *g_connection,
+ NMSystemConfigHalManager *hal_mgr,
+ GError **error)
+{
+ GObject *object;
+ NMConnection *wrapped;
+ gboolean unmanaged = FALSE;
+ char *udi;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ wrapped = connection_from_file (filename, &unmanaged, error);
+ if (!wrapped)
+ return NULL;
+
+ udi = get_udi_for_connection (wrapped, g_connection, hal_mgr, DEVICE_TYPE_UNKNOWN);
+
+ object = (GObject *) g_object_new (NM_TYPE_IFCFG_CONNECTION,
+ NM_IFCFG_CONNECTION_FILENAME, filename,
+ NM_IFCFG_CONNECTION_UNMANAGED, unmanaged,
+ NM_IFCFG_CONNECTION_UDI, udi,
+ NM_EXPORTED_CONNECTION_CONNECTION, wrapped,
+ NULL);
+ if (object && !udi) {
+ NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
+
+ priv->hal_mgr = g_object_ref (hal_mgr);
+ priv->g_connection = dbus_g_connection_ref (g_connection);
+ priv->daid = g_signal_connect (priv->hal_mgr, "device-added", G_CALLBACK (device_added_cb), object);
+ }
+
+ g_object_unref (wrapped);
+ g_free (udi);
+ return (NMIfcfgConnection *) object;
+}
+
+const char *
+nm_ifcfg_connection_get_filename (NMIfcfgConnection *self)
+{
+ g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL);
+
+ return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->filename;
+}
+
+const char *
+nm_ifcfg_connection_get_udi (NMIfcfgConnection *self)
+{
+ g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL);
+
+ return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->udi;
+}
+
+gboolean
+nm_ifcfg_connection_get_unmanaged (NMIfcfgConnection *self)
+{
+ g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), FALSE);
+
+ return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged;
+}
+
+static GHashTable *
+get_settings (NMExportedConnection *exported)
+{
+ return nm_connection_to_hash (nm_exported_connection_get_connection (exported));
+}
+
+static const char *
+get_id (NMExportedConnection *exported)
+{
+ return NM_IFCFG_CONNECTION_GET_PRIVATE (exported)->filename;
+}
+
+static gboolean
+update (NMExportedConnection *exported, GHashTable *new_settings, GError **error)
+{
+// write_connection (NM_IFCFG_CONNECTION (exported));
+ return TRUE;
+}
+
+static gboolean
+delete (NMExportedConnection *exported, GError **error)
+{
+ NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (exported);
+
+ g_unlink (priv->filename);
+ if (priv->keyfile)
+ g_unlink (priv->keyfile);
+
+ return TRUE;
+}
+
+/* GObject */
+
+static void
+nm_ifcfg_connection_init (NMIfcfgConnection *connection)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
+ NMConnection *wrapped;
+
+ wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (object));
+ if (wrapped)
+ nm_connection_clear_secrets (wrapped);
+
+ g_free (priv->filename);
+ g_free (priv->udi);
+
+ if (priv->hal_mgr) {
+ if (priv->daid)
+ g_signal_handler_disconnect (G_OBJECT (priv->hal_mgr), priv->daid);
+
+ g_object_unref (priv->hal_mgr);
+ }
+
+ if (priv->g_connection)
+ dbus_g_connection_unref (priv->g_connection);
+
+ G_OBJECT_CLASS (nm_ifcfg_connection_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ /* Construct only */
+ priv->filename = g_value_dup_string (value);
+ break;
+ case PROP_UNMANAGED:
+ priv->unmanaged = g_value_get_boolean (value);
+ break;
+ case PROP_UDI:
+ /* Construct only */
+ priv->udi = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ g_value_set_string (value, priv->filename);
+ break;
+ case PROP_UNMANAGED:
+ g_value_set_boolean (value, priv->unmanaged);
+ break;
+ case PROP_UDI:
+ g_value_set_string (value, priv->udi);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_ifcfg_connection_class_init (NMIfcfgConnectionClass *ifcfg_connection_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (ifcfg_connection_class);
+ NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (ifcfg_connection_class);
+
+ g_type_class_add_private (ifcfg_connection_class, sizeof (NMIfcfgConnectionPrivate));
+
+ /* Virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->finalize = finalize;
+
+ connection_class->get_settings = get_settings;
+ connection_class->get_id = get_id;
+ connection_class->update = update;
+ connection_class->delete = delete;
+
+ /* Properties */
+ g_object_class_install_property
+ (object_class, PROP_FILENAME,
+ g_param_spec_string (NM_IFCFG_CONNECTION_FILENAME,
+ "FileName",
+ "File name",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property
+ (object_class, PROP_UNMANAGED,
+ g_param_spec_boolean (NM_IFCFG_CONNECTION_UNMANAGED,
+ "Unmanaged",
+ "Unmanaged",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property
+ (object_class, PROP_UDI,
+ g_param_spec_string (NM_IFCFG_CONNECTION_UDI,
+ "UDI",
+ "UDI",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
Added: trunk/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.h
==============================================================================
--- (empty file)
+++ trunk/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.h Sun May 11 20:20:52 2008
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_IFCFG_CONNECTION_H
+#define NM_IFCFG_CONNECTION_H
+
+G_BEGIN_DECLS
+
+#include <nm-settings.h>
+#include "nm-system-config-hal-manager.h"
+
+#define NM_TYPE_IFCFG_CONNECTION (nm_ifcfg_connection_get_type ())
+#define NM_IFCFG_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnection))
+#define NM_IFCFG_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnectionClass))
+#define NM_IS_IFCFG_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IFCFG_CONNECTION))
+#define NM_IS_IFCFG_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_IFCFG_CONNECTION))
+#define NM_IFCFG_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnectionClass))
+
+#define NM_IFCFG_CONNECTION_FILENAME "filename"
+#define NM_IFCFG_CONNECTION_UNMANAGED "unmanaged"
+#define NM_IFCFG_CONNECTION_UDI "udi"
+
+typedef struct {
+ NMExportedConnection parent;
+} NMIfcfgConnection;
+
+typedef struct {
+ NMExportedConnectionClass parent;
+} NMIfcfgConnectionClass;
+
+GType nm_ifcfg_connection_get_type (void);
+
+NMIfcfgConnection *nm_ifcfg_connection_new (const char *filename,
+ DBusGConnection *g_connection,
+ NMSystemConfigHalManager *hal_mgr,
+ GError **error);
+
+const char *nm_ifcfg_connection_get_filename (NMIfcfgConnection *self);
+
+const char *nm_ifcfg_connection_get_udi (NMIfcfgConnection *self);
+
+gboolean nm_ifcfg_connection_get_unmanaged (NMIfcfgConnection *self);
+
+G_END_DECLS
+
+#endif /* NM_IFCFG_CONNECTION_H */
Modified: trunk/system-settings/plugins/ifcfg-fedora/plugin.c
==============================================================================
--- trunk/system-settings/plugins/ifcfg-fedora/plugin.c (original)
+++ trunk/system-settings/plugins/ifcfg-fedora/plugin.c Sun May 11 20:20:52 2008
@@ -16,14 +16,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * (C) Copyright 2007 Red Hat, Inc.
+ * (C) Copyright 2008 Red Hat, Inc.
*/
+#include <config.h>
#include <gmodule.h>
#include <glib-object.h>
#include <glib/gi18n.h>
#include <string.h>
-#include <sys/inotify.h>
#include <unistd.h>
#include <errno.h>
#include <net/ethernet.h>
@@ -32,19 +32,18 @@
#include <dbus/dbus-glib.h>
#include <nm-setting-connection.h>
-#include <nm-setting-wired.h>
-#include <nm-setting-wireless.h>
-#include <nm-setting-gsm.h>
-#include <nm-setting-cdma.h>
-#include <nm-setting-pppoe.h>
-#include <nm-setting-wireless-security.h>
-#include <nm-setting-8021x.h>
+#ifndef NO_GIO
+#include <gio/gio.h>
+#else
+#include <gfilemonitor/gfilemonitor.h>
+#endif
+
+#include "common.h"
#include "nm-dbus-glib-types.h"
#include "plugin.h"
-#include "parser.h"
-#include "shvar.h"
#include "nm-system-config-interface.h"
+#include "nm-ifcfg-connection.h"
#define IFCFG_PLUGIN_NAME "ifcfg-fedora"
#define IFCFG_PLUGIN_INFO "(c) 2007 - 2008 Red Hat, Inc. To report bugs please use the NetworkManager mailing list."
@@ -61,16 +60,13 @@
typedef struct {
- gboolean initialized;
-
DBusGConnection *g_connection;
NMSystemConfigHalManager *hal_mgr;
- GSList *connections;
+ GHashTable *connections;
- int ifd;
- int wd;
- GHashTable *watch_table;
+ GFileMonitor *monitor;
+ guint monitor_id;
} SCPluginIfcfgPrivate;
@@ -85,804 +81,295 @@
return error_quark;
}
-static char *
-get_ether_device_udi (SCPluginIfcfg *plugin, GByteArray *mac, GSList *devices)
-{
- SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
- GError *error = NULL;
- GSList *iter;
- char *udi = NULL;
-
- if (!priv->g_connection || !mac)
- return NULL;
-
- for (iter = devices; !udi && iter; iter = g_slist_next (iter)) {
- DBusGProxy *dev_proxy;
- char *address = NULL;
-
- dev_proxy = dbus_g_proxy_new_for_name (priv->g_connection,
- "org.freedesktop.Hal",
- iter->data,
- "org.freedesktop.Hal.Device");
- if (!dev_proxy)
- continue;
-
- if (dbus_g_proxy_call_with_timeout (dev_proxy,
- "GetPropertyString", 10000, &error,
- G_TYPE_STRING, "net.address", G_TYPE_INVALID,
- G_TYPE_STRING, &address, G_TYPE_INVALID)) {
- struct ether_addr *dev_mac;
-
- if (address && strlen (address)) {
- dev_mac = ether_aton (address);
- if (!memcmp (dev_mac->ether_addr_octet, mac->data, ETH_ALEN))
- udi = g_strdup (iter->data);
- }
- } else {
- g_error_free (error);
- error = NULL;
- }
- g_free (address);
- g_object_unref (dev_proxy);
- }
-
- return udi;
-}
-
-static NMDeviceType
-get_device_type_for_connection (NMConnection *connection)
-{
- NMDeviceType devtype = DEVICE_TYPE_UNKNOWN;
- NMSettingConnection *s_con;
-
- s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
- if (!s_con)
- return DEVICE_TYPE_UNKNOWN;
-
- if ( !strcmp (s_con->type, NM_SETTING_WIRED_SETTING_NAME)
- || !strcmp (s_con->type, NM_SETTING_PPPOE_SETTING_NAME)) {
- if (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED))
- devtype = DEVICE_TYPE_802_3_ETHERNET;
- } else if (!strcmp (s_con->type, NM_SETTING_WIRELESS_SETTING_NAME)) {
- if (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS))
- devtype = DEVICE_TYPE_802_11_WIRELESS;
- } else if (!strcmp (s_con->type, NM_SETTING_GSM_SETTING_NAME)) {
- if (nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM))
- devtype = DEVICE_TYPE_GSM;
- } else if (!strcmp (s_con->type, NM_SETTING_CDMA_SETTING_NAME)) {
- if (nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA))
- devtype = DEVICE_TYPE_CDMA;
- }
-
- return devtype;
-}
-
-static char *
-get_udi_for_connection (SCPluginIfcfg *plugin, NMConnection *connection, NMDeviceType devtype)
-{
- SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
- NMSettingWired *s_wired;
- NMSettingWireless *s_wireless;
- char *udi = NULL;
- GSList *devices = NULL;
-
- if (devtype == DEVICE_TYPE_UNKNOWN)
- devtype = get_device_type_for_connection (connection);
-
- switch (devtype) {
- case DEVICE_TYPE_802_3_ETHERNET:
- s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
- if (s_wired) {
- devices = nm_system_config_hal_manager_get_devices_of_type (priv->hal_mgr, DEVICE_TYPE_802_3_ETHERNET);
- udi = get_ether_device_udi (plugin, s_wired->mac_address, devices);
- }
- break;
-
- case DEVICE_TYPE_802_11_WIRELESS:
- s_wireless = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
- if (s_wireless) {
- devices = nm_system_config_hal_manager_get_devices_of_type (priv->hal_mgr, DEVICE_TYPE_802_11_WIRELESS);
- udi = get_ether_device_udi (plugin, s_wireless->mac_address, devices);
- }
- break;
-
- default:
- break;
- }
-
- g_slist_foreach (devices, (GFunc) g_free, NULL);
- g_slist_free (devices);
-
- return udi;
-}
-
static void
-device_added_cb (NMSystemConfigHalManager *hal_mgr,
- const char *udi,
- NMDeviceType devtype,
- gpointer user_data)
+check_unmanaged (gpointer key, gpointer data, gpointer user_data)
{
- SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
- SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+ GSList **list = (GSList **) user_data;
+ NMIfcfgConnection *connection = NM_IFCFG_CONNECTION (data);
+ const char *udi;
GSList *iter;
- gboolean changed = FALSE;
-
- /* Try to get the UDI for all connections that don't have a UDI yet */
- for (iter = priv->connections; iter; iter = g_slist_next (iter)) {
- NMConnection *connection = NM_CONNECTION (iter->data);
- ConnectionData *cdata = connection_data_get (connection);
-
- if (!cdata->udi) {
- cdata->udi = get_udi_for_connection (plugin, connection, devtype);
- if (cdata->udi && cdata->ignored)
- changed = TRUE;
- }
- }
- if (changed)
- g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
-}
+ if (!nm_ifcfg_connection_get_unmanaged (connection))
+ return;
-static void
-device_removed_cb (NMSystemConfigHalManager *hal_mgr,
- const char *udi,
- NMDeviceType devtype,
- gpointer user_data)
-{
- SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
- SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
- GSList *iter;
- gboolean changed = FALSE;
+ udi = nm_ifcfg_connection_get_udi (connection);
+ if (!udi)
+ return;
- /* Try to get the UDI for all connections that don't have a UDI yet */
- for (iter = priv->connections; iter; iter = g_slist_next (iter)) {
- NMConnection *connection = NM_CONNECTION (iter->data);
- ConnectionData *cdata = connection_data_get (connection);
-
- if (cdata->udi && !strcmp (cdata->udi, udi)) {
- g_free (cdata->udi);
- cdata->udi = NULL;
- if (cdata->ignored)
- changed = TRUE;
- }
+ /* Just return if the UDI is already in the list */
+ for (iter = *list; iter; iter = g_slist_next (iter)) {
+ if (!strcmp ((char *) iter->data, udi))
+ return;
}
- if (changed)
- g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
+ *list = g_slist_prepend (*list, g_strdup (udi));
}
static GSList *
get_unmanaged_devices (NMSystemConfigInterface *config)
{
- SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
- SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
- GSList *copy = NULL, *iter;
-
- for (iter = priv->connections; iter; iter = g_slist_next (iter)) {
- ConnectionData *cdata = connection_data_get (NM_CONNECTION (iter->data));
-
- if (cdata->ignored && cdata->udi)
- copy = g_slist_append (copy, g_strdup (cdata->udi));
- }
- return copy;
-}
-
-struct FindInfo {
- const char *path;
- gboolean found;
-};
-
-static void
-find_watched_path (gpointer key, gpointer value, gpointer user_data)
-{
- struct FindInfo *info = (struct FindInfo *) user_data;
+ SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (config);
+ GSList *list = NULL;
- if (info->found)
- return;
-
- if (!strcmp (info->path, value)) {
- info->found = TRUE;
- return;
- }
+ g_hash_table_foreach (priv->connections, check_unmanaged, &list);
+ return list;
}
static void
-watch_path (const char *path, const int inotify_fd, GHashTable *table)
+connection_unmanaged_changed (NMIfcfgConnection *connection,
+ GParamSpec *pspec,
+ gpointer user_data)
{
- int wd;
- struct FindInfo info;
-
- g_return_if_fail (g_path_is_absolute (path));
-
- info.found = FALSE;
- info.path = path;
- g_hash_table_foreach (table, find_watched_path, &info);
- if (info.found)
- return;
-
- wd = inotify_add_watch (inotify_fd, path,
- IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MOVE | IN_MOVE_SELF | IN_DELETE_SELF);
- if (wd == -1) {
- PLUGIN_PRINT (IFCFG_PLUGIN_NAME, " inotify error watching '%s': errno %d",
- path, errno);
- } else {
- g_hash_table_insert (table, GINT_TO_POINTER (wd), g_strdup (path));
- }
+ g_signal_emit_by_name (SC_PLUGIN_IFCFG (user_data), "unmanaged-devices-changed");
}
-static NMConnection *
-build_one_connection (SCPluginIfcfg *plugin, const char *path)
+static NMIfcfgConnection *
+read_one_connection (SCPluginIfcfg *plugin, const char *filename)
{
- NMConnection *connection;
+ SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+ NMIfcfgConnection *connection;
GError *error = NULL;
- g_return_val_if_fail (path != NULL, NULL);
-
- PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "parsing %s ... ", path);
+ PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "parsing %s ... ", filename);
- connection = parser_parse_file (path, &error);
+ connection = nm_ifcfg_connection_new (filename, priv->g_connection, priv->hal_mgr, &error);
if (connection) {
+ NMConnection *wrapped;
NMSettingConnection *s_con;
- ConnectionData *cdata = connection_data_get (connection);
- cdata->udi = get_udi_for_connection (plugin, connection, DEVICE_TYPE_UNKNOWN);
-
- s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+ wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection));
+ g_assert (wrapped);
+ s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION));
g_assert (s_con);
g_assert (s_con->id);
+
+ g_hash_table_insert (priv->connections,
+ (gpointer) nm_ifcfg_connection_get_filename (connection),
+ g_object_ref (connection));
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, " read connection '%s'", s_con->id);
+
+ if (nm_ifcfg_connection_get_unmanaged (connection)) {
+ PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' and its "
+ "device because NM_CONTROLLED was false.", s_con->id);
+ g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
+ } else {
+ /* Wait for the connection to become unmanaged once it knows the
+ * UDI of it's device, if/when the device gets plugged in.
+ */
+ g_signal_connect (G_OBJECT (connection), "notify::unmanaged",
+ G_CALLBACK (connection_unmanaged_changed), plugin);
+ }
} else {
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, " error: %s",
error->message ? error->message : "(unknown)");
+ g_error_free (error);
}
return connection;
}
-static NMConnection *
-handle_new_ifcfg (SCPluginIfcfg *plugin,
- const char *basename,
- const int inotify_fd,
- GHashTable *watch_table)
-{
- NMConnection *connection = NULL;
- ConnectionData *cdata;
- char *keys_file;
- char *path;
-
- g_return_val_if_fail (basename != NULL, NULL);
- g_return_val_if_fail (watch_table != NULL, NULL);
-
- path = g_build_filename (IFCFG_DIR, basename, NULL);
- if (!path) {
- PLUGIN_WARN (IFCFG_PLUGIN_NAME, "not enough memory for new connection.");
- return NULL;
- }
-
- connection = build_one_connection (plugin, path);
- if (!connection)
- goto out;
-
- /* Watch the file too so we can match up the watch descriptor with the
- * path we care about if the file is a hardlink.
- */
- watch_path (path, inotify_fd, watch_table);
-
- /* If there's a keys file watch that too */
- keys_file = g_strdup_printf (IFCFG_DIR KEYS_TAG "%s", basename + strlen (IFCFG_TAG));
- if (keys_file && g_file_test (keys_file, G_FILE_TEST_EXISTS))
- watch_path (keys_file, inotify_fd, watch_table);
- g_free (keys_file);
-
- cdata = connection_data_get (connection);
- if (cdata->ignored) {
- PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' and its "
- "device because NM_CONTROLLED was false.", basename);
- }
-
-out:
- g_free (path);
- return connection;
-}
-
-static void
-release_one_connection (gpointer item, gpointer user_data)
-{
- NMConnection *connection = NM_CONNECTION (item);
- SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
-
- g_signal_emit_by_name (plugin, "connection-removed", connection);
- g_object_unref (connection);
-}
-
-static void
-free_watch (gpointer key, gpointer value, gpointer user_data)
-{
- int ifd = GPOINTER_TO_INT (user_data);
- int wd = GPOINTER_TO_INT (value);
-
- if (inotify_rm_watch (ifd, wd) != 0)
- PLUGIN_WARN (IFCFG_PLUGIN_NAME, "error removing inotify watch on %s", (char *) key);
-}
-
-static void
-clear_all_connections (SCPluginIfcfg *plugin)
-{
- SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
-
- /* Remove all existing connections */
- if (priv->connections) {
- g_slist_foreach (priv->connections, release_one_connection, plugin);
- g_slist_free (priv->connections);
- priv->connections = NULL;
- }
-
- if (priv->watch_table) {
- g_hash_table_foreach (priv->watch_table, free_watch, GINT_TO_POINTER (priv->ifd));
- g_hash_table_destroy (priv->watch_table);
- priv->watch_table = NULL;
- }
-}
-
-static void
-kill_old_auto_wired_file (void)
+static gboolean
+should_ignore_file (const char *basename, const char *tag)
{
- char *path;
- const char *match = "# Written by nm-system-settings\nTYPE=Ethernet\nBOOTPROTO=dhcp\nONBOOT=yes\nUSERCTL=yes\nPEERDNS=yes\n";
- char *contents = NULL;
- gsize length = 0;
-
- path = g_strdup_printf (IFCFG_DIR "/ifcfg-Auto Wired");
- if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
- g_free (path);
- return;
- }
-
- if (!g_file_get_contents (path, &contents, &length, NULL))
- goto out;
-
- if (!length && !contents)
- goto out;
-
- if ( (length != strlen (match))
- && (length != (strlen (match) - 1))
- && (length != (strlen (match) + 1)))
- goto out;
-
- if (strncmp (contents, match, MIN (length, strlen (match))))
- goto out;
+ int len, tag_len;
- unlink (path);
+ g_return_val_if_fail (basename != NULL, TRUE);
+ g_return_val_if_fail (tag != NULL, TRUE);
-out:
- g_free (contents);
- g_free (path);
+ len = strlen (basename);
+ tag_len = strlen (tag);
+ if ((len > tag_len) && !strcasecmp (basename + len - tag_len, tag))
+ return TRUE;
+ return FALSE;
}
static void
-read_all_connections (SCPluginIfcfg *plugin)
+read_connections (SCPluginIfcfg *plugin)
{
- SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
GDir *dir;
- const char *item;
+ GError *err = NULL;
- clear_all_connections (plugin);
-
- priv->watch_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
-
- dir = g_dir_open (IFCFG_DIR, 0, NULL);
+ dir = g_dir_open (IFCFG_DIR, 0, &err);
if (dir) {
+ const char *item;
+
while ((item = g_dir_read_name (dir))) {
- NMConnection *connection;
- ConnectionData *cdata;
+ char *full_path;
if (strncmp (item, IFCFG_TAG, strlen (IFCFG_TAG)))
continue;
- connection = handle_new_ifcfg (plugin, item, priv->ifd, priv->watch_table);
- if (connection) {
- priv->connections = g_slist_append (priv->connections, connection);
- cdata = connection_data_get (connection);
- if (cdata->ignored && cdata->udi)
- g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
- }
- }
- g_dir_close (dir);
- } else {
- PLUGIN_WARN (IFCFG_PLUGIN_NAME, "couldn't access network config directory '" IFCFG_DIR "'.");
- }
-
- kill_old_auto_wired_file ();
-}
-
-static GSList *
-get_connections (NMSystemConfigInterface *config)
-{
- SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
- SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
- GSList *list = NULL, *iter;
-
- if (!priv->initialized)
- read_all_connections (plugin);
+ /* ignore some files */
+ if ( should_ignore_file (item, BAK_TAG)
+ || should_ignore_file (item, TILDE_TAG)
+ || should_ignore_file (item, ORIG_TAG)
+ || should_ignore_file (item, REJ_TAG))
+ continue;
- for (iter = priv->connections; iter; iter = g_slist_next (iter)) {
- NMConnection *connection = NM_CONNECTION (iter->data);
- ConnectionData *cdata;
-
- cdata = connection_data_get (connection);
- if (!cdata->ignored) {
- list = g_slist_append (list, connection);
- cdata->exported = TRUE;
+ full_path = g_build_filename (IFCFG_DIR, item, NULL);
+ read_one_connection (plugin, full_path);
+ g_free (full_path);
}
- }
- return list;
-}
-
-static GValue *
-string_to_gvalue (const char *str)
-{
- GValue *val;
-
- val = g_slice_new0 (GValue);
- g_value_init (val, G_TYPE_STRING);
- g_value_set_string (val, str);
-
- return val;
-}
-
-static void
-add_one_secret (gpointer key, gpointer data, gpointer user_data)
-{
- g_hash_table_insert ((GHashTable *) user_data, g_strdup (key), string_to_gvalue (data));
-}
-
-static void
-destroy_gvalue (gpointer data)
-{
- GValue *value = (GValue *) data;
-
- g_value_unset (value);
- g_slice_free (GValue, value);
-}
-
-static GHashTable *
-get_secrets (NMSystemConfigInterface *config,
- NMConnection *connection,
- NMSetting *setting)
-{
- GHashTable *settings;
- ConnectionData *cdata;
- GHashTable *secrets;
-
- cdata = connection_data_get (connection);
- if (!cdata)
- return NULL;
-
- settings = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) g_hash_table_destroy);
-
- if (cdata->wifi_secrets) {
- secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_gvalue);
- g_hash_table_foreach (cdata->wifi_secrets, add_one_secret, secrets);
- g_hash_table_insert (settings, g_strdup (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME), secrets);
- }
-
- if (cdata->onex_secrets) {
- secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_gvalue);
- g_hash_table_foreach (cdata->onex_secrets, add_one_secret, secrets);
- g_hash_table_insert (settings, g_strdup (NM_SETTING_802_1X_SETTING_NAME), secrets);
+ g_dir_close (dir);
+ } else {
+ PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Can not read directory '%s': %s", IFCFG_DIR, err->message);
+ g_error_free (err);
}
-
- /* FIXME: PPP secrets (which are actually split out into GSM/CDMA/etc */
-
- return settings;
}
-static NMConnection *
-find_connection_by_path (GSList *connections, const char *path)
-{
- GSList *iter;
-
- g_return_val_if_fail (path != NULL, NULL);
-
- for (iter = connections; iter; iter = g_slist_next (iter)) {
- NMConnection *list_connection = NM_CONNECTION (iter->data);
- ConnectionData *cdata;
-
- cdata = connection_data_get (list_connection);
- g_assert (cdata);
- if (cdata->ifcfg_path && !strcmp (cdata->ifcfg_path, path))
- return list_connection;
- }
- return NULL;
-}
+/* Monitoring */
static void
-handle_connection_changed (SCPluginIfcfg *plugin,
- const char *basename)
+dir_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
{
+ SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
- char *filename = NULL;
- NMConnection *new_connection;
- NMConnection *existing;
- ConnectionData *new_cdata;
- GHashTable *new_settings;
- ConnectionData *existing_cdata;
- gboolean remove = FALSE;
-
- if (!strncmp (basename, IFCFG_TAG, strlen (IFCFG_TAG))) {
- filename = g_strdup_printf (IFCFG_DIR "%s", basename);
- } else if (!strncmp (basename, KEYS_TAG, strlen (KEYS_TAG))) {
- filename = g_strdup_printf (IFCFG_DIR IFCFG_TAG "%s", basename + strlen (KEYS_TAG));
- } else {
- PLUGIN_WARN (IFCFG_PLUGIN_NAME, "ignored event for '%s'.", basename);
- return;
- }
+ char *name;
+ NMIfcfgConnection *connection;
+ gboolean do_remove = FALSE, do_new = FALSE;
+
+ name = g_file_get_path (file);
+ connection = g_hash_table_lookup (priv->connections, name);
+
+ switch (event_type) {
+ case G_FILE_MONITOR_EVENT_DELETED:
+ if (connection) {
+ PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "removed %s.", name);
+ do_remove = TRUE;
+ }
+ break;
+ case G_FILE_MONITOR_EVENT_CREATED:
+ case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+ if (connection) {
+ /* Update */
+ NMIfcfgConnection *tmp;
+ GError *error = NULL;
+
+ PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "updating %s", name);
+
+ tmp = (NMIfcfgConnection *) nm_ifcfg_connection_new (name, priv->g_connection, priv->hal_mgr, &error);
+ if (tmp) {
+ GHashTable *settings;
+ gboolean new_unmanaged, old_unmanaged;
+
+ old_unmanaged = nm_ifcfg_connection_get_unmanaged (NM_IFCFG_CONNECTION (connection));
+ new_unmanaged = nm_ifcfg_connection_get_unmanaged (NM_IFCFG_CONNECTION (tmp));
+
+ if (new_unmanaged) {
+ if (!old_unmanaged) {
+ /* Unexport the connection by destroying it, then re-creating it as unmanaged */
+ do_remove = do_new = TRUE;
+ }
+ } else {
+ NMConnection *old_wrapped, *new_wrapped;
+
+ if (old_unmanaged) /* no longer unmanaged */
+ g_signal_emit_by_name (plugin, "connection-added", connection);
+
+ new_wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (tmp));
+ old_wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection));
+
+ /* Only update if different */
+ if (!nm_connection_compare (new_wrapped, old_wrapped, COMPARE_FLAGS_EXACT)) {
+ settings = nm_connection_to_hash (new_wrapped);
+ nm_exported_connection_update (NM_EXPORTED_CONNECTION (connection), settings, NULL);
+ g_hash_table_destroy (settings);
+ }
- if (!filename) {
- PLUGIN_WARN (IFCFG_PLUGIN_NAME, "not enough memory to update connection.");
- return;
- }
+ /* Update unmanaged status */
+ g_object_set (connection, "unmanaged", new_unmanaged, NULL);
+ g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
+ }
+ g_object_unref (tmp);
+ } else {
+ /* couldn't read connection; remove it */
- /* Could return NULL if the connection got deleted */
- new_connection = build_one_connection (plugin, filename);
+ PLUGIN_WARN (IFCFG_PLUGIN_NAME, " error: %s",
+ error->message ? error->message : "(unknown)");
+ g_error_free (error);
- existing = find_connection_by_path (priv->connections, filename);
- if (!existing) {
- if (new_connection) {
- new_cdata = connection_data_get (new_connection);
- g_assert (new_cdata);
-
- /* totally new connection */
- priv->connections = g_slist_append (priv->connections, new_connection);
- if (!new_cdata->ignored) {
- new_cdata->exported = TRUE;
- g_signal_emit_by_name (plugin, "connection-added", new_connection);
- } else {
- PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' and its "
- "device because NM_CONTROLLED was false.", basename);
- if (new_cdata->udi)
- g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
+ PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "removed %s.", name);
+ do_remove = TRUE;
}
+ } else {
+ do_new = TRUE;
}
- g_free (filename);
- return;
+ break;
+ default:
+ break;
}
- existing_cdata = connection_data_get (existing);
- g_assert (existing_cdata);
+ if (do_remove) {
+ gboolean unmanaged = nm_ifcfg_connection_get_unmanaged (connection);
- if (new_connection) {
- /* update the settings of the existing connection for this
- * ifcfg file and notify listeners that something has changed.
- */
- new_settings = nm_connection_to_hash (new_connection);
- if (!nm_connection_replace_settings (existing, new_settings)) {
- /* couldn't replace the settings for some reason; have to
- * remove the connection then.
- */
- PLUGIN_WARN (IFCFG_PLUGIN_NAME, "couldn't update connection for '%s'.", filename);
- remove = TRUE;
- } else {
- /* Success */
- new_cdata = connection_data_get (new_connection);
- g_assert (new_cdata);
-
- connection_data_copy_secrets (new_cdata, existing_cdata);
- g_free (existing_cdata->udi);
- existing_cdata->udi = new_cdata->udi ? g_strdup (new_cdata->udi) : NULL;
-
- if (new_cdata->ignored && !existing_cdata->ignored) {
- /* connection now ignored */
- PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' and its "
- "device because NM_CONTROLLED was false.", basename);
-
- existing_cdata->ignored = TRUE;
- g_signal_emit_by_name (plugin, "connection-removed", existing);
- existing_cdata->exported = FALSE;
- if (existing_cdata->udi)
- g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
- } else if (!new_cdata->ignored && existing_cdata->ignored) {
- /* connection no longer ignored, let the system settings
- * service know about it now.
- */
- existing_cdata->ignored = FALSE;
- existing_cdata->exported = TRUE;
- if (existing_cdata->udi)
- g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
- g_signal_emit_by_name (plugin, "connection-added", existing);
- } else if (!new_cdata->ignored && !existing_cdata->ignored) {
- /* connection updated and not ignored */
- g_signal_emit_by_name (plugin, "connection-updated", existing);
- } else if (new_cdata->ignored && existing_cdata->ignored) {
- if (existing_cdata->udi)
- g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
- }
- }
- g_object_unref (new_connection);
- } else {
- remove = TRUE;
+ g_hash_table_remove (priv->connections, name);
+ nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (connection));
+
+ /* Emit unmanaged changes _after_ removing the connection */
+ if (unmanaged)
+ g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
}
- if (remove) {
- priv->connections = g_slist_remove (priv->connections, existing);
- if (!existing_cdata->ignored)
- g_signal_emit_by_name (plugin, "connection-removed", existing);
- else {
- if (existing_cdata->udi)
- g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
+ if (do_new) {
+ connection = read_one_connection (plugin, name);
+ if (connection) {
+ if (!nm_ifcfg_connection_get_unmanaged (NM_IFCFG_CONNECTION (connection)))
+ g_signal_emit_by_name (plugin, "connection-added", connection);
}
- g_object_unref (existing);
- PLUGIN_PRINT (IFCFG_PLUGIN_NAME, " removed connection");
}
- g_free (filename);
+ g_free (name);
}
static void
-handle_new_item (SCPluginIfcfg *plugin, const char *basename)
+setup_monitoring (SCPluginIfcfg *plugin)
{
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
- NMConnection *connection;
- ConnectionData *cdata;
- char *ifcfgfile;
-
- if (!strncmp (basename, KEYS_TAG, strlen (KEYS_TAG))) {
- ifcfgfile = g_strdup_printf (IFCFG_TAG "%s", basename + strlen (KEYS_TAG));
- handle_connection_changed (plugin, ifcfgfile);
- g_free (ifcfgfile);
- return;
- }
+ GFile *file;
+ GFileMonitor *monitor;
- if (strncmp (basename, IFCFG_TAG, strlen (IFCFG_TAG)))
- return;
+ priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
- /* New connection */
- connection = handle_new_ifcfg (plugin, basename, priv->ifd, priv->watch_table);
- if (!connection)
- return;
+ file = g_file_new_for_path (IFCFG_DIR);
+ monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
+ g_object_unref (file);
- cdata = connection_data_get (connection);
- g_assert (cdata);
-
- /* new connection */
- priv->connections = g_slist_append (priv->connections, connection);
- if (!cdata->ignored) {
- cdata->exported = TRUE;
- g_signal_emit_by_name (plugin, "connection-added", connection);
- } else {
- if (cdata->udi)
- g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
+ if (monitor) {
+ priv->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (dir_changed), plugin);
+ priv->monitor = monitor;
}
}
-static gboolean
-should_ignore_file (const char *basename, const char *tag)
+static void
+hash_to_slist (gpointer key, gpointer value, gpointer user_data)
{
- int len, tag_len;
-
- g_return_val_if_fail (basename != NULL, TRUE);
- g_return_val_if_fail (tag != NULL, TRUE);
+ NMIfcfgConnection *exported = NM_IFCFG_CONNECTION (value);
+ GSList **list = (GSList **) user_data;
- len = strlen (basename);
- tag_len = strlen (tag);
- if ((len > tag_len) && !strcasecmp (basename + len - tag_len, tag))
- return TRUE;
- return FALSE;
+ if (!nm_ifcfg_connection_get_unmanaged (exported))
+ *list = g_slist_prepend (*list, value);
}
-static gboolean
-stuff_changed (GIOChannel *channel, GIOCondition cond, gpointer user_data)
+static GSList *
+get_connections (NMSystemConfigInterface *config)
{
- SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
+ SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
- struct inotify_event evt;
-
- /* read the notifications from the watch descriptor */
- while (g_io_channel_read_chars (channel, (gchar *) &evt, sizeof (struct inotify_event), NULL, NULL) == G_IO_STATUS_NORMAL) {
- const char *path;
- gchar filename[PATH_MAX + 1];
-
- path = g_hash_table_lookup (priv->watch_table, GINT_TO_POINTER (evt.wd));
-
- filename[0] = '\0';
- if (evt.len > 0) {
- g_io_channel_read_chars (channel,
- filename,
- evt.len > PATH_MAX ? PATH_MAX : evt.len,
- NULL, NULL);
- }
-
- if (!path && !strlen (filename))
- continue;
-
- if (evt.wd == priv->wd) {
- if ( strncmp (filename, IFCFG_TAG, strlen (IFCFG_TAG))
- && strncmp (filename, KEYS_TAG, strlen (KEYS_TAG)))
- continue;
-
- /* ignore some files */
- if ( should_ignore_file (filename, BAK_TAG)
- || should_ignore_file (filename, TILDE_TAG)
- || should_ignore_file (filename, ORIG_TAG)
- || should_ignore_file (filename, REJ_TAG))
- continue;
+ GSList *list = NULL;
- if (evt.mask & (IN_CREATE | IN_MOVED_TO)) {
- handle_new_item (plugin, filename);
- } else if (evt.mask & (IN_DELETE | IN_MOVED_FROM)) {
- /* Remove connection */
- handle_connection_changed (plugin, filename);
- } else if (evt.mask & IN_CLOSE_WRITE) {
- /* Updated connection */
- handle_connection_changed (plugin, filename);
- }
- } else {
- /* Track deletions and moves of the file itself */
- if ( (evt.mask & IN_DELETE_SELF)
- || ((evt.mask & IN_MOVE_SELF) && path && !g_file_test (path, G_FILE_TEST_EXISTS))) {
- char *basename;
-
- inotify_rm_watch (priv->ifd, evt.wd);
- g_hash_table_remove (priv->watch_table, GINT_TO_POINTER (evt.wd));
-
- /* Remove connection */
- basename = g_path_get_basename (path);
- handle_connection_changed (plugin, basename);
- g_free (basename);
- }
- }
+ if (!priv->connections) {
+ setup_monitoring (plugin);
+ read_connections (plugin);
}
- return TRUE;
-}
-
-static gboolean
-sc_plugin_inotify_init (SCPluginIfcfg *plugin, GError **error)
-{
- SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
- GIOChannel *channel;
- guint source_id;
- int ifd, wd;
-
- ifd = inotify_init ();
- if (ifd == -1) {
- g_set_error (error, ifcfg_plugin_error_quark (), 0,
- "Couldn't initialize inotify");
- return FALSE;
- }
-
- wd = inotify_add_watch (ifd, IFCFG_DIR,
- IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MOVE);
- if (wd == -1) {
- g_set_error (error, ifcfg_plugin_error_quark (), 0,
- "Couldn't monitor " IFCFG_DIR);
- close (ifd);
- return FALSE;
- }
-
- priv->ifd = ifd;
- priv->wd = wd;
-
- /* Watch the inotify descriptor for file/directory change events */
- channel = g_io_channel_unix_new (ifd);
- if (!channel) {
- g_set_error (error, ifcfg_plugin_error_quark (), 0,
- "Couldn't create new GIOChannel");
- close (ifd);
- return FALSE;
- }
- g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
- g_io_channel_set_encoding (channel, NULL, NULL);
-
- source_id = g_io_add_watch (channel,
- G_IO_IN | G_IO_ERR,
- (GIOFunc) stuff_changed,
- plugin);
- g_io_channel_unref (channel);
+ g_hash_table_foreach (priv->connections, hash_to_slist, &list);
- return TRUE;
+ return list;
}
static void
@@ -890,17 +377,8 @@
{
SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
- GError *error = NULL;
-
- if (!sc_plugin_inotify_init (plugin, &error)) {
- PLUGIN_PRINT (IFCFG_PLUGIN_NAME, " inotify error: %s",
- error->message ? error->message : "(unknown)");
- g_error_free (error);
- }
priv->hal_mgr = g_object_ref (hal_manager);
- g_signal_connect (priv->hal_mgr, "device-added", G_CALLBACK (device_added_cb), config);
- g_signal_connect (priv->hal_mgr, "device-removed", G_CALLBACK (device_removed_cb), config);
}
static void
@@ -923,13 +401,22 @@
SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (object);
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
- clear_all_connections (plugin);
-
g_object_unref (priv->hal_mgr);
if (priv->g_connection)
dbus_g_connection_unref (priv->g_connection);
+ if (priv->connections)
+ g_hash_table_destroy (priv->connections);
+
+ if (priv->monitor) {
+ if (priv->monitor_id)
+ g_signal_handler_disconnect (priv->monitor, priv->monitor_id);
+
+ g_file_monitor_cancel (priv->monitor);
+ g_object_unref (priv->monitor);
+ }
+
G_OBJECT_CLASS (sc_plugin_ifcfg_parent_class)->dispose (object);
}
@@ -981,7 +468,6 @@
{
/* interface implementation */
system_config_interface_class->get_connections = get_connections;
- system_config_interface_class->get_secrets = get_secrets;
system_config_interface_class->get_unmanaged_devices = get_unmanaged_devices;
system_config_interface_class->init = init;
}
Added: trunk/system-settings/plugins/ifcfg-fedora/reader.c
==============================================================================
--- (empty file)
+++ trunk/system-settings/plugins/ifcfg-fedora/reader.c Sun May 11 20:20:52 2008
@@ -0,0 +1,905 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <sys/inotify.h>
+#include <errno.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <netinet/ether.h>
+
+#ifndef __user
+#define __user
+#endif
+#include <linux/types.h>
+#include <wireless.h>
+#undef __user
+
+#include <glib.h>
+#include <nm-connection.h>
+#include <NetworkManager.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-ip4-config.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-wireless.h>
+#include <nm-utils.h>
+
+#include "common.h"
+#include "shvar.h"
+
+#include "reader.h"
+
+#define TYPE_ETHERNET "Ethernet"
+#define TYPE_WIRELESS "Wireless"
+
+static char *
+get_ifcfg_name (const char *file)
+{
+ char *ifcfg_name;
+ char *basename;
+
+ basename = g_path_get_basename (file);
+ if (!basename)
+ return NULL;
+
+ ifcfg_name = g_strdup (basename + strlen (IFCFG_TAG));
+ g_free (basename);
+ return ifcfg_name;
+}
+
+static gboolean
+get_int (const char *str, int *value)
+{
+ char *e;
+
+ *value = strtol (str, &e, 0);
+ if (*e != '\0')
+ return FALSE;
+
+ return TRUE;
+}
+
+static NMSetting *
+make_connection_setting (const char *file,
+ shvarFile *ifcfg,
+ const char *type,
+ const char *suggested)
+{
+ NMSettingConnection *s_con;
+ char *ifcfg_name = NULL;
+
+ ifcfg_name = get_ifcfg_name (file);
+ if (!ifcfg_name)
+ return NULL;
+
+ s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+
+ if (suggested) {
+ /* For cosmetic reasons, if the suggested name is the same as
+ * the ifcfg files name, don't use it.
+ */
+ if (strcmp (ifcfg_name, suggested))
+ s_con->id = g_strdup_printf ("System %s (%s)", suggested, ifcfg_name);
+ }
+
+ if (!s_con->id)
+ s_con->id = g_strdup_printf ("System %s", ifcfg_name);
+
+ s_con->type = g_strdup (type);
+
+ /* Be somewhat conservative about autoconnect */
+ if (svTrueValue (ifcfg, "ONBOOT", FALSE))
+ s_con->autoconnect = TRUE;
+
+ g_free (ifcfg_name);
+ return (NMSetting *) s_con;
+}
+
+static void
+get_one_ip4_addr (shvarFile *ifcfg,
+ const char *tag,
+ guint32 *out_addr,
+ GError **error)
+{
+ char *value = NULL;
+ struct in_addr ip4_addr;
+
+ g_return_if_fail (ifcfg != NULL);
+ g_return_if_fail (tag != NULL);
+ g_return_if_fail (out_addr != NULL);
+ g_return_if_fail (error != NULL);
+ g_return_if_fail (*error == NULL);
+
+ value = svGetValue (ifcfg, tag);
+ if (!value)
+ return;
+
+ if (inet_pton (AF_INET, value, &ip4_addr))
+ *out_addr = ip4_addr.s_addr;
+ else {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Invalid %s IP4 address '%s'", tag, value);
+ }
+ g_free (value);
+}
+
+#define GET_ONE_DNS(tag) \
+ { \
+ guint32 dns = 0; \
+ get_one_ip4_addr (ifcfg, tag, &dns, error); \
+ if (*error) \
+ goto error; \
+ if (dns) \
+ g_array_append_val (s_ip4->dns, dns); \
+ }
+
+
+static NMSetting *
+make_ip4_setting (shvarFile *ifcfg, GError **error)
+{
+ NMSettingIP4Config *s_ip4 = NULL;
+ char *value = NULL;
+ NMSettingIP4Address tmp = { 0, 0, 0 };
+ char *method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
+
+ value = svGetValue (ifcfg, "BOOTPROTO");
+ if (value && (!g_ascii_strcasecmp (value, "bootp") || !g_ascii_strcasecmp (value, "dhcp")))
+ method = NM_SETTING_IP4_CONFIG_METHOD_DHCP;
+
+ if (value && !g_ascii_strcasecmp (value, "autoip")) {
+ method = NM_SETTING_IP4_CONFIG_METHOD_AUTOIP;
+ goto done;
+ }
+
+ get_one_ip4_addr (ifcfg, "IPADDR", &tmp.address, error);
+ if (*error)
+ goto error;
+
+ get_one_ip4_addr (ifcfg, "GATEWAY", &tmp.gateway, error);
+ if (*error)
+ goto error;
+
+ get_one_ip4_addr (ifcfg, "NETMASK", &tmp.netmask, error);
+ if (*error)
+ goto error;
+
+
+done:
+ s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+ s_ip4->method = g_strdup (method);
+ if (tmp.address || tmp.netmask || tmp.gateway) {
+ NMSettingIP4Address *addr;
+ addr = g_new0 (NMSettingIP4Address, 1);
+ memcpy (addr, &tmp, sizeof (NMSettingIP4Address));
+ s_ip4->addresses = g_slist_append (s_ip4->addresses, addr);
+ }
+
+ /* No DNS for autoip */
+ if (g_ascii_strcasecmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTOIP)) {
+ s_ip4->dns = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3);
+
+ GET_ONE_DNS("DNS1");
+ GET_ONE_DNS("DNS2");
+ GET_ONE_DNS("DNS3");
+
+ if (s_ip4->dns && !s_ip4->dns->len) {
+ g_array_free (s_ip4->dns, TRUE);
+ s_ip4->dns = NULL;
+ }
+
+ /* DNS searches */
+ value = svGetValue (ifcfg, "SEARCH");
+ if (value) {
+ char **searches = NULL;
+
+ searches = g_strsplit (value, " ", 0);
+ if (searches) {
+ char **item;
+ for (item = searches; *item; item++)
+ s_ip4->dns_search = g_slist_append (s_ip4->dns_search, *item);
+ g_free (searches);
+ }
+ }
+ }
+
+ return NM_SETTING (s_ip4);
+
+error:
+ g_free (value);
+ if (s_ip4)
+ g_object_unref (s_ip4);
+ return NULL;
+}
+
+/*
+ * utils_bin2hexstr
+ *
+ * Convert a byte-array into a hexadecimal string.
+ *
+ * Code originally by Alex Larsson <alexl redhat com> and
+ * copyright Red Hat, Inc. under terms of the LGPL.
+ *
+ */
+static char *
+utils_bin2hexstr (const char *bytes, int len, int final_len)
+{
+ static char hex_digits[] = "0123456789abcdef";
+ char * result;
+ int i;
+
+ g_return_val_if_fail (bytes != NULL, NULL);
+ g_return_val_if_fail (len > 0, NULL);
+ g_return_val_if_fail (len < 256, NULL); /* Arbitrary limit */
+
+ result = g_malloc0 (len * 2 + 1);
+ for (i = 0; i < len; i++)
+ {
+ result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf];
+ result[2*i+1] = hex_digits[bytes[i] & 0xf];
+ }
+ /* Cut converted key off at the correct length for this cipher type */
+ if (final_len > -1)
+ result[final_len] = '\0';
+
+ return result;
+}
+
+static gboolean
+read_mac_address (shvarFile *ifcfg, GByteArray **array, GError **error)
+{
+ char *value = NULL;
+ struct ether_addr *mac;
+
+ g_return_val_if_fail (ifcfg != NULL, FALSE);
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (*array == NULL, FALSE);
+ g_return_val_if_fail (error != NULL, FALSE);
+ g_return_val_if_fail (*error == NULL, FALSE);
+
+ value = svGetValue (ifcfg, "HWADDR");
+ if (!value || !strlen (value)) {
+ g_free (value);
+ return TRUE;
+ }
+
+ mac = ether_aton (value);
+ if (!mac) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "The MAC address '%s' was invalid.", value);
+ goto error;
+ }
+
+ *array = g_byte_array_sized_new (ETH_ALEN);
+ g_byte_array_append (*array, (guint8 *) mac->ether_addr_octet, ETH_ALEN);
+
+ return TRUE;
+
+error:
+ g_free (value);
+ if (*array) {
+ g_byte_array_free (*array, TRUE);
+ *array = NULL;
+ }
+ return FALSE;
+}
+
+static gboolean
+add_one_wep_key (shvarFile *ifcfg,
+ const char *shvar_key,
+ guint8 key_idx,
+ NMSettingWirelessSecurity *s_wsec,
+ GError **error)
+{
+ char *key = NULL;
+ char *value = NULL;
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (ifcfg != NULL, FALSE);
+ g_return_val_if_fail (shvar_key != NULL, FALSE);
+ g_return_val_if_fail (key_idx <= 3, FALSE);
+ g_return_val_if_fail (s_wsec != NULL, FALSE);
+
+ value = svGetValue (ifcfg, shvar_key);
+ if (!value || !strlen (value)) {
+ g_free (value);
+ return TRUE;
+ }
+
+ /* Validate keys */
+ if (strlen (value) == 10 || strlen (value) == 26) {
+ /* Hexadecimal WEP key */
+ char *p = value;
+
+ while (*p) {
+ if (!g_ascii_isxdigit (*p)) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Invalid hexadecimal WEP key.");
+ goto out;
+ }
+ p++;
+ }
+ key = g_strdup (value);
+ } else if (strlen (value) == 5 || strlen (value) == 13) {
+ /* ASCII passphrase */
+ char *p = value;
+
+ while (*p) {
+ if (!isascii ((int) (*p))) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Invalid ASCII WEP passphrase.");
+ goto out;
+ }
+ p++;
+ }
+
+ key = utils_bin2hexstr (value, strlen (value), strlen (value) * 2);
+ } else {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0, "Invalid WEP key length.");
+ }
+
+ if (key) {
+ if (key_idx == 0)
+ s_wsec->wep_key0 = key;
+ else if (key_idx == 1)
+ s_wsec->wep_key1 = key;
+ else if (key_idx == 2)
+ s_wsec->wep_key2 = key;
+ else if (key_idx == 3)
+ s_wsec->wep_key3 = key;
+ else
+ g_assert_not_reached ();
+ success = TRUE;
+ }
+
+out:
+ g_free (value);
+ return success;
+}
+
+static shvarFile *
+get_keys_ifcfg (const char *parent)
+{
+ char *ifcfg_name;
+ char *keys_file = NULL;
+ char *tmp = NULL;
+ shvarFile *ifcfg = NULL;
+
+ ifcfg_name = get_ifcfg_name (parent);
+ if (!ifcfg_name)
+ return NULL;
+
+ tmp = g_path_get_dirname (parent);
+ if (!tmp)
+ goto out;
+
+ keys_file = g_strdup_printf ("%s/" KEYS_TAG "%s", tmp, ifcfg_name);
+ if (!keys_file)
+ goto out;
+
+ ifcfg = svNewFile (keys_file);
+
+out:
+ g_free (keys_file);
+ g_free (tmp);
+ g_free (ifcfg_name);
+ return ifcfg;
+}
+
+static gboolean
+read_wep_keys (shvarFile *ifcfg,
+ guint8 def_idx,
+ NMSettingWirelessSecurity *s_wsec,
+ GError **error)
+{
+ if (!add_one_wep_key (ifcfg, "KEY1", 0, s_wsec, error))
+ return FALSE;
+ if (!add_one_wep_key (ifcfg, "KEY2", 1, s_wsec, error))
+ return FALSE;
+ if (!add_one_wep_key (ifcfg, "KEY3", 2, s_wsec, error))
+ return FALSE;
+ if (!add_one_wep_key (ifcfg, "KEY4", 3, s_wsec, error))
+ return FALSE;
+ if (!add_one_wep_key (ifcfg, "KEY", def_idx, s_wsec, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static NMSetting *
+make_wireless_security_setting (shvarFile *ifcfg,
+ const char *file,
+ GError **error)
+{
+ NMSettingWirelessSecurity *s_wireless_sec;
+ char *value;
+ shvarFile *keys_ifcfg = NULL;
+ int default_key_idx = 0;
+
+ s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
+
+ value = svGetValue (ifcfg, "DEFAULTKEY");
+ if (value) {
+ gboolean success;
+
+ success = get_int (value, &default_key_idx);
+ if (success && (default_key_idx >= 1) && (default_key_idx <= 4)) {
+ default_key_idx--; /* convert to [0...3] */
+ s_wireless_sec->wep_tx_keyidx = default_key_idx;
+ } else {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Invalid default WEP key '%s'", value);
+ g_free (value);
+ goto error;
+ }
+ g_free (value);
+ }
+
+ /* Read keys in the ifcfg file */
+ if (!read_wep_keys (ifcfg, default_key_idx, s_wireless_sec, error))
+ goto error;
+
+ /* Try to get keys from the "shadow" key file */
+ keys_ifcfg = get_keys_ifcfg (file);
+ if (keys_ifcfg) {
+ if (!read_wep_keys (keys_ifcfg, default_key_idx, s_wireless_sec, error)) {
+ svCloseFile (keys_ifcfg);
+ goto error;
+ }
+ svCloseFile (keys_ifcfg);
+ }
+
+ /* If there's a default key, ensure that key exists */
+ if ((default_key_idx == 1) && !s_wireless_sec->wep_key1) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Default WEP key index was 2, but no valid KEY2 exists.");
+ goto error;
+ } else if ((default_key_idx == 2) && !s_wireless_sec->wep_key2) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Default WEP key index was 3, but no valid KEY3 exists.");
+ goto error;
+ } else if ((default_key_idx == 3) && !s_wireless_sec->wep_key3) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Default WEP key index was 4, but no valid KEY4 exists.");
+ goto error;
+ }
+
+ value = svGetValue (ifcfg, "SECURITYMODE");
+ if (value) {
+ char *lcase;
+
+ lcase = g_ascii_strdown (value, -1);
+ g_free (value);
+
+ if (!strcmp (lcase, "open")) {
+ s_wireless_sec->auth_alg = g_strdup ("open");
+ } else if (!strcmp (lcase, "restricted")) {
+ s_wireless_sec->auth_alg = g_strdup ("shared");
+ } else {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Invalid WEP authentication algoritm '%s'",
+ lcase);
+ g_free (lcase);
+ goto error;
+ }
+ g_free (lcase);
+ }
+
+ if ( !s_wireless_sec->wep_key0
+ && !s_wireless_sec->wep_key1
+ && !s_wireless_sec->wep_key2
+ && !s_wireless_sec->wep_key3
+ && !s_wireless_sec->wep_tx_keyidx) {
+ if (s_wireless_sec->auth_alg && !strcmp (s_wireless_sec->auth_alg, "shared")) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "WEP Shared Key authentication is invalid for "
+ "unencrypted connections.");
+ goto error;
+ }
+
+ /* Unencrypted */
+ g_object_unref (s_wireless_sec);
+ s_wireless_sec = NULL;
+ } else {
+ // FIXME: WEP-only for now
+ s_wireless_sec->key_mgmt = g_strdup ("none");
+ }
+
+ return (NMSetting *) s_wireless_sec;
+
+error:
+ if (s_wireless_sec)
+ g_object_unref (s_wireless_sec);
+ return NULL;
+}
+
+
+static NMSetting *
+make_wireless_setting (shvarFile *ifcfg,
+ NMSetting *security,
+ GError **error)
+{
+ NMSettingWireless *s_wireless;
+ char *value;
+
+ s_wireless = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
+
+ value = svGetValue (ifcfg, "ESSID");
+ if (value) {
+ gsize len = strlen (value);
+
+ if (len > 32 || len == 0) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Invalid SSID '%s' (size %zu not between 1 and 32 inclusive)",
+ value, len);
+ goto error;
+ }
+
+ s_wireless->ssid = g_byte_array_sized_new (strlen (value));
+ g_byte_array_append (s_wireless->ssid, (const guint8 *) value, len);
+ g_free (value);
+ } else {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0, "Missing SSID");
+ goto error;
+ }
+
+ value = svGetValue (ifcfg, "MODE");
+ if (value) {
+ char *lcase;
+
+ lcase = g_ascii_strdown (value, -1);
+ g_free (value);
+
+ if (!strcmp (lcase, "ad-hoc")) {
+ s_wireless->mode = g_strdup ("adhoc");
+ } else if (!strcmp (lcase, "managed")) {
+ s_wireless->mode = g_strdup ("infrastructure");
+ } else {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Invalid mode '%s' (not ad-hoc or managed)",
+ lcase);
+ g_free (lcase);
+ goto error;
+ }
+ g_free (lcase);
+ }
+
+ if (security)
+ s_wireless->security = g_strdup (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+
+ if (!read_mac_address (ifcfg, &s_wireless->mac_address, error)) {
+ g_object_unref (s_wireless);
+ s_wireless = NULL;
+ }
+
+ // FIXME: channel/freq, other L2 parameters like RTS
+
+ return NM_SETTING (s_wireless);
+
+error:
+ if (s_wireless)
+ g_object_unref (s_wireless);
+ return NULL;
+}
+
+static NMConnection *
+wireless_connection_from_ifcfg (const char *file, shvarFile *ifcfg, GError **error)
+{
+ NMConnection *connection = NULL;
+ NMSetting *con_setting = NULL;
+ NMSetting *wireless_setting = NULL;
+ NMSettingWireless *tmp;
+ NMSetting *security_setting = NULL;
+ char *printable_ssid = NULL;
+
+ g_return_val_if_fail (file != NULL, NULL);
+ g_return_val_if_fail (ifcfg != NULL, NULL);
+ g_return_val_if_fail (error != NULL, NULL);
+ g_return_val_if_fail (*error == NULL, NULL);
+
+ connection = nm_connection_new ();
+ if (!connection) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Failed to allocate new connection for %s.", file);
+ return NULL;
+ }
+
+ /* Wireless security */
+ security_setting = make_wireless_security_setting (ifcfg, file, error);
+ if (*error)
+ goto error;
+ if (security_setting)
+ nm_connection_add_setting (connection, security_setting);
+
+ /* Wireless */
+ wireless_setting = make_wireless_setting (ifcfg, security_setting, error);
+ if (!wireless_setting)
+ goto error;
+
+ nm_connection_add_setting (connection, wireless_setting);
+
+ tmp = NM_SETTING_WIRELESS (wireless_setting);
+ printable_ssid = nm_utils_ssid_to_utf8 ((const char *) tmp->ssid->data,
+ (guint32) tmp->ssid->len);
+
+ con_setting = make_connection_setting (file, ifcfg,
+ NM_SETTING_WIRELESS_SETTING_NAME,
+ printable_ssid);
+ if (!con_setting) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Failed to create connection setting.");
+ goto error;
+ }
+ nm_connection_add_setting (connection, con_setting);
+
+ if (!nm_connection_verify (connection)) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Connection from %s was invalid.", file);
+ goto error;
+ }
+
+ return connection;
+
+error:
+ g_free (printable_ssid);
+ g_object_unref (connection);
+ if (con_setting)
+ g_object_unref (con_setting);
+ if (wireless_setting)
+ g_object_unref (wireless_setting);
+ return NULL;
+}
+
+static NMSetting *
+make_wired_setting (shvarFile *ifcfg, GError **error)
+{
+ NMSettingWired *s_wired;
+ char *value;
+ int mtu;
+
+ s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
+
+ value = svGetValue (ifcfg, "MTU");
+ if (value) {
+ if (get_int (value, &mtu)) {
+ if (mtu >= 0 && mtu < 65536)
+ s_wired->mtu = mtu;
+ } else {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Invalid MTU '%s'", value);
+ g_object_unref (s_wired);
+ s_wired = NULL;
+ }
+ g_free (value);
+ }
+
+ if (!read_mac_address (ifcfg, &s_wired->mac_address, error)) {
+ g_object_unref (s_wired);
+ s_wired = NULL;
+ }
+
+ return (NMSetting *) s_wired;
+}
+
+static NMConnection *
+wired_connection_from_ifcfg (const char *file, shvarFile *ifcfg, GError **error)
+{
+ NMConnection *connection = NULL;
+ NMSetting *con_setting = NULL;
+ NMSetting *wired_setting = NULL;
+
+ g_return_val_if_fail (file != NULL, NULL);
+ g_return_val_if_fail (ifcfg != NULL, NULL);
+
+ connection = nm_connection_new ();
+ if (!connection) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Failed to allocate new connection for %s.", file);
+ return NULL;
+ }
+
+ con_setting = make_connection_setting (file, ifcfg, NM_SETTING_WIRED_SETTING_NAME, NULL);
+ if (!con_setting) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Failed to create connection setting.");
+ goto error;
+ }
+ nm_connection_add_setting (connection, con_setting);
+
+ wired_setting = make_wired_setting (ifcfg, error);
+ if (!wired_setting)
+ goto error;
+
+ nm_connection_add_setting (connection, wired_setting);
+
+ if (!nm_connection_verify (connection)) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Connection from %s was invalid.", file);
+ goto error;
+ }
+
+ return connection;
+
+error:
+ g_object_unref (connection);
+ if (con_setting)
+ g_object_unref (con_setting);
+ if (wired_setting)
+ g_object_unref (wired_setting);
+ return NULL;
+}
+
+static gboolean
+is_wireless_device (const char *iface, gboolean *is_wireless)
+{
+ int fd;
+ struct iw_range range;
+ struct iwreq wrq;
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (iface != NULL, FALSE);
+ g_return_val_if_fail (is_wireless != NULL, FALSE);
+
+ *is_wireless = FALSE;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (!fd)
+ return FALSE;
+
+ memset (&wrq, 0, sizeof (struct iwreq));
+ memset (&range, 0, sizeof (struct iw_range));
+ strncpy (wrq.ifr_name, iface, IFNAMSIZ);
+ wrq.u.data.pointer = (caddr_t) ⦥
+ wrq.u.data.length = sizeof (struct iw_range);
+
+ if (ioctl (fd, SIOCGIWRANGE, &wrq) < 0) {
+ if (errno == EOPNOTSUPP)
+ success = TRUE;
+ goto out;
+ }
+
+ *is_wireless = TRUE;
+ success = TRUE;
+
+out:
+ close (fd);
+ return success;
+}
+
+NMConnection *
+connection_from_file (const char *filename, gboolean *ignored, GError **error)
+{
+ NMConnection *connection = NULL;
+ shvarFile *parsed;
+ char *type;
+ char *nmc = NULL;
+ NMSetting *s_ip4;
+ char *ifcfg_name = NULL;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+ g_return_val_if_fail (ignored != NULL, NULL);
+
+ ifcfg_name = get_ifcfg_name (filename);
+ if (!ifcfg_name) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Ignoring connection '%s' because it's not an ifcfg file.", filename);
+ return NULL;
+ }
+ g_free (ifcfg_name);
+
+ parsed = svNewFile (filename);
+ if (!parsed) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Couldn't parse file '%s'", filename);
+ return NULL;
+ }
+
+ type = svGetValue (parsed, "TYPE");
+ if (!type) {
+ char *device;
+ gboolean is_wireless = FALSE;
+
+ /* If no type, if the device has wireless extensions, it's wifi,
+ * otherwise it's ethernet.
+ */
+ device = svGetValue (parsed, "DEVICE");
+ if (!device) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "File '%s' had neither TYPE nor DEVICE keys.", filename);
+ goto done;
+ }
+
+ if (!strcmp (device, "lo")) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Ignoring loopback device config.");
+ g_free (device);
+ goto done;
+ }
+
+ /* Test wireless extensions */
+ if (!is_wireless_device (device, &is_wireless)) {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "File '%s' specified device '%s', but the device's "
+ "type could not be determined.", filename, device);
+ g_free (device);
+ goto done;
+ }
+
+ if (is_wireless)
+ type = g_strdup (TYPE_WIRELESS);
+ else
+ type = g_strdup (TYPE_ETHERNET);
+
+ g_free (device);
+ }
+
+ nmc = svGetValue (parsed, "NM_CONTROLLED");
+ if (nmc) {
+ char *lower;
+
+ lower = g_ascii_strdown (nmc, -1);
+ g_free (nmc);
+
+ if (!strcmp (lower, "no") || !strcmp (lower, "n") || !strcmp (lower, "false"))
+ *ignored = TRUE;
+ g_free (lower);
+ }
+
+ if (!strcmp (type, TYPE_ETHERNET))
+ connection = wired_connection_from_ifcfg (filename, parsed, error);
+ else if (!strcmp (type, TYPE_WIRELESS))
+ connection = wireless_connection_from_ifcfg (filename, parsed, error);
+ else {
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Unknown connection type '%s'", type);
+ }
+
+ g_free (type);
+
+ if (!connection)
+ goto done;
+
+ s_ip4 = make_ip4_setting (parsed, error);
+ if (*error) {
+ g_object_unref (connection);
+ connection = NULL;
+ goto done;
+ } else if (s_ip4) {
+ nm_connection_add_setting (connection, s_ip4);
+ }
+
+ if (!nm_connection_verify (connection)) {
+ g_object_unref (connection);
+ connection = NULL;
+ g_set_error (error, ifcfg_plugin_error_quark (), 0,
+ "Connection was invalid");
+ }
+
+done:
+ svCloseFile (parsed);
+ return connection;
+}
+
+
Added: trunk/system-settings/plugins/ifcfg-fedora/reader.h
==============================================================================
--- (empty file)
+++ trunk/system-settings/plugins/ifcfg-fedora/reader.h Sun May 11 20:20:52 2008
@@ -0,0 +1,29 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#ifndef __READER_H__
+#define __READER_H__
+
+#include <glib.h>
+#include <nm-connection.h>
+
+NMConnection *connection_from_file (const char *filename, gboolean *ignored, GError **error);
+
+#endif /* __READER_H__ */
Modified: trunk/system-settings/src/dbus-settings.c
==============================================================================
--- trunk/system-settings/src/dbus-settings.c (original)
+++ trunk/system-settings/src/dbus-settings.c Sun May 11 20:20:52 2008
@@ -70,6 +70,38 @@
};
static void
+load_connections (NMSysconfigSettings *self)
+{
+ NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+ GSList *iter;
+
+ if (priv->connections_loaded)
+ return;
+
+ for (iter = priv->plugins; iter; iter = g_slist_next (iter)) {
+ NMSystemConfigInterface *plugin = NM_SYSTEM_CONFIG_INTERFACE (iter->data);
+ GSList *plugin_connections;
+ GSList *elt;
+
+ plugin_connections = nm_system_config_interface_get_connections (plugin);
+
+ // FIXME: ensure connections from plugins loaded with a lower priority
+ // get rejected when they conflict with connections from a higher
+ // priority plugin.
+
+ for (elt = plugin_connections; elt; elt = g_slist_next (elt))
+ nm_sysconfig_settings_add_connection (self, NM_EXPORTED_CONNECTION (elt->data));
+
+ g_slist_free (plugin_connections);
+ }
+
+ /* FIXME: Bad hack */
+ unmanaged_devices_changed (NULL, self);
+
+ priv->connections_loaded = TRUE;
+}
+
+static void
hash_keys_to_slist (gpointer key, gpointer val, gpointer user_data)
{
GSList **list = (GSList **) user_data;
@@ -84,31 +116,7 @@
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
GSList *list = NULL;
- if (!priv->connections_loaded) {
- GSList *iter;
-
- for (iter = priv->plugins; iter; iter = g_slist_next (iter)) {
- NMSystemConfigInterface *plugin = NM_SYSTEM_CONFIG_INTERFACE (iter->data);
- GSList *plugin_connections;
- GSList *elt;
-
- plugin_connections = nm_system_config_interface_get_connections (plugin);
-
- // FIXME: ensure connections from plugins loaded with a lower priority
- // get rejected when they conflict with connections from a higher
- // priority plugin.
-
- for (elt = plugin_connections; elt; elt = g_slist_next (elt))
- nm_sysconfig_settings_add_connection (self, NM_EXPORTED_CONNECTION (elt->data));
-
- g_slist_free (plugin_connections);
- }
-
- /* FIXME: Bad hack */
- unmanaged_devices_changed (NULL, self);
-
- priv->connections_loaded = TRUE;
- }
+ load_connections (self);
g_hash_table_foreach (priv->connections, hash_keys_to_slist, &list);
@@ -195,6 +203,8 @@
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
GPtrArray *devices;
+ load_connections (self);
+
devices = g_ptr_array_sized_new (3);
g_hash_table_foreach (priv->unmanaged_devices, (GHFunc) add_one_unmanaged_device, devices);
return devices;
@@ -406,6 +416,9 @@
g_return_val_if_fail (NM_IS_SYSCONFIG_SETTINGS (self), FALSE);
priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+ load_connections (self);
+
if (g_hash_table_lookup (priv->unmanaged_devices, udi))
return FALSE;
return TRUE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]