From: Colin Vidal Date: Fri, 17 Apr 2026 11:09:56 +0000 (+0200) Subject: Do not add glues from different parent in delegdb X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aeee4c1c1d0b1abf431556a465e4c49fb23ca4e0;p=thirdparty%2Fbind9.git Do not add glues from different parent in delegdb When processing a referral, the `cache_delegns()` function was accepting glues from a different parent. For instance: ``` AUTHORITY test.example. NS ns.test.example. test.example. NS ns.foo.example. test.example. NS ns.bar. ADDITIONAL ns.bar. A 1.2.3.4 ns.foo.example. A 5.6.7.8 ns.test.example. A 9.8.7.6 ``` In such situation, only the glues for `ns.foo.example.` and `ns.test.example.` should be used, and the glue from `ns.bar.` should be ignored as this is not either a sub-domain or a sibling domain, the parent is different (`bar.` instead of `example.`). This is now fixed. Sibling glue and cyclic sibling glues are defined in RFC 9471 section 2.2 and section 2.3. --- diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 3e5018f241f..19c4c29f0d0 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -6689,12 +6689,26 @@ cache_delegns(respctx_t *rctx) { dns_delegdb_t *delegdb = fctx->res->view->deleg; dns_delegset_t *delegset = NULL; dns_ttl_t ttl = rctx->ns_rdataset->ttl; + dns_fixedname_t fparent; + dns_name_t *parent = dns_fixedname_initname(&fparent); + size_t labels; isc_result_t result; FCTXTRACE("cache_delegns"); dns_delegset_allocset(delegdb, &delegset); + /* + * The top of the delegated zone is `rctx->ns_name`. So truncating + * the first label gives the common parent domain allowed to get + * glues (this allows in-domain and sibling, but not different + * parents). + */ + labels = dns_name_countlabels(rctx->ns_name); + if (labels > 1) { + dns_name_getlabelsequence(rctx->ns_name, 1, labels - 1, parent); + } + DNS_RDATASET_FOREACH(rctx->ns_rdataset) { dns_rdataset_t *gluerdataset = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; @@ -6715,20 +6729,26 @@ cache_delegns(respctx_t *rctx) { INSIST(rdata.type == dns_rdatatype_ns); dns_rdata_tostruct(&rdata, &ns, NULL); - result = dns_message_findname( - rctx->query->rmessage, DNS_SECTION_ADDITIONAL, &ns.name, - dns_rdatatype_a, 0, NULL, &gluerdataset); - if (result == ISC_R_SUCCESS) { - cache_delegglue(delegset, deleg, &ttl, gluerdataset); - gluerdataset = NULL; - } + if (labels > 1 && dns_name_issubdomain(&ns.name, parent)) { + result = dns_message_findname(rctx->query->rmessage, + DNS_SECTION_ADDITIONAL, + &ns.name, dns_rdatatype_a, + 0, NULL, &gluerdataset); + if (result == ISC_R_SUCCESS) { + cache_delegglue(delegset, deleg, &ttl, + gluerdataset); + gluerdataset = NULL; + } - result = dns_message_findname( - rctx->query->rmessage, DNS_SECTION_ADDITIONAL, &ns.name, - dns_rdatatype_aaaa, 0, NULL, &gluerdataset); - if (result == ISC_R_SUCCESS) { - cache_delegglue6(delegset, deleg, &ttl, gluerdataset); - gluerdataset = NULL; + result = dns_message_findname( + rctx->query->rmessage, DNS_SECTION_ADDITIONAL, + &ns.name, dns_rdatatype_aaaa, 0, NULL, + &gluerdataset); + if (result == ISC_R_SUCCESS) { + cache_delegglue6(delegset, deleg, &ttl, + gluerdataset); + gluerdataset = NULL; + } } if (ISC_LIST_EMPTY(deleg->addresses)) {