diff --git a/fuzz/dns_qp.c b/fuzz/dns_qp.c index 08a6c4d662..f0b70d260c 100644 --- a/fuzz/dns_qp.c +++ b/fuzz/dns_qp.c @@ -104,12 +104,13 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { for (size_t i = 0; i < ARRAY_SIZE(item); i++) { size_t len = isc_random_uniform(100) + 16; - item[i].len = len; - for (size_t off = 0; off < len; off++) { + item[i].len = len + 1; + item[i].key[0] = 0; + for (size_t off = 1; off < len; off++) { item[i].key[off] = random_byte(); } - memmove(item[i].ascii, item[i].key, len); - qp_test_keytoascii(item[i].ascii, len); + memmove(item[i].ascii, item[i].key, item[i].len); + qp_test_keytoascii(item[i].ascii, item[i].len); } return 0; diff --git a/fuzz/dns_qpkey_name.c b/fuzz/dns_qpkey_name.c index c362a4b12d..c66eba8ea8 100644 --- a/fuzz/dns_qpkey_name.c +++ b/fuzz/dns_qpkey_name.c @@ -43,6 +43,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { dns_name_t *namein, *nameout, *namecmp; isc_buffer_t buf; dns_qpkey_t key, cmp; + dns_namespace_t space; namein = dns_fixedname_initname(&fixedin); nameout = dns_fixedname_initname(&fixedout); @@ -55,15 +56,17 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { CHECK(dns_name_fromwire(namein, &buf, DNS_DECOMPRESS_NEVER, NULL)); /* verify round-trip conversion of first name */ - size_t keylen = dns_qpkey_fromname(key, namein); - dns_qpkey_toname(key, keylen, nameout); + size_t keylen = dns_qpkey_fromname(key, namein, DNS_DBNAMESPACE_NORMAL); + dns_qpkey_toname(key, keylen, nameout, &space); assert(dns_name_equal(namein, nameout)); + assert(space == DNS_DBNAMESPACE_NORMAL); /* is there a second name? */ CHECK(dns_name_fromwire(namecmp, &buf, DNS_DECOMPRESS_NEVER, NULL)); - size_t cmplen = dns_qpkey_fromname(cmp, namecmp); + size_t cmplen = dns_qpkey_fromname(cmp, namecmp, + DNS_DBNAMESPACE_NORMAL); size_t len = ISC_MIN(keylen, cmplen); int namerel = dns_name_compare(namein, namecmp); @@ -72,6 +75,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { assert((namerel < 0) == (keyrel < 0)); assert((namerel == 0) == (keyrel == 0)); assert((namerel > 0) == (keyrel > 0)); + assert(space == DNS_DBNAMESPACE_NORMAL); return 0; } diff --git a/lib/dns/forward.c b/lib/dns/forward.c index b46111fb13..aa2ba37016 100644 --- a/lib/dns/forward.c +++ b/lib/dns/forward.c @@ -163,7 +163,8 @@ dns_fwdtable_find(dns_fwdtable_t *fwdtable, const dns_name_t *name, REQUIRE(VALID_FWDTABLE(fwdtable)); dns_qpmulti_query(fwdtable->table, &qpr); - result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, &pval, NULL); + result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL, + NULL, &pval, NULL); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { dns_forwarders_t *fwdrs = pval; *forwardersp = fwdrs; @@ -233,7 +234,7 @@ 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); + return dns_qpkey_fromname(key, &fwd->name, DNS_DBNAMESPACE_NORMAL); } static void diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index e53f8a92e8..f04253dff7 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -233,15 +233,15 @@ struct dns_dbonupdatelistener { }; /*% - * Used in composite databases such as RBTDB to indicate whether a node - * exists in a specal tree for NSEC or NSEC3. + * Used in QP keys to indicate whether a node is in a special namespace + * such as NSEC or NSEC3. These values will be mapped to characters at + * the beginning of the key, converting them to '0', '1', and '2'. */ -enum { - DNS_DB_NSEC_NORMAL = 0, /* in main tree */ - DNS_DB_NSEC_HAS_NSEC = 1, /* also has node in nsec tree */ - DNS_DB_NSEC_NSEC = 2, /* in nsec tree */ - DNS_DB_NSEC_NSEC3 = 3 /* in nsec3 tree */ -}; +typedef enum { + DNS_DBNAMESPACE_NORMAL = 0, /* regular namespace */ + DNS_DBNAMESPACE_NSEC = 1, /* nsec namespace */ + DNS_DBNAMESPACE_NSEC3 = 2, /* nsec3 namespace */ +} dns_namespace_t; /*@{*/ /*% diff --git a/lib/dns/include/dns/qp.h b/lib/dns/include/dns/qp.h index bbac5ca6fb..456cf635a2 100644 --- a/lib/dns/include/dns/qp.h +++ b/lib/dns/include/dns/qp.h @@ -86,6 +86,7 @@ #include +#include #include #include @@ -181,8 +182,11 @@ typedef union dns_qpreadable { * A domain name can be up to 255 bytes. When converted to a key, each * character in the name corresponds to one byte in the key if it is a * common hostname character; otherwise unusual characters are escaped, - * using two bytes in the key. So we allow keys to be up to 512 bytes. - * (The actual max is (255 - 5) * 2 + 6 == 506) + * using two bytes in the key. Because the maximum label length is 63 + * characters, the actual max is (255 - 5) * 2 + 6 == 506. Then, we need + * one more byte to prepend the namespace. + * + * Note: this gives us 5 bytes available space to store more data. */ #define DNS_QP_MAXKEY 512 @@ -470,9 +474,10 @@ dns_qpmulti_memusage(dns_qpmulti_t *multi); */ size_t -dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name); +dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name, + dns_namespace_t space); /*%< - * Convert a DNS name into a trie lookup key. + * Convert a DNS name into a trie lookup key in the right namespace. * * Requires: * \li `name` is a pointer to a valid `dns_name_t` @@ -485,10 +490,13 @@ dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name); */ void -dns_qpkey_toname(const dns_qpkey_t key, size_t keylen, dns_name_t *name); +dns_qpkey_toname(const dns_qpkey_t key, size_t keylen, dns_name_t *name, + dns_namespace_t *space); /*%< * Convert a trie lookup key back into a DNS name. * + * 'space' stores whether the key is for a normal name, or denial of existence. + * * Requires: * \li `name` is a pointer to a valid `dns_name_t` * \li `name->buffer` is not NULL @@ -514,10 +522,10 @@ dns_qp_getkey(dns_qpreadable_t qpr, const dns_qpkey_t search_key, */ isc_result_t -dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, void **pval_r, - uint32_t *ival_r); +dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, + dns_namespace_t space, void **pval_r, uint32_t *ival_r); /*%< - * Find a leaf in a qp-trie that matches the given DNS name + * Find a leaf in a qp-trie that matches the given DNS name, and namespace. * * The leaf values are assigned to whichever of `*pval_r` and `*ival_r` * are not null, unless the return value is ISC_R_NOTFOUND. @@ -533,11 +541,11 @@ dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, void **pval_r, isc_result_t dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name, - dns_name_t *foundname, dns_qpiter_t *iter, dns_qpchain_t *chain, - void **pval_r, uint32_t *ival_r); + dns_namespace_t space, dns_name_t *foundname, dns_qpiter_t *iter, + dns_qpchain_t *chain, void **pval_r, uint32_t *ival_r); /*%< * Look up a leaf in a qp-trie that is equal to, or an ancestor domain of, - * 'name'. + * 'name' in the namespace 'space'. * * If 'foundname' is not NULL, it will be updated to contain the name * that was found (if any). The return code, ISC_R_SUCCESS or @@ -609,10 +617,10 @@ dns_qp_deletekey(dns_qp_t *qp, const dns_qpkey_t key, size_t keylen, */ isc_result_t -dns_qp_deletename(dns_qp_t *qp, const dns_name_t *name, void **pval_r, - uint32_t *ival_r); +dns_qp_deletename(dns_qp_t *qp, const dns_name_t *name, dns_namespace_t space, + void **pval_r, uint32_t *ival_r); /*%< - * Delete a leaf from a qp-trie that matches the given DNS name + * Delete a leaf from a qp-trie that matches the given DNS name, and namespace. * * The leaf values are assigned to whichever of `*pval_r` and `*ival_r` * are not null, unless the return value is ISC_R_NOTFOUND. diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c index 280740b991..018b4f73e0 100644 --- a/lib/dns/keytable.c +++ b/lib/dns/keytable.c @@ -273,7 +273,8 @@ delete_ds(dns_qp_t *qp, dns_keytable_t *keytable, dns_keynode_t *knode, } } - result = dns_qp_deletename(qp, &knode->name, &pval, NULL); + result = dns_qp_deletename(qp, &knode->name, DNS_DBNAMESPACE_NORMAL, + &pval, NULL); INSIST(result == ISC_R_SUCCESS); INSIST(pval == knode); @@ -343,7 +344,8 @@ insert(dns_keytable_t *keytable, bool managed, bool initial, dns_qpmulti_write(keytable->table, &qp); - result = dns_qp_getname(qp, keyname, &pval, NULL); + result = dns_qp_getname(qp, keyname, DNS_DBNAMESPACE_NORMAL, &pval, + NULL); if (result != ISC_R_SUCCESS) { /* * There was no match for "keyname" in "keytable" yet, so one @@ -400,7 +402,8 @@ dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname, REQUIRE(keyname != NULL); dns_qpmulti_write(keytable->table, &qp); - result = dns_qp_deletename(qp, keyname, &pval, NULL); + result = dns_qp_deletename(qp, keyname, DNS_DBNAMESPACE_NORMAL, &pval, + NULL); if (result == ISC_R_SUCCESS) { dns_keynode_t *n = pval; if (callback != NULL) { @@ -430,7 +433,8 @@ dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname, REQUIRE(dnskey != NULL); dns_qpmulti_write(keytable->table, &qp); - result = dns_qp_getname(qp, keyname, &pval, NULL); + result = dns_qp_getname(qp, keyname, DNS_DBNAMESPACE_NORMAL, &pval, + NULL); if (result != ISC_R_SUCCESS) { goto finish; } @@ -479,7 +483,8 @@ dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname, REQUIRE(keynodep != NULL && *keynodep == NULL); dns_qpmulti_query(keytable->table, &qpr); - result = dns_qp_getname(&qpr, keyname, &pval, NULL); + result = dns_qp_getname(&qpr, keyname, DNS_DBNAMESPACE_NORMAL, &pval, + NULL); if (result == ISC_R_SUCCESS) { dns_keynode_t *knode = pval; dns_keynode_attach(knode, keynodep); @@ -506,7 +511,8 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name, REQUIRE(foundname != NULL); dns_qpmulti_query(keytable->table, &qpr); - result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, &pval, NULL); + result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL, + NULL, &pval, NULL); keynode = pval; if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { @@ -535,7 +541,8 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name, REQUIRE(wantdnssecp != NULL); dns_qpmulti_query(keytable->table, &qpr); - result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, &pval, NULL); + result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL, + NULL, &pval, NULL); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { keynode = pval; if (foundname != NULL) { @@ -830,7 +837,7 @@ 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); + return dns_qpkey_fromname(key, &keynode->name, DNS_DBNAMESPACE_NORMAL); } static void diff --git a/lib/dns/nametree.c b/lib/dns/nametree.c index 3084c25ece..7d67bd0c1c 100644 --- a/lib/dns/nametree.c +++ b/lib/dns/nametree.c @@ -164,14 +164,16 @@ dns_nametree_add(dns_nametree_t *nametree, const dns_name_t *name, case DNS_NAMETREE_COUNT: new = newnode(nametree->mctx, name); new->set = true; - result = dns_qp_deletename(qp, name, (void **)&old, &count); + result = dns_qp_deletename(qp, name, DNS_DBNAMESPACE_NORMAL, + (void **)&old, &count); if (result == ISC_R_SUCCESS) { count += 1; } break; case DNS_NAMETREE_BITS: - result = dns_qp_getname(qp, name, (void **)&old, NULL); + result = dns_qp_getname(qp, name, DNS_DBNAMESPACE_NORMAL, + (void **)&old, NULL); if (result == ISC_R_SUCCESS && matchbit(old->bits, value)) { goto out; } @@ -187,7 +189,8 @@ dns_nametree_add(dns_nametree_t *nametree, const dns_name_t *name, new->bits = isc_mem_cget(nametree->mctx, size, sizeof(char)); if (result == ISC_R_SUCCESS) { memmove(new->bits, old->bits, old->bits[0]); - result = dns_qp_deletename(qp, name, NULL, NULL); + result = dns_qp_deletename( + qp, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL); INSIST(result == ISC_R_SUCCESS); } @@ -222,7 +225,8 @@ dns_nametree_delete(dns_nametree_t *nametree, const dns_name_t *name) { REQUIRE(name != NULL); dns_qpmulti_write(nametree->table, &qp); - result = dns_qp_deletename(qp, name, (void **)&old, &count); + result = dns_qp_deletename(qp, name, DNS_DBNAMESPACE_NORMAL, + (void **)&old, &count); switch (nametree->type) { case DNS_NAMETREE_BOOL: case DNS_NAMETREE_BITS: @@ -258,7 +262,8 @@ dns_nametree_find(dns_nametree_t *nametree, const dns_name_t *name, REQUIRE(ntnodep != NULL && *ntnodep == NULL); dns_qpmulti_query(nametree->table, &qpr); - result = dns_qp_getname(&qpr, name, (void **)&node, NULL); + result = dns_qp_getname(&qpr, name, DNS_DBNAMESPACE_NORMAL, + (void **)&node, NULL); if (result == ISC_R_SUCCESS) { dns_ntnode_attach(node, ntnodep); } @@ -278,8 +283,8 @@ dns_nametree_covered(dns_nametree_t *nametree, const dns_name_t *name, REQUIRE(VALID_NAMETREE(nametree)); dns_qpmulti_query(nametree->table, &qpr); - result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, (void **)&node, - NULL); + result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL, + NULL, (void **)&node, NULL); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { if (found != NULL) { dns_name_copy(&node->name, found); @@ -319,7 +324,7 @@ static size_t qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval, uint32_t ival ISC_ATTR_UNUSED) { dns_ntnode_t *ntnode = pval; - return dns_qpkey_fromname(key, &ntnode->name); + return dns_qpkey_fromname(key, &ntnode->name, DNS_DBNAMESPACE_NORMAL); } static void diff --git a/lib/dns/nta.c b/lib/dns/nta.c index 0a020821b8..39f7de3456 100644 --- a/lib/dns/nta.c +++ b/lib/dns/nta.c @@ -316,7 +316,8 @@ dns_ntatable_add(dns_ntatable_t *ntatable, const dns_name_t *name, bool force, result = dns_qp_insert(qp, nta, 0); switch (result) { case ISC_R_EXISTS: - result = dns_qp_getname(qp, &nta->name, &pval, NULL); + result = dns_qp_getname(qp, &nta->name, DNS_DBNAMESPACE_NORMAL, + &pval, NULL); if (result == ISC_R_SUCCESS) { /* * an NTA already existed: throw away the @@ -355,7 +356,8 @@ dns_ntatable_delete(dns_ntatable_t *ntatable, const dns_name_t *name) { REQUIRE(name != NULL); dns_qpmulti_write(ntatable->table, &qp); - result = dns_qp_deletename(qp, name, &pval, NULL); + result = dns_qp_deletename(qp, name, DNS_DBNAMESPACE_NORMAL, &pval, + NULL); if (result == ISC_R_SUCCESS) { dns__nta_t *n = pval; dns__nta_shutdown(n); @@ -379,7 +381,8 @@ delete_expired(void *arg) { RWLOCK(&ntatable->rwlock, isc_rwlocktype_write); dns_qpmulti_write(ntatable->table, &qp); - result = dns_qp_getname(qp, &nta->name, &pval, NULL); + result = dns_qp_getname(qp, &nta->name, DNS_DBNAMESPACE_NORMAL, &pval, + NULL); if (result == ISC_R_SUCCESS && ((dns__nta_t *)pval)->expiry == nta->expiry && !nta->shuttingdown) { @@ -387,7 +390,8 @@ delete_expired(void *arg) { dns_name_format(&nta->name, nb, sizeof(nb)); isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_NTA, ISC_LOG_INFO, "deleting expired NTA at %s", nb); - dns_qp_deletename(qp, &nta->name, NULL, NULL); + dns_qp_deletename(qp, &nta->name, DNS_DBNAMESPACE_NORMAL, NULL, + NULL); dns__nta_shutdown(nta); dns__nta_unref(nta); } @@ -412,7 +416,8 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now, RWLOCK(&ntatable->rwlock, isc_rwlocktype_read); dns_qpmulti_query(ntatable->table, &qpr); - result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, &pval, NULL); + result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL, + NULL, &pval, NULL); nta = pval; switch (result) { @@ -649,7 +654,7 @@ static size_t qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval, uint32_t ival ISC_ATTR_UNUSED) { dns__nta_t *nta = pval; - return dns_qpkey_fromname(key, &nta->name); + return dns_qpkey_fromname(key, &nta->name, DNS_DBNAMESPACE_NORMAL); } static void diff --git a/lib/dns/qp.c b/lib/dns/qp.c index e0b709338b..6cd9938165 100644 --- a/lib/dns/qp.c +++ b/lib/dns/qp.c @@ -115,6 +115,16 @@ ISC_REFCOUNT_STATIC_DECL(dns_qpmulti); * converting DNS names to trie keys */ +/* + * Convert the namespace value. We map namespace values to numerical + * digits so they can be represented in a single byte in the QP key; + * thus namespace 0 becomes '0', etc. + */ +#define ENCODE_NAMESPACE(c) dns_qp_bits_for_byte[(c) + (uint8_t)'0'] +#define DECODE_NAMESPACE(c) dns_qp_byte_for_bit[(c)] - (uint8_t)'0' + +#define NAME_OFFSET 1 + /* * Number of distinct byte values, i.e. 256 */ @@ -228,18 +238,22 @@ dns__qp_shutdown(void) { * dot in a zone file). */ size_t -dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name) { +dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name, + dns_namespace_t space) { REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC)); dns_offsets_t offsets; size_t labels = dns_name_offsets(name, offsets); + size_t len = 0; + /* namespace */ + key[len++] = ENCODE_NAMESPACE(space); + /* name */ if (labels == 0) { - key[0] = SHIFT_NOBYTE; - return 0; + key[len] = SHIFT_NOBYTE; + return len; } - size_t len = 0; size_t label = labels; while (label-- > 0) { const uint8_t *ldata = name->ndata + offsets[label]; @@ -261,22 +275,26 @@ dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name) { } void -dns_qpkey_toname(const dns_qpkey_t key, size_t keylen, dns_name_t *name) { +dns_qpkey_toname(const dns_qpkey_t key, size_t keylen, dns_name_t *name, + dns_namespace_t *space) { size_t locs[DNS_NAME_MAXLABELS]; size_t loc = 0; - size_t offset; + size_t offset = 0; REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC)); REQUIRE(name->buffer != NULL); + REQUIRE(keylen > 0); dns_name_reset(name); - if (keylen == 0) { + SET_IF_NOT_NULL(space, DECODE_NAMESPACE(key[offset++])); + + if (keylen == NAME_OFFSET) { return; } /* Scan the key looking for label boundaries */ - for (offset = 0; offset <= keylen; offset++) { + for (; offset <= keylen; offset++) { INSIST(key[offset] >= SHIFT_NOBYTE && key[offset] < SHIFT_OFFSET); INSIST(loc < DNS_NAME_MAXLABELS); @@ -287,7 +305,7 @@ dns_qpkey_toname(const dns_qpkey_t key, size_t keylen, dns_name_t *name) { goto scanned; } locs[loc++] = offset + 1; - } else if (offset == 0) { + } else if (offset == NAME_OFFSET) { /* This happens for a relative name */ locs[loc++] = offset; } @@ -330,7 +348,7 @@ scanned: } /* Add a root label for absolute names */ - if (key[0] == SHIFT_NOBYTE) { + if (key[NAME_OFFSET] == SHIFT_NOBYTE) { name->attributes.absolute = true; isc_buffer_putuint8(name->buffer, 0); name->length++; @@ -1826,10 +1844,10 @@ dns_qp_deletekey(dns_qp_t *qp, const dns_qpkey_t search_key, } isc_result_t -dns_qp_deletename(dns_qp_t *qp, const dns_name_t *name, void **pval_r, - uint32_t *ival_r) { +dns_qp_deletename(dns_qp_t *qp, const dns_name_t *name, dns_namespace_t space, + void **pval_r, uint32_t *ival_r) { dns_qpkey_t key; - size_t keylen = dns_qpkey_fromname(key, name); + size_t keylen = dns_qpkey_fromname(key, name, space); return dns_qp_deletekey(qp, key, keylen, pval_r, ival_r); } @@ -1847,7 +1865,7 @@ maybe_set_name(dns_qpreader_t *qp, dns_qpnode_t *node, dns_name_t *name) { dns_name_reset(name); len = leaf_qpkey(qp, node, key); - dns_qpkey_toname(key, len, name); + dns_qpkey_toname(key, len, name, NULL); } void @@ -2089,10 +2107,10 @@ dns_qp_getkey(dns_qpreadable_t qpr, const dns_qpkey_t search_key, } isc_result_t -dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, void **pval_r, - uint32_t *ival_r) { +dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, + dns_namespace_t space, void **pval_r, uint32_t *ival_r) { dns_qpkey_t key; - size_t keylen = dns_qpkey_fromname(key, name); + size_t keylen = dns_qpkey_fromname(key, name, space); return dns_qp_getkey(qpr, key, keylen, pval_r, ival_r); } @@ -2268,8 +2286,8 @@ fix_chain(dns_qpchain_t *chain, size_t offset) { isc_result_t dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name, - dns_name_t *foundname, dns_qpiter_t *iter, dns_qpchain_t *chain, - void **pval_r, uint32_t *ival_r) { + dns_namespace_t space, dns_name_t *foundname, dns_qpiter_t *iter, + dns_qpchain_t *chain, void **pval_r, uint32_t *ival_r) { dns_qpreader_t *qp = dns_qpreader(qpr); dns_qpkey_t search, found; size_t searchlen, foundlen; @@ -2284,7 +2302,7 @@ dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name, REQUIRE(QP_VALID(qp)); REQUIRE(foundname == NULL || ISC_MAGIC_VALID(name, DNS_NAME_MAGIC)); - searchlen = dns_qpkey_fromname(search, name); + searchlen = dns_qpkey_fromname(search, name, space); if (chain == NULL) { chain = &oc; diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index 5bc516728a..7e685318b8 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -150,7 +150,8 @@ struct qpcnode { uint8_t : 0; unsigned int delegating : 1; - unsigned int nsec : 2; /*%< range is 0..3 */ + unsigned int nspace : 2; /*%< range is 0..3 */ + unsigned int havensec : 1; uint8_t : 0; uint16_t locknum; @@ -357,7 +358,7 @@ static size_t qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval, uint32_t ival ISC_ATTR_UNUSED) { qpcnode_t *data = pval; - return dns_qpkey_fromname(key, &data->name); + return dns_qpkey_fromname(key, &data->name, data->nspace); } static void @@ -602,26 +603,31 @@ delete_node(qpcache_t *qpdb, qpcnode_t *node) { printname, node->locknum); } - switch (node->nsec) { - case DNS_DB_NSEC_HAS_NSEC: - /* - * Delete the corresponding node from the auxiliary NSEC - * tree before deleting from the main tree. - */ - result = dns_qp_deletename(qpdb->nsec, &node->name, NULL, NULL); - if (result != ISC_R_SUCCESS) { - isc_log_write(DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_CACHE, ISC_LOG_WARNING, - "delete_node(): " - "dns_qp_deletename: %s", - isc_result_totext(result)); + switch (node->nspace) { + case DNS_DBNAMESPACE_NORMAL: + if (node->havensec) { + /* + * Delete the corresponding node from the auxiliary NSEC + * tree before deleting from the main tree. + */ + result = dns_qp_deletename(qpdb->nsec, &node->name, + DNS_DBNAMESPACE_NSEC, NULL, + NULL); + if (result != ISC_R_SUCCESS) { + isc_log_write(DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, + ISC_LOG_WARNING, + "delete_node(): " + "dns_qp_deletename: %s", + isc_result_totext(result)); + } } - /* FALLTHROUGH */ - case DNS_DB_NSEC_NORMAL: - result = dns_qp_deletename(qpdb->tree, &node->name, NULL, NULL); + result = dns_qp_deletename(qpdb->tree, &node->name, + node->nspace, NULL, NULL); break; - case DNS_DB_NSEC_NSEC: - result = dns_qp_deletename(qpdb->nsec, &node->name, NULL, NULL); + case DNS_DBNAMESPACE_NSEC: + result = dns_qp_deletename(qpdb->nsec, &node->name, + node->nspace, NULL, NULL); break; } if (result != ISC_R_SUCCESS) { @@ -1389,8 +1395,8 @@ find_coveringnsec(qpc_search_t *search, const dns_name_t *name, /* * Look for the node in the auxilary tree. */ - result = dns_qp_lookup(search->qpdb->nsec, name, NULL, &iter, NULL, - (void **)&node, NULL); + result = dns_qp_lookup(search->qpdb->nsec, name, DNS_DBNAMESPACE_NSEC, + NULL, &iter, NULL, (void **)&node, NULL); if (result != DNS_R_PARTIALMATCH) { return ISC_R_NOTFOUND; } @@ -1410,8 +1416,8 @@ find_coveringnsec(qpc_search_t *search, const dns_name_t *name, * Lookup the predecessor in the main tree. */ node = NULL; - result = dns_qp_getname(search->qpdb->tree, predecessor, (void **)&node, - NULL); + result = dns_qp_getname(search->qpdb->tree, predecessor, + DNS_DBNAMESPACE_NORMAL, (void **)&node, NULL); if (result != ISC_R_SUCCESS) { return result; } @@ -1518,8 +1524,8 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, /* * Search down from the root of the tree. */ - result = dns_qp_lookup(search.qpdb->tree, name, NULL, NULL, - &search.chain, (void **)&node, NULL); + result = dns_qp_lookup(search.qpdb->tree, name, DNS_DBNAMESPACE_NORMAL, + NULL, NULL, &search.chain, (void **)&node, NULL); if (result != ISC_R_NOTFOUND && foundname != NULL) { dns_name_copy(&node->name, foundname); } @@ -1958,8 +1964,8 @@ qpcache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options, /* * Search down from the root of the tree. */ - result = dns_qp_lookup(search.qpdb->tree, name, NULL, NULL, - &search.chain, (void **)&node, NULL); + result = dns_qp_lookup(search.qpdb->tree, name, DNS_DBNAMESPACE_NORMAL, + NULL, NULL, &search.chain, (void **)&node, NULL); switch (result) { case ISC_R_SUCCESS: @@ -2321,10 +2327,11 @@ reactivate_node(qpcache_t *qpdb, qpcnode_t *node, } static qpcnode_t * -new_qpcnode(qpcache_t *qpdb, const dns_name_t *name) { +new_qpcnode(qpcache_t *qpdb, const dns_name_t *name, dns_namespace_t nspace) { qpcnode_t *newdata = isc_mem_get(qpdb->common.mctx, sizeof(*newdata)); *newdata = (qpcnode_t){ .name = DNS_NAME_INITEMPTY, + .nspace = nspace, .references = ISC_REFCOUNT_INITIALIZER(1), .locknum = isc_random_uniform(qpdb->buckets_count), }; @@ -2346,9 +2353,10 @@ qpcache_findnode(dns_db_t *db, const dns_name_t *name, bool create, qpcnode_t *node = NULL; isc_result_t result; isc_rwlocktype_t tlocktype = isc_rwlocktype_none; + dns_namespace_t nspace = DNS_DBNAMESPACE_NORMAL; TREE_RDLOCK(&qpdb->tree_lock, &tlocktype); - result = dns_qp_getname(qpdb->tree, name, (void **)&node, NULL); + result = dns_qp_getname(qpdb->tree, name, nspace, (void **)&node, NULL); if (result != ISC_R_SUCCESS) { if (!create) { goto unlock; @@ -2357,9 +2365,10 @@ qpcache_findnode(dns_db_t *db, const dns_name_t *name, bool create, * Try to upgrade the lock and if that fails unlock then relock. */ TREE_FORCEUPGRADE(&qpdb->tree_lock, &tlocktype); - result = dns_qp_getname(qpdb->tree, name, (void **)&node, NULL); + result = dns_qp_getname(qpdb->tree, name, nspace, + (void **)&node, NULL); if (result != ISC_R_SUCCESS) { - node = new_qpcnode(qpdb, name); + node = new_qpcnode(qpdb, name, nspace); result = dns_qp_insert(qpdb->tree, node, 0); INSIST(result == ISC_R_SUCCESS); qpcnode_unref(node); @@ -3007,7 +3016,7 @@ qpcache_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, */ if (rdataset->type == dns_rdatatype_nsec) { NODE_RDLOCK(nlock, &nlocktype); - if (qpnode->nsec != DNS_DB_NSEC_HAS_NSEC) { + if (!qpnode->havensec) { newnsec = true; } NODE_UNLOCK(nlock, &nlocktype); @@ -3033,20 +3042,20 @@ qpcache_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, expire_ttl_headers(qpdb, qpnode->locknum, &nlocktype, &tlocktype, now DNS__DB_FLARG_PASS); - if (newnsec && qpnode->nsec != DNS_DB_NSEC_HAS_NSEC) { + if (newnsec && !qpnode->havensec) { qpcnode_t *nsecnode = NULL; - result = dns_qp_getname(qpdb->nsec, name, (void **)&nsecnode, - NULL); + result = dns_qp_getname(qpdb->nsec, name, DNS_DBNAMESPACE_NSEC, + (void **)&nsecnode, NULL); if (result != ISC_R_SUCCESS) { INSIST(nsecnode == NULL); - nsecnode = new_qpcnode(qpdb, name); - nsecnode->nsec = DNS_DB_NSEC_NSEC; + nsecnode = new_qpcnode(qpdb, name, + DNS_DBNAMESPACE_NSEC); result = dns_qp_insert(qpdb->nsec, nsecnode, 0); INSIST(result == ISC_R_SUCCESS); qpcnode_detach(&nsecnode); } - qpnode->nsec = DNS_DB_NSEC_HAS_NSEC; + qpnode->havensec = true; } result = add(qpdb, qpnode, name, newheader, options, addedrdataset, now, @@ -3418,7 +3427,8 @@ resume_iteration(qpc_dbit_t *qpdbiter, bool continuing) { */ if (continuing && qpdbiter->node != NULL) { isc_result_t result; - result = dns_qp_lookup(qpdb->tree, qpdbiter->name, NULL, + result = dns_qp_lookup(qpdb->tree, qpdbiter->name, + DNS_DBNAMESPACE_NORMAL, NULL, &qpdbiter->iter, NULL, NULL, NULL); INSIST(result == ISC_R_SUCCESS); } @@ -3546,8 +3556,9 @@ dbiterator_seek(dns_dbiterator_t *iterator, dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS); - result = dns_qp_lookup(qpdb->tree, name, NULL, &qpdbiter->iter, NULL, - (void **)&qpdbiter->node, NULL); + result = dns_qp_lookup(qpdb->tree, name, DNS_DBNAMESPACE_NORMAL, NULL, + &qpdbiter->iter, NULL, (void **)&qpdbiter->node, + NULL); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { dns_name_copy(&qpdbiter->node->name, qpdbiter->name); diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index 39b0caf2f7..51c96a8c90 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -91,9 +91,12 @@ #define QPDB_ATTR_LOADED 0x01 #define QPDB_ATTR_LOADING 0x02 -#define QPDBITER_NSEC3_ORIGIN_NODE(qpdb, iterator) \ - ((iterator)->current == &(iterator)->nsec3iter && \ - (iterator)->node == (qpdb)->nsec3_origin) +#define QPDBITER_ORIGIN_NODE(qpdb, iterator) \ + ((iterator)->node == (qpdb)->origin) +#define QPDBITER_NSEC_ORIGIN_NODE(qpdb, iterator) \ + ((iterator)->node == (qpdb)->nsec_origin) +#define QPDBITER_NSEC3_ORIGIN_NODE(qpdb, iterator) \ + ((iterator)->node == (qpdb)->nsec3_origin) /*% * Note that "impmagic" is not the first four bytes of the struct, so @@ -200,7 +203,8 @@ struct qpznode { isc_refcount_t erefs; uint16_t locknum; - atomic_uint_fast8_t nsec; + _Atomic(dns_namespace_t) nspace; + atomic_bool havensec; atomic_bool wild; atomic_bool delegating; atomic_bool dirty; @@ -231,6 +235,7 @@ struct qpzonedb { isc_refcount_t references; qpznode_t *origin; + qpznode_t *nsec_origin; qpznode_t *nsec3_origin; isc_stats_t *gluecachestats; /* Locked by lock. */ @@ -248,9 +253,7 @@ struct qpzonedb { qpz_heap_t *heap; /* Resigning heap */ - dns_qpmulti_t *tree; /* Main QP trie for data storage */ - dns_qpmulti_t *nsec; /* NSEC nodes only */ - dns_qpmulti_t *nsec3; /* NSEC3 nodes only */ + dns_qpmulti_t *tree; /* QP trie for data storage */ }; #ifdef DNS_DB_NODETRACE @@ -291,8 +294,6 @@ typedef struct { typedef struct { dns_db_t *db; dns_qp_t *tree; - dns_qp_t *nsec; - dns_qp_t *nsec3; } qpz_load_t; static dns_dbmethods_t qpdb_zonemethods; @@ -350,9 +351,7 @@ typedef struct qpdb_rdatasetiter { * or DNS_DB_NONSEC3, will transparently move between the last node of the * "regular" QP trie and the root node of the NSEC3 QP trie of the database * in question, as if the latter was a successor to the former in lexical - * order. The "current" field always holds the address of either - * "mainiter" or "nsec3iter", depending on which trie is being traversed - * at given time. + * order. The "current" field always holds the address of either "iter". */ static void dbiterator_destroy(dns_dbiterator_t **iteratorp DNS__DB_FLARG); @@ -384,11 +383,8 @@ static dns_dbiteratormethods_t dbiterator_methods = { typedef struct qpdb_dbiterator { dns_dbiterator_t common; isc_result_t result; - dns_qpsnap_t *tsnap; /* main tree snapshot */ - dns_qpsnap_t *nsnap; /* nsec3 tree snapshot */ - dns_qpiter_t *current; /* current iterator, which is one of: */ - dns_qpiter_t mainiter; /* - main tree iterator */ - dns_qpiter_t nsec3iter; /* - nsec3 tree iterator */ + dns_qpsnap_t *snap; /* tree snapshot */ + dns_qpiter_t iter; /* tree iterator */ qpznode_t *node; enum { full, nonsec3, nsec3only } nsec3mode; } qpdb_dbiterator_t; @@ -580,8 +576,6 @@ qpzone_destroy(qpzonedb_t *qpdb) { sizeof(*qpdb->current_version)); dns_qpmulti_destroy(&qpdb->tree); - dns_qpmulti_destroy(&qpdb->nsec); - dns_qpmulti_destroy(&qpdb->nsec3); char buf[DNS_NAME_FORMATSIZE]; if (dns_name_dynamic(&qpdb->common.origin)) { @@ -602,6 +596,9 @@ qpdb_destroy(dns_db_t *arg) { if (qpdb->origin != NULL) { qpznode_detach(&qpdb->origin); } + if (qpdb->nsec_origin != NULL) { + qpznode_detach(&qpdb->nsec_origin); + } if (qpdb->nsec3_origin != NULL) { qpznode_detach(&qpdb->nsec3_origin); } @@ -665,10 +662,11 @@ qpz_heap_destroy(qpz_heap_t *qpheap) { } static qpznode_t * -new_qpznode(qpzonedb_t *qpdb, const dns_name_t *name) { +new_qpznode(qpzonedb_t *qpdb, const dns_name_t *name, dns_namespace_t nspace) { qpznode_t *newdata = isc_mem_get(qpdb->common.mctx, sizeof(*newdata)); *newdata = (qpznode_t){ .name = DNS_NAME_INITEMPTY, + .nspace = nspace, .heap = qpdb->heap, .references = ISC_REFCOUNT_INITIALIZER(1), .locknum = qpzone_get_locknum(), @@ -749,8 +747,6 @@ dns__qpzone_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, dns_name_dup(origin, mctx, &qpdb->common.origin); dns_qpmulti_create(mctx, &qpmethods, qpdb, &qpdb->tree); - dns_qpmulti_create(mctx, &qpmethods, qpdb, &qpdb->nsec); - dns_qpmulti_create(mctx, &qpmethods, qpdb, &qpdb->nsec3); /* * Version initialization. @@ -758,6 +754,8 @@ dns__qpzone_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, qpdb->current_version = allocate_version(mctx, 1, 1, false); qpdb->current_version->qpdb = qpdb; + dns_qpmulti_write(qpdb->tree, &qp); + /* * In order to set the node callback bit correctly in zone databases, * we need to know if the node has the origin name of the zone. @@ -769,25 +767,32 @@ dns__qpzone_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, * We now explicitly create a node for the zone's origin, and then * we simply remember the node data's address. */ + qpdb->origin = new_qpznode(qpdb, &qpdb->common.origin, + DNS_DBNAMESPACE_NORMAL); - dns_qpmulti_write(qpdb->tree, &qp); - qpdb->origin = new_qpznode(qpdb, &qpdb->common.origin); result = dns_qp_insert(qp, qpdb->origin, 0); INSIST(result == ISC_R_SUCCESS); - qpdb->origin->nsec = DNS_DB_NSEC_NORMAL; - dns_qpmulti_commit(qpdb->tree, &qp); + + /* + * Add an apex node to the NSEC tree so that we can quickly skip over + * the NSEC nodes while iterating over the full tree. + */ + qpdb->nsec_origin = new_qpznode(qpdb, &qpdb->common.origin, + DNS_DBNAMESPACE_NSEC); + result = dns_qp_insert(qp, qpdb->nsec_origin, 0); + INSIST(result == ISC_R_SUCCESS); /* * Add an apex node to the NSEC3 tree so that NSEC3 searches * return partial matches when there is only a single NSEC3 * record in the tree. */ - dns_qpmulti_write(qpdb->nsec3, &qp); - qpdb->nsec3_origin = new_qpznode(qpdb, &qpdb->common.origin); - qpdb->nsec3_origin->nsec = DNS_DB_NSEC_NSEC3; + qpdb->nsec3_origin = new_qpznode(qpdb, &qpdb->common.origin, + DNS_DBNAMESPACE_NSEC3); result = dns_qp_insert(qp, qpdb->nsec3_origin, 0); INSIST(result == ISC_R_SUCCESS); - dns_qpmulti_commit(qpdb->nsec3, &qp); + + dns_qpmulti_commit(qpdb->tree, &qp); /* * Keep the current version in the open list so that list operation @@ -994,8 +999,9 @@ qpznode_release(qpzonedb_t *qpdb, qpznode_t *node, uint32_t least_serial, } /* Handle easy and typical case first. */ - if (!node->dirty && (node->data != NULL || node == qpdb->origin || - node == qpdb->nsec3_origin)) + if (!node->dirty && + (node->data != NULL || node == qpdb->origin || + node == qpdb->nsec_origin || node == qpdb->nsec3_origin)) { goto unref; } @@ -1708,31 +1714,30 @@ loading_addnode(qpz_load_t *loadctx, const dns_name_t *name, qpznode_t *node = NULL, *nsecnode = NULL; if (type == dns_rdatatype_nsec3 || covers == dns_rdatatype_nsec3) { - result = dns_qp_getname(loadctx->nsec3, name, (void **)&node, + result = dns_qp_getname(loadctx->tree, name, + DNS_DBNAMESPACE_NSEC3, (void **)&node, NULL); if (result == ISC_R_SUCCESS) { *nodep = node; } else { - node = new_qpznode(qpdb, name); - result = dns_qp_insert(loadctx->nsec3, node, 0); + node = new_qpznode(qpdb, name, DNS_DBNAMESPACE_NSEC3); + result = dns_qp_insert(loadctx->tree, node, 0); INSIST(result == ISC_R_SUCCESS); - node->nsec = DNS_DB_NSEC_NSEC3; *nodep = node; qpznode_detach(&node); } return; } - result = dns_qp_getname(loadctx->tree, name, (void **)&node, NULL); + result = dns_qp_getname(loadctx->tree, name, DNS_DBNAMESPACE_NORMAL, + (void **)&node, NULL); if (result == ISC_R_SUCCESS) { - if (type == dns_rdatatype_nsec && - node->nsec == DNS_DB_NSEC_HAS_NSEC) - { + if (type == dns_rdatatype_nsec && node->havensec) { goto done; } } else { INSIST(node == NULL); - node = new_qpznode(qpdb, name); + node = new_qpznode(qpdb, name, DNS_DBNAMESPACE_NORMAL); result = dns_qp_insert(loadctx->tree, node, 0); INSIST(result == ISC_R_SUCCESS); qpznode_unref(node); @@ -1749,10 +1754,9 @@ loading_addnode(qpz_load_t *loadctx, const dns_name_t *name, * node there, so we can just detach the new one we created and * move on. */ - node->nsec = DNS_DB_NSEC_HAS_NSEC; - nsecnode = new_qpznode(qpdb, name); - nsecnode->nsec = DNS_DB_NSEC_NSEC; - (void)dns_qp_insert(loadctx->nsec, nsecnode, 0); + node->havensec = true; + nsecnode = new_qpznode(qpdb, name, DNS_DBNAMESPACE_NSEC); + (void)dns_qp_insert(loadctx->tree, nsecnode, 0); qpznode_detach(&nsecnode); done: @@ -2115,7 +2119,8 @@ add(qpzonedb_t *qpdb, qpznode_t *node, const dns_name_t *nodename, } static void -wildcardmagic(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name) { +wildcardmagic(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name, + dns_namespace_t nspace) { isc_result_t result; dns_name_t foundname; unsigned int n; @@ -2128,10 +2133,10 @@ wildcardmagic(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name) { dns_name_getlabelsequence(name, 1, n, &foundname); /* insert an empty node, if needed, to hold the wildcard bit */ - result = dns_qp_getname(qp, &foundname, (void **)&node, NULL); + result = dns_qp_getname(qp, &foundname, nspace, (void **)&node, NULL); if (result != ISC_R_SUCCESS) { INSIST(node == NULL); - node = new_qpznode(qpdb, &foundname); + node = new_qpznode(qpdb, &foundname, nspace); result = dns_qp_insert(qp, node, 0); INSIST(result == ISC_R_SUCCESS); qpznode_unref(node); @@ -2141,7 +2146,8 @@ wildcardmagic(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name) { } static void -addwildcards(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name) { +addwildcards(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name, + dns_namespace_t nspace) { dns_name_t foundname; unsigned int n, l, i; @@ -2152,7 +2158,7 @@ addwildcards(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name) { while (i < n) { dns_name_getlabelsequence(name, n - i, i, &foundname); if (dns_name_iswildcard(&foundname)) { - wildcardmagic(qpdb, qp, &foundname); + wildcardmagic(qpdb, qp, &foundname, nspace); } i++; @@ -2185,7 +2191,7 @@ loading_addrdataset(void *arg, const dns_name_t *name, if (rdataset->type != dns_rdatatype_nsec3 && rdataset->covers != dns_rdatatype_nsec3) { - addwildcards(qpdb, loadctx->tree, name); + addwildcards(qpdb, loadctx->tree, name, DNS_DBNAMESPACE_NORMAL); } if (dns_name_iswildcard(name)) { @@ -2203,7 +2209,8 @@ loading_addrdataset(void *arg, const dns_name_t *name, return DNS_R_INVALIDNSEC3; } - wildcardmagic(qpdb, loadctx->tree, name); + wildcardmagic(qpdb, loadctx->tree, name, + DNS_DBNAMESPACE_NORMAL); } loading_addnode(loadctx, name, rdataset->type, rdataset->covers, &node); @@ -2259,8 +2266,6 @@ loading_setup(void *arg) { qpzonedb_t *qpdb = (qpzonedb_t *)loadctx->db; dns_qpmulti_write(qpdb->tree, &loadctx->tree); - dns_qpmulti_write(qpdb->nsec, &loadctx->nsec); - dns_qpmulti_write(qpdb->nsec3, &loadctx->nsec3); } static void @@ -2272,14 +2277,6 @@ loading_commit(void *arg) { dns_qp_compact(loadctx->tree, DNS_QPGC_MAYBE); dns_qpmulti_commit(qpdb->tree, &loadctx->tree); } - if (loadctx->nsec != NULL) { - dns_qp_compact(loadctx->nsec, DNS_QPGC_MAYBE); - dns_qpmulti_commit(qpdb->nsec, &loadctx->nsec); - } - if (loadctx->nsec3 != NULL) { - dns_qp_compact(loadctx->nsec3, DNS_QPGC_MAYBE); - dns_qpmulti_commit(qpdb->nsec3, &loadctx->nsec3); - } } static isc_result_t @@ -2551,48 +2548,47 @@ findnodeintree(qpzonedb_t *qpdb, const dns_name_t *name, bool create, bool nsec3, dns_dbnode_t **nodep DNS__DB_FLARG) { isc_result_t result; qpznode_t *node = NULL; - dns_qpmulti_t *dbtree = nsec3 ? qpdb->nsec3 : qpdb->tree; + dns_namespace_t nspace = nsec3 ? DNS_DBNAMESPACE_NSEC3 + : DNS_DBNAMESPACE_NORMAL; dns_qpread_t qpr = { 0 }; dns_qp_t *qp = NULL; if (create) { - dns_qpmulti_write(dbtree, &qp); + dns_qpmulti_write(qpdb->tree, &qp); } else { - dns_qpmulti_query(dbtree, &qpr); + dns_qpmulti_query(qpdb->tree, &qpr); qp = (dns_qp_t *)&qpr; } - result = dns_qp_getname(qp, name, (void **)&node, NULL); + result = dns_qp_getname(qp, name, nspace, (void **)&node, NULL); if (result != ISC_R_SUCCESS) { if (!create) { - dns_qpread_destroy(dbtree, &qpr); + dns_qpread_destroy(qpdb->tree, &qpr); return result; } - node = new_qpznode(qpdb, name); + node = new_qpznode(qpdb, name, nspace); result = dns_qp_insert(qp, node, 0); INSIST(result == ISC_R_SUCCESS); qpznode_unref(node); - if (nsec3) { - node->nsec = DNS_DB_NSEC_NSEC3; - } else { - addwildcards(qpdb, qp, name); + if (!nsec3) { + addwildcards(qpdb, qp, name, nspace); if (dns_name_iswildcard(name)) { - wildcardmagic(qpdb, qp, name); + wildcardmagic(qpdb, qp, name, nspace); } } } - INSIST(node->nsec == DNS_DB_NSEC_NSEC3 || !nsec3); + INSIST(node->nspace == DNS_DBNAMESPACE_NSEC3 || !nsec3); qpznode_acquire(qpdb, node DNS__DB_FLARG_PASS); if (create) { dns_qp_compact(qp, DNS_QPGC_MAYBE); - dns_qpmulti_commit(dbtree, &qp); + dns_qpmulti_commit(qpdb->tree, &qp); } else { - dns_qpread_destroy(dbtree, &qpr); + dns_qpread_destroy(qpdb->tree, &qpr); } *nodep = (dns_dbnode_t *)node; @@ -2880,8 +2876,8 @@ wildcard_blocked(qpz_search_t *search, const dns_name_t *qname, } static isc_result_t -find_wildcard(qpz_search_t *search, qpznode_t **nodep, - const dns_name_t *qname) { +find_wildcard(qpz_search_t *search, qpznode_t **nodep, const dns_name_t *qname, + dns_namespace_t nspace) { dns_slabheader_t *header = NULL; isc_result_t result = ISC_R_NOTFOUND; @@ -2938,8 +2934,9 @@ find_wildcard(qpz_search_t *search, qpznode_t **nodep, break; } - result = dns_qp_lookup(&search->qpr, wname, NULL, &wit, - NULL, (void **)&wnode, NULL); + result = dns_qp_lookup(&search->qpr, wname, nspace, + NULL, &wit, NULL, + (void **)&wnode, NULL); if (result == ISC_R_SUCCESS) { /* * We have found the wildcard node. If it @@ -3020,7 +3017,7 @@ previous_closest_nsec(dns_rdatatype_t type, qpz_search_t *search, return result; } - dns_qpmulti_query(search->qpdb->nsec, &qpr); + dns_qpmulti_query(search->qpdb->tree, &qpr); for (;;) { if (*firstp) { @@ -3029,8 +3026,8 @@ previous_closest_nsec(dns_rdatatype_t type, qpz_search_t *search, * It is the first node sought in the NSEC tree. */ *firstp = false; - result = dns_qp_lookup(&qpr, name, NULL, nit, NULL, - NULL, NULL); + result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NSEC, + NULL, nit, NULL, NULL, NULL); INSIST(result != ISC_R_NOTFOUND); if (result == ISC_R_SUCCESS) { /* @@ -3063,8 +3060,9 @@ previous_closest_nsec(dns_rdatatype_t type, qpz_search_t *search, } *nodep = NULL; - result = dns_qp_lookup(&search->qpr, name, NULL, &search->iter, - &search->chain, (void **)nodep, NULL); + result = dns_qp_lookup( + &search->qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, + &search->iter, &search->chain, (void **)nodep, NULL); if (result == ISC_R_SUCCESS) { break; } @@ -3084,7 +3082,7 @@ previous_closest_nsec(dns_rdatatype_t type, qpz_search_t *search, } } - dns_qpread_destroy(search->qpdb->nsec, &qpr); + dns_qpread_destroy(search->qpdb->tree, &qpr); return result; } @@ -3200,12 +3198,10 @@ again: *nodep = (dns_dbnode_t *)node; } bindrdataset(search->qpdb, node, found, - rdataset DNS__DB_FLARG_PASS); if (foundsig != NULL) { bindrdataset( search->qpdb, node, foundsig, - sigrdataset DNS__DB_FLARG_PASS); } } else if (found == NULL && foundsig == NULL) { @@ -3451,21 +3447,23 @@ qpzone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, close_version = true; } + dns_namespace_t nspace; qpz_search_t search; qpz_search_init(&search, (qpzonedb_t *)db, (qpz_version_t *)version, options); if ((options & DNS_DBFIND_FORCENSEC3) != 0) { - dns_qpmulti_query(qpdb->nsec3, &search.qpr); nsec3 = true; + nspace = DNS_DBNAMESPACE_NSEC3; } else { - dns_qpmulti_query(qpdb->tree, &search.qpr); + nspace = DNS_DBNAMESPACE_NORMAL; } + dns_qpmulti_query(qpdb->tree, &search.qpr); /* * Search down from the root of the tree. */ - result = dns_qp_lookup(&search.qpr, name, NULL, &search.iter, + result = dns_qp_lookup(&search.qpr, name, nspace, NULL, &search.iter, &search.chain, (void **)&node, NULL); if (result != ISC_R_NOTFOUND) { dns_name_copy(&node->name, foundname); @@ -3512,7 +3510,7 @@ qpzone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, * we must see if there's a matching wildcard active * in the current version. */ - result = find_wildcard(&search, &node, name); + result = find_wildcard(&search, &node, name, nspace); if (result == ISC_R_SUCCESS) { dns_name_copy(name, foundname); wild = true; @@ -3910,11 +3908,7 @@ node_exit: NODE_UNLOCK(nlock, &nlocktype); tree_exit: - if (nsec3) { - dns_qpread_destroy(qpdb->nsec3, &search.qpr); - } else { - dns_qpread_destroy(qpdb->tree, &search.qpr); - } + dns_qpread_destroy(qpdb->tree, &search.qpr); /* * If we found a zonecut but aren't going to use it, we have to @@ -4020,7 +4014,7 @@ qpzone_detachnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) { } static unsigned int -nodecount(dns_db_t *db, dns_dbtree_t tree) { +nodecount(dns_db_t *db, dns_dbtree_t tree ISC_ATTR_UNUSED) { qpzonedb_t *qpdb = NULL; dns_qp_memusage_t mu; @@ -4028,19 +4022,7 @@ nodecount(dns_db_t *db, dns_dbtree_t tree) { REQUIRE(VALID_QPZONE(qpdb)); - switch (tree) { - case dns_dbtree_main: - mu = dns_qpmulti_memusage(qpdb->tree); - break; - case dns_dbtree_nsec: - mu = dns_qpmulti_memusage(qpdb->nsec); - break; - case dns_dbtree_nsec3: - mu = dns_qpmulti_memusage(qpdb->nsec3); - break; - default: - UNREACHABLE(); - } + mu = dns_qpmulti_memusage(qpdb->tree); return mu.leaves; } @@ -4293,8 +4275,7 @@ dbiterator_destroy(dns_dbiterator_t **iteratorp DNS__DB_FLARG) { dns_db_detach(&iter->common.db); qpzonedb_t *qpdb = (qpzonedb_t *)db; - dns_qpsnap_destroy(qpdb->tree, &iter->tsnap); - dns_qpsnap_destroy(qpdb->nsec3, &iter->nsnap); + dns_qpsnap_destroy(qpdb->tree, &iter->snap); isc_mem_put(db->mctx, iter, sizeof(*iter)); dns_db_detach(&db); @@ -4318,36 +4299,61 @@ dbiterator_first(dns_dbiterator_t *iterator DNS__DB_FLARG) { dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS); + dns_qpiter_init(qpdbiter->snap, &qpdbiter->iter); + result = dns_qpiter_next(&qpdbiter->iter, NULL, + (void **)&qpdbiter->node, NULL); + switch (qpdbiter->nsec3mode) { - case nsec3only: - qpdbiter->current = &qpdbiter->nsec3iter; - dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current); - result = dns_qpiter_next(qpdbiter->current, NULL, - (void **)&qpdbiter->node, NULL); - if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) { - /* If we're in the NSEC3 tree, skip the origin */ - if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) { - result = dns_qpiter_next( - qpdbiter->current, NULL, - (void **)&qpdbiter->node, NULL); + case nonsec3: + if (result == ISC_R_SUCCESS) { + /* + * If we immediately hit an NSEC/NSEC3 node, + * we don't have any non-nsec nodes. + */ + if (qpdbiter->node->nspace != DNS_DBNAMESPACE_NORMAL) { + qpdbiter->node = NULL; + result = ISC_R_NOMORE; } } break; - case nonsec3: - qpdbiter->current = &qpdbiter->mainiter; - dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current); - result = dns_qpiter_next(qpdbiter->current, NULL, - (void **)&qpdbiter->node, NULL); - break; case full: - qpdbiter->current = &qpdbiter->mainiter; - dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current); - result = dns_qpiter_next(qpdbiter->current, NULL, - (void **)&qpdbiter->node, NULL); - if (result == ISC_R_NOMORE) { - qpdbiter->current = &qpdbiter->nsec3iter; - dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current); - result = dns_qpiter_next(qpdbiter->current, NULL, + /* skip the NSEC3 origin node. */ + if (result == ISC_R_SUCCESS && + QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) + { + result = dns_qpiter_next(&qpdbiter->iter, NULL, + (void **)&qpdbiter->node, + NULL); + } + if (result != ISC_R_SUCCESS) { + qpdbiter->node = NULL; + break; + } + + /* + * If we hit an NSEC node, we need to start at the NSEC3 part of + * the tree. + */ + if (qpdbiter->node->nspace != DNS_DBNAMESPACE_NSEC) { + break; + } + INSIST(qpdbiter->node->nspace == DNS_DBNAMESPACE_NSEC); + + /* FALLTHROUGH */ + case nsec3only: + /* + * NSEC3 follows after all non-nsec3 nodes, seek the NSEC3 + * origin node. + */ + result = dns_qp_lookup(qpdbiter->snap, &qpdb->common.origin, + DNS_DBNAMESPACE_NSEC3, NULL, + &qpdbiter->iter, NULL, + (void **)&qpdbiter->node, NULL); + if (result != ISC_R_SUCCESS || + QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) + { + /* skip the NSEC3 origin node (or its predecessor) */ + result = dns_qpiter_next(&qpdbiter->iter, NULL, (void **)&qpdbiter->node, NULL); } @@ -4381,49 +4387,77 @@ dbiterator_last(dns_dbiterator_t *iterator DNS__DB_FLARG) { dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS); + dns_qpiter_init(qpdbiter->snap, &qpdbiter->iter); + result = dns_qpiter_prev(&qpdbiter->iter, NULL, + (void **)&qpdbiter->node, NULL); + switch (qpdbiter->nsec3mode) { case nsec3only: - qpdbiter->current = &qpdbiter->nsec3iter; - dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current); - result = dns_qpiter_prev(qpdbiter->current, NULL, - (void **)&qpdbiter->node, NULL); - if ((result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) && - QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) - { - /* - * NSEC3 tree only has an origin node. - */ - qpdbiter->node = NULL; - result = ISC_R_NOMORE; + if (result == ISC_R_SUCCESS) { + if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) { + /* tree only has NSEC3 origin node. */ + qpdbiter->node = NULL; + result = ISC_R_NOMORE; + } else if (qpdbiter->node->nspace != + DNS_DBNAMESPACE_NSEC3) + { + /* tree has no NSEC3 nodes at all. */ + qpdbiter->node = NULL; + result = ISC_R_NOMORE; + } } break; - case nonsec3: - qpdbiter->current = &qpdbiter->mainiter; - dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current); - result = dns_qpiter_prev(qpdbiter->current, NULL, - (void **)&qpdbiter->node, NULL); - break; case full: - qpdbiter->current = &qpdbiter->nsec3iter; - dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current); - result = dns_qpiter_prev(qpdbiter->current, NULL, - (void **)&qpdbiter->node, NULL); - if ((result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) && + /* skip the NSEC3 origin node. */ + if (result == ISC_R_SUCCESS && QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) { - /* - * NSEC3 tree only has an origin node. - */ - qpdbiter->node = NULL; - result = ISC_R_NOMORE; - } - if (result == ISC_R_NOMORE) { - qpdbiter->current = &qpdbiter->mainiter; - dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current); - result = dns_qpiter_prev(qpdbiter->current, NULL, + result = dns_qpiter_prev(&qpdbiter->iter, NULL, (void **)&qpdbiter->node, NULL); } + if (result != ISC_R_SUCCESS) { + qpdbiter->node = NULL; + break; + } + + /* + * If we hit an NSEC node, we need to seek the final normal node + * of the tree. + */ + if (qpdbiter->node->nspace != DNS_DBNAMESPACE_NSEC) { + break; + } + INSIST(qpdbiter->node->nspace == DNS_DBNAMESPACE_NSEC); + + /* FALLTHROUGH */ + case nonsec3: + /* + * The final non-nsec node is before the the NSEC origin node. + */ + result = dns_qp_lookup(qpdbiter->snap, &qpdb->common.origin, + DNS_DBNAMESPACE_NSEC, NULL, + &qpdbiter->iter, NULL, + (void **)&qpdbiter->node, NULL); + if (result == ISC_R_SUCCESS) { + INSIST(QPDBITER_NSEC_ORIGIN_NODE(qpdb, qpdbiter)); + /* skip the NSEC origin node */ + result = dns_qpiter_prev(&qpdbiter->iter, NULL, + (void **)&qpdbiter->node, + NULL); + } else { + /* + * The NSEC origin node was not found, but the iterator + * should point to its predecessor, which is the node we + * want. + */ + result = dns_qpiter_current(&qpdbiter->iter, NULL, + (void **)&qpdbiter->node, + NULL); + INSIST(result == ISC_R_SUCCESS); + INSIST(qpdbiter->node->nspace == + DNS_DBNAMESPACE_NORMAL); + } break; default: UNREACHABLE(); @@ -4456,32 +4490,25 @@ dbiterator_seek(dns_dbiterator_t *iterator, switch (qpdbiter->nsec3mode) { case nsec3only: - qpdbiter->current = &qpdbiter->nsec3iter; - result = dns_qp_lookup(qpdbiter->nsnap, name, NULL, - qpdbiter->current, NULL, - (void **)&qpdbiter->node, NULL); + result = dns_qp_lookup( + qpdbiter->snap, name, DNS_DBNAMESPACE_NSEC3, NULL, + &qpdbiter->iter, NULL, (void **)&qpdbiter->node, NULL); break; case nonsec3: - qpdbiter->current = &qpdbiter->mainiter; - result = dns_qp_lookup(qpdbiter->tsnap, name, NULL, - qpdbiter->current, NULL, - (void **)&qpdbiter->node, NULL); + result = dns_qp_lookup( + qpdbiter->snap, name, DNS_DBNAMESPACE_NORMAL, NULL, + &qpdbiter->iter, NULL, (void **)&qpdbiter->node, NULL); break; case full: - /* - * Stay on main chain if not found on - * either iterator. - */ - qpdbiter->current = &qpdbiter->mainiter; - result = dns_qp_lookup(qpdbiter->tsnap, name, NULL, - qpdbiter->current, NULL, - (void **)&qpdbiter->node, NULL); - if (result == DNS_R_PARTIALMATCH) { - tresult = dns_qp_lookup(qpdbiter->nsnap, name, NULL, - &qpdbiter->nsec3iter, NULL, - NULL, NULL); + result = dns_qp_lookup( + qpdbiter->snap, name, DNS_DBNAMESPACE_NORMAL, NULL, + &qpdbiter->iter, NULL, (void **)&qpdbiter->node, NULL); + if (result != ISC_R_SUCCESS) { + tresult = dns_qp_lookup(qpdbiter->snap, name, + DNS_DBNAMESPACE_NSEC3, NULL, + &qpdbiter->iter, NULL, + (void **)&qpdbiter->node, NULL); if (tresult == ISC_R_SUCCESS) { - qpdbiter->current = &qpdbiter->nsec3iter; result = tresult; } } @@ -4515,28 +4542,77 @@ dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG) { dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS); - result = dns_qpiter_prev(qpdbiter->current, NULL, + result = dns_qpiter_prev(&qpdbiter->iter, NULL, (void **)&qpdbiter->node, NULL); - if (qpdbiter->current == &qpdbiter->nsec3iter) { - if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) { - /* - * If we're in the NSEC3 tree, it's empty or - * we've reached the origin, then we're done - * with it. - */ + switch (qpdbiter->nsec3mode) { + case nsec3only: + if (result == ISC_R_SUCCESS) { if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) { + /* we hit the NSEC3 origin node. */ + qpdbiter->node = NULL; + result = ISC_R_NOMORE; + } else if (qpdbiter->node->nspace != + DNS_DBNAMESPACE_NSEC3) + { + /* we hit a non-NSEC3 node. */ qpdbiter->node = NULL; result = ISC_R_NOMORE; } } - if (result == ISC_R_NOMORE && qpdbiter->nsec3mode == full) { - qpdbiter->current = &qpdbiter->mainiter; - dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current); - result = dns_qpiter_prev(qpdbiter->current, NULL, + break; + case full: + /* skip the NSEC3 origin node. */ + if (result == ISC_R_SUCCESS && + QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) + { + result = dns_qpiter_prev(&qpdbiter->iter, NULL, (void **)&qpdbiter->node, NULL); } + if (result != ISC_R_SUCCESS) { + qpdbiter->node = NULL; + break; + } + + /* + * If we hit an NSEC node, we need to seek the final normal node + * of the tree. + */ + if (qpdbiter->node->nspace != DNS_DBNAMESPACE_NSEC) { + break; + } + + INSIST(qpdbiter->node->nspace == DNS_DBNAMESPACE_NSEC); + result = dns_qp_lookup(qpdbiter->snap, &qpdb->common.origin, + DNS_DBNAMESPACE_NSEC, NULL, + &qpdbiter->iter, NULL, + (void **)&qpdbiter->node, NULL); + + if (result == ISC_R_SUCCESS) { + INSIST(QPDBITER_NSEC_ORIGIN_NODE(qpdb, qpdbiter)); + /* skip the NSEC origin node */ + result = dns_qpiter_prev(&qpdbiter->iter, NULL, + (void **)&qpdbiter->node, + NULL); + } else { + /* + * The NSEC origin node was not found, but the iterator + * should point to its predecessor, which is the node we + * want. + */ + result = dns_qpiter_current(&qpdbiter->iter, NULL, + (void **)&qpdbiter->node, + NULL); + INSIST(result == ISC_R_SUCCESS); + INSIST(qpdbiter->node->nspace == + DNS_DBNAMESPACE_NORMAL); + } + break; + case nonsec3: + break; + default: + UNREACHABLE(); } if (result == ISC_R_SUCCESS) { @@ -4563,39 +4639,59 @@ dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG) { dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS); - result = dns_qpiter_next(qpdbiter->current, NULL, + result = dns_qpiter_next(&qpdbiter->iter, NULL, (void **)&qpdbiter->node, NULL); - if (result == ISC_R_NOMORE && qpdbiter->nsec3mode == full && - qpdbiter->current == &qpdbiter->mainiter) - { - qpdbiter->current = &qpdbiter->nsec3iter; - dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current); - result = dns_qpiter_next(qpdbiter->current, NULL, - (void **)&qpdbiter->node, NULL); - } - - if (result == ISC_R_SUCCESS) { - /* - * If we've just started the NSEC3 tree, - * skip over the origin. - */ - if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) { - switch (qpdbiter->nsec3mode) { - case nsec3only: - case full: - result = dns_qpiter_next( - qpdbiter->current, NULL, - (void **)&qpdbiter->node, NULL); - break; - case nonsec3: - result = ISC_R_NOMORE; + switch (qpdbiter->nsec3mode) { + case nonsec3: + if (result == ISC_R_SUCCESS) { + /* we hit an NSEC or NSEC3 node. */ + if (qpdbiter->node->nspace != DNS_DBNAMESPACE_NORMAL) { qpdbiter->node = NULL; - break; - default: - UNREACHABLE(); + result = ISC_R_NOMORE; } } + break; + case full: + /* skip the NSEC3 origin node. */ + if (result == ISC_R_SUCCESS && + QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) + { + result = dns_qpiter_next(&qpdbiter->iter, NULL, + (void **)&qpdbiter->node, + NULL); + } + if (result != ISC_R_SUCCESS) { + qpdbiter->node = NULL; + break; + } + + /* + * If we hit an NSEC node, we need to start at the NSEC3 part of + * the tree. + */ + if (qpdbiter->node->nspace != DNS_DBNAMESPACE_NSEC) { + break; + } + INSIST(qpdbiter->node->nspace == DNS_DBNAMESPACE_NSEC); + + result = dns_qp_lookup(qpdbiter->snap, &qpdb->common.origin, + DNS_DBNAMESPACE_NSEC3, NULL, + &qpdbiter->iter, NULL, + (void **)&qpdbiter->node, NULL); + if (result != ISC_R_SUCCESS || + QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) + { + /* skip the NSEC3 origin node (or its predecessor). */ + result = dns_qpiter_next(&qpdbiter->iter, NULL, + (void **)&qpdbiter->node, + NULL); + } + break; + case nsec3only: + break; + default: + UNREACHABLE(); } if (result == ISC_R_SUCCESS) { @@ -4651,6 +4747,7 @@ qpzone_createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp) { qpzonedb_t *qpdb = (qpzonedb_t *)db; qpdb_dbiterator_t *iter = NULL; + isc_result_t result; REQUIRE(VALID_QPZONE(qpdb)); @@ -4664,22 +4761,34 @@ qpzone_createiterator(dns_db_t *db, unsigned int options, if ((options & DNS_DB_NSEC3ONLY) != 0) { iter->nsec3mode = nsec3only; - iter->current = &iter->nsec3iter; } else if ((options & DNS_DB_NONSEC3) != 0) { iter->nsec3mode = nonsec3; - iter->current = &iter->mainiter; } else { iter->nsec3mode = full; - iter->current = &iter->mainiter; } dns_db_attach(db, &iter->common.db); - dns_qpmulti_snapshot(qpdb->tree, &iter->tsnap); - dns_qpiter_init(iter->tsnap, &iter->mainiter); + dns_qpmulti_snapshot(qpdb->tree, &iter->snap); - dns_qpmulti_snapshot(qpdb->nsec3, &iter->nsnap); - dns_qpiter_init(iter->nsnap, &iter->nsec3iter); + switch (iter->nsec3mode) { + case nonsec3: + case full: + dns_qpiter_init(iter->snap, &iter->iter); + break; + case nsec3only: + /* + * NSEC3 follows after all non-nsec3 nodes, + * seek the NSEC3 origin node. + */ + result = dns_qp_lookup(iter->snap, &qpdb->common.origin, + DNS_DBNAMESPACE_NSEC3, NULL, &iter->iter, + NULL, NULL, NULL); + INSIST(result == ISC_R_SUCCESS); + break; + default: + UNREACHABLE(); + } *iteratorp = (dns_dbiterator_t *)iter; return ISC_R_SUCCESS; @@ -4713,10 +4822,10 @@ qpzone_addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, return DNS_R_NOTZONETOP; } - REQUIRE((node->nsec == DNS_DB_NSEC_NSEC3 && + REQUIRE((node->nspace == DNS_DBNAMESPACE_NSEC3 && (rdataset->type == dns_rdatatype_nsec3 || rdataset->covers == dns_rdatatype_nsec3)) || - (node->nsec != DNS_DB_NSEC_NSEC3 && + (node->nspace != DNS_DBNAMESPACE_NSEC3 && rdataset->type != dns_rdatatype_nsec3 && rdataset->covers != dns_rdatatype_nsec3)); @@ -4756,10 +4865,8 @@ qpzone_addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, /* * Add to the auxiliary NSEC tree if we're adding an NSEC record. */ - if (node->nsec != DNS_DB_NSEC_HAS_NSEC && - rdataset->type == dns_rdatatype_nsec) - { - dns_qpmulti_write(qpdb->nsec, &nsec); + if (!node->havensec && rdataset->type == dns_rdatatype_nsec) { + dns_qpmulti_write(qpdb->tree, &nsec); } /* @@ -4777,15 +4884,15 @@ qpzone_addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, result = ISC_R_SUCCESS; if (nsec != NULL) { - node->nsec = DNS_DB_NSEC_HAS_NSEC; + node->havensec = true; /* * If it fails, there was already an NSEC node, * so we can detach the new one we created and * move on. */ - qpznode_t *nsecnode = new_qpznode(qpdb, name); - nsecnode->nsec = DNS_DB_NSEC_NSEC; + qpznode_t *nsecnode = new_qpznode(qpdb, name, + DNS_DBNAMESPACE_NSEC); (void)dns_qp_insert(nsec, nsecnode, 0); qpznode_detach(&nsecnode); } @@ -4808,7 +4915,7 @@ qpzone_addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, NODE_UNLOCK(nlock, &nlocktype); if (nsec != NULL) { - dns_qpmulti_commit(qpdb->nsec, &nsec); + dns_qpmulti_commit(qpdb->tree, &nsec); } return result; @@ -4836,10 +4943,10 @@ qpzone_subtractrdataset(dns_db_t *db, dns_dbnode_t *dbnode, REQUIRE(VALID_QPZONE(qpdb)); REQUIRE(version != NULL && version->qpdb == qpdb); - REQUIRE((node->nsec == DNS_DB_NSEC_NSEC3 && + REQUIRE((node->nspace == DNS_DBNAMESPACE_NSEC3 && (rdataset->type == dns_rdatatype_nsec3 || rdataset->covers == dns_rdatatype_nsec3)) || - (node->nsec != DNS_DB_NSEC_NSEC3 && + (node->nspace != DNS_DBNAMESPACE_NSEC3 && rdataset->type != dns_rdatatype_nsec3 && rdataset->covers != dns_rdatatype_nsec3)); @@ -5485,7 +5592,7 @@ static size_t qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval, uint32_t ival ISC_ATTR_UNUSED) { qpznode_t *data = pval; - return dns_qpkey_fromname(key, &data->name); + return dns_qpkey_fromname(key, &data->name, data->nspace); } static void diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index 42c7b286ba..ab310ff8ef 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -1422,7 +1422,8 @@ add_nm(dns_rpz_zones_t *rpzs, dns_name_t *trig_name, const nmdata_t *new_data) { dns_qp_t *qp = NULL; dns_qpmulti_write(rpzs->table, &qp); - result = dns_qp_getname(qp, trig_name, (void **)&data, NULL); + result = dns_qp_getname(qp, trig_name, DNS_DBNAMESPACE_NORMAL, + (void **)&data, NULL); if (result != ISC_R_SUCCESS) { INSIST(data == NULL); data = new_nmdata(rpzs->mctx, trig_name, new_data); @@ -2291,7 +2292,8 @@ del_name(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, trig_name = dns_fixedname_initname(&trig_namef); name2data(rpz, rpz_type, src_name, trig_name, &del_data); - result = dns_qp_getname(qp, trig_name, (void **)&data, NULL); + result = dns_qp_getname(qp, trig_name, DNS_DBNAMESPACE_NORMAL, + (void **)&data, NULL); if (result != ISC_R_SUCCESS) { return; } @@ -2314,7 +2316,8 @@ del_name(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, if (data->set.qname == 0 && data->set.ns == 0 && data->wild.qname == 0 && data->wild.ns == 0) { - result = dns_qp_deletename(qp, trig_name, NULL, NULL); + result = dns_qp_deletename(qp, trig_name, + DNS_DBNAMESPACE_NORMAL, NULL, NULL); if (result != ISC_R_SUCCESS) { /* * bin/tests/system/rpz/tests.sh looks for @@ -2516,8 +2519,8 @@ dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type, dns_qpmulti_query(rpzs->table, &qpr); dns_qpchain_init(&qpr, &chain); - result = dns_qp_lookup(&qpr, trig_name, NULL, NULL, &chain, - (void **)&data, NULL); + result = dns_qp_lookup(&qpr, trig_name, DNS_DBNAMESPACE_NORMAL, NULL, + NULL, &chain, (void **)&data, NULL); switch (result) { case ISC_R_SUCCESS: INSIST(data != NULL); @@ -2667,7 +2670,7 @@ static size_t qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval, uint32_t ival ISC_ATTR_UNUSED) { nmdata_t *data = pval; - return dns_qpkey_fromname(key, &data->name); + return dns_qpkey_fromname(key, &data->name, DNS_DBNAMESPACE_NORMAL); } static void diff --git a/lib/dns/zt.c b/lib/dns/zt.c index b4e75c1843..fae234ba67 100644 --- a/lib/dns/zt.c +++ b/lib/dns/zt.c @@ -77,7 +77,7 @@ ztqpmakekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval, uint32_t ival ISC_ATTR_UNUSED) { dns_zone_t *zone = pval; dns_name_t *name = dns_zone_getorigin(zone); - return dns_qpkey_fromname(key, name); + return dns_qpkey_fromname(key, name, DNS_DBNAMESPACE_NORMAL); } static void @@ -156,7 +156,8 @@ dns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone) { REQUIRE(VALID_ZT(zt)); dns_qpmulti_write(zt->multi, &qp); - result = dns_qp_deletename(qp, dns_zone_getorigin(zone), NULL, NULL); + result = dns_qp_deletename(qp, dns_zone_getorigin(zone), + DNS_DBNAMESPACE_NORMAL, NULL, NULL); dns_qp_compact(qp, DNS_QPGC_MAYBE); dns_qpmulti_commit(zt->multi, &qp); @@ -179,10 +180,11 @@ dns_zt_find(dns_zt_t *zt, const dns_name_t *name, dns_ztfind_t options, dns_qpmulti_query(zt->multi, &qpr); if (exactopts == DNS_ZTFIND_EXACT) { - result = dns_qp_getname(&qpr, name, &pval, NULL); + result = dns_qp_getname(&qpr, name, DNS_DBNAMESPACE_NORMAL, + &pval, NULL); } else { - result = dns_qp_lookup(&qpr, name, NULL, NULL, &chain, &pval, - NULL); + result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, + NULL, &chain, &pval, NULL); if (exactopts == DNS_ZTFIND_NOEXACT && result == ISC_R_SUCCESS) { /* get pval from the previous chain link */ diff --git a/tests/bench/load-names.c b/tests/bench/load-names.c index 67aa7ad5a0..4ef00cbb03 100644 --- a/tests/bench/load-names.c +++ b/tests/bench/load-names.c @@ -66,7 +66,8 @@ static size_t item_makekey(dns_qpkey_t key, void *ctx, void *pval, uint32_t ival) { UNUSED(ctx); assert(pval == &item[ival]); - return dns_qpkey_fromname(key, &item[ival].fixed.name); + return dns_qpkey_fromname(key, &item[ival].fixed.name, + DNS_DBNAMESPACE_NORMAL); } static void @@ -325,7 +326,8 @@ sqz_qp(void *qp) { static isc_result_t get_qp(void *qp, size_t count, void **pval) { - return dns_qp_getname(qp, &item[count].fixed.name, pval, NULL); + return dns_qp_getname(qp, &item[count].fixed.name, + DNS_DBNAMESPACE_NORMAL, pval, NULL); } static void * diff --git a/tests/bench/qp-dump.c b/tests/bench/qp-dump.c index 33bccc5ec8..8300c5cd60 100644 --- a/tests/bench/qp-dump.c +++ b/tests/bench/qp-dump.c @@ -87,7 +87,7 @@ qpkey_from_smallname(dns_qpkey_t key, void *ctx, void *pval, uint32_t ival) { UNUSED(ctx); dns_name_t name = DNS_NAME_INITEMPTY; name_from_smallname(&name, pval, ival); - return dns_qpkey_fromname(key, &name); + return dns_qpkey_fromname(key, &name, DNS_DBNAMESPACE_NORMAL); } static void diff --git a/tests/bench/qplookups.c b/tests/bench/qplookups.c index aeb3e8b54c..172019b867 100644 --- a/tests/bench/qplookups.c +++ b/tests/bench/qplookups.c @@ -81,7 +81,7 @@ qpkey_from_smallname(dns_qpkey_t key, void *ctx, void *pval, uint32_t ival) { UNUSED(ctx); dns_name_t name = DNS_NAME_INITEMPTY; name_from_smallname(&name, pval, ival); - return dns_qpkey_fromname(key, &name); + return dns_qpkey_fromname(key, &name, DNS_DBNAMESPACE_NORMAL); } static void @@ -228,7 +228,7 @@ main(int argc, char **argv) { start = isc_time_monotonic(); for (i = 0; i < n; i++) { name = dns_fixedname_name(&items[i]); - dns_qp_getname(qp, name, NULL, NULL); + dns_qp_getname(qp, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL); } stop = isc_time_monotonic(); @@ -238,7 +238,8 @@ main(int argc, char **argv) { start = isc_time_monotonic(); for (i = 0; i < n; i++) { name = dns_fixedname_name(&items[i]); - dns_qp_lookup(qp, name, 0, NULL, NULL, NULL, NULL); + dns_qp_lookup(qp, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL, + NULL, NULL, NULL); } stop = isc_time_monotonic(); @@ -263,7 +264,8 @@ main(int argc, char **argv) { ++search->ndata[1]; } - dns_qp_lookup(qp, search, 0, NULL, NULL, NULL, NULL); + dns_qp_lookup(qp, search, DNS_DBNAMESPACE_NORMAL, NULL, NULL, + NULL, NULL, NULL); } stop = isc_time_monotonic(); diff --git a/tests/bench/qpmulti.c b/tests/bench/qpmulti.c index 783bf37f51..e56ac679b0 100644 --- a/tests/bench/qpmulti.c +++ b/tests/bench/qpmulti.c @@ -137,8 +137,9 @@ init_items(isc_mem_t *mctx) { for (size_t i = 0; i < ITEM_COUNT; i++) { do { size_t len = isc_random_uniform(16) + 4; - item[i].len = len; - for (size_t off = 0; off < len; off++) { + item[i].len = len + 1; + item[i].key[0] = 0; + for (size_t off = 1; off < len; off++) { item[i].key[off] = random_byte(); } item[i].key[len] = SHIFT_NOBYTE; diff --git a/tests/dns/qp_test.c b/tests/dns/qp_test.c index 8abfdd11fd..bf7368629d 100644 --- a/tests/dns/qp_test.c +++ b/tests/dns/qp_test.c @@ -45,56 +45,78 @@ bool verbose = false; ISC_RUN_TEST_IMPL(qpkey_name) { struct { const char *namestr; + dns_namespace_t space; uint8_t key[512]; size_t len; } testcases[] = { { .namestr = "", - .key = { 0x02 }, - .len = 0, - }, - { - .namestr = ".", - .key = { 0x02, 0x02 }, + .space = DNS_DBNAMESPACE_NORMAL, + .key = { 0x07, 0x02 }, .len = 1, }, + { + .namestr = ".", + .space = DNS_DBNAMESPACE_NORMAL, + .key = { 0x07, 0x02, 0x02 }, + .len = 2, + }, { .namestr = "\\000", - .key = { 0x03, 0x03, 0x02 }, - .len = 3, - }, - { - .namestr = "\\000\\009", - .key = { 0x03, 0x03, 0x03, 0x0c, 0x02 }, - .len = 5, - }, - { - .namestr = "com", - .key = { 0x16, 0x22, 0x20, 0x02 }, + .space = DNS_DBNAMESPACE_NORMAL, + .key = { 0x07, 0x03, 0x03, 0x02 }, .len = 4, }, { - .namestr = "com.", - .key = { 0x02, 0x16, 0x22, 0x20, 0x02 }, + .namestr = "\\000\\009", + .space = DNS_DBNAMESPACE_NORMAL, + .key = { 0x07, 0x03, 0x03, 0x03, 0x0c, 0x02 }, + .len = 6, + }, + { + .namestr = "com", + .space = DNS_DBNAMESPACE_NORMAL, + .key = { 0x07, 0x16, 0x22, 0x20, 0x02 }, .len = 5, }, + { + .namestr = "com.", + .space = DNS_DBNAMESPACE_NSEC, + .key = { 0x08, 0x02, 0x16, 0x22, 0x20, 0x02 }, + .len = 6, + }, + { + .namestr = "com.", + .space = DNS_DBNAMESPACE_NSEC3, + .key = { 0x09, 0x02, 0x16, 0x22, 0x20, 0x02 }, + .len = 6, + }, + { + .namestr = "com.", + .space = DNS_DBNAMESPACE_NORMAL, + .key = { 0x07, 0x02, 0x16, 0x22, 0x20, 0x02 }, + .len = 6, + }, { .namestr = "example.com.", - .key = { 0x02, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14, + .space = DNS_DBNAMESPACE_NORMAL, + .key = { 0x07, 0x02, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, + 0x14, 0x20, 0x23, 0x1f, 0x18, 0x02 }, + .len = 14, + }, + { + .namestr = "example.com", + .space = DNS_DBNAMESPACE_NORMAL, + .key = { 0x07, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14, 0x20, 0x23, 0x1f, 0x18, 0x02 }, .len = 13, }, - { - .namestr = "example.com", - .key = { 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14, 0x20, - 0x23, 0x1f, 0x18, 0x02 }, - .len = 12, - }, { .namestr = "EXAMPLE.COM", - .key = { 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14, 0x20, - 0x23, 0x1f, 0x18, 0x02 }, - .len = 12, + .space = DNS_DBNAMESPACE_NORMAL, + .key = { 0x07, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14, + 0x20, 0x23, 0x1f, 0x18, 0x02 }, + .len = 13, }, }; @@ -104,28 +126,26 @@ ISC_RUN_TEST_IMPL(qpkey_name) { dns_fixedname_t fn1, fn2; dns_name_t *in = NULL, *out = NULL; char namebuf[DNS_NAME_FORMATSIZE]; + dns_namespace_t space; in = dns_fixedname_initname(&fn1); - if (testcases[i].len != 0) { + if (testcases[i].len > 1) { dns_test_namefromstring(testcases[i].namestr, &fn1); } - len = dns_qpkey_fromname(key, in); + len = dns_qpkey_fromname(key, in, testcases[i].space); if (verbose) { qp_test_printkey(key, len); } assert_int_equal(testcases[i].len, len); assert_memory_equal(testcases[i].key, key, len); - /* also check key correctness for empty name */ - if (len == 0) { - assert_int_equal(testcases[i].key[0], ((char *)key)[0]); - } out = dns_fixedname_initname(&fn2); - dns_qpkey_toname(key, len, out); + dns_qpkey_toname(key, len, out, &space); assert_true(dns_name_equal(in, out)); + assert_int_equal(space, testcases[i].space); /* check that 'out' is properly reset by dns_qpkey_toname */ - dns_qpkey_toname(key, len, out); + dns_qpkey_toname(key, len, out, NULL); dns_name_format(out, namebuf, sizeof(namebuf)); } } @@ -135,20 +155,27 @@ ISC_RUN_TEST_IMPL(qpkey_sort) { const char *namestr; dns_name_t *name; dns_fixedname_t fixed; + dns_namespace_t space; size_t len; dns_qpkey_t key; } testcases[] = { - { .namestr = "." }, - { .namestr = "\\000." }, - { .namestr = "\\000.\\000." }, - { .namestr = "\\000\\009." }, - { .namestr = "\\007." }, - { .namestr = "example.com." }, - { .namestr = "EXAMPLE.COM." }, - { .namestr = "www.example.com." }, - { .namestr = "exam.com." }, - { .namestr = "exams.com." }, - { .namestr = "exam\\000.com." }, + { .namestr = ".", .space = DNS_DBNAMESPACE_NORMAL }, + { .namestr = "\\000.", .space = DNS_DBNAMESPACE_NORMAL }, + { .namestr = "\\000.\\000.", .space = DNS_DBNAMESPACE_NORMAL }, + { .namestr = "\\000\\009.", .space = DNS_DBNAMESPACE_NORMAL }, + { .namestr = "\\007.", .space = DNS_DBNAMESPACE_NORMAL }, + { .namestr = "example.com.", .space = DNS_DBNAMESPACE_NORMAL }, + { .namestr = "EXAMPLE.COM.", .space = DNS_DBNAMESPACE_NORMAL }, + { .namestr = "www.example.com.", + .space = DNS_DBNAMESPACE_NORMAL }, + { .namestr = "exam.com.", .space = DNS_DBNAMESPACE_NORMAL }, + { .namestr = "exams.com.", .space = DNS_DBNAMESPACE_NORMAL }, + { .namestr = "exam\\000.com.", + .space = DNS_DBNAMESPACE_NORMAL }, + { .namestr = "exam.com.", .space = DNS_DBNAMESPACE_NSEC }, + { .namestr = "exams.com.", .space = DNS_DBNAMESPACE_NSEC }, + { .namestr = "exam.com.", .space = DNS_DBNAMESPACE_NSEC3 }, + { .namestr = "exams.com.", .space = DNS_DBNAMESPACE_NSEC3 }, }; for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) { @@ -156,7 +183,8 @@ ISC_RUN_TEST_IMPL(qpkey_sort) { &testcases[i].fixed); testcases[i].name = dns_fixedname_name(&testcases[i].fixed); testcases[i].len = dns_qpkey_fromname(testcases[i].key, - testcases[i].name); + testcases[i].name, + testcases[i].space); } for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) { @@ -168,9 +196,16 @@ ISC_RUN_TEST_IMPL(qpkey_sort) { /* include extra terminating NOBYTE */ int keycmp = memcmp(testcases[i].key, testcases[j].key, len + 1); - assert_true((namecmp < 0) == (keycmp < 0)); - assert_true((namecmp == 0) == (keycmp == 0)); - assert_true((namecmp > 0) == (keycmp > 0)); + if (testcases[i].space == testcases[j].space) { + assert_true((namecmp < 0) == (keycmp < 0)); + assert_true((namecmp == 0) == (keycmp == 0)); + assert_true((namecmp > 0) == (keycmp > 0)); + } else { + uint8_t di = testcases[i].space; + uint8_t dj = testcases[j].space; + assert_true((di < dj) == (keycmp < 0)); + assert_true((di > dj) == (keycmp > 0)); + } } } } @@ -351,14 +386,11 @@ no_op(void *uctx, void *pval, uint32_t ival) { static size_t qpkey_fromstring(dns_qpkey_t key, void *uctx, void *pval, uint32_t ival) { dns_fixedname_t fixed; + dns_namespace_t space = ival; UNUSED(uctx); - UNUSED(ival); - if (*(char *)pval == '\0') { - return 0; - } dns_test_namefromstring(pval, &fixed); - return dns_qpkey_fromname(key, dns_fixedname_name(&fixed)); + return dns_qpkey_fromname(key, dns_fixedname_name(&fixed), space); } const dns_qpmethods_t string_methods = { @@ -375,7 +407,8 @@ struct check_partialmatch { }; static void -check_partialmatch(dns_qp_t *qp, struct check_partialmatch check[]) { +check_partialmatch(dns_qp_t *qp, struct check_partialmatch check[], + dns_namespace_t space) { for (int i = 0; check[i].query != NULL; i++) { isc_result_t result; dns_fixedname_t fn1, fn2; @@ -384,12 +417,13 @@ check_partialmatch(dns_qp_t *qp, struct check_partialmatch check[]) { void *pval = NULL; dns_test_namefromstring(check[i].query, &fn1); - result = dns_qp_lookup(qp, name, foundname, NULL, NULL, &pval, - NULL); + result = dns_qp_lookup(qp, name, space, foundname, NULL, NULL, + &pval, NULL); #if 0 - fprintf(stderr, "%s %s (expected %s) " + fprintf(stderr, "%s%s %s (expected %s) " "value \"%s\" (expected \"%s\")\n", + space == DNS_DBNAMESPACE_NSEC3 ? "NSEC3:" : (space == DNS_DBNAMESPACE_NSEC ? "NSEC:" : ""), check[i].query, isc_result_totext(result), isc_result_totext(check[i].result), (char *)pval, @@ -428,16 +462,24 @@ check_partialmatch(dns_qp_t *qp, struct check_partialmatch check[]) { } static void -insert_str(dns_qp_t *qp, const char *str) { +insert_name(dns_qp_t *qp, const char *str, dns_namespace_t space) { isc_result_t result; uintptr_t pval = (uintptr_t)str; + uint32_t ival = (uint32_t)space; INSIST((pval & 3) == 0); - result = dns_qp_insert(qp, (void *)pval, 0); + result = dns_qp_insert(qp, (void *)pval, ival); + assert_int_equal(result, ISC_R_SUCCESS); +} + +static void +delete_rootkey(dns_qp_t *qp, dns_namespace_t space) { + uint8_t d = dns_qp_bits_for_byte[space + 48]; + dns_qpkey_t rootkey = { d, SHIFT_NOBYTE }; + isc_result_t result = dns_qp_deletekey(qp, rootkey, 1, NULL, NULL); assert_int_equal(result, ISC_R_SUCCESS); } ISC_RUN_TEST_IMPL(partialmatch) { - isc_result_t result; dns_qp_t *qp = NULL; int i = 0; @@ -456,7 +498,10 @@ ISC_RUN_TEST_IMPL(partialmatch) { * results when we want "not found". */ while (insert[i][0] != '.') { - insert_str(qp, insert[i++]); + insert_name(qp, insert[i], DNS_DBNAMESPACE_NORMAL); + insert_name(qp, insert[i], DNS_DBNAMESPACE_NSEC); + insert_name(qp, insert[i], DNS_DBNAMESPACE_NSEC3); + i++; } static struct check_partialmatch check1[] = { @@ -474,11 +519,16 @@ ISC_RUN_TEST_IMPL(partialmatch) { { "my.other.foo.bar.", DNS_R_PARTIALMATCH, "foo.bar." }, { NULL, 0, NULL }, }; - check_partialmatch(qp, check1); + check_partialmatch(qp, check1, DNS_DBNAMESPACE_NORMAL); + check_partialmatch(qp, check1, DNS_DBNAMESPACE_NSEC); + check_partialmatch(qp, check1, DNS_DBNAMESPACE_NSEC3); /* what if the trie contains the root? */ INSIST(insert[i][0] == '.'); - insert_str(qp, insert[i++]); + insert_name(qp, insert[i], DNS_DBNAMESPACE_NORMAL); + insert_name(qp, insert[i], DNS_DBNAMESPACE_NSEC); + insert_name(qp, insert[i], DNS_DBNAMESPACE_NSEC3); + i++; static struct check_partialmatch check2[] = { { "b.c.", DNS_R_PARTIALMATCH, "." }, @@ -487,35 +537,33 @@ ISC_RUN_TEST_IMPL(partialmatch) { { "bar", ISC_R_NOTFOUND, NULL }, { NULL, 0, NULL }, }; - check_partialmatch(qp, check2); + check_partialmatch(qp, check2, DNS_DBNAMESPACE_NORMAL); + check_partialmatch(qp, check2, DNS_DBNAMESPACE_NSEC); + check_partialmatch(qp, check2, DNS_DBNAMESPACE_NSEC3); /* * what if entries in the trie are relative to the zone apex * and there's no root node? */ - dns_qpkey_t rootkey = { SHIFT_NOBYTE }; - result = dns_qp_deletekey(qp, rootkey, 1, NULL, NULL); - assert_int_equal(result, ISC_R_SUCCESS); - check_partialmatch(qp, (struct check_partialmatch[]){ - { "bar", ISC_R_NOTFOUND, NULL }, - { "bar.", ISC_R_NOTFOUND, NULL }, - { NULL, 0, NULL }, - }); + delete_rootkey(qp, DNS_DBNAMESPACE_NORMAL); + delete_rootkey(qp, DNS_DBNAMESPACE_NSEC); + delete_rootkey(qp, DNS_DBNAMESPACE_NSEC3); - /* what if there's a root node with an empty key? */ - INSIST(insert[i][0] == '\0'); - insert_str(qp, insert[i++]); - check_partialmatch(qp, (struct check_partialmatch[]){ - { "bar", DNS_R_PARTIALMATCH, "" }, - { "bar.", DNS_R_PARTIALMATCH, "" }, - { NULL, 0, NULL }, - }); + static struct check_partialmatch check3[] = { + { "bar", ISC_R_NOTFOUND, NULL }, + { "bar.", ISC_R_NOTFOUND, NULL }, + { NULL, 0, NULL }, + }; + check_partialmatch(qp, check3, DNS_DBNAMESPACE_NORMAL); + check_partialmatch(qp, check3, DNS_DBNAMESPACE_NSEC); + check_partialmatch(qp, check3, DNS_DBNAMESPACE_NSEC3); dns_qp_destroy(&qp); } struct check_qpchain { const char *query; + dns_namespace_t space; isc_result_t result; unsigned int length; const char *names[10]; @@ -532,12 +580,13 @@ check_qpchainiter(dns_qp_t *qp, struct check_qpchain check[], dns_qpchain_init(qp, &chain); dns_test_namefromstring(check[i].query, &fn1); - result = dns_qp_lookup(qp, name, NULL, iter, &chain, NULL, - NULL); + result = dns_qp_lookup(qp, name, check[i].space, NULL, iter, + &chain, NULL, NULL); #if 0 - fprintf(stderr, "%s %s (expected %s), " - "len %d (expected %d)\n", check[i].query, - isc_result_totext(result), + fprintf(stderr, + "%s %s (expected %s), " + "len %d (expected %d)\n", + check[i].query, isc_result_totext(result), isc_result_totext(check[i].result), dns_qpchain_length(&chain), check[i].length); #endif @@ -580,24 +629,106 @@ ISC_RUN_TEST_IMPL(qpchain) { dns_qp_create(mctx, &string_methods, NULL, &qp); while (insert[i][0] != '\0') { - insert_str(qp, insert[i++]); + insert_name(qp, insert[i], DNS_DBNAMESPACE_NORMAL); + insert_name(qp, insert[i], DNS_DBNAMESPACE_NSEC); + insert_name(qp, insert[i], DNS_DBNAMESPACE_NSEC3); + i++; } static struct check_qpchain check1[] = { - { "b.", ISC_R_SUCCESS, 2, { ".", "b." } }, - { "b.a.", ISC_R_SUCCESS, 3, { ".", "a.", "b.a." } }, - { "c.", DNS_R_PARTIALMATCH, 1, { "." } }, + { "b.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, + 2, + { ".", "b." } }, + { "b.", DNS_DBNAMESPACE_NSEC, ISC_R_SUCCESS, 2, { ".", "b." } }, + { "b.", DNS_DBNAMESPACE_NSEC3, ISC_R_SUCCESS, 2, { ".", "b." } }, + + { "b.a.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, + 3, + { ".", "a.", "b.a." } }, + { "b.a.", + DNS_DBNAMESPACE_NSEC, + ISC_R_SUCCESS, + 3, + { ".", "a.", "b.a." } }, + { "b.a.", + DNS_DBNAMESPACE_NSEC3, + ISC_R_SUCCESS, + 3, + { ".", "a.", "b.a." } }, + + { "c.", DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 1, { "." } }, + { "c.", DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 1, { "." } }, + { "c.", DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 1, { "." } }, + { "e.d.c.b.a.", + DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS, 5, { ".", "a.", "b.a.", "c.b.a.", "e.d.c.b.a." } }, - { "a.b.c.d.", ISC_R_SUCCESS, 3, { ".", "c.d.", "a.b.c.d." } }, - { "b.c.d.", DNS_R_PARTIALMATCH, 2, { ".", "c.d." } }, + { "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, + ISC_R_SUCCESS, + 5, + { ".", "a.", "b.a.", "c.b.a.", "e.d.c.b.a." } }, + { "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC3, + ISC_R_SUCCESS, + 5, + { ".", "a.", "b.a.", "c.b.a.", "e.d.c.b.a." } }, + + { "a.b.c.d.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, + 3, + { ".", "c.d.", "a.b.c.d." } }, + { "a.b.c.d.", + DNS_DBNAMESPACE_NSEC, + ISC_R_SUCCESS, + 3, + { ".", "c.d.", "a.b.c.d." } }, + { "a.b.c.d.", + DNS_DBNAMESPACE_NSEC3, + ISC_R_SUCCESS, + 3, + { ".", "c.d.", "a.b.c.d." } }, + + { "b.c.d.", + DNS_DBNAMESPACE_NORMAL, + DNS_R_PARTIALMATCH, + 2, + { ".", "c.d." } }, + { "b.c.d.", + DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, + 2, + { ".", "c.d." } }, + { "b.c.d.", + DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, + 2, + { ".", "c.d." } }, + { "z.x.k.c.d.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 3, { ".", "c.d.", "x.k.c.d." } }, - { NULL, 0, 0, { NULL } }, + { "z.x.k.c.d.", + DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, + 3, + { ".", "c.d.", "x.k.c.d." } }, + { "z.x.k.c.d.", + DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, + 3, + { ".", "c.d.", "x.k.c.d." } }, + + { NULL, 0, 0, 0, { NULL } }, }; check_qpchain(qp, check1); @@ -610,12 +741,29 @@ ISC_RUN_TEST_IMPL(qpchain) { dns_qp_create(mctx, &string_methods, NULL, &qp); while (insert2[i][0] != '\0') { - insert_str(qp, insert2[i++]); + insert_name(qp, insert2[i], DNS_DBNAMESPACE_NORMAL); + insert_name(qp, insert2[i], DNS_DBNAMESPACE_NSEC); + insert_name(qp, insert2[i], DNS_DBNAMESPACE_NSEC3); + i++; } static struct check_qpchain check2[] = { - { "f.c.b.a.", DNS_R_PARTIALMATCH, 1, { "a." } }, - { NULL, 0, 0, { NULL } }, + { "f.c.b.a.", + DNS_DBNAMESPACE_NORMAL, + DNS_R_PARTIALMATCH, + 1, + { "a." } }, + { "f.c.b.a.", + DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, + 1, + { "a." } }, + { "f.c.b.a.", + DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, + 1, + { "a." } }, + { NULL, 0, 0, 0, { NULL } }, }; check_qpchain(qp, check2); @@ -624,7 +772,9 @@ ISC_RUN_TEST_IMPL(qpchain) { struct check_predecessors { const char *query; + dns_namespace_t space; const char *predecessor; + dns_namespace_t pspace; isc_result_t result; int remaining; }; @@ -637,6 +787,7 @@ check_predecessors_withchain(dns_qp_t *qp, struct check_predecessors check[], dns_name_t *name = dns_fixedname_initname(&fn1); dns_name_t *pred = dns_fixedname_initname(&fn2); char *namestr = NULL; + uint32_t ival; for (int i = 0; check[i].query != NULL; i++) { dns_qpiter_t it; @@ -655,9 +806,15 @@ check_predecessors_withchain(dns_qp_t *qp, struct check_predecessors check[], result = dns_name_tostring(expred, &predstr, mctx); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_qp_lookup(qp, name, NULL, &it, chain, NULL, NULL); + result = dns_qp_lookup(qp, name, check[i].space, NULL, &it, + chain, NULL, NULL); #if 0 - fprintf(stderr, "%s: expected %s got %s\n", check[i].query, + fprintf(stderr, "%s %s: expected %s got %s\n", check[i].query, + check[i].space == DNS_DBNAMESPACE_NSEC3 + ? "NSEC3" + : (check[i].space == DNS_DBNAMESPACE_NSEC + ? "NSEC" + : "NORMAL"), isc_result_totext(check[i].result), isc_result_totext(result)); #endif @@ -668,26 +825,28 @@ check_predecessors_withchain(dns_qp_t *qp, struct check_predecessors check[], * we found an exact match; iterate to find * the predecessor. */ - result = dns_qpiter_prev(&it, pred, NULL, NULL); + result = dns_qpiter_prev(&it, pred, NULL, &ival); if (result == ISC_R_NOMORE) { - result = dns_qpiter_prev(&it, pred, NULL, NULL); + result = dns_qpiter_prev(&it, pred, NULL, + &ival); } } else { /* * we didn't find a match, so the iterator should * already be pointed at the predecessor node. */ - result = dns_qpiter_current(&it, pred, NULL, NULL); + result = dns_qpiter_current(&it, pred, NULL, &ival); } assert_int_equal(result, ISC_R_SUCCESS); result = dns_name_tostring(pred, &namestr, mctx); #if 0 - fprintf(stderr, "... expected predecessor %s got %s\n", - predstr, namestr); + fprintf(stderr, "... expected predecessor %s %u got %s %u\n", + predstr, check[i].pspace, namestr, ival); #endif assert_int_equal(result, ISC_R_SUCCESS); assert_string_equal(namestr, predstr); + assert_int_equal(ival, check[i].pspace); #if 0 fprintf(stderr, "%d: remaining names after %s:\n", i, namestr); @@ -706,10 +865,12 @@ check_predecessors_withchain(dns_qp_t *qp, struct check_predecessors check[], #endif j++; } + #if 0 - fprintf(stderr, "\n...expected %d got %d\n", - check[i].remaining, j); + fprintf(stderr, "\n...expected %d got %d\n", check[i].remaining, + j); #endif + assert_int_equal(j, check[i].remaining); } } @@ -734,87 +895,490 @@ ISC_RUN_TEST_IMPL(predecessors) { dns_qp_create(mctx, &string_methods, NULL, &qp); while (insert[i][0] != '\0') { - insert_str(qp, insert[i++]); + insert_name(qp, insert[i], DNS_DBNAMESPACE_NORMAL); + insert_name(qp, insert[i], DNS_DBNAMESPACE_NSEC); + insert_name(qp, insert[i], DNS_DBNAMESPACE_NSEC3); + i++; } /* first check: no root label in the database */ static struct check_predecessors check1[] = { - { ".", "moops.", ISC_R_NOTFOUND, 0 }, - { "a.", "moops.", ISC_R_SUCCESS, 0 }, - { "b.a.", "a.", ISC_R_SUCCESS, 14 }, - { "b.", "e.d.c.b.a.", ISC_R_SUCCESS, 11 }, - { "aaa.a.", "a.", DNS_R_PARTIALMATCH, 14 }, - { "ddd.a.", "e.d.c.b.a.", DNS_R_PARTIALMATCH, 11 }, - { "d.c.", "c.b.b.", ISC_R_NOTFOUND, 9 }, - { "1.2.c.b.a.", "c.b.a.", DNS_R_PARTIALMATCH, 12 }, - { "a.b.c.e.f.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 }, - { "z.y.x.", "moops.", ISC_R_NOTFOUND, 0 }, - { "w.c.d.", "x.k.c.d.", DNS_R_PARTIALMATCH, 6 }, - { "z.z.z.z.k.c.d.", "x.k.c.d.", DNS_R_PARTIALMATCH, 6 }, - { "w.k.c.d.", "a.b.c.d.", DNS_R_PARTIALMATCH, 7 }, - { "d.a.", "e.d.c.b.a.", DNS_R_PARTIALMATCH, 11 }, - { "0.b.c.d.e.", "x.k.c.d.", ISC_R_NOTFOUND, 6 }, - { "b.d.", "c.b.b.", ISC_R_NOTFOUND, 9 }, - { "mon.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 }, - { "moor.", "moops.", ISC_R_NOTFOUND, 0 }, - { "mopbop.", "moops.", ISC_R_NOTFOUND, 0 }, - { "moppop.", "moops.", ISC_R_NOTFOUND, 0 }, - { "mopps.", "moops.", ISC_R_NOTFOUND, 0 }, - { "mopzop.", "moops.", ISC_R_NOTFOUND, 0 }, - { "mop.", "moops.", ISC_R_NOTFOUND, 0 }, - { "monbop.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 }, - { "monpop.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 }, - { "monps.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 }, - { "monzop.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 }, - { "mon.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 }, - { "moop.", "moon.", ISC_R_NOTFOUND, 1 }, - { "moopser.", "moops.", ISC_R_NOTFOUND, 0 }, - { "monky.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 }, - { "monkey.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 }, - { "monker.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 }, - { NULL, NULL, 0, 0 } + { ".", DNS_DBNAMESPACE_NORMAL, "moops.", DNS_DBNAMESPACE_NSEC3, + ISC_R_NOTFOUND, 0 }, + { ".", DNS_DBNAMESPACE_NSEC, "moops.", DNS_DBNAMESPACE_NORMAL, + ISC_R_NOTFOUND, 30 }, + { ".", DNS_DBNAMESPACE_NSEC3, "moops.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 15 }, + + { "a.", DNS_DBNAMESPACE_NORMAL, "moops.", DNS_DBNAMESPACE_NSEC3, + ISC_R_SUCCESS, 0 }, + { "a.", DNS_DBNAMESPACE_NSEC, "moops.", DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, 30 }, + { "a.", DNS_DBNAMESPACE_NSEC3, "moops.", DNS_DBNAMESPACE_NSEC, + ISC_R_SUCCESS, 15 }, + + { "b.a.", DNS_DBNAMESPACE_NORMAL, "a.", DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, 44 }, + { "b.a.", DNS_DBNAMESPACE_NSEC, "a.", DNS_DBNAMESPACE_NSEC, + ISC_R_SUCCESS, 29 }, + { "b.a.", DNS_DBNAMESPACE_NSEC3, "a.", DNS_DBNAMESPACE_NSEC3, + ISC_R_SUCCESS, 14 }, + + { "b.", DNS_DBNAMESPACE_NORMAL, "e.d.c.b.a.", + DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS, 41 }, + { "b.", DNS_DBNAMESPACE_NSEC, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_SUCCESS, 26 }, + { "b.", DNS_DBNAMESPACE_NSEC3, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC3, ISC_R_SUCCESS, 11 }, + + { "aaa.a.", DNS_DBNAMESPACE_NORMAL, "a.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 44 }, + { "aaa.a.", DNS_DBNAMESPACE_NSEC, "a.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 29 }, + { "aaa.a.", DNS_DBNAMESPACE_NSEC3, "a.", DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, 14 }, + + { "ddd.a.", DNS_DBNAMESPACE_NORMAL, "e.d.c.b.a.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 41 }, + { "ddd.a.", DNS_DBNAMESPACE_NSEC, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 26 }, + { "ddd.a.", DNS_DBNAMESPACE_NSEC3, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 11 }, + + { "d.c.", DNS_DBNAMESPACE_NORMAL, "c.b.b.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 39 }, + { "d.c.", DNS_DBNAMESPACE_NSEC, "c.b.b.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 24 }, + { "d.c.", DNS_DBNAMESPACE_NSEC3, "c.b.b.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 9 }, + + { "1.2.c.b.a.", DNS_DBNAMESPACE_NORMAL, "c.b.a.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 42 }, + { "1.2.c.b.a.", DNS_DBNAMESPACE_NSEC, "c.b.a.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 27 }, + { "1.2.c.b.a.", DNS_DBNAMESPACE_NSEC3, "c.b.a.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 12 }, + + { "a.b.c.e.f.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 35 }, + { "a.b.c.e.f.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 20 }, + { "a.b.c.e.f.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 5 }, + + { "z.y.x.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 30 }, + { "z.y.x.", DNS_DBNAMESPACE_NSEC, "moops.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 15 }, + { "z.y.x.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0 }, + + { "w.c.d.", DNS_DBNAMESPACE_NORMAL, "x.k.c.d.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 36 }, + { "w.c.d.", DNS_DBNAMESPACE_NSEC, "x.k.c.d.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 21 }, + { "w.c.d.", DNS_DBNAMESPACE_NSEC3, "x.k.c.d.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 6 }, + + { "z.z.z.z.k.c.d.", DNS_DBNAMESPACE_NORMAL, "x.k.c.d.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 36 }, + { "z.z.z.z.k.c.d.", DNS_DBNAMESPACE_NSEC, "x.k.c.d.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 21 }, + { "z.z.z.z.k.c.d.", DNS_DBNAMESPACE_NSEC3, "x.k.c.d.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 6 }, + + { "w.k.c.d.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 37 }, + { "w.k.c.d.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 22 }, + { "w.k.c.d.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 7 }, + + { "d.a.", DNS_DBNAMESPACE_NORMAL, "e.d.c.b.a.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 41 }, + { "d.a.", DNS_DBNAMESPACE_NSEC, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 26 }, + { "d.a.", DNS_DBNAMESPACE_NSEC3, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 11 }, + + { "0.b.c.d.e.", DNS_DBNAMESPACE_NORMAL, "x.k.c.d.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 36 }, + { "0.b.c.d.e.", DNS_DBNAMESPACE_NSEC, "x.k.c.d.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 21 }, + { "0.b.c.d.e.", DNS_DBNAMESPACE_NSEC3, "x.k.c.d.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 6 }, + + { "b.d.", DNS_DBNAMESPACE_NORMAL, "c.b.b.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 39 }, + { "b.d.", DNS_DBNAMESPACE_NSEC, "c.b.b.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 24 }, + { "b.d.", DNS_DBNAMESPACE_NSEC3, "c.b.b.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 9 }, + + { "mon.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 35 }, + { "mon.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 20 }, + { "mon.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 5 }, + + { "moor.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 30 }, + { "moor.", DNS_DBNAMESPACE_NSEC, "moops.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 15 }, + { "moor.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0 }, + + { "mopbop.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 30 }, + { "mopbop.", DNS_DBNAMESPACE_NSEC, "moops.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 15 }, + { "mopbop.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0 }, + + { "moppop.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 30 }, + { "moppop.", DNS_DBNAMESPACE_NSEC, "moops.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 15 }, + { "moppop.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0 }, + + { "mopps.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 30 }, + { "mopps.", DNS_DBNAMESPACE_NSEC, "moops.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 15 }, + { "mopps.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0 }, + + { "mopzop.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 30 }, + { "mopzop.", DNS_DBNAMESPACE_NSEC, "moops.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 15 }, + { "mopzop.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0 }, + + { "mop.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 30 }, + { "mop.", DNS_DBNAMESPACE_NSEC, "moops.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 15 }, + { "mop.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0 }, + + { "monbop.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 35 }, + { "monbop.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 20 }, + { "monbop.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 5 }, + + { "monpop.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 35 }, + { "monpop.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 20 }, + { "monpop.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 5 }, + + { "monps.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 35 }, + { "monps.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 20 }, + { "monps.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 5 }, + + { "monzop.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 35 }, + { "monzop.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 20 }, + { "monzop.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 5 }, + + { "mon.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 35 }, + { "mon.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 20 }, + { "mon.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 5 }, + + { "moop.", DNS_DBNAMESPACE_NORMAL, "moon.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 31 }, + { "moop.", DNS_DBNAMESPACE_NSEC, "moon.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 16 }, + { "moop.", DNS_DBNAMESPACE_NSEC3, "moon.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 1 }, + + { "moopser.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 30 }, + { "moopser.", DNS_DBNAMESPACE_NSEC, "moops.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 15 }, + { "moopser.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0 }, + + { "monky.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 35 }, + { "monky.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 20 }, + { "monky.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 5 }, + + { "monkey.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 35 }, + { "monkey.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 20 }, + { "monkey.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 5 }, + + { "monker.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 35 }, + { "monker.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 20 }, + { "monker.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 5 }, + + { NULL, 0, NULL, 0, 0, 0 } }; check_predecessors(qp, check1); /* second check: add a root label and try again */ const char root[16] = "."; - insert_str(qp, root); + insert_name(qp, root, DNS_DBNAMESPACE_NORMAL); + insert_name(qp, root, DNS_DBNAMESPACE_NSEC); + insert_name(qp, root, DNS_DBNAMESPACE_NSEC3); + i++; static struct check_predecessors check2[] = { - { ".", "moops.", ISC_R_SUCCESS, 0 }, - { "a.", ".", ISC_R_SUCCESS, 15 }, - { "b.a.", "a.", ISC_R_SUCCESS, 14 }, - { "b.", "e.d.c.b.a.", ISC_R_SUCCESS, 11 }, - { "aaa.a.", "a.", DNS_R_PARTIALMATCH, 14 }, - { "ddd.a.", "e.d.c.b.a.", DNS_R_PARTIALMATCH, 11 }, - { "d.c.", "c.b.b.", DNS_R_PARTIALMATCH, 9 }, - { "1.2.c.b.a.", "c.b.a.", DNS_R_PARTIALMATCH, 12 }, - { "a.b.c.e.f.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 }, - { "z.y.x.", "moops.", DNS_R_PARTIALMATCH, 0 }, - { "w.c.d.", "x.k.c.d.", DNS_R_PARTIALMATCH, 6 }, - { "z.z.z.z.k.c.d.", "x.k.c.d.", DNS_R_PARTIALMATCH, 6 }, - { "w.k.c.d.", "a.b.c.d.", DNS_R_PARTIALMATCH, 7 }, - { "d.a.", "e.d.c.b.a.", DNS_R_PARTIALMATCH, 11 }, - { "0.b.c.d.e.", "x.k.c.d.", DNS_R_PARTIALMATCH, 6 }, - { "mon.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 }, - { "moor.", "moops.", DNS_R_PARTIALMATCH, 0 }, - { "mopbop.", "moops.", DNS_R_PARTIALMATCH, 0 }, - { "moppop.", "moops.", DNS_R_PARTIALMATCH, 0 }, - { "mopps.", "moops.", DNS_R_PARTIALMATCH, 0 }, - { "mopzop.", "moops.", DNS_R_PARTIALMATCH, 0 }, - { "mop.", "moops.", DNS_R_PARTIALMATCH, 0 }, - { "monbop.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 }, - { "monpop.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 }, - { "monps.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 }, - { "monzop.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 }, - { "mon.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 }, - { "moop.", "moon.", DNS_R_PARTIALMATCH, 1 }, - { "moopser.", "moops.", DNS_R_PARTIALMATCH, 0 }, - { "monky.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 }, - { "monkey.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 }, - { "monker.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 }, - { NULL, NULL, 0, 0 } + { ".", DNS_DBNAMESPACE_NORMAL, "moops.", DNS_DBNAMESPACE_NSEC3, + ISC_R_SUCCESS, 0 }, + { ".", DNS_DBNAMESPACE_NSEC, "moops.", DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, 32 }, + { ".", DNS_DBNAMESPACE_NSEC3, "moops.", DNS_DBNAMESPACE_NSEC, + ISC_R_SUCCESS, 16 }, + + { "a.", DNS_DBNAMESPACE_NORMAL, ".", DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, 47 }, + { "a.", DNS_DBNAMESPACE_NSEC, ".", DNS_DBNAMESPACE_NSEC, + ISC_R_SUCCESS, 31 }, + { "a.", DNS_DBNAMESPACE_NSEC3, ".", DNS_DBNAMESPACE_NSEC3, + ISC_R_SUCCESS, 15 }, + + { "b.a.", DNS_DBNAMESPACE_NORMAL, "a.", DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, 46 }, + { "b.a.", DNS_DBNAMESPACE_NSEC, "a.", DNS_DBNAMESPACE_NSEC, + ISC_R_SUCCESS, 30 }, + { "b.a.", DNS_DBNAMESPACE_NSEC3, "a.", DNS_DBNAMESPACE_NSEC3, + ISC_R_SUCCESS, 14 }, + + { "b.", DNS_DBNAMESPACE_NORMAL, "e.d.c.b.a.", + DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS, 43 }, + { "b.", DNS_DBNAMESPACE_NSEC, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_SUCCESS, 27 }, + { "b.", DNS_DBNAMESPACE_NSEC3, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC3, ISC_R_SUCCESS, 11 }, + + { "aaa.a.", DNS_DBNAMESPACE_NORMAL, "a.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 46 }, + { "aaa.a.", DNS_DBNAMESPACE_NSEC, "a.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 30 }, + { "aaa.a.", DNS_DBNAMESPACE_NSEC3, "a.", DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, 14 }, + + { "ddd.a.", DNS_DBNAMESPACE_NORMAL, "e.d.c.b.a.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 43 }, + { "ddd.a.", DNS_DBNAMESPACE_NSEC, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 27 }, + { "ddd.a.", DNS_DBNAMESPACE_NSEC3, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 11 }, + + { "d.c.", DNS_DBNAMESPACE_NORMAL, "c.b.b.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 41 }, + { "d.c.", DNS_DBNAMESPACE_NSEC, "c.b.b.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 25 }, + { "d.c.", DNS_DBNAMESPACE_NSEC3, "c.b.b.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 9 }, + + { "1.2.c.b.a.", DNS_DBNAMESPACE_NORMAL, "c.b.a.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 44 }, + { "1.2.c.b.a.", DNS_DBNAMESPACE_NSEC, "c.b.a.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 28 }, + { "1.2.c.b.a.", DNS_DBNAMESPACE_NSEC3, "c.b.a.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 12 }, + + { "a.b.c.e.f.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 37 }, + { "a.b.c.e.f.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 21 }, + { "a.b.c.e.f.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 5 }, + + { "z.y.x.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 32 }, + { "z.y.x.", DNS_DBNAMESPACE_NSEC, "moops.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 16 }, + { "z.y.x.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "w.c.d.", DNS_DBNAMESPACE_NORMAL, "x.k.c.d.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 38 }, + { "w.c.d.", DNS_DBNAMESPACE_NSEC, "x.k.c.d.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 22 }, + { "w.c.d.", DNS_DBNAMESPACE_NSEC3, "x.k.c.d.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 6 }, + + { "z.z.z.z.k.c.d.", DNS_DBNAMESPACE_NORMAL, "x.k.c.d.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 38 }, + { "z.z.z.z.k.c.d.", DNS_DBNAMESPACE_NSEC, "x.k.c.d.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 22 }, + { "z.z.z.z.k.c.d.", DNS_DBNAMESPACE_NSEC3, "x.k.c.d.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 6 }, + + { "w.k.c.d.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 39 }, + { "w.k.c.d.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 23 }, + { "w.k.c.d.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 7 }, + + { "d.a.", DNS_DBNAMESPACE_NORMAL, "e.d.c.b.a.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 43 }, + { "d.a.", DNS_DBNAMESPACE_NSEC, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 27 }, + { "d.a.", DNS_DBNAMESPACE_NSEC3, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 11 }, + + { "0.b.c.d.e.", DNS_DBNAMESPACE_NORMAL, "x.k.c.d.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 38 }, + { "0.b.c.d.e.", DNS_DBNAMESPACE_NSEC, "x.k.c.d.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 22 }, + { "0.b.c.d.e.", DNS_DBNAMESPACE_NSEC3, "x.k.c.d.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 6 }, + + { "b.d.", DNS_DBNAMESPACE_NORMAL, "c.b.b.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 41 }, + { "b.d.", DNS_DBNAMESPACE_NSEC, "c.b.b.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 25 }, + { "b.d.", DNS_DBNAMESPACE_NSEC3, "c.b.b.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 9 }, + + { "mon.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 37 }, + { "mon.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 21 }, + { "mon.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 5 }, + + { "moor.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 32 }, + { "moor.", DNS_DBNAMESPACE_NSEC, "moops.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 16 }, + { "moor.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "mopbop.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 32 }, + { "mopbop.", DNS_DBNAMESPACE_NSEC, "moops.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 16 }, + { "mopbop.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "moppop.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 32 }, + { "moppop.", DNS_DBNAMESPACE_NSEC, "moops.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 16 }, + { "moppop.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "mopps.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 32 }, + { "mopps.", DNS_DBNAMESPACE_NSEC, "moops.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 16 }, + { "mopps.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "mopzop.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 32 }, + { "mopzop.", DNS_DBNAMESPACE_NSEC, "moops.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 16 }, + { "mopzop.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "mop.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 32 }, + { "mop.", DNS_DBNAMESPACE_NSEC, "moops.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 16 }, + { "mop.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "monbop.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 37 }, + { "monbop.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 21 }, + { "monbop.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 5 }, + + { "monpop.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 37 }, + { "monpop.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 21 }, + { "monpop.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 5 }, + + { "monps.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 37 }, + { "monps.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 21 }, + { "monps.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 5 }, + + { "monzop.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 37 }, + { "monzop.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 21 }, + { "monzop.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 5 }, + + { "mon.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 37 }, + { "mon.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 21 }, + { "mon.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 5 }, + + { "moop.", DNS_DBNAMESPACE_NORMAL, "moon.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 33 }, + { "moop.", DNS_DBNAMESPACE_NSEC, "moon.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 17 }, + { "moop.", DNS_DBNAMESPACE_NSEC3, "moon.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 1 }, + + { "moopser.", DNS_DBNAMESPACE_NORMAL, "moops.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 32 }, + { "moopser.", DNS_DBNAMESPACE_NSEC, "moops.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 16 }, + { "moopser.", DNS_DBNAMESPACE_NSEC3, "moops.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "monky.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 37 }, + { "monky.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 21 }, + { "monky.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 5 }, + + { "monkey.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 37 }, + { "monkey.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 21 }, + { "monkey.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 5 }, + + { "monker.", DNS_DBNAMESPACE_NORMAL, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 37 }, + { "monker.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 21 }, + { "monker.", DNS_DBNAMESPACE_NSEC3, "a.b.c.d.e.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 5 }, + + { NULL, 0, NULL, 0, 0, 0 } }; check_predecessors(qp, check2); @@ -850,18 +1414,63 @@ ISC_RUN_TEST_IMPL(fixiterator) { dns_qp_create(mctx, &string_methods, NULL, &qp); while (insert1[i][0] != '\0') { - insert_str(qp, insert1[i++]); + insert_name(qp, insert1[i], DNS_DBNAMESPACE_NORMAL); + insert_name(qp, insert1[i], DNS_DBNAMESPACE_NSEC); + insert_name(qp, insert1[i], DNS_DBNAMESPACE_NSEC3); + i++; } static struct check_predecessors check1[] = { - { "newtext.dynamic.", "mx.dynamic.", DNS_R_PARTIALMATCH, 7 }, - { "nsd.dynamic.", "ns.dynamic.", DNS_R_PARTIALMATCH, 6 }, - { "nsf.dynamic.", "nsec.dynamic.", DNS_R_PARTIALMATCH, 5 }, - { "d.", "trailing.", ISC_R_NOTFOUND, 0 }, - { "absent.", "trailing.", ISC_R_NOTFOUND, 0 }, - { "nonexistent.", "txt.dynamic.", ISC_R_NOTFOUND, 1 }, - { "wayback.", "trailing.", ISC_R_NOTFOUND, 0 }, - { NULL, NULL, 0, 0 } + { "newtext.dynamic.", DNS_DBNAMESPACE_NORMAL, "mx.dynamic.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 41 }, + { "newtext.dynamic.", DNS_DBNAMESPACE_NSEC, "mx.dynamic.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 24 }, + { "newtext.dynamic.", DNS_DBNAMESPACE_NSEC3, "mx.dynamic.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 7 }, + + { "nsd.dynamic.", DNS_DBNAMESPACE_NORMAL, "ns.dynamic.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 40 }, + { "nsd.dynamic.", DNS_DBNAMESPACE_NSEC, "ns.dynamic.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 23 }, + { "nsd.dynamic.", DNS_DBNAMESPACE_NSEC3, "ns.dynamic.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 6 }, + + { "nsf.dynamic.", DNS_DBNAMESPACE_NORMAL, "nsec.dynamic.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 39 }, + { "nsf.dynamic.", DNS_DBNAMESPACE_NSEC, "nsec.dynamic.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 22 }, + { "nsf.dynamic.", DNS_DBNAMESPACE_NSEC3, "nsec.dynamic.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 5 }, + + { "d.", DNS_DBNAMESPACE_NORMAL, "trailing.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0 }, + { "d.", DNS_DBNAMESPACE_NSEC, "trailing.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 34 }, + { "d.", DNS_DBNAMESPACE_NSEC3, "trailing.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 17 }, + + { "absent.", DNS_DBNAMESPACE_NORMAL, "trailing.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0 }, + { "absent.", DNS_DBNAMESPACE_NSEC, "trailing.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 34 }, + { "absent.", DNS_DBNAMESPACE_NSEC3, "trailing.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 17 }, + + { "nonexistent.", DNS_DBNAMESPACE_NORMAL, "txt.dynamic.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 35 }, + { "nonexistent.", DNS_DBNAMESPACE_NSEC, "txt.dynamic.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 18 }, + { "nonexistent.", DNS_DBNAMESPACE_NSEC3, "txt.dynamic.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 1 }, + + { "wayback.", DNS_DBNAMESPACE_NORMAL, "trailing.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 34 }, + { "wayback.", DNS_DBNAMESPACE_NSEC, "trailing.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 17 }, + { "wayback.", DNS_DBNAMESPACE_NSEC3, "trailing.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0 }, + + { NULL, 0, NULL, 0, 0, 0 } }; check_predecessors(qp, check1); @@ -872,15 +1481,42 @@ ISC_RUN_TEST_IMPL(fixiterator) { dns_qp_create(mctx, &string_methods, NULL, &qp); while (insert2[i][0] != '\0') { - insert_str(qp, insert2[i++]); + insert_name(qp, insert2[i], DNS_DBNAMESPACE_NORMAL); + insert_name(qp, insert2[i], DNS_DBNAMESPACE_NSEC); + insert_name(qp, insert2[i], DNS_DBNAMESPACE_NSEC3); + i++; } static struct check_predecessors check2[] = { - { "acb.", "abc.", DNS_R_PARTIALMATCH, 0 }, - { "acc.", "abc.", DNS_R_PARTIALMATCH, 0 }, - { "abbb.", "abb.", DNS_R_PARTIALMATCH, 1 }, - { "aab.", ".", DNS_R_PARTIALMATCH, 2 }, - { NULL, NULL, 0, 0 } + { "acb.", DNS_DBNAMESPACE_NORMAL, "abc.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 6 }, + { "acb.", DNS_DBNAMESPACE_NSEC, "abc.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 3 }, + { "acb.", DNS_DBNAMESPACE_NSEC3, "abc.", DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, 0 }, + + { "acc.", DNS_DBNAMESPACE_NORMAL, "abc.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 6 }, + { "acc.", DNS_DBNAMESPACE_NSEC, "abc.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 3 }, + { "acc.", DNS_DBNAMESPACE_NSEC3, "abc.", DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, 0 }, + + { "abbb.", DNS_DBNAMESPACE_NORMAL, "abb.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 7 }, + { "abbb.", DNS_DBNAMESPACE_NSEC, "abb.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 4 }, + { "abbb.", DNS_DBNAMESPACE_NSEC3, "abb.", DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, 1 }, + + { "aab.", DNS_DBNAMESPACE_NORMAL, ".", DNS_DBNAMESPACE_NORMAL, + DNS_R_PARTIALMATCH, 8 }, + { "aab.", DNS_DBNAMESPACE_NSEC, ".", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 5 }, + { "aab.", DNS_DBNAMESPACE_NSEC3, ".", DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, 2 }, + + { NULL, 0, NULL, 0, 0, 0 } }; check_predecessors(qp, check2); @@ -896,13 +1532,24 @@ ISC_RUN_TEST_IMPL(fixiterator) { dns_qp_create(mctx, &string_methods, NULL, &qp); while (insert3[i][0] != '\0') { - insert_str(qp, insert3[i++]); + insert_name(qp, insert3[i], DNS_DBNAMESPACE_NORMAL); + insert_name(qp, insert3[i], DNS_DBNAMESPACE_NSEC); + insert_name(qp, insert3[i], DNS_DBNAMESPACE_NSEC3); + i++; } - static struct check_predecessors check3[] = { { "key-is-21556.example.", - "key-is-14779.example.", - DNS_R_PARTIALMATCH, 2 }, - { NULL, NULL, 0, 0 } }; + static struct check_predecessors check3[] = { + { "key-is-21556.example.", DNS_DBNAMESPACE_NORMAL, + "key-is-14779.example.", DNS_DBNAMESPACE_NORMAL, + DNS_R_PARTIALMATCH, 12 }, + { "key-is-21556.example.", DNS_DBNAMESPACE_NSEC, + "key-is-14779.example.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 7 }, + { "key-is-21556.example.", DNS_DBNAMESPACE_NSEC3, + "key-is-14779.example.", DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, 2 }, + { NULL, 0, NULL, 0, 0, 0 } + }; check_predecessors(qp, check3); dns_qp_destroy(&qp); @@ -913,22 +1560,505 @@ ISC_RUN_TEST_IMPL(fixiterator) { dns_qp_create(mctx, &string_methods, NULL, &qp); while (insert4[i][0] != '\0') { - insert_str(qp, insert4[i++]); + insert_name(qp, insert4[i], DNS_DBNAMESPACE_NORMAL); + insert_name(qp, insert4[i], DNS_DBNAMESPACE_NSEC); + insert_name(qp, insert4[i], DNS_DBNAMESPACE_NSEC3); + i++; } static struct check_predecessors check4[] = { - { "\\007.", "\\000\\009.", DNS_R_PARTIALMATCH, 0 }, - { "\\009.", "\\000\\009.", DNS_R_PARTIALMATCH, 0 }, - { "\\045.", "\\000\\009.", DNS_R_PARTIALMATCH, 0 }, - { "\\044.", "\\000\\009.", DNS_R_PARTIALMATCH, 0 }, - { "\\000.", ".", ISC_R_SUCCESS, 3 }, - { NULL, NULL, 0, 0 }, + { "\\007.", DNS_DBNAMESPACE_NORMAL, "\\000\\009.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 8 }, + { "\\007.", DNS_DBNAMESPACE_NSEC, "\\000\\009.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 4 }, + { "\\007.", DNS_DBNAMESPACE_NSEC3, "\\000\\009.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "\\009.", DNS_DBNAMESPACE_NORMAL, "\\000\\009.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 8 }, + { "\\009.", DNS_DBNAMESPACE_NSEC, "\\000\\009.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 4 }, + { "\\009.", DNS_DBNAMESPACE_NSEC3, "\\000\\009.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "\\045.", DNS_DBNAMESPACE_NORMAL, "\\000\\009.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 8 }, + { "\\045.", DNS_DBNAMESPACE_NSEC, "\\000\\009.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 4 }, + { "\\045.", DNS_DBNAMESPACE_NSEC3, "\\000\\009.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "\\044.", DNS_DBNAMESPACE_NORMAL, "\\000\\009.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 8 }, + { "\\044.", DNS_DBNAMESPACE_NSEC, "\\000\\009.", + DNS_DBNAMESPACE_NSEC, DNS_R_PARTIALMATCH, 4 }, + { "\\044.", DNS_DBNAMESPACE_NSEC3, "\\000\\009.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "\\000.", DNS_DBNAMESPACE_NORMAL, ".", DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, 11 }, + { "\\000.", DNS_DBNAMESPACE_NSEC, ".", DNS_DBNAMESPACE_NSEC, + ISC_R_SUCCESS, 7 }, + { "\\000.", DNS_DBNAMESPACE_NSEC3, ".", DNS_DBNAMESPACE_NSEC3, + ISC_R_SUCCESS, 3 }, + + { NULL, 0, NULL, 0, 0, 0 }, }; check_predecessors(qp, check4); dns_qp_destroy(&qp); } +struct inserting { + /* Fixed size strings [32] should ensure leaf-compatible alignment. */ + const char name[32]; + dns_namespace_t space; + /* Padding */ + uint8_t pad1; + uint16_t pad2; +}; + +struct check_delete { + const char *name; + dns_namespace_t space; + isc_result_t result; +}; + +static void +check_delete(dns_qp_t *qp, struct check_delete check[]) { + for (int i = 0; check[i].name != NULL; i++) { + isc_result_t result; + dns_fixedname_t fn1; + dns_name_t *name = dns_fixedname_initname(&fn1); + dns_qpchain_t chain; + + dns_qpchain_init(qp, &chain); + dns_test_namefromstring(check[i].name, &fn1); + result = dns_qp_deletename(qp, name, check[i].space, NULL, + NULL); +#if 0 + fprintf(stderr, "%s %u %s (expected %s)\n", check[i].name, + check[i].space, isc_result_totext(result), + isc_result_totext(check[i].result)); +#endif + assert_int_equal(result, check[i].result); + } +} + +ISC_RUN_TEST_IMPL(qpkey_delete) { + int i = 0; + dns_qp_t *qp = NULL; + static struct inserting insert1[] = { + { "a.", DNS_DBNAMESPACE_NORMAL, 0, 0 }, + { "b.", DNS_DBNAMESPACE_NORMAL, 0, 0 }, + { "b.", DNS_DBNAMESPACE_NSEC, 0, 0 }, + { "b.", DNS_DBNAMESPACE_NSEC3, 0, 0 }, + { "b.a.", DNS_DBNAMESPACE_NORMAL, 0, 0 }, + { "b.a.", DNS_DBNAMESPACE_NSEC, 0, 0 }, + { "c.b.a.", DNS_DBNAMESPACE_NORMAL, 0, 0 }, + { "e.d.c.b.a.", DNS_DBNAMESPACE_NORMAL, 0, 0 }, + { "e.d.c.b.a.", DNS_DBNAMESPACE_NSEC, 0, 0 }, + { "c.b.b.", DNS_DBNAMESPACE_NSEC3, 0, 0 }, + { "c.d.", DNS_DBNAMESPACE_NSEC3, 0, 0 }, + { "a.b.c.d.", DNS_DBNAMESPACE_NORMAL, 0, 0 }, + { "a.b.c.d.e.", DNS_DBNAMESPACE_NORMAL, 0, 0 }, + { "", 0, 0, 0 }, + }; + /* + * NORMAL: a. + * NORMAL: b.a. + * NORMAL: c.b.a. + * NORMAL: e.d.c.b.a. + * NORMAL: b. + * NORMAL: a.b.c.d. + * NORMAL: a.b.c.d.e. + * + * NSEC: b.a. + * NSEC: e.d.c.b.a. + * NSEC: b. + * + * NSEC3: b. + * NSEC3: c.b.b. + * NSEC3: c.d. + */ + + dns_qp_create(mctx, &string_methods, NULL, &qp); + + while (insert1[i].name[0] != '\0') { + insert_name(qp, insert1[i].name, insert1[i].space); + i++; + } + + /* lookup checks before deleting */ + static struct check_qpchain chain1[] = { + { ".", DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 0, { NULL } }, + { ".", DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 0, { NULL } }, + { ".", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0, { NULL } }, + + { "a.", DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS, 1, { "a." } }, + { "a.", + DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, + 0, + { NULL } }, /* b.a. + */ + { "a.", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0, { NULL } }, + + { "b.", DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS, 1, { "b." } }, + { "b.", DNS_DBNAMESPACE_NSEC, ISC_R_SUCCESS, 1, { "b." } }, + { "b.", DNS_DBNAMESPACE_NSEC3, ISC_R_SUCCESS, 1, { "b." } }, + + { "b.a.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, + 2, + { "a.", "b.a." } }, + { "b.a.", DNS_DBNAMESPACE_NSEC, ISC_R_SUCCESS, 1, { "b.a." } }, + { "b.a.", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0, { NULL } }, + + { "c.b.a.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, + 3, + { "a.", "b.a.", "c.b.a." } }, + { "c.b.a.", + DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, + 1, + { "b.a." } }, + { "c.b.a.", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0, { NULL } }, + + { "c.", DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 0, { NULL } }, + { "c.", DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 0, { NULL } }, + { "c.", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0, { NULL } }, + + { "e.d.c.b.a.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, + 4, + { "a.", "b.a.", "c.b.a.", "e.d.c.b.a." } }, + { "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, + ISC_R_SUCCESS, + 2, + { "b.a.", "e.d.c.b.a." } }, + { "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC3, + ISC_R_NOTFOUND, + 0, + { NULL } }, + + { "a.b.c.d.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, + 1, + { "a.b.c.d." } }, + { "a.b.c.d.", + DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, + 0, + { NULL } }, + { "a.b.c.d.", + DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, + 1, + { "c.d." } }, + + { "b.c.d.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_NOTFOUND, + 0, + { NULL } }, /* a.b.c.d. */ + { "b.c.d.", DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 0, { NULL } }, + { "b.c.d.", + DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, + 1, + { "c.d." } }, + + { "f.b.b.d.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_NOTFOUND, + 0, + { NULL } }, + { "f.b.b.d.", + DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, + 0, + { NULL } }, + { "f.b.b.d.", + DNS_DBNAMESPACE_NSEC3, + ISC_R_NOTFOUND, + 0, + { NULL } }, + + { NULL, 0, 0, 0, { NULL } }, + }; + check_qpchain(qp, chain1); + + static struct check_predecessors pred1[] = { + { ".", DNS_DBNAMESPACE_NORMAL, "c.d.", DNS_DBNAMESPACE_NSEC3, + ISC_R_NOTFOUND, 0 }, + { ".", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 6 }, + { ".", DNS_DBNAMESPACE_NSEC3, "b.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 3 }, + + { "a.", DNS_DBNAMESPACE_NORMAL, "c.d.", DNS_DBNAMESPACE_NSEC3, + ISC_R_SUCCESS, 0 }, + { "a.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 6 }, + { "a.", DNS_DBNAMESPACE_NSEC3, "b.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 3 }, + + { "b.", DNS_DBNAMESPACE_NORMAL, "e.d.c.b.a.", + DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS, 9 }, + { "b.", DNS_DBNAMESPACE_NSEC, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_SUCCESS, 4 }, + { "b.", DNS_DBNAMESPACE_NSEC3, "b.", DNS_DBNAMESPACE_NSEC, + ISC_R_SUCCESS, 3 }, + + { "b.a.", DNS_DBNAMESPACE_NORMAL, "a.", DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, 12 }, + { "b.a.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS, 6 }, + { "b.a.", DNS_DBNAMESPACE_NSEC3, "b.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 3 }, + + { "c.b.a.", DNS_DBNAMESPACE_NORMAL, "b.a.", + DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS, 11 }, + { "c.b.a.", DNS_DBNAMESPACE_NSEC, "b.a.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 5 }, + { "c.b.a.", DNS_DBNAMESPACE_NSEC3, "b.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 3 }, + + { "c.", DNS_DBNAMESPACE_NORMAL, "b.", DNS_DBNAMESPACE_NORMAL, + ISC_R_NOTFOUND, 8 }, + { "c.", DNS_DBNAMESPACE_NSEC, "b.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 3 }, + { "c.", DNS_DBNAMESPACE_NSEC3, "c.b.b.", DNS_DBNAMESPACE_NSEC3, + ISC_R_NOTFOUND, 1 }, + + { "e.d.c.b.a.", DNS_DBNAMESPACE_NORMAL, "c.b.a.", + DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS, 10 }, + { "e.d.c.b.a.", DNS_DBNAMESPACE_NSEC, "b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_SUCCESS, 5 }, + { "e.d.c.b.a.", DNS_DBNAMESPACE_NSEC3, "b.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 3 }, + + { "a.b.c.d.", DNS_DBNAMESPACE_NORMAL, "b.", + DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS, 8 }, + { "a.b.c.d.", DNS_DBNAMESPACE_NSEC, "b.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 3 }, + { "a.b.c.d.", DNS_DBNAMESPACE_NSEC3, "c.d.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "b.c.d.", DNS_DBNAMESPACE_NORMAL, "b.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 8 }, + { "b.c.d.", DNS_DBNAMESPACE_NSEC, "b.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 3 }, + { "b.c.d.", DNS_DBNAMESPACE_NSEC3, "c.d.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "f.b.b.d.", DNS_DBNAMESPACE_NORMAL, "b.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 8 }, + { "f.b.b.d.", DNS_DBNAMESPACE_NSEC, "b.", DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, 3 }, + { "f.b.b.d.", DNS_DBNAMESPACE_NSEC3, "c.b.b.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 1 }, + + { NULL, 0, NULL, 0, 0, 0 }, + }; + check_predecessors(qp, pred1); + + /* delete checks */ + static struct check_delete del1[] = { + { ".", DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND }, + { "a.", DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND }, + { "a.", DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS }, + { "b.", DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS }, + { "b.", DNS_DBNAMESPACE_NSEC, ISC_R_SUCCESS }, + { "b.", DNS_DBNAMESPACE_NSEC3, ISC_R_SUCCESS }, + { "b.a.", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND }, + { "b.a.", DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS }, + { "e.d.c.b.a.", DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS }, + { NULL, 0, 0 }, + }; + check_delete(qp, del1); + + /* again */ + static struct check_delete del2[] = { + { ".", DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND }, + { "a.", DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND }, + { "a.", DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND }, + { "b.", DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND }, + { "b.", DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND }, + { "b.", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND }, + { "b.a.", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND }, + { "b.a.", DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND }, + { "e.d.c.b.a.", DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND }, + { NULL, 0, 0 }, + }; + check_delete(qp, del2); + + /* lookup checks after deleting */ + static struct check_qpchain chain2[] = { + { ".", DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 0, { NULL } }, + { ".", DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 0, { NULL } }, + { ".", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0, { NULL } }, + + { "a.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_NOTFOUND, + 0, + { NULL } }, /* c.b.a. + */ + { "a.", + DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, + 0, + { NULL } }, /* b.a. + */ + { "a.", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0, { NULL } }, + + { "b.", DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 0, { NULL } }, + { "b.", DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 0, { NULL } }, + { "b.", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0, { NULL } }, + + { "b.a.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_NOTFOUND, + 0, + { NULL } }, /* c.b.a. */ + { "b.a.", DNS_DBNAMESPACE_NSEC, ISC_R_SUCCESS, 1, { "b.a." } }, + { "b.a.", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0, { NULL } }, + + { "c.b.a.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, + 1, + { "c.b.a." } }, + { "c.b.a.", + DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, + 1, + { "b.a." } }, + { "c.b.a.", DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 0, { NULL } }, + + { "e.d.c.b.a.", + DNS_DBNAMESPACE_NORMAL, + DNS_R_PARTIALMATCH, + 1, + { "c.b.a." } }, + { "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, + ISC_R_SUCCESS, + 2, + { "b.a.", "e.d.c.b.a." } }, + { "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC3, + ISC_R_NOTFOUND, + 0, + { NULL } }, + + { "a.b.c.d.", + DNS_DBNAMESPACE_NORMAL, + ISC_R_SUCCESS, + 1, + { "a.b.c.d." } }, + { "a.b.c.d.", + DNS_DBNAMESPACE_NSEC, + ISC_R_NOTFOUND, + 0, + { NULL } }, + { "a.b.c.d.", + DNS_DBNAMESPACE_NSEC3, + DNS_R_PARTIALMATCH, + 1, + { "c.d." } }, + + { NULL, 0, 0, 0, { NULL } }, + }; + check_qpchain(qp, chain2); + + static struct check_predecessors pred2[] = { + { ".", DNS_DBNAMESPACE_NORMAL, "c.d.", DNS_DBNAMESPACE_NSEC3, + ISC_R_NOTFOUND, 0 }, + { ".", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 4 }, + { ".", DNS_DBNAMESPACE_NSEC3, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 2 }, + + { "a.", DNS_DBNAMESPACE_NORMAL, "c.d.", DNS_DBNAMESPACE_NSEC3, + ISC_R_NOTFOUND, 0 }, + { "a.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 4 }, + { "a.", DNS_DBNAMESPACE_NSEC3, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 2 }, + + { "b.", DNS_DBNAMESPACE_NORMAL, "c.b.a.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 6 }, + { "b.", DNS_DBNAMESPACE_NSEC, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 2 }, + { "b.", DNS_DBNAMESPACE_NSEC3, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 2 }, /* c.b.b. */ + + { "b.a.", DNS_DBNAMESPACE_NORMAL, "c.d.", DNS_DBNAMESPACE_NSEC3, + ISC_R_NOTFOUND, 0 }, /* c.b.a. */ + { "b.a.", DNS_DBNAMESPACE_NSEC, "a.b.c.d.e.", + DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS, 4 }, + { "b.a.", DNS_DBNAMESPACE_NSEC3, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 2 }, + + { "c.b.a.", DNS_DBNAMESPACE_NORMAL, "c.d.", + DNS_DBNAMESPACE_NSEC3, ISC_R_SUCCESS, 0 }, + { "c.b.a.", DNS_DBNAMESPACE_NSEC, "b.a.", DNS_DBNAMESPACE_NSEC, + DNS_R_PARTIALMATCH, 3 }, + { "c.b.a.", DNS_DBNAMESPACE_NSEC3, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 2 }, + + { "c.", DNS_DBNAMESPACE_NORMAL, "c.b.a.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 6 }, + { "c.", DNS_DBNAMESPACE_NSEC, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 2 }, + { "c.", DNS_DBNAMESPACE_NSEC3, "c.b.b.", DNS_DBNAMESPACE_NSEC3, + ISC_R_NOTFOUND, 1 }, + + { "e.d.c.b.a.", DNS_DBNAMESPACE_NORMAL, "c.b.a.", + DNS_DBNAMESPACE_NORMAL, DNS_R_PARTIALMATCH, 6 }, + { "e.d.c.b.a.", DNS_DBNAMESPACE_NSEC, "b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_SUCCESS, 3 }, + { "e.d.c.b.a.", DNS_DBNAMESPACE_NSEC3, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 2 }, + + { "a.b.c.d.", DNS_DBNAMESPACE_NORMAL, "c.b.a.", + DNS_DBNAMESPACE_NORMAL, ISC_R_SUCCESS, 6 }, + { "a.b.c.d.", DNS_DBNAMESPACE_NSEC, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 2 }, + { "a.b.c.d.", DNS_DBNAMESPACE_NSEC3, "c.d.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "b.c.d.", DNS_DBNAMESPACE_NORMAL, "c.b.a.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 6 }, + { "b.c.d.", DNS_DBNAMESPACE_NSEC, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 2 }, + { "b.c.d.", DNS_DBNAMESPACE_NSEC3, "c.d.", + DNS_DBNAMESPACE_NSEC3, DNS_R_PARTIALMATCH, 0 }, + + { "f.b.b.d.", DNS_DBNAMESPACE_NORMAL, "c.b.a.", + DNS_DBNAMESPACE_NORMAL, ISC_R_NOTFOUND, 6 }, + { "f.b.b.d.", DNS_DBNAMESPACE_NSEC, "e.d.c.b.a.", + DNS_DBNAMESPACE_NSEC, ISC_R_NOTFOUND, 2 }, + { "f.b.b.d.", DNS_DBNAMESPACE_NSEC3, "c.b.b.", + DNS_DBNAMESPACE_NSEC3, ISC_R_NOTFOUND, 1 }, + + { NULL, 0, NULL, 0, 0, 0 }, + }; + check_predecessors(qp, pred2); + + dns_qp_destroy(&qp); +} + ISC_TEST_LIST_START ISC_TEST_ENTRY(qpkey_name) ISC_TEST_ENTRY(qpkey_sort) @@ -937,6 +2067,7 @@ ISC_TEST_ENTRY(partialmatch) ISC_TEST_ENTRY(qpchain) ISC_TEST_ENTRY(predecessors) ISC_TEST_ENTRY(fixiterator) +ISC_TEST_ENTRY(qpkey_delete) ISC_TEST_LIST_END ISC_TEST_MAIN diff --git a/tests/libtest/qp.c b/tests/libtest/qp.c index c1ae208bf7..4a6a9ff943 100644 --- a/tests/libtest/qp.c +++ b/tests/libtest/qp.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -55,7 +56,7 @@ qp_test_bittoascii(dns_qpshift_t bit) { const char * qp_test_keytoascii(dns_qpkey_t key, size_t len) { - for (size_t offset = 0; offset < len; offset++) { + for (size_t offset = 1; offset < len; offset++) { key[offset] = qp_test_bittoascii(key[offset]); } key[len] = '\0'; @@ -342,11 +343,16 @@ void qp_test_printkey(const dns_qpkey_t key, size_t keylen) { dns_fixedname_t fn; dns_name_t *n = dns_fixedname_initname(&fn); + dns_namespace_t s; char txt[DNS_NAME_FORMATSIZE]; - dns_qpkey_toname(key, keylen, n); + dns_qpkey_toname(key, keylen, n, &s); dns_name_format(n, txt, sizeof(txt)); - printf("%s%s\n", txt, dns_name_isabsolute(n) ? "." : ""); + printf("%s%s%s\n", txt, + s == DNS_DBNAMESPACE_NSEC3 + ? "NSEC3:" + : (s == DNS_DBNAMESPACE_NSEC ? "NSEC" : ""), + dns_name_isabsolute(n) ? "." : ""); } /**********************************************************************/