From: Colin Vidal Date: Mon, 30 Mar 2026 09:31:47 +0000 (+0200) Subject: Use delegation DB for bestzonecut lookups X-Git-Tag: v9.21.21~4^2~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=de8bc44dc8f3260c80181a2d557ea07e98d2c2af;p=thirdparty%2Fbind9.git Use delegation DB for bestzonecut lookups 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. --- diff --git a/bin/named/server.c b/bin/named/server.c index 037a67f0594..2dddcc96446 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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); } /* diff --git a/lib/dns/adb.c b/lib/dns/adb.c index e9b374f2b43..db984019e8e 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -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; } diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index fc73fca716e..95977c66d63 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -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, diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index b0d98499ae5..740ed2496c5 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -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 diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index c5f98ad3ef2..fdba1430191 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -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) { diff --git a/lib/dns/view.c b/lib/dns/view.c index 042339b2cdb..9f18357a244 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -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; } diff --git a/lib/ns/include/ns/query.h b/lib/ns/include/ns/query.h index 0b7196dd4dd..053ed69ee3b 100644 --- a/lib/ns/include/ns/query.h +++ b/lib/ns/include/ns/query.h @@ -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 diff --git a/lib/ns/query.c b/lib/ns/query.c index 1fa9598a71c..4884d55d80c 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -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) {