NetworkManager r4077 - in trunk: . introspection libnm-glib src src/dhcp-manager system-settings/plugins/ifcfg-fedora system-settings/plugins/ifcfg-suse system-settings/plugins/keyfile system-settings/src



Author: dcbw
Date: Thu Sep 18 15:16:44 2008
New Revision: 4077
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=4077&view=rev

Log:
2008-09-18  Dan Williams  <dcbw redhat com>

	Implement support for honoring configured and automatic hostnames, and for
	setting the configured hostname.

	* introspection/nm-ip4-config.xml
	  src/nm-ip4-config.c
	  src/nm-ip4-config.h
	  src/dhcp-manager/nm-dhcp-manager.c
		- Remove useless hostname property; it's not really part of the IPv4
			config

	* introspection/nm-settings-system.xml
	  libnm-glib/nm-dbus-settings-system.c
	  libnm-glib/nm-dbus-settings-system.h
		- Add SetHostname() call to system settings D-Bus interface
		- Add Hostname property to system settings D-Bus interface
		- (nm_dbus_settings_system_save_hostname,
		   nm_dbus_settings_system_get_hostname): implement

	* src/nm-device.c
	  src/nm-device.h
		- (nm_device_get_dhcp4_config): implement

	* src/nm-manager.c
	  src/nm-manager.h
		- Fetch and track system settings service hostname changes, and proxy
			the changes via a GObject property of the manager

	* system-settings/src/nm-system-config-interface.c
	  system-settings/src/nm-system-config-interface.h
		- Replace nm_system_config_interface_supports_add() with a capabilities
			bitfield

	* system-settings/src/nm-system-config-error.c
	  system-settings/src/nm-system-config-error.h
		- Add additional errors

	* system-settings/src/dbus-settings.c
	  system-settings/src/dbus-settings.h
		- (get_property, nm_sysconfig_settings_class_init): add hostname
			property; first plugin returning a hostname wins
		- (impl_settings_add_connection): use plugin capabilities instead of
			nm_system_config_interface_supports_add()
		- (impl_settings_save_hostname): implement hostname saving

	* src/NetworkManagerPolicy.c
		- (lookup_thread_run_cb, lookup_thread_worker, lookup_thread_new,
		   lookup_thread_die): implement an asynchronous hostname lookup thread
			which given an IPv4 address tries to look up the hostname for that
			address with reverse DNS
		- (get_best_device): split out best device code from
			update_routing_and_dns()
		- (update_etc_hosts): update /etc/hosts with the machine's new hostname
			to preserve the 127.0.0.1 reverse mapping that so many things require
		- (set_system_hostname): set a given hostname
		- (update_system_hostname): implement hostname policy; a configured
			hostname (from the system settings service) is used if available,
			otherwise an automatically determined hostname from DHCP, VPN, etc.
			If there was no automatically determined hostname, reverse DNS of
			the best device's IP address will be used, and as a last resort the
			hostname 'localhost.localdomain' is set.
		- (update_routing_and_dns): use get_best_device(); update the system
			hostname when the network config changes
		- (hostname_changed): update system hostname if the system settings
			service signals a hostname change
		- (nm_policy_new): list for system settings service hostname changes
		- (nm_policy_destroy): ensure that an in-progress hostname lookup thread
			gets told to die

	* system-settings/plugins/keyfile/plugin.c
	  system-settings/plugins/ifcfg-suse/plugin.c
		- (get_property, sc_plugin_ifcfg_class_init): implement hostname and
			capabilities properties

	* system-settings/plugins/ifcfg-fedora/shvar.c
		- (svOpenFile): re-enable R/W access of ifcfg files since the plugin
			writes out /etc/sysconfig/network now

	* system-settings/plugins/ifcfg-fedora/plugin.c
		- (plugin_get_hostname): get hostname from /etc/sysconfig/network
		- (plugin_set_hostname): save hostname to /etc/sysconfig/network
		- (sc_network_changed_cb): handle changes to /etc/sysconfig/network
		- (sc_plugin_ifcfg_init): monitor /etc/sysconfig/network for changes
		- (get_property, set_property, sc_plugin_ifcfg_class_init): implement
			hostname get/set and capabilities get



Modified:
   trunk/ChangeLog
   trunk/introspection/nm-ip4-config.xml
   trunk/introspection/nm-settings-system.xml
   trunk/libnm-glib/nm-dbus-settings-system.c
   trunk/libnm-glib/nm-dbus-settings-system.h
   trunk/src/NetworkManagerPolicy.c
   trunk/src/dhcp-manager/nm-dhcp-manager.c
   trunk/src/nm-device.c
   trunk/src/nm-device.h
   trunk/src/nm-ip4-config.c
   trunk/src/nm-ip4-config.h
   trunk/src/nm-manager.c
   trunk/src/nm-manager.h
   trunk/system-settings/plugins/ifcfg-fedora/plugin.c
   trunk/system-settings/plugins/ifcfg-fedora/shvar.c
   trunk/system-settings/plugins/ifcfg-suse/plugin.c
   trunk/system-settings/plugins/keyfile/plugin.c
   trunk/system-settings/src/dbus-settings.c
   trunk/system-settings/src/dbus-settings.h
   trunk/system-settings/src/nm-system-config-error.c
   trunk/system-settings/src/nm-system-config-error.h
   trunk/system-settings/src/nm-system-config-interface.c
   trunk/system-settings/src/nm-system-config-interface.h

Modified: trunk/introspection/nm-ip4-config.xml
==============================================================================
--- trunk/introspection/nm-ip4-config.xml	(original)
+++ trunk/introspection/nm-ip4-config.xml	Thu Sep 18 15:16:44 2008
@@ -5,9 +5,6 @@
     <property name="Addresses" type="aau" access="read">
       <tp:docstring>Tuples of IPv4 address/prefix/gateway.</tp:docstring>
     </property>
-    <property name="Hostname" type="s" access="read">
-      <tp:docstring>The hostname associated with this IPv4 address. FIXME: what about multiple hostnames?</tp:docstring>
-    </property>
     <property name="Nameservers" type="au" access="read">
       <tp:docstring>The nameservers in use.</tp:docstring>
     </property>

Modified: trunk/introspection/nm-settings-system.xml
==============================================================================
--- trunk/introspection/nm-settings-system.xml	(original)
+++ trunk/introspection/nm-settings-system.xml	Thu Sep 18 15:16:44 2008
@@ -19,6 +19,24 @@
       </arg>
     </method>
 
+    <method name="SaveHostname">
+      <tp:docstring>
+        Save the hostname to persistent configuration.
+      </tp:docstring>
+      <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_save_hostname"/>
+      <arg name="hostname" type="s" direction="in">
+        <tp:docstring>
+          The hostname to save to persistent configuration.  If blank, the persistent hostname is cleared.
+        </tp:docstring>
+      </arg>
+    </method>
+
+    <property name="Hostname" type="s" access="read">
+      <tp:docstring>
+        The machine hostname stored in persistent configuration.
+      </tp:docstring>
+    </property>
+
     <property name="UnmanagedDevices" type="ao" access="read">
       <tp:docstring>
         The list of HAL UDIs of devices that should not be managed by NetworkManager.

Modified: trunk/libnm-glib/nm-dbus-settings-system.c
==============================================================================
--- trunk/libnm-glib/nm-dbus-settings-system.c	(original)
+++ trunk/libnm-glib/nm-dbus-settings-system.c	Thu Sep 18 15:16:44 2008
@@ -16,12 +16,16 @@
 	gboolean got_unmanaged_devices;
 	GSList *unmanaged_devices;
 
+	gboolean got_hostname;
+	char *hostname;
+
 	gboolean disposed;
 } NMDBusSettingsSystemPrivate;
 
 enum {
 	PROP_0,
 	PROP_UNMANAGED_DEVICES,
+	PROP_HOSTNAME,
 
 	LAST_PROP
 };
@@ -114,6 +118,68 @@
 	return priv->unmanaged_devices;
 }
 
