From dea79e7053624ff2db6e24ea4bf4d32e04d6e08f Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Wed, 5 Apr 2023 23:08:12 -0700 Subject: [PATCH] use a qp-trie for the forwarders table Instead of an RBT for the forwarders table, use a QP trie. We now use reference counting for dns_forwarders_t. When a forwarders object is retrieved by dns_fwdtable_find(), it must now be explicitly detached by the caller afterward. QP tries require stored objects to include their names, so the the forwarders object now has that. This obviates the need to pass back a separate 'foundname' value from dns_fwdtable_find(). --- bin/named/server.c | 30 ++++-- lib/dns/forward.c | 175 ++++++++++++++++++++++------------ lib/dns/include/dns/forward.h | 37 +++++-- lib/dns/resolver.c | 73 +++++++------- lib/dns/view.c | 14 +-- 5 files changed, 202 insertions(+), 127 deletions(-) diff --git a/bin/named/server.c b/bin/named/server.c index 5d7e000396..667bca425b 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -2681,8 +2681,7 @@ catz_addmodzone_cb(void *arg) { dns_name_totext(name, true, &namebuf); isc_buffer_putuint8(&namebuf, 0); - result = dns_fwdtable_find(cz->view->fwdtable, name, NULL, - &dnsforwarders); + result = dns_fwdtable_find(cz->view->fwdtable, name, &dnsforwarders); if (result == ISC_R_SUCCESS && dnsforwarders->fwdpolicy == dns_fwdpolicy_only) { @@ -2858,6 +2857,9 @@ cleanup: if (zoneconf != NULL) { cfg_obj_destroy(cfg->add_parser, &zoneconf); } + if (dnsforwarders != NULL) { + dns_forwarders_detach(&dnsforwarders); + } dns_catz_entry_detach(cz->origin, &cz->entry); dns_catz_zone_detach(&cz->origin); dns_view_detach(&cz->view); @@ -5701,6 +5703,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, empty = empty_zones[++empty_zone]) { dns_forwarders_t *dnsforwarders = NULL; + dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; /* * Look for zone on drop list. @@ -5726,12 +5729,15 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, * If we would forward this name don't add a * empty zone for it. */ - result = dns_fwdtable_find(view->fwdtable, name, NULL, + result = dns_fwdtable_find(view->fwdtable, name, &dnsforwarders); - if ((result == ISC_R_SUCCESS || - result == DNS_R_PARTIALMATCH) && - dnsforwarders->fwdpolicy == dns_fwdpolicy_only) + if (result == ISC_R_SUCCESS || + result == DNS_R_PARTIALMATCH) { + fwdpolicy = dnsforwarders->fwdpolicy; + dns_forwarders_detach(&dnsforwarders); + } + if (fwdpolicy == dns_fwdpolicy_only) { continue; } @@ -5803,6 +5809,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, ipv4only_zone++) { dns_forwarders_t *dnsforwarders = NULL; + dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; CHECK(dns_name_fromstring( name, zones[ipv4only_zone].name, 0, NULL)); @@ -5817,12 +5824,15 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, /* * If we would forward this name don't add it. */ - result = dns_fwdtable_find(view->fwdtable, name, NULL, + result = dns_fwdtable_find(view->fwdtable, name, &dnsforwarders); - if ((result == ISC_R_SUCCESS || - result == DNS_R_PARTIALMATCH) && - dnsforwarders->fwdpolicy == dns_fwdpolicy_only) + if (result == ISC_R_SUCCESS || + result == DNS_R_PARTIALMATCH) { + fwdpolicy = dnsforwarders->fwdpolicy; + dns_forwarders_detach(&dnsforwarders); + } + if (fwdpolicy == dns_fwdpolicy_only) { continue; } diff --git a/lib/dns/forward.c b/lib/dns/forward.c index df377bc202..77efc595d6 100644 --- a/lib/dns/forward.c +++ b/lib/dns/forward.c @@ -16,70 +16,88 @@ #include #include #include -#include #include +#include #include #include -#include +#include #include +#include struct dns_fwdtable { /* Unlocked. */ unsigned int magic; isc_mem_t *mctx; - isc_rwlock_t rwlock; - /* Locked by lock. */ - dns_rbt_t *table; + dns_qpmulti_t *table; }; #define FWDTABLEMAGIC ISC_MAGIC('F', 'w', 'd', 'T') #define VALID_FWDTABLE(ft) ISC_MAGIC_VALID(ft, FWDTABLEMAGIC) static void -auto_detach(void *, void *); +qp_attach(void *uctx, void *pval, uint32_t ival); +static void +qp_detach(void *uctx, void *pval, uint32_t ival); +static size_t +qp_makekey(dns_qpkey_t key, void *uctx, void *pval, uint32_t ival); +static void +qp_triename(void *uctx, char *buf, size_t size); -isc_result_t -dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep) { - dns_fwdtable_t *fwdtable; - isc_result_t result; +static dns_qpmethods_t qpmethods = { + qp_attach, + qp_detach, + qp_makekey, + qp_triename, +}; + +void +dns_fwdtable_create(isc_mem_t *mctx, dns_view_t *view, + dns_fwdtable_t **fwdtablep) { + dns_fwdtable_t *fwdtable = NULL; REQUIRE(fwdtablep != NULL && *fwdtablep == NULL); fwdtable = isc_mem_get(mctx, sizeof(*fwdtable)); + *fwdtable = (dns_fwdtable_t){ .magic = FWDTABLEMAGIC }; - fwdtable->table = NULL; - result = dns_rbt_create(mctx, auto_detach, fwdtable, &fwdtable->table); - if (result != ISC_R_SUCCESS) { - goto cleanup_fwdtable; - } + dns_qpmulti_create(mctx, &qpmethods, view, &fwdtable->table); - isc_rwlock_init(&fwdtable->rwlock); - fwdtable->mctx = NULL; isc_mem_attach(mctx, &fwdtable->mctx); - fwdtable->magic = FWDTABLEMAGIC; *fwdtablep = fwdtable; +} - return (ISC_R_SUCCESS); +static dns_forwarders_t * +new_forwarders(isc_mem_t *mctx, const dns_name_t *name, + dns_fwdpolicy_t fwdpolicy) { + dns_forwarders_t *forwarders = NULL; -cleanup_fwdtable: - isc_mem_put(mctx, fwdtable, sizeof(*fwdtable)); + forwarders = isc_mem_get(mctx, sizeof(*forwarders)); + *forwarders = (dns_forwarders_t){ + .fwdpolicy = fwdpolicy, + .fwdrs = ISC_LIST_INITIALIZER, + }; + isc_mem_attach(mctx, &forwarders->mctx); + isc_refcount_init(&forwarders->references, 1); - return (result); + forwarders->name = dns_fixedname_initname(&forwarders->fn); + dns_name_copy(name, forwarders->name); + + return (forwarders); } isc_result_t dns_fwdtable_addfwd(dns_fwdtable_t *fwdtable, const dns_name_t *name, dns_forwarderlist_t *fwdrs, dns_fwdpolicy_t fwdpolicy) { isc_result_t result; - dns_forwarders_t *forwarders; - dns_forwarder_t *fwd, *nfwd; + dns_forwarders_t *forwarders = NULL; + dns_forwarder_t *fwd = NULL, *nfwd = NULL; + dns_qp_t *qp = NULL; REQUIRE(VALID_FWDTABLE(fwdtable)); - forwarders = isc_mem_get(fwdtable->mctx, sizeof(*forwarders)); + forwarders = new_forwarders(fwdtable->mctx, name, fwdpolicy); - ISC_LIST_INIT(forwarders->fwdrs); for (fwd = ISC_LIST_HEAD(*fwdrs); fwd != NULL; fwd = ISC_LIST_NEXT(fwd, link)) { @@ -97,13 +115,15 @@ dns_fwdtable_addfwd(dns_fwdtable_t *fwdtable, const dns_name_t *name, ISC_LINK_INIT(nfwd, link); ISC_LIST_APPEND(forwarders->fwdrs, nfwd, link); } - forwarders->fwdpolicy = fwdpolicy; - RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write); - result = dns_rbt_addname(fwdtable->table, name, forwarders); - RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write); + dns_qpmulti_write(fwdtable->table, &qp); + result = dns_qp_insert(qp, forwarders, 0); + dns_qp_compact(qp, DNS_QPGC_MAYBE); + dns_qpmulti_commit(fwdtable->table, &qp); - if (result != ISC_R_SUCCESS) { + if (result == ISC_R_SUCCESS) { + dns_forwarders_detach(&forwarders); + } else { goto cleanup; } @@ -128,15 +148,15 @@ isc_result_t dns_fwdtable_add(dns_fwdtable_t *fwdtable, const dns_name_t *name, isc_sockaddrlist_t *addrs, dns_fwdpolicy_t fwdpolicy) { isc_result_t result; - dns_forwarders_t *forwarders; - dns_forwarder_t *fwd; - isc_sockaddr_t *sa; + dns_forwarders_t *forwarders = NULL; + dns_forwarder_t *fwd = NULL; + isc_sockaddr_t *sa = NULL; + dns_qp_t *qp = NULL; REQUIRE(VALID_FWDTABLE(fwdtable)); - forwarders = isc_mem_get(fwdtable->mctx, sizeof(*forwarders)); + forwarders = new_forwarders(fwdtable->mctx, name, fwdpolicy); - ISC_LIST_INIT(forwarders->fwdrs); for (sa = ISC_LIST_HEAD(*addrs); sa != NULL; sa = ISC_LIST_NEXT(sa, link)) { @@ -145,13 +165,15 @@ dns_fwdtable_add(dns_fwdtable_t *fwdtable, const dns_name_t *name, .link = ISC_LINK_INITIALIZER }; ISC_LIST_APPEND(forwarders->fwdrs, fwd, link); } - forwarders->fwdpolicy = fwdpolicy; - RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write); - result = dns_rbt_addname(fwdtable->table, name, forwarders); - RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write); + dns_qpmulti_write(fwdtable->table, &qp); + result = dns_qp_insert(qp, forwarders, 0); + dns_qp_compact(qp, DNS_QPGC_MAYBE); + dns_qpmulti_commit(fwdtable->table, &qp); - if (result != ISC_R_SUCCESS) { + if (result == ISC_R_SUCCESS) { + dns_forwarders_detach(&forwarders); + } else { goto cleanup; } @@ -169,30 +191,35 @@ cleanup: isc_result_t dns_fwdtable_find(dns_fwdtable_t *fwdtable, const dns_name_t *name, - dns_name_t *foundname, dns_forwarders_t **forwardersp) { + dns_forwarders_t **forwardersp) { isc_result_t result; + dns_qpread_t qpr; + void *pval = NULL; REQUIRE(VALID_FWDTABLE(fwdtable)); - RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read); - result = dns_rbt_findname(fwdtable->table, name, 0, foundname, - (void **)forwardersp); - RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read); + dns_qpmulti_query(fwdtable->table, &qpr); + result = dns_qp_findname_ancestor(&qpr, name, 0, &pval, NULL); + if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { + dns_forwarders_t *fwdrs = pval; + *forwardersp = fwdrs; + dns_forwarders_ref(fwdrs); + } + dns_qpread_destroy(fwdtable->table, &qpr); return (result); } void dns_fwdtable_destroy(dns_fwdtable_t **fwdtablep) { - dns_fwdtable_t *fwdtable; + dns_fwdtable_t *fwdtable = NULL; REQUIRE(fwdtablep != NULL && VALID_FWDTABLE(*fwdtablep)); fwdtable = *fwdtablep; *fwdtablep = NULL; - dns_rbt_destroy(&fwdtable->table); - isc_rwlock_destroy(&fwdtable->rwlock); + dns_qpmulti_destroy(&fwdtable->table); fwdtable->magic = 0; isc_mem_putanddetach(&fwdtable->mctx, fwdtable, sizeof(*fwdtable)); @@ -203,22 +230,52 @@ dns_fwdtable_destroy(dns_fwdtable_t **fwdtablep) { ***/ static void -auto_detach(void *data, void *arg) { - dns_forwarders_t *forwarders = data; - dns_fwdtable_t *fwdtable = arg; - dns_forwarder_t *fwd; - - UNUSED(arg); +destroy_forwarders(dns_forwarders_t *forwarders) { + dns_forwarder_t *fwd = NULL; while (!ISC_LIST_EMPTY(forwarders->fwdrs)) { fwd = ISC_LIST_HEAD(forwarders->fwdrs); ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link); if (fwd->tlsname != NULL) { - dns_name_free(fwd->tlsname, fwdtable->mctx); - isc_mem_put(fwdtable->mctx, fwd->tlsname, + dns_name_free(fwd->tlsname, forwarders->mctx); + isc_mem_put(forwarders->mctx, fwd->tlsname, sizeof(*fwd->tlsname)); } - isc_mem_put(fwdtable->mctx, fwd, sizeof(*fwd)); + isc_mem_put(forwarders->mctx, fwd, sizeof(*fwd)); } - isc_mem_put(fwdtable->mctx, forwarders, sizeof(*forwarders)); + isc_mem_putanddetach(&forwarders->mctx, forwarders, + sizeof(*forwarders)); +} + +#if DNS_FORWARD_TRACE +ISC_REFCOUNT_TRACE_IMPL(dns_forwarders, destroy_forwarders); +#else +ISC_REFCOUNT_IMPL(dns_forwarders, destroy_forwarders); +#endif + +static void +qp_attach(void *uctx ISC_ATTR_UNUSED, void *pval, + uint32_t ival ISC_ATTR_UNUSED) { + dns_forwarders_t *forwarders = pval; + dns_forwarders_ref(forwarders); +} + +static void +qp_detach(void *uctx ISC_ATTR_UNUSED, void *pval, + uint32_t ival ISC_ATTR_UNUSED) { + dns_forwarders_t *forwarders = pval; + dns_forwarders_detach(&forwarders); +} + +static size_t +qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval, + uint32_t ival ISC_ATTR_UNUSED) { + dns_forwarders_t *fwd = pval; + return (dns_qpkey_fromname(key, fwd->name)); +} + +static void +qp_triename(void *uctx, char *buf, size_t size) { + dns_view_t *view = uctx; + snprintf(buf, size, "view %s forwarder table", view->name); } diff --git a/lib/dns/include/dns/forward.h b/lib/dns/include/dns/forward.h index 3a95e69605..8ce9f6abc7 100644 --- a/lib/dns/include/dns/forward.h +++ b/lib/dns/include/dns/forward.h @@ -16,11 +16,18 @@ /*! \file dns/forward.h */ #include +#include +#include #include #include +#include +#include #include +/* Define to 1 for detailed reference tracing */ +#undef DNS_FORWARD_TRACE + ISC_LANG_BEGINDECLS struct dns_forwarder { @@ -34,20 +41,21 @@ typedef ISC_LIST(struct dns_forwarder) dns_forwarderlist_t; struct dns_forwarders { dns_forwarderlist_t fwdrs; dns_fwdpolicy_t fwdpolicy; + isc_mem_t *mctx; + isc_refcount_t references; + dns_fixedname_t fn; + dns_name_t *name; }; -isc_result_t -dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep); +void +dns_fwdtable_create(isc_mem_t *mctx, dns_view_t *view, + dns_fwdtable_t **fwdtablep); /*%< * Creates a new forwarding table. * * Requires: * \li mctx is a valid memory context. * \li fwdtablep != NULL && *fwdtablep == NULL - * - * Returns: - * \li #ISC_R_SUCCESS - * \li #ISC_R_NOMEMORY */ isc_result_t @@ -75,7 +83,7 @@ dns_fwdtable_add(dns_fwdtable_t *fwdtable, const dns_name_t *name, isc_result_t dns_fwdtable_find(dns_fwdtable_t *fwdtable, const dns_name_t *name, - dns_name_t *foundname, dns_forwarders_t **forwardersp); + dns_forwarders_t **forwardersp); /*%< * Finds a domain in the forwarding table. The closest matching parent * domain is returned. @@ -84,13 +92,11 @@ dns_fwdtable_find(dns_fwdtable_t *fwdtable, const dns_name_t *name, * \li fwdtable is a valid forwarding table. * \li name is a valid name * \li forwardersp != NULL && *forwardersp == NULL - * \li foundname to be NULL or a valid name with buffer. * * Returns: * \li #ISC_R_SUCCESS Success * \li #DNS_R_PARTIALMATCH Superdomain found with data * \li #ISC_R_NOTFOUND No match - * \li #ISC_R_NOSPACE Concatenating nodes to form foundname failed */ void @@ -105,4 +111,17 @@ dns_fwdtable_destroy(dns_fwdtable_t **fwdtablep); * \li all memory associated with the forwarding table is freed. */ +#if DNS_FORWARD_TRACE +#define dns_forwarders_ref(ptr) \ + dns_forwarders__ref(ptr, __func__, __FILE__, __LINE__) +#define dns_forwarders_unref(ptr) \ + dns_forwarders__unref(ptr, __func__, __FILE__, __LINE__) +#define dns_forwarders_attach(ptr, ptrp) \ + dns_forwarders__attach(ptr, ptrp, __func__, __FILE__, __LINE__) +#define dns_forwarders_detach(ptrp) \ + dns_forwarders__detach(ptrp, __func__, __FILE__, __LINE__) +ISC_REFCOUNT_TRACE_DECL(dns_forwarders); +#else +ISC_REFCOUNT_DECL(dns_forwarders); +#endif ISC_LANG_ENDDECLS diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index fdc4c3437d..43e3d41fbf 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -3451,8 +3451,6 @@ fctx_getaddresses(fetchctx_t *fctx, bool badcache) { dns_forwarders_t *forwarders = NULL; dns_name_t *name = fctx->name; dns_name_t suffix; - dns_fixedname_t fixed; - dns_name_t *domain; /* * DS records are found in the parent server. @@ -3468,23 +3466,24 @@ fctx_getaddresses(fetchctx_t *fctx, bool badcache) { name = &suffix; } - domain = dns_fixedname_initname(&fixed); - result = dns_fwdtable_find(res->view->fwdtable, name, domain, + result = dns_fwdtable_find(res->view->fwdtable, name, &forwarders); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { fwd = ISC_LIST_HEAD(forwarders->fwdrs); fctx->fwdpolicy = forwarders->fwdpolicy; - dns_name_copy(domain, fctx->fwdname); + dns_name_copy(forwarders->name, fctx->fwdname); if (fctx->fwdpolicy == dns_fwdpolicy_only && - isstrictsubdomain(domain, fctx->domain)) + isstrictsubdomain(forwarders->name, fctx->domain)) { fcount_decr(fctx); - dns_name_copy(domain, fctx->domain); + dns_name_copy(forwarders->name, fctx->domain); result = fcount_incr(fctx, true); if (result != ISC_R_SUCCESS) { + dns_forwarders_detach(&forwarders); return (result); } } + dns_forwarders_detach(&forwarders); } } @@ -4566,8 +4565,6 @@ fctx_create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name, if (domain == NULL) { dns_forwarders_t *forwarders = NULL; - dns_fixedname_t fixed; - dns_name_t *fname = dns_fixedname_initname(&fixed); unsigned int labels; const dns_name_t *fwdname = name; dns_name_t suffix; @@ -4588,13 +4585,25 @@ fctx_create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name, /* Find the forwarder for this name. */ result = dns_fwdtable_find(fctx->res->view->fwdtable, fwdname, - fname, &forwarders); + &forwarders); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { fctx->fwdpolicy = forwarders->fwdpolicy; - dns_name_copy(fname, fctx->fwdname); + dns_name_copy(forwarders->name, fctx->fwdname); + dns_forwarders_detach(&forwarders); } - if (fctx->fwdpolicy != dns_fwdpolicy_only) { + if (fctx->fwdpolicy == dns_fwdpolicy_only) { + /* + * We're in forward-only mode. Set the query + * domain. + */ + dns_name_copy(fctx->fwdname, fctx->domain); + dns_name_copy(fctx->fwdname, fctx->qmindcname); + /* + * Disable query minimization + */ + options &= ~DNS_FETCHOPT_QMINIMIZE; + } else { dns_fixedname_t dcfixed; dns_name_t *dcname = dns_fixedname_initname(&dcfixed); @@ -4606,29 +4615,18 @@ fctx_create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name, if (dns_rdatatype_atparent(fctx->type)) { findoptions |= DNS_DBFIND_NOEXACT; } - result = dns_view_findzonecut(res->view, name, fname, - dcname, fctx->now, - findoptions, true, true, - &fctx->nameservers, NULL); + result = dns_view_findzonecut( + res->view, name, fctx->fwdname, dcname, + fctx->now, findoptions, true, true, + &fctx->nameservers, NULL); if (result != ISC_R_SUCCESS) { goto cleanup_nameservers; } - dns_name_copy(fname, fctx->domain); + dns_name_copy(fctx->fwdname, fctx->domain); dns_name_copy(dcname, fctx->qmindcname); fctx->ns_ttl = fctx->nameservers.ttl; fctx->ns_ttl_ok = true; - } else { - /* - * We're in forward-only mode. Set the query - * domain. - */ - dns_name_copy(fname, fctx->domain); - dns_name_copy(fname, fctx->qmindcname); - /* - * Disable query minimization - */ - options &= ~DNS_FETCHOPT_QMINIMIZE; } } else { dns_name_copy(domain, fctx->domain); @@ -6557,8 +6555,6 @@ static inline bool name_external(const dns_name_t *name, dns_rdatatype_t type, fetchctx_t *fctx) { isc_result_t result; dns_forwarders_t *forwarders = NULL; - dns_fixedname_t fixed; - dns_name_t *fname = dns_fixedname_initname(&fixed); dns_name_t *apex = NULL; dns_name_t suffix; dns_zone_t *zone = NULL; @@ -6611,7 +6607,7 @@ name_external(const dns_name_t *name, dns_rdatatype_t type, fetchctx_t *fctx) { /* * Look for a forward declaration below 'name'. */ - result = dns_fwdtable_find(fctx->res->view->fwdtable, name, fname, + result = dns_fwdtable_find(fctx->res->view->fwdtable, name, &forwarders); if (ISFORWARDER(fctx->addrinfo)) { @@ -6619,7 +6615,10 @@ name_external(const dns_name_t *name, dns_rdatatype_t type, fetchctx_t *fctx) { * See if the forwarder declaration is better. */ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { - return (!dns_name_equal(fname, fctx->fwdname)); + bool better = !dns_name_equal(forwarders->name, + fctx->fwdname); + dns_forwarders_detach(&forwarders); + return (better); } /* @@ -6627,15 +6626,15 @@ name_external(const dns_name_t *name, dns_rdatatype_t type, fetchctx_t *fctx) { * changed: play it safe and don't cache. */ return (true); - } else if ((result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) && - forwarders->fwdpolicy == dns_fwdpolicy_only && - !ISC_LIST_EMPTY(forwarders->fwdrs)) - { + } else if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { /* * If 'name' is covered by a 'forward only' clause then we * can't cache this response. */ - return (true); + bool nocache = (forwarders->fwdpolicy == dns_fwdpolicy_only && + !ISC_LIST_EMPTY(forwarders->fwdrs)); + dns_forwarders_detach(&forwarders); + return (nocache); } return (false); diff --git a/lib/dns/view.c b/lib/dns/view.c index 3683ea0472..1b307dd8d7 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -135,13 +135,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, const char *name, dns_zt_create(mctx, view, &view->zonetable); - result = dns_fwdtable_create(mctx, &view->fwdtable); - if (result != ISC_R_SUCCESS) { - UNEXPECTED_ERROR("dns_fwdtable_create() failed: %s", - isc_result_totext(result)); - result = ISC_R_UNEXPECTED; - goto cleanup_zt; - } + dns_fwdtable_create(mctx, view, &view->fwdtable); dns_tsigkeyring_create(view->mctx, &view->dynamickeys); @@ -193,11 +187,7 @@ cleanup_new_zone_lock: isc_refcount_decrementz(&view->references); isc_refcount_destroy(&view->references); - if (view->fwdtable != NULL) { - dns_fwdtable_destroy(&view->fwdtable); - } - -cleanup_zt: + dns_fwdtable_destroy(&view->fwdtable); dns_zt_detach(&view->zonetable); isc_rwlock_destroy(&view->sfd_lock);