about summary refs log tree commit diff
path: root/src/settings/plugins/ifcfg-rh/plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/settings/plugins/ifcfg-rh/plugin.c')
-rw-r--r--src/settings/plugins/ifcfg-rh/plugin.c711
1 files changed, 333 insertions, 378 deletions
diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c
index 526cdafe..5afc46d6 100644
--- a/src/settings/plugins/ifcfg-rh/plugin.c
+++ b/src/settings/plugins/ifcfg-rh/plugin.c
@@ -30,39 +30,28 @@
 #include <sys/stat.h>
 
 #include <gmodule.h>
-#include <glib-object.h>
-#include <glib/gi18n.h>
-#include <gio/gio.h>
-
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
-#if HAVE_SELINUX
-#include <selinux/selinux.h>
-#endif
 
 #include "nm-setting-connection.h"
 
+#include "nm-default.h"
 #include "common.h"
-#include "nm-dbus-glib-types.h"
 #include "plugin.h"
-#include "nm-system-config-interface.h"
+#include "nm-settings-plugin.h"
 #include "nm-config.h"
-#include "nm-logging.h"
 #include "NetworkManagerUtils.h"
 
 #include "nm-ifcfg-connection.h"
-#include "nm-inotify-helper.h"
 #include "shvar.h"
 #include "reader.h"
 #include "writer.h"
 #include "utils.h"
-#include "gsystem-local-alloc.h"
+#include "nm-dbus-compat.h"
+#include "nm-exported-object.h"
 
-#define DBUS_SERVICE_NAME "com.redhat.ifcfgrh1"
-#define DBUS_OBJECT_PATH "/com/redhat/ifcfgrh1"
+#include "nmdbus-ifcfg-rh.h"
 
+#define IFCFGRH1_DBUS_SERVICE_NAME "com.redhat.ifcfgrh1"
+#define IFCFGRH1_DBUS_OBJECT_PATH "/com/redhat/ifcfgrh1"
 
 #define _NMLOG_DOMAIN  LOGD_SETTINGS
 #define _NMLOG(level, ...) \
@@ -76,15 +65,7 @@
 #define ERR_GET_MSG(err) (((err) && (err)->message) ? (err)->message : "(unknown)")
 
 
-static gboolean impl_ifcfgrh_get_ifcfg_details (SCPluginIfcfg *plugin,
-                                                const char *in_ifcfg,
-                                                const char **out_uuid,
-                                                const char **out_path,
-                                                GError **error);
-
-#include "nm-ifcfg-rh-glue.h"
-
-static NMIfcfgConnection *update_connection (SCPluginIfcfg *plugin,
+static NMIfcfgConnection *update_connection (SettingsPluginIfcfg *plugin,
                                              NMConnection *source,
                                              const char *full_path,
                                              NMIfcfgConnection *connection,
@@ -92,37 +73,40 @@ static NMIfcfgConnection *update_connection (SCPluginIfcfg *plugin,
                                              GHashTable *protected_connections,
                                              GError **error);
 
-static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class);
+static void settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface);
 
-G_DEFINE_TYPE_EXTENDED (SCPluginIfcfg, sc_plugin_ifcfg, G_TYPE_OBJECT, 0,
-						G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE,
-											   system_config_interface_init))
+G_DEFINE_TYPE_EXTENDED (SettingsPluginIfcfg, settings_plugin_ifcfg, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_PLUGIN,
+                                               settings_plugin_interface_init))
 
-#define SC_PLUGIN_IFCFG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SC_TYPE_PLUGIN_IFCFG, SCPluginIfcfgPrivate))
+#define SETTINGS_PLUGIN_IFCFG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SETTINGS_TYPE_PLUGIN_IFCFG, SettingsPluginIfcfgPrivate))
 
 
 typedef struct {
-	GHashTable *connections;  /* uuid::connection */
+	NMConfig *config;
+
+	struct {
+		GDBusConnection *connection;
+		GDBusInterfaceSkeleton *interface;
+		GCancellable *cancellable;
+		gulong signal_id;
+	} dbus;
 
+	GHashTable *connections;  /* uuid::connection */
 	gboolean initialized;
-	gulong ih_event_id;
-	int sc_network_wd;
-	GFileMonitor *hostname_monitor;
-	guint hostname_monitor_id;
-	char *hostname;
 
 	GFileMonitor *ifcfg_monitor;
-	guint ifcfg_monitor_id;
-
-	DBusGConnection *bus;
-} SCPluginIfcfgPrivate;
+	gulong ifcfg_monitor_id;
+} SettingsPluginIfcfgPrivate;
 
+static SettingsPluginIfcfg *settings_plugin_ifcfg_get (void);
+NM_DEFINE_SINGLETON_GETTER (SettingsPluginIfcfg, settings_plugin_ifcfg_get, SETTINGS_TYPE_PLUGIN_IFCFG);
 
 static void
 connection_ifcfg_changed (NMIfcfgConnection *connection, gpointer user_data)
 {
-	SCPluginIfcfg *self = SC_PLUGIN_IFCFG (user_data);
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
+	SettingsPluginIfcfg *self = SETTINGS_PLUGIN_IFCFG (user_data);
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
 	const char *path;
 
 	path = nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection));
