git: 9front

Download patch

ref: 42d7047c90fd82eec095dde5816032845adb222b
parent: b308b43f68c4b79f750790b40048253709373db4
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Jan 3 23:31:56 EST 2026

ndb/dns: improve hint processing

We used to only consider ip hints on filtered
(authoritative) ns records.

Now, consider hints for ns, mx, srv and cname records
as long as they are in baliwick.

For the baliwick check, we have to know the name server
responding to the request to find the authoritative zone.
For this, add a aux pointer to DNSmsg which gets
set to the Dest* of the responder and pass the whole
DNSmsg pointer to filterhints function.

On the server side, hints() function was kind of broken,
only providing ipv4 addresses. Fix it and provide hints
for these record types, both ipv4 and ipv6.

Also cleanup rrcat().

--- a/sys/src/cmd/ndb/dn.c
+++ b/sys/src/cmd/ndb/dn.c
@@ -1003,25 +1003,14 @@
 /*
  *  Add resource records to a list.
  */
-RR*
-rrcat(RR **start, RR *rp)
+void
+rrcat(RR **l, RR *rp)
 {
-	RR *olp, *nlp;
-	RR **last;
-
-	/* check for duplicates */
-	for (olp = *start; 0 && olp; olp = olp->next)
-		for (nlp = rp; nlp; nlp = nlp->next)
-			if (rrsame(nlp, olp))
-				dnslog("rrcat: duplicate RR: %R", nlp);
-	USED(olp);
-
-	last = start;
-	while(*last != nil)
-		last = &(*last)->next;
-
-	*last = rp;
-	return *start;
+	if(rp == nil)
+		return;
+	while(*l != nil)
+		l = &(*l)->next;
+	*l = rp;
 }
 
 RR*
--- a/sys/src/cmd/ndb/dnresolve.c
+++ b/sys/src/cmd/ndb/dnresolve.c
@@ -931,17 +931,49 @@
 }
 
 static int
+inbaliwick(RR *nsrp, RR *rr)
+{
+	char *zone;
+
+	if(nsrp == nil)
+		return 0;
+	if(nsrp->owner == rr->owner)
+		return 1;
+	zone = nsrp->owner->name;
+	if(strncmp(zone, "local#", 6) == 0)
+		return 1;
+	if(strncmp(zone, "override#", 9) == 0)
+		return 1;
+	return subsume(zone, rr->owner->name);
+}
+
+static int
 filterhints(RR *rp, void *arg)
 {
-	RR *nsrp;
+	DNSmsg *mp = arg;
+	RR *rr;
 
 	if(rp->type != Ta && rp->type != Taaaa)
 		return 0;
 
-	for(nsrp = arg; nsrp; nsrp = nsrp->next)
-		if(nsrp->type == Tns && rp->owner == nsrp->host)
+	for(rr = mp->ns; rr != nil; rr = rr->next){
+		if(rr->type == Tns && rr->host == rp->owner)
 			return 1;
+	}
 
+	for(rr = mp->an; rr != nil; rr = rr->next){
+		switch(rr->type){
+		case Tns:
+		case Tmx:
+		case Tsrv:
+		case Tcname:
+			if(rr->host == rp->owner){
+				Dest *dest = mp->responder;
+				return dest != nil && inbaliwick(dest->n, rp);
+			}
+		}
+	}
+
 	return 0;
 }
 
@@ -956,20 +988,13 @@
 	if(nsrp == nil)
 		return 0;
 
-	if(rp->type == Tsoa && rp->owner != nsrp->owner
-	&& !subsume(nsrp->owner->name, rp->owner->name)
-	&& strncmp(nsrp->owner->name, "local#", 6) != 0)
+	if(rp->type == Tsoa && !inbaliwick(nsrp, rp))
 		return 1;
 
 	if(rp->type != Tns)
 		return 0;
 
-	if(rp->owner != nsrp->owner
-	&& !subsume(nsrp->owner->name, rp->owner->name)
-	&& strncmp(nsrp->owner->name, "local#", 6) != 0)
-		return 1;
-
-	return baddelegation(rp, nsrp, dest->a);
+	return !inbaliwick(nsrp, rp) || baddelegation(rp, nsrp, dest->a);
 }
 
 static void
@@ -996,6 +1021,7 @@
 	RR *tp, *soarr;
 	int rv, rcode;
 
+	mp->responder = p;
 	if(mp->an == nil)
 		stats.negans++;
 
@@ -1061,8 +1087,8 @@
 		rrattach(mp->an, (mp->flags & Fauth) != 0);
 	}
 	if(mp->ar){
-		/* restrict hints to address rr's for nameservers only */
-		if((tp = rrremfilter(&mp->ar, filterhints, mp->ns)) != 0){
+		/* restrict hints to address rr's related to answer */
+		if((tp = rrremfilter(&mp->ar, filterhints, mp)) != 0){
 			reportandfree(mp->ar, "hint", p);
 			mp->ar = tp;
 		}
--- a/sys/src/cmd/ndb/dns.h
+++ b/sys/src/cmd/ndb/dns.h
@@ -359,6 +359,8 @@
 	int	arcount;	/* hints */
 	RR	*ar;
 	RR	*edns;		/* edns option */
+
+	void	*responder;	/* responding server */
 };
 
 /*
@@ -463,7 +465,7 @@
 RR*	rralloc(int);
 void	rrattach(RR*, int);
 int	rravfmt(Fmt*);
-RR*	rrcat(RR**, RR*);
+void	rrcat(RR**, RR*);
 RR**	rrcopy(RR*, RR**);
 int	rrfmt(Fmt*);
 void	rrfree(RR*);
--- a/sys/src/cmd/ndb/dnserver.c
+++ b/sys/src/cmd/ndb/dnserver.c
@@ -188,18 +188,15 @@
 	switch(rp->type){
 	case Tns:
 	case Tmx:
-	case Tmb:
-	case Tmf:
-	case Tmd:
+	case Tsrv:
+	case Tcname:
 		hp = rrlookup(rp->host, Ta, NOneg);
 		if(hp == nil)
 			hp = dblookup(rp->host->name, Cin, Ta, 0, 0);
+		rrcat(last, hp);
+		hp = rrlookup(rp->host, Taaaa, NOneg);
 		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;
 	}
--