code: plan9front

Download patch

ref: eb8fe8137b742646e9f3402149596eb8da62cc72
parent: 453d3c3d4c96899c7bbca81b8a143ac7a934aebe
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Nov 1 15:25:27 EDT 2023

ndb/dns: better handling of extended response code

--- a/sys/src/cmd/ndb/dn.c
+++ b/sys/src/cmd/ndb/dn.c
@@ -36,8 +36,7 @@
 } dnvars;
 
 /* names of RR types */
-static char *rrtname[] =
-{
+static char *rrnametab[] = {
 [Ta]		"ip",
 [Tns]		"ns",
 [Tmd]		"md",
@@ -102,8 +101,7 @@
 };
 
 /* names of response codes */
-char *rname[Rmask+1] =
-{
+static char *rcnametab[] = {
 [Rok]			"ok",
 [Rformat]		"format error",
 [Rserver]		"server failure",
@@ -123,17 +121,7 @@
 [Rbadname]		"duplicate key name",
 [Rbadalg]		"bad algorithm",
 };
-unsigned nrname = nelem(rname);
 
-/* names of op codes */
-char *opname[] =
-{
-[Oquery]	"query",
-[Oinverse]	"inverse query (retired)",
-[Ostatus]	"status",
-[Oupdate]	"update",
-};
-
 int maxage = Defmaxage;
 ulong target = Deftarget;
 int needrefresh;
@@ -718,9 +706,7 @@
 	for(; rp; rp = next){
 		next = rp->next;
 		rp->next = nil;
-		if(rp->type == Tall
-		|| rp->type == Topt
-		|| !rrsupported(rp->type)
+		if(rp->type == Tall || rp->type == Topt || !rrsupported(rp->type)
 		|| cfg.cachedb && !rp->db && inmyarea(rp->owner->name))
 			rrfree(rp);
 		else
@@ -981,8 +967,8 @@
 {
 	int i;
 
-	for(i = 0; i < nelem(rrtname); i++)
-		if(rrtname[i] && strcmp(rrtname[i], atype) == 0)
+	for(i = 0; i < nelem(rrnametab); i++)
+		if(rrnametab[i] && strcmp(rrnametab[i], atype) == 0)
 			return i;
 
 	/* make any a synonym for all */
@@ -1000,9 +986,9 @@
 int
 rrsupported(int type)
 {
-	if(type < 0 || type >= nelem(rrtname))
+	if(type < 0 || type >= nelem(rrnametab))
 		return 0;
-	return rrtname[type] != nil;
+	return rrnametab[type] != nil;
 }
 
 /*
@@ -1188,7 +1174,7 @@
 		rrname(rp->type, buf, sizeof buf));
 
 	if(rp->negative){
-		fmtprint(&fstr, "\tnegative - rcode %d", rp->negrcode);
+		fmtprint(&fstr, "\tnegative - rcode %d %s", rp->negrcode, rcname(rp->negrcode));
 		goto out;
 	}
 
@@ -1826,7 +1812,22 @@
 
 
 /* from here down is copied to ip/snoopy/dns.c periodically to update it */
+/*
+ *  convert a integer response code to ascii name
+ */
+char*
+rcname(int rcode)
+{
+	char *s;
 
+	s = nil;
+	if(rcode >= 0 && rcode < nelem(rcnametab))
+		s = rcnametab[rcode];
+	if(s==nil)
+		s = "";
+	return s;
+}
+
 /*
  *  convert an integer RR type to it's ascii name
  */
@@ -1833,16 +1834,16 @@
 char*
 rrname(int type, char *buf, int len)
 {
-	char *t;
+	char *s;
 
-	t = nil;
-	if(type >= 0 && type < nelem(rrtname))
-		t = rrtname[type];
-	if(t==nil){
+	s = nil;
+	if(type >= 0 && type < nelem(rrnametab))
+		s = rrnametab[type];
+	if(s==nil){
 		snprint(buf, len, "%d", type);
-		t = buf;
+		s = buf;
 	}
-	return t;
+	return s;
 }
 
 /*
--- a/sys/src/cmd/ndb/dnnotify.c
+++ b/sys/src/cmd/ndb/dnnotify.c
@@ -15,10 +15,11 @@
 	/* move one question from reqp to repp */
 	tp = reqp->qd;
 	reqp->qd = tp->next;
-	tp->next = 0;
+	tp->next = nil;
 	repp->qd = tp;
 	repp->id = reqp->id;
 	repp->flags = Fresp  | Onotify | Fauth;
+	setercode(repp, Rok);
 
 	/* make sure its the right type */
 	if(repp->qd->type != Tsoa)
--- a/sys/src/cmd/ndb/dnresolve.c
+++ b/sys/src/cmd/ndb/dnresolve.c
@@ -103,7 +103,7 @@
  */
 RR*
 dnresolve(char *name, int class, int type, Request *req, RR **cn, int depth,
-	int recurse, int rooted, int *status)
+	int recurse, int rooted, int *rcode)
 {
 	RR *rp, *nrp, *drp;
 	DN *dp;
@@ -111,8 +111,8 @@
 	char *procname;
 	char nname[Domlen];
 
-	if(status)
-		*status = Rok;
+	if(rcode)
+		*rcode = Rok;
 
 	if(depth > 12)			/* in a recursive loop? */
 		return nil;
@@ -129,7 +129,7 @@
 			snprint(nname, sizeof nname, "%s.%s", name,
 				nrp->ptr->name);
 			rp = dnresolve(nname, class, type, req, cn, depth+1,
-				recurse, rooted, status);
+				recurse, rooted, rcode);
 			rrfreelist(rrremneg(&rp));
 		}
 		if(drp != nil)
@@ -174,8 +174,8 @@
 			}
 
 		/* distinction between not found and not good */
-		if(rp == nil && status != nil && dp->respcode != Rok)
-			*status = dp->respcode;
+		if(rp == nil && rcode != nil && dp->respcode != Rok)
+			*rcode = dp->respcode;
 	}
 	procsetname("%s", procname);
 	free(procname);
@@ -500,7 +500,7 @@
 }
 
 RR*
-getednsopt(DNSmsg *mp)
+getednsopt(DNSmsg *mp, int *rcode)
 {
 	RR *rp, *x;
 
@@ -507,13 +507,18 @@
 	rp = rrremtype(&mp->ar, Topt);
 	if(rp == nil)
 		return nil;
+
 	mp->arcount--;
 	while((x = rp->next) != nil){
 		rp->next = x->next;
 		rrfree(x);
 		mp->arcount--;
+		*rcode = Rformat;
 	}
 
+	if(rp->eflags & Evers)
+		*rcode = Rbadvers;
+
 	if(rp->udpsize < 512)
 		rp->udpsize = 512;
 
@@ -520,6 +525,24 @@
 	return rp;
 }
 
+int
+getercode(DNSmsg *mp)
+{
+	if(mp->edns == nil)
+		return mp->flags & Rmask;
+	return (mp->flags & 0xF) | (mp->edns->eflags & Ercode) >> 20;
+}
+
+void
+setercode(DNSmsg *mp, int rcode)
+{
+	if(mp->edns){
+		mp->edns->eflags = (mp->edns->eflags & ~Ercode) | ((rcode << 20) & Ercode);
+		rcode &= 0xF;
+	}
+	mp->flags = (mp->flags & ~Rmask) | (rcode & Rmask);
+}
+
 RR*
 mkednsopt(void)
 {
@@ -897,15 +920,7 @@
 	rrattach(rp, Authoritative);
 }
 
-/* is mp a cachable negative response (with Rname set)? */
 static int
-isnegrname(DNSmsg *mp)
-{
-	/* TODO: could add || cfg.justforw to RHS of && */
-	return mp->an == nil && (mp->flags & Rmask) == Rname;
-}
-
-static int
 filterhints(RR *rp, void *arg)
 {
 	RR *nsrp;
@@ -974,19 +989,19 @@
 	if(mp->an == nil)
 		stats.negans++;
 
-	/* get the rcode */
-	rcode = mp->flags & Rmask;
+	/* get extended rcode */
+	rcode = Rok;
+	mp->edns = getednsopt(mp, &rcode);
+	if(rcode == Rok)
+		rcode = getercode(mp);
+	rrfreelistptr(&mp->edns);
 
-	/* get extended rcode from edns */
-	if((tp = getednsopt(mp)) != nil){
-		rcode = (rcode & 15) | (tp->eflags & Ercode) >> 20;
-		rrfreelist(tp);
-	}
-
 	/* ignore any error replies */
 	switch(rcode){
+	case Rformat:
 	case Rrefused:
 	case Rserver:
+	case Rbadvers:
 		stats.negserver++;
 		freeanswers(mp);
 		p->code = Rserver;
@@ -1065,7 +1080,7 @@
 	 *  A negative response now also terminates the search.
 	 */
 	if(mp->an || (mp->flags & Fauth) && mp->ns == nil){
-		if(isnegrname(mp))
+		if(mp->an == nil && rcode == Rname)
 			qp->dp->respcode = Rname;
 		else
 			qp->dp->respcode = Rok;
@@ -1080,7 +1095,7 @@
 		else
 			rrfreelist(soarr);
 		return 1;
-	} else if (isnegrname(mp)) {
+	} else if (mp->an == nil && rcode == Rname) {
 		qp->dp->respcode = Rname;
 		/*
 		 *  cache negative response.
@@ -1279,16 +1294,11 @@
 			if(readreply(qp, Udp, fd, endms, &m, srcip) < 0)
 				break;
 
-			if(debug)
-				dnslog("%d: got reply from %I", qp->req->id, srcip);
-
 			/* find responder */
 			for(p = dest; p < edest; p++)
 				if(ipcmp(p->a, srcip) == 0)
 					break;
 			if(p >= edest){
-				dnslog("%d: response from %I but no destination",
-					qp->req->id, srcip);
 				freeanswers(&m);
 				continue;
 			}
--- a/sys/src/cmd/ndb/dns.c
+++ b/sys/src/cmd/ndb/dns.c
@@ -736,29 +736,29 @@
 lookupquery(Job *job, Mfile *mf, Request *req, char *errbuf, char *p,
 	int wantsav, int rooted)
 {
-	int status;
+	int rcode;
 	RR *rp, *neg;
 
-	status = Rok;
-	rp = dnresolve(p, Cin, mf->type, req, nil, 0, Recurse, rooted, &status);
+	rcode = Rok;
+	rp = dnresolve(p, Cin, mf->type, req, nil, 0, Recurse, rooted, &rcode);
 
 	neg = rrremneg(&rp);
 	if(neg){
-		status = neg->negrcode;
+		rcode = neg->negrcode;
 		rrfreelist(neg);
 	}
 
-	return respond(job, mf, rp, errbuf, status, wantsav);
+	return respond(job, mf, rp, errbuf, rcode, wantsav);
 }
 
 static char *
-respond(Job *job, Mfile *mf, RR *rp, char *errbuf, int status, int wantsav)
+respond(Job *job, Mfile *mf, RR *rp, char *errbuf, int rcode, int wantsav)
 {
 	long n;
 	RR *tp;
 
 	if(rp == nil)
-		switch(status){
+		switch(rcode){
 		case Rname:
 			return "name does not exist";
 		case Rserver:
@@ -766,7 +766,8 @@
 		case Rok:
 		default:
 			snprint(errbuf, ERRMAX,
-				"resource does not exist; negrcode %d", status);
+				"resource does not exist; negrcode %d (%s)",
+					rcode, rcname(rcode));
 			return errbuf;
 		}
 
@@ -874,8 +875,7 @@
 
 	if(!debug)
 		return;
-
-	dnslog("%d: %s %I flags:%s%s%s%s%s", id, rcvd, addr,
+	dnslog("%d: %s %I %s (%s%s%s%s%s)", id, rcvd, addr, rcname(getercode(mp)),
 		mp->flags & Fauth? " auth": "",
 		mp->flags & Ftrunc? " trunc": "",
 		mp->flags & Frecurse? " rd": "",
--- a/sys/src/cmd/ndb/dns.h
+++ b/sys/src/cmd/ndb/dns.h
@@ -118,7 +118,7 @@
 	/* EDNS flags (eflags) */
 	Ercode=		0xff<<24,
 	Evers=		0xff<<16,
-	Ednssecok=	1<<15,
+	Edo=		1<<15,	/* DNSSEC ok */
 
 	Domlen=		256,	/* max domain name length (with NULL) */
 	Labellen=	64,	/* max domain label length (with NULL) */
@@ -434,10 +434,6 @@
 extern int	maxage;		/* age of oldest entry in cache (secs) */
 extern ulong	target;
 
-extern char	*rname[];
-extern unsigned	nrname;
-extern char	*opname[];
-
 RR*	getdnsservers(int);
 
 void	abort(); /* char*, ... */;
@@ -463,6 +459,7 @@
 void	getactivity(Request*);
 void	putactivity(Request*);
 RR*	randomize(RR*);
+char*	rcname(int);
 RR*	rralloc(int);
 void	rrattach(RR*, int);
 int	rravfmt(Fmt*);
@@ -512,7 +509,9 @@
 int	udpport(char *);
 int	mkreq(DN*, int type, uchar *pkt, int flags, ushort);
 RR*	mkednsopt(void);
-RR*	getednsopt(DNSmsg*);
+RR*	getednsopt(DNSmsg*, int*);
+int	getercode(DNSmsg*);
+void	setercode(DNSmsg*, int);
 
 /* dnserver.c */
 void	dnserver(DNSmsg*, DNSmsg*, Request*, uchar *, int);
--- a/sys/src/cmd/ndb/dnsdebug.c
+++ b/sys/src/cmd/ndb/dnsdebug.c
@@ -109,10 +109,10 @@
 int
 prettyrrfmt(Fmt *f)
 {
-	int rv;
-	char *strp, *t, buf[32];
+	char tname[32], *strp, *t;
 	Fmt fstr;
 	RR *rp;
+	int rv;
 
 	fmtstrinit(&fstr);
 	rp = va_arg(f->args, RR*);
@@ -123,7 +123,7 @@
 	else
 		rv = fmtprint(f, "%-32.32s %-15.15s %-5.5s%s",
 			rp->owner->name, longtime(rp->ttl),
-			rrname(rp->type, buf, sizeof buf), t);
+			rrname(rp->type, tname, sizeof tname), t);
 	free(strp);
 	return rv;
 }
@@ -141,34 +141,10 @@
 void
 logreply(int id, char *rcvd, uchar *addr, DNSmsg *mp)
 {
+	char tname[32];
 	RR *rp;
-	char buf[12], resp[32];
 
-	switch(mp->flags & Rmask){
-	case Rok:
-		strcpy(resp, "OK");
-		break;
-	case Rformat:
-		strcpy(resp, "Format error");
-		break;
-	case Rserver:
-		strcpy(resp, "Server failed");
-		break;
-	case Rname:
-		strcpy(resp, "Nonexistent");
-		break;
-	case Runimplimented:
-		strcpy(resp, "Unimplemented");
-		break;
-	case Rrefused:
-		strcpy(resp, "Refused");
-		break;
-	default:
-		sprint(resp, "%d", mp->flags & Rmask);
-		break;
-	}
-
-	print("%d: %s %I %s (%s%s%s%s%s)\n", id, rcvd, addr, resp,
+	print("%d: %s %I %s (%s%s%s%s%s)\n", id, rcvd, addr, rcname(getercode(mp)),
 		mp->flags & Fauth? "authoritative": "",
 		mp->flags & Ftrunc? " truncated": "",
 		mp->flags & Frecurse? " recurse": "",
@@ -176,7 +152,7 @@
 		(mp->flags & (Fauth|Rmask)) == (Fauth|Rname)? " nx": "");
 	for(rp = mp->qd; rp != nil; rp = rp->next)
 		print("\tQ:    %s %s\n", rp->owner->name,
-			rrname(rp->type, buf, sizeof buf));
+			rrname(rp->type, tname, sizeof tname));
 	logsection("Ans:  ", mp->an);
 	logsection("Auth: ", mp->ns);
 	logsection("Hint: ", mp->ar);
--- a/sys/src/cmd/ndb/dnserver.c
+++ b/sys/src/cmd/ndb/dnserver.c
@@ -6,18 +6,6 @@
 static RR*	doextquery(DNSmsg*, Request*, int);
 static void	hint(RR**, RR*);
 
-static void
-setflags(DNSmsg *repp, int rcode, int flags)
-{
-	if(repp->edns){
-		repp->edns->eflags = (rcode >> 4) << 24;
-		rcode &= 15;
-	}
-	rcode &= Rmask;
-	flags &= ~Rmask;
-	repp->flags |= rcode | flags;
-}
-
 /*
  *  answer a dns request
  */
@@ -24,31 +12,28 @@
 void
 dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip, int rcode)
 {
-	int recursionflag;
-	char *cp, *errmsg;
-	char tname[32];
-	DN *nsdp, *dp;
+	char tname[32], *cp;
+	DN *nsdp;
 	Area *myarea;
-	RR *tp, *neg, *rp;
+	RR *rp, *neg;
 
-	recursionflag = cfg.nonrecursive? 0: Fcanrec;
 	repp->id = reqp->id;
-	repp->flags = Fresp | recursionflag | Oquery;
+	repp->flags = Fresp | (reqp->flags & Omask);
+	if(!cfg.nonrecursive && (reqp->flags & Omask) == Oquery)
+		repp->flags |= Fcanrec;
+	setercode(repp, Rok);
 
 	/* move one question from reqp to repp */
-	tp = reqp->qd;
-	reqp->qd = tp->next;
-	tp->next = nil;
-	repp->qd = tp;
+	rp = reqp->qd;
+	reqp->qd = rp->next;
+	rp->next = nil;
+	repp->qd = rp;
 
-	if (rcode) {
-		errmsg = "";
-		if (rcode >= 0 && rcode < nrname)
-			errmsg = rname[rcode];
-		dnslog("%d: server: response code 0%o (%s), req from %I",
-			req->id, rcode, errmsg, srcip);
+	if(rcode){
+		dnslog("%d: server: response code %d %s, req from %I",
+			req->id, rcode, rcname(rcode), srcip);
 		/* provide feedback to clients who send us trash */
-		setflags(repp, rcode, Fresp | Fcanrec | Oquery);
+		setercode(repp, rcode);
 		return;
 	}
 	if(repp->qd->type == Topt || !rrsupported(repp->qd->type)){
@@ -55,7 +40,7 @@
 		if(debug)
 			dnslog("%d: server: unsupported request %s from %I",
 				req->id, rrname(repp->qd->type, tname, sizeof tname), srcip);
-		setflags(repp, Runimplimented, Fresp | Fcanrec | Oquery);
+		setercode(repp, Runimplimented);
 		return;
 	}
 
@@ -63,44 +48,41 @@
 		if(debug)
 			dnslog("%d: server: unsupported class %d from %I",
 				req->id, repp->qd->owner->class, srcip);
-		setflags(repp, Runimplimented, Fresp | Fcanrec | Oquery);
+		setercode(repp, Runimplimented);
 		return;
 	}
 
 	myarea = inmyarea(repp->qd->owner->name);
-	if(myarea != nil) {
+	if(myarea){
 		if(repp->qd->type == Tixfr || repp->qd->type == Taxfr){
 			if(debug)
 				dnslog("%d: server: unsupported xfr request %s for %s from %I",
 					req->id, rrname(repp->qd->type, tname, sizeof tname),
 					repp->qd->owner->name, srcip);
-			setflags(repp, Runimplimented, Fresp | recursionflag | Oquery);
+			setercode(repp, Runimplimented);
 			return;
 		}
 	}
 	if(myarea == nil && cfg.nonrecursive) {
 		/* we don't recurse and we're not authoritative */
-		setflags(repp, Rok, Fresp | Oquery);
+		repp->flags &= ~(Fauth|Fcanrec);
 		neg = nil;
 	} else {
+		int recurse = (reqp->flags & Frecurse) && (repp->flags & Fcanrec);
+
 		/*
 		 *  get the answer if we can, in *repp
 		 */
-		if(reqp->flags & Frecurse)
-			neg = doextquery(repp, req, Recurse);
-		else
-			neg = doextquery(repp, req, Dontrecurse);
+		neg = doextquery(repp, req, recurse? Recurse: Dontrecurse);
 
 		/* authority is transitive */
-		if(myarea != nil || (repp->an && repp->an->auth))
+		if(myarea || (repp->an && repp->an->auth))
 			repp->flags |= Fauth;
 
 		/* pass on error codes */
-		if(repp->an == nil){
-			dp = dnlookup(repp->qd->owner->name, repp->qd->owner->class, 0);
-			if(dp->rr == nil)
-				if(reqp->flags & Frecurse)
-					setflags(repp, dp->respcode, Fauth);
+		if(recurse && repp->an == nil && repp->qd->owner->rr == nil){
+			repp->flags |= Fauth;
+			setercode(repp, repp->qd->owner->respcode);
 		}
 	}
 
@@ -124,9 +106,6 @@
 				break;
 			}
 
-			if(strncmp(nsdp->name, "local#", 6) == 0)
-				dnslog("%d: returning %s as nameserver",
-					req->id, nsdp->name);
 			repp->ns = dblookup(cp, repp->qd->owner->class, Tns, 0, 0);
 			if(repp->ns)
 				break;
@@ -137,10 +116,10 @@
 	 *  add ip addresses as hints
 	 */
 	if(repp->qd->type != Taxfr && repp->qd->type != Tixfr){
-		for(tp = repp->ns; tp; tp = tp->next)
-			hint(&repp->ar, tp);
-		for(tp = repp->an; tp; tp = tp->next)
-			hint(&repp->ar, tp);
+		for(rp = repp->ns; rp; rp = rp->next)
+			hint(&repp->ar, rp);
+		for(rp = repp->an; rp; rp = rp->next)
+			hint(&repp->ar, rp);
 	}
 
 	/*
@@ -148,15 +127,15 @@
 	 *  with negative caching
 	 */
 	if(repp->an == nil){
-		if(myarea != nil){
-			rrcopy(myarea->soarr, &tp);
-			rrcat(&repp->ns, tp);
+		if(myarea){
+			rrcopy(myarea->soarr, &rp);
+			rrcat(&repp->ns, rp);
 		} else if(neg != nil) {
 			if(neg->negsoaowner != nil) {
-				tp = rrlookup(neg->negsoaowner, Tsoa, NOneg);
-				rrcat(&repp->ns, tp);
+				rp = rrlookup(neg->negsoaowner, Tsoa, NOneg);
+				rrcat(&repp->ns, rp);
 			}
-			setflags(repp, neg->negrcode, repp->flags);
+			setercode(repp, neg->negrcode);
 		}
 	}
 
--- a/sys/src/cmd/ndb/dnsgetip.c
+++ b/sys/src/cmd/ndb/dnsgetip.c
@@ -14,19 +14,13 @@
 int aflag = 0;
 int addresses = 0;
 
-char Ebotch[] = "dns botch";
-
 char*
 resolve(char *name, int type)
 {
-	int status;
-	char *errmsg;
+	int rcode;
 	Request req;
 	RR *rr, *rp, *neg;
 
-	status = Rok;
-	errmsg = nil;
-
 	memset(&req, 0, sizeof req);
 	getactivity(&req);
 	req.aborttime = timems() + Maxreqtm;
@@ -33,15 +27,11 @@
 	req.isslave = 1;
 	req.from = argv0;
 
-	rr = dnresolve(name, Cin, type, &req, nil, 0, Recurse, 0, &status);
+	rcode = Rok;
+	rr = dnresolve(name, Cin, type, &req, nil, 0, Recurse, 0, &rcode);
 	neg = rrremneg(&rr);
-	if(rr == nil || neg != nil){
-		if(neg != nil)
-			status = neg->negrcode;
-		errmsg = Ebotch;
-		if(status > 0 && status < nrname)
-			errmsg = rname[status];
-	}
+	if(neg != nil)
+		rcode = neg->negrcode;
 
 	rrfreelist(neg);
 
@@ -55,7 +45,7 @@
 	rrfreelist(rr);
 	putactivity(&req);
 
-	return errmsg;
+	return rcode!=Rok? rcname(rcode): nil;
 }
 
 void
--- a/sys/src/cmd/ndb/dntcpserver.c
+++ b/sys/src/cmd/ndb/dntcpserver.c
@@ -81,7 +81,7 @@
 
 		stats.qrecvdtcp++;
 
-		rcode = 0;
+		rcode = Rok;
 		err = convM2DNS(pkt+2, len, &reqmsg, &rcode);
 		if(err){
 			dnslog("%d: server: input err, len %d: %s from %s",
@@ -89,7 +89,7 @@
 			free(err);
 			break;
 		}
-		if(rcode == 0)
+		if(rcode == Rok)
 			if(reqmsg.qdcount < 1){
 				dnslog("%d: server: no questions from %s",
 					req.id, caller);
@@ -113,11 +113,9 @@
 		logrequest(req.id, 0, "rcvd", callip, caller,
 			reqmsg.qd->owner->name, reqmsg.qd->type);
 
-		if((reqmsg.edns = getednsopt(&reqmsg)) != nil){
-			if(reqmsg.edns->eflags & Evers)
-				rcode = Rbadvers;
-			edns = mkednsopt();
-		}
+		if(rcode == Rok)
+			if((reqmsg.edns = getednsopt(&reqmsg, &rcode)) != nil)
+				edns = mkednsopt();
 
 		/* loop through each question */
 		while(reqmsg.qd){
@@ -222,6 +220,7 @@
 	repp->flags = Fauth | Fresp | Oquery;
 	if(!cfg.nonrecursive)
 		repp->flags |= Fcanrec;
+	setercode(repp, Rok);
 	dp = repp->qd->owner;
 
 	/* send the soa */
--- a/sys/src/cmd/ndb/dnudpserver.c
+++ b/sys/src/cmd/ndb/dnudpserver.c
@@ -120,7 +120,7 @@
 		served++;
 		stats.qrecvdudp++;
 
-		rcode = 0;
+		rcode = Rok;
 		err = convM2DNS(&pkt[Udphdrsize], len, &reqmsg, &rcode);
 		if(err){
 			/* first bytes in buf are source IP addr */
@@ -129,7 +129,7 @@
 			free(err);
 			goto freereq;
 		}
-		if (rcode == 0)
+		if(rcode == Rok)
 			if(reqmsg.qdcount < 1){
 				dnslog("%d: server: no questions from %s",
 					req.id, caller);
@@ -161,16 +161,15 @@
 
 		/* determine response size */
 		len = 512;	/* default */
-		if((reqmsg.edns = getednsopt(&reqmsg)) != nil){
-			if(reqmsg.edns->eflags & Evers)
-				rcode = Rbadvers;
-			edns = mkednsopt();
-			len = Maxudp;
-			if(edns->udpsize < len)
-				len = edns->udpsize;
-			if(reqmsg.edns->udpsize < len)
-				len = reqmsg.edns->udpsize;
-		}
+		if(rcode == Rok)
+			if((reqmsg.edns = getednsopt(&reqmsg, &rcode)) != nil){
+				edns = mkednsopt();
+				len = Maxudp;
+				if(edns->udpsize < len)
+					len = edns->udpsize;
+				if(reqmsg.edns->udpsize < len)
+					len = reqmsg.edns->udpsize;
+			}
 
 		/* loop through each question */
 		while(reqmsg.qd){
@@ -204,8 +203,7 @@
 	len = convDNS2M(rep, &pkt[Udphdrsize], len);
 	len += Udphdrsize;
 	if(write(fd, pkt, len) != len)
-		dnslog("%d: error sending reply to %I: %r",
-			req->id, pkt);
+		dnslog("%d: error sending reply to %I: %r", req->id, pkt);
 }
 
 /*