]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/ndb/dn.c
fix misleading/wrong fd checks
[plan9front.git] / sys / src / cmd / ndb / dn.c
index e91183c379eb28c2376e235b4f7941c05961951b..f565a38fe653ae133c6dd292f069ad3635944d16 100644 (file)
@@ -1,7 +1,6 @@
 #include <u.h>
 #include <libc.h>
 #include <ip.h>
-#include <pool.h>
 #include <ctype.h>
 #include "dns.h"
 
  * figure it out.
  */
 enum {
-//     Deftarget       = 1<<30,        /* effectively disable aging */
-//     Minage          = 1<<30,
-//     Defagefreq      = 1<<30,        /* age names this often (seconds) */
-
        /* these settings will trigger frequent aging */
        Deftarget       = 4000,
-       Minage          =  5*60,
-       Defagefreq      = 15*60,        /* age names this often (seconds) */
+       Minage          =  5*Min,
+       Defagefreq      = 15*Min,       /* age names this often (seconds) */
 };
 
 /*
@@ -228,6 +223,25 @@ dnlookup(char *name, int class, int enter)
        return dp;
 }
 
+DN*
+idnlookup(char *name, int class, int enter)
+{
+       char dom[Domlen];
+
+       if(utf2idn(name, dom, sizeof dom) >= 0)
+               name = dom;
+       return dnlookup(name, class, enter);
+}
+
+DN*
+ipalookup(uchar *ip, int class, int enter)
+{
+       char addr[64];
+
+       snprint(addr, sizeof(addr), "%I", ip);
+       return dnlookup(addr, class, enter);
+}
+
 static int
 rrsame(RR *rr1, RR *rr2)
 {
@@ -305,9 +319,9 @@ dndump(char *file)
                for(dp = ht[i]; dp; dp = dp->next){
                        fprint(fd, "%s\n", dp->name);
                        for(rp = dp->rr; rp; rp = rp->next) {
-                               fprint(fd, "\t%R %c%c %lud/%lud\n",
+                               fprint(fd, "\t%R %c%c %ld/%lud\n",
                                        rp, rp->auth? 'A': 'U',
-                                       rp->db? 'D': 'N', rp->expire, rp->ttl);
+                                       rp->db? 'D': 'N', (long)(rp->expire - now), rp->ttl);
                                if (rronlist(rp, rp->next))
                                        fprint(fd, "*** duplicate:\n");
                        }
@@ -372,29 +386,28 @@ dnage(DN *dp)
        if (canlock(&dnlock))
                abort();        /* dnage called with dnlock not held */
        diff = now - dp->referenced;
-       if(diff < Reserved || dp->keep)
+       if(diff < Reserved || dp->mark != 0)
                return;
 
        l = &dp->rr;
        while ((rp = *l) != nil){
                assert(rp->magic == RRmagic && rp->cached);
-               if(!rp->db && (rp->expire < now || diff > dnvars.oldest))
+               if(!rp->db && ((long)(rp->expire - now) <= 0 || diff > dnvars.oldest))
                        rrdelhead(l); /* rp == *l before; *l == rp->next after */
                else
                        l = &rp->next;
        }
 }
 
-#define MARK(dp)       { if (dp) (dp)->keep = 1; }
+#define MARK(dp)       { if (dp) (dp)->mark |= 2; }
 
 /* mark a domain name and those in its RRs as never to be aged */
 void
-dnagenever(DN *dp, int dolock)
+dnagenever(DN *dp)
 {
        RR *rp;
 
-       if (dolock)
-               lock(&dnlock);
+       lock(&dnlock);
 
        /* mark all referenced domain names */
        MARK(dp);
@@ -449,11 +462,10 @@ dnagenever(DN *dp, int dolock)
                }
        }
 
-       if (dolock)
-               unlock(&dnlock);
+       unlock(&dnlock);
 }
 
