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