]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Use delegation DB for bestzonecut lookups
authorColin Vidal <colin@isc.org>
Mon, 30 Mar 2026 09:31:47 +0000 (11:31 +0200)
committerColin Vidal <colin@isc.org>
Mon, 30 Mar 2026 18:41:13 +0000 (20:41 +0200)
Function `dns_view_bestzonecut()` now uses the delegation DB instead of
the main cache when looking up at the cache.

As a result, replace `dns_rdataset_t` (representing an NS RRset) with
`dns_delegset_t` in `dns_view_bestzonecut()` and
`dns_resolver_createfetch()` APIs. The resolver and query processing now
use the delegation DB instead of the cache for zonecut lookups.

In the case of the delegation lives in the local database, the locally
found `rdataset` is internally converted into a `dns_delegset_t` object.
From caller POV, it doesn't change anything: a delegation set is a
read-only object which can be used as long as needed and must be
detached one it's done with it.

bin/named/server.c
lib/dns/adb.c
lib/dns/include/dns/resolver.h
lib/dns/include/dns/view.h
lib/dns/resolver.c
lib/dns/view.c
lib/ns/include/ns/query.h
lib/ns/query.c

index 037a67f0594e1161ff12e82a0a1561ef142b48ae..2dddcc96446d866edd28c91f0d51be363b3ac077 100644 (file)
@@ -6564,7 +6564,7 @@ tat_send(void *arg) {
        char namebuf[DNS_NAME_FORMATSIZE];
        dns_fixedname_t fdomain;
        dns_name_t *domain = NULL;
-       dns_rdataset_t nameservers;
+       dns_delegset_t *delegset = NULL;
        isc_result_t result;
        dns_name_t *keyname = NULL;
        dns_name_t *tatname = NULL;
@@ -6596,25 +6596,23 @@ tat_send(void *arg) {
         * to.
         *
         * After the dns_view_findzonecut() call, 'domain' will hold the
-        * deepest zone cut we can find for 'keyname' while 'nameservers' will
-        * hold the NS RRset at that zone cut.
+        * deepest zone cut we can find for 'keyname' while 'delegset' will
+        * hold the NS names at that zone cut.
         */
        domain = dns_fixedname_initname(&fdomain);
-       dns_rdataset_init(&nameservers);
        result = dns_view_bestzonecut(tat->view, keyname, domain, NULL, 0, 0,
-                                     true, true, &nameservers);
+                                     true, true, &delegset);
        if (result == ISC_R_SUCCESS) {
                result = dns_resolver_createfetch(
                        tat->view->resolver, tatname, dns_rdatatype_null,
-                       domain, &nameservers, NULL, NULL, 0, 0, 0, NULL, NULL,
-                       NULL, tat->loop, tat_done, tat, NULL, &tat->rdataset,
+                       domain, delegset, NULL, NULL, 0, 0, 0, NULL, NULL, NULL,
+                       tat->loop, tat_done, tat, NULL, &tat->rdataset,
                        &tat->sigrdataset, &tat->fetch);
 
                /*
-                * dns_resolver_createfetch() will create its own copy of
-                * nameservers.
+                * dns_resolver_createfetch() will internally attach delegset.
                 */
-               dns_rdataset_cleanup(&nameservers);
+               dns_delegset_detach(&delegset);
        }
 
        /*
index e9b374f2b4333b146d22e39242709afa852a12f6..db984019e8ea6df171ebaf0a13c0be5967aeb934 100644 (file)
@@ -2741,8 +2741,7 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone, bool no_validation,
        dns_adb_t *adb = NULL;
        dns_fixedname_t fixed;
        dns_name_t *name = NULL;
-       dns_rdataset_t rdataset;
-       dns_rdataset_t *nameservers = NULL;
+       dns_delegset_t *delegset = NULL;
        unsigned int options = no_validation ? DNS_FETCHOPT_NOVALIDATE : 0;
 
        REQUIRE(DNS_ADBNAME_VALID(adbname));
@@ -2756,15 +2755,12 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone, bool no_validation,
 
        adbname->fetch_err = FIND_ERR_NOTFOUND;
 
-       dns_rdataset_init(&rdataset);
-
        if (start_at_zone) {
                DP(ENTER_LEVEL, "fetch_name: starting at zone for name %p",
                   adbname);
                name = dns_fixedname_initname(&fixed);
                CHECK(dns_view_bestzonecut(adb->view, adbname->name, name, NULL,
-                                          0, 0, true, false, &rdataset));
-               nameservers = &rdataset;
+                                          0, 0, true, false, &delegset));
                options |= DNS_FETCHOPT_UNSHARED;
        } else if (adb->view->qminimization) {
                options |= DNS_FETCHOPT_QMINIMIZE | DNS_FETCHOPT_QMIN_SKIP_IP6A;
@@ -2785,7 +2781,7 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone, bool no_validation,
         */
        dns_adbname_ref(adbname);
        result = dns_resolver_createfetch(
-               adb->res, adbname->name, type, name, nameservers, NULL, NULL, 0,
+               adb->res, adbname->name, type, name, delegset, NULL, NULL, 0,
                options, depth, qc, gqc, parent, isc_loop(), fetch_callback,
                adbname, NULL, &fetch->rdataset, NULL, &fetch->fetch);
        if (result != ISC_R_SUCCESS) {
@@ -2808,7 +2804,10 @@ cleanup:
        if (fetch != NULL) {
                free_adbfetch(adb, &fetch);
        }
-       dns_rdataset_cleanup(&rdataset);
+
+       if (delegset != NULL) {
+               dns_delegset_detach(&delegset);
+       }
 
        return result;
 }
index fc73fca716e0ea9cc7d159aea1073b20c8a75af8..95977c66d6309bd207d3ab43d3b5a07b71759601 100644 (file)
@@ -262,8 +262,7 @@ typedef struct fetchctx fetchctx_t;
 isc_result_t
 dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
                         dns_rdatatype_t type, const dns_name_t *domain,
-                        dns_rdataset_t       *nameservers,
-                        dns_forwarders_t     *forwarders,
+                        dns_delegset_t *delegset, dns_forwarders_t *forwarders,
                         const isc_sockaddr_t *client, dns_messageid_t id,
                         unsigned int options, unsigned int depth,
                         isc_counter_t *qc, isc_counter_t *gqc,
index b0d98499ae55a37351c8a29f93d51211c796606d..740ed2496c5e0d51e3e3b0238b1120999ca7bf09 100644 (file)
@@ -694,7 +694,7 @@ isc_result_t
 dns_view_bestzonecut(dns_view_t *view, const dns_name_t *name,
                     dns_name_t *fname, dns_name_t *dcname, isc_stdtime_t now,
                     unsigned int options, bool use_hints, bool use_cache,
-                    dns_rdataset_t *rdataset);
+                    dns_delegset_t **delegsetp);
 /*%<
  * Find the best known zonecut containing 'name'.
  *
@@ -722,15 +722,16 @@ dns_view_bestzonecut(dns_view_t *view, const dns_name_t *name,
  *
  *\li  'name' is valid name.
  *
- *\li  'rdataset' is a valid, disassociated rdataset.
- *
- *\li  'sigrdataset' is NULL, or is a valid, disassociated rdataset.
+ *\li  'delegsetp' is a valid pointer to a NULL `dns_delegset_t` pointer. It
+ *      can also be NULL if the caller doesn't need the delegation data (but
+ *      just the zonecut name).
+ *      Note: if a delegation is found, `*delegsetp` is not NULL and must be
+ *      detached from the caller once it doesn't need it anymore.
  *
  * Returns:
  *
  *\li  #ISC_R_SUCCESS  If a delegation is found;
- *\li   #DNS_R_NXDOMAIN        If no delegation is found; 'rdataset' and 'sigrdataset'
- *                      are disassociated.
+ *\li   #DNS_R_NXDOMAIN        If no delegation is found; '*delegsetp' remains NULL.
  */
 
 isc_result_t
