[CFR] reflect resolv.conf update to running application
Hajimu UMEMOTO
ume at FreeBSD.org
Sat Aug 20 11:11:24 GMT 2005
Hi,
Our resolver reads resolv.conf once, and never re-read it. Recent
OpenBSD changed to re-read resolv.conf when it is updated. I believe
it is useful specially for mobile environment. So, I made a patch for
our resolver. Please review it.
Index: lib/libc/net/getaddrinfo.c
diff -u -p lib/libc/net/getaddrinfo.c.orig lib/libc/net/getaddrinfo.c
--- lib/libc/net/getaddrinfo.c.orig Sat May 21 22:46:37 2005
+++ lib/libc/net/getaddrinfo.c Sat May 21 23:20:27 2005
@@ -2443,7 +2443,7 @@ res_searchN(name, target)
int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
char abuf[MAXDNAME];
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ if (_res_init() == -1) {
h_errno = NETDB_INTERNAL;
return (-1);
}
Index: lib/libc/net/gethostbydns.c
diff -u -p lib/libc/net/gethostbydns.c.orig lib/libc/net/gethostbydns.c
--- lib/libc/net/gethostbydns.c.orig Sat May 21 22:46:37 2005
+++ lib/libc/net/gethostbydns.c Sat May 21 23:20:27 2005
@@ -538,10 +538,6 @@ _dns_gethostbyaddr(void *rval, void *cb_
he = va_arg(ap, struct hostent *);
hed = va_arg(ap, struct hostent_data *);
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- h_errno = NETDB_INTERNAL;
- return NS_UNAVAIL;
- }
switch (af) {
case AF_INET:
(void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
Index: lib/libc/net/gethostnamadr.c
diff -u -p lib/libc/net/gethostnamadr.c.orig lib/libc/net/gethostnamadr.c
--- lib/libc/net/gethostnamadr.c.orig Sat May 21 22:46:37 2005
+++ lib/libc/net/gethostnamadr.c Sat May 21 23:20:27 2005
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/lib/libc/net/get
#include <resolv.h> /* XXX hack for _res */
#include "un-namespace.h"
#include "netdb_private.h"
+#include "res_config.h"
extern int _ht_gethostbyname(void *, void *, va_list);
extern int _dns_gethostbyname(void *, void *, va_list);
@@ -264,7 +265,7 @@ gethostbyaddr_r(const char *addr, int le
{ 0 }
};
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ if (_res_init() == -1) {
h_errno = NETDB_INTERNAL;
return -1;
}
Index: lib/libc/net/getnetbydns.c
diff -u -p lib/libc/net/getnetbydns.c.orig lib/libc/net/getnetbydns.c
--- lib/libc/net/getnetbydns.c.orig Sat May 21 22:46:37 2005
+++ lib/libc/net/getnetbydns.c Sat May 21 23:20:27 2005
@@ -304,6 +304,10 @@ _dns_getnetbyaddr(void *rval, void *cb_d
netbr[1], netbr[0]);
break;
}
+ if (_res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return NS_UNAVAIL;
+ }
if ((buf = malloc(sizeof(*buf))) == NULL) {
h_errno = NETDB_INTERNAL;
return NS_NOTFOUND;
Index: lib/libc/net/name6.c
diff -u -p lib/libc/net/name6.c.orig lib/libc/net/name6.c
--- lib/libc/net/name6.c.orig Sat May 21 22:46:38 2005
+++ lib/libc/net/name6.c Sat May 21 23:20:27 2005
@@ -121,6 +121,7 @@ __FBSDID("$FreeBSD: src/lib/libc/net/nam
#include <unistd.h>
#include "un-namespace.h"
#include "netdb_private.h"
+#include "res_config.h"
#ifndef _PATH_HOSTS
#define _PATH_HOSTS "/etc/hosts"
@@ -1810,11 +1811,9 @@ _dns_ghbyaddr(void *rval, void *cb_data,
return NS_NOTFOUND;
}
- if ((_res.options & RES_INIT) == 0) {
- if (res_init() < 0) {
- *errp = h_errno;
- return NS_UNAVAIL;
- }
+ if (_res_init() < 0) {
+ *errp = h_errno;
+ return NS_UNAVAIL;
}
memset(&hbuf, 0, sizeof(hbuf));
hbuf.h_name = NULL;
Index: lib/libc/net/res_config.h
diff -u lib/libc/net/res_config.h.orig lib/libc/net/res_config.h
--- lib/libc/net/res_config.h.orig Sat Mar 23 08:41:54 2002
+++ lib/libc/net/res_config.h Sat May 21 23:20:27 2005
@@ -8,3 +8,5 @@
#define MULTI_PTRS_ARE_ALIASES 1 /* fold multiple PTR records into aliases */
#define CHECK_SRVR_ADDR 1 /* confirm that the server requested sent the reply */
#define BIND_UPDATE 1 /* update support */
+
+int _res_init(void);
Index: lib/libc/net/res_init.c
diff -u -p lib/libc/net/res_init.c.orig lib/libc/net/res_init.c
--- lib/libc/net/res_init.c.orig Thu Feb 26 06:03:45 2004
+++ lib/libc/net/res_init.c Sat May 21 23:20:27 2005
@@ -78,11 +78,13 @@ __FBSDID("$FreeBSD: src/lib/libc/net/res
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <ctype.h>
+#include <errno.h>
#include <limits.h>
#include <resolv.h>
#include <stdio.h>
@@ -100,6 +102,7 @@ __FBSDID("$FreeBSD: src/lib/libc/net/res
#undef h_errno
extern int h_errno;
+static void res_readconf(void);
static void res_setoptions(char *, char *);
#ifdef RESOLVSORT
@@ -112,6 +115,18 @@ static u_int32_t net_mask(struct in_addr
# define isascii(c) (!(c & 0200))
#endif
+#define timespecclear(tvp) ((tvp)->tv_sec = (tvp)->tv_nsec = 0)
+#define timespeccmp(tvp, uvp, cmp) \
+ (((tvp)->tv_sec == (uvp)->tv_sec) ? \
+ ((tvp)->tv_nsec cmp (uvp)->tv_nsec) : \
+ ((tvp)->tv_sec cmp (uvp)->tv_sec))
+
+struct __res_conf_private {
+ struct timespec mtimespec;
+};
+
+static struct __res_conf_private *___res_conf_private(void);
+
/*
* Check structure for failed per-thread allocations.
*/
@@ -119,6 +134,7 @@ static struct res_per_thread {
struct __res_state res_state;
struct __res_state_ext res_state_ext;
struct __res_send_private res_send_private;
+ struct __res_conf_private res_conf_private;
int h_errno;
} _res_per_thread_bogus = { .res_send_private = { .s = -1 } }; /* socket */
@@ -146,21 +162,8 @@ static struct res_per_thread {
int
res_init()
{
- FILE *fp;
struct __res_send_private *rsp;
- char *cp, **pp;
- int n;
- char buf[MAXDNAME];
- int nserv = 0; /* number of nameserver records read from file */
- int haveenv = 0;
- int havesearch = 0;
-#ifdef RESOLVSORT
- int nsort = 0;
- char *net;
-#endif
-#ifndef RFC1535
- int dots;
-#endif
+ char *cp;
/*
* If allocation of memory for this thread's resolver has failed,
@@ -208,6 +211,37 @@ res_init()
if (!_res.id)
_res.id = res_randomid();
+ _res.pfcode = 0;
+ res_readconf();
+
+ if (issetugid())
+ _res.options |= RES_NOALIASES;
+ else if ((cp = getenv("RES_OPTIONS")) != NULL)
+ res_setoptions(cp, "env");
+ _res.options |= RES_INIT;
+ return (0);
+}
+
+static void
+res_readconf()
+{
+ struct __res_conf_private *rcp;
+ FILE *fp;
+ char *cp, **pp;
+ int n;
+ char buf[MAXDNAME];
+ int nserv = 0; /* number of nameserver records read from file */
+ int haveenv = 0;
+ int havesearch = 0;
+#ifdef RESOLVSORT
+ int nsort = 0;
+ char *net;
+#endif
+#ifndef RFC1535
+ int dots;
+#endif
+ struct stat sb;
+
#ifdef USELOOPBACK
_res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
#else
@@ -220,7 +254,6 @@ res_init()
memcpy(&_res_ext.nsaddr, &_res.nsaddr, _res.nsaddr.sin_len);
_res.nscount = 1;
_res.ndots = 1;
- _res.pfcode = 0;
/* Allow user to override the local domain definition */
if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
@@ -262,7 +295,10 @@ res_init()
(line[sizeof(name) - 1] == ' ' || \
line[sizeof(name) - 1] == '\t'))
+ rcp = ___res_conf_private();
if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+ if (fstat(fileno(fp), &sb) == 0)
+ rcp->mtimespec = sb.st_mtimespec;
/* read the config file */
while (fgets(buf, sizeof(buf), fp) != NULL) {
/* skip comments */
@@ -396,11 +432,11 @@ res_init()
if (inet_aton(net, &a)) {
_res.sort_list[nsort].mask = a.s_addr;
} else {
- _res.sort_list[nsort].mask =
+ _res.sort_list[nsort].mask =
net_mask(_res.sort_list[nsort].addr);
}
} else {
- _res.sort_list[nsort].mask =
+ _res.sort_list[nsort].mask =
net_mask(_res.sort_list[nsort].addr);
}
_res_ext.sort_list[nsort].af = AF_INET;
@@ -465,13 +501,14 @@ res_init()
continue;
}
}
- if (nserv > 1)
+ if (nserv > 1)
_res.nscount = nserv;
#ifdef RESOLVSORT
_res.nsort = nsort;
#endif
(void) fclose(fp);
- }
+ } else
+ timespecclear(&rcp->mtimespec);
if (_res.defdname[0] == 0 &&
gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
(cp = strchr(buf, '.')) != NULL)
@@ -507,12 +544,27 @@ res_init()
#endif
#endif /* !RFC1535 */
}
+}
- if (issetugid())
- _res.options |= RES_NOALIASES;
- else if ((cp = getenv("RES_OPTIONS")) != NULL)
- res_setoptions(cp, "env");
- _res.options |= RES_INIT;
+int
+_res_init(void)
+{
+ struct __res_conf_private *rcp;
+ struct stat sb;
+
+ if ((_res.options & RES_INIT) == 0)
+ return (res_init());
+
+ if (stat(_PATH_RESCONF, &sb) == -1) {
+ /*
+ * Lost the file, in chroot?
+ * Don' trash settings
+ */
+ return (0);
+ }
+ rcp = ___res_conf_private();
+ if (timespeccmp(&sb.st_mtimespec, &rcp->mtimespec, !=))
+ res_readconf();
return (0);
}
@@ -629,6 +681,7 @@ struct __res_state _res;
#endif
struct __res_state_ext _res_ext;
static struct __res_send_private _res_send_private = { .s = -1 }; /* socket */
+static struct __res_conf_private _res_conf_private;
static thread_key_t res_key;
static once_t res_init_once = ONCE_INITIALIZER;
@@ -697,6 +750,14 @@ ___res_send_private(void)
if (thr_main() != 0)
return (&_res_send_private);
return (&allocate_res()->res_send_private);
+}
+
+struct __res_conf_private *
+___res_conf_private(void)
+{
+ if (thr_main() != 0)
+ return (&_res_conf_private);
+ return (&allocate_res()->res_conf_private);
}
int *
Index: lib/libc/net/res_query.c
diff -u -p lib/libc/net/res_query.c.orig lib/libc/net/res_query.c
--- lib/libc/net/res_query.c.orig Sat May 21 22:46:39 2005
+++ lib/libc/net/res_query.c Sat May 21 23:20:27 2005
@@ -200,7 +200,7 @@ res_search(name, class, type, answer, an
int trailing_dot, ret, saved_herrno;
int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ if (_res_init() == -1) {
h_errno = NETDB_INTERNAL;
return (-1);
}
Index: lib/libc/net/res_update.c
diff -u -p lib/libc/net/res_update.c.orig lib/libc/net/res_update.c
--- lib/libc/net/res_update.c.orig Mon Sep 16 01:51:09 2002
+++ lib/libc/net/res_update.c Sat May 21 23:20:27 2005
@@ -36,6 +36,8 @@ __FBSDID("$FreeBSD: src/lib/libc/net/res
#include <stdlib.h>
#include <string.h>
+#include "res_config.h"
+
/*
* Separate a linked list of records into groups so that all records
* in a group will belong to a single zone on the nameserver.
@@ -84,7 +86,7 @@ res_update(ns_updrec *rrecp_in) {
u_int16_t dlen, class, qclass, type, qtype;
u_int32_t ttl;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ if (_res_init() == -1) {
h_errno = NETDB_INTERNAL;
return (-1);
}
Sincerely,
--
Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan
ume at mahoroba.org ume@{,jp.}FreeBSD.org
http://www.imasy.org/~ume/
More information about the freebsd-arch
mailing list