-#define REF(dp)        { if (dp) (dp)->refs++; }
+#define REF(dp)        { if (dp) (dp)->mark |= 1; }
 
 /*
  *  periodicly sweep for old records and remove unreferenced domain names
@@ -468,7 +480,7 @@ dnageall(int doit)
        RR *rp;
        static ulong nextage;
 
-       if(dnvars.names < target || (now < nextage && !doit)){
+       if(dnvars.names < target || ((long)(nextage - now) > 0 && !doit)){
                dnvars.oldest = maxage;
                return;
        }
@@ -483,14 +495,14 @@ dnageall(int doit)
        if (agefreq > dnvars.oldest / 2)
                nextage = now + dnvars.oldest / 2;
        else
-               nextage = now + agefreq;
+               nextage = now + (ulong)agefreq;
 
        lock(&dnlock);
 
        /* time out all old entries (and set refs to 0) */
        for(i = 0; i < HTLEN; i++)
                for(dp = ht[i]; dp; dp = dp->next){
-                       dp->refs = 0;
+                       dp->mark &= ~1;
                        dnage(dp);
                }
 
@@ -552,7 +564,7 @@ dnageall(int doit)
        for(i = 0; i < HTLEN; i++){
                l = &ht[i];
                for(dp = *l; dp; dp = *l){
-                       if(dp->rr == nil && dp->refs == 0 && dp->keep == 0){
+                       if(dp->rr == nil && dp->mark == 0){
                                assert(dp->magic == DNmagic);
                                *l = dp->next;
 
@@ -586,7 +598,7 @@ dnagedb(void)
        /* time out all database entries */
        for(i = 0; i < HTLEN; i++)
                for(dp = ht[i]; dp; dp = dp->next) {
-                       dp->keep = 0;
+                       dp->mark = 0;
                        for(rp = dp->rr; rp; rp = rp->next)
                                if(rp->db)
                                        rp->expire = 0;
@@ -597,7 +609,7 @@ dnagedb(void)
 
 /*
  *  mark all local db records about my area as authoritative,
- *  time out any others
+ *  delete timed out ones
  */
 void
 dnauthdb(void)
@@ -606,7 +618,7 @@ dnauthdb(void)
        ulong minttl;
        Area *area;
        DN *dp;
-       RR *rp;
+       RR *rp, **l;
 
        lock(&dnlock);
 
@@ -614,19 +626,22 @@ dnauthdb(void)
        for(i = 0; i < HTLEN; i++)
                for(dp = ht[i]; dp; dp = dp->next){
                        area = inmyarea(dp->name);
-                       for(rp = dp->rr; rp; rp = rp->next)
+                       l = &dp->rr;
+                       for(rp = *l; rp; rp = *l){
                                if(rp->db){
+                                       if(rp->expire == 0){
+                                               rrdelhead(l);
+                                               continue;
+                                       }
                                        if(area){
                                                minttl = area->soarr->soa->minttl;
                                                if(rp->ttl < minttl)
                                                        rp->ttl = minttl;
                                                rp->auth = 1;
                                        }
-                                       if(rp->expire == 0){
-                                               rp->db = 0;
-                                               dp->referenced = now-Reserved-1;
-                                       }
                                }
+                               l = &rp->next;
+                       }
                }
 
        unlock(&dnlock);
@@ -658,6 +673,7 @@ getactivity(Request *req, int recursive)
        now = time(nil);
        nowns = nsec();
        req->id = ++dnvars.id;
+       req->aux = nil;
        unlock(&dnvars);
 
        return rv;
@@ -665,8 +681,6 @@ getactivity(Request *req, int recursive)
 void
 putactivity(int recursive)
 {
-       static ulong lastclean;
-
        if(traceactivity)
                dnslog("put: %d active by pid %d",
                        dnvars.active, getpid());
@@ -694,17 +708,11 @@ putactivity(int recursive)
        }
        unlock(&dnvars);
 
-       dncheck();
-
        db2cache(needrefresh);
-       dncheck();
 
        dnageall(0);
 
-       dncheck();
-
        /* let others back in */
-       lastclean = now;
        needrefresh = 0;
        dnvars.mutex = 0;
 }
@@ -735,22 +743,28 @@ rrattach1(RR *new, int auth)
        RR **l;
        RR *rp;
        DN *dp;
+       ulong ttl;
 
        assert(new->magic == RRmagic && !new->cached);
-       if(!new->db) {
-               /*
-                * try not to let responses expire before we
-                * can use them to complete this query, by extending
-                * past (or nearly past) expiration time.
-                */
-               new->expire = new->ttl > now + Min? new->ttl: now + 10*Min;
-       } else
-               new->expire = now + Year;
+
        dp = new->owner;
        assert(dp != nil && dp->magic == DNmagic);
        new->auth |= auth;
        new->next = 0;
 
+       /*
+        * try not to let responses expire before we
+        * can use them to complete this query, by extending
+        * past (or nearly past) expiration time.
+        */
+       if(new->db)
+               ttl = Year;
+       else
+               ttl = new->ttl;
+       if(ttl <= Min)
+               ttl = 10*Min;
+       new->expire = now + ttl;
+
        /*
         *  find first rr of the right type
         */
@@ -785,9 +799,8 @@ rrattach1(RR *new, int auth)
                        }
                        /* all things equal, pick the newer one */
                        else if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){
-                               /* new drives out old */
-                               if (new->ttl <= rp->ttl &&
-                                   new->expire <= rp->expire) {
+                               /* old drives out new */
+                               if((long)(rp->expire - new->expire) > 0) {
                                        rrfree(new);
                                        return;
                                }
@@ -839,8 +852,8 @@ rrattach(RR *rp, int auth)
                next = rp->next;
                rp->next = nil;
                dp = rp->owner;
-               /* avoid any outside spoofing; leave keepers alone */
-               if(cfg.cachedb && !rp->db && (dp->keep || inmyarea(dp->name)))
+               /* avoid any outside spoofing */
+               if(cfg.cachedb && !rp->db && inmyarea(dp->name))
                        rrfree(rp);
                else
                        rrattach1(rp, auth);
@@ -971,8 +984,8 @@ rrlookup(DN *dp, int type, int flag)
        for(rp = dp->rr; rp; rp = rp->next){
                if(!rp->db)
                if(rp->auth)
-               if(rp->ttl + 60 > now)
-               if(tsame(type, rp->type)){
+               if((long)(rp->expire - now) > 0)
+               if(tsame(type, rp->type)){
                        if(flag == NOneg && rp->negative)
                                goto out;
                        last = rrcopy(rp, last);
@@ -984,7 +997,7 @@ rrlookup(DN *dp, int type, int flag)
        /* try for a living unauthoritative network entry */
        for(rp = dp->rr; rp; rp = rp->next){
                if(!rp->db)
-               if(rp->ttl + 60 > now)
+               if((long)(rp->expire - now) > 0)
                if(tsame(type, rp->type)){
                        if(flag == NOneg && rp->negative)
                                goto out;
@@ -1082,54 +1095,69 @@ rrcat(RR **start, RR *rp)
        return *start;
 }
 
-/*
- *  remove negative cache rr's from an rr list
- */
 RR*
-rrremneg(RR **l)
+rrremfilter(RR **l, int (*filter)(RR*, void*), void *arg)
 {
-       RR **nl, *rp;
-       RR *first;
+       RR *first, *rp;
+       RR **nl;
 
        first = nil;
        nl = &first;
        while(*l != nil){
                rp = *l;
-               if(rp->negative){
+               if((*filter)(rp, arg)){
                        *l = rp->next;
                        *nl = rp;
                        nl = &rp->next;
                        *nl = nil;
                } else
-                       l = &rp->next;
+                       l = &(*l)->next;
        }
 
        return first;
 }
 
+static int
+filterneg(RR *rp, void*)
+{
+       return rp->negative;
+}
+static int
+filtertype(RR *rp, void *arg)
+{
+       return rp->type == *((int*)arg);
+}
+static int
+filterowner(RR *rp, void *arg)
+{
+       return rp->owner == (DN*)arg;
+}
+
+/*
+ *  remove negative cache rr's from an rr list
+ */
+RR*
+rrremneg(RR **l)
+{
+       return rrremfilter(l, filterneg, nil);
+}
+
 /*
  *  remove rr's of a particular type from an rr list
  */
 RR*
 rrremtype(RR **l, int type)
 {
-       RR *first, *rp;
-       RR **nl;
-
-       first = nil;
-       nl = &first;
-       while(*l != nil){
-               rp = *l;
-               if(rp->type == type){
-                       *l = rp->next;
-                       *nl = rp;
-                       nl = &rp->next;
-                       *nl = nil;
-               } else
-                       l = &(*l)->next;
-       }
+       return rrremfilter(l, filtertype, &type);
+}
 
-       return first;
+/*
+ *  remove rr's of a particular owner from an rr list
+ */
+RR*
+rrremowner(RR **l, DN *owner)
+{
+       return rrremfilter(l, filterowner, owner);
 }
 
 static char *
@@ -1138,6 +1166,17 @@ dnname(DN *dn)
        return dn? dn->name: "<null>";
 }
 
+static char *
+idnname(DN *dn, char *buf, int nbuf)
+{
+       char *name;
+
+       name = dnname(dn);
+       if(idn2utf(name, buf, nbuf) >= 0)
+               return buf;
+       return name;
+}
+
 /*
  *  print conversion for rr records
  */
@@ -1269,7 +1308,7 @@ int
 rravfmt(Fmt *f)
 {
        int rv, quote;
-       char *strp;
+       char buf[Domlen], *strp;
        Fmt fstr;
        RR *rp;
        Server *s;
@@ -1288,34 +1327,37 @@ rravfmt(Fmt *f)
        if(rp->type == Tptr)
                fmtprint(&fstr, "ptr=%s", dnname(rp->owner));
        else
-               fmtprint(&fstr, "dom=%s", dnname(rp->owner));
+               fmtprint(&fstr, "dom=%s", idnname(rp->owner, buf, sizeof(buf)));
 
        switch(rp->type){
        case Thinfo:
                fmtprint(&fstr, " cpu=%s os=%s",
-                       dnname(rp->cpu), dnname(rp->os));
+                       idnname(rp->cpu, buf, sizeof(buf)),
+                       idnname(rp->os, buf, sizeof(buf)));
                break;
        case Tcname:
-               fmtprint(&fstr, " cname=%s", dnname(rp->host));
+               fmtprint(&fstr, " cname=%s", idnname(rp->host, buf, sizeof(buf)));
                break;
        case Tmb:
        case Tmd:
        case Tmf:
-               fmtprint(&fstr, " mbox=%s", dnname(rp->host));
+               fmtprint(&fstr, " mbox=%s", idnname(rp->host, buf, sizeof(buf)));
                break;
        case Tns:
-               fmtprint(&fstr,  " ns=%s", dnname(rp->host));
+               fmtprint(&fstr,  " ns=%s", idnname(rp->host, buf, sizeof(buf)));
                break;
        case Tmg:
        case Tmr:
-               fmtprint(&fstr, " mbox=%s", dnname(rp->mb));
+               fmtprint(&fstr, " mbox=%s", idnname(rp->mb, buf, sizeof(buf)));
                break;
        case Tminfo:
                fmtprint(&fstr, " mbox=%s mbox=%s",
-                       dnname(rp->mb), dnname(rp->rmb));
+                       idnname(rp->mb, buf, sizeof(buf)),
+                       idnname(rp->rmb, buf, sizeof(buf)));
                break;
        case Tmx:
-               fmtprint(&fstr, " pref=%lud mx=%s", rp->pref, dnname(rp->host));
+               fmtprint(&fstr, " pref=%lud mx=%s", rp->pref,
+                       idnname(rp->host, buf, sizeof(buf)));
                break;
        case Ta:
        case Taaaa:
@@ -1328,7 +1370,8 @@ rravfmt(Fmt *f)
                soa = rp->soa;
                fmtprint(&fstr,
 " ns=%s mbox=%s serial=%lud refresh=%lud retry=%lud expire=%lud ttl=%lud",
-                       dnname(rp->host), dnname(rp->rmb),
+                       idnname(rp->host, buf, sizeof(buf)),
+                       idnname(rp->rmb, buf, sizeof(buf)),
                        (soa? soa->serial: 0),
                        (soa? soa->refresh: 0), (soa? soa->retry: 0),
                        (soa? soa->expire: 0), (soa? soa->minttl: 0));
@@ -1339,7 +1382,7 @@ rravfmt(Fmt *f)
                srv = rp->srv;
                fmtprint(&fstr, " pri=%ud weight=%ud port=%ud target=%s",
                        (srv? srv->pri: 0), (srv? srv->weight: 0),
-                       rp->port, dnname(rp->host));
+                       rp->port, idnname(rp->host, buf, sizeof(buf)));
                break;
        case Tnull:
                if (rp->null == nil)
@@ -1363,7 +1406,8 @@ rravfmt(Fmt *f)
                break;
        case Trp:
                fmtprint(&fstr, " rp=%s txt=%s",
-                       dnname(rp->rmb), dnname(rp->rp));
+                       idnname(rp->rmb, buf, sizeof(buf)),
+                       idnname(rp->rp, buf, sizeof(buf)));
                break;
        case Tkey:
                if (rp->key == nil)
@@ -1381,7 +1425,7 @@ rravfmt(Fmt *f)
 " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s",
                                rp->sig->type, rp->sig->alg, rp->sig->labels,
                                rp->sig->ttl, rp->sig->exp, rp->sig->incep,
-                               rp->sig->tag, dnname(rp->sig->signer));
+                               rp->sig->tag, idnname(rp->sig->signer, buf, sizeof(buf)));
                break;
        case Tcert:
                if (rp->cert == nil)
@@ -1422,31 +1466,6 @@ dnslog(char *fmt, ...)
        syslog(0, logfile, dnserr);
 }
 
-/*
- * based on libthread's threadsetname, but drags in less library code.
- * actually just sets the arguments displayed.
- */
-void
-procsetname(char *fmt, ...)
-{
-       int fd;
-       char *cmdname;
-       char buf[128];
-       va_list arg;
-
-       va_start(arg, fmt);
-       cmdname = vsmprint(fmt, arg);
-       va_end(arg);
-       if (cmdname == nil)
-               return;
-       snprint(buf, sizeof buf, "#p/%d/args", getpid());
-       if((fd = open(buf, OWRITE)) >= 0){
-               write(fd, cmdname, strlen(cmdname)+1);
-               close(fd);
-       }
-       free(cmdname);
-}
-
 /*
  *  create a slave process to handle a request to avoid one request blocking
  *  another
@@ -1504,39 +1523,6 @@ slave(Request *req)
        }
 }
 
-/*
- *  chasing down double free's
- */
-void
-dncheck(void)
-{
-       int i;
-       DN *dp;
-       RR *rp;
-
-       if(!testing)
-               return;
-
-       lock(&dnlock);
-       poolcheck(mainmem);
-       for(i = 0; i < HTLEN; i++)
-               for(dp = ht[i]; dp; dp = dp->next){
-                       assert(dp->magic == DNmagic);
-                       for(rp = dp->rr; rp; rp = rp->next){
-                               assert(rp->magic == RRmagic);
-                               assert(rp->cached);
-                               assert(rp->owner == dp);
-                               /* also check for duplicate rrs */
-                               if (rronlist(rp, rp->next)) {
-                                       dnslog("%R duplicates its next chain "
-                                               "(%R); aborting", rp, rp->next);
-                                       abort();
-                               }
-                       }
-               }
-       unlock(&dnlock);
-}
-
 static int
 rrequiv(RR *r1, RR *r2)
 {
@@ -1669,20 +1655,7 @@ sencodefmt(Fmt *f)
        ilen = f->prec;
        f->prec = 0;
        f->flags &= ~FmtPrec;
-       switch(f->r){
-       case '<':
-               len = (8*ilen+4)/5 + 3;
-               break;
-       case '[':
-               len = (8*ilen+5)/6 + 4;
-               break;
-       case 'H':
-               len = 2*ilen + 1;
-               break;
-       default:
-               goto error;
-       }
-
+       len = 2*ilen + 1;
        if(len > sizeof(obuf)){
                buf = malloc(len);
                if(buf == nil)
@@ -1692,20 +1665,7 @@ sencodefmt(Fmt *f)
 
        /* convert */
        out = buf;
-       switch(f->r){
-       case '<':
-               rv = enc32(out, len, b, ilen);
-               break;
-       case '[':
-               rv = enc64(out, len, b, ilen);
-               break;
-       case 'H':
-               rv = enc16(out, len, b, ilen);
-               break;
-       default:
-               rv = -1;
-               break;
-       }
+       rv = enc16(out, len, b, ilen);
        if(rv < 0)
                goto error;
 
@@ -1819,7 +1779,9 @@ dnptr(uchar *net, uchar *mask, char *dom, int forwtype, int subdoms, int ttl)
        for(rp = first; rp != nil; rp = nrp){
                nrp = rp->next;
                rp->next = nil;
+               dp = rp->owner;
                rrattach(rp, Authoritative);
+               dnagenever(dp);
        }
 }