NetworkManager r3805 - in trunk: . libnm-util po src src/dhcp-manager



Author: dcbw
Date: Thu Jul  3 16:22:17 2008
New Revision: 3805
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=3805&view=rev

Log:
2008-07-03  Dan Williams  <dcbw redhat com>

	* libnm-util/nm-setting-ip4-config.c
	  libnm-util/nm-setting-ip4-config.h
		- Add properties for DHCP Client Identifier and DHCP Hostname

	* src/dhcp-manager/nm-dhcp-manager.c
	  src/dhcp-manager/nm-dhcp-manager.h
		- (nm_dhcp_manager_begin_transaction): take the connection's ip4-config
			setting as an argument to pass on to the dhclient config file
			creation function
		- (nm_dhcp_manager_cancel_transaction_real): remove dhclient config when
			DHCP is torn down
		- (dhclient_run): punt config file handling to create_dhclient_config()
		- (create_dhclient_config): create an interface-specific dhclient
			config file since there may need to be interface-specific options
			passed to dhclient
		- (merge_dhclient_config): merge normal distro dhclient config file and
			add options from the connection
		- (nm_dhcp_device_new): generate the interface specific dhclient
			config file path once
		- (nm_dhcp_device_destroy): handle partially initialized objects; free
			dhclient config file path

	* src/nm-device.c
		- (real_act_stage3_ip_config_start): pass ip4-config, if any, to the
			DHCP manager when starting DHCP



Modified:
   trunk/ChangeLog
   trunk/libnm-util/nm-setting-ip4-config.c
   trunk/libnm-util/nm-setting-ip4-config.h
   trunk/po/POTFILES.in
   trunk/src/dhcp-manager/nm-dhcp-manager.c
   trunk/src/dhcp-manager/nm-dhcp-manager.h
   trunk/src/nm-device.c

Modified: trunk/libnm-util/nm-setting-ip4-config.c
==============================================================================
--- trunk/libnm-util/nm-setting-ip4-config.c	(original)
+++ trunk/libnm-util/nm-setting-ip4-config.c	Thu Jul  3 16:22:17 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 -*- */
 
 #include <string.h>
 
@@ -54,6 +54,8 @@
 	PROP_ADDRESSES,
 	PROP_ROUTES,
 	PROP_IGNORE_DHCP_DNS,
+	PROP_DHCP_CLIENT_ID,
+	PROP_DHCP_HOSTNAME,
 
 	LAST_PROP
 };
@@ -120,6 +122,16 @@
 		return FALSE;
 	}
 
+	if (self->dhcp_client_id && !strlen (self->dhcp_client_id)) {
+		g_warning ("invalid DHCP client ID");
+		return FALSE;
+	}
+
+	if (self->dhcp_hostname && !strlen (self->dhcp_hostname)) {
+		g_warning ("invalid DHCP client ID");
+		return FALSE;
+	}
+
 	return TRUE;
 }
 
@@ -176,6 +188,14 @@
 	case PROP_IGNORE_DHCP_DNS:
 		setting->ignore_dhcp_dns = g_value_get_boolean (value);
 		break;
