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..8c55992df8 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; + uint8_t denial; namein = dns_fixedname_initname(&fixedin); nameout = dns_fixedname_initname(&fixedout); @@ -55,15 +56,16 @@ 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, 0); + dns_qpkey_toname(key, keylen, nameout, &denial); assert(dns_name_equal(namein, nameout)); + assert(denial == 0); /* 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, 0); size_t len = ISC_MIN(keylen, cmplen); int namerel = dns_name_compare(namein, namecmp); @@ -72,6 +74,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(denial == 0); return 0; } diff --git a/lib/dns/forward.c b/lib/dns/forward.c index b46111fb13..5764917ed8 100644 --- a/lib/dns/forward.c +++ b/lib/dns/forward.c @@ -233,7 +233,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, 0); } static void diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index e53f8a92e8..e84ba19284 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -237,10 +237,9 @@ struct dns_dbonupdatelistener { * exists in a specal tree for NSEC or NSEC3. */ 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 */ + DNS_DB_NSEC_NORMAL = 0, /* in main tree */ + DNS_DB_NSEC_NSEC = 2, /* in nsec tree */ + DNS_DB_NSEC_NSEC3 = 3 /* in nsec3 tree */ }; /*@{*/ diff --git a/lib/dns/include/dns/qp.h b/lib/dns/include/dns/qp.h index bbac5ca6fb..b0cce58b27 100644 --- a/lib/dns/include/dns/qp.h +++ b/lib/dns/include/dns/qp.h @@ -181,8 +181,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 denial of existence value. + * + * Note: this gives us 5 bytes available space to store more data. */ #define DNS_QP_MAXKEY 512 @@ -470,10 +473,14 @@ 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, uint8_t denial); /*%< * Convert a DNS name into a trie lookup key. * + * If 'denial' is DNS_DB_NSEC_NORMAL (0), convert the name for a NSEC lookup. + * If 'denial' is DNS_DB_NSEC_NSEC, convert the name for a NSEC lookup. + * If 'denial' is DNS_DB_NSEC_NSEC3, convert the name for a NSEC3 lookup. + * * Requires: * \li `name` is a pointer to a valid `dns_name_t` * @@ -485,10 +492,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, + uint8_t *denial); /*%< * Convert a trie lookup key back into a DNS name. * + * 'denial' 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 +524,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, uint8_t denial, + 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 denial value. * * The leaf values are assigned to whichever of `*pval_r` and `*ival_r` * are not null, unless the return value is ISC_R_NOTFOUND. @@ -575,6 +585,16 @@ dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name, * \li ISC_R_NOTFOUND if no match was found */ +isc_result_t +dns_qp_lookup2(dns_qpreadable_t qpr, const dns_name_t *name, uint8_t denial, + dns_name_t *foundname, dns_qpiter_t *iter, dns_qpchain_t *chain, + void **pval_r, uint32_t *ival_r); +/*%< + * The same as 'dns_qp_lookup', but with the possibility to set a denial value, + * either DNS_DB_NSEC_NORMAL (or 0, which is the equivalent of 'dns_qp_lookup'), + * DNS_DB_NSEC_NSEC, OR DNS_DB_NSEC3. + */ + isc_result_t dns_qp_insert(dns_qp_t *qp, void *pval, uint32_t ival); /*%< @@ -609,10 +629,11 @@ 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, uint8_t denial, + 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 denial + * value. * * 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..d4cc637dde 100644 --- a/lib/dns/keytable.c +++ b/lib/dns/keytable.c @@ -273,7 +273,7 @@ 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, 0, &pval, NULL); INSIST(result == ISC_R_SUCCESS); INSIST(pval == knode); @@ -343,7 +343,7 @@ 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, 0, &pval, NULL); if (result != ISC_R_SUCCESS) { /* * There was no match for "keyname" in "keytable" yet, so one @@ -400,7 +400,7 @@ 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, 0, &pval, NULL); if (result == ISC_R_SUCCESS) { dns_keynode_t *n = pval; if (callback != NULL) { @@ -430,7 +430,7 @@ 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, 0, &pval, NULL); if (result != ISC_R_SUCCESS) { goto finish; } @@ -479,7 +479,7 @@ 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, 0, &pval, NULL); if (result == ISC_R_SUCCESS) { dns_keynode_t *knode = pval; dns_keynode_attach(knode, keynodep); @@ -830,7 +830,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, 0); } static void diff --git a/lib/dns/nametree.c b/lib/dns/nametree.c index 3084c25ece..13b65bfef0 100644 --- a/lib/dns/nametree.c +++ b/lib/dns/nametree.c @@ -164,14 +164,14 @@ 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, 0, (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, 0, (void **)&old, NULL); if (result == ISC_R_SUCCESS && matchbit(old->bits, value)) { goto out; } @@ -187,7 +187,7 @@ 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, 0, NULL, NULL); INSIST(result == ISC_R_SUCCESS); } @@ -222,7 +222,7 @@ 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, 0, (void **)&old, &count); switch (nametree->type) { case DNS_NAMETREE_BOOL: case DNS_NAMETREE_BITS: @@ -258,7 +258,7 @@ 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, 0, (void **)&node, NULL); if (result == ISC_R_SUCCESS) { dns_ntnode_attach(node, ntnodep); } @@ -319,7 +319,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, 0); } static void diff --git a/lib/dns/nta.c b/lib/dns/nta.c index 0a020821b8..59613da29d 100644 --- a/lib/dns/nta.c +++ b/lib/dns/nta.c @@ -316,7 +316,7 @@ 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, 0, &pval, NULL); if (result == ISC_R_SUCCESS) { /* * an NTA already existed: throw away the @@ -355,7 +355,7 @@ 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, 0, &pval, NULL); if (result == ISC_R_SUCCESS) { dns__nta_t *n = pval; dns__nta_shutdown(n); @@ -379,7 +379,7 @@ 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, 0, &pval, NULL); if (result == ISC_R_SUCCESS && ((dns__nta_t *)pval)->expiry == nta->expiry && !nta->shuttingdown) { @@ -387,7 +387,7 @@ 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, 0, NULL, NULL); dns__nta_shutdown(nta); dns__nta_unref(nta); } @@ -649,7 +649,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, 0); } static void diff --git a/lib/dns/qp.c b/lib/dns/qp.c index e0b709338b..e6715dd34c 100644 --- a/lib/dns/qp.c +++ b/lib/dns/qp.c @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -115,6 +116,11 @@ ISC_REFCOUNT_STATIC_DECL(dns_qpmulti); * converting DNS names to trie keys */ +/* + * An offset for the denial value. + */ +#define DENIAL_OFFSET 48 + /* * Number of distinct byte values, i.e. 256 */ @@ -228,18 +234,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, uint8_t denial) { REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC)); + REQUIRE(denial <= DNS_DB_NSEC_NSEC3); dns_offsets_t offsets; size_t labels = dns_name_offsets(name, offsets); + size_t len = 0; + /* denial? */ + key[len++] = dns_qp_bits_for_byte[denial + DENIAL_OFFSET]; + /* 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 +271,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, + uint8_t *denial) { size_t locs[DNS_NAME_MAXLABELS]; size_t loc = 0; size_t offset; 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(denial, dns_qp_byte_for_bit[key[0]] - DENIAL_OFFSET); + + if (keylen == 1) { return; } /* Scan the key looking for label boundaries */ - for (offset = 0; offset <= keylen; offset++) { + for (offset = 1; offset <= keylen; offset++) { INSIST(key[offset] >= SHIFT_NOBYTE && key[offset] < SHIFT_OFFSET); INSIST(loc < DNS_NAME_MAXLABELS); @@ -287,7 +301,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 == 1) { /* This happens for a relative name */ locs[loc++] = offset; } @@ -330,7 +344,7 @@ scanned: } /* Add a root label for absolute names */ - if (key[0] == SHIFT_NOBYTE) { + if (key[1] == SHIFT_NOBYTE) { name->attributes.absolute = true; isc_buffer_putuint8(name->buffer, 0); name->length++; @@ -1826,10 +1840,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, uint8_t denial, + 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, denial); return dns_qp_deletekey(qp, key, keylen, pval_r, ival_r); } @@ -1847,7 +1861,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 +2103,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, uint8_t denial, + 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, denial); return dns_qp_getkey(qpr, key, keylen, pval_r, ival_r); } @@ -2267,9 +2281,9 @@ 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_qp_lookup2(dns_qpreadable_t qpr, const dns_name_t *name, uint8_t denial, + 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 +2298,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, denial); if (chain == NULL) { chain = &oc; @@ -2415,4 +2429,12 @@ dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name, return ISC_R_NOTFOUND; } +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) { + return dns_qp_lookup2(qpr, name, 0, foundname, iter, chain, pval_r, + ival_r); +} + /**********************************************************************/ diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index 5bc516728a..2104a57e39 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -151,6 +151,7 @@ struct qpcnode { uint8_t : 0; unsigned int delegating : 1; unsigned int nsec : 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->nsec); } static void @@ -603,25 +604,30 @@ delete_node(qpcache_t *qpdb, qpcnode_t *node) { } 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)); - } - /* FALLTHROUGH */ case DNS_DB_NSEC_NORMAL: - result = dns_qp_deletename(qpdb->tree, &node->name, NULL, NULL); + 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_DB_NSEC_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)); + } + } + result = dns_qp_deletename(qpdb->tree, &node->name, node->nsec, + NULL, NULL); break; case DNS_DB_NSEC_NSEC: - result = dns_qp_deletename(qpdb->nsec, &node->name, NULL, NULL); + result = dns_qp_deletename(qpdb->nsec, &node->name, node->nsec, + 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_lookup2(search->qpdb->nsec, name, DNS_DB_NSEC_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_DB_NSEC_NORMAL, (void **)&node, NULL); if (result != ISC_R_SUCCESS) { return result; } @@ -2346,9 +2352,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; + uint8_t dopt = DNS_DB_NSEC_NORMAL; TREE_RDLOCK(&qpdb->tree_lock, &tlocktype); - result = dns_qp_getname(qpdb->tree, name, (void **)&node, NULL); + result = dns_qp_getname(qpdb->tree, name, dopt, (void **)&node, NULL); if (result != ISC_R_SUCCESS) { if (!create) { goto unlock; @@ -2357,9 +2364,11 @@ 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, dopt, (void **)&node, + NULL); if (result != ISC_R_SUCCESS) { node = new_qpcnode(qpdb, name); + node->nsec = dopt; 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,11 +3042,11 @@ 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_DB_NSEC_NSEC, + (void **)&nsecnode, NULL); if (result != ISC_R_SUCCESS) { INSIST(nsecnode == NULL); nsecnode = new_qpcnode(qpdb, name); @@ -3046,7 +3055,7 @@ qpcache_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 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, diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index 39b0caf2f7..771bb35136 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -201,6 +201,7 @@ struct qpznode { uint16_t locknum; atomic_uint_fast8_t nsec; + atomic_bool havensec; atomic_bool wild; atomic_bool delegating; atomic_bool dirty; @@ -772,9 +773,9 @@ dns__qpzone_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, dns_qpmulti_write(qpdb->tree, &qp); qpdb->origin = new_qpznode(qpdb, &qpdb->common.origin); + qpdb->origin->nsec = DNS_DB_NSEC_NORMAL; 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); /* @@ -1708,31 +1709,31 @@ 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, - NULL); + result = dns_qp_getname(loadctx->nsec3, name, DNS_DB_NSEC_NSEC3, + (void **)&node, NULL); if (result == ISC_R_SUCCESS) { *nodep = node; } else { node = new_qpznode(qpdb, name); + node->nsec = DNS_DB_NSEC_NSEC3; result = dns_qp_insert(loadctx->nsec3, 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_DB_NSEC_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->nsec = DNS_DB_NSEC_NORMAL; result = dns_qp_insert(loadctx->tree, node, 0); INSIST(result == ISC_R_SUCCESS); qpznode_unref(node); @@ -1749,7 +1750,7 @@ 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; + node->havensec = true; nsecnode = new_qpznode(qpdb, name); nsecnode->nsec = DNS_DB_NSEC_NSEC; (void)dns_qp_insert(loadctx->nsec, nsecnode, 0); @@ -2115,7 +2116,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, + uint8_t denial) { isc_result_t result; dns_name_t foundname; unsigned int n; @@ -2128,10 +2130,11 @@ 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, denial, (void **)&node, NULL); if (result != ISC_R_SUCCESS) { INSIST(node == NULL); node = new_qpznode(qpdb, &foundname); + node->nsec = denial; result = dns_qp_insert(qp, node, 0); INSIST(result == ISC_R_SUCCESS); qpznode_unref(node); @@ -2141,7 +2144,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, + uint8_t denial) { dns_name_t foundname; unsigned int n, l, i; @@ -2152,7 +2156,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, denial); } i++; @@ -2185,7 +2189,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_DB_NSEC_NORMAL); } if (dns_name_iswildcard(name)) { @@ -2203,7 +2207,7 @@ loading_addrdataset(void *arg, const dns_name_t *name, return DNS_R_INVALIDNSEC3; } - wildcardmagic(qpdb, loadctx->tree, name); + wildcardmagic(qpdb, loadctx->tree, name, DNS_DB_NSEC_NORMAL); } loading_addnode(loadctx, name, rdataset->type, rdataset->covers, &node); @@ -2551,6 +2555,7 @@ 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; + uint8_t denial = nsec3 ? DNS_DB_NSEC_NSEC3 : DNS_DB_NSEC_NORMAL; dns_qpmulti_t *dbtree = nsec3 ? qpdb->nsec3 : qpdb->tree; dns_qpread_t qpr = { 0 }; dns_qp_t *qp = NULL; @@ -2562,7 +2567,7 @@ findnodeintree(qpzonedb_t *qpdb, const dns_name_t *name, bool create, qp = (dns_qp_t *)&qpr; } - result = dns_qp_getname(qp, name, (void **)&node, NULL); + result = dns_qp_getname(qp, name, denial, (void **)&node, NULL); if (result != ISC_R_SUCCESS) { if (!create) { dns_qpread_destroy(dbtree, &qpr); @@ -2570,16 +2575,15 @@ findnodeintree(qpzonedb_t *qpdb, const dns_name_t *name, bool create, } node = new_qpznode(qpdb, name); + node->nsec = denial; 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, denial); if (dns_name_iswildcard(name)) { - wildcardmagic(qpdb, qp, name); + wildcardmagic(qpdb, qp, name, denial); } } } @@ -2880,8 +2884,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, + uint8_t denial) { dns_slabheader_t *header = NULL; isc_result_t result = ISC_R_NOTFOUND; @@ -2938,8 +2942,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_lookup2(&search->qpr, wname, denial, + NULL, &wit, NULL, + (void **)&wnode, NULL); if (result == ISC_R_SUCCESS) { /* * We have found the wildcard node. If it @@ -3029,8 +3034,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_lookup2(&qpr, name, DNS_DB_NSEC_NSEC, + NULL, nit, NULL, NULL, NULL); INSIST(result != ISC_R_NOTFOUND); if (result == ISC_R_SUCCESS) { /* @@ -3063,8 +3068,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_lookup2(&search->qpr, name, DNS_DB_NSEC_NORMAL, + NULL, &search->iter, &search->chain, + (void **)nodep, NULL); if (result == ISC_R_SUCCESS) { break; } @@ -3200,12 +3206,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,6 +3455,7 @@ qpzone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, close_version = true; } + uint8_t denial; qpz_search_t search; qpz_search_init(&search, (qpzonedb_t *)db, (qpz_version_t *)version, options); @@ -3458,15 +3463,17 @@ qpzone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, if ((options & DNS_DBFIND_FORCENSEC3) != 0) { dns_qpmulti_query(qpdb->nsec3, &search.qpr); nsec3 = true; + denial = DNS_DB_NSEC_NSEC3; } else { dns_qpmulti_query(qpdb->tree, &search.qpr); + denial = DNS_DB_NSEC_NORMAL; } /* * Search down from the root of the tree. */ - result = dns_qp_lookup(&search.qpr, name, NULL, &search.iter, - &search.chain, (void **)&node, NULL); + result = dns_qp_lookup2(&search.qpr, name, denial, NULL, &search.iter, + &search.chain, (void **)&node, NULL); if (result != ISC_R_NOTFOUND) { dns_name_copy(&node->name, foundname); } @@ -3512,7 +3519,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, denial); if (result == ISC_R_SUCCESS) { dns_name_copy(name, foundname); wild = true; @@ -4457,9 +4464,10 @@ 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_lookup2(qpdbiter->nsnap, name, + DNS_DB_NSEC_NSEC3, NULL, + qpdbiter->current, NULL, + (void **)&qpdbiter->node, NULL); break; case nonsec3: qpdbiter->current = &qpdbiter->mainiter; @@ -4477,9 +4485,9 @@ dbiterator_seek(dns_dbiterator_t *iterator, 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); + tresult = dns_qp_lookup2( + qpdbiter->nsnap, name, DNS_DB_NSEC_NSEC3, NULL, + &qpdbiter->nsec3iter, NULL, NULL, NULL); if (tresult == ISC_R_SUCCESS) { qpdbiter->current = &qpdbiter->nsec3iter; result = tresult; @@ -4756,9 +4764,7 @@ 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) - { + if (!node->havensec && rdataset->type == dns_rdatatype_nsec) { dns_qpmulti_write(qpdb->nsec, &nsec); } @@ -4777,7 +4783,7 @@ 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, @@ -5485,7 +5491,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->nsec); } static void diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index 42c7b286ba..35dd80577a 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -1422,7 +1422,7 @@ 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, 0, (void **)&data, NULL); if (result != ISC_R_SUCCESS) { INSIST(data == NULL); data = new_nmdata(rpzs->mctx, trig_name, new_data); @@ -2291,7 +2291,7 @@ 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, 0, (void **)&data, NULL); if (result != ISC_R_SUCCESS) { return; } @@ -2314,7 +2314,7 @@ 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, 0, NULL, NULL); if (result != ISC_R_SUCCESS) { /* * bin/tests/system/rpz/tests.sh looks for @@ -2667,7 +2667,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, 0); } static void diff --git a/lib/dns/zt.c b/lib/dns/zt.c index b4e75c1843..2ec4dd5fe2 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, 0); } static void @@ -156,7 +156,7 @@ 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), 0, NULL, NULL); dns_qp_compact(qp, DNS_QPGC_MAYBE); dns_qpmulti_commit(zt->multi, &qp); @@ -179,7 +179,7 @@ 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, 0, &pval, NULL); } else { result = dns_qp_lookup(&qpr, name, NULL, NULL, &chain, &pval, NULL); diff --git a/tests/bench/load-names.c b/tests/bench/load-names.c index 67aa7ad5a0..ca9578fb27 100644 --- a/tests/bench/load-names.c +++ b/tests/bench/load-names.c @@ -66,7 +66,7 @@ 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, 0); } static void @@ -325,7 +325,7 @@ 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, 0, pval, NULL); } static void * diff --git a/tests/bench/qp-dump.c b/tests/bench/qp-dump.c index 33bccc5ec8..92446dfae7 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, 0); } static void diff --git a/tests/bench/qplookups.c b/tests/bench/qplookups.c index aeb3e8b54c..612d15e8cc 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, 0); } 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, 0, 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..67f2cb94f7 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; + uint8_t denial; uint8_t key[512]; size_t len; } testcases[] = { { .namestr = "", - .key = { 0x02 }, - .len = 0, - }, - { - .namestr = ".", - .key = { 0x02, 0x02 }, + .denial = DNS_DB_NSEC_NORMAL, + .key = { 0x00, 0x02 }, .len = 1, }, + { + .namestr = ".", + .denial = DNS_DB_NSEC_NORMAL, + .key = { 0x00, 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 }, + .denial = DNS_DB_NSEC_NORMAL, + .key = { 0x00, 0x03, 0x03, 0x02 }, .len = 4, }, { - .namestr = "com.", - .key = { 0x02, 0x16, 0x22, 0x20, 0x02 }, + .namestr = "\\000\\009", + .denial = DNS_DB_NSEC_NORMAL, + .key = { 0x00, 0x03, 0x03, 0x03, 0x0c, 0x02 }, + .len = 6, + }, + { + .namestr = "com", + .denial = DNS_DB_NSEC_NORMAL, + .key = { 0x00, 0x16, 0x22, 0x20, 0x02 }, .len = 5, }, + { + .namestr = "com.", + .denial = DNS_DB_NSEC_NSEC, + .key = { 0x02, 0x02, 0x16, 0x22, 0x20, 0x02 }, + .len = 6, + }, + { + .namestr = "com.", + .denial = DNS_DB_NSEC_NSEC3, + .key = { 0x03, 0x02, 0x16, 0x22, 0x20, 0x02 }, + .len = 6, + }, + { + .namestr = "com.", + .denial = DNS_DB_NSEC_NORMAL, + .key = { 0x00, 0x02, 0x16, 0x22, 0x20, 0x02 }, + .len = 6, + }, { .namestr = "example.com.", - .key = { 0x02, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14, + .denial = DNS_DB_NSEC_NORMAL, + .key = { 0x00, 0x02, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, + 0x14, 0x20, 0x23, 0x1f, 0x18, 0x02 }, + .len = 14, + }, + { + .namestr = "example.com", + .denial = DNS_DB_NSEC_NORMAL, + .key = { 0x00, 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, + .denial = DNS_DB_NSEC_NORMAL, + .key = { 0x00, 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]; + uint8_t denial; 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].denial); 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, &denial); assert_true(dns_name_equal(in, out)); + assert_int_equal(denial, testcases[i].denial); /* 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)); } } @@ -156,7 +176,7 @@ 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, 0); } for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) { @@ -358,7 +378,7 @@ qpkey_fromstring(dns_qpkey_t key, void *uctx, void *pval, uint32_t ival) { 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), 0); } const dns_qpmethods_t string_methods = { @@ -493,7 +513,7 @@ ISC_RUN_TEST_IMPL(partialmatch) { * what if entries in the trie are relative to the zone apex * and there's no root node? */ - dns_qpkey_t rootkey = { SHIFT_NOBYTE }; + dns_qpkey_t rootkey = { 0x00, SHIFT_NOBYTE }; result = dns_qp_deletekey(qp, rootkey, 1, NULL, NULL); assert_int_equal(result, ISC_R_SUCCESS); check_partialmatch(qp, (struct check_partialmatch[]){ @@ -502,15 +522,6 @@ ISC_RUN_TEST_IMPL(partialmatch) { { NULL, 0, NULL }, }); - /* 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 }, - }); - dns_qp_destroy(&qp); } diff --git a/tests/libtest/qp.c b/tests/libtest/qp.c index c1ae208bf7..cb6e479989 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,15 @@ void qp_test_printkey(const dns_qpkey_t key, size_t keylen) { dns_fixedname_t fn; dns_name_t *n = dns_fixedname_initname(&fn); + uint8_t d; char txt[DNS_NAME_FORMATSIZE]; - dns_qpkey_toname(key, keylen, n); + dns_qpkey_toname(key, keylen, n, &d); dns_name_format(n, txt, sizeof(txt)); - printf("%s%s\n", txt, dns_name_isabsolute(n) ? "." : ""); + printf("%s%s%s\n", txt, + d == DNS_DB_NSEC_NSEC3 ? "NSEC3:" + : (d == DNS_DB_NSEC_NSEC ? "NSEC" : ""), + dns_name_isabsolute(n) ? "." : ""); } /**********************************************************************/