Browse Source

Plan 9 from Bell Labs 2011-03-25

David du Colombier 13 years ago
parent
commit
08fbb8920f

+ 10 - 8
sys/src/cmd/ndb/convM2DNS.c

@@ -303,16 +303,18 @@ err:
  * ms windows 2000 seems to get the bytes backward in the type field
  * of ptr records, so return a format error as feedback.
  */
-static void
-mstypehack(Scan *sp, int type, char *where)
+static ushort
+mstypehack(Scan *sp, ushort type, char *where)
 {
-	if ((uchar)type == 0 && (uchar)(type>>8) != 0) {
+	if ((uchar)type == 0 && (type>>8) != 0) {
 		USED(where);
 //		dnslog("%s: byte-swapped type field in ptr rr from win2k",
 //			where);
-		if (sp->rcode == 0)
+		if (sp->rcode == Rok)
 			sp->rcode = Rformat;
+		return (uchar)type << 8 | type >> 8;
 	}
+	return type;
 }
 
 /*
@@ -332,7 +334,7 @@ retry:
 	USHORT(type);
 	USHORT(class);
 
-	mstypehack(sp, type, "convM2RR");
+	type = mstypehack(sp, type, "convM2RR");
 	rp = rralloc(type);
 	rp->owner = dnlookup(dname, class, 1);
 	rp->type = type;
@@ -499,7 +501,7 @@ convM2Q(Scan *sp)
 	if(sp->err || sp->rcode || sp->stop)
 		return nil;
 
-	mstypehack(sp, type, "convM2Q");
+	type = mstypehack(sp, type, "convM2Q");
 	rp = rralloc(type);
 	rp->owner = dnlookup(dname, class, 1);
 
@@ -552,7 +554,7 @@ convM2DNS(uchar *buf, int len, DNSmsg *m, int *codep)
 	Scan *sp;
 
 	if (codep)
-		*codep = 0;
+		*codep = Rok;
 	assert(len >= 0);
 	sp = &scan;
 	memset(sp, 0, sizeof *sp);
@@ -580,7 +582,7 @@ convM2DNS(uchar *buf, int len, DNSmsg *m, int *codep)
 	if (sp->trunc)
 		m->flags |= Ftrunc;
 	if (sp->stop)
-		sp->rcode = 0;
+		sp->rcode = Rok;
 	if (codep)
 		*codep = sp->rcode;
 	return err;

+ 12 - 3
sys/src/cmd/ndb/dblookup.c

@@ -213,6 +213,10 @@ dblookup1(char *name, int type, int auth, int ttl)
 		attr = "ip";
 		f = addrrr;
 		break;
+	case Taaaa:
+		attr = "ipv6";
+		f = addrrr;
+		break;
 	case Tnull:
 		attr = "nullrr";
 		f = nullrr;
@@ -581,7 +585,8 @@ dbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair)
 	static ulong ord;
 
 	rp = 0;
-	if(cistrcmp(pair->attr, "ip") == 0){
+	if(cistrcmp(pair->attr, "ip") == 0 ||
+	   cistrcmp(pair->attr, "ipv6") == 0){
 		dp->ordinal = ord++;
 		rp = addrrr(entry, pair);
 	} else 	if(cistrcmp(pair->attr, "ns") == 0)
@@ -875,6 +880,7 @@ addlocaldnsserver(DN *dp, int class, char *ipaddr, int i)
 	DN *nsdp;
 	RR *rp;
 	char buf[32];
+	uchar ip[IPaddrlen];
 
 	/* reject our own ip addresses so we don't query ourselves via udp */
 	if (myaddr(ipaddr))
@@ -905,8 +911,11 @@ addlocaldnsserver(DN *dp, int class, char *ipaddr, int i)
 	rp->ttl = (1UL<<31)-1;
 	rrattach(rp, Authoritative);	/* will not attach rrs in my area */
 
-	/* A record */
-	rp = rralloc(Ta);
+	/* A or AAAA record */
+	if (parseip(ip, ipaddr) >= 0 && isv4(ip))
+		rp = rralloc(Ta);
+	else
+		rp = rralloc(Taaaa);
 	rp->ip = dnlookup(ipaddr, class, 1);
 	rp->owner = nsdp;
 	rp->local = 1;

+ 4 - 1
sys/src/cmd/ndb/dn.c

@@ -1047,7 +1047,10 @@ rrtype(char *atype)
 	/* make any a synonym for all */
 	if(strcmp(atype, "any") == 0)
 		return Tall;
-	return atoi(atype);
+	else if(isascii(atype[0]) && isdigit(atype[0]))
+		return atoi(atype);
+	else
+		return -1;
 }
 
 /*

+ 2 - 0
sys/src/cmd/ndb/dnnotify.c

@@ -65,6 +65,8 @@ send_notify(char *slave, RR *soa, Request *req)
 			dnslog("bad address %s to notify", slave);
 	} else {
 		rp = dnresolve(slave, Cin, Ta, req, nil, 0, 1, 1, &status);
+		if(rp == nil)
+			rp = dnresolve(slave, Cin, Taaaa, req, nil, 0, 1, 1, &status);
 		if(rp == nil)
 			return;
 		parseip(up->raddr, rp->ip->name);

+ 64 - 14
sys/src/cmd/ndb/dnresolve.c

@@ -204,7 +204,7 @@ dnresolve(char *name, int class, int type, Request *req, RR **cn, int depth,
 			}
 
 		/* distinction between not found and not good */
