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"); >