For review: updates to add IPv6 dynamic dns support



Note: this is for review and not submit. After I respond to any comments, make appropriate additions and/or subtractions, and gone over the code myself "just one more time", I will submit the patch and it should be RSN (real soon now).

Note: NO changes were made to the IPv4 dhcp support.

OK, there are multiple parts to this.

1. Modified nm-dhcp-manager.c and nm-dhcp-dhclient.c to put the HOSTNAME or DHCP_HOSTNAME on the dhclient "-6" command line using the "-F" parameter. This tells dhclient to send the name as a fqdn.fqdn to the dhcp server. Note: sending a hostname in dhcp6 does not work; it must be the fqdn.fqdn. And yes, the hostname is not a fully qualified domain name (with dots) but that is OK and specified in the dhcp-options man-page as well as RFC4704.

2. Modify IPv6 stuff in libnm-util to add IPv6 having its own copy of the DHCP_HOSTNAME. I am not sure what/how docs such as the libnm-util reference manual to update.

3. Add code to ifcfg-rh/reader.c and ifcfg-rh/writer.c to set the IPv6 DHCP_HOSTNAME both ways. While the code in ifcfg-rh/writer.c may duplicate what IPv4 has already done, it is necessary because without it, when you run a single IPv6 stack network, the DHCP_HOSTNAME will disappear.

4. I added some nm_log_dbg and PLUGIN_WARN statements to help with the debugging. I plan to leave these in ... who knows, they may be needed at a later point in time.

Most of the testing has been done with qemu/kvm/libvirt virtual guests. It works. I tested with both dhcpd6/named and dnsmasq as servers. I found dnsmasq to actually do a better job (I am not sure that dhcpd6 is in compliance with the RFC).

I did a little test with using plugin=keyfile instead of plugin=ifcfg-rh and it worked. I am not sure what kind of testing could be done or what kind of parameters could be specified. The ifcfg-rh plugin seems to handle a whole bunch of IPV6 parameters but none of these appears to be supported by the applet.

All development and testing was done on Fedora 17 using NetworkManager-0.9.4.0-9.git20120521. However, I have applied the patch (with no changes) to NetworkManager-0.9.7.0-1.git20120820 as well as a git clone copy ... it apples clean and "makes" clean. I will be testing 0.9.7.0 as soon as I figure out how to get its rpms and network-manager-applet rpms built.

Comment?  Suggestions?? Whatever?

BTW, my reason for doing this is so that I can add IPv6 dhcp and ddns support (via dnsmasq) to libvirt.

Gene
diff -urp NetworkManager-0.9.4.0.orig/libnm-util/libnm-util.ver NetworkManager-0.9.4.0/libnm-util/libnm-util.ver
--- NetworkManager-0.9.4.0.orig/libnm-util/libnm-util.ver	2012-05-21 08:20:28.000000000 -0400
+++ NetworkManager-0.9.4.0/libnm-util/libnm-util.ver	2012-09-23 18:48:11.944984285 -0400
@@ -310,6 +310,7 @@ global:
 	nm_setting_ip6_config_error_get_type;
 	nm_setting_ip6_config_error_quark;
 	nm_setting_ip6_config_get_address;
+	nm_setting_ip6_config_get_dhcp_hostname;
 	nm_setting_ip6_config_get_dns;
 	nm_setting_ip6_config_get_dns_search;
 	nm_setting_ip6_config_get_ignore_auto_dns;