@@ -142,14 +126,14 @@ connection_ifcfg_changed (NMIfcfgConnection *connection, gpointer user_data)
 static void
 connection_removed_cb (NMSettingsConnection *obj, gpointer user_data)
 {
-	g_hash_table_remove (SC_PLUGIN_IFCFG_GET_PRIVATE (user_data)->connections,
+	g_hash_table_remove (SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (user_data)->connections,
 	                     nm_connection_get_uuid (NM_CONNECTION (obj)));
 }
 
 static void
-remove_connection (SCPluginIfcfg *self, NMIfcfgConnection *connection)
+remove_connection (SettingsPluginIfcfg *self, NMIfcfgConnection *connection)
 {
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
 	gboolean unmanaged, unrecognized;
 
 	g_return_if_fail (self != NULL);
@@ -168,15 +152,15 @@ remove_connection (SCPluginIfcfg *self, NMIfcfgConnection *connection)
 
 	/* Emit changes _after_ removing the connection */
 	if (unmanaged)
-		g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
+		g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED);
 	if (unrecognized)
-		g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED);
+		g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNRECOGNIZED_SPECS_CHANGED);
 }
 
 static NMIfcfgConnection *
-find_by_path (SCPluginIfcfg *self, const char *path)
+find_by_path (SettingsPluginIfcfg *self, const char *path)
 {
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
 	GHashTableIter iter;
 	NMSettingsConnection *candidate = NULL;
 
@@ -191,7 +175,7 @@ find_by_path (SCPluginIfcfg *self, const char *path)
 }
 
 static NMIfcfgConnection *
-update_connection (SCPluginIfcfg *self,
+update_connection (SettingsPluginIfcfg *self,
                    NMConnection *source,
                    const char *full_path,
                    NMIfcfgConnection *connection,
@@ -199,7 +183,7 @@ update_connection (SCPluginIfcfg *self,
                    GHashTable *protected_connections,
                    GError **error)
 {
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
 	NMIfcfgConnection *connection_new;
 	NMIfcfgConnection *connection_by_uuid;
 	GError *local = NULL;
@@ -346,18 +330,18 @@ update_connection (SCPluginIfcfg *self,
 				if (old_unmanaged /* && !new_unmanaged */) {
 					_LOGI ("Managing connection "NM_IFCFG_CONNECTION_LOG_FMT" and its device because NM_CONTROLLED was true.",
 					       NM_IFCFG_CONNECTION_LOG_ARG (connection_new));
-					g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection_by_uuid);
+					g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_CONNECTION_ADDED, connection_by_uuid);
 				} else if (old_unrecognized /* && !new_unrecognized */) {
 					_LOGI ("Managing connection "NM_IFCFG_CONNECTION_LOG_FMT" because it is now a recognized type.",
 					       NM_IFCFG_CONNECTION_LOG_ARG (connection_new));
-					g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection_by_uuid);
+					g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_CONNECTION_ADDED, connection_by_uuid);
 				}
 			}
 
 			if (unmanaged_changed)
-				g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
+				g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED);
 			if (unrecognized_changed)
-				g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED);
+				g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNRECOGNIZED_SPECS_CHANGED);
 		}
 		nm_settings_connection_set_filename (NM_SETTINGS_CONNECTION (connection_by_uuid), full_path);
 		g_object_unref (connection_new);
@@ -401,11 +385,11 @@ update_connection (SCPluginIfcfg *self,
 			/* Only raise the signal if we were called without source, i.e. if we read the connection from file.
 			 * Otherwise, we were called by add_connection() which does not expect the signal. */
 			if (nm_ifcfg_connection_get_unmanaged_spec (connection_new))
-				g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
+				g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED);
 			else if (nm_ifcfg_connection_get_unrecognized_spec (connection_new))
-				g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED);
+				g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNRECOGNIZED_SPECS_CHANGED);
 			else
-				g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection_new);
+				g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_CONNECTION_ADDED, connection_new);
 		}
 		return connection_new;
 	}
