about summary refs log tree commit diff
path: root/src/settings/nm-settings.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/settings/nm-settings.c')
-rw-r--r--src/settings/nm-settings.c524
1 files changed, 29 insertions, 495 deletions
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index afd1b084..e2b467a2 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -76,6 +76,7 @@
 #include "NetworkManagerUtils.h"
 #include "nm-dispatcher.h"
 #include "nm-inotify-helper.h"
+#include "nm-hostname-manager.h"
 
 #include "introspection/org.freedesktop.NetworkManager.Settings.h"
 
@@ -90,20 +91,9 @@ EXPORT(nm_inotify_helper_remove_watch)
 
 EXPORT(nm_settings_connection_get_type)
 EXPORT(nm_settings_connection_replace_settings)
-EXPORT(nm_settings_connection_replace_and_commit)
 
 /*****************************************************************************/
 
-#define HOSTNAMED_SERVICE_NAME      "org.freedesktop.hostname1"
-#define HOSTNAMED_SERVICE_PATH      "/org/freedesktop/hostname1"
-#define HOSTNAMED_SERVICE_INTERFACE "org.freedesktop.hostname1"
-
-#define HOSTNAME_FILE_DEFAULT        "/etc/hostname"
-#define HOSTNAME_FILE_UCASE_HOSTNAME "/etc/HOSTNAME"
-#define HOSTNAME_FILE_GENTOO         "/etc/conf.d/hostname"
-#define IFCFG_DIR                    SYSCONFDIR "/sysconfig/network"
-#define CONF_DHCP                    IFCFG_DIR "/dhcp"
-
 static NM_CACHED_QUARK_FCN ("plugin-module-path", plugin_module_path_quark)
 
 #if (defined(HOSTNAME_PERSIST_SUSE) + defined(HOSTNAME_PERSIST_SLACKWARE) + defined(HOSTNAME_PERSIST_GENTOO)) > 1
@@ -162,14 +152,8 @@ typedef struct {
 	gboolean started;
 	gboolean startup_complete;
 
-	struct {
-		char *value;
-		GFileMonitor *monitor;
-		GFileMonitor *dhcp_monitor;
-		gulong monitor_id;
-		gulong dhcp_monitor_id;
-		GDBusProxy *hostnamed_proxy;
-	} hostname;
+	NMHostnameManager *hostname_manager;
+
 } NMSettingsPrivate;
 
 struct _NMSettings {
@@ -568,131 +552,6 @@ get_plugin (NMSettings *self, guint32 capability)
 	return NULL;
 }
 