-		if(rp == nil && status != nil && dp->respcode != 0)
+		if(rp == nil && status != nil && dp->respcode != Rok)
 			*status = dp->respcode;
 	}
 	procsetname(procname);
@@ -424,6 +424,9 @@ dnresolve1(char *name, int class, int type, Request *req, int depth,
 			/* unauthoritative db entries are hints */
 			if(rp->auth) {
 				noteinmem();
+				if(debug)
+					dnslog("[%d] dnresolve1 %s %d %d: auth rr in db",
+						getpid(), name, type, class);
 				return rp;
 			}
 		} else
@@ -432,6 +435,9 @@ dnresolve1(char *name, int class, int type, Request *req, int depth,
 				/* but Tall entries are special */
 				if(type != Tall || rp->query == Tall) {
 					noteinmem();
+					if(debug)
+						dnslog("[%d] dnresolve1 %s %d %d: rr not in db",
+							getpid(), name, type, class);
 					return rp;
 				}
 	rrfreelist(rp);
@@ -446,8 +452,12 @@ dnresolve1(char *name, int class, int type, Request *req, int depth,
 	if(type != Tcname){
 		rp = rrlookup(dp, Tcname, NOneg);
 		rrfreelist(rp);
-		if(rp)
+		if(rp){
+			if(debug)
+				dnslog("[%d] dnresolve1 %s %d %d: rr from rrlookup for non-cname",
+					getpid(), name, type, class);
 			return nil;
+		}
 	}
 
 	/*
@@ -468,16 +478,34 @@ dnresolve1(char *name, int class, int type, Request *req, int depth,
 	rp = issuequery(qp, name, class, depth, recurse);
 	querydestroy(qp);
 	free(qp);
-	if(rp)
+	if(rp){
+		if(debug)
+			dnslog("[%d] dnresolve1 %s %d %d: rr from query",
+				getpid(), name, type, class);
 		return rp;
+	}
 
 	/* settle for a non-authoritative answer */
 	rp = rrlookup(dp, type, OKneg);
-	if(rp)
+	if(rp){
+		if(debug)
+			dnslog("[%d] dnresolve1 %s %d %d: rr from rrlookup",
+				getpid(), name, type, class);
 		return rp;
+	}
 
 	/* noone answered.  try the database, we might have a chance. */
-	return dblookup(name, class, type, 0, 0);
+	rp = dblookup(name, class, type, 0, 0);
+	if (rp) {
+		if(debug)
+			dnslog("[%d] dnresolve1 %s %d %d: rr from dblookup",
+				getpid(), name, type, class);
+	}else{
+		if(debug)
+			dnslog("[%d] dnresolve1 %s %d %d: no rr from dblookup; crapped out",
+				getpid(), name, type, class);
+	}
+	return rp;
 }
 
 /*
@@ -535,6 +563,24 @@ udpport(char *mtpt)
 	return fd;
 }
 
+void
+initdnsmsg(DNSmsg *mp, RR *rp, int flags, ushort reqno)
+{
+	mp->flags = flags;
+	mp->id = reqno;
+	mp->qd = rp;
+}
+
+DNSmsg *
+newdnsmsg(RR *rp, int flags, ushort reqno)
+{
+	DNSmsg *mp;
+
+	mp = emalloc(sizeof *mp);
+	initdnsmsg(mp, rp, flags, reqno);
+	return mp;
+}
+
 /* generate a DNS UDP query packet */
 int
 mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno)