@@ -418,7 +402,7 @@ ifcfg_dir_changed (GFileMonitor *monitor,
                    GFileMonitorEvent event_type,
                    gpointer user_data)
 {
-	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
+	SettingsPluginIfcfg *plugin = SETTINGS_PLUGIN_IFCFG (user_data);
 	char *path, *ifcfg_path;
 	NMIfcfgConnection *connection;
 
@@ -447,9 +431,9 @@ ifcfg_dir_changed (GFileMonitor *monitor,
 }
 
 static void
-setup_ifcfg_monitoring (SCPluginIfcfg *plugin)
+setup_ifcfg_monitoring (SettingsPluginIfcfg *plugin)
 {
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (plugin);
 	GFile *file;
 	GFileMonitor *monitor;
 
@@ -502,9 +486,9 @@ _sort_paths (const char **f1, const char **f2, GHashTable *paths)
 }
 
 static void
-read_connections (SCPluginIfcfg *plugin)
+read_connections (SettingsPluginIfcfg *plugin)
 {
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (plugin);
 	GDir *dir;
 	GError *err = NULL;
 	const char *item;
@@ -574,10 +558,10 @@ read_connections (SCPluginIfcfg *plugin)
 }
 
 static GSList *
-get_connections (NMSystemConfigInterface *config)
+get_connections (NMSettingsPlugin *config)
 {
-	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	SettingsPluginIfcfg *plugin = SETTINGS_PLUGIN_IFCFG (config);
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (plugin);
 	GSList *list = NULL;
 	GHashTableIter iter;
 	NMIfcfgConnection *connection;
@@ -600,10 +584,10 @@ get_connections (NMSystemConfigInterface *config)
 }
 
 static gboolean
-load_connection (NMSystemConfigInterface *config,
+load_connection (NMSettingsPlugin *config,
                  const char *filename)
 {
-	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
+	SettingsPluginIfcfg *plugin = SETTINGS_PLUGIN_IFCFG (config);
 	NMIfcfgConnection *connection;
 	int dir_len = strlen (IFCFG_DIR);
 	char *ifcfg_path;
@@ -629,18 +613,18 @@ load_connection (NMSystemConfigInterface *config,
 }
 
 static void
-reload_connections (NMSystemConfigInterface *config)
+reload_connections (NMSettingsPlugin *config)
 {
-	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
+	SettingsPluginIfcfg *plugin = SETTINGS_PLUGIN_IFCFG (config);
 
 	read_connections (plugin);
 }
 
 static GSList *
-get_unhandled_specs (NMSystemConfigInterface *config,
+get_unhandled_specs (NMSettingsPlugin *config,
                      const char *property)
 {
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (config);
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (config);
 	GSList *list = NULL, *list_iter;
 	GHashTableIter iter;
 	gpointer connection;
@@ -668,24 +652,24 @@ get_unhandled_specs (NMSystemConfigInterface *config,
 }
 
 static GSList *
-get_unmanaged_specs (NMSystemConfigInterface *config)
+get_unmanaged_specs (NMSettingsPlugin *config)
 {
 	return get_unhandled_specs (config, NM_IFCFG_CONNECTION_UNMANAGED_SPEC);
 }
 
 static GSList *
-get_unrecognized_specs (NMSystemConfigInterface *config)
+get_unrecognized_specs (NMSettingsPlugin *config)
 {
 	return get_unhandled_specs (config, NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC);
 }
 
 static NMSettingsConnection *
-add_connection (NMSystemConfigInterface *config,
+add_connection (NMSettingsPlugin *config,
                 NMConnection *connection,
                 gboolean save_to_disk,
                 GError **error)
 {
-	SCPluginIfcfg *self = SC_PLUGIN_IFCFG (config);
+	SettingsPluginIfcfg *self = SETTINGS_PLUGIN_IFCFG (config);
 	gs_free char *path = NULL;
 
 	/* Ensure we reject attempts to add the connection long before we're
@@ -701,312 +685,316 @@ add_connection (NMSystemConfigInterface *config,
 	return NM_SETTINGS_CONNECTION (update_connection (self, connection, path, NULL, FALSE, NULL, error));
 }
 
-#define SC_NETWORK_FILE "/etc/sysconfig/network"
-#define HOSTNAME_FILE   "/etc/hostname"
-
-static char *
-plugin_get_hostname (SCPluginIfcfg *plugin)
+static void
+impl_ifcfgrh_get_ifcfg_details (SettingsPluginIfcfg *plugin,
+                                GDBusMethodInvocation *context,
+                                const char *in_ifcfg)
 {
-	shvarFile *network;
-	char *hostname;
-	gboolean ignore_localhost;
+	NMIfcfgConnection *connection;
+	NMSettingConnection *s_con;
+	const char *uuid;
+	const char *path;
+	gs_free char *ifcfg_path = NULL;
 
-	if (g_file_get_contents (HOSTNAME_FILE, &hostname, NULL, NULL)) {
-		g_strchomp (hostname);
-		return hostname;
+	if (!g_path_is_absolute (in_ifcfg)) {
+		g_dbus_method_invocation_return_error (context,
+		                                       NM_SETTINGS_ERROR,
+		                                       NM_SETTINGS_ERROR_INVALID_CONNECTION,
+		                                       "ifcfg path '%s' is not absolute", in_ifcfg);
+		return;
 	}
 
-	network = svOpenFile (SC_NETWORK_FILE, NULL);
-	if (!network) {
-		_LOGW ("Could not get hostname: failed to read " SC_NETWORK_FILE);
-		return NULL;
+	ifcfg_path = utils_detect_ifcfg_path (in_ifcfg, TRUE);
+	if (!ifcfg_path) {
+		g_dbus_method_invocation_return_error (context,
+		                                       NM_SETTINGS_ERROR,
+		                                       NM_SETTINGS_ERROR_INVALID_CONNECTION,
+		                                       "ifcfg path '%s' is not an ifcfg base file", in_ifcfg);
+		return;
 	}
 
-	hostname = svGetValue (network, "HOSTNAME", FALSE);
-	ignore_localhost = svTrueValue (network, "NM_IGNORE_HOSTNAME_LOCALHOST", FALSE);
-	if (ignore_localhost) {
-		/* Ignore a default hostname ('localhost[6]' or 'localhost[6].localdomain[6]')
-		 * to preserve 'network' service behavior.
-		 */
-		if (hostname && !nm_utils_is_specific_hostname (hostname)) {
-			g_free (hostname);
-			hostname = NULL;
-		}
+	connection = find_by_path (plugin, ifcfg_path);
+	if (   !connection
+	    || nm_ifcfg_connection_get_unmanaged_spec (connection)
+	    || nm_ifcfg_connection_get_unrecognized_spec (connection)) {
+		g_dbus_method_invocation_return_error (context,
+		                                       NM_SETTINGS_ERROR,
+		                                       NM_SETTINGS_ERROR_INVALID_CONNECTION,
+		                                       "ifcfg file '%s' unknown", in_ifcfg);
+		return;
 	}
 
-	svCloseFile (network);
-	return hostname;
-}
-
-static gboolean
-plugin_set_hostname (SCPluginIfcfg *plugin, const char *hostname)
-{
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
-	shvarFile *network;
-	char *hostname_eol;
-	gboolean ret;
-#if HAVE_SELINUX
-	security_context_t se_ctx_prev = NULL, se_ctx = NULL;
-	struct stat file_stat = { .st_mode = 0 };
-	mode_t st_mode = 0;
-
-	/* Get default context for HOSTNAME_FILE and set it for fscreate */
-	if (stat (HOSTNAME_FILE, &file_stat) == 0)
-		st_mode = file_stat.st_mode;
-	matchpathcon (HOSTNAME_FILE, st_mode, &se_ctx);
-	matchpathcon_fini ();
-	getfscreatecon (&se_ctx_prev);
-	setfscreatecon (se_ctx);
-#endif
-
-	hostname_eol = g_strdup_printf ("%s\n", hostname);
-	ret = g_file_set_contents (HOSTNAME_FILE, hostname_eol, -1, NULL);
-
-#if HAVE_SELINUX
-	/* Restore previous context and cleanup */
-	setfscreatecon (se_ctx_prev);
-	freecon (se_ctx);
-	freecon (se_ctx_prev);
-#endif
-
-	if (!ret) {
-		_LOGW ("Could not save hostname: failed to create/open " HOSTNAME_FILE);
-		g_free (hostname_eol);
-		return FALSE;
+	s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
+	if (!s_con) {
+		g_dbus_method_invocation_return_error (context,
+		                                       NM_SETTINGS_ERROR,
+		                                       NM_SETTINGS_ERROR_FAILED,
+		                                       "unable to retrieve the connection setting");
+		return;
 	}
 
-	g_free (priv->hostname);
-	priv->hostname = g_strdup (hostname);
-	g_free (hostname_eol);
+	uuid = nm_setting_connection_get_uuid (s_con);
+	if (!uuid) {
+		g_dbus_method_invocation_return_error (context,
+		                                       NM_SETTINGS_ERROR,
+		                                       NM_SETTINGS_ERROR_FAILED,
+		                                       "unable to get the UUID");
+		return;
+	}
 
-	/* Remove "HOSTNAME" from SC_NETWORK_FILE, if present */
-	network = svOpenFile (SC_NETWORK_FILE, NULL);
-	if (network) {
-		svSetValue (network, "HOSTNAME", NULL, FALSE);
-		svWriteFile (network, 0644, NULL);
-		svCloseFile (network);
+	path = nm_connection_get_path (NM_CONNECTION (connection));
+	if (!path) {
+		g_dbus_method_invocation_return_error (context,
+		                                       NM_SETTINGS_ERROR,
+		                                       NM_SETTINGS_ERROR_FAILED,
+		                                       "unable to get the connection D-Bus path");
+		return;
 	}
 
-	return TRUE;
+	g_dbus_method_invocation_return_value (context,
+	                                       g_variant_new ("(so)", uuid, path));
 }
 
-static void
-hostname_maybe_changed (SCPluginIfcfg *plugin)
-{
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
-	char *new_hostname;
-
-	new_hostname = plugin_get_hostname (plugin);
-	if (   (new_hostname && !priv->hostname)
-	    || (!new_hostname && priv->hostname)
-	    || (priv->hostname && new_hostname && strcmp (priv->hostname, new_hostname))) {
-		g_free (priv->hostname);
-		priv->hostname = new_hostname;
-		g_object_notify (G_OBJECT (plugin), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
-	} else
-		g_free (new_hostname);
-}
+/*****************************************************************************/
 
 static void
-sc_network_changed_cb (NMInotifyHelper *ih,
-                       struct inotify_event *evt,
-                       const char *path,
-                       gpointer user_data)
+_dbus_clear (SettingsPluginIfcfg *self)
 {
-	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
 
-	if (evt->wd != priv->sc_network_wd)
-		return;
+	nm_clear_g_signal_handler (priv->dbus.connection, &priv->dbus.signal_id);
+
+	nm_clear_g_cancellable (&priv->dbus.cancellable);
+
+	if (priv->dbus.interface) {
+		g_dbus_interface_skeleton_unexport (priv->dbus.interface);
+		nm_exported_object_skeleton_release (priv->dbus.interface);
+		priv->dbus.interface = NULL;
+	}
 
-	hostname_maybe_changed (plugin);
+	g_clear_object (&priv->dbus.connection);
 }
 
 static void
-hostname_changed_cb (GFileMonitor *monitor,
-                     GFile *file,
-                     GFile *other_file,
-                     GFileMonitorEvent event_type,
-                     gpointer user_data)
+_dbus_connection_closed (GDBusConnection *connection,
+                         gboolean         remote_peer_vanished,
+                         GError          *error,
+                         gpointer         user_data)
 {
-	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
+	_LOGW ("dbus: %s bus closed", IFCFGRH1_DBUS_SERVICE_NAME);
+	_dbus_clear (SETTINGS_PLUGIN_IFCFG (user_data));
 
-	hostname_maybe_changed (plugin);
+	/* Retry or recover? */
 }
 
-static gboolean
-impl_ifcfgrh_get_ifcfg_details (SCPluginIfcfg *plugin,
-                                const char *in_ifcfg,
-                                const char **out_uuid,
-                                const char **out_path,
-                                GError **error)
+static void
+_dbus_request_name_done (GObject *source_object,
+                         GAsyncResult *res,
+                         gpointer user_data)
 {
-	NMIfcfgConnection *connection;
-	NMSettingConnection *s_con;
-	const char *uuid;
-	const char *path;
+	GDBusConnection *connection = G_DBUS_CONNECTION (source_object);
+	SettingsPluginIfcfg *self;
+	SettingsPluginIfcfgPrivate *priv;
+	gs_free_error GError *error = NULL;
+	gs_unref_variant GVariant *ret = NULL;
+	guint32 result;
+
+	ret = g_dbus_connection_call_finish (connection, res, &error);
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
 
-	if (!g_path_is_absolute (in_ifcfg)) {
-		g_set_error (error,
-		             NM_SETTINGS_ERROR,
-		             NM_SETTINGS_ERROR_INVALID_CONNECTION,
-		             "ifcfg path '%s' is not absolute", in_ifcfg);
-		return FALSE;
-	}
+	self = SETTINGS_PLUGIN_IFCFG (user_data);
+	priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
 
-	connection = find_by_path (plugin, in_ifcfg);
-	if (   !connection
-	    || nm_ifcfg_connection_get_unmanaged_spec (connection)
-	    || nm_ifcfg_connection_get_unrecognized_spec (connection)) {
-		g_set_error (error,
-		             NM_SETTINGS_ERROR,
-		             NM_SETTINGS_ERROR_INVALID_CONNECTION,
-		             "ifcfg file '%s' unknown", in_ifcfg);
-		return FALSE;
-	}
+	g_clear_object (&priv->dbus.cancellable);
 
-	s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
-	if (!s_con) {
-		g_set_error (error,
-		             NM_SETTINGS_ERROR,
-		             NM_SETTINGS_ERROR_FAILED,
-		             "unable to retrieve the connection setting");
-		return FALSE;
+	if (!ret) {
+		_LOGW ("dbus: couldn't acquire D-Bus service: %s", error->message);
+		_dbus_clear (self);
+		return;
 	}
 
-	uuid = nm_setting_connection_get_uuid (s_con);
-	if (!uuid) {
-		g_set_error (error,
-		             NM_SETTINGS_ERROR,
-		             NM_SETTINGS_ERROR_FAILED,
-		             "unable to get the UUID");
-		return FALSE;
-	}
-	
-	path = nm_connection_get_path (NM_CONNECTION (connection));
-	if (!path) {
-		g_set_error (error,
-		             NM_SETTINGS_ERROR,
-		             NM_SETTINGS_ERROR_FAILED,
-		             "unable to get the connection D-Bus path");
-		return FALSE;
+	g_variant_get (ret, "(u)", &result);
+
+	if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+		_LOGW ("dbus: couldn't acquire ifcfgrh1 D-Bus service (already taken)");
+		_dbus_clear (self);
+		return;
 	}
 
-	*out_uuid = g_strdup (uuid);
-	*out_path = g_strdup (path);
+	{
+		GType skeleton_type = NMDBUS_TYPE_IFCFGRH1_SKELETON;
+		gs_free char *method_name_get_ifcfg_details = NULL;
+		NMExportedObjectDBusMethodImpl methods[] = {
+			{
+				.method_name = (method_name_get_ifcfg_details = nm_exported_object_skeletonify_method_name ("GetIfcfgDetails")),
+				.impl = G_CALLBACK (impl_ifcfgrh_get_ifcfg_details),
+			},
+		};
+
+		priv->dbus.interface = nm_exported_object_skeleton_create (skeleton_type,
+		                                                           g_type_class_peek (SETTINGS_TYPE_PLUGIN_IFCFG),
+		                                                           methods,
+		                                                           G_N_ELEMENTS (methods),
+		                                                           (GObject *) self);
+
+		if (!g_dbus_interface_skeleton_export (priv->dbus.interface,
+		                                       priv->dbus.connection,
+		                                       IFCFGRH1_DBUS_OBJECT_PATH,
+		                                       &error)) {
+			nm_exported_object_skeleton_release (priv->dbus.interface);
+			priv->dbus.interface = NULL;
+			_LOGW ("dbus: failed exporting interface: %s", error->message);
+			_dbus_clear (self);
+			return;
+		}
+	}
 
-	return TRUE;
+	_LOGD ("dbus: aquired D-Bus service %s and exported %s object",
+	       IFCFGRH1_DBUS_SERVICE_NAME,
+	       IFCFGRH1_DBUS_OBJECT_PATH);
 }
 
 static void
-init (NMSystemConfigInterface *config)
+_dbus_create_done (GObject *source_object,
+                   GAsyncResult *res,
+                   gpointer user_data)
 {
+	SettingsPluginIfcfg *self;
+	SettingsPluginIfcfgPrivate *priv;
+	gs_free_error GError *error = NULL;
+	GDBusConnection *connection;
+
+	connection = g_dbus_connection_new_for_address_finish (res, &error);
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
+
+	self = SETTINGS_PLUGIN_IFCFG (user_data);
+	priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
+
+	g_clear_object (&priv->dbus.cancellable);
+
+	if (!connection) {
+		_LOGW ("dbus: couldn't initialize system bus: %s", error->message);
+		return;
+	}
+
+	priv->dbus.connection = connection;
+	priv->dbus.cancellable = g_cancellable_new ();
+
+	priv->dbus.signal_id = g_signal_connect (priv->dbus.connection,
+	                                         "closed",
+	                                         G_CALLBACK (_dbus_connection_closed),
+	                                         self);
+
+	g_dbus_connection_call (priv->dbus.connection,
+	                        DBUS_SERVICE_DBUS,
+	                        DBUS_PATH_DBUS,
+	                        DBUS_INTERFACE_DBUS,
+	                        "RequestName",
+	                        g_variant_new ("(su)",
+	                                       IFCFGRH1_DBUS_SERVICE_NAME,
+	                                       DBUS_NAME_FLAG_DO_NOT_QUEUE),
+	                        G_VARIANT_TYPE ("(u)"),
+	                        G_DBUS_CALL_FLAGS_NONE,
+	                        -1,
+	                        priv->dbus.cancellable,
+	                        _dbus_request_name_done,
+	                        self);
 }
 
 static void
-sc_plugin_ifcfg_init (SCPluginIfcfg *plugin)
+_dbus_setup (SettingsPluginIfcfg *self)
 {
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
-	NMInotifyHelper *ih;
-	GError *error = NULL;
-	gboolean success = FALSE;
-	GFile *file;
-	GFileMonitor *monitor;
-
-	priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
+	gs_free char *address = NULL;
+	gs_free_error GError *error = NULL;
 
-	/* We watch SC_NETWORK_FILE via NMInotifyHelper (which doesn't track file creation but
-	 * *does* track modifications made via other hard links), since we expect it to always
-	 * exist. But we watch HOSTNAME_FILE via GFileMonitor (which has the opposite
-	 * semantics), since /etc/hostname might not exist, but is unlikely to have hard
-	 * links. bgo 532815 is the bug for being able to just use GFileMonitor for both.
-	 */
-
-	ih = nm_inotify_helper_get ();
-	priv->ih_event_id = g_signal_connect (ih, "event", G_CALLBACK (sc_network_changed_cb), plugin);
-	priv->sc_network_wd = nm_inotify_helper_add_watch (ih, SC_NETWORK_FILE);
+	g_return_if_fail (!priv->dbus.connection);
 
-	file = g_file_new_for_path (HOSTNAME_FILE);
-	monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL);
-	g_object_unref (file);
-	if (monitor) {
-		priv->hostname_monitor_id =
-			g_signal_connect (monitor, "changed", G_CALLBACK (hostname_changed_cb), plugin);
-		priv->hostname_monitor = monitor;
+	address = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+	if (address == NULL) {
+		_LOGW ("dbus: failed getting address for system bus: %s", error->message);
+		return;
 	}
 
-	priv->hostname = plugin_get_hostname (plugin);
+	priv->dbus.cancellable = g_cancellable_new ();
 
-	priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
-	if (!priv->bus) {
-		_LOGW ("Couldn't connect to D-Bus: %s", error->message);
-		g_clear_error (&error);
-	} else {
-		DBusConnection *tmp;
-		DBusGProxy *proxy;
-		int result;
-
-		tmp = dbus_g_connection_get_connection (priv->bus);
-		dbus_connection_set_exit_on_disconnect (tmp, FALSE);
-
-		proxy = dbus_g_proxy_new_for_name (priv->bus,
-		                                   "org.freedesktop.DBus",
-		                                   "/org/freedesktop/DBus",
-		                                   "org.freedesktop.DBus");
-
-		if (!dbus_g_proxy_call (proxy, "RequestName", &error,
-		                        G_TYPE_STRING, DBUS_SERVICE_NAME,
-		                        G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE,
-		                        G_TYPE_INVALID,
-		                        G_TYPE_UINT, &result,
-		                        G_TYPE_INVALID)) {
-			_LOGW ("Couldn't acquire D-Bus service: %s", error->message);
-			g_clear_error (&error);
-		} else if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
-			_LOGW ("Couldn't acquire ifcfgrh1 D-Bus service (already taken)");
-		} else
-			success = TRUE;
-	}
+	g_dbus_connection_new_for_address (address,
+	                                   G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT
+	                                   | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
+	                                   NULL,
+	                                   priv->dbus.cancellable,
+	                                   _dbus_create_done,
+	                                   self);
+}
 
-	if (!success) {
-		if (priv->bus) {
-			dbus_g_connection_unref (priv->bus);
-			priv->bus = NULL;
-		}
+static void
+config_changed_cb (NMConfig *config,
+                   NMConfigData *config_data,
+                   NMConfigChangeFlags changes,
+                   NMConfigData *old_data,
+                   SettingsPluginIfcfg *self)
+{
+	/* If the dbus connection for some reason is borked the D-Bus service
+	 * won't be offered.
+	 *
+	 * On SIGHUP and SIGUSR1 try to re-connect to D-Bus. So in the unlikely
+	 * event that the D-Bus conneciton is broken, that allows for recovery
+	 * without need for restarting NetworkManager. */
+	if (   NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_SIGHUP)
+	    || NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_SIGUSR1)) {
+		if (!SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self)->dbus.connection)
+			_dbus_setup (self);
 	}
 }
 
+/*****************************************************************************/
+
 static void
-dispose (GObject *object)
+init (NMSettingsPlugin *config)
 {
-	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (object);
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
-	NMInotifyHelper *ih;
+}
 
-	if (priv->bus) {
-		dbus_g_connection_unref (priv->bus);
-		priv->bus = NULL;
-	}
+static void
+settings_plugin_ifcfg_init (SettingsPluginIfcfg *plugin)
+{
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+
+	priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+}
 
-	if (priv->ih_event_id) {
-		ih = nm_inotify_helper_get ();
+static void
+constructed (GObject *object)
+{
+	SettingsPluginIfcfg *self = SETTINGS_PLUGIN_IFCFG (object);
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
 
-		g_signal_handler_disconnect (ih, priv->ih_event_id);
-		priv->ih_event_id = 0;
+	G_OBJECT_CLASS (settings_plugin_ifcfg_parent_class)->constructed (object);
 
-		if (priv->sc_network_wd >= 0)
-			nm_inotify_helper_remove_watch (ih, priv->sc_network_wd);
-	}
+	priv->config = nm_config_get ();
+	g_object_add_weak_pointer ((GObject *) priv->config, (gpointer *) &priv->config);
+	g_signal_connect (priv->config,
+	                  NM_CONFIG_SIGNAL_CONFIG_CHANGED,
+	                  G_CALLBACK (config_changed_cb),
+	                  self);
 
-	if (priv->hostname_monitor) {
-		if (priv->hostname_monitor_id)
-			g_signal_handler_disconnect (priv->hostname_monitor, priv->hostname_monitor_id);
+	_dbus_setup (self);
+}
+
+static void
+dispose (GObject *object)
+{
+	SettingsPluginIfcfg *self = SETTINGS_PLUGIN_IFCFG (object);
+	SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self);
 
-		g_file_monitor_cancel (priv->hostname_monitor);
-		g_object_unref (priv->hostname_monitor);
+	if (priv->config) {
+		g_object_remove_weak_pointer ((GObject *) priv->config, (gpointer *) &priv->config);
+		g_signal_handlers_disconnect_by_func (priv->config, config_changed_cb, self);
+		priv->config = NULL;
 	}
 
-	g_free (priv->hostname);
+	_dbus_clear (self);
 
 	if (priv->connections) {
 		g_hash_table_destroy (priv->connections);
@@ -1021,27 +1009,22 @@ dispose (GObject *object)
 		g_object_unref (priv->ifcfg_monitor);
 	}
 
-	G_OBJECT_CLASS (sc_plugin_ifcfg_parent_class)->dispose (object);
+	G_OBJECT_CLASS (settings_plugin_ifcfg_parent_class)->dispose (object);
 }
 
 static void
 get_property (GObject *object, guint prop_id,
 			  GValue *value, GParamSpec *pspec)
 {
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (object);
-
 	switch (prop_id) {
-	case NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME:
+	case NM_SETTINGS_PLUGIN_PROP_NAME:
 		g_value_set_string (value, IFCFG_PLUGIN_NAME);
 		break;
-	case NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO:
+	case NM_SETTINGS_PLUGIN_PROP_INFO:
 		g_value_set_string (value, IFCFG_PLUGIN_INFO);
 		break;
-	case NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES:
-		g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS | NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME);
-		break;
-	case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME:
-		g_value_set_string (value, priv->hostname);
+	case NM_SETTINGS_PLUGIN_PROP_CAPABILITIES:
+		g_value_set_uint (value, NM_SETTINGS_PLUGIN_CAP_MODIFY_CONNECTIONS);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1053,15 +1036,7 @@ static void
 set_property (GObject *object, guint prop_id,
 			  const GValue *value, GParamSpec *pspec)
 {
-	const char *hostname;
-
 	switch (prop_id) {
-	case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME:
-		hostname = g_value_get_string (value);
-		if (hostname && strlen (hostname) < 1)
-			hostname = NULL;
-		plugin_set_hostname (SC_PLUGIN_IFCFG (object), hostname);
-		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1069,65 +1044,45 @@ set_property (GObject *object, guint prop_id,
 }
 
 static void
-sc_plugin_ifcfg_class_init (SCPluginIfcfgClass *req_class)
+settings_plugin_ifcfg_class_init (SettingsPluginIfcfgClass *req_class)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (req_class);
 
-	g_type_class_add_private (req_class, sizeof (SCPluginIfcfgPrivate));
+	g_type_class_add_private (req_class, sizeof (SettingsPluginIfcfgPrivate));
 
+	object_class->constructed = constructed;
 	object_class->dispose = dispose;
 	object_class->get_property = get_property;
 	object_class->set_property = set_property;
 
 	g_object_class_override_property (object_class,
-	                                  NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME,
-	                                  NM_SYSTEM_CONFIG_INTERFACE_NAME);
-
-	g_object_class_override_property (object_class,
-	                                  NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO,
-	                                  NM_SYSTEM_CONFIG_INTERFACE_INFO);
+	                                  NM_SETTINGS_PLUGIN_PROP_NAME,
+	                                  NM_SETTINGS_PLUGIN_NAME);
 
 	g_object_class_override_property (object_class,
-	                                  NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES,
-	                                  NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES);
+	                                  NM_SETTINGS_PLUGIN_PROP_INFO,
+	                                  NM_SETTINGS_PLUGIN_INFO);
 
 	g_object_class_override_property (object_class,
-	                                  NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME,
-	                                  NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
-
-	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (req_class),
-									 &dbus_glib_nm_ifcfg_rh_object_info);
+	                                  NM_SETTINGS_PLUGIN_PROP_CAPABILITIES,
+	                                  NM_SETTINGS_PLUGIN_CAPABILITIES);
 }
 
 static void
-system_config_interface_init (NMSystemConfigInterface *system_config_interface_class)
+settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface)
 {
 	/* interface implementation */
-	system_config_interface_class->get_connections = get_connections;
-	system_config_interface_class->add_connection = add_connection;
-	system_config_interface_class->load_connection = load_connection;
-	system_config_interface_class->reload_connections = reload_connections;
-	system_config_interface_class->get_unmanaged_specs = get_unmanaged_specs;
-	system_config_interface_class->get_unrecognized_specs = get_unrecognized_specs;
-	system_config_interface_class->init = init;
+	plugin_iface->get_connections = get_connections;
+	plugin_iface->add_connection = add_connection;
+	plugin_iface->load_connection = load_connection;
+	plugin_iface->reload_connections = reload_connections;
+	plugin_iface->get_unmanaged_specs = get_unmanaged_specs;
+	plugin_iface->get_unrecognized_specs = get_unrecognized_specs;
+	plugin_iface->init = init;
 }
 
 G_MODULE_EXPORT GObject *
-nm_system_config_factory (void)
+nm_settings_plugin_factory (void)
 {
-	static SCPluginIfcfg *singleton = NULL;
-	SCPluginIfcfgPrivate *priv;
-
-	if (!singleton) {
-		singleton = SC_PLUGIN_IFCFG (g_object_new (SC_TYPE_PLUGIN_IFCFG, NULL));
-		priv = SC_PLUGIN_IFCFG_GET_PRIVATE (singleton);
-		if (priv->bus)
-			dbus_g_connection_register_g_object (priv->bus,
-			                                     DBUS_OBJECT_PATH,
-			                                     G_OBJECT (singleton));
-		_LOGD ("Acquired D-Bus service %s", DBUS_SERVICE_NAME);
-	} else
-		g_object_ref (singleton);
-
-	return G_OBJECT (singleton);
+	return g_object_ref (settings_plugin_ifcfg_get ());
 }