+gboolean
+nm_dbus_settings_system_save_hostname (NMDBusSettingsSystem *self,
+                                       const char *hostname,
+                                       GError **err)
+{
+	NMDBusSettingsSystemPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), FALSE);
+
+	priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self);
+
+	return org_freedesktop_NetworkManagerSettings_System_save_hostname (priv->settings_proxy, hostname ? hostname : "", err);
+}
+
+static void
+update_hostname (NMDBusSettingsSystem *self, GValue *value)
+{
+	NMDBusSettingsSystemPrivate *priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self);
+
+	if (priv->hostname) {
+		g_free (priv->hostname);
+		priv->hostname = NULL;
+	}
+
+	if (G_VALUE_TYPE (value) == G_TYPE_STRING) {
+		priv->hostname = g_value_dup_string (value);
+		priv->got_hostname = TRUE;
+	} else
+		g_warning ("%s: Invalid return value type: %s", __func__, G_VALUE_TYPE_NAME (value));
+}
+
+const char *
+nm_dbus_settings_system_get_hostname (NMDBusSettingsSystem *self)
+{
+	NMDBusSettingsSystemPrivate *priv;
+	GValue value = { 0, };
+	GError *err = NULL;
+
+	g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), NULL);
+
+	priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self);
+
+	if (priv->got_hostname)
+		return priv->hostname;
+
+	if (!dbus_g_proxy_call (priv->props_proxy, "Get", &err,
+					    G_TYPE_STRING, NM_DBUS_SERVICE_SYSTEM_SETTINGS,
+					    G_TYPE_STRING, "Hostname",
+					    G_TYPE_INVALID,
+					    G_TYPE_VALUE, &value,
+					    G_TYPE_INVALID)) {
+		g_warning ("Could not retrieve hostname: %s", err->message);
+		g_error_free (err);
+		return NULL;
+	}
+
+	update_hostname (self, &value);
+	g_value_unset (&value);
+
+	return priv->hostname;
+}
+
 static void
 proxy_properties_changed (DBusGProxy *proxy,
                           GHashTable *properties,
@@ -127,6 +193,12 @@
 		update_unmanaged_devices (self, value);
 		g_object_notify (G_OBJECT (self), NM_DBUS_SETTINGS_SYSTEM_UNMANAGED_DEVICES);
 	}
+
+	value = (GValue *) g_hash_table_lookup (properties, "Hostname");
+	if (value) {
+		update_hostname (self, value);
+		g_object_notify (G_OBJECT (self), NM_DBUS_SETTINGS_SYSTEM_HOSTNAME);
+	}
 }
 
 static void
@@ -184,6 +256,8 @@
 
 	priv->disposed = TRUE;
 
+	g_free (priv->hostname);
+
 	if (priv->unmanaged_devices) {
 		g_slist_foreach (priv->unmanaged_devices, (GFunc) g_free, NULL);
 		g_slist_free (priv->unmanaged_devices);
@@ -205,6 +279,9 @@
 	case PROP_UNMANAGED_DEVICES:
 		g_value_set_pointer (value, nm_dbus_settings_system_get_unmanaged_devices (self));
 		break;
+	case PROP_HOSTNAME:
+		g_value_set_string (value, nm_dbus_settings_system_get_hostname (self));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -230,4 +307,13 @@
 						   "Unmanaged devices",
 						   "Unmanaged devices",
 						   G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_HOSTNAME,
+		 g_param_spec_string (NM_DBUS_SETTINGS_SYSTEM_HOSTNAME,
+						   "Hostname",
+						   "Configured hostname",
+						   NULL,
+						   G_PARAM_READABLE));
 }
+

Modified: trunk/libnm-glib/nm-dbus-settings-system.h
==============================================================================
--- trunk/libnm-glib/nm-dbus-settings-system.h	(original)
+++ trunk/libnm-glib/nm-dbus-settings-system.h	Thu Sep 18 15:16:44 2008
@@ -15,6 +15,7 @@
 #define NM_DBUS_SETTINGS_SYSTEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DBUS_SETTINGS_SYSTEM, NMDBusSettingsSystemClass))
 
 #define NM_DBUS_SETTINGS_SYSTEM_UNMANAGED_DEVICES "unmanaged-devices"
+#define NM_DBUS_SETTINGS_SYSTEM_HOSTNAME "hostname"
 
 typedef struct {
 	NMDBusSettings parent;
@@ -34,6 +35,11 @@
 
 GSList *nm_dbus_settings_system_get_unmanaged_devices (NMDBusSettingsSystem *self);
 
+const char *nm_dbus_settings_system_get_hostname (NMDBusSettingsSystem *self);
+
+gboolean nm_dbus_settings_system_save_hostname (NMDBusSettingsSystem *self,
+                                                const char *hostname,
+                                                GError **err);
 
 G_END_DECLS
 

Modified: trunk/src/NetworkManagerPolicy.c
==============================================================================
--- trunk/src/NetworkManagerPolicy.c	(original)
+++ trunk/src/NetworkManagerPolicy.c	Thu Sep 18 15:16:44 2008
@@ -17,10 +17,14 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2005 Red Hat, Inc.
+ * (C) Copyright 2005 - 2008 Red Hat, Inc.
  */
 
 #include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <ctype.h>
 
 #include "NetworkManagerPolicy.h"
 #include "NetworkManagerUtils.h"
@@ -40,6 +44,25 @@
 #include "NetworkManagerSystem.h"
 #include "nm-named-manager.h"
 
+typedef struct LookupThread LookupThread;
+
+typedef void (*LookupCallback) (LookupThread *thread, gpointer user_data);
+
+struct LookupThread {
+	GThread *thread;
+
+	GMutex *lock;
+	gboolean die;
+	int ret;
+
+	guint32 ip4_addr;
+	char hostname[NI_MAXHOST + 1];
+
+	guint done_id;
+	LookupCallback callback;
+	gpointer user_data;
+};
+
 struct NMPolicy {
 	NMManager *manager;
 	guint update_state_id;
@@ -48,8 +71,92 @@
 	GSList *dev_signal_ids;
 
 	NMDevice *default_device;
+
+	LookupThread *lookup;
 };
 
+static gboolean
+lookup_thread_run_cb (gpointer user_data)
+{
+	LookupThread *thread = (LookupThread *) user_data;
+
+	(*thread->callback) (thread, thread->user_data);
+	return FALSE;
+}
+
+static gpointer
+lookup_thread_worker (gpointer data)
+{
+	LookupThread *thread = (LookupThread *) data;
+	struct sockaddr_in addr;
+
+	g_mutex_lock (thread->lock);
+	if (thread->die) {
+		g_mutex_unlock (thread->lock);
+		return (gpointer) NULL;
+	}
+	g_mutex_unlock (thread->lock);
+
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = thread->ip4_addr;
+
+	thread->ret = getnameinfo ((struct sockaddr *) &addr, sizeof (struct sockaddr_in),
+	                           thread->hostname, NI_MAXHOST, NULL, 0,
+	                           NI_NAMEREQD);
+	if (thread->ret == 0) {
+		int i;
+
+		for (i = 0; i < strlen (thread->hostname); i++)
+			thread->hostname[i] = tolower (thread->hostname[i]);
+	}
+
+	thread->done_id = g_idle_add (lookup_thread_run_cb, thread);
+	return (gpointer) TRUE;
+}
+
+static void
+lookup_thread_free (LookupThread *thread)
+{
+	g_return_if_fail (thread != NULL);
+
+	g_mutex_free (thread->lock);
+	memset (thread, 0, sizeof (LookupThread));
+	g_free (thread);
+}
+
+static LookupThread *
+lookup_thread_new (guint32 ip4_addr, LookupCallback callback, gpointer user_data)
+{
+	LookupThread *thread;
+
+	thread = g_malloc0 (sizeof (LookupThread));
+	if (!thread)
+		return NULL;
+
+	thread->lock = g_mutex_new ();
+	thread->callback = callback;
+	thread->user_data = user_data;
+	thread->ip4_addr = ip4_addr;
+
+	thread->thread = g_thread_create (lookup_thread_worker, thread, FALSE, NULL);
+	if (!thread->thread) {
+		lookup_thread_free (thread);
+		return NULL;
+	}
+
+	return thread;
+}
+
+static void
+lookup_thread_die (LookupThread *thread)
+{
+	g_return_if_fail (thread != NULL);
+
+	g_mutex_lock (thread->lock);
+	thread->die = TRUE;
+	g_mutex_unlock (thread->lock);
+}
+
 #define INVALID_TAG "invalid"
 
 static const char *
@@ -65,28 +172,6 @@
 	return s_con->id;
 }
 
