diff options
author | cinap_lenrek <cinap_lenrek@flatbox.9hal> | 2012-03-09 06:02:17 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@flatbox.9hal> | 2012-03-09 06:02:17 +0100 |
commit | 0d926a251269277214ab0ce5e84f5c4674576d6f (patch) | |
tree | 98b9399d29bd6555f870b084152b8a89e71bbbba /sys/src/cmd/ndb | |
parent | f7bc3526b3acfe70263167e0a78dbb4a4050c6e4 (diff) |
dns: import changes from sources
Diffstat (limited to 'sys/src/cmd/ndb')
-rw-r--r-- | sys/src/cmd/ndb/convM2DNS.c | 61 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dblookup.c | 21 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dn.c | 62 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dnarea.c | 2 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dnresolve.c | 237 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dnsdebug.c | 2 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dnserver.c | 10 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dnudpserver.c | 8 | ||||
-rw-r--r-- | sys/src/cmd/ndb/inform.c | 18 | ||||
-rw-r--r-- | sys/src/cmd/ndb/mkhash.c | 2 |
10 files changed, 267 insertions, 156 deletions
diff --git a/sys/src/cmd/ndb/convM2DNS.c b/sys/src/cmd/ndb/convM2DNS.c index 1434c334d..047b1bbec 100644 --- a/sys/src/cmd/ndb/convM2DNS.c +++ b/sys/src/cmd/ndb/convM2DNS.c @@ -6,9 +6,9 @@ typedef struct Scan Scan; struct Scan { - uchar *base; - uchar *p; - uchar *ep; + uchar *base; /* input buffer */ + uchar *p; /* current position */ + uchar *ep; /* byte after the end */ char *err; char errbuf[256]; /* hold a formatted error sometimes */ @@ -17,16 +17,6 @@ struct Scan int trunc; /* flag: input truncated */ }; -#define NAME(x) gname(x, rp, sp) -#define SYMBOL(x) (x = gsym(rp, sp)) -#define STRING(x) (x = gstr(rp, sp)) -#define USHORT(x) (x = gshort(rp, sp)) -#define ULONG(x) (x = glong(rp, sp)) -#define UCHAR(x) (x = gchar(rp, sp)) -#define V4ADDR(x) (x = gv4addr(rp, sp)) -#define V6ADDR(x) (x = gv6addr(rp, sp)) -#define BYTES(x, y) (y = gbytes(rp, sp, &x, len - (sp->p - data))) - static int errneg(RR *rp, Scan *sp, int actual) { @@ -56,7 +46,7 @@ errtoolong(RR *rp, Scan *sp, int remain, int need, char *where) /* hack to cope with servers that don't set Ftrunc when they should */ if (remain < Maxudp && need > Maxudp) sp->trunc = 1; - if (debug) + if (debug && rp) dnslog("malformed rr: %R", rp); return 0; } @@ -236,6 +226,10 @@ gname(char *to, RR *rp, Scan *sp) goto err; pointer = 0; p = sp->p; + if (p == nil) { + dnslog("gname: %R: nil sp->p", rp); + goto err; + } toend = to + Domlen; for(len = 0; *p && p < sp->ep; len += (pointer? 0: n+1)) { n = 0; @@ -312,24 +306,35 @@ mstypehack(Scan *sp, ushort type, char *where) // where); if (sp->rcode == Rok) sp->rcode = Rformat; - return (uchar)type << 8 | type >> 8; + type >>= 8; } return type; } +#define NAME(x) gname(x, rp, sp) +#define SYMBOL(x) ((x) = gsym(rp, sp)) +#define STRING(x) ((x) = gstr(rp, sp)) +#define USHORT(x) ((x) = gshort(rp, sp)) +#define ULONG(x) ((x) = glong(rp, sp)) +#define UCHAR(x) ((x) = gchar(rp, sp)) +#define V4ADDR(x) ((x) = gv4addr(rp, sp)) +#define V6ADDR(x) ((x) = gv6addr(rp, sp)) +#define BYTES(x, y) ((y) = gbytes(rp, sp, &(x), len - (sp->p - data))) + /* * convert the next RR from a message */ static RR* convM2RR(Scan *sp, char *what) { - int type, class, len; + int type, class, len, left; char dname[Domlen+1]; uchar *data; - RR *rp = nil; + RR *rp; Txt *t, **l; retry: + rp = nil; NAME(dname); USHORT(type); USHORT(class); @@ -341,8 +346,10 @@ retry: ULONG(rp->ttl); rp->ttl += now; - USHORT(len); + USHORT(len); /* length of data following */ data = sp->p; + assert(data != nil); + left = sp->ep - sp->p; /* * ms windows generates a lot of badly-formatted hints. @@ -350,21 +357,23 @@ retry: * it also generates answers in which p overshoots ep by exactly * one byte; this seems to be harmless, so don't log them either. */ - if (sp->ep - sp->p < len && + if (len > left && !(strcmp(what, "hints") == 0 || sp->p == sp->ep + 1 && strcmp(what, "answers") == 0)) - errtoolong(rp, sp, sp->ep - sp->p, len, "convM2RR"); + errtoolong(rp, sp, left, len, "convM2RR"); if(sp->err || sp->rcode || sp->stop){ rrfree(rp); return nil; } + /* even if we don't log an error message, truncate length to fit data */ + if (len > left) + len = left; switch(type){ default: /* unknown type, just ignore it */ sp->p = data + len; rrfree(rp); - rp = nil; goto retry; case Thinfo: SYMBOL(rp->cpu); @@ -493,8 +502,9 @@ convM2Q(Scan *sp) { char dname[Domlen+1]; int type, class; - RR *rp = nil; + RR *rp; + rp = nil; NAME(dname); USHORT(type); USHORT(class); @@ -535,7 +545,8 @@ rrloop(Scan *sp, char *what, int count, int quest) *l = rp; l = &rp->next; } -// setmalloctag(first, getcallerpc(&sp)); +// if(first) +// setmalloctag(first, getcallerpc(&sp)); return first; } @@ -553,15 +564,15 @@ convM2DNS(uchar *buf, int len, DNSmsg *m, int *codep) Scan scan; Scan *sp; - if (codep) - *codep = Rok; assert(len >= 0); + assert(buf != nil); sp = &scan; memset(sp, 0, sizeof *sp); sp->base = sp->p = buf; sp->ep = buf + len; sp->err = nil; sp->errbuf[0] = '\0'; + sp->rcode = Rok; memset(m, 0, sizeof *m); USHORT(m->id); diff --git a/sys/src/cmd/ndb/dblookup.c b/sys/src/cmd/ndb/dblookup.c index a704983c4..5c3995f7e 100644 --- a/sys/src/cmd/ndb/dblookup.c +++ b/sys/src/cmd/ndb/dblookup.c @@ -100,28 +100,25 @@ dblookup(char *name, int class, int type, int auth, int ttl) char buf[256]; RR *rp, *tp; DN *dp, *ndp; - static int parallel; - static int parfd[2]; - static char token[1]; /* so far only internet lookups are implemented */ if(class != Cin) return 0; err = Rname; + rp = nil; if(type == Tall){ - lock(&dnlock); - rp = nil; for (type = Ta; type < Tall; type++) - if(implemented[type]) - rrcat(&rp, dblookup(name, class, type, auth, ttl)); - unlock(&dnlock); + if(implemented[type]) { + tp = dblookup(name, class, type, auth, ttl); + lock(&dnlock); + rrcat(&rp, tp); + unlock(&dnlock); + } return rp; } - rp = nil; - lock(&dblock); dp = dnlookup(name, class, 1); @@ -1199,13 +1196,15 @@ insideaddr(char *dom) if (!cfg.inside || !cfg.straddle || !cfg.serve) return 1; + if (dom[0] == '\0' || strcmp(dom, ".") == 0) /* dns root? */ + return 1; /* hack for initialisation */ lock(&dblock); if (indoms == nil) loaddomsrvs(); if (indoms == nil) { unlock(&dblock); - return 1; /* no "inside" sys, try inside nameservers */ + return 1; /* no "inside-dom" sys, try inside nameservers */ } rv = 0; diff --git a/sys/src/cmd/ndb/dn.c b/sys/src/cmd/ndb/dn.c index 0c5e2677e..9f0c70a9c 100644 --- a/sys/src/cmd/ndb/dn.c +++ b/sys/src/cmd/ndb/dn.c @@ -14,11 +14,14 @@ * figure it out. */ enum { - Deftarget = 8000, -}; -enum { - Minage = 10*60, - Defagefreq = 30*60, /* age names this often (seconds) */ + 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) */ }; /* @@ -339,13 +342,20 @@ dnpurge(void) } /* - * delete rp from *l, free rp. + * delete head of *l and free the old head. * call with dnlock held. */ static void -rrdelete(RR **l, RR *rp) +rrdelhead(RR **l) { - *l = rp->next; + RR *rp; + + if (canlock(&dnlock)) + abort(); /* rrdelhead called with dnlock not held */ + rp = *l; + if(rp == nil) + return; + *l = rp->next; /* unlink head */ rp->cached = 0; /* avoid blowing an assertion in rrfree */ rrfree(rp); } @@ -361,6 +371,8 @@ dnage(DN *dp) RR *rp, *next; ulong diff; + if (canlock(&dnlock)) + abort(); /* dnage called with dnlock not held */ diff = now - dp->referenced; if(diff < Reserved || dp->keep) return; @@ -370,7 +382,7 @@ dnage(DN *dp) assert(rp->magic == RRmagic && rp->cached); next = rp->next; if(!rp->db && (rp->expire < now || diff > dnvars.oldest)) - rrdelete(l, rp); + rrdelhead(l); /* rp == *l before; *l == rp->next after */ else l = &rp->next; } @@ -783,8 +795,9 @@ rrattach1(RR *new, int auth) if(rp->db == new->db && rp->auth == new->auth){ /* negative drives out positive and vice versa */ if(rp->negative != new->negative) { - rrdelete(l, rp); - continue; /* *l == rp->next */ + /* rp == *l before; *l == rp->next after */ + rrdelhead(l); + continue; } /* all things equal, pick the newer one */ else if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){ @@ -794,8 +807,9 @@ rrattach1(RR *new, int auth) rrfree(new); return; } - rrdelete(l, rp); - continue; /* *l == rp->next */ + /* rp == *l before; *l == rp->next after */ + rrdelhead(l); + continue; } /* * Hack for pointer records. This makes sure @@ -833,7 +847,7 @@ rrattach1(RR *new, int auth) void rrattach(RR *rp, int auth) { - RR *next; + RR *next, *tp; DN *dp; lock(&dnlock); @@ -842,17 +856,20 @@ rrattach(RR *rp, int auth) rp->next = nil; dp = rp->owner; - /* avoid any outside spoofing */ // dnslog("rrattach: %s", rp->owner->name); - if(cfg.cachedb && !rp->db && inmyarea(rp->owner->name)) + /* avoid any outside spoofing; leave keepers alone */ + if(cfg.cachedb && !rp->db && inmyarea(rp->owner->name) +// || dp->keep /* TODO: make this work */ + ) rrfree(rp); else { - /* ameliorate the memory leak */ + /* ameliorate the memory leak (someday delete this) */ if (0 && rrlistlen(dp->rr) > 50 && !dp->keep) { dnslog("rrattach(%s): rr list too long; " "freeing it", dp->name); - rrfreelist(dp->rr); + tp = dp->rr; dp->rr = nil; + rrfreelist(tp); } else USED(dp); rrattach1(rp, auth); @@ -873,6 +890,8 @@ rrcopy(RR *rp, RR **last) Sig *sig; Txt *t, *nt, **l; + if (canlock(&dnlock)) + abort(); /* rrcopy called with dnlock not held */ nrp = rralloc(rp->type); setmalloctag(nrp, getcallerpc(&rp)); switch(rp->type){ @@ -1024,8 +1043,8 @@ rrlookup(DN *dp, int type, int flag) } out: - unlock(&dnlock); unique(first); + unlock(&dnlock); // dnslog("rrlookup(%s) -> %#p\t# in-core only", dp->name, first); // if (first) // setmalloctag(first, getcallerpc(&dp)); @@ -1084,6 +1103,8 @@ rrcat(RR **start, RR *rp) RR *olp, *nlp; RR **last; + if (canlock(&dnlock)) + abort(); /* rrcat called with dnlock not held */ /* check for duplicates */ for (olp = *start; 0 && olp; olp = olp->next) for (nlp = rp; nlp; nlp = nlp->next) @@ -1108,6 +1129,8 @@ rrremneg(RR **l) RR **nl, *rp; RR *first; + if (canlock(&dnlock)) + abort(); /* rrremneg called with dnlock not held */ first = nil; nl = &first; while(*l != nil){ @@ -1573,6 +1596,7 @@ rrequiv(RR *r1, RR *r2) && r1->arg1 == r2->arg1; } +/* called with dnlock held */ void unique(RR *rp) { diff --git a/sys/src/cmd/ndb/dnarea.c b/sys/src/cmd/ndb/dnarea.c index ca680219c..deb2ac506 100644 --- a/sys/src/cmd/ndb/dnarea.c +++ b/sys/src/cmd/ndb/dnarea.c @@ -91,8 +91,10 @@ freearea(Area **l) while(s = *l){ *l = s->next; + lock(&dnlock); rrfree(s->soarr); memset(s, 0, sizeof *s); /* cause trouble */ + unlock(&dnlock); free(s); } } diff --git a/sys/src/cmd/ndb/dnresolve.c b/sys/src/cmd/ndb/dnresolve.c index d5539ff11..bcdd69d5f 100644 --- a/sys/src/cmd/ndb/dnresolve.c +++ b/sys/src/cmd/ndb/dnresolve.c @@ -16,13 +16,27 @@ enum { Udp, Tcp, + Answerr= -1, + Answnone, + Maxdest= 24, /* maximum destinations for a request message */ - Maxtrans= 3, /* maximum transmissions to a server */ - Maxretries= 3, /* cname+actual resends: was 32; have pity on user */ - Maxwaitms= 1000, /* wait no longer for a remote dns query */ - Minwaitms= 100, /* willing to wait for a remote dns query */ - Remntretry= 15, /* min. sec.s between /net.alt remount tries */ Maxoutstanding= 15, /* max. outstanding queries per domain name */ + Remntretry= 15, /* min. sec.s between /net.alt remount tries */ + + /* + * these are the old values; we're trying longer timeouts now + * primarily for the benefit of remote nameservers querying us + * during times of bad connectivity. + */ +// Maxtrans= 3, /* maximum transmissions to a server */ +// Maxretries= 3, /* cname+actual resends: was 32; have pity on user */ +// Maxwaitms= 1000, /* wait no longer for a remote dns query */ +// Minwaitms= 100, /* willing to wait for a remote dns query */ + + Maxtrans= 5, /* maximum transmissions to a server */ + Maxretries= 5, /* cname+actual resends: was 32; have pity on user */ + Maxwaitms= 5000, /* wait no longer for a remote dns query */ + Minwaitms= 500, /* willing to wait for a remote dns query */ Destmagic= 0xcafebabe, Querymagic= 0xdeadbeef, @@ -58,8 +72,8 @@ struct Query { /* dest must not be on the stack due to forking in slave() */ Dest *dest; /* array of destinations */ - Dest *curdest; /* pointer to one of them */ - int ndest; + Dest *curdest; /* pointer to next to fill */ + int ndest; /* transmit to this many on this round */ int udpfd; @@ -116,6 +130,18 @@ procgetname(void) return strdup(lp+1); } +void +rrfreelistptr(RR **rpp) +{ + RR *rp; + + if (rpp == nil || *rpp == nil) + return; + rp = *rpp; + *rpp = nil; /* update pointer in memory before freeing list */ + rrfreelist(rp); +} + /* * lookup 'type' info for domain name 'name'. If it doesn't exist, try * looking it up as a canonical name. @@ -264,12 +290,6 @@ destck(Dest *p) assert(p->magic == Destmagic); } -static void -destdestroy(Dest *p) -{ - USED(p); -} - /* * if the response to a query hasn't arrived within 100 ms., * it's unlikely to arrive at all. after 1 s., it's really unlikely. @@ -308,6 +328,20 @@ noteinmem(void) qunlock(&stats); } +/* netquery with given name servers, free ns rrs when done */ +static int +netqueryns(Query *qp, int depth, RR *nsrp) +{ + int rv; + + qp->nsrp = nsrp; + rv = netquery(qp, depth); + lock(&dnlock); + rrfreelist(nsrp); + unlock(&dnlock); + return rv; +} + static RR* issuequery(Query *qp, char *name, int class, int depth, int recurse) { @@ -321,14 +355,9 @@ issuequery(Query *qp, char *name, int class, int depth, int recurse) */ if(cfg.resolver){ nsrp = randomize(getdnsservers(class)); - if(nsrp != nil) { - qp->nsrp = nsrp; - if(netquery(qp, depth+1)){ - rrfreelist(nsrp); + if(nsrp != nil) + if(netqueryns(qp, depth+1, nsrp) > Answnone) return rrlookup(qp->dp, qp->type, OKneg); - } - rrfreelist(nsrp); - } } /* @@ -343,7 +372,9 @@ issuequery(Query *qp, char *name, int class, int depth, int recurse) dbnsrp = randomize(dblookup(cp, class, Tns, 0, 0)); if(dbnsrp && dbnsrp->local){ rp = dblookup(name, class, qp->type, 1, dbnsrp->ttl); + lock(&dnlock); rrfreelist(dbnsrp); + unlock(&dnlock); return rp; } @@ -352,8 +383,11 @@ issuequery(Query *qp, char *name, int class, int depth, int recurse) * entries */ if(recurse == Dontrecurse){ - if(dbnsrp) + if(dbnsrp) { + lock(&dnlock); rrfreelist(dbnsrp); + unlock(&dnlock); + } continue; } @@ -365,34 +399,23 @@ issuequery(Query *qp, char *name, int class, int depth, int recurse) /* if the entry timed out, ignore it */ if(nsrp && nsrp->ttl < now){ - rrfreelist(nsrp); - nsrp = nil; + lock(&dnlock); + rrfreelistptr(&nsrp); + unlock(&dnlock); } if(nsrp){ - rrfreelist(dbnsrp); + lock(&dnlock); + rrfreelistptr(&dbnsrp); + unlock(&dnlock); /* query the name servers found in cache */ - qp->nsrp = nsrp; - if(netquery(qp, depth+1)){ - rrfreelist(nsrp); + if(netqueryns(qp, depth+1, nsrp) > Answnone) return rrlookup(qp->dp, qp->type, OKneg); - } - rrfreelist(nsrp); - continue; - } - - /* use ns from db */ - if(dbnsrp){ + } else if(dbnsrp) /* try the name servers found in db */ - qp->nsrp = dbnsrp; - if(netquery(qp, depth+1)){ - /* we got an answer */ - rrfreelist(dbnsrp); + if(netqueryns(qp, depth+1, dbnsrp) > Answnone) return rrlookup(qp->dp, qp->type, NOneg); - } - rrfreelist(dbnsrp); - } } return nil; } @@ -440,7 +463,9 @@ dnresolve1(char *name, int class, int type, Request *req, int depth, getpid(), name, type, class); return rp; } + lock(&dnlock); rrfreelist(rp); + unlock(&dnlock); rp = nil; /* accident prevention */ USED(rp); @@ -451,7 +476,9 @@ dnresolve1(char *name, int class, int type, Request *req, int depth, */ if(type != Tcname){ rp = rrlookup(dp, Tcname, NOneg); + lock(&dnlock); rrfreelist(rp); + unlock(&dnlock); if(rp){ if(debug) dnslog("[%d] dnresolve1 %s %d %d: rr from rrlookup for non-cname", @@ -569,6 +596,8 @@ initdnsmsg(DNSmsg *mp, RR *rp, int flags, ushort reqno) mp->flags = flags; mp->id = reqno; mp->qd = rp; + if(rp != nil) + mp->qdcount = 1; } DNSmsg * @@ -600,7 +629,7 @@ mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno) rp->owner = dp; initdnsmsg(&m, rp, flags, reqno); len = convDNS2M(&m, &buf[Udphdrsize], Maxudp); - rrfree(m.qd); + rrfreelistptr(&m.qd); memset(&m, 0, sizeof m); /* cause trouble */ return len; } @@ -608,14 +637,16 @@ mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno) void freeanswers(DNSmsg *mp) { - rrfreelist(mp->qd); - rrfreelist(mp->an); - rrfreelist(mp->ns); - rrfreelist(mp->ar); - mp->qd = mp->an = mp->ns = mp->ar = nil; + lock(&dnlock); + rrfreelistptr(&mp->qd); + rrfreelistptr(&mp->an); + rrfreelistptr(&mp->ns); + rrfreelistptr(&mp->ar); + unlock(&dnlock); + mp->qdcount = mp->ancount = mp->nscount = mp->arcount = 0; } -/* timed read of reply. sets srcip */ +/* timed read of reply. sets srcip. ibuf must be 64K to handle tcp answers. */ static int readnet(Query *qp, int medium, uchar *ibuf, uvlong endms, uchar **replyp, uchar *srcip) @@ -656,7 +687,7 @@ readnet(Query *qp, int medium, uchar *ibuf, uvlong endms, uchar **replyp, dnslog("readnet: %s: tcp fd unset for dest %I", qp->dp->name, qp->tcpip); else if (readn(fd, lenbuf, 2) != 2) { - dnslog("readnet: short read of tcp size from %I", + dnslog("readnet: short read of 2-byte tcp msg size from %I", qp->tcpip); /* probably a time-out */ notestats(startns, 1, qp->type); @@ -792,7 +823,7 @@ ipisbm(uchar *ip) } /* - * Get next server address + * Get next server address(es) into qp->dest[nd] and beyond */ static int serveraddrs(Query *qp, int nd, int depth) @@ -800,8 +831,8 @@ serveraddrs(Query *qp, int nd, int depth) RR *rp, *arp, *trp; Dest *cur; - if(nd >= Maxdest) - return 0; + if(nd >= Maxdest) /* dest array is full? */ + return Maxdest - 1; /* * look for a server whose address we already know. @@ -875,7 +906,9 @@ serveraddrs(Query *qp, int nd, int depth) cur->code = Rtimeout; nd++; } + lock(&dnlock); rrfreelist(arp); + unlock(&dnlock); return nd; } @@ -893,10 +926,10 @@ cacheneg(DN *dp, int type, int rcode, RR *soarr) /* no cache time specified, don't make anything up */ if(soarr != nil){ - if(soarr->next != nil){ - rrfreelist(soarr->next); - soarr->next = nil; - } + lock(&dnlock); + if(soarr->next != nil) + rrfreelistptr(&soarr->next); + unlock(&dnlock); soaowner = soarr->owner; } else soaowner = nil; @@ -945,7 +978,7 @@ mydnsquery(Query *qp, int medium, uchar *udppkt, int len) { int rv = -1, nfd; char *domain; - char conndir[40]; + char conndir[40], net[40]; uchar belen[2]; NetConnInfo *nci; @@ -984,8 +1017,10 @@ mydnsquery(Query *qp, int medium, uchar *udppkt, int len) break; case Tcp: /* send via TCP & keep fd around for reply */ + snprint(net, sizeof net, "%s/tcp", + (mntpt[0] != '\0'? mntpt: "/net")); alarm(10*1000); - qp->tcpfd = rv = dial(netmkaddr(domain, "tcp", "dns"), nil, + qp->tcpfd = rv = dial(netmkaddr(domain, net, "dns"), nil, conndir, &qp->tcpctlfd); alarm(0); if (qp->tcpfd < 0) { @@ -1035,8 +1070,14 @@ xmitquery(Query *qp, int medium, int depth, uchar *obuf, int inns, int len) */ p = qp->dest; destck(p); - if (qp->ndest < 0 || qp->ndest > Maxdest) + if (qp->ndest < 0 || qp->ndest > Maxdest) { dnslog("qp->ndest %d out of range", qp->ndest); + abort(); + } + /* + * we're to transmit to more destinations than we currently have, + * so get another. + */ if (qp->ndest > qp->curdest - p) { j = serveraddrs(qp, qp->curdest - p, depth); if (j < 0 || j >= Maxdest) { @@ -1051,15 +1092,16 @@ xmitquery(Query *qp, int medium, int depth, uchar *obuf, int inns, int len) if (qp->ndest == 0) if (cfg.straddle && cfg.inside) { /* get ips of "outside-ns-ips" */ - p = qp->curdest = qp->dest; + qp->curdest = qp->dest; for(n = 0; n < Maxdest; n++, qp->curdest++) if (setdestoutns(qp->curdest, n) < 0) break; - } else { + if(n == 0) + dnslog("xmitquery: %s: no outside-ns nameservers", + qp->dp->name); + } else /* it's probably just a bogus domain, don't log it */ - // dnslog("xmitquery: %s: no nameservers", qp->dp->name); return -1; - } /* send to first 'qp->ndest' destinations */ j = 0; @@ -1085,6 +1127,9 @@ xmitquery(Query *qp, int medium, int depth, uchar *obuf, int inns, int len) if((1<<p->nx) > qp->ndest) continue; + if(memcmp(p->a, IPnoaddr, sizeof IPnoaddr) == 0) + continue; /* mistake */ + procsetname("udp %sside query to %I/%s %s %s", (inns? "in": "out"), p->a, p->s->name, qp->dp->name, rrname(qp->type, buf, sizeof buf)); @@ -1098,7 +1143,6 @@ xmitquery(Query *qp, int medium, int depth, uchar *obuf, int inns, int len) p->nx++; } if(j == 0) { - // dnslog("xmitquery: %s: no destinations left", qp->dp->name); return -1; } return 0; @@ -1135,6 +1179,7 @@ isnegrname(DNSmsg *mp) return mp->an == nil && (mp->flags & Rmask) == Rname; } +/* returns Answerr (-1) on errors, else number of answers, which can be zero. */ static int procansw(Query *qp, DNSmsg *mp, uchar *srcip, int depth, Dest *p) { @@ -1154,7 +1199,7 @@ procansw(Query *qp, DNSmsg *mp, uchar *srcip, int depth, Dest *p) freeanswers(mp); if(p != qp->curdest) p->code = Rserver; - return -1; + return Answerr; } /* ignore any bad delegations */ @@ -1165,10 +1210,14 @@ procansw(Query *qp, DNSmsg *mp, uchar *srcip, int depth, Dest *p) freeanswers(mp); if(p != qp->curdest) p->code = Rserver; - return -1; + dnslog(" and no answers"); + return Answerr; } - rrfreelist(mp->ns); - mp->ns = nil; + dnslog(" but has answers; ignoring ns"); + lock(&dnlock); + rrfreelistptr(&mp->ns); + unlock(&dnlock); + mp->nscount = 0; } /* remove any soa's from the authority section */ @@ -1180,6 +1229,7 @@ procansw(Query *qp, DNSmsg *mp, uchar *srcip, int depth, Dest *p) unique(mp->ns); unique(mp->ar); unlock(&dnlock); + if(mp->an) rrattach(mp->an, (mp->flags & Fauth) != 0); if(mp->ar) @@ -1189,14 +1239,18 @@ procansw(Query *qp, DNSmsg *mp, uchar *srcip, int depth, Dest *p) rrattach(mp->ns, Notauthoritative); } else { ndp = nil; - rrfreelist(mp->ns); - mp->ns = nil; + lock(&dnlock); + rrfreelistptr(&mp->ns); + unlock(&dnlock); + mp->nscount = 0; } /* free the question */ if(mp->qd) { - rrfreelist(mp->qd); - mp->qd = nil; + lock(&dnlock); + rrfreelistptr(&mp->qd); + unlock(&dnlock); + mp->qdcount = 0; } /* @@ -1217,8 +1271,11 @@ procansw(Query *qp, DNSmsg *mp, uchar *srcip, int depth, Dest *p) */ if( /* (mp->flags & Fauth) && */ mp->an == nil) cacheneg(qp->dp, qp->type, (mp->flags & Rmask), soarr); - else + else { + lock(&dnlock); rrfreelist(soarr); + unlock(&dnlock); + } return 1; } else if (isnegrname(mp)) { qp->dp->respcode = Rname; @@ -1231,7 +1288,9 @@ procansw(Query *qp, DNSmsg *mp, uchar *srcip, int depth, Dest *p) return 1; } stats.negnorname++; + lock(&dnlock); rrfreelist(soarr); + unlock(&dnlock); /* * if we've been given better name servers, recurse. @@ -1239,11 +1298,13 @@ procansw(Query *qp, DNSmsg *mp, uchar *srcip, int depth, Dest *p) * to forward to a fixed set of named servers. */ if(!mp->ns || cfg.resolver && cfg.justforw) - return 0; + return Answnone; tp = rrlookup(ndp, Tns, NOneg); if(contains(qp->nsrp, tp)){ + lock(&dnlock); rrfreelist(tp); - return 0; + unlock(&dnlock); + return Answnone; } procsetname("recursive query for %s %s", qp->dp->name, rrname(qp->type, buf, sizeof buf)); @@ -1252,7 +1313,7 @@ procansw(Query *qp, DNSmsg *mp, uchar *srcip, int depth, Dest *p) * netquery, which current holds qp->dp->querylck, * so release it now and acquire it upon return. */ -// lcktype = qtype2lck(qp->type); +// lcktype = qtype2lck(qp->type); /* someday try this again */ // qunlock(&qp->dp->querylck[lcktype]); nqp = emalloc(sizeof *nqp); @@ -1303,7 +1364,8 @@ tcpquery(Query *qp, DNSmsg *mp, int depth, uchar *ibuf, uchar *obuf, int len, } /* - * query name servers. If the name server returns a pointer to another + * query name servers. fill in obuf with on-the-wire representation of a + * DNSmsg derived from qp. if the name server returns a pointer to another * name server, recurse. */ static int @@ -1383,7 +1445,7 @@ queryns(Query *qp, int depth, uchar *ibuf, uchar *obuf, ulong waitms, int inns) /* free or incorporate RRs in m */ rv = procansw(qp, &m, srcip, depth, p); - if (rv > 0) { + if (rv > Answnone) { free(qp->dest); qp->dest = qp->curdest = nil; /* prevent accidents */ return rv; @@ -1405,7 +1467,7 @@ queryns(Query *qp, int depth, uchar *ibuf, uchar *obuf, ulong waitms, int inns) free(qp->dest); qp->dest = qp->curdest = nil; /* prevent accidents */ - return 0; + return Answnone; } /* @@ -1465,7 +1527,6 @@ udpquery(Query *qp, char *mntpt, int depth, int patient, int inns) static ulong lastmount; /* use alloced buffers rather than ones from the stack */ - // ibuf = emalloc(Maxudpin+Udphdrsize); ibuf = emalloc(64*1024); /* max. tcp reply size */ obuf = emalloc(Maxudp+Udphdrsize); @@ -1537,9 +1598,9 @@ netquery(Query *qp, int depth) Querylck *qlp; static int whined; - rv = 0; /* pessimism */ + rv = Answnone; /* pessimism */ if(depth > 12) /* in a recursive loop? */ - return 0; + return Answnone; slave(qp->req); /* @@ -1604,7 +1665,7 @@ netquery(Query *qp, int depth) * if we're still looking, are inside, and have an outside domain, * try it on our outside interface, if any. */ - if (rv == 0 && cfg.inside && !inname) { + if (rv == Answnone && cfg.inside && !inname) { if (triedin) dnslog( "[%d] netquery: internal nameservers failed for %s; trying external", @@ -1616,7 +1677,7 @@ netquery(Query *qp, int depth) rv = udpquery(qp, "/net.alt", depth, Patient, Outns); } -// if (rv == 0) /* could ask /net.alt/dns directly */ +// if (rv == Answnone) /* could ask /net.alt/dns directly */ // askoutdns(dp, qp->type); if(lock && qlp) { @@ -1634,17 +1695,21 @@ seerootns(void) int rv; char root[] = ""; Request req; + RR *rr; Query *qp; memset(&req, 0, sizeof req); req.isslave = 1; req.aborttime = timems() + Maxreqtm; req.from = "internal"; + qp = emalloc(sizeof *qp); queryinit(qp, dnlookup(root, Cin, 1), Tns, &req); - qp->nsrp = dblookup(root, Cin, Tns, 0, 0); - rv = netquery(qp, 0); + for (rr = qp->nsrp; rr != nil; rr = rr->next) /* DEBUG */ + dnslog("seerootns query nsrp: %R", rr); + + rv = netquery(qp, 0); /* lookup ". ns" using qp->nsrp */ rrfreelist(qp->nsrp); querydestroy(qp); diff --git a/sys/src/cmd/ndb/dnsdebug.c b/sys/src/cmd/ndb/dnsdebug.c index 28ecf9a1c..8a9623f11 100644 --- a/sys/src/cmd/ndb/dnsdebug.c +++ b/sys/src/cmd/ndb/dnsdebug.c @@ -343,7 +343,9 @@ preloadserveraddrs(void) l = &first; for(rp = serveraddrs; rp != nil; rp = rp->next){ + lock(&dnlock); rrcopy(rp, l); + unlock(&dnlock); rrattach(first, Authoritative); } } diff --git a/sys/src/cmd/ndb/dnserver.c b/sys/src/cmd/ndb/dnserver.c index f3fd8fd07..801fa2213 100644 --- a/sys/src/cmd/ndb/dnserver.c +++ b/sys/src/cmd/ndb/dnserver.c @@ -20,7 +20,7 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip, int rcode) char tname[32]; DN *nsdp, *dp; Area *myarea; - RR *tp, *neg; + RR *tp, *neg, *rp; dncheck(nil, 1); @@ -109,8 +109,11 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip, int rcode) if(repp->ns){ /* don't pass on anything we know is wrong */ if(repp->ns->negative){ - rrfreelist(repp->ns); + lock(&dnlock); + rp = repp->ns; repp->ns = nil; + rrfreelist(rp); + unlock(&dnlock); } break; } @@ -216,8 +219,9 @@ hint(RR **last, RR *rp) hp = dblookup(rp->host->name, Cin, Taaaa, 0, 0); if (hp && strncmp(hp->owner->name, "local#", 6) == 0) dnslog("returning %s as hint", hp->owner->name); + lock(&dnlock); rrcat(last, hp); + unlock(&dnlock); break; } } -
\ No newline at end of file diff --git a/sys/src/cmd/ndb/dnudpserver.c b/sys/src/cmd/ndb/dnudpserver.c index 6898f8a15..fd7ef1eab 100644 --- a/sys/src/cmd/ndb/dnudpserver.c +++ b/sys/src/cmd/ndb/dnudpserver.c @@ -283,19 +283,21 @@ udpannounce(char *mntpt) ctl = announce(datafile, dir); if(ctl < 0){ if(!whined++) - warning("can't announce on dns udp port"); + warning("can't announce on %s", datafile); return -1; } - snprint(datafile, sizeof(datafile), "%s/data", dir); /* turn on header style interface */ if(write(ctl, hmsg, strlen(hmsg)) != strlen(hmsg)) abort(); /* hmsg */ + + snprint(datafile, sizeof(datafile), "%s/data", dir); data = open(datafile, ORDWR); if(data < 0){ close(ctl); if(!whined++) - warning("can't announce on dns udp port"); + warning("can't open %s to announce on dns udp port", + datafile); return -1; } diff --git a/sys/src/cmd/ndb/inform.c b/sys/src/cmd/ndb/inform.c index 6398f7c07..58e3936fd 100644 --- a/sys/src/cmd/ndb/inform.c +++ b/sys/src/cmd/ndb/inform.c @@ -24,11 +24,6 @@ char *errmsgs[] = { [10] "domain name not in zone", }; -char *dnsrch[] = { - "dnsdomain", - "dom", -}; - void usage(void) { @@ -98,12 +93,12 @@ main(int argc, char *argv[]) { int debug, len, fd; uint err; - char *sysname, *dnsdomain, *dom, *ns, net[32]; + char *sysname, *dnsdomain, *dom, *inform, *ns, net[32]; uchar *p, buf[4096], addr[IPv4addrlen], v6addr[IPaddrlen]; ushort txid; Ndb *db; Ndbtuple *t, *tt; - static char *query[] = { "dom", "dnsdomain", "ns", }; + static char *query[] = { "dom", "dnsdomain", "ns", "inform" }; fmtinstall('I', eipfmt); fmtinstall('V', eipfmt); @@ -112,6 +107,7 @@ main(int argc, char *argv[]) debug = 0; ns = nil; dom = nil; + inform = nil; dnsdomain = nil; ARGBEGIN{ case 'd': @@ -133,16 +129,22 @@ main(int argc, char *argv[]) if((db = ndbopen(nil)) == nil) sysfatal("can't open ndb: %r"); tt = ndbipinfo(db, "sys", sysname, query, nelem(query)); - for(t = tt; t; t = t->entry) + for(t = tt; t; t = t->entry){ if(strcmp(t->attr, "ns") == 0) ns = t->val; else if(strcmp(t->attr, "dom") == 0) dom = t->val; else if(strcmp(t->attr, "dnsdomain") == 0) dnsdomain = t->val; + else if(strcmp(t->attr, "inform") == 0) + inform = t->val; + } + ndbfree(tt); ndbclose(db); + if(inform) + dom = inform; if(!ns) sysfatal("no relevant ns="); if(!dom) diff --git a/sys/src/cmd/ndb/mkhash.c b/sys/src/cmd/ndb/mkhash.c index 507bd7c78..00a1ee595 100644 --- a/sys/src/cmd/ndb/mkhash.c +++ b/sys/src/cmd/ndb/mkhash.c @@ -76,7 +76,7 @@ main(int argc, char **argv) uchar *p; if(argc != 3){ - fprint(2, "mkhash: usage file attribute\n"); + fprint(2, "usage: mkhash file attribute\n"); exits("usage"); } db = ndbopen(argv[1]); |