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