diff options
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/resolv/res_init.c | 22 | ||||
-rw-r--r-- | lib/libc/resolv/res_private.h | 5 | ||||
-rw-r--r-- | lib/libc/resolv/res_state.c | 39 |
3 files changed, 62 insertions, 4 deletions
diff --git a/lib/libc/resolv/res_init.c b/lib/libc/resolv/res_init.c index f636baa..41e9f5a 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> @@ -238,6 +239,7 @@ __res_vinit(res_state statp, int preinit) { statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr; strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa"); strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int"); + statp->_u._ext.ext->reload_period = 2; } else { /* * Historically res_init() rarely, if at all, failed. @@ -323,6 +325,18 @@ __res_vinit(res_state statp, int preinit) { nserv = 0; if ((fp = fopen(_PATH_RESCONF, "re")) != NULL) { + struct stat sb; + struct timespec now; + + if (statp->_u._ext.ext != NULL) { + if (_fstat(fileno(fp), &sb) == 0) { + statp->_u._ext.ext->conf_mtim = sb.st_mtim; + if (clock_gettime(CLOCK_MONOTONIC_FAST, &now) == 0) { + statp->_u._ext.ext->conf_stat = now.tv_sec; + } + } + } + /* read the config file */ while (fgets(buf, sizeof(buf), fp) != NULL) { /* skip comments */ @@ -583,9 +597,7 @@ res_setoptions(res_state statp, const char *options, const char *source) { const char *cp = options; int i; -#ifndef _LIBC struct __res_state_ext *ext = statp->_u._ext.ext; -#endif #ifdef DEBUG if (statp->options & RES_DEBUG) @@ -668,6 +680,12 @@ 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)) { + if (ext != NULL) { + ext->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_private.h b/lib/libc/resolv/res_private.h index 4e98157..a986e95 100644 --- a/lib/libc/resolv/res_private.h +++ b/lib/libc/resolv/res_private.h @@ -1,3 +1,5 @@ +/* $FreeBSD$ */ + #ifndef res_private_h #define res_private_h @@ -12,6 +14,9 @@ struct __res_state_ext { } sort_list[MAXRESOLVSORT]; char nsuffix[64]; char nsuffix2[64]; + struct timespec conf_mtim; /* mod time of loaded resolv.conf */ + time_t conf_stat; /* time of last stat(resolv.conf) */ + u_short reload_period; /* seconds between stat(resolv.conf) */ }; extern int diff --git a/lib/libc/resolv/res_state.c b/lib/libc/resolv/res_state.c index 59c9430..6d31d92 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> @@ -35,6 +37,8 @@ #include "reentrant.h" #include "un-namespace.h" +#include "res_private.h" + #undef _res struct __res_state _res; @@ -59,13 +63,44 @@ 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; + struct __res_state_ext *ext; + + if ((statp->options & RES_INIT) == 0) { + return (statp); + } + + ext = statp->_u._ext.ext; + if (ext == NULL || ext->reload_period == 0) { + return (statp); + } + + if (clock_gettime(CLOCK_MONOTONIC_FAST, &now) != 0 || + (now.tv_sec - ext->conf_stat) < ext->reload_period) { + return (statp); + } + + ext->conf_stat = now.tv_sec; + if (stat(_PATH_RESCONF, &sb) == 0 && + (sb.st_mtim.tv_sec != ext->conf_mtim.tv_sec || + sb.st_mtim.tv_nsec != ext->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 +108,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); |