summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/resolv/res_init.c22
-rw-r--r--lib/libc/resolv/res_state.c31
2 files changed, 51 insertions, 2 deletions
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);
OpenPOWER on IntegriCloud