-static void
-update_default_route (NMPolicy *policy, NMDevice *new)
-{
-	const char *ip_iface;
-
-	/* FIXME: Not sure if the following makes any sense. */
-	/* If iface and ip_iface are the same, it's a regular network device and we
-	   treat it as such. However, if they differ, it's most likely something like
-	   a serial device with ppp interface, so route all the traffic to it. */
-	ip_iface = nm_device_get_ip_iface (new);
-	if (strcmp (ip_iface, nm_device_get_iface (new))) {
-		nm_system_device_replace_default_ip4_route (ip_iface, 0, 0);
-	} else {
-		NMIP4Config *config;
-		const NMSettingIP4Address *def_addr;
-
-		config = nm_device_get_ip4_config (new);
-		def_addr = nm_ip4_config_get_address (config, 0);
-		nm_system_device_replace_default_ip4_route (ip_iface, def_addr->gateway, nm_ip4_config_get_mss (config));
-	}
-}
-
 static guint32
 get_device_priority (NMDevice *dev)
 {
@@ -105,16 +190,19 @@
 	return 1;
 }
 
-static void
-update_routing_and_dns (NMPolicy *policy, gboolean force_update)
+static NMDevice *
+get_best_device (NMManager *manager, NMActRequest **out_req)
 {
+	GSList *devices, *iter;
 	NMDevice *best = NULL;
 	guint32 best_prio = 0;
-	NMActRequest *best_req = NULL;
-	GSList *devices, *iter;
-	NMNamedManager *named_mgr;
 
-	devices = nm_manager_get_devices (policy->manager);
+	g_return_val_if_fail (manager != NULL, NULL);
+	g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
+	g_return_val_if_fail (out_req != NULL, NULL);
+	g_return_val_if_fail (*out_req == NULL, NULL);
+
+	devices = nm_manager_get_devices (manager);
 	for (iter = devices; iter; iter = g_slist_next (iter)) {
 		NMDevice *dev = NM_DEVICE (iter->data);
 		NMActRequest *req;
@@ -161,10 +249,259 @@
 		if (prio > best_prio) {
 			best = dev;
 			best_prio = prio;
-			best_req = req;
+			*out_req = req;
+		}
+	}
+
+	return best;
+}
+
+#define FALLBACK_HOSTNAME "localhost.localdomain"
+
+static gboolean
+update_etc_hosts (const char *hostname)
+{
+	char *contents = NULL;
+	char **lines = NULL, **line;
+	GError *error = NULL;
+	gboolean initial_comments = TRUE;
+	gboolean added = FALSE;
+	gsize contents_len = 0;
+	GString *new_contents;
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (hostname != NULL, FALSE);
+
+	if (!g_file_get_contents (SYSCONFDIR "/hosts", &contents, &contents_len, &error)) {
+		nm_warning ("%s: couldn't read " SYSCONFDIR "/hosts: (%d) %s",
+		            __func__, error ? error->code : 0,
+		            (error && error->message) ? error->message : "(unknown)");
+	} else {
+		lines = g_strsplit_set (contents, "\n\r", 0);
+		g_free (contents);
+	}
+
+	new_contents = g_string_sized_new (contents_len ? contents_len + 100 : 200);
+	if (!new_contents) {
+		nm_warning ("%s: not enough memory to update " SYSCONFDIR "/hosts", __func__);
+		return FALSE;
+	}
+
+	/* Replace any 127.0.0.1 entry that is at the beginning of the file or right
+	 * after initial comments.  If there is no 127.0.0.1 entry at the beginning
+	 * or after initial comments, add one there and ignore any other 127.0.0.1
+	 * entries.
+	 */
+	for (line = lines; lines && *line; line++) {
+		gboolean add_line = TRUE;
+
+		/* This is the first line after the initial comments */
+		if (initial_comments && (*line[0] != '#')) {
+			initial_comments = FALSE;
+			g_string_append_printf (new_contents, "127.0.0.1\t%s", hostname);
+			if (strcmp (hostname, FALLBACK_HOSTNAME))
+				g_string_append_printf (new_contents, "\t" FALLBACK_HOSTNAME);
+			g_string_append (new_contents, "\tlocalhost\n");
+			added = TRUE;
+
+			/* Don't add the entry if it's supposed to be the actual localhost reverse mapping */
+			if (!strncmp (*line, "127.0.0.1", strlen ("127.0.0.1")) && strstr (*line, "localhost"))
+				add_line = FALSE;
+		}
+
+		if (add_line) {
+			g_string_append (new_contents, *line);
+			g_string_append_c (new_contents, '\n');
+		}
+	}
+
+	/* Hmm, /etc/hosts was empty for some reason */
+	if (!added) {
+		g_string_append (new_contents, "# Do not remove the following line, or various programs");
+		g_string_append (new_contents, "# that require network functionality will fail.");
+		g_string_append (new_contents, "127.0.0.1\t" FALLBACK_HOSTNAME "\tlocalhost");
+	}
+
+	if (!g_file_set_contents (SYSCONFDIR "/hosts", new_contents->str, -1, &error)) {
+		nm_warning ("%s: couldn't update " SYSCONFDIR "/hosts: (%d) %s",
+		            __func__, error ? error->code : 0,
+		            (error && error->message) ? error->message : "(unknown)");
+	} else
+		success = TRUE;
+
+	g_string_free (new_contents, TRUE);
+	return success;
+}
+
+static void
+set_system_hostname (const char *new_hostname, const char *msg)
+{
+	char old_hostname[HOST_NAME_MAX + 1];
+	int ret = 0;
+	const char *name = new_hostname ? new_hostname : FALLBACK_HOSTNAME;
+
+	old_hostname[HOST_NAME_MAX] = '\0';
+	errno = 0;
+	ret = gethostname (old_hostname, HOST_NAME_MAX);
+	if (ret != 0) {
+		nm_warning ("%s: couldn't get the system hostname: (%d) %s",
+		            __func__, errno, strerror (errno));
+	} else {
+		/* Do nothing if the hostname isn't actually changing */
+		if (   (new_hostname && !strcmp (old_hostname, new_hostname))
+		    || (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME)))
+			return;
+	}
+
+	nm_info ("Setting system hostname to '%s' (%s)", name, msg);
+
+	ret = sethostname (name, strlen (name));
+	if (ret == 0) {
+		if (!update_etc_hosts (name)) {
+			/* error updating /etc/hosts; fallback to localhost.localdomain */
+			nm_info ("Setting system hostname to '" FALLBACK_HOSTNAME "' (error updating /etc/hosts)");
+			sethostname (FALLBACK_HOSTNAME, strlen (FALLBACK_HOSTNAME));
+		}
+	} else {
+		nm_warning ("%s: couldn't set the system hostname to '%s': (%d) %s",
+		            __func__, name, errno, strerror (errno));
+	}
+}
+
+static void
+lookup_callback (LookupThread *thread, gpointer user_data)
+{
+	NMPolicy *policy = (NMPolicy *) user_data;
+
+	/* If the thread was told to die or it's not the current in-progress
+	 * hostname lookup, nothing to do.
+	 */
+	if (thread->die || (thread != policy->lookup))
+		goto done;
+
+	policy->lookup = NULL;
+	if (!strlen (thread->hostname)) {
+		char *msg;
+
+		/* No valid IP4 config (!!); fall back to localhost.localdomain */
+		msg = g_strdup_printf ("address lookup failed: %d", thread->ret);
+		set_system_hostname (NULL, msg);
+		g_free (msg);
+	} else
+		set_system_hostname (thread->hostname, "from address lookup");
+
+done:
+	lookup_thread_free (thread);
+}
+
+static void
+update_system_hostname (NMPolicy *policy, NMDevice *best)
+{
+	char *configured_hostname = NULL;
+	NMActRequest *best_req = NULL;
+	NMDHCP4Config *dhcp4_config;
+	NMIP4Config *ip4_config;
+	const NMSettingIP4Address *addr;
+
+	g_return_if_fail (policy != NULL);
+
+	if (policy->lookup) {
+		lookup_thread_die (policy->lookup);
+		policy->lookup = NULL;
+	}
+
+	/* A configured hostname (via the system-settings service) overrides
+	 * all automatic hostname determination.  If there is no configured hostname,
+	 * the best device's automatically determined hostname (from DHCP, VPN, PPP,
+	 * etc) is used.  If there is no automatically determined hostname, reverse
+	 * DNS lookup using the best device's IP address is started to determined the
+	 * the hostname.
+	 */
+
+	/* Try a configured hostname first */
+	g_object_get (G_OBJECT (policy->manager), NM_MANAGER_HOSTNAME, &configured_hostname, NULL);
+	if (configured_hostname) {
+		set_system_hostname (configured_hostname, "from system configuration");
+		g_free (configured_hostname);
+		return;
+	}
+
+	/* Try automatically determined hostname from the best device's IP config */
+	if (!best)
+		best = get_best_device (policy->manager, &best_req);
+
+	if (!best) {
+		/* No best device; fall back to localhost.localdomain */
+		set_system_hostname (NULL, "no default device");
+		return;
+	}
+
+	/* Grab a hostname out of the device's DHCP4 config */
+	dhcp4_config = nm_device_get_dhcp4_config (best);
+	if (dhcp4_config) {
+		const char *dhcp4_hostname;
+
+		dhcp4_hostname = nm_dhcp4_config_get_option (dhcp4_config, "host_name");
+		if (dhcp4_hostname && strlen (dhcp4_hostname)) {
+			set_system_hostname (dhcp4_hostname, "from DHCP");
+			return;
 		}
 	}
 
+	/* No configured hostname, no automatically determined hostname either. Start
+	 * reverse DNS of the current IP address to try and find it.
+	 */
+	ip4_config = nm_device_get_ip4_config (best);
+	if (   !ip4_config
+	    || (nm_ip4_config_get_num_nameservers (ip4_config) == 0)
+	    || (nm_ip4_config_get_num_addresses (ip4_config) == 0)) {
+		/* No valid IP4 config (!!); fall back to localhost.localdomain */
+		set_system_hostname (NULL, "no IPv4 config");
+		return;
+	}
+
+	addr = nm_ip4_config_get_address (ip4_config, 0);
+	g_assert (addr); /* checked for > 1 address above */
+
+	/* Start the hostname lookup thread */
+	policy->lookup = lookup_thread_new (addr->address, lookup_callback, policy);
+	if (!policy->lookup) {
+		/* Fall back to 'localhost.localdomain' */
+		set_system_hostname (NULL, "error starting hostname thread");
+	}
+}
+
+static void
+update_default_route (NMPolicy *policy, NMDevice *new)
+{
+	const char *ip_iface;
+
+	/* FIXME: Not sure if the following makes any sense. */
+	/* If iface and ip_iface are the same, it's a regular network device and we
+	   treat it as such. However, if they differ, it's most likely something like
+	   a serial device with ppp interface, so route all the traffic to it. */
+	ip_iface = nm_device_get_ip_iface (new);
+	if (strcmp (ip_iface, nm_device_get_iface (new))) {
+		nm_system_device_replace_default_ip4_route (ip_iface, 0, 0);
+	} else {
+		NMIP4Config *config;
+		const NMSettingIP4Address *def_addr;
+
+		config = nm_device_get_ip4_config (new);
+		def_addr = nm_ip4_config_get_address (config, 0);
+		nm_system_device_replace_default_ip4_route (ip_iface, def_addr->gateway, nm_ip4_config_get_mss (config));
+	}
+}
+
+static void
+update_routing_and_dns (NMPolicy *policy, gboolean force_update)
+{
+	NMDevice *best = NULL;
+	NMActRequest *best_req = NULL;
+	NMNamedManager *named_mgr;
+	GSList *devices = NULL, *iter;
+
+	best = get_best_device (policy->manager, &best_req);
 	if (!best)
 		goto out;
 	if (!force_update && (best == policy->default_device))
@@ -177,6 +514,7 @@
 	 * first.  The order is important, we don't want two connections marked
 	 * default at the same time ever.
 	 */
+	devices = nm_manager_get_devices (policy->manager);
 	for (iter = devices; iter; iter = g_slist_next (iter)) {
 		NMDevice *dev = NM_DEVICE (iter->data);
 		NMActRequest *req;
@@ -203,6 +541,9 @@
 	         nm_device_get_iface (best));
 
 out:
+	/* Update the system hostname */
+	update_system_hostname (policy, best);
+
 	policy->default_device = best;	
 }
 