@@ -542,6 +588,7 @@ mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno)
 	DNSmsg m;
 	int len;
 	Udphdr *uh = (Udphdr*)buf;
+	RR *rp;
 
 	/* stuff port number into output buffer */
 	memset(uh, 0, sizeof *uh);
@@ -549,13 +596,9 @@ mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno)
 
 	/* make request and convert it to output format */
 	memset(&m, 0, sizeof m);
-	m.flags = flags;
-	m.id = reqno;
-	m.qd = rralloc(type);
-	m.qd->owner = dp;
-	m.qd->type = type;
-	if (m.qd->type != type)
-		dnslog("mkreq: bogus type %d", type);
+	rp = rralloc(type);
+	rp->owner = dp;
+	initdnsmsg(&m, rp, flags, reqno);
 	len = convDNS2M(&m, &buf[Udphdrsize], Maxudp);
 	rrfree(m.qd);
 	memset(&m, 0, sizeof m);		/* cause trouble */
@@ -771,11 +814,15 @@ serveraddrs(Query *qp, int nd, int depth)
 		if(rp->marker)
 			continue;
 		arp = rrlookup(rp->host, Ta, NOneg);
+		if(arp == nil)
+			arp = rrlookup(rp->host, Taaaa, NOneg);
 		if(arp){
 			rp->marker = 1;
 			break;
 		}
 		arp = dblookup(rp->host->name, Cin, Ta, 0, 0);
+		if(arp == nil)
+			arp = dblookup(rp->host->name, Cin, Taaaa, 0, 0);
 		if(arp){
 			rp->marker = 1;
 			break;
@@ -801,6 +848,9 @@ serveraddrs(Query *qp, int nd, int depth)
 
 			arp = dnresolve(rp->host->name, Cin, Ta, qp->req, 0,
 				depth+1, Recurse, 1, 0);
+			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);
@@ -1158,7 +1208,7 @@ procansw(Query *qp, DNSmsg *mp, uchar *srcip, int depth, Dest *p)
 		if(isnegrname(mp))
 			qp->dp->respcode = Rname;
 		else
-			qp->dp->respcode = 0;
+			qp->dp->respcode = Rok;
 
 		/*
 		 *  cache any negative responses, free soarr.
@@ -1346,7 +1396,7 @@ queryns(Query *qp, int depth, uchar *ibuf, uchar *obuf, ulong waitms, int inns)
 	for(p = dest; p < qp->curdest; p++) {
 		destck(p);
 		if(p->code != Rserver)
-			qp->dp->respcode = 0;
+			qp->dp->respcode = Rok;
 		p->magic = 0;			/* prevent accidents */
 	}
 

+ 119 - 64
sys/src/cmd/ndb/dns.c

@@ -81,6 +81,7 @@ char	*logfile = "dns";	/* or "dns.test" */
 char	*dbfile;
 char	mntpt[Maxpath];
 
+int	addforwtarg(char *);
 int	fillreply(Mfile*, int);
 void	freejob(Job*);
 void	io(void);
@@ -102,6 +103,10 @@ void	rwstat(Job*, Mfile*);
 void	sendmsg(Job*, char*);
 void	setext(char*, int, char*);
 