diff -urp NetworkManager-0.9.4.0.orig/libnm-util/nm-setting-ip6-config.c NetworkManager-0.9.4.0/libnm-util/nm-setting-ip6-config.c
--- NetworkManager-0.9.4.0.orig/libnm-util/nm-setting-ip6-config.c	2012-02-28 04:26:07.000000000 -0500
+++ NetworkManager-0.9.4.0/libnm-util/nm-setting-ip6-config.c	2012-09-23 18:48:11.946984271 -0400
@@ -67,6 +67,7 @@ G_DEFINE_TYPE (NMSettingIP6Config, nm_se
 
 typedef struct {
 	char *method;
+	char *dhcp_hostname;
 	GSList *dns;        /* array of struct in6_addr */
 	GSList *dns_search; /* list of strings */
 	GSList *addresses;  /* array of NMIP6Address */
@@ -82,6 +83,7 @@ typedef struct {
 enum {
 	PROP_0,
 	PROP_METHOD,
+	PROP_DHCP_HOSTNAME,
 	PROP_DNS,
 	PROP_DNS_SEARCH,
 	PROP_ADDRESSES,
@@ -123,6 +125,23 @@ nm_setting_ip6_config_get_method (NMSett
 }
 
 /**
+ * nm_setting_ip6_config_get_dhcp_hostname:
+ * @setting: the #NMSettingIP6Config
+ *
+ * Returns the value contained in the #NMSettingIP6Config:dhcp-hostname
+ * property.
+ *
+ * Returns: the configured hostname to send to the DHCP server
+ **/
+const char *
+nm_setting_ip6_config_get_dhcp_hostname (NMSettingIP6Config *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL);
+
+	return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dhcp_hostname;
+}
+
+/**
  * nm_setting_ip6_config_get_num_dns:
  * @setting: the #NMSettingIP6Config
  *
@@ -694,6 +713,14 @@ verify (NMSetting *setting, GSList *all_
 		return FALSE;
 	}
 
+	if (priv->dhcp_hostname && !strlen (priv->dhcp_hostname)) {
+		g_set_error (error,
+		             NM_SETTING_IP6_CONFIG_ERROR,
+		             NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
+		             NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME);
+		return FALSE;
+	}
+
 	return TRUE;
 }
 
@@ -752,6 +779,10 @@ set_property (GObject *object, guint pro
 	case PROP_IGNORE_AUTO_DNS:
 		priv->ignore_auto_dns = g_value_get_boolean (value);
 		break;
+	case PROP_DHCP_HOSTNAME:
+		g_free (priv->dhcp_hostname);
+		priv->dhcp_hostname = g_value_dup_string (value);
+		break;
 	case PROP_NEVER_DEFAULT:
 		priv->never_default = g_value_get_boolean (value);
 		break;
@@ -795,6 +826,9 @@ get_property (GObject *object, guint pro
 	case PROP_IGNORE_AUTO_DNS:
 		g_value_set_boolean (value, priv->ignore_auto_dns);
 		break;
+	case PROP_DHCP_HOSTNAME:
+		g_value_set_string (value, priv->dhcp_hostname);
+		break;
 	case PROP_NEVER_DEFAULT:
 		g_value_set_boolean (value, priv->never_default);
 		break;
@@ -861,6 +895,20 @@ nm_setting_ip6_config_class_init (NMSett
 						      G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
 
 	/**
+	 * NMSettingIP6Config:dhcp-hostname:
+	 *
+	 * The specified name will be sent to the DHCP server when acquiring a lease.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DHCP_HOSTNAME,
+		 g_param_spec_string (NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME,
+						   "DHCP Hostname",
+						   "The specified name will be sent to the DHCP server "
+						   "when acquiring a lease.",
+						   NULL,
+						   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	/**
 	 * NMSettingIP6Config:dns:
 	 *
 	 * Array of DNS servers, where each member of the array is a byte array
diff -urp NetworkManager-0.9.4.0.orig/libnm-util/nm-setting-ip6-config.h NetworkManager-0.9.4.0/libnm-util/nm-setting-ip6-config.h
--- NetworkManager-0.9.4.0.orig/libnm-util/nm-setting-ip6-config.h	2012-03-13 07:08:39.000000000 -0400
+++ NetworkManager-0.9.4.0/libnm-util/nm-setting-ip6-config.h	2012-09-23 18:48:11.947984264 -0400
@@ -69,6 +69,8 @@ GQuark nm_setting_ip6_config_error_quark
 #define NM_SETTING_IP6_CONFIG_NEVER_DEFAULT      "never-default"
 #define NM_SETTING_IP6_CONFIG_MAY_FAIL           "may-fail"
 #define NM_SETTING_IP6_CONFIG_IP6_PRIVACY        "ip6-privacy"
+#define NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME      "dhcp-hostname"
+
 
 /**
  * NM_SETTING_IP6_CONFIG_METHOD_IGNORE:
@@ -239,6 +241,7 @@ void                   nm_setting_ip6_co
 gboolean               nm_setting_ip6_config_get_ignore_auto_routes (NMSettingIP6Config *setting);
 
 gboolean               nm_setting_ip6_config_get_ignore_auto_dns    (NMSettingIP6Config *setting);
+const char *           nm_setting_ip6_config_get_dhcp_hostname      (NMSettingIP6Config *setting);
 gboolean               nm_setting_ip6_config_get_never_default      (NMSettingIP6Config *setting);
 gboolean               nm_setting_ip6_config_get_may_fail           (NMSettingIP6Config *setting);
 NMSettingIP6ConfigPrivacy nm_setting_ip6_config_get_ip6_privacy (NMSettingIP6Config *setting);
diff -urp NetworkManager-0.9.4.0.orig/src/dhcp-manager/nm-dhcp-dhclient.c NetworkManager-0.9.4.0/src/dhcp-manager/nm-dhcp-dhclient.c
--- NetworkManager-0.9.4.0.orig/src/dhcp-manager/nm-dhcp-dhclient.c	2012-05-21 09:00:51.000000000 -0400
+++ NetworkManager-0.9.4.0/src/dhcp-manager/nm-dhcp-dhclient.c	2012-09-23 18:48:11.938984326 -0400
@@ -419,7 +419,8 @@ dhclient_child_setup (gpointer user_data
 static GPid
 dhclient_start (NMDHCPClient *client,
                 const char *mode_opt,
-                gboolean release)
+                gboolean release,
+                const char *hostname)
 {
 	NMDHCPDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client);
 	GPtrArray *argv = NULL;
@@ -489,6 +490,10 @@ dhclient_start (NMDHCPClient *client,
 		g_ptr_array_add (argv, (gpointer) "-6");
 		if (mode_opt)
 			g_ptr_array_add (argv, (gpointer) mode_opt);
+		if ((hostname!=NULL) && (strlen(hostname)>0)){
+			g_ptr_array_add (argv, (gpointer) "-F");
+			g_ptr_array_add (argv, (gpointer) hostname);
+		}
 	} else {
 		g_ptr_array_add (argv, (gpointer) "-4");
 	}
@@ -561,7 +566,7 @@ real_ip4_start (NMDHCPClient *client,
 		return -1;
 	}
 
-	return dhclient_start (client, NULL, FALSE);
+	return dhclient_start (client, NULL, FALSE, hostname);
 }
 
 static GPid
@@ -571,7 +576,7 @@ real_ip6_start (NMDHCPClient *client,
                 const char *hostname,
                 gboolean info_only)
 {
-	return dhclient_start (client, info_only ? "-S" : "-N", FALSE);
+	return dhclient_start (client, info_only ? "-S" : "-N", FALSE, hostname);
 }
 
 static void
@@ -593,7 +598,7 @@ real_stop (NMDHCPClient *client, gboolea
 	if (release) {
 		GPid rpid;
 
-		rpid = dhclient_start (client, NULL, TRUE);
+		rpid = dhclient_start (client, NULL, TRUE, NULL);
 		if (rpid > 0) {
 			/* Wait a few seconds for the release to happen */
 			nm_dhcp_client_stop_pid (rpid, nm_dhcp_client_get_iface (client), 5);
diff -urp NetworkManager-0.9.4.0.orig/src/dhcp-manager/nm-dhcp-manager.c NetworkManager-0.9.4.0/src/dhcp-manager/nm-dhcp-manager.c
--- NetworkManager-0.9.4.0.orig/src/dhcp-manager/nm-dhcp-manager.c	2012-02-16 06:26:23.000000000 -0500
+++ NetworkManager-0.9.4.0/src/dhcp-manager/nm-dhcp-manager.c	2012-09-23 18:48:11.961984168 -0400
@@ -424,6 +424,11 @@ client_start (NMDHCPManager *self,
 	g_return_val_if_fail (client != NULL, NULL);
 	add_client (self, client);
 
+	if (hostname==NULL)
+		nm_log_dbg (LOGD_DHCP, "hostname is %s for start %s", 
+				hostname ? hostname : "NULL",
+				ipv6 ? "ipv6" : "ipv4");
+
 	if (ipv6)
 		success = nm_dhcp_client_start_ip6 (client, s_ip6, dhcp_anycast_addr, hostname, info_only);
 	else
@@ -498,7 +503,28 @@ nm_dhcp_manager_start_ip6 (NMDHCPManager
                            guint8 *dhcp_anycast_addr,
                            gboolean info_only)
 {
-	return client_start (self, iface, uuid, TRUE, NULL, s_ip6, timeout, dhcp_anycast_addr, NULL, info_only);
+	NMDHCPManagerPrivate *priv;
+	const char *hostname = NULL;
+
+	g_return_val_if_fail (self, NULL);
+	g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL);
+
+	priv = NM_DHCP_MANAGER_GET_PRIVATE (self);
+
+
+	hostname = nm_setting_ip6_config_get_dhcp_hostname (s_ip6);
+
+	if (hostname==NULL && priv->hostname_provider) {
+		nm_log_dbg (LOGD_DHCP6, 
+			"hostname is NULL from ip6_config_get, trying hostname_provider");
+		hostname = nm_hostname_provider_get_hostname (priv->hostname_provider);
+		if (   hostname
+		    && (!strcmp (hostname, "localhost.localdomain") ||
+		        !strcmp (hostname, "localhost6.localdomain6")))
+			hostname = NULL;
+	}
+
+	return client_start (self, iface, uuid, TRUE, NULL, s_ip6, timeout, dhcp_anycast_addr, hostname, info_only);
 }
 
 static void
diff -urp NetworkManager-0.9.4.0.orig/src/settings/plugins/ifcfg-rh/reader.c NetworkManager-0.9.4.0/src/settings/plugins/ifcfg-rh/reader.c
--- NetworkManager-0.9.4.0.orig/src/settings/plugins/ifcfg-rh/reader.c	2012-05-21 08:20:29.000000000 -0400
+++ NetworkManager-0.9.4.0/src/settings/plugins/ifcfg-rh/reader.c	2012-09-23 18:48:11.964984148 -0400
@@ -1301,6 +1301,8 @@ make_ip4_setting (shvarFile *ifcfg,
 		}
 	} else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
 		value = svGetValue (ifcfg, "DHCP_HOSTNAME", FALSE);
+		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "IPv4 hostname is '%s'", 
+			value ? value : "NULL");
 		if (value && strlen (value))
 			g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, value, NULL);
 		g_free (value);
