]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
use a qp-trie for the forwarders table
authorEvan Hunt <each@isc.org>
Thu, 6 Apr 2023 06:08:12 +0000 (23:08 -0700)
committerOndřej Surý <ondrej@isc.org>
Tue, 15 Aug 2023 12:25:24 +0000 (14:25 +0200)
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
lib/dns/forward.c
lib/dns/include/dns/forward.h
lib/dns/resolver.c
lib/dns/view.c

index 5d7e000396792c595e958e6418387600dbc005b1..667bca425b773e46d365acfeb59a58358e4970a7 100644 (file)
@@ -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;
                        }
 
index df377bc202170a06f3822dd37326c2804063100d..77efc595d6fbb6b93c965c9ad8fdb7ffc0c72505 100644 (file)
 #include <isc/magic.h>
 #include <isc/mem.h>
 #include <isc/result.h>
-#include <isc/rwlock.h>
 #include <isc/util.h>
 
+#include <dns/fixedname.h>
 #include <dns/forward.h>
 #include <dns/name.h>
-#include <dns/rbt.h>
+#include <dns/qp.h>
 #include <dns/types.h>
+#include <dns/view.h>
 
 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);
 }
index 3a95e69605b025687a852f894f725e2cd3dc3126..8ce9f6abc7ddc84738917a32b7a33db4b9b2fa6e 100644 (file)
 /*! \file dns/forward.h */
 
 #include <isc/lang.h>
+#include <isc/mem.h>
+#include <isc/refcount.h>
 #include <isc/result.h>
 #include <isc/sockaddr.h>
 
+#include <dns/fixedname.h>
+#include <dns/qp.h>
 #include <dns/types.h>
 
+/* 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
index fdc4c3437d1d8b37f5885e7106ab6ab77f431c61..43e3d41fbfb443ea8d7134e89571de93b13c8762 100644 (file)
@@ -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);
index 3683ea0472b563ae98312068c383f418090cfb21..1b307dd8d7180f02da575708d145b9d61fdde931 100644 (file)
@@ -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);