index c5f98ad3ef28b4db423e8eded4faa96cb9111958..fdba143019130d861cfcc5aa7cc7e4ba433bfb26 100644 (file)
@@ -359,7 +359,7 @@ struct fetchctx {
        /*% Locked by loop event serialization. */
        dns_fixedname_t dfname;
        dns_name_t *domain;
-       dns_rdataset_t nameservers;
+       dns_delegset_t *delegset;
        atomic_uint_fast32_t attributes;
        isc_timer_t *timer;
        isc_time_t expires;
@@ -650,9 +650,8 @@ enum {
 #define BADCOOKIE(a)   (((a)->flags & FCTX_ADDRINFO_BADCOOKIE) != 0)
 #define ISDUALSTACK(a) (((a)->flags & FCTX_ADDRINFO_DUALSTACK) != 0)
 
-#define NXDOMAIN(r)   (((r)->attributes.nxdomain))
-#define NEGATIVE(r)   (((r)->attributes.negative))
-#define STATICSTUB(r) (((r)->attributes.staticstub))
+#define NXDOMAIN(r) (((r)->attributes.nxdomain))
+#define NEGATIVE(r) (((r)->attributes.negative))
 
 #ifdef ENABLE_AFL
 bool dns_fuzzing_resolver = false;
@@ -839,7 +838,7 @@ resume_qmin(void *arg);
 static isc_result_t
 get_attached_fctx(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
                  dns_rdatatype_t type, const dns_name_t *domain,
-                 dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
+                 dns_delegset_t *delegset, const isc_sockaddr_t *client,
                  unsigned int options, unsigned int depth, isc_counter_t *qc,
                  isc_counter_t *gqc, fetchctx_t *parent, fetchctx_t **fctxp,
                  bool *new_fctx);
@@ -3659,20 +3658,22 @@ static isc_result_t
 fctx_getaddresses_nameservers(fetchctx_t *fctx, isc_stdtime_t now,
                              unsigned int stdoptions, size_t fetches_allowed,
                              bool *need_alternatep, bool *all_spilledp) {
-       dns_rdata_ns_t ns;
        bool have_address = false;
        unsigned int ns_processed = 0;
        uint32_t ns_processing_limit = fctx->res->view->max_delegation_servers;
-       static thread_local dns_rdata_t nameservers_s[MAX_DELEGATION_SERVERS];
-       static thread_local dns_rdata_t *nameservers[MAX_DELEGATION_SERVERS];
+       dns_namelist_t *availablens = NULL;
+       static thread_local dns_name_t *nameservers[MAX_DELEGATION_SERVERS];
 
-       DNS_RDATASET_FOREACH(&fctx->nameservers) {
-               dns_rdata_t *rdata = nameservers[ns_processed] =
-                       &nameservers_s[ns_processed];
-
-               dns_rdata_init(rdata);
+       /*
+        * For now, only NS-based deleg is supported, and this can be only in a
+        * single list element.
+        */
+       INSIST(ISC_LIST_HEAD(fctx->delegset->deleg) ==
+              ISC_LIST_TAIL(fctx->delegset->deleg));
+       availablens = &ISC_LIST_HEAD(fctx->delegset->deleg)->nameserver;
 
-               dns_rdataset_current(&fctx->nameservers, rdata);
+       ISC_LIST_FOREACH(*availablens, ns, link) {
+               nameservers[ns_processed] = ns;
 
                if (++ns_processed >= ns_processing_limit) {
                        break;
@@ -3694,22 +3695,13 @@ fctx_getaddresses_nameservers(fetchctx_t *fctx, isc_stdtime_t now,
        }
 
        for (size_t i = 0; i < ns_processed; i++) {
-               isc_result_t result = ISC_R_SUCCESS;
                bool overquota = false;
                unsigned int static_stub = 0;
                unsigned int no_fetch = 0;
-               dns_rdata_t *rdata = nameservers[i];
-
-               /*
-                * Extract the name from the NS record.
-                */
-               result = dns_rdata_tostruct(rdata, &ns, NULL);
-               if (result != ISC_R_SUCCESS) {
-                       continue;
-               }
+               dns_name_t *ns = nameservers[i];
 
-               if (STATICSTUB(&fctx->nameservers) &&
-                   dns_name_equal(&ns.name, fctx->domain))
+               if (fctx->delegset->staticstub &&
+                   dns_name_equal(ns, fctx->domain))
                {
                        static_stub = DNS_ADBFIND_STATICSTUB;
                }
@@ -3722,14 +3714,12 @@ fctx_getaddresses_nameservers(fetchctx_t *fctx, isc_stdtime_t now,
                        no_fetch = DNS_ADBFIND_NOFETCH;
                }
 
-               findname(fctx, &ns.name, 0, stdoptions | static_stub | no_fetch,
-                        0, now, &overquota, need_alternatep, &have_address);
+               findname(fctx, ns, 0, stdoptions | static_stub | no_fetch, 0,
+                        now, &overquota, need_alternatep, &have_address);
 
                if (!overquota) {
                        *all_spilledp = false;
                }
-
-               dns_rdata_freestruct(&ns);
        }
 
        if (fctx->pending_running == 0 && !have_address) {
@@ -4319,7 +4309,7 @@ fctx_try(fetchctx_t *fctx, bool retrying) {
                fetchctx_ref(fctx);
                result = dns_resolver_createfetch(
                        fctx->res, fctx->qmin.name, fctx->qmintype,
-                       fctx->domain, &fctx->nameservers, NULL, NULL, 0,
+                       fctx->domain, fctx->delegset, NULL, NULL, 0,
                        options | DNS_FETCHOPT_QMINFETCH, 0, fctx->qc,
                        fctx->gqc, fctx, fctx->loop, resume_qmin, fctx,
                        &fctx->edectx, &fctx->qmin.rdataset,
@@ -4532,14 +4522,14 @@ resume_qmin(void *arg) {
        }
 
        clear_resp(&resp);
-       dns_rdataset_cleanup(&fctx->nameservers);
+       dns_delegset_detach(&fctx->delegset);
 
        if (dns_rdatatype_atparent(fctx->type)) {
                findoptions |= DNS_DBFIND_NOEXACT;
        }
        result = dns_view_bestzonecut(res->view, fctx->name, fname, dcname,
                                      fctx->now, findoptions, true, true,
-                                     &fctx->nameservers);
+                                     &fctx->delegset);
        FCTXTRACEN("resume_qmin findzonecut", fname, result);
 
        if (result != ISC_R_SUCCESS) {
@@ -4552,7 +4542,7 @@ resume_qmin(void *arg) {
        CHECK(fcount_incr(fctx, false));
 
        dns_name_copy(dcname, fctx->qmin.dcname);
-       fctx->ns_ttl = fctx->nameservers.ttl;
+       fctx->ns_ttl = fctx->delegset->expires - fctx->now;
        fctx->ns_ttl_ok = true;
 
        fctx_minimize_qname(fctx);
@@ -4649,7 +4639,9 @@ fctx__destroy(fetchctx_t *fctx, const char *func, const char *file,
        }
        fcount_decr(fctx);
        dns_message_detach(&fctx->qmessage);
-       dns_rdataset_cleanup(&fctx->nameservers);
+       if (fctx->delegset != NULL) {
+               dns_delegset_detach(&fctx->delegset);
+       }
        dns_db_detach(&fctx->cache);
        dns_adb_detach(&fctx->adb);
        dns_dispatchmgr_detach(&fctx->dispatchmgr);
@@ -4800,7 +4792,7 @@ log_ns_ttl(fetchctx_t *fctx, const char *where) {
 static isc_result_t
 fctx__create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
             dns_rdatatype_t type, const dns_name_t *domain,
-            dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
+            dns_delegset_t *delegset, const isc_sockaddr_t *client,
             unsigned int options, unsigned int depth, isc_counter_t *qc,
             isc_counter_t *gqc, fetchctx_t *parent, fetchctx_t **fctxp,
             const char *func, const char *file, const unsigned int line) {
@@ -4840,7 +4832,6 @@ fctx__create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
                              .bad = ISC_LIST_INITIALIZER,
                              .edns = ISC_LIST_INITIALIZER,
                              .validators = ISC_LIST_INITIALIZER,
-                             .nameservers = DNS_RDATASET_INIT,
                              .nsrrset = DNS_RDATASET_INIT,
                              .resp_result = DNS_R_SERVFAIL,
                              .qmin.rdataset = DNS_RDATASET_INIT,
@@ -4977,21 +4968,21 @@ fctx__create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
                        result = dns_view_bestzonecut(
                                res->view, name, fctx->fwdname, dcname,
                                fctx->now, findoptions, true, true,
-                               &fctx->nameservers);
+                               &fctx->delegset);
                        if (result != ISC_R_SUCCESS) {
                                goto cleanup_nameservers;
                        }
 
                        dns_name_copy(fctx->fwdname, fctx->domain);
                        dns_name_copy(dcname, fctx->qmin.dcname);
-                       fctx->ns_ttl = fctx->nameservers.ttl;
+                       fctx->ns_ttl = fctx->delegset->expires - fctx->now;
                        fctx->ns_ttl_ok = true;
                }
        } else {
-               dns_rdataset_clone(nameservers, &fctx->nameservers);
+               dns_delegset_attach(delegset, &fctx->delegset);
                dns_name_copy(domain, fctx->domain);
                dns_name_copy(domain, fctx->qmin.dcname);
-               fctx->ns_ttl = fctx->nameservers.ttl;
+               fctx->ns_ttl = fctx->delegset->expires - fctx->now;
                fctx->ns_ttl_ok = true;
        }
 
@@ -5106,7 +5097,9 @@ cleanup_fcount:
        fcount_decr(fctx);
 
 cleanup_nameservers:
-       dns_rdataset_cleanup(&fctx->nameservers);
+       if (fctx->delegset != NULL) {
+               dns_delegset_detach(&fctx->delegset);
+       }
        isc_mem_free(fctx->mctx, fctx->info);
        if (fctx->nfails != NULL) {
                isc_counter_detach(&fctx->nfails);
@@ -6950,8 +6943,8 @@ resume_dslookup(void *arg) {
        isc_loop_t *loop = resp->loop;
        isc_result_t result;
        dns_resolver_t *res = NULL;
-       dns_rdataset_t *frdataset = NULL, *nsrdataset = NULL;
-       dns_rdataset_t nameservers;
+       dns_rdataset_t *frdataset = NULL;
+       dns_delegset_t *delegset = NULL;
        dns_fixedname_t fixed;
        dns_name_t *domain = NULL;
        unsigned int n;
@@ -6973,9 +6966,8 @@ resume_dslookup(void *arg) {
        }
 
        /* Preserve data from resp before freeing it. */
-       frdataset = resp->rdataset; /* a.k.a. fctx->nsrrset */
+       frdataset = resp->rdataset;
        result = resp->result;
-
        dns_resolver_freefresp(&resp);
 
        LOCK(&fctx->lock);
@@ -6993,15 +6985,21 @@ resume_dslookup(void *arg) {
        case ISC_R_SUCCESS:
                FCTXTRACE("resuming DS lookup");
 
-               dns_rdataset_cleanup(&fctx->nameservers);
-               dns_rdataset_clone(frdataset, &fctx->nameservers);
-
-               /*
-                * Disassociate now the NS's are saved.
-                */
+               dns_delegset_fromnsrdataset(frdataset, &delegset);
                dns_rdataset_cleanup(frdataset);
 
-               fctx->ns_ttl = fctx->nameservers.ttl;
+               if (delegset == NULL) {
+                       result = DNS_R_SERVFAIL;
+                       break;
+               }
+
+               if (fctx->delegset != NULL) {
+                       dns_delegset_detach(&fctx->delegset);
+               }
+
+               dns_delegset_attach(delegset, &fctx->delegset);
+
+               fctx->ns_ttl = fctx->delegset->expires - fctx->now;
                fctx->ns_ttl_ok = true;
                log_ns_ttl(fctx, "resume_dslookup");
 
@@ -7015,9 +7013,6 @@ resume_dslookup(void *arg) {
 
        case ISC_R_SHUTTINGDOWN:
        case ISC_R_CANCELED:
-               /* Don't try anymore. */
-               /* Can't be done in cleanup. */
-               dns_rdataset_cleanup(frdataset);
                goto cleanup;
 
        default:
@@ -7037,11 +7032,9 @@ resume_dslookup(void *arg) {
                }
 
                /* Get nameservers from fetch before we destroy it. */
-               dns_rdataset_init(&nameservers);
-               if (dns_rdataset_isassociated(&fetch->private->nameservers)) {
-                       dns_rdataset_clone(&fetch->private->nameservers,
-                                          &nameservers);
-                       nsrdataset = &nameservers;
+               if (fetch->private->delegset != NULL) {
+                       dns_delegset_attach(fetch->private->delegset,
+                                           &delegset);
 
                        /* Get domain from fetch before we destroy it. */
                        domain = dns_fixedname_initname(&fixed);
@@ -7055,7 +7048,7 @@ resume_dslookup(void *arg) {
 
                fetchctx_ref(fctx);
                result = dns_resolver_createfetch(
-                       res, fctx->nsname, dns_rdatatype_ns, domain, nsrdataset,
+                       res, fctx->nsname, dns_rdatatype_ns, domain, delegset,
                        NULL, NULL, 0, fctx->options, 0, fctx->qc, fctx->gqc,
                        fctx, loop, resume_dslookup, fctx, &fctx->edectx,
                        &fctx->nsrrset, NULL, &fctx->nsfetch);
@@ -7065,11 +7058,12 @@ resume_dslookup(void *arg) {
                                result = DNS_R_SERVFAIL;
                        }
                }
-
-               dns_rdataset_cleanup(&nameservers);
        }
 
 cleanup:
+       if (delegset != NULL) {
+               dns_delegset_detach(&delegset);
+       }
        dns_resolver_destroyfetch(&fetch);
 
        if (result != ISC_R_SUCCESS) {
@@ -9182,7 +9176,7 @@ rctx_referral(respctx_t *rctx) {
        INSIST(dns_name_countlabels(fctx->domain) > 0);
        fcount_decr(fctx);
 
-       dns_rdataset_cleanup(&fctx->nameservers);
+       dns_delegset_detach(&fctx->delegset);
 
        dns_name_copy(rctx->ns_name, fctx->domain);
 
@@ -9308,7 +9302,7 @@ rctx_nextserver(respctx_t *rctx, dns_message_t *message,
                }
                result = dns_view_bestzonecut(fctx->res->view, name, fname,
                                              dcname, fctx->now, findoptions,
-                                             true, true, &fctx->nameservers);
+                                             true, true, &fctx->delegset);
                if (result != ISC_R_SUCCESS) {
                        FCTXTRACE("couldn't find a zonecut");
                        fctx_failure_detach(&rctx->fctx, DNS_R_SERVFAIL);
@@ -9334,7 +9328,7 @@ rctx_nextserver(respctx_t *rctx, dns_message_t *message,
                        fctx_failure_detach(&rctx->fctx, DNS_R_SERVFAIL);
                        return;
                }
-               fctx->ns_ttl = fctx->nameservers.ttl;
+               fctx->ns_ttl = fctx->delegset->expires - fctx->now;
                fctx->ns_ttl_ok = true;
                fctx_cancelqueries(fctx, true, false);
                fctx_cleanup(fctx);
@@ -10191,7 +10185,7 @@ fctx_minimize_qname(fetchctx_t *fctx) {
 static isc_result_t
 get_attached_fctx(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
                  dns_rdatatype_t type, const dns_name_t *domain,
-                 dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
+                 dns_delegset_t *delegset, const isc_sockaddr_t *client,
                  unsigned int options, unsigned int depth, isc_counter_t *qc,
                  isc_counter_t *gqc, fetchctx_t *parent, fetchctx_t **fctxp,
                  bool *new_fctx) {
@@ -10214,7 +10208,7 @@ get_attached_fctx(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
 
        if (fctx == NULL) {
        create:
-               result = fctx_create(res, loop, name, type, domain, nameservers,
+               result = fctx_create(res, loop, name, type, domain, delegset,
                                     client, options, depth, qc, gqc, parent,
                                     &fctx);
                if (result != ISC_R_SUCCESS) {
@@ -10315,8 +10309,7 @@ waiting_for_fetch(fetchctx_t *fctx, const dns_name_t *name,
 isc_result_t
 dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
                         dns_rdatatype_t type, const dns_name_t *domain,
-                        dns_rdataset_t *nameservers,
-                        dns_forwarders_t *forwarders,
+                        dns_delegset_t *delegset, dns_forwarders_t *forwarders,
                         const isc_sockaddr_t *client, dns_messageid_t id,
                         unsigned int options, unsigned int depth,
                         isc_counter_t *qc, isc_counter_t *gqc,
@@ -10339,10 +10332,9 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
        REQUIRE(res->frozen);
        /* XXXRTH  Check for meta type */
        if (domain != NULL) {
-               REQUIRE(DNS_RDATASET_VALID(nameservers));
-               REQUIRE(nameservers->type == dns_rdatatype_ns);
+               REQUIRE(DNS_DELEGSET_VALID(delegset));
        } else {
-               REQUIRE(nameservers == NULL);
+               REQUIRE(delegset == NULL);
        }
        REQUIRE(forwarders == NULL);
        REQUIRE(!dns_rdataset_isassociated(rdataset));
@@ -10401,8 +10393,8 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
                UNLOCK(&res->lock);
 
                result = get_attached_fctx(res, loop, name, type, domain,
-                                          nameservers, client, options, depth,
-                                          qc, gqc, parent, &fctx, &new_fctx);
+                                          delegset, client, options, depth, qc,
+                                          gqc, parent, &fctx, &new_fctx);
                if (result != ISC_R_SUCCESS) {
                        goto fail;
                }
@@ -10435,7 +10427,7 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
                        }
                }
        } else {
-               result = fctx_create(res, loop, name, type, domain, nameservers,
+               result = fctx_create(res, loop, name, type, domain, delegset,
                                     client, options, depth, qc, gqc, parent,
                                     &fctx);
                if (result != ISC_R_SUCCESS) {
index 042339b2cdb8ad108b0026de765fe0f3f5e5e90a..9f18357a244e6e67c295ded073982e69df06341a 100644 (file)
@@ -988,7 +988,7 @@ dns_view_simplefind(dns_view_t *view, const dns_name_t *name,
 }
 
 static isc_result_t
-findzonecut_zone(dns_view_t *view, const dns_name_t *name, dns_name_t *fname,
+bestzonecut_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_db_t *db = NULL;
@@ -1061,15 +1061,14 @@ cleanup:
 }
 
 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,
-                 dns_rdataset_t *rdataset) {
+bestzonecut_delegdb(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_delegset_t **delegsetp) {
        isc_result_t result = DNS_R_NXDOMAIN;
 
-       if (view->cachedb != NULL) {
-               result = dns_db_findzonecut(view->cachedb, name, options, now,
-                                           NULL, fname, dcname, rdataset,
-                                           NULL);
+       if (view->deleg != NULL) {
+               result = dns_delegdb_lookup(view->deleg, name, now, options,
+                                           fname, dcname, delegsetp);
        }
 
        /*
@@ -1078,26 +1077,26 @@ findzonecut_cache(dns_view_t *view, const dns_name_t *name, dns_name_t *fname,
         * keep DNS_R_NXDOMAIN, so the hints can be checked.
         */
        if (result != ISC_R_SUCCESS) {
-               dns_rdataset_cleanup(rdataset);
                result = DNS_R_NXDOMAIN;
        }
-
        return result;
 }
 
 static void
-findzonecut_zoneorcache(dns_view_t *view, const dns_name_t *name,
+bestzonecut_zoneorcache(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 *rdataset, dns_delegset_t **delegsetp) {
        isc_result_t result;
-       dns_rdataset_t crdataset = DNS_RDATASET_INIT;
        dns_fixedname_t f, dc;
        dns_name_t *cfname = dns_fixedname_initname(&f);
        dns_name_t *cdcname = dns_fixedname_initname(&dc);
 
-       CHECK(findzonecut_cache(view, name, cfname, cdcname, now, options,
-                               &crdataset));
+       result = bestzonecut_delegdb(view, name, cfname, cdcname, now, options,
+                                    delegsetp);
+       if (result != ISC_R_SUCCESS) {
+               return;
+       }
 
        bool cacheclosest = dns_name_issubdomain(cfname, fname);
        bool staticstub = rdataset->attributes.staticstub &&
@@ -1105,20 +1104,18 @@ findzonecut_zoneorcache(dns_view_t *view, const dns_name_t *name,
 
        if (cacheclosest && !staticstub) {
                dns_rdataset_cleanup(rdataset);
-               dns_rdataset_clone(&crdataset, rdataset);
 
                dns_name_copy(cfname, fname);
                if (dcname != NULL) {
                        dns_name_copy(cdcname, dcname);
                }
+       } else {
+               dns_delegset_detach(delegsetp);
        }
-
-cleanup:
-       dns_rdataset_cleanup(&crdataset);
 }
 
 static isc_result_t
-findzonecut_hints(dns_view_t *view, dns_name_t *fname, dns_name_t *dcname,
+bestzonecut_hints(dns_view_t *view, dns_name_t *fname, dns_name_t *dcname,
                  isc_stdtime_t now, dns_rdataset_t *rdataset) {
        isc_result_t result = ISC_R_NOTFOUND;
 
@@ -1141,13 +1138,20 @@ isc_result_t
 dns_view_bestzonecut(dns_view_t *view, const dns_name_t *name,
                     dns_name_t *fname, dns_name_t *dcname, isc_stdtime_t now,
                     unsigned int options, bool usehints, bool usecache,
-                    dns_rdataset_t *rdataset) {
+                    dns_delegset_t **delegsetp) {
        isc_result_t result;
+       dns_rdataset_t rdatasetdata = DNS_RDATASET_INIT;
+       dns_rdataset_t *rdataset = NULL;
 
        REQUIRE(DNS_VIEW_VALID(view));
        REQUIRE(view->frozen);
 
-       result = findzonecut_zone(view, name, fname, dcname, now, options,
+       if (delegsetp != NULL) {
+               REQUIRE(*delegsetp == NULL);
+               rdataset = &rdatasetdata;
+       }
+
+       result = bestzonecut_zone(view, name, fname, dcname, now, options,
                                  rdataset);
 
        if (result == DNS_R_NXDOMAIN && usecache) {
@@ -1155,29 +1159,31 @@ dns_view_bestzonecut(dns_view_t *view, const dns_name_t *name,
                 * No local zone matches `name`, but the cache might have a
                 * delegation.
                 */
-               result = findzonecut_cache(view, name, fname, dcname, now,
-                                          options, rdataset);
+               result = bestzonecut_delegdb(view, name, fname, dcname, now,
+                                            options, delegsetp);
        } else if (result == ISC_R_SUCCESS && usecache) {
                /*
                 * A zone with a (possibly partial) delegation match but the
                 * cache can have a more precise delegation.
                 */
-               findzonecut_zoneorcache(view, name, fname, dcname, now, options,
-                                       rdataset);
+               bestzonecut_zoneorcache(view, name, fname, dcname, now, options,
+                                       rdataset, delegsetp);
        }
 
        /*
         * No local zone nor cache match. Last attempt with the hints.
         */
        if (result == DNS_R_NXDOMAIN && usehints) {
-               result = findzonecut_hints(view, fname, dcname, now, rdataset);
+               result = bestzonecut_hints(view, fname, dcname, now, rdataset);
        }
 
        if (result != ISC_R_SUCCESS) {
                result = DNS_R_NXDOMAIN;
-               dns_rdataset_cleanup(rdataset);
+       } else {
+               dns_delegset_fromrdataset(rdataset, delegsetp);
        }
 
+       dns_rdataset_cleanup(rdataset);
        return result;
 }
 
index 0b7196dd4dd4137544d4eae929b9138be67d5070..053ed69ee3b9bd818ae42c8319def0721a74075a 100644 (file)
@@ -260,8 +260,7 @@ ns_query_done(query_ctx_t *qctx);
 
 isc_result_t
 ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
-                dns_name_t *qdomain, dns_rdataset_t *nameservers,
-                bool resuming);
+                dns_name_t *qdomain, dns_delegset_t *delegset, bool resuming);
 /*%<
  * Prepare client for recursion, then create a resolver fetch, with
  * the event callback set to fetch_callback(). Afterward we terminate
index 1fa9598a71c4e5358ba06fb4d0dacff8d7bd31ad..4884d55d80cedd9ceb91ac2fe8ad1e9ac80abf6a 100644 (file)
@@ -6226,8 +6226,7 @@ release_recursionquota(ns_client_t *client) {
 
 isc_result_t
 ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
-                dns_name_t *qdomain, dns_rdataset_t *nameservers,
-                bool resuming) {
+                dns_name_t *qdomain, dns_delegset_t *delegset, bool resuming) {
        isc_result_t result;
        dns_rdataset_t *rdataset, *sigrdataset;
        isc_sockaddr_t *peeraddr = NULL;
@@ -6255,7 +6254,6 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
        /*
         * Invoke the resolver.
         */
-       REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);
        REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL);
 
        rdataset = ns_client_newrdataset(client);
@@ -6278,11 +6276,11 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
                            &HANDLE_RECTYPE_NORMAL(client));
        maybe_init_fetch_counter(client);
        result = dns_resolver_createfetch(
-               client->inner.view->resolver, qname, qtype, qdomain,
-               nameservers, NULL, peeraddr, client->message->id,
-               client->query.fetchoptions, 0, NULL, client->query.qc, NULL,
-               client->manager->loop, fetch_callback, client, &client->edectx,
-               rdataset, sigrdataset, &FETCH_RECTYPE_NORMAL(client));
+               client->inner.view->resolver, qname, qtype, qdomain, delegset,
+               NULL, peeraddr, client->message->id, client->query.fetchoptions,
+               0, NULL, client->query.qc, NULL, client->manager->loop,
+               fetch_callback, client, &client->edectx, rdataset, sigrdataset,
+               &FETCH_RECTYPE_NORMAL(client));
        if (result != ISC_R_SUCCESS) {
                release_recursionquota(client);
 
@@ -8659,9 +8657,15 @@ query_delegation_recurse(query_ctx_t *qctx) {
                /*
                 * Any other recursion.
                 */
+               dns_delegset_t *delegset = NULL;
+
+               dns_deleg_fromrdataset(qctx->rdataset, &delegset);
                result = ns_query_recurse(qctx->client, qctx->qtype, qname,
-                                         qctx->fname, qctx->rdataset,
+                                         qctx->fname, delegset,
                                          qctx->resuming);
+               if (delegset != NULL) {
+                       dns_delegset_detach(&delegset);
+               }
        }
 
        if (result == ISC_R_SUCCESS) {