@@ -292,6 +633,12 @@
 }
 
 static void
+hostname_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
+{
+	update_system_hostname ((NMPolicy *) user_data, NULL);
+}
+
+static void
 schedule_activate_check (NMPolicy *policy, NMDevice *device)
 {
 	ActivateData *data;
@@ -547,6 +894,10 @@
 	                       G_CALLBACK (global_state_changed), policy);
 	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
 
+	id = g_signal_connect (manager, "notify::hostname",
+	                       G_CALLBACK (hostname_changed), policy);
+	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
+
 	id = g_signal_connect (manager, "device-added",
 	                       G_CALLBACK (device_added), policy);
 	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
@@ -585,6 +936,14 @@
 
 	g_return_if_fail (policy != NULL);
 
+	/* Tell any existing hostname lookup thread to die, it'll get cleaned up
+	 * by the lookup thread callback.
+	  */
+	if (policy->lookup) {
+		lookup_thread_die (policy->lookup);
+		policy->lookup = NULL;
+	}
+
 	for (iter = policy->pending_activation_checks; iter; iter = g_slist_next (iter)) {
 		ActivateData *data = (ActivateData *) iter->data;
 

Modified: trunk/src/dhcp-manager/nm-dhcp-manager.c
==============================================================================
--- trunk/src/dhcp-manager/nm-dhcp-manager.c	(original)
+++ trunk/src/dhcp-manager/nm-dhcp-manager.c	Thu Sep 18 15:16:44 2008
@@ -793,10 +793,8 @@
 	addr = NULL;
 
 	str = g_hash_table_lookup (device->options, "new_host_name");
-	if (str) {
-		nm_ip4_config_set_hostname (ip4_config, str);
+	if (str)
 		nm_info ("  hostname '%s'", str);
-	}
 
 	str = g_hash_table_lookup (device->options, "new_domain_name_servers");
 	if (str) {

Modified: trunk/src/nm-device.c
==============================================================================
--- trunk/src/nm-device.c	(original)
+++ trunk/src/nm-device.c	Thu Sep 18 15:16:44 2008
@@ -1853,6 +1853,19 @@
 	}
 }
 
+NMDHCP4Config *
+nm_device_get_dhcp4_config (NMDevice *self)
+{
+	NMDevicePrivate *priv;
+
+	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
+
+	priv = NM_DEVICE_GET_PRIVATE (self);
+
+	if (priv->dhcp_manager)
+		return priv->dhcp4_config;
+	return NULL;
+}
 
 NMIP4Config *
 nm_device_get_ip4_config (NMDevice *self)

Modified: trunk/src/nm-device.h
==============================================================================
--- trunk/src/nm-device.h	(original)
+++ trunk/src/nm-device.h	Thu Sep 18 15:16:44 2008
@@ -29,6 +29,7 @@
 #include "NetworkManager.h"
 #include "nm-activation-request.h"
 #include "nm-ip4-config.h"
+#include "nm-dhcp4-config.h"
 #include "nm-connection.h"
 
 typedef enum NMActStageReturn