-#if defined(HOSTNAME_PERSIST_GENTOO)
-static gchar *
-read_hostname_gentoo (const char *path)
-{
-	gs_free char *contents = NULL;
-	gs_strfreev char **all_lines = NULL;
-	const char *tmp;
-	guint i;
-
-	if (!g_file_get_contents (path, &contents, NULL, NULL))
-		return NULL;
-
-	all_lines = g_strsplit (contents, "\n", 0);
-	for (i = 0; all_lines[i]; i++) {
-		g_strstrip (all_lines[i]);
-		if (all_lines[i][0] == '#' || all_lines[i][0] == '\0')
-			continue;
-		if (g_str_has_prefix (all_lines[i], "hostname=")) {
-			tmp = &all_lines[i][NM_STRLEN ("hostname=")];
-			return g_shell_unquote (tmp, NULL);
-		}
-	}
-	return NULL;
-}
-#endif
-
-#if defined(HOSTNAME_PERSIST_SLACKWARE)
-static gchar *
-read_hostname_slackware (const char *path)
-{
-	gs_free char *contents = NULL;
-	gs_strfreev char **all_lines = NULL;
-	char *tmp;
-	guint i, j = 0;
-
-	if (!g_file_get_contents (path, &contents, NULL, NULL))
-		return NULL;
-
-	all_lines = g_strsplit (contents, "\n", 0);
-	for (i = 0; all_lines[i]; i++) {
-		g_strstrip (all_lines[i]);
-		if (all_lines[i][0] == '#' || all_lines[i][0] == '\0')
-			continue;
-		tmp = &all_lines[i][0];
-		/* We only want up to the first '.' -- the rest of the */
-		/* fqdn is defined in /etc/hosts */
-		while (tmp[j] != '\0') {
-			if (tmp[j] == '.') {
-				tmp[j] = '\0';
-				break;
-			}
-			j++;
-		}
-		return g_shell_unquote (tmp, NULL);
-	}
-	return NULL;
-}
-#endif
-
-#if defined(HOSTNAME_PERSIST_SUSE)
-static gboolean
-hostname_is_dynamic (void)
-{
-	GIOChannel *channel;
-	char *str = NULL;
-	gboolean dynamic = FALSE;
-
-	channel = g_io_channel_new_file (CONF_DHCP, "r", NULL);
-	if (!channel)
-		return dynamic;
-
-	while (g_io_channel_read_line (channel, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) {
-		if (str) {
-			g_strstrip (str);
-			if (g_str_has_prefix (str, "DHCLIENT_SET_HOSTNAME="))
-				dynamic = strcmp (&str[NM_STRLEN ("DHCLIENT_SET_HOSTNAME=")], "\"yes\"") == 0;
-			g_free (str);
-		}
-	}
-
-	g_io_channel_shutdown (channel, FALSE, NULL);
-	g_io_channel_unref (channel);
-
-	return dynamic;
-}
-#endif
-
-/* Returns an allocated string which the caller owns and must eventually free */
-char *
-nm_settings_get_hostname (NMSettings *self)
-{
-	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
-	char *hostname = NULL;
-
-	if (!priv->started)
-		return NULL;
-
-	if (priv->hostname.hostnamed_proxy) {
-		hostname = g_strdup (priv->hostname.value);
-		goto out;
-	}
-
-#if defined(HOSTNAME_PERSIST_SUSE)
-	if (priv->hostname.dhcp_monitor_id && hostname_is_dynamic ())
-		return NULL;
-#endif
-
-#if defined(HOSTNAME_PERSIST_GENTOO)
-	hostname = read_hostname_gentoo (HOSTNAME_FILE);
-#elif defined(HOSTNAME_PERSIST_SLACKWARE)
-	hostname = read_hostname_slackware (HOSTNAME_FILE);
-#else
-	if (g_file_get_contents (HOSTNAME_FILE, &hostname, NULL, NULL))
-		g_strchomp (hostname);
-#endif
-
-out:
-	if (hostname && !hostname[0]) {
-		g_free (hostname);
-		hostname = NULL;
-	}
-
-	return hostname;
-}
-
 static gboolean
 find_spec (GSList *spec_list, const char *spec)
 {
@@ -1626,160 +1485,7 @@ impl_settings_reload_connections (NMSettings *self,
 	g_dbus_method_invocation_return_value (context, g_variant_new ("(b)", TRUE));
 }
 
-typedef struct {
-	char *hostname;
-	NMSettingsSetHostnameCb cb;
-	gpointer user_data;
-} SetHostnameInfo;
-
-static void
-set_transient_hostname_done (GObject *object,
-                             GAsyncResult *res,
-                             gpointer user_data)
-{
-	GDBusProxy *proxy = G_DBUS_PROXY (object);
-	gs_free SetHostnameInfo *info = user_data;
-	gs_unref_variant GVariant *result = NULL;
-	gs_free_error GError *error = NULL;
-
-	result = g_dbus_proxy_call_finish (proxy, res, &error);
-
-	if (error) {
-		_LOGW ("couldn't set the system hostname to '%s' using hostnamed: %s",
-		       info->hostname, error->message);
-	}
-
-	info->cb (info->hostname, !error, info->user_data);
-	g_free (info->hostname);
-}
-
-void
-nm_settings_set_transient_hostname (NMSettings *self,
-                                    const char *hostname,
-                                    NMSettingsSetHostnameCb cb,
-                                    gpointer user_data)
-{
-	NMSettingsPrivate *priv;
-	SetHostnameInfo *info;
-
-	g_return_if_fail (NM_IS_SETTINGS (self));
-	priv = NM_SETTINGS_GET_PRIVATE (self);
-
-	if (!priv->hostname.hostnamed_proxy) {
-		cb (hostname, FALSE, user_data);
-		return;
-	}
-
-	info = g_new0 (SetHostnameInfo, 1);
-	info->hostname = g_strdup (hostname);
-	info->cb = cb;
-	info->user_data = user_data;
-
-	g_dbus_proxy_call (priv->hostname.hostnamed_proxy,
-	                   "SetHostname",
-	                   g_variant_new ("(sb)", hostname, FALSE),
-	                   G_DBUS_CALL_FLAGS_NONE,
-	                   -1,
-	                   NULL,
-	                   set_transient_hostname_done,
-	                   info);
-}
-
-gboolean
-nm_settings_get_transient_hostname (NMSettings *self, char **hostname)
-{
-	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
-	GVariant *v_hostname;
-
-	if (!priv->hostname.hostnamed_proxy)
-		return FALSE;
-
-	v_hostname = g_dbus_proxy_get_cached_property (priv->hostname.hostnamed_proxy,
-	                                               "Hostname");
-	if (!v_hostname) {
-		_LOGT ("transient hostname retrieval failed");
-		return FALSE;
-	}
-
-	*hostname = g_variant_dup_string (v_hostname, NULL);
-	g_variant_unref (v_hostname);
-
-	return TRUE;
-}
-
-static gboolean
-write_hostname (NMSettingsPrivate *priv, const char *hostname)
-{
-	char *hostname_eol;
-	gboolean ret;
-	gs_free_error GError *error = NULL;
-	const char *file = HOSTNAME_FILE;
-	gs_free char *link_path = NULL;
-	gs_unref_variant GVariant *var = NULL;
-	struct stat file_stat;
-#if HAVE_SELINUX
-	security_context_t se_ctx_prev = NULL, se_ctx = NULL;
-	mode_t st_mode = 0;
-#endif
-
-	if (priv->hostname.hostnamed_proxy) {
-		var = g_dbus_proxy_call_sync (priv->hostname.hostnamed_proxy,
-		                              "SetStaticHostname",
-		                              g_variant_new ("(sb)", hostname, FALSE),
-		                              G_DBUS_CALL_FLAGS_NONE,
-		                              -1,
-		                              NULL,
-		                              &error);
-		if (error)
-			_LOGW ("could not set hostname: %s", error->message);
-
-		return !error;
-	}
-
-	/* If the hostname file is a symbolic link, follow it to find where the
-	 * real file is located, otherwise g_file_set_contents will attempt to
-	 * replace the link with a plain file.
-	 */
-	if (   lstat (file, &file_stat) == 0
-	    && S_ISLNK (file_stat.st_mode)
-	    && (link_path = nm_utils_read_link_absolute (file, NULL)))
-		file = link_path;
-
-#if HAVE_SELINUX
-	/* Get default context for hostname file and set it for fscreate */
-	if (stat (file, &file_stat) == 0)
-		st_mode = file_stat.st_mode;
-	matchpathcon (file, st_mode, &se_ctx);
-	matchpathcon_fini ();
-	getfscreatecon (&se_ctx_prev);
-	setfscreatecon (se_ctx);
-#endif
-
-#if defined (HOSTNAME_PERSIST_GENTOO)
-	hostname_eol = g_strdup_printf ("#Generated by NetworkManager\n"
-	                                "hostname=\"%s\"\n", hostname);
-#else
-	hostname_eol = g_strdup_printf ("%s\n", hostname);
-#endif
-
-	ret = g_file_set_contents (file, hostname_eol, -1, &error);
-
-#if HAVE_SELINUX
-	/* Restore previous context and cleanup */
-	setfscreatecon (se_ctx_prev);
-	freecon (se_ctx);
-	freecon (se_ctx_prev);
-#endif
-
-	g_free (hostname_eol);
-
-	if (!ret) {
-		_LOGW ("could not save hostname to %s: %s", file, error->message);
-		return FALSE;
-	}
-
-	return TRUE;
-}
+/*****************************************************************************/
 
 static void
 pk_hostname_cb (NMAuthChain *chain,
@@ -1812,7 +1518,7 @@ pk_hostname_cb (NMAuthChain *chain,
 	} else {
 		hostname = nm_auth_chain_get_data (chain, "hostname");
 
-		if (!write_hostname (priv, hostname)) {
+		if (!nm_hostname_manager_write_hostname (priv->hostname_manager, hostname)) {
 			error = g_error_new_literal (NM_SETTINGS_ERROR,
 			                             NM_SETTINGS_ERROR_FAILED,
 			                             "Saving the hostname failed.");
@@ -1827,33 +1533,6 @@ pk_hostname_cb (NMAuthChain *chain,
 	nm_auth_chain_unref (chain);
 }
 
-static gboolean
-validate_hostname (const char *hostname)
-{
-	const char *p;
-	gboolean dot = TRUE;
-
-	if (!hostname || !hostname[0])
-		return FALSE;
-
-	for (p = hostname; *p; p++) {
-		if (*p == '.') {
-			if (dot)
-				return FALSE;
-			dot = TRUE;
-		} else {
-			if (!g_ascii_isalnum (*p) && (*p != '-') && (*p != '_'))
-				return FALSE;
-			dot = FALSE;
-		}
-	}
-
-	if (dot)
-		return FALSE;
-
-	return (p - hostname <= HOST_NAME_MAX);
-}
-
 static void
 impl_settings_save_hostname (NMSettings *self,
                              GDBusMethodInvocation *context,
@@ -1864,7 +1543,7 @@ impl_settings_save_hostname (NMSettings *self,
 	GError *error = NULL;
 
 	/* Minimal validation of the hostname */
-	if (!validate_hostname (hostname)) {
+	if (!nm_hostname_manager_validate_hostname (hostname)) {
 		error = g_error_new_literal (NM_SETTINGS_ERROR,
 		                             NM_SETTINGS_ERROR_INVALID_HOSTNAME,
 		                             "The hostname was too long or contained invalid characters.");
@@ -1888,37 +1567,7 @@ done:
 		g_dbus_method_invocation_take_error (context, error);
 }
 
-static void
-hostname_maybe_changed (NMSettings *settings)
-{
-	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (settings);
-	char *new_hostname;
-
-	new_hostname = nm_settings_get_hostname (settings);
-
-	if (   (new_hostname && !priv->hostname.value)
-	    || (!new_hostname && priv->hostname.value)
-	    || (priv->hostname.value && new_hostname && strcmp (priv->hostname.value, new_hostname))) {
-
-		_LOGI ("hostname changed from %s%s%s to %s%s%s",
-		       NM_PRINT_FMT_QUOTED (priv->hostname.value, "\"", priv->hostname.value, "\"", "(none)"),
-		       NM_PRINT_FMT_QUOTED (new_hostname, "\"", new_hostname, "\"", "(none)"));
-		g_free (priv->hostname.value);
-		priv->hostname.value = new_hostname;
-		_notify (settings, PROP_HOSTNAME);
-	} else
-		g_free (new_hostname);
-}
-
-static void
-hostname_file_changed_cb (GFileMonitor *monitor,
-                          GFile *file,
-                          GFile *other_file,
-                          GFileMonitorEvent event_type,
-                          gpointer user_data)
-{
-	hostname_maybe_changed (user_data);
-}
+/*****************************************************************************/
 
 static gboolean
 have_connection_for_device (NMSettings *self, NMDevice *device)
@@ -2124,7 +1773,7 @@ nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean quittin
 		 * remains up and can be assumed if NM starts again.
 		 */
 		if (quitting == FALSE)
-			nm_settings_connection_delete (connection, NULL, NULL);
+			nm_settings_connection_delete (connection, NULL);
 	}
 }
 
@@ -2141,95 +1790,19 @@ nm_settings_get_startup_complete (NMSettings *self)
 /*****************************************************************************/
 
 static void
-hostnamed_properties_changed (GDBusProxy *proxy,
-                              GVariant *changed_properties,
-                              char **invalidated_properties,
-                              gpointer user_data)
+_hostname_changed_cb (NMHostnameManager *hostname_manager,
+                      GParamSpec *pspec,
+                      gpointer user_data)
 {
-	NMSettings *self = user_data;
-	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
-	GVariant *v_hostname;
-	const char *hostname;
-
-	v_hostname = g_dbus_proxy_get_cached_property (priv->hostname.hostnamed_proxy,
-	                                               "StaticHostname");
-	if (!v_hostname)
-		return;
-
-	hostname = g_variant_get_string (v_hostname, NULL);
-
-	if (g_strcmp0 (priv->hostname.value, hostname) != 0) {
-		_LOGI ("hostname changed from %s%s%s to %s%s%s",
-		       NM_PRINT_FMT_QUOTED (priv->hostname.value, "\"", priv->hostname.value, "\"", "(none)"),
-		       NM_PRINT_FMT_QUOTED (hostname, "\"", hostname, "\"", "(none)"));
-		g_free (priv->hostname.value);
-		priv->hostname.value = g_strdup (hostname);
-		_notify (self, PROP_HOSTNAME);
-		nm_dispatcher_call_hostname (NULL, NULL, NULL);
-	}
-
-	g_variant_unref (v_hostname);
+	_notify (user_data, PROP_HOSTNAME);
 }
 
-static void
-setup_hostname_file_monitors (NMSettings *self)
-{
-	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
-	GFileMonitor *monitor;
-	const char *path = HOSTNAME_FILE;
-	char *link_path = NULL;
-	struct stat file_stat;
-	GFile *file;
-
-	priv->hostname.value = nm_settings_get_hostname (self);
-
-	/* resolve the path to the hostname file if it is a symbolic link */
-	if (   lstat(path, &file_stat) == 0
-	    && S_ISLNK (file_stat.st_mode)
-	    && (link_path = nm_utils_read_link_absolute (path, NULL))) {
-		path = link_path;
-		if (   lstat(link_path, &file_stat) == 0
-		    && S_ISLNK (file_stat.st_mode)) {
-			_LOGW ("only one level of symbolic link indirection is allowed when monitoring "
-			       HOSTNAME_FILE);
-		}
-	}
-
-	/* monitor changes to hostname file */
-	file = g_file_new_for_path (path);
-	monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL);
-	g_object_unref (file);
-	g_free(link_path);
-	if (monitor) {
-		priv->hostname.monitor_id = g_signal_connect (monitor, "changed",
-		                                              G_CALLBACK (hostname_file_changed_cb),
-		                                              self);
-		priv->hostname.monitor = monitor;
-	}
-
-#if defined (HOSTNAME_PERSIST_SUSE)
-	/* monitor changes to dhcp file to know whether the hostname is valid */
-	file = g_file_new_for_path (CONF_DHCP);
-	monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL);
-	g_object_unref (file);
-	if (monitor) {
-		priv->hostname.dhcp_monitor_id = g_signal_connect (monitor, "changed",
-		                                                   G_CALLBACK (hostname_file_changed_cb),
-		                                                   self);
-		priv->hostname.dhcp_monitor = monitor;
-	}
-#endif
-
-	hostname_maybe_changed (self);
-}
+/*****************************************************************************/
 
 gboolean
 nm_settings_start (NMSettings *self, GError **error)
 {
 	NMSettingsPrivate *priv;
-	GDBusProxy *proxy;
-	GVariant *variant;
-	GError *local_error = NULL;
 	gs_strfreev char **plugins = NULL;
 
 	priv = NM_SETTINGS_GET_PRIVATE (self);
@@ -2245,33 +1818,14 @@ nm_settings_start (NMSettings *self, GError **error)
 	load_connections (self);
 	check_startup_complete (self);
 
-	proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, 0, NULL,
-	                                       HOSTNAMED_SERVICE_NAME, HOSTNAMED_SERVICE_PATH,
-	                                       HOSTNAMED_SERVICE_INTERFACE, NULL, &local_error);
-	if (proxy) {
-		variant = g_dbus_proxy_get_cached_property (proxy, "StaticHostname");
-		if (variant) {
-			_LOGI ("hostname: using hostnamed");
-			priv->hostname.hostnamed_proxy = proxy;
-			g_signal_connect (proxy, "g-properties-changed",
-			                  G_CALLBACK (hostnamed_properties_changed), self);
-			hostnamed_properties_changed (proxy, NULL, NULL, self);
-			g_variant_unref (variant);
-		} else {
-			_LOGI ("hostname: couldn't get property from hostnamed");
-			g_object_unref (proxy);
-		}
-	} else {
-		_LOGI ("hostname: hostnamed not used as proxy creation failed with: %s",
-		       local_error->message);
-		g_clear_error (&local_error);
-	}
-
-	if (!priv->hostname.hostnamed_proxy)
-		setup_hostname_file_monitors (self);
+	priv->hostname_manager = g_object_ref (nm_hostname_manager_get ());
+	g_signal_connect (priv->hostname_manager,
+	                  "notify::"NM_HOSTNAME_MANAGER_HOSTNAME,
+	                  G_CALLBACK (_hostname_changed_cb),
+	                  self);
+	if (nm_hostname_manager_get_hostname (priv->hostname_manager))
+		_notify (self, PROP_HOSTNAME);
 
-	priv->started = TRUE;
-	_notify (self, PROP_HOSTNAME);
 	return TRUE;
 }
 
@@ -2298,11 +1852,10 @@ get_property (GObject *object, guint prop_id,
 		g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE));
 		break;
 	case PROP_HOSTNAME:
-		g_value_take_string (value, nm_settings_get_hostname (self));
-
-		/* Don't ever pass NULL through D-Bus */
-		if (!g_value_get_string (value))
-			g_value_set_static_string (value, "");
+		g_value_set_string (value,
+		                    priv->hostname_manager
+		                      ? nm_hostname_manager_get_hostname (priv->hostname_manager)
+		                      : NULL);
 		break;
 	case PROP_CAN_MODIFY:
 		g_value_set_boolean (value, !!get_plugin (self, NM_SETTINGS_PLUGIN_CAP_MODIFY_CONNECTIONS));
@@ -2331,7 +1884,7 @@ nm_settings_init (NMSettings *self)
 {
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
 
-	priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+	priv->connections = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_object_unref);
 
 	/* Hold a reference to the agent manager so it stays alive; the only
 	 * other holders are NMSettingsConnection objects which are often
@@ -2362,32 +1915,13 @@ dispose (GObject *object)
 
 	g_object_unref (priv->agent_mgr);
 
-	if (priv->hostname.hostnamed_proxy) {
-		g_signal_handlers_disconnect_by_func (priv->hostname.hostnamed_proxy,
-		                                      G_CALLBACK (hostnamed_properties_changed),
+	if (priv->hostname_manager) {
+		g_signal_handlers_disconnect_by_func (priv->hostname_manager,
+		                                      G_CALLBACK (_hostname_changed_cb),
 		                                      self);
-		g_clear_object (&priv->hostname.hostnamed_proxy);
-	}
-
-	if (priv->hostname.monitor) {
-		if (priv->hostname.monitor_id)
-			g_signal_handler_disconnect (priv->hostname.monitor, priv->hostname.monitor_id);
-
-		g_file_monitor_cancel (priv->hostname.monitor);
-		g_clear_object (&priv->hostname.monitor);
+		g_clear_object (&priv->hostname_manager);
 	}
 
-	if (priv->hostname.dhcp_monitor) {
-		if (priv->hostname.dhcp_monitor_id)
-			g_signal_handler_disconnect (priv->hostname.dhcp_monitor,
-			                             priv->hostname.dhcp_monitor_id);
-
-		g_file_monitor_cancel (priv->hostname.dhcp_monitor);
-		g_clear_object (&priv->hostname.dhcp_monitor);
-	}
-
-	g_clear_pointer (&priv->hostname.value, g_free);
-
 	G_OBJECT_CLASS (nm_settings_parent_class)->dispose (object);
 }