Re: gethostbyname() and resolv.conf updates

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

 



On Sat, Jun 19, 2010 at 10:54 PM, Dan Williams <dcbw@xxxxxxxxxx> wrote:
>
> I'm just gonna make NM use a local caching nameserver (which means
> dnsmasq) by default at some point soon.  People that don't want it can
> turn it off.

When thinking about this, there's a rather obvious patch here that
really should have been made 5+ years ago...make it an option!  And
this actually makes some sense, e.g. if NetworkManager writes out a
static configuration, then there's no need to stat() on it since we
can assume it won't change.  (This does still screw over server admins
who hand-edit it, but...)

glibc and NetworkManager patches attached.

(I'm totally in favor of the dnsmasq approach too since the OS
desperately needs DNS caching too, but this is a simple patch that
doesn't conceptually conflict).
From 464035fa03acd915c8cf460452d0dc6c031180ca Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@xxxxxxxxxx>
Date: Fri, 18 Jun 2010 16:19:12 -0400
Subject: [PATCH] [resolv.conf] Add a new "dynamic" option which tells us to re-stat the file

Various operating system vendors have been shipping variants of a
patch which stat()s resolv.conf on every gethostbyname() call.  The
reason for this is simply that on mobile devices, nameservers can
change, and having to restart all applications and processes for this
is simply broken.  (NSCD exists, but is considered unreliable)

The intent of this patch is that in e.g. Fedora, NetworkManager's
generated resolv.conf file will include this if it gets any of its
data from DHCP.  Otherwise, it can omit the option, and processes
won't have to pay the cost of the stat() (assuming it was even a real
concern to begin with).
---
 resolv/res_init.c |    2 ++
 resolv/res_libc.c |   26 ++++++++++++++++++++++++++
 resolv/resolv.h   |    1 +
 3 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/resolv/res_init.c b/resolv/res_init.c
index 40dbe7d..7b02e49 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -535,6 +535,8 @@ res_setoptions(res_state statp, const char *options, const char *source) {
 			statp->options &= ~RES_NOIP6DOTINT;
 		} else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
 			statp->options |= RES_ROTATE;
+		} else if (!strncmp(cp, "dynamic", sizeof("dynamic") - 1)) {
+			statp->options |= RES_DYNAMIC;
 		} else if (!strncmp(cp, "no-check-names",
 				    sizeof("no-check-names") - 1)) {
 			statp->options |= RES_NOCHECKNAME;
diff --git a/resolv/res_libc.c b/resolv/res_libc.c
index 810fbc8..5dc4e3a 100644
--- a/resolv/res_libc.c
+++ b/resolv/res_libc.c
@@ -89,12 +89,38 @@ res_init(void) {
 	return (__res_vinit(&_res, 1));
 }
 
+/* If the DYNAMIC option is set, we stat the file, and see if its
+ * mtime has changed.  If so, request an initialization.
+ */
+static void
+_res_dynamic_check (void)
+{
+	static time_t last_mtime, last_check;
+	time_t now;
+	struct stat statbuf;
+  
+	time (&now);
+	if (now != last_check) {
+		last_check = now;
+		if (stat (_PATH_RESCONF, &statbuf) == 0 && last_mtime != statbuf.st_mtime) {
+			last_mtime = statbuf.st_mtime;
+			atomicinclock (lock);
+			atomicinc (__res_initstamp);
+			atomicincunlock (lock);
+		}
+	}
+}
+
 /* Initialize resp if RES_INIT is not yet set or if res_init in some other
    thread requested re-initializing.  */
 int
 __res_maybe_init (res_state resp, int preinit)
 {
 	if (resp->options & RES_INIT) {
+		if (resp->options & RES_DYNAMIC) {
+			_res_dynamic_check ();
+		}
+
 		if (__res_initstamp != resp->_u._ext.initstamp) {
 			if (resp->nscount > 0)
 				__res_iclose (resp, true);
diff --git a/resolv/resolv.h b/resolv/resolv.h
index e49c29d..8f4a202 100644
--- a/resolv/resolv.h
+++ b/resolv/resolv.h
@@ -219,6 +219,7 @@ struct res_sym {
 #define RES_SNGLKUPREOP	0x00400000	/* -"-, but open new socket for each
 					   request */
 #define RES_USE_DNSSEC	0x00800000	/* use DNSSEC using OK bit in OPT */
+#define RES_DYNAMIC	0x01000000	/* check for changes in resolv.conf */
 
 #define RES_DEFAULT	(RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT)
 
-- 
1.7.0.1

From 09551d7225637d3b809ff78ab76739cd7b9d4f63 Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@xxxxxxxxxx>
Date: Mon, 21 Jun 2010 10:33:14 -0400
Subject: [PATCH] Add "options dynamic" to generated resolv.conf

---
 src/named-manager/nm-named-manager.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/src/named-manager/nm-named-manager.c b/src/named-manager/nm-named-manager.c
index fc3b6e2..f9bb6fa 100644
--- a/src/named-manager/nm-named-manager.c
+++ b/src/named-manager/nm-named-manager.c
@@ -304,6 +304,10 @@ write_resolv_conf (FILE *f, const char *domain,
                    char **nameservers,
                    GError **error)
 {
+	/* This tells glibc that we may rewrite the file at any time,
+     * so it should check with stat()
+	 */
+	const char *options_str = "options dynamic\n";
 	char *domain_str = NULL;
 	char *searches_str = NULL;
 	char *nameservers_str = NULL;
@@ -354,8 +358,9 @@ write_resolv_conf (FILE *f, const char *domain,
 		nameservers_str = g_string_free (str, FALSE);
 	}
 
-	if (fprintf (f, "%s%s%s",
+	if (fprintf (f, "%s%s%s%s",
 	             domain_str ? domain_str : "",
+	             options_str,
 	             searches_str ? searches_str : "",
 	             nameservers_str ? nameservers_str : "") != -1)
 		retval = TRUE;
-- 
1.7.0.1

-- 
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxxx
https://admin.fedoraproject.org/mailman/listinfo/devel

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Fedora Announce]     [Fedora Kernel]     [Fedora Testing]     [Fedora Formulas]     [Fedora PHP Devel]     [Kernel Development]     [Fedora Legacy]     [Fedora Maintainers]     [Fedora Desktop]     [PAM]     [Red Hat Development]     [Gimp]     [Yosemite News]
  Powered by Linux