summary refs log tree commit diff
path: root/src/dns-manager
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2012-06-29 20:12:44 +0200
committerMichael Biebl <biebl@debian.org>2012-06-29 20:12:44 +0200
commit867254ea7c2b193fecf8cd36cc6e5dc53c290d92 (patch)
tree7c698b403882736ab70c3efd524c3460f08c391c /src/dns-manager
parentde06e5715e780baade318f3490ac7a4c9ce84e32 (diff)
Imported Upstream version 0.9.5.95 upstream/0.9.5.95
Diffstat (limited to 'src/dns-manager')
-rw-r--r--src/dns-manager/Makefile.am2
-rw-r--r--src/dns-manager/Makefile.in14
-rw-r--r--src/dns-manager/nm-dns-manager.c161
-rw-r--r--src/dns-manager/nm-dns-manager.h4
-rw-r--r--src/dns-manager/nm-dns-plugin.c9
5 files changed, 127 insertions, 63 deletions
diff --git a/src/dns-manager/Makefile.am b/src/dns-manager/Makefile.am
index 331f85c4..fd31b140 100644
--- a/src/dns-manager/Makefile.am
+++ b/src/dns-manager/Makefile.am
@@ -1,5 +1,6 @@
 INCLUDES = \
 	-I${top_srcdir}/src/logging \
+	-I${top_srcdir}/src/posix-signals \
 	-I${top_srcdir}/libnm-util \
 	-I${top_builddir}/libnm-util \
 	-I${top_srcdir}/src \
@@ -28,6 +29,7 @@ libdns_manager_la_CPPFLAGS = \
 
 libdns_manager_la_LIBADD = \
 	$(top_builddir)/src/logging/libnm-logging.la \
+	$(top_builddir)/src/posix-signals/libnm-posix-signals.la \
 	$(LIBNL_LIBS) \
 	$(DBUS_LIBS) \
 	$(GLIB_LIBS)
diff --git a/src/dns-manager/Makefile.in b/src/dns-manager/Makefile.in
index c9b8b0b3..ddcce666 100644
--- a/src/dns-manager/Makefile.in
+++ b/src/dns-manager/Makefile.in
@@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
 	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
 	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
 	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
-	$(top_srcdir)/configure.ac
+	$(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -58,6 +58,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES)
 am__DEPENDENCIES_1 =
 libdns_manager_la_DEPENDENCIES =  \
 	$(top_builddir)/src/logging/libnm-logging.la \
+	$(top_builddir)/src/posix-signals/libnm-posix-signals.la \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1)
 am_libdns_manager_la_OBJECTS = libdns_manager_la-nm-dns-manager.lo \
@@ -172,6 +173,10 @@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
 INTLTOOL_MERGE = @INTLTOOL_MERGE@
 INTLTOOL_PERL = @INTLTOOL_PERL@
 INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
 INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
 INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
 INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
@@ -267,6 +272,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
+VAPIGEN = @VAPIGEN@
+VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
+VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
 XGETTEXT_015 = @XGETTEXT_015@
@@ -305,6 +313,8 @@ htmldir = @htmldir@
 includedir = @includedir@
 infodir = @infodir@
 install_sh = @install_sh@
+intltool__v_merge_options_ = @intltool__v_merge_options_@
+intltool__v_merge_options_0 = @intltool__v_merge_options_0@
 libdir = @libdir@
 libexecdir = @libexecdir@
 localedir = @localedir@
@@ -327,6 +337,7 @@ top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = \
 	-I${top_srcdir}/src/logging \
+	-I${top_srcdir}/src/posix-signals \
 	-I${top_srcdir}/libnm-util \
 	-I${top_builddir}/libnm-util \
 	-I${top_srcdir}/src \
@@ -354,6 +365,7 @@ libdns_manager_la_CPPFLAGS = \
 
 libdns_manager_la_LIBADD = \
 	$(top_builddir)/src/logging/libnm-logging.la \
+	$(top_builddir)/src/posix-signals/libnm-posix-signals.la \
 	$(LIBNL_LIBS) \
 	$(DBUS_LIBS) \
 	$(GLIB_LIBS)
diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c
index 6272e374..38ef08ea 100644
--- a/src/dns-manager/nm-dns-manager.c
+++ b/src/dns-manager/nm-dns-manager.c
@@ -16,7 +16,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2004 - 2005 Colin Walters <walters@redhat.com>
- * Copyright (C) 2004 - 2011 Red Hat, Inc.
+ * Copyright (C) 2004 - 2012 Red Hat, Inc.
  * Copyright (C) 2005 - 2008 Novell, Inc.
  *   and others
  */