+static char *lookupqueryold(Job*, Mfile*, Request*, char*, char*, int, int);
+static char *lookupquerynew(Job*, Mfile*, Request*, char*, char*, int, int);
+static char *respond(Job*, Mfile*, RR*, char*, int, int);
+
 void
 usage(void)
 {
@@ -110,8 +115,6 @@ usage(void)
 	exits("usage");
 }
 
-int addforwtarg(char *);
-
 void
 main(int argc, char *argv[])
 {
@@ -700,26 +703,25 @@ rread(Job *job, Mfile *mf)
 void
 rwrite(Job *job, Mfile *mf, Request *req)
 {
-	int rooted, status, wantsav;
-	long n;
+	int rooted, wantsav, send;
 	ulong cnt;
 	char *err, *p, *atype;
-	RR *rp, *tp, *neg;
+	char errbuf[ERRMAX];
 
 	err = nil;
 	cnt = job->request.count;
-	if(mf->qid.type & QTDIR){
+	send = 1;
+	if(mf->qid.type & QTDIR)
 		err = "can't write directory";
-		goto send;
-	}
-	if (job->request.offset != 0) {
+	else if (job->request.offset != 0)
 		err = "writing at non-zero offset";
-		goto send;
-	}
-	if(cnt >= Maxrequest){
+	else if(cnt >= Maxrequest)
 		err = "request too long";
+	else
+		send = 0;
+	if (send)
 		goto send;
-	}
+
 	job->request.data[cnt] = 0;
 	if(cnt > 0 && job->request.data[cnt-1] == '\n')
 		job->request.data[cnt-1] = 0;
@@ -728,35 +730,31 @@ rwrite(Job *job, Mfile *mf, Request *req)
 	 *  special commands
 	 */
 //	dnslog("rwrite got: %s", job->request.data);
-	if(strcmp(job->request.data, "debug")==0){
+	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)
 		debug ^= 1;
-		goto send;
-	} else if(strcmp(job->request.data, "dump")==0){
+	else if(strcmp(job->request.data, "dump")==0)
 		dndump("/lib/ndb/dnsdump");
-		goto send;
-	} else if(strcmp(job->request.data, "poolcheck")==0){
+	else if(strcmp(job->request.data, "poolcheck")==0)
 		poolcheck(mainmem);
-		goto send;
-	} else if(strcmp(job->request.data, "refresh")==0){
+	else if(strcmp(job->request.data, "refresh")==0)
 		needrefresh = 1;
-		goto send;
-	} else if(strcmp(job->request.data, "restart")==0){
+	else if(strcmp(job->request.data, "restart")==0)
 		stop = 1;
-		goto send;
-	} else if(strcmp(job->request.data, "stats")==0){
+	else if(strcmp(job->request.data, "stats")==0)
 		dnstats("/lib/ndb/dnsstats");
-		goto send;
-	} else if(strncmp(job->request.data, "target ", 7)==0){
+	else if(strncmp(job->request.data, "target ", 7)==0){
 		target = atol(job->request.data + 7);
 		dnslog("target set to %ld", target);
+	} else
+		send = 0;
+	if (send)
 		goto send;
-	} else if(strcmp(job->request.data, "age")==0){
-		dnslog("dump, age & dump forced");
-		dndump("/lib/ndb/dnsdump1");
-		dnforceage();
-		dndump("/lib/ndb/dnsdump2");
-		goto send;
-	}
 
 	/*
 	 *  kill previous reply
@@ -769,7 +767,9 @@ rwrite(Job *job, Mfile *mf, Request *req)
 	 */
 	atype = strchr(job->request.data, ' ');
 	if(atype == 0){
-		err = "illegal request";
+		snprint(errbuf, sizeof errbuf, "illegal request %s",
+			job->request.data);
+		err = errbuf;
 		goto send;
 	} else
 		*atype++ = 0;
@@ -791,7 +791,8 @@ rwrite(Job *job, Mfile *mf, Request *req)
 	stats.qrecvd9p++;
 	mf->type = rrtype(atype);
 	if(mf->type < 0){
-		err = "unknown type";
+		snprint(errbuf, sizeof errbuf, "unknown type %s", atype);
+		err = errbuf;
 		goto send;
 	}
 
@@ -809,8 +810,32 @@ rwrite(Job *job, Mfile *mf, Request *req)
 	} else
 		wantsav = 0;
 
