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;
}
--
⑨