ref: 0d926a251269277214ab0ce5e84f5c4674576d6f
parent: f7bc3526b3acfe70263167e0a78dbb4a4050c6e4
author: cinap_lenrek <[email protected]>
date: Fri Mar 9 01:02:17 EST 2012
dns: import changes from sources
--- 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 @@
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 @@
/* 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 @@
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,11 +306,21 @@
// 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
*/
@@ -323,13 +327,14 @@
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 @@
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,14 +357,17 @@
* 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:
@@ -364,7 +374,6 @@
/* unknown type, just ignore it */
sp->p = data + len;
rrfree(rp);
- rp = nil;
goto retry;
case Thinfo:
SYMBOL(rp->cpu);
@@ -493,8 +502,9 @@
{
char dname[Domlen+1];
int type, class;
- RR *rp = nil;
+ RR *rp;
+ rp = nil;
NAME(dname);
USHORT(type);
USHORT(class);
@@ -535,7 +545,8 @@
*l = rp;
l = &rp->next;
}
-// setmalloctag(first, getcallerpc(&sp));
+// if(first)
+// setmalloctag(first, getcallerpc(&sp));
return first;
}
@@ -553,9 +564,8 @@
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;
@@ -562,6 +572,7 @@
sp->ep = buf + len;
sp->err = nil;
sp->errbuf[0] = '\0';
+ sp->rcode = Rok;
memset(m, 0, sizeof *m);
USHORT(m->id);
--- a/sys/src/cmd/ndb/dblookup.c
+++ b/sys/src/cmd/ndb/dblookup.c
@@ -100,9 +100,6 @@
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)
@@ -109,19 +106,19 @@
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,6 +1196,8 @@
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)
@@ -1205,7 +1204,7 @@
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;
--- a/sys/src/cmd/ndb/dn.c
+++ b/sys/src/cmd/ndb/dn.c
@@ -14,12 +14,15 @@
* figure it out.
*/
enum {
- Deftarget = 8000,
+ 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) */
};
-enum {
- Minage = 10*60,
- Defagefreq = 30*60, /* age names this often (seconds) */
-};
/*
* Hash table for domain names. The hash is based only on the
@@ -339,13 +342,20 @@
}
/*
- * 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 @@
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 @@
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 @@
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 @@
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 @@
void
rrattach(RR *rp, int auth)
{
- RR *next;
+ RR *next, *tp;
DN *dp;
lock(&dnlock);
@@ -842,17 +856,20 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
&& r1->arg1 == r2->arg1;
}
+/* called with dnlock held */
void
unique(RR *rp)
{
--- a/sys/src/cmd/ndb/dnarea.c
+++ b/sys/src/cmd/ndb/dnarea.c
@@ -91,8 +91,10 @@
while(s = *l){
*l = s->next;
+ lock(&dnlock);
rrfree(s->soarr);
memset(s, 0, sizeof *s); /* cause trouble */
+ unlock(&dnlock);
free(s);
}
}
--- a/sys/src/cmd/ndb/dnresolve.c
+++ b/sys/src/cmd/ndb/dnresolve.c
@@ -16,14 +16,28 @@
{
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 @@
/* 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 @@
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 @@
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 @@
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 @@
*/
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 @@
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 @@
* entries
*/
if(recurse == Dontrecurse){
- if(dbnsrp)
+ if(dbnsrp) {
+ lock(&dnlock);
rrfreelist(dbnsrp);
+ unlock(&dnlock);
+ }
continue;
}
@@ -365,34 +399,23 @@
/* 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 @@
getpid(), name, type, class);
return rp;
}
+ lock(&dnlock);
rrfreelist(rp);
+ unlock(&dnlock);
rp = nil; /* accident prevention */
USED(rp);
@@ -451,7 +476,9 @@
*/
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 @@
mp->flags = flags;
mp->id = reqno;
mp->qd = rp;
+ if(rp != nil)
+ mp->qdcount = 1;
}
DNSmsg *
@@ -600,7 +629,7 @@
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 @@
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 @@
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 @@
}
/*
- * 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 @@
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 @@
cur->code = Rtimeout;
nd++;
}
+ lock(&dnlock);
rrfreelist(arp);
+ unlock(&dnlock);
return nd;
}
@@ -893,10 +926,10 @@
/* 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 @@
{
int rv = -1, nfd;
char *domain;
- char conndir[40];
+ char conndir[40], net[40];
uchar belen[2];
NetConnInfo *nci;
@@ -984,8 +1017,10 @@
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 @@
*/
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 @@
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 @@
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 @@
p->nx++;
}
if(j == 0) {
- // dnslog("xmitquery: %s: no destinations left", qp->dp->name);
return -1;
}
return 0;
@@ -1135,6 +1179,7 @@
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 @@
freeanswers(mp);
if(p != qp->curdest)
p->code = Rserver;
- return -1;
+ return Answerr;
}
/* ignore any bad delegations */
@@ -1165,10 +1210,14 @@
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 @@
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 @@
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 @@
*/
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 @@
return 1;
}
stats.negnorname++;
+ lock(&dnlock);
rrfreelist(soarr);
+ unlock(&dnlock);
/*
* if we've been given better name servers, recurse.
@@ -1239,11 +1298,13 @@
* 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 @@
* 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 @@
}
/*
- * 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 @@
/* 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 @@
free(qp->dest);
qp->dest = qp->curdest = nil; /* prevent accidents */
- return 0;
+ return Answnone;
}
/*
@@ -1465,7 +1527,6 @@
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 @@
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 @@
* 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 @@
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,6 +1695,7 @@
int rv;
char root[] = "";
Request req;
+ RR *rr;
Query *qp;
memset(&req, 0, sizeof req);
@@ -1640,11 +1702,14 @@
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);
--- a/sys/src/cmd/ndb/dnsdebug.c
+++ b/sys/src/cmd/ndb/dnsdebug.c
@@ -343,7 +343,9 @@
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
@@ -20,7 +20,7 @@
char tname[32];
DN *nsdp, *dp;
Area *myarea;
- RR *tp, *neg;
+ RR *tp, *neg, *rp;
dncheck(nil, 1);
@@ -109,8 +109,11 @@
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 @@
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
--- a/sys/src/cmd/ndb/dnudpserver.c
+++ b/sys/src/cmd/ndb/dnudpserver.c
@@ -283,19 +283,21 @@
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;
}
--- a/sys/src/cmd/ndb/inform.c
+++ b/sys/src/cmd/ndb/inform.c
@@ -24,11 +24,6 @@
[10] "domain name not in zone",
};
-char *dnsrch[] = {
- "dnsdomain",
- "dom",
-};
-
void
usage(void)
{
@@ -98,12 +93,12 @@
{
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 @@
debug = 0;
ns = nil;
dom = nil;
+ inform = nil;
dnsdomain = nil;
ARGBEGIN{
case 'd':
@@ -133,7 +129,7 @@
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)
@@ -140,9 +136,15 @@
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)
--- a/sys/src/cmd/ndb/mkhash.c
+++ b/sys/src/cmd/ndb/mkhash.c
@@ -76,7 +76,7 @@
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]);