]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Do not add glues from different parent in delegdb
authorColin Vidal <colin@isc.org>
Fri, 17 Apr 2026 11:09:56 +0000 (13:09 +0200)
committerColin Vidal <colin@isc.org>
Tue, 28 Apr 2026 18:17:39 +0000 (19:17 +0100)
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.

lib/dns/resolver.c

index 3e5018f241f4e1734d34987abfec8c24360693d5..19c4c29f0d044cdb08386f5a7749ae8d7e812695 100644 (file)
@@ -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)) {