diff --git a/ChangeLog b/ChangeLog index 95344a13c0..19ca32ba91 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2008-05-11 Dan Williams + + 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 + 2008-05-11 Dan Williams * configure.in diff --git a/system-settings/plugins/ifcfg-fedora/Makefile.am b/system-settings/plugins/ifcfg-fedora/Makefile.am index ab00fbb0c0..f1765fc3f1 100644 --- a/system-settings/plugins/ifcfg-fedora/Makefile.am +++ b/system-settings/plugins/ifcfg-fedora/Makefile.am @@ -4,10 +4,13 @@ pkglib_LTLIBRARIES = libnm-settings-plugin-ifcfg-fedora.la 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 @@ libnm_settings_plugin_ifcfg_fedora_la_CPPFLAGS = \ -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_LDFLAGS = -module -avoid-version 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 diff --git a/system-settings/plugins/ifcfg-fedora/parser.h b/system-settings/plugins/ifcfg-fedora/common.h similarity index 57% rename from system-settings/plugins/ifcfg-fedora/parser.h rename to system-settings/plugins/ifcfg-fedora/common.h index 397ccbdd6f..67e89b4e63 100644 --- a/system-settings/plugins/ifcfg-fedora/parser.h +++ b/system-settings/plugins/ifcfg-fedora/common.h @@ -1,6 +1,5 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager system settings service - * - * Søren Sandmann * * 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 @@ -16,15 +15,11 @@ * 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. */ -#ifndef _PARSER_H_ -#define _PARSER_H_ - -#include -#include -#include +#ifndef __COMMON_H__ +#define __COMMON_H__ #define IFCFG_TAG "ifcfg-" #define KEYS_TAG "keys-" @@ -33,21 +28,10 @@ #define ORIG_TAG ".orig" #define REJ_TAG ".rej" -typedef struct { - char *ifcfg_path; - char *udi; - gboolean ignored; - gboolean exported; +#include - GHashTable *wifi_secrets; - GHashTable *onex_secrets; - GHashTable *ppp_secrets; -} ConnectionData; +GQuark ifcfg_plugin_error_quark (void); -NMConnection * parser_parse_file (const char *file, GError **error); -ConnectionData *connection_data_get (NMConnection *connection); -ConnectionData *connection_data_add (NMConnection *connection, const char *ifcfg_path); -void connection_data_copy_secrets (ConnectionData *from, ConnectionData *to); +#endif /* __COMMON_H__ */ -#endif /* _PARSER_H_ */ diff --git a/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.c b/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.c new file mode 100644 index 0000000000..79932a30d4 --- /dev/null +++ b/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.c @@ -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 +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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)); +} diff --git a/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.h b/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.h new file mode 100644 index 0000000000..7d1acbd7bf --- /dev/null +++ b/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.h @@ -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 +#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 */ diff --git a/system-settings/plugins/ifcfg-fedora/plugin.c b/system-settings/plugins/ifcfg-fedora/plugin.c index 01d71d4a28..f80f25ec97 100644 --- a/system-settings/plugins/ifcfg-fedora/plugin.c +++ b/system-settings/plugins/ifcfg-fedora/plugin.c @@ -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 #include #include #include #include -#include #include #include #include @@ -32,19 +32,18 @@ #include #include -#include -#include -#include -#include -#include -#include -#include +#ifndef NO_GIO +#include +#else +#include +#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 @@ G_DEFINE_TYPE_EXTENDED (SCPluginIfcfg, sc_plugin_ifcfg, G_TYPE_OBJECT, 0, 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,676 +81,91 @@ ifcfg_plugin_error_quark (void) 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 (!nm_ifcfg_connection_get_unmanaged (connection)) + return; - if (!cdata->udi) { - cdata->udi = get_udi_for_connection (plugin, connection, devtype); - if (cdata->udi && cdata->ignored) - changed = TRUE; - } + udi = nm_ifcfg_connection_get_udi (connection); + if (!udi) + return; + + /* 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"); -} - -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; - - /* 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; - } - } - - 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; - - if (info->found) - return; - - if (!strcmp (info->path, value)) { - info->found = TRUE; - return; - } -} - -static void -watch_path (const char *path, const int inotify_fd, GHashTable *table) -{ - 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)); - } -} - -static NMConnection * -build_one_connection (SCPluginIfcfg *plugin, const char *path) -{ - NMConnection *connection; - GError *error = NULL; - - g_return_val_if_fail (path != NULL, NULL); - - PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "parsing %s ... ", path); - - connection = parser_parse_file (path, &error); - if (connection) { - 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)); - g_assert (s_con); - g_assert (s_con->id); - PLUGIN_PRINT (IFCFG_PLUGIN_NAME, " read connection '%s'", s_con->id); - } else { - PLUGIN_PRINT (IFCFG_PLUGIN_NAME, " error: %s", - error->message ? error->message : "(unknown)"); - } - - 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) -{ - 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; - - unlink (path); - -out: - g_free (contents); - g_free (path); -} - -static void -read_all_connections (SCPluginIfcfg *plugin) -{ - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); - GDir *dir; - const char *item; - - 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); - if (dir) { - while ((item = g_dir_read_name (dir))) { - NMConnection *connection; - ConnectionData *cdata; - - 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); - - 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; - } - } + SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (config); + GSList *list = NULL; + g_hash_table_foreach (priv->connections, check_unmanaged, &list); 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) +connection_unmanaged_changed (NMIfcfgConnection *connection, + GParamSpec *pspec, + gpointer user_data) { - g_hash_table_insert ((GHashTable *) user_data, g_strdup (key), string_to_gvalue (data)); + g_signal_emit_by_name (SC_PLUGIN_IFCFG (user_data), "unmanaged-devices-changed"); } -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); - } - - /* 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; -} - -static void -handle_connection_changed (SCPluginIfcfg *plugin, - const char *basename) +static NMIfcfgConnection * +read_one_connection (SCPluginIfcfg *plugin, const char *filename) { 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; + NMIfcfgConnection *connection; + GError *error = NULL; - 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; - } + PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "parsing %s ... ", filename); - if (!filename) { - PLUGIN_WARN (IFCFG_PLUGIN_NAME, "not enough memory to update connection."); - return; - } + connection = nm_ifcfg_connection_new (filename, priv->g_connection, priv->hal_mgr, &error); + if (connection) { + NMConnection *wrapped; + NMSettingConnection *s_con; - /* Could return NULL if the connection got deleted */ - new_connection = build_one_connection (plugin, filename); + 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); - existing = find_connection_by_path (priv->connections, filename); - if (!existing) { - if (new_connection) { - new_cdata = connection_data_get (new_connection); - g_assert (new_cdata); + 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); - /* 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"); - } - } - g_free (filename); - return; - } - - existing_cdata = connection_data_get (existing); - g_assert (existing_cdata); - - 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; - } - - 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"); - } - g_object_unref (existing); - PLUGIN_PRINT (IFCFG_PLUGIN_NAME, " removed connection"); - } - - g_free (filename); -} - -static void -handle_new_item (SCPluginIfcfg *plugin, const char *basename) -{ - 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; - } - - if (strncmp (basename, IFCFG_TAG, strlen (IFCFG_TAG))) - return; - - /* New connection */ - connection = handle_new_ifcfg (plugin, basename, priv->ifd, priv->watch_table); - if (!connection) - return; - - 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) + 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 gboolean @@ -772,117 +183,193 @@ should_ignore_file (const char *basename, const char *tag) return FALSE; } -static gboolean -stuff_changed (GIOChannel *channel, GIOCondition cond, gpointer user_data) +static void +read_connections (SCPluginIfcfg *plugin) { - SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data); - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); - struct inotify_event evt; + GDir *dir; + GError *err = NULL; - /* 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]; + dir = g_dir_open (IFCFG_DIR, 0, &err); + if (dir) { + const char *item; - path = g_hash_table_lookup (priv->watch_table, GINT_TO_POINTER (evt.wd)); + while ((item = g_dir_read_name (dir))) { + char *full_path; - 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))) + if (strncmp (item, IFCFG_TAG, strlen (IFCFG_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)) + 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; - 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); + full_path = g_build_filename (IFCFG_DIR, item, NULL); + read_one_connection (plugin, full_path); + g_free (full_path); + } + + g_dir_close (dir); + } else { + PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Can not read directory '%s': %s", IFCFG_DIR, err->message); + g_error_free (err); + } +} + +/* Monitoring */ + +static void +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 *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); + } + + /* 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 */ + + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " error: %s", + error->message ? error->message : "(unknown)"); + g_error_free (error); + + PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "removed %s.", name); + do_remove = TRUE; } } 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; + do_new = TRUE; + } + break; + default: + break; + } - inotify_rm_watch (priv->ifd, evt.wd); - g_hash_table_remove (priv->watch_table, GINT_TO_POINTER (evt.wd)); + if (do_remove) { + gboolean unmanaged = nm_ifcfg_connection_get_unmanaged (connection); - /* Remove connection */ - basename = g_path_get_basename (path); - handle_connection_changed (plugin, basename); - g_free (basename); - } + 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 (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); } } - return TRUE; + g_free (name); } -static gboolean -sc_plugin_inotify_init (SCPluginIfcfg *plugin, GError **error) +static void +setup_monitoring (SCPluginIfcfg *plugin) { SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); - GIOChannel *channel; - guint source_id; - int ifd, wd; + GFile *file; + GFileMonitor *monitor; - ifd = inotify_init (); - if (ifd == -1) { - g_set_error (error, ifcfg_plugin_error_quark (), 0, - "Couldn't initialize inotify"); - return FALSE; + priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); + + file = g_file_new_for_path (IFCFG_DIR); + monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); + g_object_unref (file); + + if (monitor) { + priv->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (dir_changed), plugin); + priv->monitor = monitor; + } +} + +static void +hash_to_slist (gpointer key, gpointer value, gpointer user_data) +{ + NMIfcfgConnection *exported = NM_IFCFG_CONNECTION (value); + GSList **list = (GSList **) user_data; + + if (!nm_ifcfg_connection_get_unmanaged (exported)) + *list = g_slist_prepend (*list, value); +} + +static GSList * +get_connections (NMSystemConfigInterface *config) +{ + SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config); + SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); + GSList *list = NULL; + + if (!priv->connections) { + setup_monitoring (plugin); + read_connections (plugin); } - 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; - } + g_hash_table_foreach (priv->connections, hash_to_slist, &list); - 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); - - return TRUE; + return list; } static void @@ -890,17 +377,8 @@ init (NMSystemConfigInterface *config, NMSystemConfigHalManager *hal_manager) { 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 @@ dispose (GObject *object) 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 @@ system_config_interface_init (NMSystemConfigInterface *system_config_interface_c { /* 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; } diff --git a/system-settings/plugins/ifcfg-fedora/parser.c b/system-settings/plugins/ifcfg-fedora/reader.c similarity index 77% rename from system-settings/plugins/ifcfg-fedora/parser.c rename to system-settings/plugins/ifcfg-fedora/reader.c index f67931be51..4567639675 100644 --- a/system-settings/plugins/ifcfg-fedora/parser.c +++ b/system-settings/plugins/ifcfg-fedora/reader.c @@ -1,6 +1,5 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager system settings service - * - * Søren Sandmann * * 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 @@ -16,7 +15,7 @@ * 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 @@ -40,7 +39,6 @@ #undef __user #include - #include #include #include @@ -49,91 +47,27 @@ #include #include +#include "common.h" #include "shvar.h" -#include "parser.h" -#include "plugin.h" -#define CONNECTION_DATA_TAG "plugin-data" +#include "reader.h" -ConnectionData * -connection_data_get (NMConnection *connection) +#define TYPE_ETHERNET "Ethernet" +#define TYPE_WIRELESS "Wireless" + +static char * +get_ifcfg_name (const char *file) { - return (ConnectionData *) g_object_get_data (G_OBJECT (connection), CONNECTION_DATA_TAG); -} + char *ifcfg_name; + char *basename; -static void -copy_one_cdata_secret (gpointer key, gpointer data, gpointer user_data) -{ - GHashTable *to = (GHashTable *) user_data; + basename = g_path_get_basename (file); + if (!basename) + return NULL; - g_hash_table_insert (to, key, g_strdup (data)); -} - -static void -clear_one_cdata_secret (gpointer key, gpointer data, gpointer user_data) -{ - guint32 len = strlen (data); - memset (data, 0, len); -} - -void -connection_data_copy_secrets (ConnectionData *from, ConnectionData *to) -{ - g_return_if_fail (from != NULL); - g_return_if_fail (to != NULL); - - g_hash_table_foreach (to->wifi_secrets, clear_one_cdata_secret, NULL); - g_hash_table_remove_all (to->wifi_secrets); - g_hash_table_foreach (from->wifi_secrets, copy_one_cdata_secret, to->wifi_secrets); - - g_hash_table_foreach (to->onex_secrets, clear_one_cdata_secret, NULL); - g_hash_table_remove_all (to->onex_secrets); - g_hash_table_foreach (from->onex_secrets, copy_one_cdata_secret, to->onex_secrets); - - g_hash_table_foreach (to->ppp_secrets, clear_one_cdata_secret, NULL); - g_hash_table_remove_all (to->ppp_secrets); - g_hash_table_foreach (from->ppp_secrets, copy_one_cdata_secret, to->ppp_secrets); -} - -static void -connection_data_free (gpointer userdata) -{ - ConnectionData *cdata = (ConnectionData *) userdata; - - g_return_if_fail (cdata != NULL); - - g_hash_table_foreach (cdata->wifi_secrets, clear_one_cdata_secret, NULL); - g_hash_table_destroy (cdata->wifi_secrets); - - g_hash_table_foreach (cdata->onex_secrets, clear_one_cdata_secret, NULL); - g_hash_table_destroy (cdata->onex_secrets); - - g_hash_table_foreach (cdata->ppp_secrets, clear_one_cdata_secret, NULL); - g_hash_table_destroy (cdata->ppp_secrets); - - g_free (cdata->ifcfg_path); - g_free (cdata->udi); - - memset (cdata, 0, sizeof (ConnectionData)); - g_free (cdata); -} - -ConnectionData * -connection_data_add (NMConnection *connection, const char *ifcfg_path) -{ - ConnectionData *cdata; - - cdata = g_malloc0 (sizeof (ConnectionData)); - cdata->ifcfg_path = g_strdup (ifcfg_path); - - cdata->wifi_secrets = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free); - cdata->onex_secrets = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free); - cdata->ppp_secrets = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free); - - g_object_set_data_full (G_OBJECT (connection), - CONNECTION_DATA_TAG, cdata, - connection_data_free); - return cdata; + ifcfg_name = g_strdup (basename + strlen (IFCFG_TAG)); + g_free (basename); + return ifcfg_name; } static gboolean @@ -148,56 +82,6 @@ get_int (const char *str, int *value) return TRUE; } -static gboolean -should_ignore_file (const char *basename, const char *tag) -{ - int len, tag_len; - - g_return_val_if_fail (basename != NULL, TRUE); - g_return_val_if_fail (tag != NULL, TRUE); - - len = strlen (basename); - tag_len = strlen (tag); - if ((len > tag_len) && !strcasecmp (basename + len - tag_len, tag)) - return TRUE; - return FALSE; -} - -static char * -get_ifcfg_name (const char *file) -{ - char *ifcfg_name = NULL; - char *basename; - int len; - - basename = g_path_get_basename (file); - if (!basename) - goto error; - len = strlen (basename); - - if (len < strlen (IFCFG_TAG) + 1) - goto error; - - if (strncmp (basename, IFCFG_TAG, strlen (IFCFG_TAG))) - goto error; - - /* ignore some files */ - if (should_ignore_file (basename, BAK_TAG)) - goto error; - if (should_ignore_file (basename, TILDE_TAG)) - goto error; - if (should_ignore_file (basename, ORIG_TAG)) - goto error; - if (should_ignore_file (basename, REJ_TAG)) - goto error; - - ifcfg_name = g_strdup (basename + strlen (IFCFG_TAG)); - -error: - g_free (basename); - return ifcfg_name; -} - static NMSetting * make_connection_setting (const char *file, shvarFile *ifcfg, @@ -426,7 +310,7 @@ static gboolean add_one_wep_key (shvarFile *ifcfg, const char *shvar_key, guint8 key_idx, - GHashTable *secrets, + NMSettingWirelessSecurity *s_wsec, GError **error) { char *key = NULL; @@ -436,7 +320,7 @@ add_one_wep_key (shvarFile *ifcfg, 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 (secrets != NULL, FALSE); + g_return_val_if_fail (s_wsec != NULL, FALSE); value = svGetValue (ifcfg, shvar_key); if (!value || !strlen (value)) { @@ -478,13 +362,13 @@ add_one_wep_key (shvarFile *ifcfg, if (key) { if (key_idx == 0) - g_hash_table_insert (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, key); + s_wsec->wep_key0 = key; else if (key_idx == 1) - g_hash_table_insert (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, key); + s_wsec->wep_key1 = key; else if (key_idx == 2) - g_hash_table_insert (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, key); + s_wsec->wep_key2 = key; else if (key_idx == 3) - g_hash_table_insert (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3, key); + s_wsec->wep_key3 = key; else g_assert_not_reached (); success = TRUE; @@ -525,17 +409,20 @@ out: } static gboolean -read_wep_keys (shvarFile *ifcfg, guint8 def_idx, GHashTable *secrets, GError **error) +read_wep_keys (shvarFile *ifcfg, + guint8 def_idx, + NMSettingWirelessSecurity *s_wsec, + GError **error) { - if (!add_one_wep_key (ifcfg, "KEY1", 0, secrets, error)) + if (!add_one_wep_key (ifcfg, "KEY1", 0, s_wsec, error)) return FALSE; - if (!add_one_wep_key (ifcfg, "KEY2", 1, secrets, error)) + if (!add_one_wep_key (ifcfg, "KEY2", 1, s_wsec, error)) return FALSE; - if (!add_one_wep_key (ifcfg, "KEY3", 2, secrets, error)) + if (!add_one_wep_key (ifcfg, "KEY3", 2, s_wsec, error)) return FALSE; - if (!add_one_wep_key (ifcfg, "KEY4", 3, secrets, error)) + if (!add_one_wep_key (ifcfg, "KEY4", 3, s_wsec, error)) return FALSE; - if (!add_one_wep_key (ifcfg, "KEY", def_idx, secrets, error)) + if (!add_one_wep_key (ifcfg, "KEY", def_idx, s_wsec, error)) return FALSE; return TRUE; @@ -544,7 +431,6 @@ read_wep_keys (shvarFile *ifcfg, guint8 def_idx, GHashTable *secrets, GError **e static NMSetting * make_wireless_security_setting (shvarFile *ifcfg, const char *file, - ConnectionData *cdata, GError **error) { NMSettingWirelessSecurity *s_wireless_sec; @@ -572,13 +458,13 @@ make_wireless_security_setting (shvarFile *ifcfg, } /* Read keys in the ifcfg file */ - if (!read_wep_keys (ifcfg, default_key_idx, cdata->wifi_secrets, error)) + 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, cdata->wifi_secrets, error)) { + if (!read_wep_keys (keys_ifcfg, default_key_idx, s_wireless_sec, error)) { svCloseFile (keys_ifcfg); goto error; } @@ -586,18 +472,15 @@ make_wireless_security_setting (shvarFile *ifcfg, } /* If there's a default key, ensure that key exists */ - if ( (default_key_idx == 1) - && !g_hash_table_lookup (cdata->wifi_secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1)) { + 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) - && !g_hash_table_lookup (cdata->wifi_secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2)) { + } 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) - && !g_hash_table_lookup (cdata->wifi_secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3)) { + } 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; @@ -624,10 +507,10 @@ make_wireless_security_setting (shvarFile *ifcfg, g_free (lcase); } - if ( !g_hash_table_lookup (cdata->wifi_secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0) - && !g_hash_table_lookup (cdata->wifi_secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1) - && !g_hash_table_lookup (cdata->wifi_secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2) - && !g_hash_table_lookup (cdata->wifi_secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3) + 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, @@ -730,7 +613,6 @@ wireless_connection_from_ifcfg (const char *file, shvarFile *ifcfg, GError **err NMSettingWireless *tmp; NMSetting *security_setting = NULL; char *printable_ssid = NULL; - ConnectionData *cdata; g_return_val_if_fail (file != NULL, NULL); g_return_val_if_fail (ifcfg != NULL, NULL); @@ -744,11 +626,8 @@ wireless_connection_from_ifcfg (const char *file, shvarFile *ifcfg, GError **err return NULL; } - /* Add plugin specific data to connection */ - cdata = connection_data_add (connection, file); - /* Wireless security */ - security_setting = make_wireless_security_setting (ifcfg, file, cdata, error); + security_setting = make_wireless_security_setting (ifcfg, file, error); if (*error) goto error; if (security_setting) @@ -830,7 +709,6 @@ wired_connection_from_ifcfg (const char *file, shvarFile *ifcfg, GError **error) NMConnection *connection = NULL; NMSetting *con_setting = NULL; NMSetting *wired_setting = NULL; - ConnectionData *cdata; g_return_val_if_fail (file != NULL, NULL); g_return_val_if_fail (ifcfg != NULL, NULL); @@ -850,9 +728,6 @@ wired_connection_from_ifcfg (const char *file, shvarFile *ifcfg, GError **error) } nm_connection_add_setting (connection, con_setting); - /* Add plugin data to connection */ - cdata = connection_data_add (connection, file); - wired_setting = make_wired_setting (ifcfg, error); if (!wired_setting) goto error; @@ -913,11 +788,8 @@ out: return success; } -#define TYPE_ETHERNET "Ethernet" -#define TYPE_WIRELESS "Wireless" - NMConnection * -parser_parse_file (const char *file, GError **error) +connection_from_file (const char *filename, gboolean *ignored, GError **error) { NMConnection *connection = NULL; shvarFile *parsed; @@ -925,23 +797,22 @@ parser_parse_file (const char *file, GError **error) char *nmc = NULL; NMSetting *s_ip4; char *ifcfg_name = NULL; - gboolean ignored = FALSE; - ConnectionData *cdata; - g_return_val_if_fail (file != NULL, NULL); + g_return_val_if_fail (filename != NULL, NULL); + g_return_val_if_fail (ignored != NULL, NULL); - ifcfg_name = get_ifcfg_name (file); + 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.", file); + "Ignoring connection '%s' because it's not an ifcfg file.", filename); return NULL; } g_free (ifcfg_name); - parsed = svNewFile (file); + parsed = svNewFile (filename); if (!parsed) { g_set_error (error, ifcfg_plugin_error_quark (), 0, - "Couldn't parse file '%s'", file); + "Couldn't parse file '%s'", filename); return NULL; } @@ -956,7 +827,7 @@ parser_parse_file (const char *file, GError **error) device = svGetValue (parsed, "DEVICE"); if (!device) { g_set_error (error, ifcfg_plugin_error_quark (), 0, - "File '%s' had neither TYPE nor DEVICE keys.", file); + "File '%s' had neither TYPE nor DEVICE keys.", filename); goto done; } @@ -971,7 +842,7 @@ parser_parse_file (const char *file, GError **error) 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.", file, device); + "type could not be determined.", filename, device); g_free (device); goto done; } @@ -992,14 +863,14 @@ parser_parse_file (const char *file, GError **error) g_free (nmc); if (!strcmp (lower, "no") || !strcmp (lower, "n") || !strcmp (lower, "false")) - ignored = TRUE; + *ignored = TRUE; g_free (lower); } if (!strcmp (type, TYPE_ETHERNET)) - connection = wired_connection_from_ifcfg (file, parsed, error); + connection = wired_connection_from_ifcfg (filename, parsed, error); else if (!strcmp (type, TYPE_WIRELESS)) - connection = wireless_connection_from_ifcfg (file, parsed, error); + connection = wireless_connection_from_ifcfg (filename, parsed, error); else { g_set_error (error, ifcfg_plugin_error_quark (), 0, "Unknown connection type '%s'", type); @@ -1019,10 +890,6 @@ parser_parse_file (const char *file, GError **error) nm_connection_add_setting (connection, s_ip4); } - /* Update the ignored tag */ - cdata = connection_data_get (connection); - cdata->ignored = ignored; - if (!nm_connection_verify (connection)) { g_object_unref (connection); connection = NULL; @@ -1035,3 +902,4 @@ done: return connection; } + diff --git a/system-settings/plugins/ifcfg-fedora/reader.h b/system-settings/plugins/ifcfg-fedora/reader.h new file mode 100644 index 0000000000..c00fa8a18d --- /dev/null +++ b/system-settings/plugins/ifcfg-fedora/reader.h @@ -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 +#include + +NMConnection *connection_from_file (const char *filename, gboolean *ignored, GError **error); + +#endif /* __READER_H__ */ diff --git a/system-settings/src/dbus-settings.c b/system-settings/src/dbus-settings.c index 0dd84d974b..969697c7e3 100644 --- a/system-settings/src/dbus-settings.c +++ b/system-settings/src/dbus-settings.c @@ -69,6 +69,38 @@ enum { LAST_PROP }; +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) { @@ -84,31 +116,7 @@ list_connections (NMSettings *settings) 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 @@ get_unmanaged_devices (NMSysconfigSettings *self) 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 @@ nm_sysconfig_settings_is_device_managed (NMSysconfigSettings *self, 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;