ref: 6320d483b2be10793461e92cc60aad4a59a29cfd
parent: b31f1df1d643e39a29ea565ad9836e25261dbbc7
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Wed Aug 29 15:01:05 EDT 2012
ndb/dns: bug fixes and massive cleanup removing the querylck from the DN as it was never used or being effective which saves like a ton on space per domain name. remove the Query.tcplock and put query on the stack. it is unneccesary to lock the query as its only used by one process at a time. put Query's on the stack. change outsidens() to outsidensip() which now takes the ip buffer that it fills instead of returning static buffer (which would race with multiple processes involved). eleminate mostly all of the lock(&dnlock)/unlock(&dnlock) calls. we'r not working on shared cache RR's in the resolver procs. we work on *copies* done by rrlookup() made under the dnlock. the cache garbage collection only runs when all processes are locked out and is also taking the dnlock while doing so. cleanup xmitquery(). for the tcp case, we dont need to get more nameserver addresses, just take the ip from the udp header that tcpquery() placed there for us. fixed baddelegation() to actually check for delegation loop even if theres no dom info for our host. remove lots of debug code. remove the dnforceage() as it doenst make sure other processes are locked out. this could destroy dn's currenctly refered by running queries. remove dnageallnever() as its not used. dont attach rr's to keepers to prevent outside spoofing. make myaddr() retrive the ip address if not set.
--- a/sys/src/cmd/ndb/dblookup.c
+++ b/sys/src/cmd/ndb/dblookup.c
@@ -116,12 +116,9 @@
if(type == Tall){for (type = Ta; type < Tall; type++)
- if(implemented[type]) {- tp = dblookup(name, class, type, auth, ttl);
- lock(&dnlock);
- rrcat(&rp, tp);
- unlock(&dnlock);
- }
+ if(implemented[type])
+ rrcat(&rp, dblookup(name, class, type, auth, ttl));
+
return rp;
}
@@ -756,14 +753,6 @@
unlock(&dblock);
}
-void
-dnforceage(void)
-{- lock(&dblock);
- dnageall(1);
- unlock(&dblock);
-}
-
extern char mntpt[Maxpath]; /* net mountpoint */
static uchar ipaddr[IPaddrlen]; /* my ip address */
@@ -810,8 +799,6 @@
if(t == nil)
t = lookupinfo("dom");- if(t == nil)
- return 0;
for(; rp; rp = rp->next){if(rp->type != Tns)
@@ -827,6 +814,9 @@
return 1;
}
+ if(t == nil)
+ continue;
+
/* see if delegating to us what we don't own */
for(nt = t; nt != nil; nt = nt->entry)
if(rp->host && cistrcmp(rp->host->name, nt->val) == 0)
@@ -847,12 +837,13 @@
int
myaddr(char *addr)
{- char *name, *line, *sp;
+ char *line, *sp;
char buf[64];
Biobuf *bp;
if(ipcmp(ipaddr, IPnoaddr) == 0)
- return -1;
+ if(myipaddr(ipaddr, mntpt) < 0)
+ return -1;
snprint(buf, sizeof buf, "%I", ipaddr);
if (strcmp(addr, buf) == 0) {@@ -860,9 +851,8 @@
return 1;
}
- name = smprint("%s/ipselftab", mntpt);- bp = Bopen(name, OREAD);
- free(name);
+ snprint(buf, sizeof buf, "%s/ipselftab", mntpt);
+ bp = Bopen(buf, OREAD);
if (bp != nil) { while ((line = Brdline(bp, '\n')) != nil) {line[Blinelen(bp) - 1] = '\0';
@@ -1246,18 +1236,17 @@
return 0;
}
-uchar *
-outsidens(int n)
+int
+outsidensip(int n, uchar *ip)
{int i;
Ndbtuple *t;
- static uchar ipa[IPaddrlen];
i = 0;
for (t = outnmsrvs; t != nil; t = t->entry)
if (strcmp(t->attr, "ip") == 0 && i++ == n) {- parseip(ipa, t->val);
- return ipa;
+ parseip(ip, t->val);
+ return 0;
}
- return nil;
+ return -1;
}
--- a/sys/src/cmd/ndb/dn.c
+++ b/sys/src/cmd/ndb/dn.c
@@ -218,7 +218,7 @@
dp->magic = DNmagic;
dp->name = estrdup(name);
dp->class = class;
- dp->rr = 0;
+ dp->rr = nil;
dp->referenced = now;
/* add new DN to tail of the hash list. *l points to last next ptr. */
dp->next = nil;
@@ -366,8 +366,7 @@
void
dnage(DN *dp)
{- RR **l;
- RR *rp, *next;
+ RR **l, *rp;
ulong diff;
if (canlock(&dnlock))
@@ -377,9 +376,8 @@
return;
l = &dp->rr;
- for(rp = dp->rr; rp; rp = next){+ while ((rp = *l) != nil){assert(rp->magic == RRmagic && rp->cached);
- next = rp->next;
if(!rp->db && (rp->expire < now || diff > dnvars.oldest))
rrdelhead(l); /* rp == *l before; *l == rp->next after */
else
@@ -455,28 +453,6 @@
unlock(&dnlock);
}
-/* mark all current domain names as never to be aged */
-void
-dnageallnever(void)
-{- int i;
- DN *dp;
-
- lock(&dnlock);
-
- /* mark all referenced domain names */
- for(i = 0; i < HTLEN; i++)
- for(dp = ht[i]; dp; dp = dp->next)
- dnagenever(dp, 0);
-
- unlock(&dnlock);
-
- dnslog("%ld initial domain names; target is %ld", dnvars.names, target);- if(dnvars.names >= target)
- dnslog("more initial domain names (%ld) than target (%ld)",- dnvars.names, target);
-}
-
#define REF(dp) { if (dp) (dp)->refs++; }/*
@@ -576,17 +552,16 @@
for(i = 0; i < HTLEN; i++){l = &ht[i];
for(dp = *l; dp; dp = *l){- if(dp->rr == 0 && dp->refs == 0 && dp->keep == 0){+ if(dp->rr == nil && dp->refs == 0 && dp->keep == 0){assert(dp->magic == DNmagic);
*l = dp->next;
- if(dp->name)
- free(dp->name);
- dp->magic = ~dp->magic;
- dnvars.names--;
+ free(dp->name);
memset(dp, 0, sizeof *dp); /* cause trouble */
+ dp->magic = ~DNmagic;
free(dp);
+ dnvars.names--;
continue;
}
l = &dp->next;
@@ -719,12 +694,15 @@
}
unlock(&dnvars);
- dncheck(0, 1);
+ dncheck();
db2cache(needrefresh);
+ dncheck();
+
dnageall(0);
- dncheck(0, 1);
+ dncheck();
+
/* let others back in */
lastclean = now;
needrefresh = 0;
@@ -862,9 +840,7 @@
rp->next = nil;
dp = rp->owner;
/* avoid any outside spoofing; leave keepers alone */
- if(cfg.cachedb && !rp->db && inmyarea(dp->name)
-// || dp->keep /* TODO: make this work */
- )
+ if((cfg.cachedb && !rp->db && inmyarea(dp->name)) || dp->keep)
rrfree(rp);
else
rrattach1(rp, auth);
@@ -872,7 +848,6 @@
unlock(&dnlock);
}
-/* should be called with dnlock held */
RR**
rrcopy(RR *rp, RR **last)
{@@ -886,8 +861,6 @@
Txt *t, *nt, **l;
assert(rp->magic == RRmagic);
- if (canlock(&dnlock))
- abort(); /* rrcopy called with dnlock not held */
nrp = rralloc(rp->type);
switch(rp->type){case Tsoa:
@@ -954,7 +927,7 @@
nrp->pc = getcallerpc(&rp);
setmalloctag(nrp, nrp->pc);
nrp->cached = 0;
- nrp->next = 0;
+ nrp->next = nil;
*last = nrp;
return &nrp->next;
}
@@ -979,7 +952,7 @@
assert(dp->magic == DNmagic);
- first = 0;
+ first = nil;
last = &first;
lock(&dnlock);
@@ -1039,8 +1012,8 @@
}
out:
- unique(first);
unlock(&dnlock);
+ unique(first);
return first;
}
@@ -1086,9 +1059,7 @@
}
/*
- * Add resource records to a list, duplicate them if they are cached
- * RR's since these are shared. should be called with dnlock held
- * to avoid racing down the start chain.
+ * Add resource records to a list.
*/
RR*
rrcat(RR **start, RR *rp)
@@ -1096,8 +1067,6 @@
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)
@@ -1122,8 +1091,6 @@
RR **nl, *rp;
RR *first;
- if (canlock(&dnlock))
- abort(); /* rrremneg called with dnlock not held */
first = nil;
nl = &first;
while(*l != nil){@@ -1541,26 +1508,19 @@
* chasing down double free's
*/
void
-dncheck(void *p, int dolock)
+dncheck(void)
{int i;
DN *dp;
RR *rp;
- if(p != nil){- dp = p;
- assert(dp->magic == DNmagic);
- }
-
if(!testing)
return;
- if(dolock)
- lock(&dnlock);
+ lock(&dnlock);
poolcheck(mainmem);
for(i = 0; i < HTLEN; i++)
for(dp = ht[i]; dp; dp = dp->next){- assert(dp != p);
assert(dp->magic == DNmagic);
for(rp = dp->rr; rp; rp = rp->next){assert(rp->magic == RRmagic);
@@ -1567,7 +1527,7 @@
assert(rp->cached);
assert(rp->owner == dp);
/* also check for duplicate rrs */
- if (dolock && rronlist(rp, rp->next)) {+ if (rronlist(rp, rp->next)) { dnslog("%R duplicates its next chain ""(%R); aborting", rp, rp->next);
abort();
@@ -1574,8 +1534,7 @@
}
}
}
- if(dolock)
- unlock(&dnlock);
+ unlock(&dnlock);
}
static int
@@ -1587,7 +1546,6 @@
&& r1->arg1 == r2->arg1;
}
-/* called with dnlock held */
void
unique(RR *rp)
{@@ -1995,19 +1953,10 @@
void
rrfree(RR *rp)
{- DN *dp;
- RR *nrp;
Txt *t;
assert(rp->magic == RRmagic && !rp->cached);
- dp = rp->owner;
- if(dp){- assert(dp->magic == DNmagic);
- for(nrp = dp->rr; nrp; nrp = nrp->next)
- assert(nrp != rp); /* "rrfree of live rr" */
- }
-
switch(rp->type){case Tsoa:
freeserverlist(rp->soa->slaves);
@@ -2048,7 +1997,7 @@
break;
}
- rp->magic = ~rp->magic;
memset(rp, 0, sizeof *rp); /* cause trouble */
+ rp->magic = ~RRmagic;
free(rp);
}
--- a/sys/src/cmd/ndb/dnresolve.c
+++ b/sys/src/cmd/ndb/dnresolve.c
@@ -36,9 +36,6 @@
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,
};
enum { Hurry, Patient, }; enum { Outns, Inns, };@@ -49,15 +46,8 @@
DN *s; /* name server */
int nx; /* number of transmissions */
int code; /* response code; used to clear dp->respcode */
-
- ulong magic;
};
-/*
- * Query has a QLock in it, thus it can't be an automatic
- * variable, since each process would see a separate copy
- * of the lock on its stack.
- */
struct Query {DN *dp; /* domain */
ushort type; /* and type to look up */
@@ -71,13 +61,10 @@
int udpfd;
- QLock tcplock; /* only one tcp call at a time per query */
int tcpset;
int tcpfd; /* if Tcp, read replies from here */
int tcpctlfd;
uchar tcpip[IPaddrlen];
-
- ulong magic;
};
/* estimated % probability of such a record existing at all */
@@ -175,15 +162,10 @@
nrp->ptr->name);
rp = dnresolve(nname, class, type, req, cn, depth+1,
recurse, rooted, status);
- lock(&dnlock);
rrfreelist(rrremneg(&rp));
- unlock(&dnlock);
}
- if(drp != nil){- lock(&dnlock);
+ if(drp != nil)
rrfreelist(drp);
- unlock(&dnlock);
- }
procsetname(procname);
free(procname);
return rp;
@@ -193,12 +175,11 @@
* try the name directly
*/
rp = dnresolve1(name, class, type, req, depth, recurse);
- if(rp == nil) {+ if(rp == nil && (dp = dnlookup(name, class, 0)) != nil) {/*
* try it as a canonical name if we weren't told
* that the name didn't exist
*/
- dp = dnlookup(name, class, 0);
if(type != Tptr && dp->respcode != Rname)
for(loops = 0; rp == nil && loops < Maxretries; loops++){/* retry cname, then the actual type */
@@ -207,11 +188,9 @@
if(rp == nil)
break;
- lock(&dnlock);
/* rp->host == nil shouldn't happen, but does */
if(rp->negative || rp->host == nil){rrfreelist(rp);
- unlock(&dnlock);
rp = nil;
break;
}
@@ -221,7 +200,6 @@
rrcat(cn, rp);
else
rrfreelist(rp);
- unlock(&dnlock);
rp = dnresolve1(name, class, type, req,
depth, recurse);
@@ -239,6 +217,8 @@
static void
queryinit(Query *qp, DN *dp, int type, Request *req)
{+ assert(dp && dp->magic == DNmagic);
+
memset(qp, 0, sizeof *qp);
qp->udpfd = qp->tcpfd = qp->tcpctlfd = -1;
qp->dp = dp;
@@ -248,20 +228,11 @@
qp->req = req;
qp->nsrp = nil;
qp->dest = qp->curdest = nil;
- qp->magic = Querymagic;
}
static void
-queryck(Query *qp)
-{- assert(qp);
- assert(qp->magic == Querymagic);
-}
-
-static void
querydestroy(Query *qp)
{- queryck(qp);
/* leave udpfd open */
if (qp->tcpfd >= 0)
close(qp->tcpfd);
@@ -269,25 +240,10 @@
hangup(qp->tcpctlfd);
close(qp->tcpctlfd);
}
- free(qp->dest);
memset(qp, 0, sizeof *qp); /* prevent accidents */
qp->udpfd = qp->tcpfd = qp->tcpctlfd = -1;
}
-static void
-destinit(Dest *p)
-{- memset(p, 0, sizeof *p);
- p->magic = Destmagic;
-}
-
-static void
-destck(Dest *p)
-{- assert(p);
- assert(p->magic == Destmagic);
-}
-
/*
* 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.
@@ -335,9 +291,7 @@
qp->nsrp = nsrp;
rv = netquery(qp, depth);
qp->nsrp = nil; /* prevent accidents */
- lock(&dnlock);
rrfreelist(nsrp);
- unlock(&dnlock);
return rv;
}
@@ -371,9 +325,7 @@
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;
}
@@ -382,11 +334,8 @@
* entries
*/
if(recurse == Dontrecurse){- if(dbnsrp) {- lock(&dnlock);
+ if(dbnsrp)
rrfreelist(dbnsrp);
- unlock(&dnlock);
- }
continue;
}
@@ -397,16 +346,11 @@
nsrp = randomize(rrlookup(nsdp, Tns, NOneg));
/* if the entry timed out, ignore it */
- if(nsrp && nsrp->ttl < now){- lock(&dnlock);
+ if(nsrp && nsrp->ttl < now)
rrfreelistptr(&nsrp);
- unlock(&dnlock);
- }
if(nsrp){- lock(&dnlock);
rrfreelistptr(&dbnsrp);
- unlock(&dnlock);
/* query the name servers found in cache */
if(netqueryns(qp, depth+1, nsrp) > Answnone)
@@ -426,7 +370,7 @@
Area *area;
DN *dp;
RR *rp;
- Query *qp;
+ Query q;
if(debug)
dnslog("[%d] dnresolve1 %s %d %d", getpid(), name, type, class);@@ -462,9 +406,7 @@
getpid(), name, type, class);
return rp;
}
- lock(&dnlock);
rrfreelist(rp);
- unlock(&dnlock);
rp = nil; /* accident prevention */
USED(rp);
@@ -475,9 +417,7 @@
*/
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",@@ -494,11 +434,10 @@
if (area || strncmp(dp->name, "local#", 6) == 0)
return nil;
- qp = emalloc(sizeof *qp);
- queryinit(qp, dp, type, req);
- rp = issuequery(qp, name, class, depth, recurse);
- querydestroy(qp);
- free(qp);
+ queryinit(&q, dp, type, req);
+ rp = issuequery(&q, name, class, depth, recurse);
+ querydestroy(&q);
+
if(rp){if(debug)
dnslog("[%d] dnresolve1 %s %d %d: rr from query",@@ -620,12 +559,10 @@
void
freeanswers(DNSmsg *mp)
{- 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;
}
@@ -708,7 +645,6 @@
uchar srcip[IPaddrlen];
RR *rp;
- queryck(qp);
for (; timems() < endms &&
(len = readnet(qp, medium, ibuf, endms, &reply, srcip)) >= 0;
freeanswers(mp)){@@ -810,7 +746,7 @@
serveraddrs(Query *qp, int nd, int depth)
{RR *rp, *arp, *trp;
- Dest *cur;
+ Dest *p;
if(nd >= Maxdest) /* dest array is full? */
return Maxdest;
@@ -863,9 +799,7 @@
if(arp == nil)
arp = dnresolve(rp->host->name, Cin, Taaaa,
qp->req, 0, depth+1, Recurse, 1, 0);
- lock(&dnlock);
rrfreelist(rrremneg(&arp));
- unlock(&dnlock);
if(arp)
break;
}
@@ -872,24 +806,23 @@
/* use any addresses that we found */
for(trp = arp; trp && nd < Maxdest; trp = trp->next){- cur = &qp->dest[nd];
- parseip(cur->a, trp->ip->name);
+ p = &qp->dest[nd];
+ memset(p, 0, sizeof *p);
+ parseip(p->a, trp->ip->name);
/*
* straddling servers can reject all nameservers if they are all
* inside, so be sure to list at least one outside ns at
* the end of the ns list in /lib/ndb for `dom='.
*/
- if (ipisbm(cur->a) ||
- cfg.straddle && !insideaddr(qp->dp->name) && insidens(cur->a))
+ if (ipisbm(p->a) ||
+ cfg.straddle && !insideaddr(qp->dp->name) && insidens(p->a))
continue;
- cur->nx = 0;
- cur->s = trp->owner;
- cur->code = Rtimeout;
+ p->nx = 0;
+ p->s = trp->owner;
+ p->code = Rtimeout;
nd++;
}
- lock(&dnlock);
rrfreelist(arp);
- unlock(&dnlock);
return nd;
}
@@ -909,10 +842,8 @@
/* no cache time specified, don't make anything up */
if(soarr != nil){- lock(&dnlock);
if(soarr->next != nil)
rrfreelistptr(&soarr->next);
- unlock(&dnlock);
soaowner = soarr->owner;
} else
soaowner = nil;
@@ -938,16 +869,12 @@
static int
setdestoutns(Dest *p, int n)
{- uchar *outns = outsidens(n);
-
- destck(p);
- destinit(p);
- if (outns == nil) {+ memset(p, 0, sizeof *p);
+ if (outsidensip(n, p->a) < 0){if (n == 0)
dnslog("[%d] no outside-ns in ndb", getpid());return -1;
}
- memmove(p->a, outns, sizeof p->a);
p->s = dnlookup("outside-ns-ips", Cin, 1);return 0;
}
@@ -960,22 +887,15 @@
mydnsquery(Query *qp, int medium, uchar *udppkt, int len)
{int rv, nfd;
- char *domain;
- char conndir[40], addr[128];
+ char conndir[40], addr[128], domain[64];
uchar belen[2];
NetConnInfo *nci;
rv = -1;
- queryck(qp);
- domain = smprint("%I", udppkt);- if (domain == nil) {- warning("mydnsquery: no memory for domain");- return rv;
- }
+ snprint(domain, sizeof(domain), "%I", udppkt);
if (myaddr(domain)) { dnslog("mydnsquery: trying to send to myself (%s); bzzzt",domain);
- free(domain);
return rv;
}
switch (medium) {@@ -1005,7 +925,7 @@
break;
case Tcp:
/* send via TCP & keep fd around for reply */
- parseip(qp->tcpip, domain);
+ memmove(qp->tcpip, udppkt, sizeof qp->tcpip);
snprint(addr, sizeof addr, "%s/tcp!%s!dns",
(mntpt && *mntpt) ? mntpt : "/net",
domain);
@@ -1033,7 +953,6 @@
rv = 0;
break;
}
- free(domain);
return rv;
}
@@ -1044,118 +963,78 @@
static int
xmitquery(Query *qp, int medium, int depth, uchar *obuf, int inns, int len)
{- int j, n;
+ int n;
char buf[32];
Dest *p;
- queryck(qp);
if(timems() >= qp->req->aborttime)
return -1;
/*
- * get a nameserver address if we need one.
- * serveraddrs populates qp->dest.
+ * if we send tcp query, we just take the dest ip address from
+ * the udp header placed there by tcpquery().
*/
- p = qp->dest;
- destck(p);
- if (qp->ndest < 0 || qp->ndest > Maxdest) {- dnslog("qp->ndest %d out of range", qp->ndest);- abort();
+ if (medium == Tcp) {+ procsetname("tcp %sside query for %s %s", (inns? "in": "out"),+ qp->dp->name, rrname(qp->type, buf, sizeof buf));
+ if(mydnsquery(qp, medium, obuf, len) < 0) /* sets qp->tcpip from obuf */
+ return -1;
+ if(debug)
+ logsend(qp->req->id, depth, qp->tcpip, "", qp->dp->name,
+ qp->type);
+ return 0;
}
+
/*
+ * get a nameserver address if we need one.
* 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) {- dnslog("serveraddrs() result %d out of range", j);- abort();
- }
- qp->curdest = &qp->dest[j];
- }
-
- /* no servers, punt */
- if (qp->ndest == 0)
- if (cfg.straddle && cfg.inside) {+ p = qp->dest;
+ n = qp->curdest - p;
+ if (qp->ndest > n) {+ n = serveraddrs(qp, n, depth); /* populates qp->dest. */
+ assert(n >= 0 && n <= Maxdest);
+ if (n == 0 && cfg.straddle && cfg.inside) {/* get ips of "outside-ns-ips" */
- qp->curdest = qp->dest;
- for(n = 0; n < Maxdest; n++, qp->curdest++)
- if (setdestoutns(qp->curdest, n) < 0)
+ while(n < Maxdest){+ if (setdestoutns(&qp->dest[n], n) < 0)
break;
+ n++;
+ }
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 */
- return -1;
+ }
+ qp->curdest = &qp->dest[n];
+ }
- /* send to first 'qp->ndest' destinations */
- j = 0;
- if (medium == Tcp) {- j++;
- queryck(qp);
- assert(qp->dp);
- procsetname("tcp %sside query for %s %s", (inns? "in": "out"),+ for(n = 0; p < &qp->dest[qp->ndest] && p < qp->curdest; p++){+ /* skip destinations we've finished with */
+ if(p->nx >= Maxtrans)
+ continue;
+ /* exponential backoff of requests */
+ 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));
- mydnsquery(qp, medium, obuf, len); /* sets qp->tcpip from obuf */
if(debug)
- logsend(qp->req->id, depth, qp->tcpip, "", qp->dp->name,
- qp->type);
- } else
- for(; p < &qp->dest[qp->ndest] && p < qp->curdest; p++){- /* skip destinations we've finished with */
- if(p->nx >= Maxtrans)
- continue;
+ logsend(qp->req->id, depth, p->a, p->s->name,
+ qp->dp->name, qp->type);
- j++;
-
- /* exponential backoff of requests */
- 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));
- if(debug)
- logsend(qp->req->id, depth, p->a, p->s->name,
- qp->dp->name, qp->type);
-
- /* fill in UDP destination addr & send it */
- memmove(obuf, p->a, sizeof p->a);
- mydnsquery(qp, medium, obuf, len);
- p->nx++;
- }
- if(j == 0) {- return -1;
+ /* fill in UDP destination addr & send it */
+ memmove(obuf, p->a, sizeof p->a);
+ if(mydnsquery(qp, medium, obuf, len) == 0)
+ n++;
+ p->nx++;
}
- return 0;
-}
-static int lckindex[Maxlcks] = {- 0, /* all others map here */
- Ta,
- Tns,
- Tcname,
- Tsoa,
- Tptr,
- Tmx,
- Ttxt,
- Taaaa,
-};
-
-static int
-qtype2lck(int qtype) /* map query type to querylck index */
-{- int i;
-
- for (i = 1; i < nelem(lckindex); i++)
- if (lckindex[i] == qtype)
- return i;
- return 0;
+ return n == 0 ? -1 : 0;
}
/* is mp a cachable negative response (with Rname set)? */
@@ -1173,7 +1052,7 @@
int rv;
char buf[32];
DN *ndp;
- Query *nqp;
+ Query nq;
RR *tp, *soarr;
if (mp->an == nil)
@@ -1183,7 +1062,7 @@
if((mp->flags & Rmask) == Rserver){stats.negserver++;
freeanswers(mp);
- if(p != qp->curdest)
+ if(p != nil)
p->code = Rserver;
return Answerr;
}
@@ -1194,20 +1073,17 @@
if(mp->an == nil){stats.negbdnoans++;
freeanswers(mp);
- if(p != qp->curdest)
+ if(p != nil)
p->code = Rserver;
dnslog(" and no answers");return Answerr;
}
dnslog(" but has answers; ignoring ns");- lock(&dnlock);
rrfreelistptr(&mp->ns);
- unlock(&dnlock);
mp->nscount = 0;
}
/* remove any soa's from the authority section */
- lock(&dnlock);
soarr = rrremtype(&mp->ns, Tsoa);
/* incorporate answers */
@@ -1214,7 +1090,6 @@
unique(mp->an);
unique(mp->ns);
unique(mp->ar);
- unlock(&dnlock);
if(mp->an)
rrattach(mp->an, (mp->flags & Fauth) != 0);
@@ -1225,17 +1100,13 @@
rrattach(mp->ns, Notauthoritative);
} else {ndp = nil;
- lock(&dnlock);
rrfreelistptr(&mp->ns);
- unlock(&dnlock);
mp->nscount = 0;
}
/* free the question */
if(mp->qd) {- lock(&dnlock);
rrfreelistptr(&mp->qd);
- unlock(&dnlock);
mp->qdcount = 0;
}
@@ -1257,11 +1128,8 @@
*/
if( /* (mp->flags & Fauth) && */ mp->an == nil)
cacheneg(qp->dp, qp->type, (mp->flags & Rmask), soarr);
- else {- lock(&dnlock);
+ else
rrfreelist(soarr);
- unlock(&dnlock);
- }
return 1;
} else if (isnegrname(mp)) {qp->dp->respcode = Rname;
@@ -1274,9 +1142,7 @@
return 1;
}
stats.negnorname++;
- lock(&dnlock);
rrfreelist(soarr);
- unlock(&dnlock);
/*
* if we've been given better name servers, recurse.
@@ -1287,19 +1153,16 @@
return Answnone;
tp = rrlookup(ndp, Tns, NOneg);
if(contains(qp->nsrp, tp)){- lock(&dnlock);
rrfreelist(tp);
- unlock(&dnlock);
return Answnone;
}
procsetname("recursive query for %s %s", qp->dp->name,rrname(qp->type, buf, sizeof buf));
- nqp = emalloc(sizeof *nqp);
- queryinit(nqp, qp->dp, qp->type, qp->req);
- rv = netqueryns(nqp, depth+1, tp);
- querydestroy(nqp);
- free(nqp);
+ queryinit(&nq, qp->dp, qp->type, qp->req);
+ rv = netqueryns(&nq, depth+1, tp);
+ querydestroy(&nq);
+
return rv;
}
@@ -1322,7 +1185,6 @@
dnslog("%s: udp reply truncated; retrying query via tcp to %I",qp->dp->name, qp->tcpip);
- qlock(&qp->tcplock);
memmove(obuf, ibuf, IPaddrlen); /* send back to respondent */
memset(mp, 0, sizeof *mp);
if (xmitquery(qp, Tcp, depth, obuf, inns, len) < 0 ||
@@ -1334,7 +1196,7 @@
close(qp->tcpfd);
}
qp->tcpfd = qp->tcpctlfd = -1;
- qunlock(&qp->tcplock);
+
return rv;
}
@@ -1349,9 +1211,9 @@
int ndest, len, replywaits, rv;
ushort req;
uvlong endms;
- char buf[12];
+ char buf[32];
uchar srcip[IPaddrlen];
- Dest *p, *np, *dest;
+ Dest *p, *np, dest[Maxdest];
/* pack request into a udp message */
req = rand();
@@ -1358,12 +1220,7 @@
len = mkreq(qp->dp, qp->type, obuf, Frecurse|Oquery, req);
/* no server addresses yet */
- queryck(qp);
- dest = emalloc(Maxdest * sizeof *dest); /* dest can't be on stack */
- for (p = dest; p < dest + Maxdest; p++)
- destinit(p);
- /* this dest array is local to this call of queryns() */
- free(qp->dest);
+ memset(dest, 0, sizeof dest);
qp->curdest = qp->dest = dest;
/*
@@ -1413,16 +1270,17 @@
if(memcmp(p->a, srcip, sizeof p->a) == 0)
break;
- /* remove all addrs of responding server from list */
- if(p != qp->curdest)
+ if(p != qp->curdest) {+ /* remove all addrs of responding server from list */
for(np = qp->dest; np < qp->curdest; np++)
if(np->s == p->s)
np->nx = Maxtrans;
+ } else
+ p = nil;
/* free or incorporate RRs in m */
rv = procansw(qp, &m, srcip, depth, p);
if (rv > Answnone) {- free(qp->dest);
qp->dest = qp->curdest = nil; /* prevent accidents */
return rv;
}
@@ -1431,17 +1289,13 @@
/* if all servers returned failure, propagate it */
qp->dp->respcode = Rserver;
- for(p = dest; p < qp->curdest; p++) {- destck(p);
+ for(p = dest; p < qp->curdest; p++)
if(p->code != Rserver)
qp->dp->respcode = Rok;
- p->magic = 0; /* prevent accidents */
- }
// if (qp->dp->respcode)
// dnslog("queryns setting Rserver for %s", qp->dp->name);- free(qp->dest);
qp->dest = qp->curdest = nil; /* prevent accidents */
return Answnone;
}
@@ -1570,12 +1424,8 @@
static int
netquery(Query *qp, int depth)
{- int lock, rv, triedin, inname;
- char buf[32];
+ int rv, triedin, inname;
RR *rp;
- DN *dp;
- Querylck *qlp;
- static int whined;
rv = Answnone; /* pessimism */
if(depth > 12) /* in a recursive loop? */
@@ -1592,39 +1442,7 @@
if(!qp->req->isslave && strcmp(qp->req->from, "9p") == 0)
return Answnone;
- /*
- * don't lock before call to slave so only children can block.
- * just lock at top-level invocation.
- */
- lock = depth <= 1 && qp->req->isslave;
- dp = qp->dp; /* ensure that it doesn't change underfoot */
- qlp = nil;
- if(lock) {- procsetname("query lock wait: %s %s from %s", dp->name,- rrname(qp->type, buf, sizeof buf), qp->req->from);
- /*
- * don't make concurrent queries for this name.
- * dozens of processes blocking here probably indicates
- * an error in our dns data that causes us to not
- * recognise a zone (area) as one of our own, thus
- * causing us to query other nameservers.
- */
- qlp = &dp->querylck[qtype2lck(qp->type)];
- qlock(qlp);
- if (qlp->Ref.ref > Maxoutstanding) {- qunlock(qlp);
- if (!whined) {- whined = 1;
- dnslog("too many outstanding queries for %s;"- " dropping this one; no further logging"
- " of drops", dp->name);
- }
- return Answnone;
- }
- ++qlp->Ref.ref;
- qunlock(qlp);
- }
- procsetname("netquery: %s", dp->name);+ procsetname("netquery: %s", qp->dp->name);/* prepare server RR's for incremental lookup */
for(rp = qp->nsrp; rp; rp = rp->next)
@@ -1638,7 +1456,7 @@
* for inside addresses and /net.alt for outside addresses,
* thus bypassing other inside nameservers.
*/
- inname = insideaddr(dp->name);
+ inname = insideaddr(qp->dp->name);
if (!cfg.straddle || inname) {rv = udpquery(qp, mntpt, depth, Hurry, (cfg.inside? Inns: Outns));
triedin = 1;
@@ -1652,7 +1470,7 @@
if (triedin)
dnslog(
"[%d] netquery: internal nameservers failed for %s; trying external",
- getpid(), dp->name);
+ getpid(), qp->dp->name);
/* prepare server RR's for incremental lookup */
for(rp = qp->nsrp; rp; rp = rp->next)
@@ -1661,12 +1479,6 @@
rv = udpquery(qp, "/net.alt", depth, Patient, Outns);
}
- if(lock && qlp) {- qlock(qlp);
- assert(qlp->Ref.ref > 0);
- qunlock(qlp);
- decref(qlp);
- }
return rv;
}
@@ -1677,19 +1489,17 @@
char root[] = "";
Request req;
RR *rr, *nsrp;
- Query *qp;
+ Query q;
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);
+ queryinit(&q, dnlookup(root, Cin, 1), Tns, &req);
nsrp = dblookup(root, Cin, Tns, 0, 0);
- for (rr = nsrp; rr != nil; rr = rr->next) /* DEBUG */
+ for (rr = nsrp; rr != nil; rr = rr->next)
dnslog("seerootns query nsrp: %R", rr);- rv = netqueryns(qp, 0, nsrp); /* lookup ". ns" using nsrp */
- querydestroy(qp);
- free(qp);
+ rv = netqueryns(&q, 0, nsrp); /* lookup ". ns" using nsrp */
+ querydestroy(&q);
return rv;
}
--- a/sys/src/cmd/ndb/dns.c
+++ b/sys/src/cmd/ndb/dns.c
@@ -212,7 +212,6 @@
srand(now*getpid());
db2cache(1);
-// dnageallnever();
if (cfg.straddle && !seerootns())
dnslog("straddle server misconfigured; can't see root name servers");@@ -723,12 +722,7 @@
*/
// 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, "testing")==0)
testing ^= 1;
@@ -806,7 +800,6 @@
err = lookupquery(job, mf, req, errbuf, p, wantsav, rooted);
send:
- dncheck(0, 1);
job->reply.count = cnt;
sendmsg(job, err);
}
@@ -828,18 +821,14 @@
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);
}
@@ -880,9 +869,7 @@
}
unlock(&joblock);
- lock(&dnlock);
rrfreelist(rp);
- unlock(&dnlock);
return nil;
}
--- a/sys/src/cmd/ndb/dns.h
+++ b/sys/src/cmd/ndb/dns.h
@@ -1,5 +1,3 @@
-#include <thread.h> /* for Ref */
-
#define NS2MS(ns) ((ns) / 1000000L)
#define S2MS(s) ((s) * 1000LL)
@@ -186,14 +184,6 @@
char *from; /* who asked us? */
};
-typedef struct Querylck Querylck;
-struct Querylck
-{- QLock;
-// Rendez;
- Ref;
-};
-
/*
* a domain name
*/
@@ -211,9 +201,6 @@
ushort class; /* RR class */
uchar keep; /* flag: never age this name */
uchar respcode; /* response code */
-/* was: char nonexistent; /* true if we get an authoritative nx for this domain */
- /* permit only 1 query per (domain name, type) at a time */
- Querylck querylck[Maxlcks];
};
/*
@@ -461,10 +448,9 @@
void dnage(DN*);
void dnageall(int);
void dnagedb(void);
-void dnageallnever(void);
void dnagenever(DN *, int);
void dnauthdb(void);
-void dncheck(void*, int);
+void dncheck(void);
void dndump(char*);
void dnget(void);
void dninit(void);
@@ -511,7 +497,6 @@
int baddelegation(RR*, RR*, uchar*);
RR* dbinaddr(DN*, int);
RR* dblookup(char*, int, int, int, int);
-void dnforceage(void);
RR* dnsservers(int);
RR* domainlist(int);
int insideaddr(char *dom);
@@ -518,7 +503,7 @@
int insidens(uchar *ip);
int myaddr(char *addr);
int opendatabase(void);
-uchar* outsidens(int);
+int outsidensip(int, uchar *ip);
/* dns.c */
char* walkup(char*);
--- a/sys/src/cmd/ndb/dnsdebug.c
+++ b/sys/src/cmd/ndb/dnsdebug.c
@@ -341,11 +341,10 @@
{RR *rp, **l, *first;
+ first = nil;
l = &first;
for(rp = serveraddrs; rp != nil; rp = rp->next){- lock(&dnlock);
rrcopy(rp, l);
- unlock(&dnlock);
rrattach(first, Authoritative);
}
}
--- a/sys/src/cmd/ndb/dnserver.c
+++ b/sys/src/cmd/ndb/dnserver.c
@@ -22,8 +22,6 @@
Area *myarea;
RR *tp, *neg, *rp;
- dncheck(nil, 1);
-
recursionflag = norecursion? 0: Fcanrec;
memset(repp, 0, sizeof(*repp));
repp->id = reqp->id;
@@ -109,11 +107,9 @@
if(repp->ns){/* don't pass on anything we know is wrong */
if(repp->ns->negative){- lock(&dnlock);
rp = repp->ns;
repp->ns = nil;
rrfreelist(rp);
- unlock(&dnlock);
}
break;
}
@@ -135,8 +131,6 @@
hint(&repp->ar, tp);
}
- /* hint calls rrlookup which holds dnlock, so don't lock before this. */
-
/*
* add an soa to the authority section to help client
* with negative caching
@@ -143,16 +137,12 @@
*/
if(repp->an == nil)
if(myarea != nil){- lock(&dnlock);
rrcopy(myarea->soarr, &tp);
rrcat(&repp->ns, tp);
- unlock(&dnlock);
} else if(neg != nil) { if(neg->negsoaowner != nil) {tp = rrlookup(neg->negsoaowner, Tsoa, NOneg);
- lock(&dnlock);
rrcat(&repp->ns, tp);
- unlock(&dnlock);
}
repp->flags |= neg->negrcode;
}
@@ -160,15 +150,11 @@
/*
* get rid of duplicates
*/
- lock(&dnlock);
unique(repp->an);
unique(repp->ns);
unique(repp->ar);
rrfreelist(neg);
- unlock(&dnlock);
-
- dncheck(nil, 1);
}
/*
@@ -185,7 +171,6 @@
type = mp->qd->type;
rp = dnresolve(name, Cin, type, req, &mp->an, 0, recurse, 1, 0);
- lock(&dnlock);
/* don't return soa hints as answers, it's wrong */
if(rp && rp->db && !rp->auth && rp->type == Tsoa) {rrfreelist(rp);
@@ -195,7 +180,7 @@
/* don't let negative cached entries escape */
neg = rrremneg(&rp);
rrcat(&mp->an, rp);
- unlock(&dnlock);
+
return neg;
}
@@ -219,9 +204,7 @@
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;
}
}
--- a/sys/src/cmd/ndb/dnudpserver.c
+++ b/sys/src/cmd/ndb/dnudpserver.c
@@ -189,7 +189,6 @@
// ((Udphdr*)buf)->raddr, ((Udphdr*)buf)->laddr);
getactivity(&req, 0);
req.aborttime = timems() + Maxreqtm;
-// req.from = smprint("%I", ((Udphdr*)buf)->raddr); req.from = smprint("%I", buf);rcode = 0;
stats.qrecvdudp++;
--
⑨