+	err = lookupqueryold(job, mf, req, errbuf, p, wantsav, rooted);
+send:
+	dncheck(0, 1);
+	job->reply.count = cnt;
+	sendmsg(job, err);
+}
+
+/*
+ * dnsdebug calls
+ *	rr = dnresolve(buf, Cin, type, &req, 0, 0, Recurse, rooted, 0);
+ * which generates a UDP query, which eventually calls
+ *	dnserver(&reqmsg, &repmsg, &req, buf, rcode);
+ * which calls
+ *	rp = dnresolve(name, Cin, type, req, &mp->an, 0, recurse, 1, 0);
+ *
+ * but here we just call dnresolve directly.
+ */
+static char *
+lookupqueryold(Job *job, Mfile *mf, Request *req, char *errbuf, char *p,
+	int wantsav, int rooted)
+{
+	int status;
+	RR *rp, *neg;
+
 	dncheck(0, 1);
-	status = 0;
+	status = Rok;
 	rp = dnresolve(p, Cin, mf->type, req, 0, 0, Recurse, rooted, &status);
 
 	dncheck(0, 1);
@@ -822,43 +847,73 @@ rwrite(Job *job, Mfile *mf, Request *req)
 	}
 	unlock(&dnlock);
 
+	return respond(job, mf, rp, errbuf, status, wantsav);
+}
+
+static char *
+respond(Job *job, Mfile *mf, RR *rp, char *errbuf, int status, int wantsav)
+{
+	long n;
+	RR *tp;
+
 	if(rp == nil)
 		switch(status){
 		case Rname:
-			err = "name does not exist";
-			break;
+			return "name does not exist";
 		case Rserver:
-			err = "dns failure";
-			break;
+			return "dns failure";
+		case Rok:
 		default:
-			err = "resource does not exist";
-			break;
+			snprint(errbuf, ERRMAX,
+				"resource does not exist; negrcode %d", status);
+			return errbuf;
 		}
-	else {
-		lock(&joblock);
-		if(!job->flushed){
-			/* format data to be read later */
-			n = 0;
-			mf->nrr = 0;
-			for(tp = rp; mf->nrr < Maxrrr-1 && n < Maxreply && tp &&
-			    tsame(mf->type, tp->type); tp = tp->next){
-				mf->rr[mf->nrr++] = n;
-				if(wantsav)
-					n += snprint(mf->reply+n, Maxreply-n,
-						"%Q", tp);
-				else
-					n += snprint(mf->reply+n, Maxreply-n,
-						"%R", tp);
-			}
-			mf->rr[mf->nrr] = n;
+
+	lock(&joblock);
+	if(!job->flushed){
+		/* format data to be read later */
+		n = 0;
+		mf->nrr = 0;
+		for(tp = rp; mf->nrr < Maxrrr-1 && n < Maxreply && tp &&
+		    tsame(mf->type, tp->type); tp = tp->next){
+			mf->rr[mf->nrr++] = n;
+			if(wantsav)
+				n += snprint(mf->reply+n, Maxreply-n, "%Q", tp);
+			else
+				n += snprint(mf->reply+n, Maxreply-n, "%R", tp);
 		}
-		unlock(&joblock);
-		rrfreelist(rp);
+		mf->rr[mf->nrr] = n;
 	}
-send:
+	unlock(&joblock);
+	rrfreelist(rp);
+	return nil;
+}
+
+/* simulate what dnsudpserver does */
+static char *
+lookupquerynew(Job *job, Mfile *mf, Request *req, char *errbuf, char *p,
+	int wantsav, int)
+{
+	char *err;
+	uchar buf[Udphdrsize + Maxudp + 1024];
+	DNSmsg *mp;
+	DNSmsg repmsg;
+	RR *rp;
+
 	dncheck(0, 1);
-	job->reply.count = cnt;
-	sendmsg(job, err);
+
+	memset(&repmsg, 0, sizeof repmsg);
+	rp = rralloc(mf->type);
+	rp->owner = dnlookup(p, Cin, 1);
+	mp = newdnsmsg(rp, Frecurse|Oquery, (ushort)rand());
+
+	dnserver(mp, &repmsg, req, buf, Rok);
+
+	freeanswers(mp);
+	err = respond(job, mf, repmsg.an, errbuf, Rok, wantsav);
+	repmsg.an = nil;		/* freed above */
+	freeanswers(&repmsg);
+	return err;
 }
 
 void

+ 2 - 0
sys/src/cmd/ndb/dns.h

@@ -532,6 +532,8 @@ RR*	dnresolve(char*, int, int, Request*, RR**, int, int, int, int*);
 int	udpport(char *);
 int	mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno);
 int	seerootns(void);
+void	initdnsmsg(DNSmsg *mp, RR *rp, int flags, ushort reqno);
+DNSmsg*	newdnsmsg(RR *rp, int flags, ushort reqno);
 
 /* dnserver.c */
 void	dnserver(DNSmsg*, DNSmsg*, Request*, uchar *, int);

+ 10 - 3
sys/src/cmd/ndb/dnsdebug.c

@@ -40,7 +40,7 @@ void	squirrelserveraddrs(void);
 void
 usage(void)
 {
-	fprint(2, "%s: [-rx] [-f db-file]\n", argv0);
+	fprint(2, "%s: [-rx] [-f db-file] [[@server] domain [type]]\n", argv0);
 	exits("usage");
 }
 
@@ -300,6 +300,8 @@ getdnsservers(int class)
 void
 squirrelserveraddrs(void)
 {
+	int v4;
+	char *attr;
 	RR *rr, *rp, **l;
 	Request req;
 
@@ -312,8 +314,10 @@ squirrelserveraddrs(void)
 	rr = getdnsservers(Cin);
 	l = &serveraddrs;
 	for(rp = rr; rp != nil; rp = rp->next){
-		if(strcmp(ipattr(rp->host->name), "ip") == 0){
-			*l = rralloc(Ta);
+		attr = ipattr(rp->host->name);
+		v4 = strcmp(attr, "ip") == 0;
+		if(v4 || strcmp(attr, "ipv6") == 0){
+			*l = rralloc(v4? Ta: Taaaa);
 			(*l)->owner = rp->host;
 			(*l)->ip = rp->host;
 			l = &(*l)->next;
@@ -322,6 +326,9 @@ squirrelserveraddrs(void)
 		req.isslave = 1;
 		req.aborttime = NS2MS(nowns) + Maxreqtm;
 		*l = dnresolve(rp->host->name, Cin, Ta, &req, 0, 0, Recurse, 0, 0);
+		if(*l == nil)
+			*l = dnresolve(rp->host->name, Cin, Taaaa, &req,
+				0, 0, Recurse, 0, 0);
 		while(*l != nil)
 			l = &(*l)->next;
 	}

+ 5 - 0
sys/src/cmd/ndb/dnserver.c

@@ -210,9 +210,14 @@ hint(RR **last, RR *rp)
 		hp = rrlookup(rp->host, Ta, NOneg);
 		if(hp == nil)
 			hp = dblookup(rp->host->name, Cin, Ta, 0, 0);
+		if(hp == nil)
+			hp = rrlookup(rp->host, Taaaa, NOneg);
+		if(hp == nil)
+			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);
 		rrcat(last, hp);
 		break;
 	}
 }
+ 

+ 1 - 1
sys/src/cmd/ndb/dnudpserver.c

@@ -238,7 +238,7 @@ restart:
 					uh->rport[1], reqmsg.id,
 					reqmsg.qd->owner->name,
 					rrname(reqmsg.qd->type, tname,
-					sizeof tname));	// DEBUG
+					sizeof tname));
 		}
 		/* loop through each question */
 		while(reqmsg.qd){