@@ -1556,6 +1558,17 @@ make_ip6_setting (shvarFile *ifcfg,
 	              NM_SETTING_IP6_CONFIG_IP6_PRIVACY, ip6_privacy_val,
 	              NULL);
 
+	/* Handle IPv6 hostname */
+	if (dhcp6) {
+		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "info: DHCPV6C specified");
+		value = svGetValue (ifcfg, "DHCP_HOSTNAME", FALSE);
+		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "IPv6 hostname is '%s'", 
+			value ? value : "NULL");
+		if (value && strlen (value))
+			g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME, value, NULL);
+		g_free (value);
+	}
+
 	/* Don't bother to read IP, DNS and routes when IPv6 is disabled */
 	if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0)
 		return NM_SETTING (s_ip6);
@@ -1592,6 +1605,16 @@ make_ip6_setting (shvarFile *ifcfg,
 		g_strfreev (list);
 	} else if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
 		/* TODO - autoconf or DHCPv6 stuff goes here */
+		/* Handle IPv6 hostname */
+		if (dhcp6) {
+			value = svGetValue (ifcfg, "DHCP_HOSTNAME", FALSE);
+			if (value && strlen (value))
+				g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME, value, NULL);
+			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "IPv6 hostname is '%s'", 
+					value ? value : "NULL");
+			g_free (value);
+		}
+
 	}
 
 	/* DNS servers
diff -urp NetworkManager-0.9.4.0.orig/src/settings/plugins/ifcfg-rh/writer.c NetworkManager-0.9.4.0/src/settings/plugins/ifcfg-rh/writer.c
--- NetworkManager-0.9.4.0.orig/src/settings/plugins/ifcfg-rh/writer.c	2012-04-03 08:56:19.000000000 -0400
+++ NetworkManager-0.9.4.0/src/settings/plugins/ifcfg-rh/writer.c	2012-09-23 18:48:11.970984106 -0400
@@ -1529,6 +1529,8 @@ write_ip4_setting (NMConnection *connect
 		            FALSE);
 
 		value = nm_setting_ip4_config_get_dhcp_hostname (s_ip4);
+		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "IPv4 DHCP_HOSTNAME is '%s'",
+		             value ? value : "NULL");
 		if (value)
 			svSetValue (ifcfg, "DHCP_HOSTNAME", value, FALSE);
 
@@ -1726,9 +1728,15 @@ write_ip6_setting (NMConnection *connect
 		svSetValue (ifcfg, "IPV6_AUTOCONF", "yes", FALSE);
 		svSetValue (ifcfg, "DHCPV6C", NULL, FALSE);
 	} else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
+		const char *hostname;
 		svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
 		svSetValue (ifcfg, "IPV6_AUTOCONF", "no", FALSE);
 		svSetValue (ifcfg, "DHCPV6C", "yes", FALSE);
+		hostname = nm_setting_ip6_config_get_dhcp_hostname (s_ip6);
+		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "IPv6 DHCP_HOSTNAME is '%s'",
+		             hostname ? hostname : "NULL");
+		if (hostname)
+			svSetValue (ifcfg, "DHCP_HOSTNAME", hostname, FALSE);
 	} else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
 		svSetValue (ifcfg, "IPV6INIT", "yes", FALSE);
 		svSetValue (ifcfg, "IPV6_AUTOCONF", "no", FALSE);


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