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

Reply via email to