]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/ndb/dns.c
ndb/dns: do recursive lookup for dnsslave=
[plan9front.git] / sys / src / cmd / ndb / dns.c
old mode 100755 (executable)
new mode 100644 (file)
index 1bab668..83fe86b
@@ -3,9 +3,7 @@
 #include <auth.h>
 #include <fcall.h>
 #include <bio.h>
-#include <ctype.h>
 #include <ip.h>
-#include <pool.h>
 #include "dns.h"
 
 enum
@@ -27,13 +25,10 @@ typedef struct Network      Network;
 
 int vers;              /* incremented each clone/attach */
 
-static volatile int stop;
-
 /* holds data to be returned via read of /net/dns, perhaps multiple reads */
 struct Mfile
 {
        Mfile           *next;          /* next free mfile */
-       int             ref;
 
        char            *user;
        Qid             qid;
@@ -65,20 +60,19 @@ struct {
 
 Cfg    cfg;
 int    debug;
-uchar  ipaddr[IPaddrlen];      /* my ip address */
 int    maxage = Defmaxage;
 int    mfd[2];
 int    needrefresh;
 ulong  now;
 vlong  nowns;
 int    sendnotifies;
-int    testing;
 char   *trace;
 int    traceactivity;
 char   *zonerefreshprogram;
 
 char   *logfile = "dns";       /* or "dns.test" */
 char   *dbfile;
+char   *dnsuser;
 char   mntpt[Maxpath];
 
 int    addforwtarg(char *);
@@ -103,14 +97,13 @@ void       rwstat(Job*, Mfile*);
 void   sendmsg(Job*, char*);
 void   setext(char*, int, char*);
 
-static char *lookupqueryold(Job*, Mfile*, Request*, char*, char*, int, int);
-static char *lookupquerynew(Job*, Mfile*, Request*, char*, char*, int, int);
+static char *lookupquery(Job*, Mfile*, Request*, char*, char*, int, int);
 static char *respond(Job*, Mfile*, RR*, char*, int, int);
 
 void
 usage(void)
 {
-       fprint(2, "usage: %s [-FnorRst] [-a maxage] [-f ndb-file] [-N target] "
+       fprint(2, "usage: %s [-FnorRs] [-a maxage] [-f ndb-file] [-N target] "
                "[-T forwip] [-x netmtpt] [-z refreshprog]\n", argv0);
        exits("usage");
 }
@@ -118,7 +111,6 @@ usage(void)
 void
 main(int argc, char *argv[])
 {
-       int kid, pid;
        char servefile[Maxpath], ext[Maxpath];
        Dir *dir;
 
@@ -161,9 +153,6 @@ main(int argc, char *argv[])
                cfg.serve = 1;          /* serve network */
                cfg.cachedb = 1;
                break;
-       case 't':
-               testing = 1;
-               break;
        case 'T':
                addforwtarg(EARGF(usage()));
                break;
@@ -181,9 +170,6 @@ main(int argc, char *argv[])
        if(argc != 0)
                usage();
 
-       if(testing)
-               mainmem->flags |= POOL_NOREUSE | POOL_ANTAGONISM;
-       mainmem->flags |= POOL_ANTAGONISM;
        rfork(RFREND|RFNOTEG);
 
        cfg.inside = (*mntpt == '\0' || strcmp(mntpt, "/net") == 0);
@@ -191,19 +177,17 @@ main(int argc, char *argv[])
        /* start syslog before we fork */
        fmtinstall('F', fcallfmt);
        dninit();
-       /* this really shouldn't be fatal */
-       if(myipaddr(ipaddr, mntpt) < 0)
-               sysfatal("can't read my ip address");
-       dnslog("starting %s%sdns %s%s%son %I's %s",
+       dnslog("starting %s%sdns %s%s%son %s",
                (cfg.straddle? "straddling ": ""),
                (cfg.cachedb? "caching ": ""),
                (cfg.serve?   "udp server ": ""),
                (cfg.justforw? "forwarding-only ": ""),
-               (cfg.resolver? "resolver ": ""), ipaddr, mntpt);
+               (cfg.resolver? "resolver ": ""), mntpt);
 
        opendatabase();
        now = time(nil);                /* open time files before we fork */
        nowns = nsec();
+       dnsuser = estrdup(getuser());
 
        snprint(servefile, sizeof servefile, "#s/dns%s", ext);
        dir = dirstat(servefile);
@@ -211,43 +195,21 @@ main(int argc, char *argv[])
                sysfatal("%s exists; another dns instance is running",
                        servefile);
        free(dir);
-//     unmount(servefile, mntpt);
-//     remove(servefile);
-
        mountinit(servefile, mntpt);    /* forks, parent exits */
 
-       srand(now*getpid());
+       srand(truerand());
        db2cache(1);
-//     dnageallnever();
 
        if (cfg.straddle && !seerootns())
                dnslog("straddle server misconfigured; can't see root name servers");
-       /*
-        * fork without sharing heap.
-        * parent waits around for child to die, then forks & restarts.
-        * child may spawn udp server, notify procs, etc.; when it gets too
-        * big, it kills itself and any children.
-        * /srv/dns and /net/dns remain open and valid.
-        */
-       for (;;) {
-               kid = rfork(RFPROC|RFFDG|RFNOTEG);
-               switch (kid) {
-               case -1:
-                       sysfatal("fork failed: %r");
-               case 0:
-                       if(cfg.serve)
-                               dnudpserver(mntpt);
-                       if(sendnotifies)
-                               notifyproc();
-                       io();
-                       _exits("restart");
-               default:
-                       while ((pid = waitpid()) != kid && pid != -1)
-                               continue;
-                       break;
-               }
-               dnslog("dns restarting");
-       }
+
+       if(cfg.serve)
+               dnudpserver(mntpt);
+       if(sendnotifies)
+               notifyproc();
+
+       io();
+       _exits(0);
 }
 
 /*
@@ -279,29 +241,28 @@ mountinit(char *service, char *mntpt)
        char buf[32];
 
        if(pipe(p) < 0)
-               abort(); /* "pipe failed" */;
+               sysfatal("pipe failed: %r");
+
+       /*
+        *  make a /srv/dns
+        */
+       if((f = create(service, OWRITE|ORCLOSE, 0666)) < 0)
+               sysfatal("create %s failed: %r", service);
+       snprint(buf, sizeof buf, "%d", p[1]);
+       if(write(f, buf, strlen(buf)) != strlen(buf))
+               sysfatal("write %s failed: %r", service);
+
        /* copy namespace to avoid a deadlock */
        switch(rfork(RFFDG|RFPROC|RFNAMEG)){
-       case 0:                 /* child: hang around and (re)start main proc */
+       case 0:                 /* child: start main proc */
                close(p[1]);
-               procsetname("%s restarter", mntpt);
+               procsetname("%s", mntpt);
                break;
        case -1:
-               abort(); /* "fork failed\n" */;
+               sysfatal("fork failed: %r");
        default:                /* parent: make /srv/dns, mount it, exit */
                close(p[0]);
 
-               /*
-                *  make a /srv/dns
-                */
-               f = create(service, 1, 0666);
-               if(f < 0)
-                       abort(); /* service */;
-               snprint(buf, sizeof buf, "%d", p[1]);
-               if(write(f, buf, strlen(buf)) != strlen(buf))
-                       abort(); /* "write %s", service */;
-               close(f);
-
                /*
                 *  put ourselves into the file system
                 */
@@ -327,7 +288,10 @@ newfid(int fid, int needunused)
                }
        mf = emalloc(sizeof(*mf));
        mf->fid = fid;
-       mf->user = estrdup("dummy");
+       mf->qid.vers = vers;
+       mf->qid.type = QTDIR;
+       mf->qid.path = 0LL;
+       mf->user = estrdup("none");
        mf->next = mfalloc.inuse;
        mfalloc.inuse = mf;
        unlock(&mfalloc);
@@ -343,8 +307,7 @@ freefid(Mfile *mf)
        for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next)
                if(*l == mf){
                        *l = mf->next;
-                       if(mf->user)
-                               free(mf->user);
+                       free(mf->user);
                        memset(mf, 0, sizeof *mf);      /* cause trouble */
                        free(mf);
                        unlock(&mfalloc);
@@ -363,7 +326,7 @@ copyfid(Mfile *mf, int fid)
        if(nmf == nil)
                return nil;
        nmf->fid = fid;
-       free(nmf->user);                        /* estrdup("dummy") */
+       free(nmf->user);                        /* estrdup("none") */
        nmf->user = estrdup(mf->user);
        nmf->qid.type = mf->qid.type;
        nmf->qid.path = mf->qid.path;
@@ -433,22 +396,19 @@ io(void)
        if(setjmp(req.mret))
                putactivity(0);
        req.isslave = 0;
-       stop = 0;
-       while(!stop){
-               procsetname("%d %s/dns Twrites of %d 9p rpcs read; %d alarms",
-                       stats.qrecvd9p, mntpt, stats.qrecvd9prpc, stats.alarms);
-               n = read9pmsg(mfd[0], mdata, sizeof mdata);
-               if(n<=0){
+       while((n = read9pmsg(mfd[0], mdata, sizeof mdata)) != 0){
+               if(n < 0){
                        dnslog("error reading 9P from %s: %r", mntpt);
-                       sleep(2000);    /* don't thrash after read error */
-                       return;
+                       break;
                }
 
                stats.qrecvd9prpc++;
                job = newjob();
                if(convM2S(mdata, n, &job->request) != n){
+                       dnslog("format error %ux %ux %ux %ux %ux",
+                               mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]);
                        freejob(job);
-                       continue;
+                       break;
                }
                mf = newfid(job->request.fid, 0);
                if(debug)
@@ -516,9 +476,6 @@ io(void)
 
                putactivity(0);
        }
-       /* kill any udp server, notifier, etc. processes */
-       postnote(PNGROUP, getpid(), "die");
-       sleep(1000);
 }
 
 void
@@ -726,26 +683,21 @@ rwrite(Job *job, Mfile *mf, Request *req)
        if(cnt > 0 && job->request.data[cnt-1] == '\n')
                job->request.data[cnt-1] = 0;
 
+       if(strcmp(mf->user, "none") == 0 || strcmp(mf->user, dnsuser) != 0)
+               goto query;     /* skip special commands if not owner */
+
        /*
         *  special commands
         */
-//     dnslog("rwrite got: %s", job->request.data);
+       if(debug)
+               dnslog("rwrite got: %s", job->request.data);
        send = 1;
-       if(strcmp(job->request.data, "age")==0){
-               dnslog("dump, age & dump forced");
-               dndump("/lib/ndb/dnsdump1");
-               dnforceage();
-               dndump("/lib/ndb/dnsdump2");
-       } else if(strcmp(job->request.data, "debug")==0)
+       if(strcmp(job->request.data, "debug")==0)
                debug ^= 1;
        else if(strcmp(job->request.data, "dump")==0)
                dndump("/lib/ndb/dnsdump");
-       else if(strcmp(job->request.data, "poolcheck")==0)
-               poolcheck(mainmem);
        else if(strcmp(job->request.data, "refresh")==0)
                needrefresh = 1;
-       else if(strcmp(job->request.data, "restart")==0)
-               stop = 1;
        else if(strcmp(job->request.data, "stats")==0)
                dnstats("/lib/ndb/dnsstats");
        else if(strncmp(job->request.data, "target ", 7)==0){
@@ -756,6 +708,7 @@ rwrite(Job *job, Mfile *mf, Request *req)
        if (send)
                goto send;
 
+query:
        /*
         *  kill previous reply
         */
@@ -810,9 +763,8 @@ rwrite(Job *job, Mfile *mf, Request *req)
        } else
                wantsav = 0;
 
-       err = lookupqueryold(job, mf, req, errbuf, p, wantsav, rooted);
+       err = lookupquery(job, mf, req, errbuf, p, wantsav, rooted);
 send:
-       dncheck(0, 1);
        job->reply.count = cnt;
        sendmsg(job, err);
 }
@@ -828,24 +780,20 @@ send:
  * but here we just call dnresolve directly.
  */
 static char *
-lookupqueryold(Job *job, Mfile *mf, Request *req, char *errbuf, char *p,
+lookupquery(Job *job, Mfile *mf, Request *req, char *errbuf, char *p,
        int wantsav, int rooted)
 {
        int status;
        RR *rp, *neg;
 
-       dncheck(0, 1);
        status = Rok;
        rp = dnresolve(p, Cin, mf->type, req, 0, 0, Recurse, rooted, &status);
 
-       dncheck(0, 1);
-       lock(&dnlock);
        neg = rrremneg(&rp);
        if(neg){
                status = neg->negrcode;
                rrfreelist(neg);
        }
-       unlock(&dnlock);
 
        return respond(job, mf, rp, errbuf, status, wantsav);
 }
@@ -885,35 +833,10 @@ respond(Job *job, Mfile *mf, RR *rp, char *errbuf, int status, int wantsav)
                mf->rr[mf->nrr] = n;
        }
        unlock(&joblock);
-       rrfreelist(rp);
-       return nil;
-}
 
-/* simulate what dnsudpserver does */
-static char *
-lookupquerynew(Job *job, Mfile *mf, Request *req, char *errbuf, char *p,
-       int wantsav, int)
-{
-       char *err;
-       uchar buf[Udphdrsize + Maxudp + 1024];
-       DNSmsg *mp;
-       DNSmsg repmsg;
-       RR *rp;
-
-       dncheck(0, 1);
-
-       memset(&repmsg, 0, sizeof repmsg);
-       rp = rralloc(mf->type);
-       rp->owner = dnlookup(p, Cin, 1);
-       mp = newdnsmsg(rp, Frecurse|Oquery, (ushort)rand());
-
-       dnserver(mp, &repmsg, req, buf, Rok);
+       rrfreelist(rp);
 
-       freeanswers(mp);
-       err = respond(job, mf, repmsg.an, errbuf, Rok, wantsav);
-       repmsg.an = nil;                /* freed above */
-       freeanswers(&repmsg);
-       return err;
+       return nil;
 }
 
 void