]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
findzonecut: helper function for zone lookup
authorColin Vidal <colin@isc.org>
Tue, 16 Dec 2025 13:26:11 +0000 (14:26 +0100)
committerColin Vidal <colin@isc.org>
Thu, 8 Jan 2026 19:26:32 +0000 (20:26 +0100)
Move the zone lookup code into a separate helper function.

The main extra change here is the return codes. This helper function can
return 3 (and only those 3) values:

- ISC_R_SUCCESS: a delegation is found
- DNS_R_NXDOMAIN: no zone matches the qname
- ISC_R_NOTFOUND: a zone is found, but no delegation in the zone (this
  can be either because there is simply no delegation, or for other
  reasons, like, the zone DB is not loaded yet).

This enables the caller to make decisions about whether to attempt a
cache and/or hints lookup or not.

lib/dns/view.c

index 276acd3c083ced9bff5e0367325e9595bd57d4b6..c6deb0696a2c0f2d9254dc808e131899060c8092 100644 (file)
@@ -983,6 +983,77 @@ dns_view_simplefind(dns_view_t *view, const dns_name_t *name,
        return result;
 }
 
+static isc_result_t
+findzonecut_zone(dns_view_t *view, const dns_name_t *name, dns_name_t *fname,
+                dns_name_t *dcname, isc_stdtime_t now, unsigned int options,
+                dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
+       dns_db_t *db = NULL;
+       dns_zone_t *zone = NULL;
+       unsigned int ztoptions = DNS_ZTFIND_MIRROR;
+       isc_result_t result;
+
+       if ((options & DNS_DBFIND_NOEXACT) != 0) {
+               ztoptions |= DNS_ZTFIND_NOEXACT;
+       }
+
+       result = dns_view_findzone(view, name, ztoptions, &zone);
+       if (result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH) {
+               CLEANUP(DNS_R_NXDOMAIN);
+       }
+
+       result = dns_zone_getdb(zone, &db);
+       if (result != ISC_R_SUCCESS) {
+               /*
+                * The zone exists, but there is no DB (likely not loaded yet),
+                * as for the case below (no delegation), ISC_R_NOTFOUND is used
+                * to differentiate from the case where there is no zone at all,
+                * so the caller won't attempt to hit the cache or hints.
+                */
+               CLEANUP(ISC_R_NOTFOUND);
+       }
+
+       result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options, now,
+                            NULL, fname, rdataset, sigrdataset);
+       if (result != DNS_R_DELEGATION && result != ISC_R_SUCCESS) {
+               /*
+                * The zone exists, but there is no delegation. Using
+                * ISC_R_NOTFOUND enable to differentiate from the case where
+                * there is no zone at all.
+                */
+               CLEANUP(ISC_R_NOTFOUND);
+       }
+
+       /*
+        * Tag static stub NS RRset so that when we look for
+        * addresses we use the configured server addresses.
+        */
+       if (dns_zone_gettype(zone) == dns_zone_staticstub) {
+               rdataset->attributes.staticstub = true;
+       }
+
+       if (dcname != NULL) {
+               dns_name_copy(fname, dcname);
+       }
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       if (result != ISC_R_SUCCESS) {
+               dns_rdataset_cleanup(rdataset);
+               dns_rdataset_cleanup(sigrdataset);
+       }
+
+       if (db != NULL) {
+               dns_db_detach(&db);
+       }
+
+       if (zone != NULL) {
+               dns_zone_detach(&zone);
+       }
+
+       return result;
+}
+
 static isc_result_t
 findzonecut_cache(dns_view_t *view, const dns_name_t *name, dns_name_t *fname,
                  dns_name_t *dcname, isc_stdtime_t now, unsigned int options,
@@ -1104,22 +1175,12 @@ db_find:
         * Look for the zonecut.
         */
        if (!is_cache) {
-               result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options,
-                                    now, NULL, fname, rdataset, sigrdataset);
-               if (result == DNS_R_DELEGATION) {
-                       result = ISC_R_SUCCESS;
-               } else if (result != ISC_R_SUCCESS) {
+               result = findzonecut_zone(view, name, fname, NULL, now, options,
+                                         rdataset, sigrdataset);
+               if (result != ISC_R_SUCCESS) {
                        goto cleanup;
                }
 
-               /*
-                * Tag static stub NS RRset so that when we look for
-                * addresses we use the configured server addresses.
-                */
-               if (dns_zone_gettype(zone) == dns_zone_staticstub) {
-                       rdataset->attributes.staticstub = true;
-               }
-
                if (use_cache && view->cachedb != NULL && db != view->hints) {
                        /*
                         * We found an answer, but the cache may be better.