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);