From: Evan Hunt Date: Sat, 15 Apr 2023 21:49:45 +0000 (-0700) Subject: use a qp-trie for the keytable X-Git-Tag: v9.19.17~53^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b4664394371c58a0ba1f91f035c722258913e294;p=thirdparty%2Fbind9.git use a qp-trie for the keytable Instead of an RBT for the trust anchor tables, use a QP-trie. --- diff --git a/bin/delv/delv.c b/bin/delv/delv.c index 2e6f82c7e5e..e947abedec6 100644 --- a/bin/delv/delv.c +++ b/bin/delv/delv.c @@ -2161,7 +2161,7 @@ run_server(void *arg) { view->qminimization = qmin; view->qmin_strict = qmin_strict; - CHECK(dns_view_initsecroots(view, mctx)); + dns_view_initsecroots(view); CHECK(setup_dnsseckeys(NULL, view)); dns_view_setdispatchmgr(view, dispatchmgr); diff --git a/bin/named/server.c b/bin/named/server.c index 667bca425b7..c8b1bdbf816 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -1044,7 +1044,7 @@ keyloaded(dns_view_t *view, const dns_name_t *name) { result = dns_keytable_find(secroots, name, &keynode); if (keynode != NULL) { - dns_keytable_detachkeynode(secroots, &keynode); + dns_keynode_detach(&keynode); } if (secroots != NULL) { dns_keytable_detach(&secroots); @@ -1062,7 +1062,7 @@ keyloaded(dns_view_t *view, const dns_name_t *name) { static isc_result_t configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, const cfg_obj_t *config, const cfg_obj_t *bindkeys, - bool auto_root, isc_mem_t *mctx) { + bool auto_root) { isc_result_t result = ISC_R_SUCCESS; const cfg_obj_t *view_keys = NULL; const cfg_obj_t *global_keys = NULL; @@ -1116,14 +1116,7 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, maps[i++] = named_g_defaults; maps[i] = NULL; - result = dns_view_initsecroots(view, mctx); - if (result != ISC_R_SUCCESS) { - isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, - NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, - "couldn't create keytable"); - return (ISC_R_UNEXPECTED); - } - + dns_view_initsecroots(view); dns_view_initntatable(view, named_g_loopmgr); if (auto_root && view->rdclass == dns_rdataclass_in) { @@ -5534,7 +5527,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, * "security roots". */ CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys, - auto_root, mctx)); + auto_root)); dns_resolver_resetmustbesecure(view->resolver); obj = NULL; result = named_config_get(maps, "dnssec-must-be-secure", &obj); @@ -7309,7 +7302,7 @@ tat_timer_tick(void *arg) { dotat_arg.view = view; dotat_arg.loop = named_g_mainloop; - (void)dns_keytable_forall(secroots, dotat, &dotat_arg); + dns_keytable_forall(secroots, dotat, &dotat_arg); dns_keytable_detach(&secroots); } } diff --git a/lib/dns/client.c b/lib/dns/client.c index e2127000979..2eee2d34809 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -214,28 +214,18 @@ createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, isc_loopmgr_t *loopmgr, dns_view_setdispatchmgr(view, dispatchmgr); /* Initialize view security roots */ - result = dns_view_initsecroots(view, mctx); - if (result != ISC_R_SUCCESS) { - goto cleanup_view; - } - - result = dns_view_createresolver(view, loopmgr, 1, nm, 0, - tlsctx_client_cache, dispatchv4, - dispatchv6); - if (result != ISC_R_SUCCESS) { - goto cleanup_view; - } + dns_view_initsecroots(view); - result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_cache, - rdclass, 0, NULL, &view->cachedb); - if (result != ISC_R_SUCCESS) { - goto cleanup_view; - } + CHECK(dns_view_createresolver(view, loopmgr, 1, nm, 0, + tlsctx_client_cache, dispatchv4, + dispatchv6)); + CHECK(dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_cache, + rdclass, 0, NULL, &view->cachedb)); *viewp = view; return (ISC_R_SUCCESS); -cleanup_view: +cleanup: dns_view_detach(&view); return (result); } diff --git a/lib/dns/include/dns/keytable.h b/lib/dns/include/dns/keytable.h index 6095a85e3fa..b407cf2552a 100644 --- a/lib/dns/include/dns/keytable.h +++ b/lib/dns/include/dns/keytable.h @@ -51,59 +51,15 @@ ISC_LANG_BEGINDECLS typedef void (*dns_keytable_callback_t)(const dns_name_t *name, void *fn_arg); -isc_result_t -dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep); +void +dns_keytable_create(dns_view_t *view, dns_keytable_t **keytablep); /*%< * Create a keytable. * * Requires: * - *\li 'mctx' is a valid memory context. - * + *\li 'view' is a valid memory context. *\li keytablep != NULL && *keytablep == NULL - * - * Ensures: - * - *\li On success, *keytablep is a valid, empty key table. - * - * Returns: - * - *\li ISC_R_SUCCESS - * - *\li Any other result indicates failure. - */ - -void -dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp); -/*%< - * Attach *targetp to source. - * - * Requires: - * - *\li 'source' is a valid keytable. - * - *\li 'targetp' points to a NULL dns_keytable_t *. - * - * Ensures: - * - *\li *targetp is attached to source. - */ - -void -dns_keytable_detach(dns_keytable_t **keytablep); -/*%< - * Detach *keytablep from its keytable. - * - * Requires: - * - *\li 'keytablep' points to a valid keytable. - * - * Ensures: - * - *\li *keytablep is NULL. - * - *\li If '*keytablep' is the last reference to the keytable, - * all resources used by the keytable will be freed */ isc_result_t @@ -252,20 +208,6 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name, *\li Any other result indicates an error. */ -void -dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep); -/*%< - * Detach a keynode found via dns_keytable_find(). - * - * Requires: - * - *\li *keynodep is a valid keynode returned by a call to dns_keytable_find(). - * - * Ensures: - * - *\li *keynodep == NULL - */ - isc_result_t dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name, dns_name_t *foundname, bool *wantdnssecp); @@ -343,9 +285,15 @@ dns_keynode_trust(dns_keynode_t *keynode); * trusted: no longer an initializing key. */ -isc_result_t +void dns_keytable_forall(dns_keytable_t *keytable, void (*func)(dns_keytable_t *, dns_keynode_t *, dns_name_t *, void *), void *arg); +/*%< + * Call 'func' on each keynode in 'keytable'. + */ + +ISC_REFCOUNT_DECL(dns_keytable); +ISC_REFCOUNT_DECL(dns_keynode); ISC_LANG_ENDDECLS diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index 9269e27b567..f22cb876a29 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -960,8 +960,8 @@ dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp); *\li ISC_R_NOTFOUND */ -isc_result_t -dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx); +void +dns_view_initsecroots(dns_view_t *view); /*%< * Initialize security roots for the view, detaching any previously * existing security roots first. (Note that secroots_priv is diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c index aa8c66ef81e..99ffe5623ac 100644 --- a/lib/dns/keytable.c +++ b/lib/dns/keytable.c @@ -25,11 +25,12 @@ #include #include #include -#include +#include #include #include #include #include +#include #define KEYTABLE_MAGIC ISC_MAGIC('K', 'T', 'b', 'l') #define VALID_KEYTABLE(kt) ISC_MAGIC_VALID(kt, KEYTABLE_MAGIC) @@ -38,20 +39,20 @@ #define VALID_KEYNODE(kn) ISC_MAGIC_VALID(kn, KEYNODE_MAGIC) struct dns_keytable { - /* Unlocked. */ unsigned int magic; isc_mem_t *mctx; isc_refcount_t references; isc_rwlock_t rwlock; - /* Locked by rwlock. */ - dns_rbt_t *table; + dns_qpmulti_t *table; }; struct dns_keynode { unsigned int magic; isc_mem_t *mctx; - isc_refcount_t refcount; + isc_refcount_t references; isc_rwlock_t rwlock; + dns_fixedname_t fn; + dns_name_t *name; dns_rdatalist_t *dslist; dns_rdataset_t dsset; bool managed; @@ -59,9 +60,27 @@ struct dns_keynode { }; static dns_keynode_t * -new_keynode(dns_rdata_ds_t *ds, dns_keytable_t *keytable, bool managed, - bool initial); +new_keynode(const dns_name_t *name, dns_rdata_ds_t *ds, + dns_keytable_t *keytable, bool managed, bool initial); + +/* QP trie methods */ +static 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); + +static dns_qpmethods_t qpmethods = { + qp_attach, + qp_detach, + qp_makekey, + qp_triename, +}; +/* rdataset methods */ static void keynode_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG); static isc_result_t @@ -82,55 +101,33 @@ static dns_rdatasetmethods_t methods = { }; static void -keynode_attach(dns_keynode_t *source, dns_keynode_t **target) { - REQUIRE(VALID_KEYNODE(source)); - isc_refcount_increment(&source->refcount); - *target = source; -} - -static void -keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynodep) { - REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep)); - dns_keynode_t *knode = *keynodep; - *keynodep = NULL; - - if (isc_refcount_decrement(&knode->refcount) == 1) { - dns_rdata_t *rdata = NULL; - isc_refcount_destroy(&knode->refcount); - isc_rwlock_destroy(&knode->rwlock); - if (knode->dslist != NULL) { - for (rdata = ISC_LIST_HEAD(knode->dslist->rdata); - rdata != NULL; - rdata = ISC_LIST_HEAD(knode->dslist->rdata)) - { - ISC_LIST_UNLINK(knode->dslist->rdata, rdata, - link); - isc_mem_put(mctx, rdata->data, - DNS_DS_BUFFERSIZE); - isc_mem_put(mctx, rdata, sizeof(*rdata)); - } +destroy_keynode(dns_keynode_t *knode) { + dns_rdata_t *rdata = NULL; - isc_mem_put(mctx, knode->dslist, - sizeof(*knode->dslist)); - knode->dslist = NULL; + isc_refcount_destroy(&knode->references); + isc_rwlock_destroy(&knode->rwlock); + if (knode->dslist != NULL) { + for (rdata = ISC_LIST_HEAD(knode->dslist->rdata); rdata != NULL; + rdata = ISC_LIST_HEAD(knode->dslist->rdata)) + { + ISC_LIST_UNLINK(knode->dslist->rdata, rdata, link); + isc_mem_put(knode->mctx, rdata->data, + DNS_DS_BUFFERSIZE); + isc_mem_put(knode->mctx, rdata, sizeof(*rdata)); } - isc_mem_putanddetach(&knode->mctx, knode, - sizeof(dns_keynode_t)); - } -} -static void -free_keynode(void *node, void *arg) { - dns_keynode_t *keynode = node; - isc_mem_t *mctx = arg; + isc_mem_put(knode->mctx, knode->dslist, sizeof(*knode->dslist)); + knode->dslist = NULL; + } - keynode_detach(mctx, &keynode); + isc_mem_putanddetach(&knode->mctx, knode, sizeof(dns_keynode_t)); } -isc_result_t -dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) { - dns_keytable_t *keytable; - isc_result_t result; +ISC_REFCOUNT_IMPL(dns_keynode, destroy_keynode); + +void +dns_keytable_create(dns_view_t *view, dns_keytable_t **keytablep) { + dns_keytable_t *keytable = NULL; /* * Create a keytable. @@ -138,55 +135,40 @@ dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) { REQUIRE(keytablep != NULL && *keytablep == NULL); - keytable = isc_mem_get(mctx, sizeof(*keytable)); + keytable = isc_mem_get(view->mctx, sizeof(*keytable)); + *keytable = (dns_keytable_t){ + .magic = KEYTABLE_MAGIC, + }; - keytable->table = NULL; - result = dns_rbt_create(mctx, free_keynode, mctx, &keytable->table); - if (result != ISC_R_SUCCESS) { - goto cleanup_keytable; - } - - isc_rwlock_init(&keytable->rwlock); + isc_mem_attach(view->mctx, &keytable->mctx); + dns_qpmulti_create(view->mctx, &qpmethods, view, &keytable->table); isc_refcount_init(&keytable->references, 1); - - keytable->mctx = NULL; - isc_mem_attach(mctx, &keytable->mctx); - keytable->magic = KEYTABLE_MAGIC; *keytablep = keytable; +} - return (ISC_R_SUCCESS); - -cleanup_keytable: - isc_mem_putanddetach(&mctx, keytable, sizeof(*keytable)); +static void +destroy_keytable(dns_keytable_t *keytable) { + dns_qpread_t qpr; + dns_qpiter_t iter; + void *pval = NULL; - return (result); -} + keytable->magic = 0; -void -dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) { - REQUIRE(VALID_KEYTABLE(source)); - REQUIRE(targetp != NULL && *targetp == NULL); + dns_qpmulti_query(keytable->table, &qpr); + dns_qpiter_init(&qpr, &iter); + while (dns_qpiter_next(&iter, &pval, NULL) == ISC_R_SUCCESS) { + dns_keynode_t *n = pval; + dns_keynode_detach(&n); + } + dns_qpread_destroy(keytable->table, &qpr); - isc_refcount_increment(&source->references); + dns_qpmulti_destroy(&keytable->table); + isc_refcount_destroy(&keytable->references); - *targetp = source; + isc_mem_putanddetach(&keytable->mctx, keytable, sizeof(*keytable)); } -void -dns_keytable_detach(dns_keytable_t **keytablep) { - REQUIRE(keytablep != NULL && VALID_KEYTABLE(*keytablep)); - dns_keytable_t *keytable = *keytablep; - *keytablep = NULL; - - if (isc_refcount_decrement(&keytable->references) == 1) { - isc_refcount_destroy(&keytable->references); - dns_rbt_destroy(&keytable->table); - isc_rwlock_destroy(&keytable->rwlock); - keytable->magic = 0; - isc_mem_putanddetach(&keytable->mctx, keytable, - sizeof(*keytable)); - } -} +ISC_REFCOUNT_IMPL(dns_keytable, destroy_keytable); static void add_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) { @@ -245,13 +227,15 @@ add_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) { } static isc_result_t -delete_ds(dns_keytable_t *keytable, dns_rbtnode_t *node, dns_rdata_ds_t *ds) { - dns_keynode_t *knode = node->data; +delete_ds(dns_qp_t *qp, dns_keytable_t *keytable, dns_keynode_t *knode, + dns_rdata_ds_t *ds) { isc_result_t result; dns_rdata_t dsrdata = DNS_RDATA_INIT; dns_rdata_t *rdata = NULL; + dns_keynode_t *newnode = NULL; unsigned char data[DNS_DS_BUFFERSIZE]; bool found = false; + void *pval = NULL; isc_buffer_t b; RWLOCK(&knode->rwlock, isc_rwlocktype_read); @@ -290,8 +274,8 @@ delete_ds(dns_keytable_t *keytable, dns_rbtnode_t *node, dns_rdata_ds_t *ds) { /* * Replace knode with a new instance without the DS. */ - node->data = new_keynode(NULL, keytable, knode->managed, - knode->initial); + newnode = new_keynode(knode->name, NULL, keytable, knode->managed, + knode->initial); for (rdata = ISC_LIST_HEAD(knode->dslist->rdata); rdata != NULL; rdata = ISC_LIST_NEXT(rdata, link)) { @@ -299,13 +283,20 @@ delete_ds(dns_keytable_t *keytable, dns_rbtnode_t *node, dns_rdata_ds_t *ds) { dns_rdata_ds_t ds0; result = dns_rdata_tostruct(rdata, &ds0, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); - add_ds(node->data, &ds0, keytable->mctx); + add_ds(newnode, &ds0, keytable->mctx); } } - RWUNLOCK(&knode->rwlock, isc_rwlocktype_read); - keynode_detach(keytable->mctx, &knode); + result = dns_qp_deletename(qp, knode->name, &pval, NULL); + INSIST(result == ISC_R_SUCCESS); + INSIST(pval == knode); + + result = dns_qp_insert(qp, newnode, 0); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + RWUNLOCK(&knode->rwlock, isc_rwlocktype_read); + dns_keynode_detach(&knode); return (ISC_R_SUCCESS); } @@ -315,8 +306,8 @@ delete_ds(dns_keytable_t *keytable, dns_rbtnode_t *node, dns_rdata_ds_t *ds) { * to "node" in "keytable". */ static dns_keynode_t * -new_keynode(dns_rdata_ds_t *ds, dns_keytable_t *keytable, bool managed, - bool initial) { +new_keynode(const dns_name_t *name, dns_rdata_ds_t *ds, + dns_keytable_t *keytable, bool managed, bool initial) { dns_keynode_t *knode = NULL; REQUIRE(VALID_KEYTABLE(keytable)); @@ -326,9 +317,12 @@ new_keynode(dns_rdata_ds_t *ds, dns_keytable_t *keytable, bool managed, *knode = (dns_keynode_t){ .magic = KEYNODE_MAGIC }; dns_rdataset_init(&knode->dsset); - isc_refcount_init(&knode->refcount, 1); + isc_refcount_init(&knode->references, 1); isc_rwlock_init(&knode->rwlock); + knode->name = dns_fixedname_initname(&knode->fn); + dns_name_copy(name, knode->name); + /* * If a DS was supplied, initialize an rdatalist. */ @@ -354,45 +348,41 @@ static isc_result_t insert(dns_keytable_t *keytable, bool managed, bool initial, const dns_name_t *keyname, dns_rdata_ds_t *ds, dns_keytable_callback_t callback, void *callback_arg) { - dns_rbtnode_t *node = NULL; isc_result_t result; + dns_keynode_t *newnode = NULL; + dns_qp_t *qp = NULL; + void *pval = NULL; REQUIRE(VALID_KEYTABLE(keytable)); - RWLOCK(&keytable->rwlock, isc_rwlocktype_write); + dns_qpmulti_write(keytable->table, &qp); - result = dns_rbt_addnode(keytable->table, keyname, &node); - if (result == ISC_R_SUCCESS) { + result = dns_qp_getname(qp, keyname, &pval, NULL); + if (result != ISC_R_SUCCESS) { /* - * There was no node for "keyname" in "keytable" yet, so one + * There was no match for "keyname" in "keytable" yet, so one * was created. Create a new key node for the supplied * trust anchor (or a null key node if "ds" is NULL) - * and attach it to the created node. + * and insert it. */ - node->data = new_keynode(ds, keytable, managed, initial); + newnode = new_keynode(keyname, ds, keytable, managed, initial); + result = dns_qp_insert(qp, newnode, 0); if (callback != NULL) { (*callback)(keyname, callback_arg); } - } else if (result == ISC_R_EXISTS) { + } else { /* * A node already exists for "keyname" in "keytable". */ if (ds != NULL) { - dns_keynode_t *knode = node->data; - if (knode == NULL) { - node->data = new_keynode(ds, keytable, managed, - initial); - if (callback != NULL) { - (*callback)(keyname, callback_arg); - } - } else { - add_ds(knode, ds, keytable->mctx); - } + dns_keynode_t *knode = pval; + add_ds(knode, ds, keytable->mctx); } result = ISC_R_SUCCESS; } - RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write); + dns_qp_compact(qp, DNS_QPGC_MAYBE); + dns_qpmulti_commit(keytable->table, &qp); return (result); } @@ -417,28 +407,23 @@ isc_result_t dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname, dns_keytable_callback_t callback, void *callback_arg) { isc_result_t result; - dns_rbtnode_t *node = NULL; + dns_qp_t *qp = NULL; + void *pval = NULL; REQUIRE(VALID_KEYTABLE(keytable)); REQUIRE(keyname != NULL); - RWLOCK(&keytable->rwlock, isc_rwlocktype_write); - result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL, - DNS_RBTFIND_NOOPTIONS, NULL, NULL); + dns_qpmulti_write(keytable->table, &qp); + result = dns_qp_deletename(qp, keyname, &pval, NULL); if (result == ISC_R_SUCCESS) { - if (node->data != NULL) { - result = dns_rbt_deletenode(keytable->table, node, - false); - if (callback != NULL) { - (*callback)(keyname, callback_arg); - } - } else { - result = ISC_R_NOTFOUND; + dns_keynode_t *n = pval; + if (callback != NULL) { + (*callback)(keyname, callback_arg); } - } else if (result == DNS_R_PARTIALMATCH) { - result = ISC_R_NOTFOUND; + dns_keynode_detach(&n); } - RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write); + dns_qp_compact(qp, DNS_QPGC_MAYBE); + dns_qpmulti_commit(keytable->table, &qp); return (result); } @@ -447,33 +432,24 @@ isc_result_t dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname, dns_rdata_dnskey_t *dnskey) { isc_result_t result; - dns_rbtnode_t *node = NULL; dns_keynode_t *knode = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; unsigned char data[4096], digest[DNS_DS_BUFFERSIZE]; dns_rdata_ds_t ds; isc_buffer_t b; + dns_qp_t *qp = NULL; + void *pval = NULL; REQUIRE(VALID_KEYTABLE(keytable)); REQUIRE(dnskey != NULL); - RWLOCK(&keytable->rwlock, isc_rwlocktype_write); - result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL, - DNS_RBTFIND_NOOPTIONS, NULL, NULL); - - if (result == DNS_R_PARTIALMATCH) { - result = ISC_R_NOTFOUND; - } + dns_qpmulti_write(keytable->table, &qp); + result = dns_qp_getname(qp, keyname, &pval, NULL); if (result != ISC_R_SUCCESS) { goto finish; } - if (node->data == NULL) { - result = ISC_R_NOTFOUND; - goto finish; - } - - knode = node->data; + knode = pval; RWLOCK(&knode->rwlock, isc_rwlocktype_read); if (knode->dslist == NULL) { @@ -496,10 +472,12 @@ dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname, goto finish; } - result = delete_ds(keytable, node, &ds); + result = delete_ds(qp, keytable, knode, &ds); finish: - RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write); + dns_qp_compact(qp, DNS_QPGC_MAYBE); + dns_qpmulti_commit(keytable->table, &qp); + return (result); } @@ -507,25 +485,20 @@ isc_result_t dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname, dns_keynode_t **keynodep) { isc_result_t result; - dns_rbtnode_t *node = NULL; + dns_qpread_t qpr; + void *pval = NULL; REQUIRE(VALID_KEYTABLE(keytable)); REQUIRE(keyname != NULL); REQUIRE(keynodep != NULL && *keynodep == NULL); - RWLOCK(&keytable->rwlock, isc_rwlocktype_read); - result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL, - DNS_RBTFIND_NOOPTIONS, NULL, NULL); + dns_qpmulti_query(keytable->table, &qpr); + result = dns_qp_getname(&qpr, keyname, &pval, NULL); if (result == ISC_R_SUCCESS) { - if (node->data != NULL) { - keynode_attach(node->data, keynodep); - } else { - result = ISC_R_NOTFOUND; - } - } else if (result == DNS_R_PARTIALMATCH) { - result = ISC_R_NOTFOUND; + dns_keynode_t *knode = pval; + dns_keynode_attach(knode, keynodep); } - RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); + dns_qpread_destroy(keytable->table, &qpr); return (result); } @@ -534,7 +507,9 @@ isc_result_t dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name, dns_name_t *foundname) { isc_result_t result; - void *data; + dns_qpread_t qpr; + dns_keynode_t *keynode = NULL; + void *pval = NULL; /* * Search for the deepest match in 'keytable'. @@ -544,37 +519,26 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name, REQUIRE(dns_name_isabsolute(name)); REQUIRE(foundname != NULL); - RWLOCK(&keytable->rwlock, isc_rwlocktype_read); - - data = NULL; - result = dns_rbt_findname(keytable->table, name, 0, foundname, &data); + dns_qpmulti_query(keytable->table, &qpr); + result = dns_qp_findname_ancestor(&qpr, name, 0, &pval, NULL); + keynode = pval; if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { + dns_name_copy(keynode->name, foundname); result = ISC_R_SUCCESS; } - RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); - + dns_qpread_destroy(keytable->table, &qpr); return (result); } -void -dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep) { - /* - * Give back a keynode found via dns_keytable_findkeynode(). - */ - - REQUIRE(VALID_KEYTABLE(keytable)); - REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep)); - - keynode_detach(keytable->mctx, keynodep); -} - isc_result_t dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name, dns_name_t *foundname, bool *wantdnssecp) { isc_result_t result; - dns_rbtnode_t *node = NULL; + dns_qpread_t qpr; + dns_keynode_t *keynode = NULL; + void *pval = NULL; /* * Is 'name' at or beneath a trusted key? @@ -584,12 +548,13 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name, REQUIRE(dns_name_isabsolute(name)); REQUIRE(wantdnssecp != NULL); - RWLOCK(&keytable->rwlock, isc_rwlocktype_read); - - result = dns_rbt_findnode(keytable->table, name, foundname, &node, NULL, - DNS_RBTFIND_NOOPTIONS, NULL, NULL); + dns_qpmulti_query(keytable->table, &qpr); + result = dns_qp_findname_ancestor(&qpr, name, 0, &pval, NULL); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { - INSIST(node->data != NULL); + keynode = pval; + if (foundname != NULL) { + dns_name_copy(keynode->name, foundname); + } *wantdnssecp = true; result = ISC_R_SUCCESS; } else if (result == ISC_R_NOTFOUND) { @@ -597,7 +562,7 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name, result = ISC_R_SUCCESS; } - RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); + dns_qpread_destroy(keytable->table, &qpr); return (result); } @@ -644,20 +609,19 @@ dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) { } static isc_result_t -keynode_dslist_totext(dns_name_t *name, dns_keynode_t *keynode, - isc_buffer_t **text) { +keynode_dslist_totext(dns_keynode_t *keynode, isc_buffer_t **text) { isc_result_t result; char namebuf[DNS_NAME_FORMATSIZE]; char obuf[DNS_NAME_FORMATSIZE + 200]; dns_rdataset_t dsset; - dns_name_format(name, namebuf, sizeof(namebuf)); - dns_rdataset_init(&dsset); if (!dns_keynode_dsset(keynode, &dsset)) { return (ISC_R_SUCCESS); } + dns_name_format(keynode->name, namebuf, sizeof(namebuf)); + for (result = dns_rdataset_first(&dsset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&dsset)) { @@ -691,114 +655,57 @@ keynode_dslist_totext(dns_name_t *name, dns_keynode_t *keynode, isc_result_t dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) { - isc_result_t result; - dns_keynode_t *knode; - dns_rbtnode_t *node; - dns_rbtnodechain_t chain; - dns_name_t *foundname, *origin, *fullname; - dns_fixedname_t fixedfoundname, fixedorigin, fixedfullname; + isc_result_t result = ISC_R_SUCCESS; + dns_qpread_t qpr; + dns_qpiter_t iter; + void *pval = NULL; REQUIRE(VALID_KEYTABLE(keytable)); REQUIRE(text != NULL && *text != NULL); - origin = dns_fixedname_initname(&fixedorigin); - fullname = dns_fixedname_initname(&fixedfullname); - foundname = dns_fixedname_initname(&fixedfoundname); + dns_qpmulti_query(keytable->table, &qpr); + dns_qpiter_init(&qpr, &iter); - RWLOCK(&keytable->rwlock, isc_rwlocktype_read); - dns_rbtnodechain_init(&chain); - result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL); - if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { - if (result == ISC_R_NOTFOUND) { - result = ISC_R_SUCCESS; - } - goto cleanup; - } - for (;;) { - dns_rbtnodechain_current(&chain, foundname, origin, &node); - - knode = node->data; - if (knode != NULL && knode->dslist != NULL) { - result = dns_name_concatenate(foundname, origin, - fullname, NULL); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - - result = keynode_dslist_totext(fullname, knode, text); + while (dns_qpiter_next(&iter, &pval, NULL) == ISC_R_SUCCESS) { + dns_keynode_t *knode = pval; + if (knode->dslist != NULL) { + result = keynode_dslist_totext(knode, text); if (result != ISC_R_SUCCESS) { - goto cleanup; + break; } } - - result = dns_rbtnodechain_next(&chain, NULL, NULL); - if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { - if (result == ISC_R_NOMORE) { - result = ISC_R_SUCCESS; - } - break; - } } -cleanup: - dns_rbtnodechain_invalidate(&chain); - RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); + dns_qpread_destroy(keytable->table, &qpr); return (result); } -isc_result_t +void dns_keytable_forall(dns_keytable_t *keytable, void (*func)(dns_keytable_t *, dns_keynode_t *, dns_name_t *, void *), void *arg) { - isc_result_t result; - dns_rbtnode_t *node; - dns_rbtnodechain_t chain; - dns_fixedname_t fixedfoundname, fixedorigin, fixedfullname; - dns_name_t *foundname, *origin, *fullname; + dns_qpread_t qpr; + dns_qpiter_t iter; + void *pval = NULL; REQUIRE(VALID_KEYTABLE(keytable)); - origin = dns_fixedname_initname(&fixedorigin); - fullname = dns_fixedname_initname(&fixedfullname); - foundname = dns_fixedname_initname(&fixedfoundname); + dns_qpmulti_query(keytable->table, &qpr); + dns_qpiter_init(&qpr, &iter); - RWLOCK(&keytable->rwlock, isc_rwlocktype_read); - dns_rbtnodechain_init(&chain); - result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL); - if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { - if (result == ISC_R_NOTFOUND) { - result = ISC_R_SUCCESS; - } - goto cleanup; + while (dns_qpiter_next(&iter, &pval, NULL) == ISC_R_SUCCESS) { + dns_keynode_t *knode = pval; + (*func)(keytable, knode, knode->name, arg); } - for (;;) { - dns_rbtnodechain_current(&chain, foundname, origin, &node); - if (node->data != NULL) { - result = dns_name_concatenate(foundname, origin, - fullname, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - (*func)(keytable, node->data, fullname, arg); - } - result = dns_rbtnodechain_next(&chain, NULL, NULL); - if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { - if (result == ISC_R_NOMORE) { - result = ISC_R_SUCCESS; - } - break; - } - } - -cleanup: - dns_rbtnodechain_invalidate(&chain); - RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); - return (result); + dns_qpread_destroy(keytable->table, &qpr); } bool dns_keynode_dsset(dns_keynode_t *keynode, dns_rdataset_t *rdataset) { bool result; + REQUIRE(VALID_KEYNODE(keynode)); REQUIRE(rdataset == NULL || DNS_RDATASET_VALID(rdataset)); @@ -853,18 +760,18 @@ dns_keynode_trust(dns_keynode_t *keynode) { static void keynode_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) { - dns_keynode_t *keynode; + dns_keynode_t *keynode = NULL; rdataset->methods = NULL; keynode = rdataset->keytable.node; rdataset->keytable.node = NULL; - keynode_detach(keynode->mctx, &keynode); + dns_keynode_detach(&keynode); } static isc_result_t keynode_first(dns_rdataset_t *rdataset) { - dns_keynode_t *keynode; + dns_keynode_t *keynode = NULL; keynode = rdataset->keytable.node; RWLOCK(&keynode->rwlock, isc_rwlocktype_read); @@ -880,8 +787,8 @@ keynode_first(dns_rdataset_t *rdataset) { static isc_result_t keynode_next(dns_rdataset_t *rdataset) { - dns_keynode_t *keynode; - dns_rdata_t *rdata; + dns_keynode_t *keynode = NULL; + dns_rdata_t *rdata = NULL; rdata = rdataset->keytable.iter; if (rdata == NULL) { @@ -902,7 +809,7 @@ keynode_next(dns_rdataset_t *rdataset) { static void keynode_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { - dns_rdata_t *list_rdata; + dns_rdata_t *list_rdata = NULL; list_rdata = rdataset->keytable.iter; INSIST(list_rdata != NULL); @@ -912,11 +819,38 @@ keynode_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { static void keynode_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG) { - dns_keynode_t *keynode; + dns_keynode_t *keynode = NULL; keynode = source->keytable.node; - isc_refcount_increment(&keynode->refcount); + isc_refcount_increment(&keynode->references); *target = *source; target->keytable.iter = NULL; } + +static void +qp_attach(void *uctx ISC_ATTR_UNUSED, void *pval, + uint32_t ival ISC_ATTR_UNUSED) { + dns_keynode_t *keynode = pval; + dns_keynode_ref(keynode); +} + +static void +qp_detach(void *uctx ISC_ATTR_UNUSED, void *pval, + uint32_t ival ISC_ATTR_UNUSED) { + dns_keynode_t *keynode = pval; + dns_keynode_detach(&keynode); +} + +static size_t +qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval, + uint32_t ival ISC_ATTR_UNUSED) { + dns_keynode_t *keynode = pval; + return (dns_qpkey_fromname(key, keynode->name)); +} + +static void +qp_triename(void *uctx, char *buf, size_t size) { + dns_view_t *view = uctx; + snprintf(buf, size, "view %s secroots table", view->name); +} diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 0887c07ad97..3b9c8fc5db4 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -1715,7 +1715,7 @@ validate_dnskey(dns_validator_t *val) { if (dns_keynode_dsset(keynode, &val->fdsset)) { val->dsset = &val->fdsset; } - dns_keytable_detachkeynode(val->keytable, &keynode); + dns_keynode_detach(&keynode); } } diff --git a/lib/dns/view.c b/lib/dns/view.c index 1b307dd8d71..8f08e108d7e 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -1574,13 +1574,13 @@ dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp) { return (ISC_R_SUCCESS); } -isc_result_t -dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) { +void +dns_view_initsecroots(dns_view_t *view) { REQUIRE(DNS_VIEW_VALID(view)); if (view->secroots_priv != NULL) { dns_keytable_detach(&view->secroots_priv); } - return (dns_keytable_create(mctx, &view->secroots_priv)); + dns_keytable_create(view, &view->secroots_priv); } isc_result_t @@ -1759,7 +1759,7 @@ finish: dns_rdataset_disassociate(&dsset); } if (knode != NULL) { - dns_keytable_detachkeynode(sr, &knode); + dns_keynode_detach(&knode); } dns_keytable_detach(&sr); return (answer); diff --git a/lib/dns/zone.c b/lib/dns/zone.c index a99817294d8..2ecc27557cb 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -4594,7 +4594,7 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) { } if (keynode != NULL) { - dns_keytable_detachkeynode(sr, &keynode); + dns_keynode_detach(&keynode); } } dns_rriterator_destroy(&rrit); @@ -4632,7 +4632,7 @@ failure: isc_time_settoepoch(&zone->refreshkeytime); } if (keynode != NULL) { - dns_keytable_detachkeynode(sr, &keynode); + dns_keynode_detach(&keynode); } if (sr != NULL) { dns_keytable_detach(&sr); @@ -10035,7 +10035,7 @@ keyfetch_done(void *arg) { anchors_done: if (keynode != NULL) { - dns_keytable_detachkeynode(secroots, &keynode); + dns_keynode_detach(&keynode); } /* diff --git a/lib/dns/zoneverify.c b/lib/dns/zoneverify.c index 7709ed8d8ae..f2ff9ad38bf 100644 --- a/lib/dns/zoneverify.c +++ b/lib/dns/zoneverify.c @@ -1554,7 +1554,7 @@ check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey, cleanup: if (keynode != NULL) { - dns_keytable_detachkeynode(vctx->secroots, &keynode); + dns_keynode_detach(&keynode); } if (key != NULL) { dst_key_free(&key); diff --git a/lib/ns/query.c b/lib/ns/query.c index 1212ed16e17..e2e00b28c66 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -7513,7 +7513,7 @@ has_ta(query_ctx_t *qctx) { result = dns_keytable_find(keytable, dns_rootname, &keynode); if (result != ISC_R_SUCCESS) { if (keynode != NULL) { - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); } dns_keytable_detach(&keytable); return (false); @@ -7533,7 +7533,7 @@ has_ta(query_ctx_t *qctx) { result = dns_rdata_tostruct(&rdata, &ds, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); if (ds.key_tag == sentinel) { - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); dns_keytable_detach(&keytable); dns_rdataset_disassociate(&dsset); return (true); @@ -7543,7 +7543,7 @@ has_ta(query_ctx_t *qctx) { } if (keynode != NULL) { - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); } dns_keytable_detach(&keytable); diff --git a/tests/dns/keytable_test.c b/tests/dns/keytable_test.c index 93e13e6cc3b..f3657c6649b 100644 --- a/tests/dns/keytable_test.c +++ b/tests/dns/keytable_test.c @@ -173,7 +173,7 @@ create_tables(void) { assert_int_equal(dns_test_makeview("view", false, &view), ISC_R_SUCCESS); - assert_int_equal(dns_keytable_create(mctx, &keytable), ISC_R_SUCCESS); + dns_keytable_create(view, &keytable); dns_ntatable_create(view, loopmgr, &ntatable); /* Add a normal key */ @@ -244,13 +244,13 @@ ISC_LOOP_TEST_IMPL(add) { assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds, NULL, NULL), ISC_R_SUCCESS); - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); assert_int_equal( dns_keytable_find(keytable, str2name("example.com"), &keynode), ISC_R_SUCCESS); /* Add another key (different keydata) */ - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds); assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds, NULL, NULL), @@ -258,7 +258,7 @@ ISC_LOOP_TEST_IMPL(add) { assert_int_equal( dns_keytable_find(keytable, str2name("example.com"), &keynode), ISC_R_SUCCESS); - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); /* * Get the keynode for the managed.com key. Ensure the @@ -271,7 +271,7 @@ ISC_LOOP_TEST_IMPL(add) { assert_int_equal(dns_keynode_initial(keynode), true); dns_keynode_trust(keynode); assert_int_equal(dns_keynode_initial(keynode), false); - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); /* * Add a different managed key for managed.com, marking it as an @@ -287,7 +287,7 @@ ISC_LOOP_TEST_IMPL(add) { dns_keytable_find(keytable, str2name("managed.com"), &keynode), ISC_R_SUCCESS); assert_int_equal(dns_keynode_initial(keynode), false); - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); /* * Add the same managed key again, but this time mark it as a @@ -302,7 +302,7 @@ ISC_LOOP_TEST_IMPL(add) { dns_keytable_find(keytable, str2name("managed.com"), &keynode), ISC_R_SUCCESS); assert_int_equal(dns_keynode_initial(keynode), false); - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); /* * Add a managed key at a new node, two.com, marking it as an @@ -317,7 +317,7 @@ ISC_LOOP_TEST_IMPL(add) { dns_keytable_find(keytable, str2name("two.com"), &keynode), ISC_R_SUCCESS); assert_int_equal(dns_keynode_initial(keynode), true); - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); /* * Add a different managed key for two.com, marking it as a @@ -333,7 +333,7 @@ ISC_LOOP_TEST_IMPL(add) { dns_keytable_find(keytable, str2name("two.com"), &keynode), ISC_R_SUCCESS); assert_int_equal(dns_keynode_initial(keynode), true); - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); /* * Add a normal key to a name that has a null key. The null key node @@ -351,7 +351,7 @@ ISC_LOOP_TEST_IMPL(add) { dns_keytable_find(keytable, str2name("null.example"), &keynode), ISC_R_SUCCESS); assert_ptr_equal(keynode, null_keynode); /* should be the same node */ - dns_keytable_detachkeynode(keytable, &null_keynode); + dns_keynode_detach(&null_keynode); /* * Try to add a null key to a name that already has a key. It's @@ -366,9 +366,9 @@ ISC_LOOP_TEST_IMPL(add) { &null_keynode), ISC_R_SUCCESS); assert_ptr_equal(keynode, null_keynode); - dns_keytable_detachkeynode(keytable, &null_keynode); + dns_keynode_detach(&null_keynode); - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); destroy_tables(); isc_loopmgr_shutdown(loopmgr); @@ -500,11 +500,11 @@ ISC_LOOP_TEST_IMPL(find) { assert_int_equal( dns_keytable_find(keytable, str2name("example.com"), &keynode), ISC_R_SUCCESS); - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); assert_int_equal( dns_keytable_find(keytable, str2name("null.example"), &keynode), ISC_R_SUCCESS); - dns_keytable_detachkeynode(keytable, &keynode); + dns_keynode_detach(&keynode); /* * dns_keytable_finddeepestmatch() allows partial match. Also match @@ -605,8 +605,8 @@ ISC_LOOP_TEST_IMPL(nta) { result = dns_test_makeview("view", false, &myview); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_view_initsecroots(myview, mctx); - assert_int_equal(result, ISC_R_SUCCESS); + dns_view_initsecroots(myview); + result = dns_view_getsecroots(myview, &keytable); assert_int_equal(result, ISC_R_SUCCESS);