Re: NetworkManager on Debian



Le mardi 27 mai 2008 à 20:26 +0200, Vincent Bernat a écrit :
> OoO  En ce  début d'après-midi  ensoleillé du  mardi 27  mai  2008, vers
> 15:59, Dan Williams <dcbw redhat com> disait:
> 
> > Even if the resolvconf binary is installed, how do you know it's
> > actually in use?
> 
> You   should  also   check   if  /etc/resolv.conf   is   a  symlink   to
> /etc/resolvconf/run/resolv.conf.

Thanks a lot for this hint.
Here what I currently use .
As you can see there is one dirty "guess". That is that there is only
one ip4config when removing happens : well I don't expect it to be true
but right now I don't know how to handle more than one to find out if
the interace is "down". One (I ?) need to spend time deciphering this
one out.
Also the interface name may be missing as the code shows in
NetworkManagerSystem.c nm_system_vpn_device_set_from_ip4_config :
 if (!iface || !strlen (iface))
                goto out;
this is not handled at all as I don't understand the vpn code yet.

Second a not so pretty usage of spawn process with a call to /bin/sh as
I use echo and a pipe. Seems to me as it is not something new to NM to
send data over a pipe to a program instead of using a file though I need
to find an example or learn more about pipe usage with nm_process_spawn
before fixing this one.
I also find it unpretty to duplicate the code from rewrite_resolv_conf
in src/named-manager/nm-named-manager.c into compute_resolv_conf.
Factorizing it would require a change in the way rewrite_resolv_conf
works so I was not ready to do it.

And the most critical part is well to find out if this approach to the
issue at stake is bitrotten . Should I switch to another approach and
what could it be ?

I also attached part of the debian patches for NM available in Michael
Biebl repository. This chunk prevent NM from overwritting resolvconf
version of /etc/resolv.conf . Maybe it should also check for the
symlink ?

To Michael : I have not followed Hristo track as he told me via private
email that he would take care of it though not right now (that is use
the dispatcher). And also because Dan told he was not keen with the use
of the dispatcher for it. I don't know what is best and I don't want to
predate his work (his talks on this ML are the genesis of my own work).
Though I believe it cannot hurt to follow different tracks.


Thanks for all your comments
Alban
Index: src/nm-device.c
===================================================================
--- src/nm-device.c	(révision 3712)
+++ src/nm-device.c	(copie de travail)
@@ -1367,7 +1367,7 @@
 
 		/* Remove any previous IP4 Config from the named manager */
 		named_mgr = nm_named_manager_get ();
-		nm_named_manager_remove_ip4_config (named_mgr, priv->ip4_config);
+		nm_named_manager_remove_ip4_config (named_mgr, priv->ip4_config, nm_device_get_iface (self));
 		g_object_unref (named_mgr);
 
 		g_object_unref (priv->ip4_config);
Index: src/named-manager/nm-named-manager.c
===================================================================
--- src/named-manager/nm-named-manager.c	(révision 3712)
+++ src/named-manager/nm-named-manager.c	(copie de travail)
@@ -41,6 +41,7 @@
 #include "nm-ip4-config.h"
 #include "nm-utils.h"
 #include "NetworkManagerSystem.h"
+#include "NetworkManagerUtils.h"
 #include "nm-dbus-manager.h"
 
 #ifdef HAVE_SELINUX
@@ -51,6 +52,12 @@
 #define RESOLV_CONF "/etc/resolv.conf"
 #endif
 
+#ifndef RESOLVCONF
+#define RESOLVCONF "resolvconf"
+#define RESOLVCONF_ETC "/etc/resolvconf/run/resolv.conf"
+#define RESOLVCONF_BIN "/sbin/resolvconf"
+#endif
+
 #ifndef NAMED_DBUS_SERVICE
 #define NAMED_DBUS_SERVICE "com.redhat.named"
 #define NAMED_DBUS_INTERFACE "com.redhat.named"
@@ -426,6 +433,111 @@
 	return *error ? FALSE : TRUE;
 }
 