@@ -133,6 +134,7 @@
 gboolean		nm_device_get_use_dhcp	(NMDevice *dev);
 void			nm_device_set_use_dhcp	(NMDevice *dev,
 								 gboolean use_dhcp);
+NMDHCP4Config * nm_device_get_dhcp4_config (NMDevice *dev);
 
 NMIP4Config *	nm_device_get_ip4_config	(NMDevice *dev);
 gboolean		nm_device_set_ip4_config	(NMDevice *dev,

Modified: trunk/src/nm-ip4-config.c
==============================================================================
--- trunk/src/nm-ip4-config.c	(original)
+++ trunk/src/nm-ip4-config.c	Thu Sep 18 15:16:44 2008
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 
 /* NetworkManager -- Network link manager
  *
@@ -18,7 +18,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2005 Red Hat, Inc.
+ * (C) Copyright 2005 - 2008 Red Hat, Inc.
  */
 
 
@@ -57,7 +57,6 @@
 	GPtrArray *domains;
 	GPtrArray *searches;
 
-	gchar *hostname;
 	GSList *routes;
 } NMIP4ConfigPrivate;
 
@@ -65,7 +64,6 @@
 enum {
 	PROP_0,
 	PROP_ADDRESSES,
-	PROP_HOSTNAME,
 	PROP_NAMESERVERS,
 	PROP_DOMAINS,
 	PROP_ROUTES,
@@ -223,24 +221,6 @@
 		g_array_remove_range (priv->nameservers, 0, priv->nameservers->len);
 }
 
-void nm_ip4_config_set_hostname (NMIP4Config *config, const char *hostname)
-{
-	g_return_if_fail (NM_IS_IP4_CONFIG (config));
-	g_return_if_fail (hostname != NULL);
-
-	if (!strlen (hostname))
-		return;
-
-	NM_IP4_CONFIG_GET_PRIVATE (config)->hostname = g_strdup (hostname);
-}
-
-const char *nm_ip4_config_get_hostname (NMIP4Config *config)
-{
-	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
-
-	return NM_IP4_CONFIG_GET_PRIVATE (config)->hostname;
-}
-
 void
 nm_ip4_config_take_route (NMIP4Config *config,
 						   NMSettingIP4Route *route)
@@ -510,7 +490,6 @@
 	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
 
 	nm_utils_slist_free (priv->addresses, g_free);
-	g_free (priv->hostname);
 	g_array_free (priv->nameservers, TRUE);
 	g_ptr_array_free (priv->domains, TRUE);
 	g_ptr_array_free (priv->searches, TRUE);
@@ -527,9 +506,6 @@
 	case PROP_ADDRESSES:
 		nm_utils_ip4_addresses_to_gvalue (priv->addresses, value);
 		break;
-	case PROP_HOSTNAME:
-		g_value_set_string (value, priv->hostname);
-		break;
 	case PROP_NAMESERVERS:
 		g_value_set_boxed (value, priv->nameservers);
 		break;
@@ -565,13 +541,6 @@
 							DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
 							G_PARAM_READABLE));
 	g_object_class_install_property
-		(object_class, PROP_HOSTNAME,
-		 g_param_spec_string (NM_IP4_CONFIG_HOSTNAME,
-							  "Hostname",
-							  "Hostname",
-							  NULL,
-							  G_PARAM_READABLE));
-	g_object_class_install_property
 		(object_class, PROP_NAMESERVERS,
 		 g_param_spec_boxed (NM_IP4_CONFIG_NAMESERVERS,
 							 "Nameservers",

Modified: trunk/src/nm-ip4-config.h
==============================================================================
--- trunk/src/nm-ip4-config.h	(original)
+++ trunk/src/nm-ip4-config.h	Thu Sep 18 15:16:44 2008
@@ -18,7 +18,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2004 Red Hat, Inc.
+ * (C) Copyright 2004 - 2008 Red Hat, Inc.
  */
 
 #ifndef NM_IP4_CONFIG_H
@@ -45,11 +45,8 @@
 } NMIP4ConfigClass;
 
 #define NM_IP4_CONFIG_ADDRESSES "addresses"
-#define NM_IP4_CONFIG_HOSTNAME "hostname"
 #define NM_IP4_CONFIG_NAMESERVERS "nameservers"
 #define NM_IP4_CONFIG_DOMAINS "domains"
-#define NM_IP4_CONFIG_NIS_DOMAIN "nis-domain"
-#define NM_IP4_CONFIG_NIS_SERVERS "nis-servers"
 #define NM_IP4_CONFIG_ROUTES "routes"
 
 GType nm_ip4_config_get_type (void);
@@ -80,9 +77,6 @@
 guint32		nm_ip4_config_get_num_routes		(NMIP4Config *config);
 void            nm_ip4_config_reset_routes		(NMIP4Config *config);
 
-void			nm_ip4_config_set_hostname		(NMIP4Config *config, const char *hostname);
-const char * 	nm_ip4_config_get_hostname		(NMIP4Config *config);
-
 void			nm_ip4_config_add_domain			(NMIP4Config *config, const char *domain);
 const char *	nm_ip4_config_get_domain			(NMIP4Config *config, guint i);
 guint32		nm_ip4_config_get_num_domains		(NMIP4Config *config);

Modified: trunk/src/nm-manager.c
==============================================================================
--- trunk/src/nm-manager.c	(original)
+++ trunk/src/nm-manager.c	Thu Sep 18 15:16:44 2008
@@ -70,6 +70,10 @@
 static void hal_manager_hal_reappeared_cb (NMHalManager *hal_mgr,
                                            gpointer user_data);
 
+static void system_settings_properties_changed_cb (DBusGProxy *proxy,
+                                                   GHashTable *properties,
+                                                   gpointer user_data);
+
 #define SSD_POKE_INTERVAL 120000
 
 typedef struct {
@@ -95,6 +99,7 @@
 	DBusGProxy *system_proxy;
 	DBusGProxy *system_props_proxy;
 	GSList *unmanaged_udis;
+	char *hostname;
 
 	PendingConnectionInfo *pending_connection_info;
 	gboolean wireless_enabled;
@@ -139,6 +144,9 @@
 	PROP_WIRELESS_HARDWARE_ENABLED,
 	PROP_ACTIVE_CONNECTIONS,
 
+	/* Not exported */
+	PROP_HOSTNAME,
+
 	LAST_PROP
 };
 
@@ -280,6 +288,8 @@
 	priv->vpn_manager_id = id;
 
 	g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr);
+
+	/* avahi-autoipd stuff */
 	priv->aipd_proxy = dbus_g_proxy_new_for_name (g_connection,
 	                                              NM_AUTOIP_DBUS_SERVICE,
 	                                              "/",
@@ -300,7 +310,24 @@
 									 manager,
 									 NULL);
 	} else
-		nm_warning ("Could not initialize avahi-autoipd D-Bus proxy");
+		nm_warning ("%s: could not initialize avahi-autoipd D-Bus proxy", __func__);
+
+	/* System settings stuff */
+	priv->system_props_proxy = dbus_g_proxy_new_for_name (g_connection,
+	                                                      NM_DBUS_SERVICE_SYSTEM_SETTINGS,
+	                                                      NM_DBUS_PATH_SETTINGS,
+	                                                      "org.freedesktop.NetworkManagerSettings.System");
+	if (priv->system_props_proxy) {
+		dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED,
+									G_TYPE_NONE, G_TYPE_VALUE, G_TYPE_INVALID);
+		dbus_g_proxy_add_signal (priv->system_props_proxy, "PropertiesChanged",
+		                         DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID);
+		dbus_g_proxy_connect_signal (priv->system_props_proxy, "PropertiesChanged",
+		                             G_CALLBACK (system_settings_properties_changed_cb),
+		                             manager,
+		                             NULL);
+	} else
+		nm_warning ("%s: could not initialize system settings properties D-Bus proxy", __func__);
 }
 
 NMState
@@ -434,6 +461,8 @@
 	g_hash_table_destroy (priv->system_connections);
 	priv->system_connections = NULL;
 