+	case PROP_DHCP_CLIENT_ID:
+		g_free (setting->dhcp_client_id);
+		setting->dhcp_client_id = g_value_dup_string (value);
+		break;
+	case PROP_DHCP_HOSTNAME:
+		g_free (setting->dhcp_hostname);
+		setting->dhcp_hostname = g_value_dup_string (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -207,6 +227,12 @@
 	case PROP_IGNORE_DHCP_DNS:
 		g_value_set_boolean (value, setting->ignore_dhcp_dns);
 		break;
+	case PROP_DHCP_CLIENT_ID:
+		g_value_set_string (value, setting->dhcp_client_id);
+		break;
+	case PROP_DHCP_HOSTNAME:
+		g_value_set_string (value, setting->dhcp_hostname);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -273,4 +299,21 @@
 						   "Ignore DHCP DNS",
 						   FALSE,
 						   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	g_object_class_install_property
+		(object_class, PROP_DHCP_CLIENT_ID,
+		 g_param_spec_string (NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID,
+						   "DHCP Client ID",
+						   "DHCP Client ID",
+						   NULL,
+						   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	g_object_class_install_property
+		(object_class, PROP_DHCP_HOSTNAME,
+		 g_param_spec_string (NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME,
+						   "DHCP Hostname",
+						   "DHCP Hostname",
+						   NULL,
+						   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
 }
+

Modified: trunk/libnm-util/nm-setting-ip4-config.h
==============================================================================
--- trunk/libnm-util/nm-setting-ip4-config.h	(original)
+++ trunk/libnm-util/nm-setting-ip4-config.h	Thu Jul  3 16:22:17 2008
@@ -36,6 +36,8 @@
 #define NM_SETTING_IP4_CONFIG_ADDRESSES       "addresses"
 #define NM_SETTING_IP4_CONFIG_ROUTES          "routes"
 #define NM_SETTING_IP4_CONFIG_IGNORE_DHCP_DNS "ignore-dhcp-dns"
+#define NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID  "dhcp-client-id"
+#define NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME   "dhcp-hostname"
 
 #define NM_SETTING_IP4_CONFIG_METHOD_DHCP   "dhcp"
 #define NM_SETTING_IP4_CONFIG_METHOD_AUTOIP "autoip"
@@ -57,6 +59,8 @@
 	GSList *addresses;  /* array of NMSettingIP4Address */
 	GSList *routes;     /* array of NMSettingIP4Address */
 	gboolean ignore_dhcp_dns;
+	char *dhcp_client_id;
+	char *dhcp_hostname;
 } NMSettingIP4Config;
 
 typedef struct {

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Thu Jul  3 16:22:17 2008
@@ -3,6 +3,7 @@
 # Please keep this file sorted alphabetically.
 src/nm-netlink-monitor.c
 src/NetworkManager.c
+src/dhcp-manager/nm-dhcp-manager.c
 src/named-manager/nm-named-manager.c
 system-settings/plugins/ifcfg-fedora/plugin.c
 system-settings/src/main.c

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 Jul  3 16:22:17 2008
@@ -22,6 +22,7 @@
 
 
 #include <glib.h>
+#include <glib/gi18n.h>
 #include <dbus/dbus.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -32,6 +33,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
+#include <fcntl.h>
 
 #include "nm-dhcp-manager.h"
 #include "nm-marshal.h"
@@ -55,14 +57,6 @@
 
 #define NM_DHCP_TIMEOUT   	45 /* DHCP timeout, in seconds */
 
-#if defined(TARGET_SUSE)
-#define DHCLIENT_CONF_PATH  SYSCONFDIR "/dhclient.conf"
-#elif defined(TARGET_DEBIAN)
-#define DHCLIENT_CONF_PATH  SYSCONFDIR "/dhcp3/dhclient.conf"
-#else
-#define DHCLIENT_CONF_PATH_FORMAT  SYSCONFDIR "/dhclient-%s.conf"
-#endif
-
 
 static const char *dhclient_binary_paths[] =
 {
@@ -76,6 +70,7 @@
         char *			iface;
         guchar 			state;
         GPid 			dhclient_pid;
+        char *			dhclient_conf;
         guint			timeout_id;
         guint			watch_id;
         NMDHCPManager *	manager;
@@ -224,9 +219,19 @@
 static void
 nm_dhcp_device_destroy (NMDHCPDevice *device)
 {
+	int ret;
+
 	nm_dhcp_device_timeout_cleanup (device);
 	nm_dhcp_device_watch_cleanup (device);
-	g_hash_table_destroy (device->options);
+
+	if (device->options)
+		g_hash_table_destroy (device->options);
+
+	if (device->dhclient_conf) {
+		ret = unlink (device->dhclient_conf);
+		g_free (device->dhclient_conf);
+	}
+
 	g_free (device->iface);
 	g_slice_free (NMDHCPDevice, device);
 }
@@ -529,6 +534,7 @@
 {
 	NMDHCPDevice *device;
 	GHashTable * hash = NM_DHCP_MANAGER_GET_PRIVATE (manager)->devices;
+	char *tmp;
 
 	device = g_slice_new0 (NMDHCPDevice);
 	if (!device) {
@@ -546,6 +552,10 @@
 	
 	device->manager = manager;
 
+	tmp = g_strdup_printf ("nm-dhclient-%s.conf", iface);
+	device->dhclient_conf = g_build_filename ("/var", "run", tmp, NULL);
+	g_free (tmp);
+
 	nm_dhcp_manager_cancel_transaction_real (device, FALSE);
 
 	/* Do this after the transaction cancel since that clears options out */
@@ -564,9 +574,7 @@
 	return device;
 
 error:
-	g_hash_table_destroy (device->options);
-	g_free (device->iface);
-	g_slice_free (NMDHCPDevice, device);
+	nm_dhcp_device_destroy (device);
 	return NULL;
 }
 
@@ -607,8 +615,131 @@
 	setpgid (pid, pid);
 }
 
+
+#define DHCP_CLIENT_ID_TAG "send dhcp-client-identifier"
+#define DHCP_CLIENT_ID_FORMAT DHCP_CLIENT_ID_TAG " \"%s\"; # added by NetworkManager"
+
+#define DHCP_HOSTNAME_TAG "send host-name"
+#define DHCP_HOSTNAME_FORMAT DHCP_HOSTNAME_TAG " \"%s\"; # added by NetworkManager"
+
 static gboolean
-dhclient_run (NMDHCPDevice *device)
+merge_dhclient_config (NMDHCPDevice *device,
+                       NMSettingIP4Config *s_ip4,
+                       const char *contents,
+                       const char *orig,
+                       GError **error)
+{
+	GString *new_contents;
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (device != NULL, FALSE);
+	g_return_val_if_fail (device->iface != NULL, FALSE);
+	
+	new_contents = g_string_new (_("# Created by NetworkManager\n"));
+
+	/* Add existing options, if any, but ignore stuff NM will replace. */
+	if (contents) {
+		char **lines = NULL, **line;
+
+		g_string_append_printf (new_contents, _("# Merged from %s\n\n"), orig);
+
+		lines = g_strsplit_set (contents, "\n\r", 0);
+		for (line = lines; lines && *line; line++) {
+			gboolean ignore = FALSE;
+
+			if (!strlen (g_strstrip (*line)))
+				continue;
+
+			if (   s_ip4
+			    && s_ip4->dhcp_client_id
+			    && !strncmp (*line, DHCP_CLIENT_ID_TAG, strlen (DHCP_CLIENT_ID_TAG)))
+				ignore = TRUE;
+
+			if (   s_ip4
+			    && s_ip4->dhcp_client_id
+			    && !strncmp (*line, DHCP_HOSTNAME_TAG, strlen (DHCP_HOSTNAME_TAG)))
+				ignore = TRUE;
+
+			if (!ignore) {
+				g_string_append (new_contents, *line);
+				g_string_append_c (new_contents, '\n');
+			}
+		}
+
+		if (lines)
+			g_strfreev (lines);
+	} else
+		g_string_append_c (new_contents, '\n');
+
+	/* Add NM options from connection */
+	if (s_ip4 && s_ip4->dhcp_client_id)
+		g_string_append_printf (new_contents, DHCP_CLIENT_ID_FORMAT "\n", s_ip4->dhcp_client_id);
+
+	if (s_ip4 && s_ip4->dhcp_hostname)
+		g_string_append_printf (new_contents, DHCP_HOSTNAME_FORMAT "\n", s_ip4->dhcp_hostname);
+
+	if (g_file_set_contents (device->dhclient_conf, new_contents->str, -1, error))
+		success = TRUE;
+
+	g_string_free (new_contents, TRUE);
+	return success;
+}
+
+/* NM provides interface-specific options; thus the same dhclient config
+ * file cannot be used since DHCP transactions can happen in parallel.
+ * Since some distros don't have default per-interface dhclient config files,
+ * read their single config file and merge that into a custom per-interface
+ * config file along with the NM options.
+ */
+static gboolean
+create_dhclient_config (NMDHCPDevice *device, NMSettingIP4Config *s_ip4)
+{
+	char *orig = NULL, *contents = NULL;
+	GError *error = NULL;
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (device != NULL, FALSE);
+
+#if defined(TARGET_SUSE)
+	orig = g_strdup (SYSCONFDIR "/dhclient.conf");
+#elif defined(TARGET_DEBIAN)
+	orig = g_strdup (SYSCONFDIR "/dhcp3/dhclient.conf");
+#else
+	orig = g_strdup_printf (SYSCONFDIR "/dhclient-%s.conf", device->iface);
+#endif
+
+	if (!orig) {
+		nm_warning ("%s: not enough memory for dhclient options.", device->iface);
+		return FALSE;
+	}
+
+	if (!g_file_test (orig, G_FILE_TEST_EXISTS))
+		goto out;
+
+	if (!g_file_get_contents (orig, &contents, NULL, &error)) {
+		nm_warning ("%s: error reading dhclient configuration %s: %s",
+		            device->iface, orig, error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+out:
+	error = NULL;
+	if (merge_dhclient_config (device, s_ip4, contents, orig, &error))
+		success = TRUE;
+	else {
+		nm_warning ("%s: error creating dhclient configuration: %s",
+		            device->iface, error->message);
+		g_error_free (error);
+	}
+
+	g_free (contents);
+	g_free (orig);
+	return success;
+}
+
+static gboolean
+dhclient_run (NMDHCPDevice *device, NMSettingIP4Config *s_ip4)
 {
 	const char **	dhclient_binary = NULL;
 	GPtrArray *		dhclient_argv = NULL;
@@ -616,7 +747,6 @@
 	GError *		error = NULL;
 	char *			pidfile = NULL;
 	char *			leasefile = NULL;
-	char *			conffile = NULL;
 	gboolean		success = FALSE;
 	char *			pid_contents = NULL;
 
@@ -645,15 +775,8 @@
 		goto out;
 	}
 
-#ifdef DHCLIENT_CONF_PATH_FORMAT
-	conffile = g_strdup_printf (DHCLIENT_CONF_PATH_FORMAT, device->iface);
-#else
-	conffile = g_strdup (DHCLIENT_CONF_PATH);
-#endif
-	if (!conffile) {
-		nm_warning ("%s: not enough memory for dhclient options.", device->iface);
+	if (!create_dhclient_config (device, s_ip4))
 		goto out;
-	}
 
 	/* Kill any existing dhclient bound to this interface */
 	if (g_file_get_contents (pidfile, &pid_contents, NULL, NULL)) {
@@ -679,7 +802,7 @@
 	g_ptr_array_add (dhclient_argv, (gpointer) leasefile);
 
 	g_ptr_array_add (dhclient_argv, (gpointer) "-cf");	/* Set interface config file */
-	g_ptr_array_add (dhclient_argv, (gpointer) conffile);
+	g_ptr_array_add (dhclient_argv, (gpointer) device->dhclient_conf);
 
 	g_ptr_array_add (dhclient_argv, (gpointer) device->iface);
 	g_ptr_array_add (dhclient_argv, NULL);
@@ -701,7 +824,6 @@
 
 out:
 	g_free (pid_contents);
-	g_free (conffile);
 	g_free (leasefile);
 	g_free (pidfile);
 	g_ptr_array_free (dhclient_argv, TRUE);
@@ -711,6 +833,7 @@
 gboolean
 nm_dhcp_manager_begin_transaction (NMDHCPManager *manager,
 								   const char *iface,
+								   NMSettingIP4Config *s_ip4,
 								   guint32 timeout)
 {
 	NMDHCPManagerPrivate *priv;
@@ -740,7 +863,7 @@
 	                                    nm_dhcp_manager_handle_timeout,
 	                                    device);
 
-	dhclient_run (device);
+	dhclient_run (device, s_ip4);
 
 	return TRUE;
 }
@@ -810,6 +933,9 @@
 		g_free (leasefile);
 	}
 
+	/* Clean up config file if it got left around */
+	remove (device->dhclient_conf);
+
 	nm_dhcp_device_watch_cleanup (device);
 	nm_dhcp_device_timeout_cleanup (device);
 	g_hash_table_remove_all (device->options);

Modified: trunk/src/dhcp-manager/nm-dhcp-manager.h
==============================================================================
--- trunk/src/dhcp-manager/nm-dhcp-manager.h	(original)
+++ trunk/src/dhcp-manager/nm-dhcp-manager.h	Thu Jul  3 16:22:17 2008
@@ -23,6 +23,9 @@
 
 #include <glib/gtypes.h>
 #include <glib-object.h>
+
+#include <nm-setting-ip4-config.h>
+
 #include "nm-ip4-config.h"
 
 #define NM_TYPE_DHCP_MANAGER            (nm_dhcp_manager_get_type ())
@@ -68,6 +71,7 @@
 NMDHCPManager *nm_dhcp_manager_get                  (void);
 gboolean       nm_dhcp_manager_begin_transaction    (NMDHCPManager *manager,
                                                      const char *iface,
+                                                     NMSettingIP4Config *s_ip4,
                                                      guint32 timeout);
 void           nm_dhcp_manager_cancel_transaction   (NMDHCPManager *manager,
                                                      const char *iface);

Modified: trunk/src/nm-device.c
==============================================================================
--- trunk/src/nm-device.c	(original)
+++ trunk/src/nm-device.c	Thu Jul  3 16:22:17 2008
@@ -525,16 +525,16 @@
 static NMActStageReturn
 real_act_stage3_ip_config_start (NMDevice *self)
 {
-	NMSettingIP4Config *setting;
+	NMSettingIP4Config *s_ip4;
 	NMActRequest *req;
 	NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
 
 	req = nm_device_get_act_request (self);
-	setting = (NMSettingIP4Config *) nm_connection_get_setting (nm_act_request_get_connection (req),
+	s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (nm_act_request_get_connection (req),
 													NM_TYPE_SETTING_IP4_CONFIG);
 
 	/* If we did not receive IP4 configuration information, default to DHCP */
-	if (!setting || !strcmp (setting->method, NM_SETTING_IP4_CONFIG_METHOD_DHCP)) {
+	if (!s_ip4 || !strcmp (s_ip4->method, NM_SETTING_IP4_CONFIG_METHOD_DHCP)) {
 		NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 		gboolean success;
 
@@ -547,6 +547,7 @@
 
 		success = nm_dhcp_manager_begin_transaction (priv->dhcp_manager,
 													 nm_device_get_iface (self),
+													 s_ip4,
 													 45);
 
 		g_signal_handler_unblock (priv->dhcp_manager, priv->dhcp_state_sigid);



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