BTW I'm not picking on you.. my DNS setup blew up this week for local resolution and I've been dealing with the fallout - so the topic is relatively near and dear to my heart.
On Wed, Sep 14, 2016 at 10:07 PM, Bob Beck <b...@obtuse.com> wrote: > > Yep. and now you need to solve the problem that when prepending > 127.0.0.1, and hitting rebound, which in turn is going to only grab the > first dns server from my resolv.conf instead of all of them, that it now > doubles my failure time when the first dns server doesn't respond (once for > libc asking rebound, which asks only the first server it found, which > fails) then falls back to libc asking resolv.conf which again... asks the > first server, and fails again. > > So the problem here is that it's going to be great when things are working > but become a failure multiplier when something breaks. > > Of course - perhaps you could query them all in parallel to mitigate this? > Rebound might need to become a real boy if we're going to do something > like this. If rebound were a "real boy" it would be it easier to say "just > use rebound or if it's not there just use resolv.conf normally > > then nothing changes at *all* when it's not there. > > > On Wed, Sep 14, 2016 at 8:39 PM, Ted Unangst <t...@tedunangst.com> wrote: > >> Ted Unangst wrote: >> > Bob Beck wrote: >> > > how is rebound going to handle a change in resolv.conf? thats still a >> > > problem here >> > >> > oh, that's easy. it watches the file for changes. i never quite got >> around to >> > that, but it's another five lines. >> >> ok, so it's a net +15 lines, including blanks. >> >> Index: rebound.8 >> =================================================================== >> RCS file: /cvs/src/usr.sbin/rebound/rebound.8,v >> retrieving revision 1.4 >> diff -u -p -r1.4 rebound.8 >> --- rebound.8 4 Dec 2015 04:50:43 -0000 1.4 >> +++ rebound.8 15 Sep 2016 00:57:21 -0000 >> @@ -33,9 +33,7 @@ The options are as follows: >> .Bl -tag -width Ds >> .It Fl c Ar config >> Specify an alternative configuration file, instead of the default >> -.Pa /etc/rebound.conf . >> -At present, the config file consists of a single line containing the next >> -hop DNS server. >> +.Pa /etc/resolv.conf . >> .Nm >> will reload the configuration file when sent a SIGHUP signal. >> .It Fl d >> @@ -46,8 +44,8 @@ does not >> into the background. >> .El >> .Sh FILES >> -.Bl -tag -width "/etc/rebound.confXX" -compact >> -.It Pa /etc/rebound.conf >> +.Bl -tag -width "/etc/resolv.confXX" -compact >> +.It Pa /etc/resolv.conf >> Default >> .Nm >> configuration file. >> Index: rebound.c >> =================================================================== >> RCS file: /cvs/src/usr.sbin/rebound/rebound.c,v >> retrieving revision 1.70 >> diff -u -p -r1.70 rebound.c >> --- rebound.c 1 Sep 2016 10:57:24 -0000 1.70 >> +++ rebound.c 15 Sep 2016 02:30:46 -0000 >> @@ -33,10 +33,12 @@ >> #include <string.h> >> #include <err.h> >> #include <unistd.h> >> +#include <fcntl.h> >> #include <pwd.h> >> #include <errno.h> >> #include <getopt.h> >> #include <stdarg.h> >> +#include <ctype.h> >> >> #define MINIMUM(a,b) (((a)<(b))?(a):(b)) >> >> @@ -455,34 +457,51 @@ fail: >> } >> >> static int >> -readconfig(FILE *conf, union sockun *remoteaddr) >> +readconfig(int conffd, union sockun *remoteaddr) >> { >> + const char ns[] = "nameserver"; >> char buf[1024]; >> + char *p; >> struct sockaddr_in *sin = &remoteaddr->i; >> struct sockaddr_in6 *sin6 = &remoteaddr->i6; >> + FILE *conf; >> + int rv = -1; >> >> - if (fgets(buf, sizeof(buf), conf) == NULL) >> - return -1; >> - buf[strcspn(buf, "\n")] = '\0'; >> + conf = fdopen(conffd, "r"); >> >> - memset(remoteaddr, 0, sizeof(*remoteaddr)); >> - if (inet_pton(AF_INET, buf, &sin->sin_addr) == 1) { >> - sin->sin_len = sizeof(*sin); >> - sin->sin_family = AF_INET; >> - sin->sin_port = htons(53); >> - return AF_INET; >> - } else if (inet_pton(AF_INET6, buf, &sin6->sin6_addr) == 1) { >> - sin6->sin6_len = sizeof(*sin6); >> - sin6->sin6_family = AF_INET6; >> - sin6->sin6_port = htons(53); >> - return AF_INET6; >> - } else { >> - return -1; >> + while (fgets(buf, sizeof(buf), conf) != NULL) { >> + buf[strcspn(buf, "\n")] = '\0'; >> + >> + if (strncmp(buf, ns, strlen(ns)) != 0) >> + continue; >> + p = buf + strlen(ns) + 1; >> + while (isspace((unsigned char)*p)) >> + p++; >> + >> + /* this will not end well */ >> + if (strcmp(p, "127.0.0.1") == 0) >> + continue; >> + >> + memset(remoteaddr, 0, sizeof(*remoteaddr)); >> + if (inet_pton(AF_INET, p, &sin->sin_addr) == 1) { >> + sin->sin_len = sizeof(*sin); >> + sin->sin_family = AF_INET; >> + sin->sin_port = htons(53); >> + rv = AF_INET; >> + } else if (inet_pton(AF_INET6, p, &sin6->sin6_addr) == 1) >> { >> + sin6->sin6_len = sizeof(*sin6); >> + sin6->sin6_family = AF_INET6; >> + sin6->sin6_port = htons(53); >> + rv = AF_INET6; >> + } >> + break; >> } >> + fclose(conf); >> + return rv; >> } >> >> static int >> -launch(FILE *conf, int ud, int ld, int kq) >> +launch(int conffd, int ud, int ld) >> { >> union sockun remoteaddr; >> struct kevent ch[2], kev[4]; >> @@ -490,16 +509,13 @@ launch(FILE *conf, int ud, int ld, int k >> struct request *req; >> struct dnscache *ent; >> struct passwd *pwd; >> - int i, r, af; >> + int i, r, af, kq; >> pid_t parent, child; >> >> parent = getpid(); >> if (!debug) { >> - if ((child = fork())) { >> - fclose(conf); >> + if ((child = fork())) >> return child; >> - } >> - close(kq); >> } >> >> kq = kqueue(); >> @@ -526,8 +542,7 @@ launch(FILE *conf, int ud, int ld, int k >> if (pledge("stdio inet", NULL) == -1) >> logerr("pledge failed"); >> >> - af = readconfig(conf, &remoteaddr); >> - fclose(conf); >> + af = readconfig(conffd, &remoteaddr); >> if (af == -1) >> logerr("parse error in config file"); >> >> @@ -647,6 +662,23 @@ launch(FILE *conf, int ud, int ld, int k >> exit(1); >> } >> >> +static int >> +openconfig(const char *confname, int kq) >> +{ >> + struct kevent kev; >> + int conffd; >> + >> + conffd = open(confname, O_RDONLY); >> + if (conffd == -1) >> + logerr("failed to open config %s", confname); >> + if (kq != -1) { >> + EV_SET(&kev, conffd, EVFILT_VNODE, EV_ADD, >> + NOTE_DELETE | NOTE_WRITE | NOTE_ATTRIB, 0, NULL); >> + kevent(kq, &kev, 1, NULL, 0, NULL); >> + } >> + return conffd; >> +} >> + >> static void __dead >> usage(void) >> { >> @@ -658,15 +690,14 @@ int >> main(int argc, char **argv) >> { >> union sockun bindaddr; >> - int r, kq, ld, ud, ch; >> + int r, kq, ld, ud, ch, conffd; >> int one; >> int childdead, hupped; >> pid_t child; >> struct kevent kev; >> struct rlimit rlim; >> struct timespec ts, *timeout = NULL; >> - const char *confname = "/etc/rebound.conf"; >> - FILE *conf; >> + const char *confname = "/etc/resolv.conf"; >> >> while ((ch = getopt(argc, argv, "c:d")) != -1) { >> switch (ch) { >> @@ -726,17 +757,15 @@ main(int argc, char **argv) >> logerr("bind: %s", strerror(errno)); >> if (listen(ld, 10) == -1) >> logerr("listen: %s", strerror(errno)); >> - >> - conf = fopen(confname, "r"); >> - if (!conf) >> - logerr("failed to open config %s", confname); >> - >> + >> signal(SIGPIPE, SIG_IGN); >> signal(SIGUSR1, SIG_IGN); >> signal(SIGHUP, SIG_IGN); >> >> - if (debug) >> - return launch(conf, ud, ld, -1); >> + if (debug) { >> + conffd = openconfig(confname, -1); >> + return launch(conffd, ud, ld); >> + } >> >> if (daemon(0, 0) == -1) >> logerr("daemon: %s", strerror(errno)); >> @@ -744,12 +773,14 @@ main(int argc, char **argv) >> >> kq = kqueue(); >> >> + conffd = openconfig(confname, kq); >> + >> EV_SET(&kev, SIGHUP, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); >> kevent(kq, &kev, 1, NULL, 0, NULL); >> while (1) { >> hupped = 0; >> childdead = 0; >> - child = launch(conf, ud, ld, kq); >> + child = launch(conffd, ud, ld); >> if (child == -1) >> logerr("failed to launch"); >> >> @@ -767,6 +798,12 @@ main(int argc, char **argv) >> if (r == 0) { >> /* timeout expired */ >> logerr("child died without HUP"); >> + } else if (kev.filter == EVFILT_VNODE) { >> + /* config file changed */ >> + logmsg(LOG_INFO, "config changed, >> reloading"); >> + close(conffd); >> + sleep(1); >> + raise(SIGHUP); >> } else if (kev.filter == EVFILT_SIGNAL) { >> /* signaled. kill child. */ >> logmsg(LOG_INFO, "received HUP, >> restarting"); >> @@ -774,10 +811,7 @@ main(int argc, char **argv) >> if (childdead) >> break; >> kill(child, SIGHUP); >> - conf = fopen(confname, "r"); >> - if (!conf) >> - logerr("failed to open config %s", >> - confname); >> + conffd = openconfig(confname, kq); >> } else if (kev.filter == EVFILT_PROC) { >> /* child died. wait for our own HUP. */ >> logmsg(LOG_INFO, "observed child exit"); >> > >