+static char * 
+compute_resolv_conf (NMNamedManager *mgr)
+{
+	NMNamedManagerPrivate *priv;
+	char *searches = NULL, *domain = NULL;
+	guint32 num_domains, num_searches, i;
+	NMIP4Config *composite;
+	GSList *iter;
+	GString *str;
+
+	priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
+
+
+	/* Construct the composite config from all the currently active IP4Configs */
+	composite = nm_ip4_config_new ();
+
+	if (priv->vpn_config)
+		merge_one_ip4_config (composite, priv->vpn_config);
+
+	if (priv->device_config)
+		merge_one_ip4_config (composite, priv->device_config);
+
+	for (iter = priv->configs; iter; iter = g_slist_next (iter)) {
+		NMIP4Config *config = NM_IP4_CONFIG (iter->data);
+
+		if ((config == priv->vpn_config) || (config == priv->device_config))
+			continue;
+
+		merge_one_ip4_config (composite, config);
+	}
+
+	/* ISC DHCP 3.1 provides support for the domain-search option. This is the
+	 * correct way for a DHCP server to provide a domain search list. Wedging
+	 * multiple domains into the domain-name option is a horrible hack.
+	 *
+	 * So, we handle it like this (as proposed by Andrew Pollock at
+	 * http://bugs.debian.org/465158):
+	 *
+	 * - if the domain-search option is present in the data received via DHCP,
+	 *   use it in favour of the domain-name option for setting the search
+	 *   directive in /etc/resolv.conf
+	 *
+	 * - if the domain-name option is present in the data received via DHCP, use
+	 *   it to set the domain directive in /etc/resolv.conf
+	 *   (this is handled in compute_domain() below)
+	 *
+	 * - if only the domain-name option is present in the data received via DHCP
+	 *   (and domain-search is not), for backwards compatibility, set the search
+	 *   directive in /etc/resolv.conf to the specified domain names
+	 */
+
+	num_domains = nm_ip4_config_get_num_domains (composite);
+	num_searches = nm_ip4_config_get_num_searches (composite);
+
+	if ((num_searches == 0)  && (num_domains > 0)) {
+		str = g_string_new ("search");
+		for (i = 0; i < num_domains; i++) {
+			g_string_append_c (str, ' ');
+			g_string_append (str, nm_ip4_config_get_domain (composite, i));		
+		}
+
+		g_string_append (str, "\n\n");
+		searches = g_string_free (str, FALSE);
+	} else if (num_searches > 0) {
+		str = g_string_new ("search");
+		for (i = 0; i < num_searches; i++) {
+			g_string_append_c (str, ' ');
+			g_string_append (str, nm_ip4_config_get_search (composite, i));		
+		}
+
+		g_string_append (str, "\n\n");
+		searches = g_string_free (str, FALSE);
+	}
+
+	/* Compute resolv.conf domain */
+	if (num_domains > 0) {
+		str = g_string_new ("domain ");
+		g_string_append (str, nm_ip4_config_get_domain (composite, 0));
+		g_string_append (str, "\n\n");
+
+		domain = g_string_free (str, FALSE);
+	}
+
+	str = g_string_new("# generated by NetworkManager, do not edit!\n\n");
+	if (mgr->priv->use_named == TRUE) {
+		/* Using caching-nameserver & local DNS */
+		g_string_append(str , "; Use a local caching nameserver controlled by NetworkManager\n\n");
+		g_string_append(str, searches ? searches : "");
+		g_string_append(str, "\nnameserver 127.0.0.1\n");
+
+	} else {
+		/* Using glibc resolver */
+		char *nameservers = compute_nameservers (composite);
+
+		g_string_append(str, domain ? domain : "");
+		g_string_append(str, searches ? searches : "");
+		g_string_append(str, nameservers ? nameservers : "");
+		g_free (nameservers);
+	}
+
+	g_free (domain);
+	g_free (searches);
+	return g_string_free(str, FALSE);
+}
+
 static const char *
 get_domain_for_config (NMNamedManager *mgr, NMIP4Config *config, gboolean *dflt)
 {
@@ -765,9 +877,13 @@
 gboolean
 nm_named_manager_add_ip4_config (NMNamedManager *mgr,
                                  NMIP4Config *config,
-                                 NMNamedIPConfigType cfg_type)
+                                 NMNamedIPConfigType cfg_type,
+				 const char *iface)
 {
 	NMNamedManagerPrivate *priv;
+	char *resolvconf_cmd;
+	gsize b_written;
+	GString *str;
 	GError *error = NULL;
 
 	g_return_val_if_fail (mgr != NULL, FALSE);
@@ -801,13 +917,31 @@
 		g_error_free (error);
 	}
 
+	if (g_find_program_in_path(RESOLVCONF) != NULL ) {
+		if (g_file_test(RESOLV_CONF, G_FILE_TEST_IS_SYMLINK) && !strcmp(g_filename_to_utf8(g_file_read_link(RESOLV_CONF, NULL), -1, NULL, &b_written, NULL), RESOLVCONF_ETC)) {
+			str = g_string_new("/bin/sh -c \"/bin/echo -e ");
+			g_string_append(str, g_shell_quote(compute_resolv_conf(mgr)));
+			g_string_append(str, " | ");
+			g_string_append(str, RESOLVCONF_BIN);
+			g_string_append(str, " -a ");
+			g_string_append(str, iface);
+			g_string_append(str, "\"");
+			resolvconf_cmd= g_string_free(str, FALSE);
+			nm_warning("Spawning resolvconf : '%s'", resolvconf_cmd);
+			nm_spawn_process(resolvconf_cmd);
+			nm_system_update_dns ();
+		}
+	}
+
 	return TRUE;
 }
 
 gboolean