@@ -42,6 +42,7 @@
 #include "nm-logging.h"
 #include "backends/nm-backend.h"
 #include "NetworkManagerUtils.h"
+#include "nm-posix-signals.h"
 
 #include "nm-dns-plugin.h"
 #include "nm-dns-dnsmasq.h"
@@ -61,6 +62,8 @@ G_DEFINE_TYPE(NMDnsManager, nm_dns_manager, G_TYPE_OBJECT)
                                        NM_TYPE_DNS_MANAGER, \
                                        NMDnsManagerPrivate))
 
+#define HASH_LEN 20
+
 typedef struct {
 	gboolean disposed;
 
@@ -70,14 +73,10 @@ typedef struct {
 	NMIP6Config *ip6_device_config;
 	GSList *configs;
 	char *hostname;
+	guint updates_queue;
 
-	/* poor man's hash; we assume that the IP4 config object won't change
-	 * after it's given to us, which is (at this time) a fair assumption. So
-	 * we track the order of the currently applied IP configs and if they
-	 * haven't changed we don't need to rewrite resolv.conf.
-	 */
-	#define HLEN 6
-	gpointer hash[HLEN];
+	guint8 hash[HASH_LEN];  /* SHA1 hash of current DNS config */
+	guint8 prev_hash[HASH_LEN];  /* Hash when begin_updates() was called */
 
 	GSList *plugins;
 
@@ -218,6 +217,12 @@ netconfig_child_setup (gpointer user_data G_GNUC_UNUSED)
 {
 	pid_t pid = getpid ();
 	setpgid (pid, pid);
+
+	/*
+	 * We blocked signals in main(). We need to restore original signal
+	 * mask for netconfig here so that it can receive signals.
+	 */
+	nm_unblock_posix_signals (NULL);
 }
 
 static GPid
@@ -529,34 +534,43 @@ out:
 }
 
 static void
-compute_hash (NMDnsManager *self, gpointer *hash)
+compute_hash (NMDnsManager *self, guint8 buffer[HASH_LEN])
 {
 	NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self);
-	gpointer check[HLEN];
+	GChecksum *sum;
 	GSList *iter;
-	int i = 0;
+	gsize len = HASH_LEN;
 
-	memset (check, 0, sizeof (check));
+	sum = g_checksum_new (G_CHECKSUM_SHA1);
+	g_assert (len == g_checksum_type_get_length (G_CHECKSUM_SHA1));
 
 	if (priv->ip4_vpn_config)
-		check[i++] = priv->ip4_vpn_config;
+		nm_ip4_config_hash (priv->ip4_vpn_config, sum, TRUE);
 	if (priv->ip4_device_config)
-		check[i++] = priv->ip4_device_config;
+		nm_ip4_config_hash (priv->ip4_device_config, sum, TRUE);
 
 	if (priv->ip6_vpn_config)
-		check[i++] = priv->ip6_vpn_config;
+		nm_ip6_config_hash (priv->ip6_vpn_config, sum, TRUE);
 	if (priv->ip6_device_config)
-		check[i++] = priv->ip6_device_config;
+		nm_ip6_config_hash (priv->ip6_device_config, sum, TRUE);
 
-	/* Add two more "other" configs if any exist */
-	for (iter = priv->configs; iter && i < HLEN; iter = g_slist_next (iter)) {
-		if (   (iter->data != priv->ip4_vpn_config)
-		    && (iter->data != priv->ip4_device_config)
-		    && (iter->data != priv->ip6_vpn_config)
-		    && (iter->data != priv->ip6_device_config))
-			check[i++] = iter->data;
+	/* add any other configs we know about */
+	for (iter = priv->configs; iter; iter = g_slist_next (iter)) {
+		if (   (iter->data == priv->ip4_vpn_config)
+		    && (iter->data == priv->ip4_device_config)
+		    && (iter->data == priv->ip6_vpn_config)
+		    && (iter->data == priv->ip6_device_config))
+			continue;
+
+		if (NM_IS_IP4_CONFIG (iter->data))
+			nm_ip4_config_hash (NM_IP4_CONFIG (iter->data), sum, TRUE);
+		else if (NM_IS_IP6_CONFIG (iter->data))
+			nm_ip6_config_hash (NM_IP6_CONFIG (iter->data), sum, TRUE);
 	}
-	memcpy (hash, check, sizeof (check));
+
+	memset (buffer, 0, sizeof (buffer));
+	g_checksum_get_digest (sum, buffer, &len);
+	g_checksum_free (sum);
 }
 
 static gboolean
@@ -581,6 +595,8 @@ update_dns (NMDnsManager *self,
 
 	priv = NM_DNS_MANAGER_GET_PRIVATE (self);
 
+	nm_log_dbg (LOGD_DNS, "updating resolv.conf");
+
 	if (iface && (iface != priv->last_iface)) {
 		g_free (priv->last_iface);
 		priv->last_iface = g_strdup (iface);
@@ -784,23 +800,6 @@ plugin_failed (NMDnsPlugin *plugin, gpointer user_data)
 	}
 }
 
-static gboolean
-config_changed (NMDnsManager *self)
-{
-	NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self);
-	gpointer check[HLEN];
-
-	/* We only store HLEN configs; so if there are actually more than that,
-	 * we have to assume that the config has changed.
-	 */
-	if (g_slist_length (priv->configs) > HLEN)
-		return TRUE;
-
-	/* Otherwise return TRUE if the configuration has changed */
-	compute_hash (self, check);
-	return memcmp (check, priv->hash, sizeof (check)) ? TRUE : FALSE;
-}
-
 gboolean
 nm_dns_manager_add_ip4_config (NMDnsManager *mgr,
                                const char *iface,
@@ -831,10 +830,7 @@ nm_dns_manager_add_ip4_config (NMDnsManager *mgr,
 	if (!g_slist_find (priv->configs, config))
 		priv->configs = g_slist_append (priv->configs, g_object_ref (config));
 
-	if (!config_changed (mgr))
-		return TRUE;
-
-	if (!update_dns (mgr, iface, FALSE, &error)) {
+	if (!priv->updates_queue && !update_dns (mgr, iface, FALSE, &error)) {
 		nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s",
 		             error ? error->code : -1,
 		             error && error->message ? error->message : "(unknown)");
@@ -871,10 +867,7 @@ nm_dns_manager_remove_ip4_config (NMDnsManager *mgr,
 
 	g_object_unref (config);
 
-	if (!config_changed (mgr))
-		return TRUE;
-
-	if (!update_dns (mgr, iface, FALSE, &error)) {
+	if (!priv->updates_queue && !update_dns (mgr, iface, FALSE, &error)) {
 		nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s",
 		             error ? error->code : -1,
 		             error && error->message ? error->message : "(unknown)");
@@ -901,8 +894,6 @@ nm_dns_manager_add_ip6_config (NMDnsManager *mgr,
 
 	switch (cfg_type) {
 	case NM_DNS_IP_CONFIG_TYPE_VPN:
-		/* FIXME: not quite yet... */
-		g_return_val_if_fail (cfg_type != NM_DNS_IP_CONFIG_TYPE_VPN, FALSE);
 		priv->ip6_vpn_config = config;
 		break;
 	case NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE:
@@ -916,10 +907,7 @@ nm_dns_manager_add_ip6_config (NMDnsManager *mgr,
 	if (!g_slist_find (priv->configs, config))
 		priv->configs = g_slist_append (priv->configs, g_object_ref (config));
 
-	if (!config_changed (mgr))
-		return TRUE;
-
-	if (!update_dns (mgr, iface, FALSE, &error)) {
+	if (!priv->updates_queue && !update_dns (mgr, iface, FALSE, &error)) {
 		nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s",
 		             error ? error->code : -1,
 		             error && error->message ? error->message : "(unknown)");
@@ -956,10 +944,7 @@ nm_dns_manager_remove_ip6_config (NMDnsManager *mgr,
 
 	g_object_unref (config);	
 
-	if (!config_changed (mgr))
-		return TRUE;
-
-	if (!update_dns (mgr, iface, FALSE, &error)) {
+	if (!priv->updates_queue && !update_dns (mgr, iface, FALSE, &error)) {
 		nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s",
 		             error ? error->code : -1,
 		             error && error->message ? error->message : "(unknown)");
@@ -997,7 +982,7 @@ nm_dns_manager_set_hostname (NMDnsManager *mgr,
 	 * wants one.  But hostname changes are system-wide and *not* tied to a
 	 * specific interface, so netconfig can't really handle this.  Fake it.
 	 */
-	if (!update_dns (mgr, priv->last_iface, FALSE, &error)) {
+	if (!priv->updates_queue && !update_dns (mgr, priv->last_iface, FALSE, &error)) {
 		nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s",
 		             error ? error->code : -1,
 		             error && error->message ? error->message : "(unknown)");
@@ -1005,6 +990,58 @@ nm_dns_manager_set_hostname (NMDnsManager *mgr,
 	}
 }
 
+void
+nm_dns_manager_begin_updates (NMDnsManager *mgr, const char *func)
+{
+	NMDnsManagerPrivate *priv;
+
+	g_return_if_fail (mgr != NULL);
+	priv = NM_DNS_MANAGER_GET_PRIVATE (mgr);
+
+	/* Save current hash when starting a new batch */
+	if (priv->updates_queue == 0)
+		memcpy (priv->prev_hash, priv->hash, sizeof (priv->hash));
+
+	priv->updates_queue++;
+
+	nm_log_dbg (LOGD_DNS, "(%s): queueing DNS updates (%d)", func, priv->updates_queue);
+}
+
+void
+nm_dns_manager_end_updates (NMDnsManager *mgr, const char *func)
+{
+	NMDnsManagerPrivate *priv;
+	GError *error = NULL;
+	gboolean changed;
+	guint8 new[HASH_LEN];
+
+	g_return_if_fail (mgr != NULL);
+
+	priv = NM_DNS_MANAGER_GET_PRIVATE (mgr);
+	g_return_if_fail (priv->updates_queue > 0);
+
+	compute_hash (mgr, new);
+	changed = (memcmp (new, priv->prev_hash, sizeof (new)) != 0) ? TRUE : FALSE;
+	nm_log_dbg (LOGD_DNS, "(%s): DNS configuration %s", __func__, changed ? "changed" : "did not change");
+
+	priv->updates_queue--;
+	if ((priv->updates_queue > 0) || (changed == FALSE)) {
+		nm_log_dbg (LOGD_DNS, "(%s): no DNS changes to commit (%d)", func, priv->updates_queue);
+		return;
+	}
+
+	/* Commit all the outstanding changes */
+	nm_log_dbg (LOGD_DNS, "(%s): committing DNS changes (%d)", func, priv->updates_queue);
+	if (!update_dns (mgr, priv->last_iface, FALSE, &error)) {
+		nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s",
+			         error ? error->code : -1,
+			         error && error->message ? error->message : "(unknown)");
+		g_clear_error (&error);
+	}
+
+	memset (priv->prev_hash, 0, sizeof (priv->prev_hash));
+}
+
 static void
 load_plugins (NMDnsManager *self, const char **plugins)
 {
@@ -1079,8 +1116,10 @@ nm_dns_manager_error_quark (void)
 }
 
 static void
-nm_dns_manager_init (NMDnsManager *mgr)
+nm_dns_manager_init (NMDnsManager *self)
 {
+	/* Set the initial hash */
+	compute_hash (self, NM_DNS_MANAGER_GET_PRIVATE (self)->hash);
 }
 
 static void
diff --git a/src/dns-manager/nm-dns-manager.h b/src/dns-manager/nm-dns-manager.h
index 25d2a981..f559865b 100644
--- a/src/dns-manager/nm-dns-manager.h
+++ b/src/dns-manager/nm-dns-manager.h
@@ -66,6 +66,10 @@ GType nm_dns_manager_get_type (void);
 
 NMDnsManager * nm_dns_manager_get (const char **plugins);
 
+/* Allow changes to be batched together */
+void nm_dns_manager_begin_updates (NMDnsManager *mgr, const char *func);
+void nm_dns_manager_end_updates (NMDnsManager *mgr, const char *func);
+
 gboolean nm_dns_manager_add_ip4_config (NMDnsManager *mgr,
                                         const char *iface,
                                         NMIP4Config *config,
diff --git a/src/dns-manager/nm-dns-plugin.c b/src/dns-manager/nm-dns-plugin.c
index e997948e..b26f2b94 100644
--- a/src/dns-manager/nm-dns-plugin.c
+++ b/src/dns-manager/nm-dns-plugin.c
@@ -13,7 +13,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2010 - 2012 Red Hat, Inc.
  *
  */
 
@@ -27,6 +27,7 @@
 
 #include "nm-dns-plugin.h"
 #include "nm-logging.h"
+#include "nm-posix-signals.h"
 
 typedef struct {
 	gboolean disposed;
@@ -141,6 +142,12 @@ child_setup (gpointer user_data G_GNUC_UNUSED)
 	/* We are in the child process at this point */
 	pid_t pid = getpid ();
 	setpgid (pid, pid);
+
+	/*
+	 * We blocked signals in main(). We need to restore original signal
+	 * mask for DNS plugin here so that it can receive signals.
+	 */
+	nm_unblock_posix_signals (NULL);
 }
 
 GPid