+	g_free (priv->hostname);
+
 	if (priv->system_props_proxy) {
 		g_object_unref (priv->system_props_proxy);
 		priv->system_props_proxy = NULL;
@@ -526,6 +555,9 @@
 	case PROP_ACTIVE_CONNECTIONS:
 		g_value_take_boxed (value, get_active_connections (self, NULL));
 		break;
+	case PROP_HOSTNAME:
+		g_value_set_string (value, priv->hostname);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -579,6 +611,15 @@
 							  DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
 							  G_PARAM_READABLE));
 
+	/* Hostname is not exported over D-Bus */
+	g_object_class_install_property
+		(object_class, PROP_HOSTNAME,
+		 g_param_spec_string (NM_MANAGER_HOSTNAME,
+							  "Hostname",
+							  "Hostname",
+							  NULL,
+							  G_PARAM_READABLE | NM_PROPERTY_PARAM_NO_EXPORT));
+
 	/* signals */
 	signals[DEVICE_ADDED] =
 		g_signal_new ("device-added",
@@ -1128,6 +1169,22 @@
 }
 
 static void
+handle_hostname (NMManager *manager, const char *hostname)
+{
+	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
+
+	if (!hostname && !priv->hostname)
+		return;
+
+	if (hostname && priv->hostname && !strcmp (hostname, priv->hostname))
+		return;
+
+	g_free (priv->hostname);
+	priv->hostname = (hostname && strlen (hostname)) ? g_strdup (hostname) : NULL;
+	g_object_notify (G_OBJECT (manager), NM_MANAGER_HOSTNAME);
+}
+
+static void
 system_settings_properties_changed_cb (DBusGProxy *proxy,
                                        GHashTable *properties,
                                        gpointer user_data)
@@ -1136,10 +1193,12 @@
 	GValue *value;
 
 	value = g_hash_table_lookup (properties, "UnmanagedDevices");
-	if (!value || !G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH))
-		return;
+	if (value && G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH))
+		handle_unmanaged_devices (manager, g_value_get_boxed (value));
 
-	handle_unmanaged_devices (manager, g_value_get_boxed (value));
+	value = g_hash_table_lookup (properties, "Hostname");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING))
+		handle_hostname (manager, g_value_get_string (value));
 }
 
 static void
@@ -1158,6 +1217,7 @@
 		            "settings service: (%d) %s",
 		            __func__, error->code, error->message);
 		g_error_free (error);
+		g_object_unref (proxy);
 		return;
 	}
 
@@ -1165,37 +1225,45 @@
 		handle_unmanaged_devices (manager, g_value_get_boxed (&value));
 
 	g_value_unset (&value);
+	g_object_unref (proxy);
+}
+
+static void
+system_settings_get_hostname_cb (DBusGProxy *proxy,
+                                 DBusGProxyCall *call_id,
+                                 gpointer user_data)
+{
+	NMManager *manager = NM_MANAGER (user_data);
+	GError *error = NULL;
+	GValue value = { 0, };
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &error,
+	                            G_TYPE_VALUE, &value,
+	                            G_TYPE_INVALID)) {
+		nm_warning ("%s: Error getting hostname from the system settings service: (%d) %s",
+		            __func__, error->code, error->message);
+		g_error_free (error);
+		g_object_unref (proxy);
+		return;
+	}
 
+	if (G_VALUE_HOLDS (&value, G_TYPE_STRING))
+		handle_hostname (manager, g_value_get_string (&value));
+
+	g_value_unset (&value);
 	g_object_unref (proxy);
 }
 
 static void
-query_unmanaged_devices (NMManager *manager)
+query_system_settings_property (NMManager *manager,
+                                const char *property,
+                                DBusGProxyCallNotify callback)
 {
 	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
 	DBusGConnection *g_connection;
 	DBusGProxy *get_proxy;
 
 	g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr);
-	if (!priv->system_props_proxy) {
-		priv->system_props_proxy = dbus_g_proxy_new_for_name (g_connection,
-		                                                      NM_DBUS_SERVICE_SYSTEM_SETTINGS,
-		                                                      NM_DBUS_PATH_SETTINGS,
-		                                                      "org.freedesktop.NetworkManagerSettings.System");
-		if (!priv->system_props_proxy) {
-			nm_warning ("Error: could not init system settings properties proxy.");
-			return;
-		}
-
-		dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED,
-									G_TYPE_NONE, G_TYPE_VALUE, G_TYPE_INVALID);
-		dbus_g_proxy_add_signal (priv->system_props_proxy, "PropertiesChanged",
-		                         DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID);
-		dbus_g_proxy_connect_signal (priv->system_props_proxy, "PropertiesChanged",
-		                             G_CALLBACK (system_settings_properties_changed_cb),
-		                             manager,
-		                             NULL);
-	}
 
 	/* Get unmanaged devices */
 	get_proxy = dbus_g_proxy_new_for_name (g_connection,
@@ -1203,12 +1271,9 @@
 		                                   NM_DBUS_PATH_SETTINGS,
 		                                   "org.freedesktop.DBus.Properties");
 
-	dbus_g_proxy_begin_call (get_proxy, "Get",
-	                         system_settings_get_unmanaged_devices_cb,
-	                         manager,
-	                         NULL,
-	                         G_TYPE_STRING, "org.freedesktop.NetworkManagerSettings.System",
-	                         G_TYPE_STRING, "UnmanagedDevices",
+	dbus_g_proxy_begin_call (get_proxy, "Get", callback, manager, NULL,
+	                         G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS_SYSTEM,
+	                         G_TYPE_STRING, property,
 	                         G_TYPE_INVALID);
 }
 
@@ -1240,7 +1305,8 @@
 			}
 
 			/* System Settings service appeared, update stuff */