-nm_named_manager_remove_ip4_config (NMNamedManager *mgr, NMIP4Config *config)
+nm_named_manager_remove_ip4_config (NMNamedManager *mgr, NMIP4Config *config, const char *iface)
 {
 	NMNamedManagerPrivate *priv;
+	char *resolvconf_cmd;
+	gsize b_written;
 	GError *error = NULL;
 
 	g_return_val_if_fail (mgr != NULL, FALSE);
@@ -848,6 +982,16 @@
 			g_error_free (error);
 	}
 
+	if (g_find_program_in_path(RESOLVCONF) != NULL) {
+		if (g_file_test(RESOLV_CONF, G_FILE_TEST_IS_SYMLINK) && !strcmp(g_filename_to_utf8(g_file_read_link(RESOLV_CONF, NULL), -1, NULL, &b_written, NULL), RESOLVCONF_ETC)) {
+			resolvconf_cmd = g_strdup_printf("%s -d %s", RESOLVCONF_BIN, iface);
+			nm_warning("Spawning resolvconf : '%s'", resolvconf_cmd);
+			nm_spawn_process(resolvconf_cmd);
+		}
+		nm_system_update_dns ();
+	}
+
+
 	return TRUE;
 }
 
Index: src/named-manager/nm-named-manager.h
===================================================================
--- src/named-manager/nm-named-manager.h	(révision 3712)
+++ src/named-manager/nm-named-manager.h	(copie de travail)
@@ -71,9 +71,10 @@
 
 gboolean nm_named_manager_add_ip4_config (NMNamedManager *mgr,
                                           NMIP4Config *config,
-                                          NMNamedIPConfigType cfg_type);
+                                          NMNamedIPConfigType cfg_type,
+					  const char *iface);
 
-gboolean nm_named_manager_remove_ip4_config (NMNamedManager *mgr, NMIP4Config *config);
+gboolean nm_named_manager_remove_ip4_config (NMNamedManager *mgr, NMIP4Config *config, const char *iface);
 
 G_END_DECLS
 

Index: src/NetworkManagerSystem.c
===================================================================
--- src/NetworkManagerSystem.c	(révision 3712)
+++ src/NetworkManagerSystem.c	(copie de travail)
@@ -378,7 +378,7 @@
 
 out:
 	named_mgr = nm_named_manager_get ();
-	nm_named_manager_add_ip4_config (named_mgr, config, NM_NAMED_IP_CONFIG_TYPE_VPN);
+	nm_named_manager_add_ip4_config (named_mgr, config, NM_NAMED_IP_CONFIG_TYPE_VPN, iface);
 	g_object_unref (named_mgr);
 
 	return TRUE;
@@ -399,7 +399,7 @@
 	g_return_val_if_fail (config != NULL, FALSE);
 
 	named_mgr = nm_named_manager_get ();
-	nm_named_manager_remove_ip4_config (named_mgr, config);
+	nm_named_manager_remove_ip4_config (named_mgr, config, iface);
 	g_object_unref (named_mgr);
 
 	return TRUE;

Index: src/backends/NetworkManagerDebian.c
===================================================================
--- src/backends/NetworkManagerDebian.c	(révision 3712)
+++ src/backends/NetworkManagerDebian.c	(copie de travail)
@@ -43,6 +43,8 @@
 #include "interface_parser.h"
 #include "nm-utils.h"
 
+#define RESOLVCONF "resolvconf"
+
 /*
  * nm_system_init
  *
@@ -80,14 +82,16 @@
 /*
  * nm_system_update_dns
  *
- * Make glibc/nscd aware of any changes to the resolv.conf file by
- * restarting nscd.
+ * Invalidate the nscd host cache, if it exists, since
+ * we changed resolv.conf.
  *
  */
 void nm_system_update_dns (void)
 {
-	nm_spawn_process ("/usr/sbin/invoke-rc.d nscd restart");
-
+	if (g_file_test ("/usr/sbin/nscd", G_FILE_TEST_IS_EXECUTABLE)) {
+		nm_info ("Clearing nscd hosts cache.");
+		nm_spawn_process ("/usr/sbin/nscd -i hosts");
+	}
 }
 
 /*
@@ -127,6 +131,9 @@
  */
 gboolean nm_system_should_modify_resolv_conf (void)
 {
-	return TRUE;
+	if (g_find_program_in_path(RESOLVCONF) != NULL)
+		return FALSE;
+	else
+		return TRUE;
 }
 


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