summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/resolv.h5
-rw-r--r--lib/libc/resolv/res_init.c22
-rw-r--r--lib/libc/resolv/res_state.c31
-rw-r--r--share/man/man5/resolver.518
4 files changed, 70 insertions, 6 deletions
diff --git a/include/resolv.h b/include/resolv.h
index e3d4fd1..78da374 100644
--- a/include/resolv.h
+++ b/include/resolv.h
@@ -176,7 +176,8 @@ struct __res_state {
int res_h_errno; /*%< last one set for this context */
int _vcsock; /*%< PRIVATE: for res_send VC i/o */
u_int _flags; /*%< PRIVATE: see below */
- u_int _pad; /*%< make _u 64 bit aligned */
+ u_short reload_period; /*%< seconds between stat(resolv.conf)*/
+ u_short _pad; /*%< make _u 64 bit aligned */
union {
/* On an 32-bit arch this means 512b total. */
char pad[72 - 4*sizeof (int) - 3*sizeof (void *)];
@@ -188,6 +189,8 @@ struct __res_state {
} _ext;
} _u;
u_char *_rnd; /*%< PRIVATE: random state */
+ struct timespec conf_mtim; /*%< mod time of loaded resolv.conf */
+ time_t conf_stat; /*%< time of last stat(resolv.conf) */
};
typedef struct __res_state *res_state;
diff --git a/lib/libc/resolv/res_init.c b/lib/libc/resolv/res_init.c
index 4dbd6d1..087e6a8 100644
--- a/lib/libc/resolv/res_init.c
+++ b/lib/libc/resolv/res_init.c
@@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/time.h>
#include <netinet/in.h>
@@ -227,6 +228,7 @@ __res_vinit(res_state statp, int preinit) {
statp->pfcode = 0;
statp->_vcsock = -1;
statp->_flags = 0;
+ statp->reload_period = 2;
statp->qhook = NULL;
statp->rhook = NULL;
statp->_u._ext.nscount = 0;
@@ -321,6 +323,22 @@ __res_vinit(res_state statp, int preinit) {
nserv = 0;
if ((fp = fopen(_PATH_RESCONF, "re")) != NULL) {
+ struct stat sb;
+ struct timespec now;
+
+ if (_fstat(fileno(fp), &sb) == 0) {
+ statp->conf_mtim = sb.st_mtim;
+ if (clock_gettime(CLOCK_MONOTONIC_FAST, &now) == 0) {
+ statp->conf_stat = now.tv_sec;
+ } else {
+ statp->conf_stat = 0;
+ }
+ } else {
+ statp->conf_mtim.tv_sec = 0;
+ statp->conf_mtim.tv_nsec = 0;
+ statp->conf_stat = 0;
+ }
+
/* read the config file */
while (fgets(buf, sizeof(buf), fp) != NULL) {
/* skip comments */
@@ -666,6 +684,10 @@ res_setoptions(res_state statp, const char *options, const char *source)
} else if (!strncmp(cp, "no-check-names",
sizeof("no-check-names") - 1)) {
statp->options |= RES_NOCHECKNAME;
+ } else if (!strncmp(cp, "reload-period:",
+ sizeof("reload-period:") - 1)) {
+ statp->reload_period = (u_short)
+ atoi(cp + sizeof("reload-period:") - 1);
}
#ifdef RES_USE_EDNS0
else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
diff --git a/lib/libc/resolv/res_state.c b/lib/libc/resolv/res_state.c
index 59c9430..87643422 100644
--- a/lib/libc/resolv/res_state.c
+++ b/lib/libc/resolv/res_state.c
@@ -26,6 +26,8 @@
*/
#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
@@ -59,13 +61,38 @@ res_keycreate(void)
res_thr_keycreated = thr_keycreate(&res_key, free_res) == 0;
}
+static res_state
+res_check_reload(res_state statp)
+{
+ struct timespec now;
+ struct stat sb;
+
+ if ((statp->options & RES_INIT) == 0 || statp->reload_period == 0) {
+ return (statp);
+ }
+
+ if (clock_gettime(CLOCK_MONOTONIC_FAST, &now) != 0 ||
+ (now.tv_sec - statp->conf_stat) < statp->reload_period) {
+ return (statp);
+ }
+
+ statp->conf_stat = now.tv_sec;
+ if (stat(_PATH_RESCONF, &sb) == 0 &&
+ (sb.st_mtim.tv_sec != statp->conf_mtim.tv_sec ||
+ sb.st_mtim.tv_nsec != statp->conf_mtim.tv_nsec)) {
+ statp->options &= ~RES_INIT;
+ }
+
+ return (statp);
+}
+
res_state
__res_state(void)
{
res_state statp;
if (thr_main() != 0)
- return (&_res);
+ return res_check_reload(&_res);
if (thr_once(&res_init_once, res_keycreate) != 0 ||
!res_thr_keycreated)
@@ -73,7 +100,7 @@ __res_state(void)
statp = thr_getspecific(res_key);
if (statp != NULL)
- return (statp);
+ return res_check_reload(statp);
statp = calloc(1, sizeof(*statp));
if (statp == NULL)
return (&_res);
diff --git a/share/man/man5/resolver.5 b/share/man/man5/resolver.5
index 4116f23..a3c5e05 100644
--- a/share/man/man5/resolver.5
+++ b/share/man/man5/resolver.5
@@ -28,7 +28,7 @@
.\" @(#)resolver.5 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd December 25, 2013
+.Dd October 12, 2015
.Dt RESOLVER 5
.Os
.Sh NAME
@@ -175,6 +175,19 @@ the resolver from obeying the standard
and
.Sy search
rules with the given name.
+.It Sy reload-period: Ns Ar n
+The resolver checks the modification time of
+.Pa /etc/resolv.conf
+every
+.Ar n
+seconds.
+If
+.Pa /etc/resolv.conf
+has changed, it is automatically reloaded.
+The default for
+.Ar n
+is two seconds.
+Setting it to zero disables the file check.
.El
.Pp
Options may also be specified as a space or tab separated list using the
@@ -191,8 +204,7 @@ If more than one instance of these keywords is present,
the last instance will override.
.Pp
The keyword and value must appear on a single line, and the keyword
-(e.g.\&
-.Sy nameserver )
+.Pq for example, Sy nameserver
must start the line.
The value follows the keyword, separated by white space.
.Sh FILES
OpenPOWER on IntegriCloud