-			query_unmanaged_devices (manager);
+			query_system_settings_property (manager, "UnmanagedDevices", system_settings_get_unmanaged_devices_cb);
+			query_system_settings_property (manager, "Hostname", system_settings_get_hostname_cb);
 			query_connections (manager, NM_CONNECTION_SCOPE_SYSTEM);
 		} else {
 			/* System Settings service disappeared, throw them away (?) */
@@ -1299,7 +1365,8 @@
 
 	if (nm_dbus_manager_name_has_owner (nm_dbus_manager_get (),
 	                                    NM_DBUS_SERVICE_SYSTEM_SETTINGS)) {
-		query_unmanaged_devices (manager);
+		query_system_settings_property (manager, "UnmanagedDevices", system_settings_get_unmanaged_devices_cb);
+		query_system_settings_property (manager, "Hostname", system_settings_get_hostname_cb);
 		query_connections (manager, NM_CONNECTION_SCOPE_SYSTEM);
 	} else {
 		/* Try to activate the system settings daemon */

Modified: trunk/src/nm-manager.h
==============================================================================
--- trunk/src/nm-manager.h	(original)
+++ trunk/src/nm-manager.h	Thu Sep 18 15:16:44 2008
@@ -19,6 +19,9 @@
 #define NM_MANAGER_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled"
 #define NM_MANAGER_ACTIVE_CONNECTIONS "active-connections"
 
+/* Not exported */
+#define NM_MANAGER_HOSTNAME "hostname"
+
 #define NM_MANAGER_CONNECTION_PROXY_TAG "dbus-proxy"
 #define NM_MANAGER_CONNECTION_SECRETS_PROXY_TAG "dbus-secrets-proxy"
 

Modified: trunk/system-settings/plugins/ifcfg-fedora/plugin.c
==============================================================================
--- trunk/system-settings/plugins/ifcfg-fedora/plugin.c	(original)
+++ trunk/system-settings/plugins/ifcfg-fedora/plugin.c	Thu Sep 18 15:16:44 2008
@@ -1,5 +1,6 @@
 /* NetworkManager system settings service
  *
+ * Dan Williams <dcbw redhat com>
  * SÃren Sandmann <sandmann daimi au dk>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -44,6 +45,8 @@
 #include "plugin.h"
 #include "nm-system-config-interface.h"
 #include "nm-ifcfg-connection.h"
+#include "nm-inotify-helper.h"
+#include "shvar.h"
 
 #define IFCFG_DIR SYSCONFDIR"/sysconfig/network-scripts/"
 
@@ -74,6 +77,10 @@
 
 	GHashTable *connections;
 
+	gulong ih_event_id;
+	int sc_network_wd;
+	char *hostname;
+
 	GFileMonitor *monitor;
 	guint monitor_id;
 } SCPluginIfcfgPrivate;
@@ -417,7 +424,7 @@
 }
 
 static void
-setup_monitoring (SCPluginIfcfg *plugin)
+setup_ifcfg_monitoring (SCPluginIfcfg *plugin)
 {
 	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
 	GFile *file;
@@ -453,7 +460,7 @@
 	GSList *list = NULL;
 
 	if (!priv->connections) {
-		setup_monitoring (plugin);
+		setup_ifcfg_monitoring (plugin);
 		read_connections (plugin);
 	}
 
@@ -462,6 +469,70 @@
 	return list;
 }
 
+#define SC_NETWORK_FILE SYSCONFDIR"/sysconfig/network"
+
+static char *
+plugin_get_hostname (SCPluginIfcfg *plugin)
+{
+	shvarFile *network;
+	char *hostname;
+
+	network = svNewFile (SC_NETWORK_FILE);
+	if (!network) {
+		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Could not get hostname: failed to read " SC_NETWORK_FILE);
+		return FALSE;
+	}
+
+	hostname = svGetValue (network, "HOSTNAME");
+	svCloseFile (network);
+	return hostname;
+}
+
+static gboolean
+plugin_set_hostname (SCPluginIfcfg *plugin, const char *hostname)
+{
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	shvarFile *network;
+
+	network = svCreateFile (SC_NETWORK_FILE);
+	if (!network) {
+		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Could not save hostname: failed to create/open " SC_NETWORK_FILE);
+		return FALSE;
+	}
+
+	svSetValue (network, "HOSTNAME", hostname);
+	svWriteFile (network, 0644);
+	svCloseFile (network);
+
+	g_free (priv->hostname);
+	priv->hostname = hostname ? g_strdup (hostname) : NULL;
+	return TRUE;
+}
+
+static void
+sc_network_changed_cb (NMInotifyHelper *ih,
+                       struct inotify_event *evt,
+                       const char *path,
+                       gpointer user_data)
+{
+	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	char *new_hostname;
+
+	if (evt->wd != priv->sc_network_wd)
+		return;
+
+	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
 init (NMSystemConfigInterface *config, NMSystemConfigHalManager *hal_manager)
 {
@@ -476,6 +547,7 @@
 {
 	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
 	GError *error = NULL;
+	NMInotifyHelper *ih;
 
 	priv->g_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
 	if (!priv->g_connection) {
@@ -483,6 +555,12 @@
 		              error->message ? error->message : "(unknown)");
 		g_error_free (error);
 	}
+
+	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);
+
+	priv->hostname = plugin_get_hostname (plugin);
 }
 
 static void
@@ -490,9 +568,19 @@
 {
 	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (object);
 	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	NMInotifyHelper *ih;
 
 	g_object_unref (priv->hal_mgr);
 
+	ih = nm_inotify_helper_get ();
+
+	g_signal_handler_disconnect (ih, priv->ih_event_id);
+
+	if (priv->sc_network_wd >= 0)
+		nm_inotify_helper_remove_watch (ih, priv->sc_network_wd);
+
+	g_free (priv->hostname);
+
 	if (priv->g_connection)
 		dbus_g_connection_unref (priv->g_connection);
 
@@ -520,6 +608,8 @@
 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:
 		g_value_set_string (value, IFCFG_PLUGIN_NAME);
@@ -527,6 +617,32 @@
 	case NM_SYSTEM_CONFIG_INTERFACE_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_HOSTNAME);
+		break;
+	case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME:
+		g_value_set_string (value, priv->hostname);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+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 (!strlen (hostname))
+			hostname = NULL;
+		plugin_set_hostname (SC_PLUGIN_IFCFG (object),
+		                     (hostname && strlen (hostname)) ? hostname : NULL);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -543,14 +659,23 @@
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
 	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);
 
 	g_object_class_override_property (object_class,
-									  NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME,
-									  NM_SYSTEM_CONFIG_INTERFACE_NAME);
+	                                  NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES,
+	                                  NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES);
 
 	g_object_class_override_property (object_class,
-									  NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO,
-									  NM_SYSTEM_CONFIG_INTERFACE_INFO);
+	                                  NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME,
+	                                  NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
 }
 
 static void

Modified: trunk/system-settings/plugins/ifcfg-fedora/shvar.c
==============================================================================
--- trunk/system-settings/plugins/ifcfg-fedora/shvar.c	(original)
+++ trunk/system-settings/plugins/ifcfg-fedora/shvar.c	Thu Sep 18 15:16:44 2008
@@ -49,17 +49,15 @@
 
     s = g_malloc0(sizeof(shvarFile));
 
-#if 1   /* NetworkManager local change */
-    s->fd = open(name, O_RDONLY); /* NOT O_CREAT */
-    if (s->fd != -1) closefd = 1;
-#else
-    s->fd = open(name, O_RDWR); /* NOT O_CREAT */
-    if (s->fd == -1) {
+    s->fd = -1;
+    if (create)
+	s->fd = open(name, O_RDWR); /* NOT O_CREAT */
+ 
+    if (!create || s->fd == -1) {
 	/* try read-only */
 	s->fd = open(name, O_RDONLY); /* NOT O_CREAT */
 	if (s->fd != -1) closefd = 1;
     }
-#endif
     s->fileName = g_strdup(name);
 
     if (s->fd != -1) {

Modified: trunk/system-settings/plugins/ifcfg-suse/plugin.c
==============================================================================
--- trunk/system-settings/plugins/ifcfg-suse/plugin.c	(original)
+++ trunk/system-settings/plugins/ifcfg-suse/plugin.c	Thu Sep 18 15:16:44 2008
@@ -379,6 +379,12 @@
 	case NM_SYSTEM_CONFIG_INTERFACE_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_NONE);
+		break;
+	case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME:
+		g_value_set_string (value, "");
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -402,6 +408,14 @@
 	g_object_class_override_property (object_class,
 							    NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO,
 							    NM_SYSTEM_CONFIG_INTERFACE_INFO);
+
+	g_object_class_override_property (object_class,
+							    NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES,
+							    NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES);
+
+	g_object_class_override_property (object_class,
+							    NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME,
+							    NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
 }
 
 static void

Modified: trunk/system-settings/plugins/keyfile/plugin.c
==============================================================================
--- trunk/system-settings/plugins/keyfile/plugin.c	(original)
+++ trunk/system-settings/plugins/keyfile/plugin.c	Thu Sep 18 15:16:44 2008
@@ -283,6 +283,12 @@
 	case NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO:
 		g_value_set_string (value, KEYFILE_PLUGIN_INFO);
 		break;
+	case NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES:
+		g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS);
+		break;
+	case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME:
+		g_value_set_string (value, "");
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -324,12 +330,20 @@
 	object_class->get_property = get_property;
 
 	g_object_class_override_property (object_class,
-							    NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME,
-							    NM_SYSTEM_CONFIG_INTERFACE_NAME);
+	                                  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);
+
+	g_object_class_override_property (object_class,
+	                                  NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES,
+	                                  NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES);
 
 	g_object_class_override_property (object_class,
-							    NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO,
-							    NM_SYSTEM_CONFIG_INTERFACE_INFO);
+	                                  NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME,
+	                                  NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
 }
 
 static void

Modified: trunk/system-settings/src/dbus-settings.c
==============================================================================
--- trunk/system-settings/src/dbus-settings.c	(original)
+++ trunk/system-settings/src/dbus-settings.c	Thu Sep 18 15:16:44 2008
@@ -476,6 +476,27 @@
 	return TRUE;
 }
 
+static NMSystemConfigInterface *
+get_first_plugin_by_capability (NMSysconfigSettings *self,
+                                guint32 capability)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	GSList *iter;
+
+	g_return_val_if_fail (self != NULL, NULL);
+
+	/* Do any of the plugins support setting the hostname? */
+	for (iter = priv->plugins; iter; iter = iter->next) {
+		NMSystemConfigInterfaceCapabilities caps = NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE;
+
+		g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL);
+		if (caps & capability)
+			return NM_SYSTEM_CONFIG_INTERFACE (iter->data);
+	}
+
+	return NULL;
+}
+
 static gboolean
 impl_settings_add_connection (NMSysconfigSettings *self,
 						GHashTable *hash,
@@ -485,18 +506,10 @@
 	NMConnection *connection;
 	GSList *iter;
 	GError *err = NULL, *cnfh_error = NULL;
-	gboolean success;
+	gboolean success = FALSE;
 
 	/* Do any of the plugins support adding? */
-	success = FALSE;
-	for (iter = priv->plugins; iter && success == FALSE; iter = iter->next) {
-		NMSystemConfigInterfaceCapabilities caps = NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE;
-
-		g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL);
-		success = (caps & NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS);
-	}
-
-	if (!success) {
+	if (!get_first_plugin_by_capability (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) {
 		err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR,
 					    NM_SYSCONFIG_SETTINGS_ERROR_ADD_NOT_SUPPORTED,
 					    "%s", "None of the registered plugins support add.");
@@ -559,19 +572,12 @@
                              DBusGMethodInvocation *context)
 {
 	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
-	gboolean success = FALSE;
 	GError *err = NULL;
 	GSList *iter;
+	gboolean success = FALSE;
 
 	/* Do any of the plugins support setting the hostname? */
-	for (iter = priv->plugins; iter && success == FALSE; iter = iter->next) {
-		NMSystemConfigInterfaceCapabilities caps = NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE;
-
-		g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL);
-		success = (caps & NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME);
-	}
-
-	if (!success) {
+	if (!get_first_plugin_by_capability (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME)) {
 		err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR,
 		                   NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED,
 		                   "%s", "None of the registered plugins support setting the hostname.");
@@ -581,8 +587,8 @@
 	if (!check_polkit_privileges (priv->g_connection, priv->pol_ctx, context, &err))
 		goto out;
 
-	/* Now actually set the hostname in all plugins */
-	for (iter = priv->plugins, success = FALSE; iter; iter = iter->next) {
+	/* Set the hostname in all plugins */
+	for (iter = priv->plugins; iter; iter = iter->next) {
 		NMSystemConfigInterfaceCapabilities caps = NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE;
 
 		g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL);

Modified: trunk/system-settings/src/dbus-settings.h
==============================================================================
--- trunk/system-settings/src/dbus-settings.h	(original)
+++ trunk/system-settings/src/dbus-settings.h	Thu Sep 18 15:16:44 2008
@@ -39,6 +39,7 @@
 #define NM_SYSCONFIG_SETTINGS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsClass))
 
 #define NM_SYSCONFIG_SETTINGS_UNMANAGED_DEVICES "unmanaged-devices"
+#define NM_SYSCONFIG_SETTINGS_HOSTNAME "hostname"
 
 struct _NMSysconfigSettings
 {

Modified: trunk/system-settings/src/nm-system-config-error.c
==============================================================================
--- trunk/system-settings/src/nm-system-config-error.c	(original)
+++ trunk/system-settings/src/nm-system-config-error.c	Thu Sep 18 15:16:44 2008
@@ -29,6 +29,8 @@
 			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED, "UpdateNotSupported"),
 			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_DELETE_NOT_SUPPORTED, "DeleteNotSupported"),
 			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_ADD_FAILED, "AddFailed"),
+			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED, "SaveHostnameNotSupported"),
+			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED, "SaveHostnameFailed"),
 			{ 0, 0, 0 }
 		};
 

Modified: trunk/system-settings/src/nm-system-config-error.h
==============================================================================
--- trunk/system-settings/src/nm-system-config-error.h	(original)
+++ trunk/system-settings/src/nm-system-config-error.h	Thu Sep 18 15:16:44 2008
@@ -13,7 +13,9 @@
 	NM_SYSCONFIG_SETTINGS_ERROR_ADD_NOT_SUPPORTED,
 	NM_SYSCONFIG_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED,
 	NM_SYSCONFIG_SETTINGS_ERROR_DELETE_NOT_SUPPORTED,
-	NM_SYSCONFIG_SETTINGS_ERROR_ADD_FAILED
+	NM_SYSCONFIG_SETTINGS_ERROR_ADD_FAILED,
+	NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED,
+	NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED,
 };
 
 #define NM_SYSCONFIG_SETTINGS_ERROR (nm_sysconfig_settings_error_quark ())

Modified: trunk/system-settings/src/nm-system-config-interface.c
==============================================================================
--- trunk/system-settings/src/nm-system-config-interface.c	(original)
+++ trunk/system-settings/src/nm-system-config-interface.c	Thu Sep 18 15:16:44 2008
@@ -17,7 +17,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 Red Hat, Inc.
+ * (C) Copyright 2007 - 2008 Red Hat, Inc.
  */
 
 #include "nm-system-config-interface.h"
@@ -48,6 +48,24 @@
 							  NULL,
 							  G_PARAM_READABLE));
 
+	g_object_interface_install_property
+		(g_iface,
+		 g_param_spec_uint (NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES,
+							  "Capabilities",
+							  "Plugin capabilties",
+							  NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE,
+							  NM_SYSTEM_CONFIG_INTERFACE_CAP_LAST - 1,
+							  NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE,
+							  G_PARAM_READABLE));
+
+	g_object_interface_install_property
+		(g_iface,
+		 g_param_spec_string (NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME,
+							  "Hostname",
+							  "Configured hostname",
+							  NULL,
+							  G_PARAM_READWRITE));
+
 	/* Signals */
 	g_signal_new ("connection-added",
 				  iface_type,
@@ -130,14 +148,6 @@
 }
 
 gboolean
-nm_system_config_interface_supports_add (NMSystemConfigInterface *config)
-{
-	g_return_val_if_fail (config != NULL, FALSE);
-
-	return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection != NULL;
-}
-
-gboolean
 nm_system_config_interface_add_connection (NMSystemConfigInterface *config,
                                            NMConnection *connection,
                                            GError **error)

Modified: trunk/system-settings/src/nm-system-config-interface.h
==============================================================================
--- trunk/system-settings/src/nm-system-config-interface.h	(original)
+++ trunk/system-settings/src/nm-system-config-interface.h	Thu Sep 18 15:16:44 2008
@@ -60,13 +60,23 @@
 
 #define NM_SYSTEM_CONFIG_INTERFACE_NAME "name"
 #define NM_SYSTEM_CONFIG_INTERFACE_INFO "info"
+#define NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES "capabilities"
 #define NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME "hostname"
 
 typedef enum {
+	NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE = 0x00000000,
+	NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS = 0x00000001,
+	NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME = 0x00000002,
+
+	NM_SYSTEM_CONFIG_INTERFACE_CAP_LAST = NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME
+} NMSystemConfigInterfaceCapabilities;
+
+typedef enum {
 	NM_SYSTEM_CONFIG_INTERFACE_PROP_FIRST = 0x1000,
 
 	NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME = NM_SYSTEM_CONFIG_INTERFACE_PROP_FIRST,
 	NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO,
+	NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES,
 	NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME,
 } NMSystemConfigInterfaceProp;
 
@@ -110,12 +120,10 @@
 void nm_system_config_interface_init (NMSystemConfigInterface *config,
                                       NMSystemConfigHalManager *hal_manager);
 
-GSList * nm_system_config_interface_get_connections (NMSystemConfigInterface *config);
+GSList *nm_system_config_interface_get_connections (NMSystemConfigInterface *config);
 
 GSList *nm_system_config_interface_get_unmanaged_devices (NMSystemConfigInterface *config);
 
-gboolean nm_system_config_interface_supports_add (NMSystemConfigInterface *config);
-
 gboolean nm_system_config_interface_add_connection (NMSystemConfigInterface *config,
                                                     NMConnection *connection,
                                                     GError **error);



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