2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 10:10:06 +00:00

Prepend qpkey with denial byte

In preparation to merge the three qp tries (tree, nsec, nsec3) into
one, add the piece of information into the qpkey. This is the most
significant bit of information, so prepend the denial type to the qpkey.

This means we need to pass on the denial type when constructing the
qpkey from a name, or doing a lookup.

Reuse the the DNS_DB_NSEC_* values. Most qp tries in the code we just
pass on 0 (nta, rpz, zt, etc.), because there is no need for denial of
existence, but for qpzone and qpcache we must pass the right value.

Change the code, so that node->nsec no longer can have the value
DNS_DB_NSEC_HAS_NSEC, instead track this in a new attribute 'havensec'.

Since we use node->nsec to convert names to keys, the value MUST be set
before inserting the node into the qp-trie.

Update the fuzzing and unit tests accordingly. This only adds a few
extra test cases, more are needed.

In the qp_test.c we can remove test code for empty keys as this is
no longer possible.
This commit is contained in:
Matthijs Mekking 2025-04-25 17:21:16 +02:00
parent 658698896a
commit 16a1c5a623
19 changed files with 276 additions and 198 deletions

View File

@ -104,12 +104,13 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
for (size_t i = 0; i < ARRAY_SIZE(item); i++) { for (size_t i = 0; i < ARRAY_SIZE(item); i++) {
size_t len = isc_random_uniform(100) + 16; size_t len = isc_random_uniform(100) + 16;
item[i].len = len; item[i].len = len + 1;
for (size_t off = 0; off < len; off++) { item[i].key[0] = 0;
for (size_t off = 1; off < len; off++) {
item[i].key[off] = random_byte(); item[i].key[off] = random_byte();
} }
memmove(item[i].ascii, item[i].key, len); memmove(item[i].ascii, item[i].key, item[i].len);
qp_test_keytoascii(item[i].ascii, len); qp_test_keytoascii(item[i].ascii, item[i].len);
} }
return 0; return 0;

View File

@ -43,6 +43,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
dns_name_t *namein, *nameout, *namecmp; dns_name_t *namein, *nameout, *namecmp;
isc_buffer_t buf; isc_buffer_t buf;
dns_qpkey_t key, cmp; dns_qpkey_t key, cmp;
uint8_t denial;
namein = dns_fixedname_initname(&fixedin); namein = dns_fixedname_initname(&fixedin);
nameout = dns_fixedname_initname(&fixedout); 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)); CHECK(dns_name_fromwire(namein, &buf, DNS_DECOMPRESS_NEVER, NULL));
/* verify round-trip conversion of first name */ /* verify round-trip conversion of first name */
size_t keylen = dns_qpkey_fromname(key, namein); size_t keylen = dns_qpkey_fromname(key, namein, 0);
dns_qpkey_toname(key, keylen, nameout); dns_qpkey_toname(key, keylen, nameout, &denial);
assert(dns_name_equal(namein, nameout)); assert(dns_name_equal(namein, nameout));
assert(denial == 0);
/* is there a second name? */ /* is there a second name? */
CHECK(dns_name_fromwire(namecmp, &buf, DNS_DECOMPRESS_NEVER, NULL)); 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); size_t len = ISC_MIN(keylen, cmplen);
int namerel = dns_name_compare(namein, namecmp); 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((namerel == 0) == (keyrel == 0));
assert((namerel > 0) == (keyrel > 0)); assert((namerel > 0) == (keyrel > 0));
assert(denial == 0);
return 0; return 0;
} }

View File

@ -233,7 +233,7 @@ static size_t
qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval, qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) { uint32_t ival ISC_ATTR_UNUSED) {
dns_forwarders_t *fwd = pval; dns_forwarders_t *fwd = pval;
return dns_qpkey_fromname(key, &fwd->name); return dns_qpkey_fromname(key, &fwd->name, 0);
} }
static void static void

View File

@ -237,10 +237,9 @@ struct dns_dbonupdatelistener {
* exists in a specal tree for NSEC or NSEC3. * exists in a specal tree for NSEC or NSEC3.
*/ */
enum { enum {
DNS_DB_NSEC_NORMAL = 0, /* in main tree */ 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_NSEC = 2, /* in nsec tree */ DNS_DB_NSEC_NSEC3 = 3 /* in nsec3 tree */
DNS_DB_NSEC_NSEC3 = 3 /* in nsec3 tree */
}; };
/*@{*/ /*@{*/

View File

@ -181,8 +181,11 @@ typedef union dns_qpreadable {
* A domain name can be up to 255 bytes. When converted to a key, each * 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 * character in the name corresponds to one byte in the key if it is a
* common hostname character; otherwise unusual characters are escaped, * common hostname character; otherwise unusual characters are escaped,
* using two bytes in the key. So we allow keys to be up to 512 bytes. * using two bytes in the key. Because the maximum label length is 63
* (The actual max is (255 - 5) * 2 + 6 == 506) * 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 #define DNS_QP_MAXKEY 512
@ -470,10 +473,14 @@ dns_qpmulti_memusage(dns_qpmulti_t *multi);
*/ */
size_t 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. * 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: * Requires:
* \li `name` is a pointer to a valid `dns_name_t` * \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 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. * 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: * Requires:
* \li `name` is a pointer to a valid `dns_name_t` * \li `name` is a pointer to a valid `dns_name_t`
* \li `name->buffer` is not NULL * \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 isc_result_t
dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, void **pval_r, dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, uint8_t denial,
uint32_t *ival_r); 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` * The leaf values are assigned to whichever of `*pval_r` and `*ival_r`
* are not null, unless the return value is ISC_R_NOTFOUND. * 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 * \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 isc_result_t
dns_qp_insert(dns_qp_t *qp, void *pval, uint32_t ival); 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 isc_result_t
dns_qp_deletename(dns_qp_t *qp, const dns_name_t *name, void **pval_r, dns_qp_deletename(dns_qp_t *qp, const dns_name_t *name, uint8_t denial,
uint32_t *ival_r); 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` * The leaf values are assigned to whichever of `*pval_r` and `*ival_r`
* are not null, unless the return value is ISC_R_NOTFOUND. * are not null, unless the return value is ISC_R_NOTFOUND.

View File

@ -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(result == ISC_R_SUCCESS);
INSIST(pval == knode); INSIST(pval == knode);
@ -343,7 +343,7 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
dns_qpmulti_write(keytable->table, &qp); 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) { if (result != ISC_R_SUCCESS) {
/* /*
* There was no match for "keyname" in "keytable" yet, so one * 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); REQUIRE(keyname != NULL);
dns_qpmulti_write(keytable->table, &qp); 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) { if (result == ISC_R_SUCCESS) {
dns_keynode_t *n = pval; dns_keynode_t *n = pval;
if (callback != NULL) { if (callback != NULL) {
@ -430,7 +430,7 @@ dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname,
REQUIRE(dnskey != NULL); REQUIRE(dnskey != NULL);
dns_qpmulti_write(keytable->table, &qp); 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) { if (result != ISC_R_SUCCESS) {
goto finish; goto finish;
} }
@ -479,7 +479,7 @@ dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname,
REQUIRE(keynodep != NULL && *keynodep == NULL); REQUIRE(keynodep != NULL && *keynodep == NULL);
dns_qpmulti_query(keytable->table, &qpr); 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) { if (result == ISC_R_SUCCESS) {
dns_keynode_t *knode = pval; dns_keynode_t *knode = pval;
dns_keynode_attach(knode, keynodep); 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, qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) { uint32_t ival ISC_ATTR_UNUSED) {
dns_keynode_t *keynode = pval; dns_keynode_t *keynode = pval;
return dns_qpkey_fromname(key, &keynode->name); return dns_qpkey_fromname(key, &keynode->name, 0);
} }
static void static void

View File

@ -164,14 +164,14 @@ dns_nametree_add(dns_nametree_t *nametree, const dns_name_t *name,
case DNS_NAMETREE_COUNT: case DNS_NAMETREE_COUNT:
new = newnode(nametree->mctx, name); new = newnode(nametree->mctx, name);
new->set = true; 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) { if (result == ISC_R_SUCCESS) {
count += 1; count += 1;
} }
break; break;
case DNS_NAMETREE_BITS: 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)) { if (result == ISC_R_SUCCESS && matchbit(old->bits, value)) {
goto out; 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)); new->bits = isc_mem_cget(nametree->mctx, size, sizeof(char));
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
memmove(new->bits, old->bits, old->bits[0]); 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); INSIST(result == ISC_R_SUCCESS);
} }
@ -222,7 +222,7 @@ dns_nametree_delete(dns_nametree_t *nametree, const dns_name_t *name) {
REQUIRE(name != NULL); REQUIRE(name != NULL);
dns_qpmulti_write(nametree->table, &qp); 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) { switch (nametree->type) {
case DNS_NAMETREE_BOOL: case DNS_NAMETREE_BOOL:
case DNS_NAMETREE_BITS: 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); REQUIRE(ntnodep != NULL && *ntnodep == NULL);
dns_qpmulti_query(nametree->table, &qpr); 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) { if (result == ISC_R_SUCCESS) {
dns_ntnode_attach(node, ntnodep); 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, qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) { uint32_t ival ISC_ATTR_UNUSED) {
dns_ntnode_t *ntnode = pval; dns_ntnode_t *ntnode = pval;
return dns_qpkey_fromname(key, &ntnode->name); return dns_qpkey_fromname(key, &ntnode->name, 0);
} }
static void static void

View File

@ -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); result = dns_qp_insert(qp, nta, 0);
switch (result) { switch (result) {
case ISC_R_EXISTS: 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) { if (result == ISC_R_SUCCESS) {
/* /*
* an NTA already existed: throw away the * 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); REQUIRE(name != NULL);
dns_qpmulti_write(ntatable->table, &qp); 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) { if (result == ISC_R_SUCCESS) {
dns__nta_t *n = pval; dns__nta_t *n = pval;
dns__nta_shutdown(n); dns__nta_shutdown(n);
@ -379,7 +379,7 @@ delete_expired(void *arg) {
RWLOCK(&ntatable->rwlock, isc_rwlocktype_write); RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
dns_qpmulti_write(ntatable->table, &qp); 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 && if (result == ISC_R_SUCCESS &&
((dns__nta_t *)pval)->expiry == nta->expiry && !nta->shuttingdown) ((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)); dns_name_format(&nta->name, nb, sizeof(nb));
isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_NTA, isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_NTA,
ISC_LOG_INFO, "deleting expired NTA at %s", nb); 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_shutdown(nta);
dns__nta_unref(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, qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) { uint32_t ival ISC_ATTR_UNUSED) {
dns__nta_t *nta = pval; dns__nta_t *nta = pval;
return dns_qpkey_fromname(key, &nta->name); return dns_qpkey_fromname(key, &nta->name, 0);
} }
static void static void

View File

@ -41,6 +41,7 @@
#include <isc/urcu.h> #include <isc/urcu.h>
#include <isc/util.h> #include <isc/util.h>
#include <dns/db.h>
#include <dns/fixedname.h> #include <dns/fixedname.h>
#include <dns/name.h> #include <dns/name.h>
#include <dns/qp.h> #include <dns/qp.h>
@ -115,6 +116,11 @@ ISC_REFCOUNT_STATIC_DECL(dns_qpmulti);
* converting DNS names to trie keys * converting DNS names to trie keys
*/ */
/*
* An offset for the denial value.
*/
#define DENIAL_OFFSET 48
/* /*
* Number of distinct byte values, i.e. 256 * Number of distinct byte values, i.e. 256
*/ */
@ -228,18 +234,22 @@ dns__qp_shutdown(void) {
* dot in a zone file). * dot in a zone file).
*/ */
size_t 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(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
REQUIRE(denial <= DNS_DB_NSEC_NSEC3);
dns_offsets_t offsets; dns_offsets_t offsets;
size_t labels = dns_name_offsets(name, 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) { if (labels == 0) {
key[0] = SHIFT_NOBYTE; key[len] = SHIFT_NOBYTE;
return 0; return len;
} }
size_t len = 0;
size_t label = labels; size_t label = labels;
while (label-- > 0) { while (label-- > 0) {
const uint8_t *ldata = name->ndata + offsets[label]; 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 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 locs[DNS_NAME_MAXLABELS];
size_t loc = 0; size_t loc = 0;
size_t offset; size_t offset;
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC)); REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
REQUIRE(name->buffer != NULL); REQUIRE(name->buffer != NULL);
REQUIRE(keylen > 0);
dns_name_reset(name); 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; return;
} }
/* Scan the key looking for label boundaries */ /* Scan the key looking for label boundaries */
for (offset = 0; offset <= keylen; offset++) { for (offset = 1; offset <= keylen; offset++) {
INSIST(key[offset] >= SHIFT_NOBYTE && INSIST(key[offset] >= SHIFT_NOBYTE &&
key[offset] < SHIFT_OFFSET); key[offset] < SHIFT_OFFSET);
INSIST(loc < DNS_NAME_MAXLABELS); 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; goto scanned;
} }
locs[loc++] = offset + 1; locs[loc++] = offset + 1;
} else if (offset == 0) { } else if (offset == 1) {
/* This happens for a relative name */ /* This happens for a relative name */
locs[loc++] = offset; locs[loc++] = offset;
} }
@ -330,7 +344,7 @@ scanned:
} }
/* Add a root label for absolute names */ /* Add a root label for absolute names */
if (key[0] == SHIFT_NOBYTE) { if (key[1] == SHIFT_NOBYTE) {
name->attributes.absolute = true; name->attributes.absolute = true;
isc_buffer_putuint8(name->buffer, 0); isc_buffer_putuint8(name->buffer, 0);
name->length++; name->length++;
@ -1826,10 +1840,10 @@ dns_qp_deletekey(dns_qp_t *qp, const dns_qpkey_t search_key,
} }
isc_result_t isc_result_t
dns_qp_deletename(dns_qp_t *qp, const dns_name_t *name, void **pval_r, dns_qp_deletename(dns_qp_t *qp, const dns_name_t *name, uint8_t denial,
uint32_t *ival_r) { void **pval_r, uint32_t *ival_r) {
dns_qpkey_t key; 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); 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); dns_name_reset(name);
len = leaf_qpkey(qp, node, key); len = leaf_qpkey(qp, node, key);
dns_qpkey_toname(key, len, name); dns_qpkey_toname(key, len, name, NULL);
} }
void void
@ -2089,10 +2103,10 @@ dns_qp_getkey(dns_qpreadable_t qpr, const dns_qpkey_t search_key,
} }
isc_result_t isc_result_t
dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, void **pval_r, dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, uint8_t denial,
uint32_t *ival_r) { void **pval_r, uint32_t *ival_r) {
dns_qpkey_t key; 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); 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 isc_result_t
dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name, 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, dns_name_t *foundname, dns_qpiter_t *iter, dns_qpchain_t *chain,
void **pval_r, uint32_t *ival_r) { void **pval_r, uint32_t *ival_r) {
dns_qpreader_t *qp = dns_qpreader(qpr); dns_qpreader_t *qp = dns_qpreader(qpr);
dns_qpkey_t search, found; dns_qpkey_t search, found;
size_t searchlen, foundlen; 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(QP_VALID(qp));
REQUIRE(foundname == NULL || ISC_MAGIC_VALID(name, DNS_NAME_MAGIC)); 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) { if (chain == NULL) {
chain = &oc; chain = &oc;
@ -2415,4 +2429,12 @@ dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name,
return ISC_R_NOTFOUND; 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);
}
/**********************************************************************/ /**********************************************************************/

View File

@ -151,6 +151,7 @@ struct qpcnode {
uint8_t : 0; uint8_t : 0;
unsigned int delegating : 1; unsigned int delegating : 1;
unsigned int nsec : 2; /*%< range is 0..3 */ unsigned int nsec : 2; /*%< range is 0..3 */
unsigned int havensec : 1;
uint8_t : 0; uint8_t : 0;
uint16_t locknum; uint16_t locknum;
@ -357,7 +358,7 @@ static size_t
qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval, qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) { uint32_t ival ISC_ATTR_UNUSED) {
qpcnode_t *data = pval; qpcnode_t *data = pval;
return dns_qpkey_fromname(key, &data->name); return dns_qpkey_fromname(key, &data->name, data->nsec);
} }
static void static void
@ -603,25 +604,30 @@ delete_node(qpcache_t *qpdb, qpcnode_t *node) {
} }
switch (node->nsec) { 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: 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; break;
case DNS_DB_NSEC_NSEC: 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; break;
} }
if (result != ISC_R_SUCCESS) { 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. * Look for the node in the auxilary tree.
*/ */
result = dns_qp_lookup(search->qpdb->nsec, name, NULL, &iter, NULL, result = dns_qp_lookup2(search->qpdb->nsec, name, DNS_DB_NSEC_NSEC,
(void **)&node, NULL); NULL, &iter, NULL, (void **)&node, NULL);
if (result != DNS_R_PARTIALMATCH) { if (result != DNS_R_PARTIALMATCH) {
return ISC_R_NOTFOUND; 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. * Lookup the predecessor in the main tree.
*/ */
node = NULL; node = NULL;
result = dns_qp_getname(search->qpdb->tree, predecessor, (void **)&node, result = dns_qp_getname(search->qpdb->tree, predecessor,
NULL); DNS_DB_NSEC_NORMAL, (void **)&node, NULL);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
return result; return result;
} }
@ -2346,9 +2352,10 @@ qpcache_findnode(dns_db_t *db, const dns_name_t *name, bool create,
qpcnode_t *node = NULL; qpcnode_t *node = NULL;
isc_result_t result; isc_result_t result;
isc_rwlocktype_t tlocktype = isc_rwlocktype_none; isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
uint8_t dopt = DNS_DB_NSEC_NORMAL;
TREE_RDLOCK(&qpdb->tree_lock, &tlocktype); 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 (result != ISC_R_SUCCESS) {
if (!create) { if (!create) {
goto unlock; 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. * Try to upgrade the lock and if that fails unlock then relock.
*/ */
TREE_FORCEUPGRADE(&qpdb->tree_lock, &tlocktype); 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) { if (result != ISC_R_SUCCESS) {
node = new_qpcnode(qpdb, name); node = new_qpcnode(qpdb, name);
node->nsec = dopt;
result = dns_qp_insert(qpdb->tree, node, 0); result = dns_qp_insert(qpdb->tree, node, 0);
INSIST(result == ISC_R_SUCCESS); INSIST(result == ISC_R_SUCCESS);
qpcnode_unref(node); 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) { if (rdataset->type == dns_rdatatype_nsec) {
NODE_RDLOCK(nlock, &nlocktype); NODE_RDLOCK(nlock, &nlocktype);
if (qpnode->nsec != DNS_DB_NSEC_HAS_NSEC) { if (!qpnode->havensec) {
newnsec = true; newnsec = true;
} }
NODE_UNLOCK(nlock, &nlocktype); 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, expire_ttl_headers(qpdb, qpnode->locknum, &nlocktype, &tlocktype,
now DNS__DB_FLARG_PASS); now DNS__DB_FLARG_PASS);
if (newnsec && qpnode->nsec != DNS_DB_NSEC_HAS_NSEC) { if (newnsec && !qpnode->havensec) {
qpcnode_t *nsecnode = NULL; qpcnode_t *nsecnode = NULL;
result = dns_qp_getname(qpdb->nsec, name, (void **)&nsecnode, result = dns_qp_getname(qpdb->nsec, name, DNS_DB_NSEC_NSEC,
NULL); (void **)&nsecnode, NULL);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
INSIST(nsecnode == NULL); INSIST(nsecnode == NULL);
nsecnode = new_qpcnode(qpdb, name); 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); INSIST(result == ISC_R_SUCCESS);
qpcnode_detach(&nsecnode); qpcnode_detach(&nsecnode);
} }
qpnode->nsec = DNS_DB_NSEC_HAS_NSEC; qpnode->havensec = true;
} }
result = add(qpdb, qpnode, name, newheader, options, addedrdataset, now, result = add(qpdb, qpnode, name, newheader, options, addedrdataset, now,

View File

@ -201,6 +201,7 @@ struct qpznode {
uint16_t locknum; uint16_t locknum;
atomic_uint_fast8_t nsec; atomic_uint_fast8_t nsec;
atomic_bool havensec;
atomic_bool wild; atomic_bool wild;
atomic_bool delegating; atomic_bool delegating;
atomic_bool dirty; 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); dns_qpmulti_write(qpdb->tree, &qp);
qpdb->origin = new_qpznode(qpdb, &qpdb->common.origin); qpdb->origin = new_qpznode(qpdb, &qpdb->common.origin);
qpdb->origin->nsec = DNS_DB_NSEC_NORMAL;
result = dns_qp_insert(qp, qpdb->origin, 0); result = dns_qp_insert(qp, qpdb->origin, 0);
INSIST(result == ISC_R_SUCCESS); INSIST(result == ISC_R_SUCCESS);
qpdb->origin->nsec = DNS_DB_NSEC_NORMAL;
dns_qpmulti_commit(qpdb->tree, &qp); 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; qpznode_t *node = NULL, *nsecnode = NULL;
if (type == dns_rdatatype_nsec3 || covers == dns_rdatatype_nsec3) { if (type == dns_rdatatype_nsec3 || covers == dns_rdatatype_nsec3) {
result = dns_qp_getname(loadctx->nsec3, name, (void **)&node, result = dns_qp_getname(loadctx->nsec3, name, DNS_DB_NSEC_NSEC3,
NULL); (void **)&node, NULL);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
*nodep = node; *nodep = node;
} else { } else {
node = new_qpznode(qpdb, name); node = new_qpznode(qpdb, name);
node->nsec = DNS_DB_NSEC_NSEC3;
result = dns_qp_insert(loadctx->nsec3, node, 0); result = dns_qp_insert(loadctx->nsec3, node, 0);
INSIST(result == ISC_R_SUCCESS); INSIST(result == ISC_R_SUCCESS);
node->nsec = DNS_DB_NSEC_NSEC3;
*nodep = node; *nodep = node;
qpznode_detach(&node); qpznode_detach(&node);
} }
return; 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 (result == ISC_R_SUCCESS) {
if (type == dns_rdatatype_nsec && if (type == dns_rdatatype_nsec && node->havensec) {
node->nsec == DNS_DB_NSEC_HAS_NSEC)
{
goto done; goto done;
} }
} else { } else {
INSIST(node == NULL); INSIST(node == NULL);
node = new_qpznode(qpdb, name); node = new_qpznode(qpdb, name);
node->nsec = DNS_DB_NSEC_NORMAL;
result = dns_qp_insert(loadctx->tree, node, 0); result = dns_qp_insert(loadctx->tree, node, 0);
INSIST(result == ISC_R_SUCCESS); INSIST(result == ISC_R_SUCCESS);
qpznode_unref(node); 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 * node there, so we can just detach the new one we created and
* move on. * move on.
*/ */
node->nsec = DNS_DB_NSEC_HAS_NSEC; node->havensec = true;
nsecnode = new_qpznode(qpdb, name); nsecnode = new_qpznode(qpdb, name);
nsecnode->nsec = DNS_DB_NSEC_NSEC; nsecnode->nsec = DNS_DB_NSEC_NSEC;
(void)dns_qp_insert(loadctx->nsec, nsecnode, 0); (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 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; isc_result_t result;
dns_name_t foundname; dns_name_t foundname;
unsigned int n; 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); dns_name_getlabelsequence(name, 1, n, &foundname);
/* insert an empty node, if needed, to hold the wildcard bit */ /* 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) { if (result != ISC_R_SUCCESS) {
INSIST(node == NULL); INSIST(node == NULL);
node = new_qpznode(qpdb, &foundname); node = new_qpznode(qpdb, &foundname);
node->nsec = denial;
result = dns_qp_insert(qp, node, 0); result = dns_qp_insert(qp, node, 0);
INSIST(result == ISC_R_SUCCESS); INSIST(result == ISC_R_SUCCESS);
qpznode_unref(node); qpznode_unref(node);
@ -2141,7 +2144,8 @@ wildcardmagic(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name) {
} }
static void 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; dns_name_t foundname;
unsigned int n, l, i; 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) { while (i < n) {
dns_name_getlabelsequence(name, n - i, i, &foundname); dns_name_getlabelsequence(name, n - i, i, &foundname);
if (dns_name_iswildcard(&foundname)) { if (dns_name_iswildcard(&foundname)) {
wildcardmagic(qpdb, qp, &foundname); wildcardmagic(qpdb, qp, &foundname, denial);
} }
i++; i++;
@ -2185,7 +2189,7 @@ loading_addrdataset(void *arg, const dns_name_t *name,
if (rdataset->type != dns_rdatatype_nsec3 && if (rdataset->type != dns_rdatatype_nsec3 &&
rdataset->covers != 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)) { if (dns_name_iswildcard(name)) {
@ -2203,7 +2207,7 @@ loading_addrdataset(void *arg, const dns_name_t *name,
return DNS_R_INVALIDNSEC3; 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); 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) { bool nsec3, dns_dbnode_t **nodep DNS__DB_FLARG) {
isc_result_t result; isc_result_t result;
qpznode_t *node = NULL; 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_qpmulti_t *dbtree = nsec3 ? qpdb->nsec3 : qpdb->tree;
dns_qpread_t qpr = { 0 }; dns_qpread_t qpr = { 0 };
dns_qp_t *qp = NULL; 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; 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 (result != ISC_R_SUCCESS) {
if (!create) { if (!create) {
dns_qpread_destroy(dbtree, &qpr); 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 = new_qpznode(qpdb, name);
node->nsec = denial;
result = dns_qp_insert(qp, node, 0); result = dns_qp_insert(qp, node, 0);
INSIST(result == ISC_R_SUCCESS); INSIST(result == ISC_R_SUCCESS);
qpznode_unref(node); qpznode_unref(node);
if (nsec3) { if (!nsec3) {
node->nsec = DNS_DB_NSEC_NSEC3; addwildcards(qpdb, qp, name, denial);
} else {
addwildcards(qpdb, qp, name);
if (dns_name_iswildcard(name)) { 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 static isc_result_t
find_wildcard(qpz_search_t *search, qpznode_t **nodep, find_wildcard(qpz_search_t *search, qpznode_t **nodep, const dns_name_t *qname,
const dns_name_t *qname) { uint8_t denial) {
dns_slabheader_t *header = NULL; dns_slabheader_t *header = NULL;
isc_result_t result = ISC_R_NOTFOUND; isc_result_t result = ISC_R_NOTFOUND;
@ -2938,8 +2942,9 @@ find_wildcard(qpz_search_t *search, qpznode_t **nodep,
break; break;
} }
result = dns_qp_lookup(&search->qpr, wname, NULL, &wit, result = dns_qp_lookup2(&search->qpr, wname, denial,
NULL, (void **)&wnode, NULL); NULL, &wit, NULL,
(void **)&wnode, NULL);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
/* /*
* We have found the wildcard node. If it * 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. * It is the first node sought in the NSEC tree.
*/ */
*firstp = false; *firstp = false;
result = dns_qp_lookup(&qpr, name, NULL, nit, NULL, result = dns_qp_lookup2(&qpr, name, DNS_DB_NSEC_NSEC,
NULL, NULL); NULL, nit, NULL, NULL, NULL);
INSIST(result != ISC_R_NOTFOUND); INSIST(result != ISC_R_NOTFOUND);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
/* /*
@ -3063,8 +3068,9 @@ previous_closest_nsec(dns_rdatatype_t type, qpz_search_t *search,
} }
*nodep = NULL; *nodep = NULL;
result = dns_qp_lookup(&search->qpr, name, NULL, &search->iter, result = dns_qp_lookup2(&search->qpr, name, DNS_DB_NSEC_NORMAL,
&search->chain, (void **)nodep, NULL); NULL, &search->iter, &search->chain,
(void **)nodep, NULL);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
break; break;
} }
@ -3200,12 +3206,10 @@ again:
*nodep = (dns_dbnode_t *)node; *nodep = (dns_dbnode_t *)node;
} }
bindrdataset(search->qpdb, node, found, bindrdataset(search->qpdb, node, found,
rdataset DNS__DB_FLARG_PASS); rdataset DNS__DB_FLARG_PASS);
if (foundsig != NULL) { if (foundsig != NULL) {
bindrdataset( bindrdataset(
search->qpdb, node, foundsig, search->qpdb, node, foundsig,
sigrdataset DNS__DB_FLARG_PASS); sigrdataset DNS__DB_FLARG_PASS);
} }
} else if (found == NULL && foundsig == NULL) { } 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; close_version = true;
} }
uint8_t denial;
qpz_search_t search; qpz_search_t search;
qpz_search_init(&search, (qpzonedb_t *)db, (qpz_version_t *)version, qpz_search_init(&search, (qpzonedb_t *)db, (qpz_version_t *)version,
options); 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) { if ((options & DNS_DBFIND_FORCENSEC3) != 0) {
dns_qpmulti_query(qpdb->nsec3, &search.qpr); dns_qpmulti_query(qpdb->nsec3, &search.qpr);
nsec3 = true; nsec3 = true;
denial = DNS_DB_NSEC_NSEC3;
} else { } else {
dns_qpmulti_query(qpdb->tree, &search.qpr); dns_qpmulti_query(qpdb->tree, &search.qpr);
denial = DNS_DB_NSEC_NORMAL;
} }
/* /*
* Search down from the root of the tree. * Search down from the root of the tree.
*/ */
result = dns_qp_lookup(&search.qpr, name, NULL, &search.iter, result = dns_qp_lookup2(&search.qpr, name, denial, NULL, &search.iter,
&search.chain, (void **)&node, NULL); &search.chain, (void **)&node, NULL);
if (result != ISC_R_NOTFOUND) { if (result != ISC_R_NOTFOUND) {
dns_name_copy(&node->name, foundname); 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 * we must see if there's a matching wildcard active
* in the current version. * in the current version.
*/ */
result = find_wildcard(&search, &node, name); result = find_wildcard(&search, &node, name, denial);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
dns_name_copy(name, foundname); dns_name_copy(name, foundname);
wild = true; wild = true;
@ -4457,9 +4464,10 @@ dbiterator_seek(dns_dbiterator_t *iterator,
switch (qpdbiter->nsec3mode) { switch (qpdbiter->nsec3mode) {
case nsec3only: case nsec3only:
qpdbiter->current = &qpdbiter->nsec3iter; qpdbiter->current = &qpdbiter->nsec3iter;
result = dns_qp_lookup(qpdbiter->nsnap, name, NULL, result = dns_qp_lookup2(qpdbiter->nsnap, name,
qpdbiter->current, NULL, DNS_DB_NSEC_NSEC3, NULL,
(void **)&qpdbiter->node, NULL); qpdbiter->current, NULL,
(void **)&qpdbiter->node, NULL);
break; break;
case nonsec3: case nonsec3:
qpdbiter->current = &qpdbiter->mainiter; qpdbiter->current = &qpdbiter->mainiter;
@ -4477,9 +4485,9 @@ dbiterator_seek(dns_dbiterator_t *iterator,
qpdbiter->current, NULL, qpdbiter->current, NULL,
(void **)&qpdbiter->node, NULL); (void **)&qpdbiter->node, NULL);
if (result == DNS_R_PARTIALMATCH) { if (result == DNS_R_PARTIALMATCH) {
tresult = dns_qp_lookup(qpdbiter->nsnap, name, NULL, tresult = dns_qp_lookup2(
&qpdbiter->nsec3iter, NULL, qpdbiter->nsnap, name, DNS_DB_NSEC_NSEC3, NULL,
NULL, NULL); &qpdbiter->nsec3iter, NULL, NULL, NULL);
if (tresult == ISC_R_SUCCESS) { if (tresult == ISC_R_SUCCESS) {
qpdbiter->current = &qpdbiter->nsec3iter; qpdbiter->current = &qpdbiter->nsec3iter;
result = tresult; 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. * Add to the auxiliary NSEC tree if we're adding an NSEC record.
*/ */
if (node->nsec != DNS_DB_NSEC_HAS_NSEC && if (!node->havensec && rdataset->type == dns_rdatatype_nsec) {
rdataset->type == dns_rdatatype_nsec)
{
dns_qpmulti_write(qpdb->nsec, &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; result = ISC_R_SUCCESS;
if (nsec != NULL) { if (nsec != NULL) {
node->nsec = DNS_DB_NSEC_HAS_NSEC; node->havensec = true;
/* /*
* If it fails, there was already an NSEC node, * 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, qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) { uint32_t ival ISC_ATTR_UNUSED) {
qpznode_t *data = pval; qpznode_t *data = pval;
return dns_qpkey_fromname(key, &data->name); return dns_qpkey_fromname(key, &data->name, data->nsec);
} }
static void static void

View File

@ -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_qp_t *qp = NULL;
dns_qpmulti_write(rpzs->table, &qp); 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) { if (result != ISC_R_SUCCESS) {
INSIST(data == NULL); INSIST(data == NULL);
data = new_nmdata(rpzs->mctx, trig_name, new_data); 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); trig_name = dns_fixedname_initname(&trig_namef);
name2data(rpz, rpz_type, src_name, trig_name, &del_data); 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) { if (result != ISC_R_SUCCESS) {
return; 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 && if (data->set.qname == 0 && data->set.ns == 0 &&
data->wild.qname == 0 && data->wild.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) { if (result != ISC_R_SUCCESS) {
/* /*
* bin/tests/system/rpz/tests.sh looks for * 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, qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) { uint32_t ival ISC_ATTR_UNUSED) {
nmdata_t *data = pval; nmdata_t *data = pval;
return dns_qpkey_fromname(key, &data->name); return dns_qpkey_fromname(key, &data->name, 0);
} }
static void static void

View File

@ -77,7 +77,7 @@ ztqpmakekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) { uint32_t ival ISC_ATTR_UNUSED) {
dns_zone_t *zone = pval; dns_zone_t *zone = pval;
dns_name_t *name = dns_zone_getorigin(zone); dns_name_t *name = dns_zone_getorigin(zone);
return dns_qpkey_fromname(key, name); return dns_qpkey_fromname(key, name, 0);
} }
static void static void
@ -156,7 +156,7 @@ dns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone) {
REQUIRE(VALID_ZT(zt)); REQUIRE(VALID_ZT(zt));
dns_qpmulti_write(zt->multi, &qp); 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_qp_compact(qp, DNS_QPGC_MAYBE);
dns_qpmulti_commit(zt->multi, &qp); 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); dns_qpmulti_query(zt->multi, &qpr);
if (exactopts == DNS_ZTFIND_EXACT) { if (exactopts == DNS_ZTFIND_EXACT) {
result = dns_qp_getname(&qpr, name, &pval, NULL); result = dns_qp_getname(&qpr, name, 0, &pval, NULL);
} else { } else {
result = dns_qp_lookup(&qpr, name, NULL, NULL, &chain, &pval, result = dns_qp_lookup(&qpr, name, NULL, NULL, &chain, &pval,
NULL); NULL);

View File

@ -66,7 +66,7 @@ static size_t
item_makekey(dns_qpkey_t key, void *ctx, void *pval, uint32_t ival) { item_makekey(dns_qpkey_t key, void *ctx, void *pval, uint32_t ival) {
UNUSED(ctx); UNUSED(ctx);
assert(pval == &item[ival]); 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 static void
@ -325,7 +325,7 @@ sqz_qp(void *qp) {
static isc_result_t static isc_result_t
get_qp(void *qp, size_t count, void **pval) { 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 * static void *

View File

@ -87,7 +87,7 @@ qpkey_from_smallname(dns_qpkey_t key, void *ctx, void *pval, uint32_t ival) {
UNUSED(ctx); UNUSED(ctx);
dns_name_t name = DNS_NAME_INITEMPTY; dns_name_t name = DNS_NAME_INITEMPTY;
name_from_smallname(&name, pval, ival); name_from_smallname(&name, pval, ival);
return dns_qpkey_fromname(key, &name); return dns_qpkey_fromname(key, &name, 0);
} }
static void static void

View File

@ -81,7 +81,7 @@ qpkey_from_smallname(dns_qpkey_t key, void *ctx, void *pval, uint32_t ival) {
UNUSED(ctx); UNUSED(ctx);
dns_name_t name = DNS_NAME_INITEMPTY; dns_name_t name = DNS_NAME_INITEMPTY;
name_from_smallname(&name, pval, ival); name_from_smallname(&name, pval, ival);
return dns_qpkey_fromname(key, &name); return dns_qpkey_fromname(key, &name, 0);
} }
static void static void
@ -228,7 +228,7 @@ main(int argc, char **argv) {
start = isc_time_monotonic(); start = isc_time_monotonic();
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
name = dns_fixedname_name(&items[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(); stop = isc_time_monotonic();

View File

@ -137,8 +137,9 @@ init_items(isc_mem_t *mctx) {
for (size_t i = 0; i < ITEM_COUNT; i++) { for (size_t i = 0; i < ITEM_COUNT; i++) {
do { do {
size_t len = isc_random_uniform(16) + 4; size_t len = isc_random_uniform(16) + 4;
item[i].len = len; item[i].len = len + 1;
for (size_t off = 0; off < len; off++) { item[i].key[0] = 0;
for (size_t off = 1; off < len; off++) {
item[i].key[off] = random_byte(); item[i].key[off] = random_byte();
} }
item[i].key[len] = SHIFT_NOBYTE; item[i].key[len] = SHIFT_NOBYTE;

View File

@ -45,56 +45,78 @@ bool verbose = false;
ISC_RUN_TEST_IMPL(qpkey_name) { ISC_RUN_TEST_IMPL(qpkey_name) {
struct { struct {
const char *namestr; const char *namestr;
uint8_t denial;
uint8_t key[512]; uint8_t key[512];
size_t len; size_t len;
} testcases[] = { } testcases[] = {
{ {
.namestr = "", .namestr = "",
.key = { 0x02 }, .denial = DNS_DB_NSEC_NORMAL,
.len = 0, .key = { 0x00, 0x02 },
},
{
.namestr = ".",
.key = { 0x02, 0x02 },
.len = 1, .len = 1,
}, },
{
.namestr = ".",
.denial = DNS_DB_NSEC_NORMAL,
.key = { 0x00, 0x02, 0x02 },
.len = 2,
},
{ {
.namestr = "\\000", .namestr = "\\000",
.key = { 0x03, 0x03, 0x02 }, .denial = DNS_DB_NSEC_NORMAL,
.len = 3, .key = { 0x00, 0x03, 0x03, 0x02 },
},
{
.namestr = "\\000\\009",
.key = { 0x03, 0x03, 0x03, 0x0c, 0x02 },
.len = 5,
},
{
.namestr = "com",
.key = { 0x16, 0x22, 0x20, 0x02 },
.len = 4, .len = 4,
}, },
{ {
.namestr = "com.", .namestr = "\\000\\009",
.key = { 0x02, 0x16, 0x22, 0x20, 0x02 }, .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, .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.", .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 }, 0x20, 0x23, 0x1f, 0x18, 0x02 },
.len = 13, .len = 13,
}, },
{
.namestr = "example.com",
.key = { 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14, 0x20,
0x23, 0x1f, 0x18, 0x02 },
.len = 12,
},
{ {
.namestr = "EXAMPLE.COM", .namestr = "EXAMPLE.COM",
.key = { 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14, 0x20, .denial = DNS_DB_NSEC_NORMAL,
0x23, 0x1f, 0x18, 0x02 }, .key = { 0x00, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14,
.len = 12, 0x20, 0x23, 0x1f, 0x18, 0x02 },
.len = 13,
}, },
}; };
@ -104,28 +126,26 @@ ISC_RUN_TEST_IMPL(qpkey_name) {
dns_fixedname_t fn1, fn2; dns_fixedname_t fn1, fn2;
dns_name_t *in = NULL, *out = NULL; dns_name_t *in = NULL, *out = NULL;
char namebuf[DNS_NAME_FORMATSIZE]; char namebuf[DNS_NAME_FORMATSIZE];
uint8_t denial;
in = dns_fixedname_initname(&fn1); in = dns_fixedname_initname(&fn1);
if (testcases[i].len != 0) { if (testcases[i].len > 1) {
dns_test_namefromstring(testcases[i].namestr, &fn1); dns_test_namefromstring(testcases[i].namestr, &fn1);
} }
len = dns_qpkey_fromname(key, in); len = dns_qpkey_fromname(key, in, testcases[i].denial);
if (verbose) { if (verbose) {
qp_test_printkey(key, len); qp_test_printkey(key, len);
} }
assert_int_equal(testcases[i].len, len); assert_int_equal(testcases[i].len, len);
assert_memory_equal(testcases[i].key, key, 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); 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_true(dns_name_equal(in, out));
assert_int_equal(denial, testcases[i].denial);
/* check that 'out' is properly reset by dns_qpkey_toname */ /* 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)); dns_name_format(out, namebuf, sizeof(namebuf));
} }
} }
@ -156,7 +176,7 @@ ISC_RUN_TEST_IMPL(qpkey_sort) {
&testcases[i].fixed); &testcases[i].fixed);
testcases[i].name = dns_fixedname_name(&testcases[i].fixed); testcases[i].name = dns_fixedname_name(&testcases[i].fixed);
testcases[i].len = dns_qpkey_fromname(testcases[i].key, 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++) { 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; return 0;
} }
dns_test_namefromstring(pval, &fixed); 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 = { 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 * what if entries in the trie are relative to the zone apex
* and there's no root node? * 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); result = dns_qp_deletekey(qp, rootkey, 1, NULL, NULL);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
check_partialmatch(qp, (struct check_partialmatch[]){ check_partialmatch(qp, (struct check_partialmatch[]){
@ -502,15 +522,6 @@ ISC_RUN_TEST_IMPL(partialmatch) {
{ NULL, 0, NULL }, { 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); dns_qp_destroy(&qp);
} }

View File

@ -23,6 +23,7 @@
#include <isc/urcu.h> #include <isc/urcu.h>
#include <isc/util.h> #include <isc/util.h>
#include <dns/db.h>
#include <dns/fixedname.h> #include <dns/fixedname.h>
#include <dns/name.h> #include <dns/name.h>
#include <dns/qp.h> #include <dns/qp.h>
@ -55,7 +56,7 @@ qp_test_bittoascii(dns_qpshift_t bit) {
const char * const char *
qp_test_keytoascii(dns_qpkey_t key, size_t len) { 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[offset] = qp_test_bittoascii(key[offset]);
} }
key[len] = '\0'; key[len] = '\0';
@ -342,11 +343,15 @@ void
qp_test_printkey(const dns_qpkey_t key, size_t keylen) { qp_test_printkey(const dns_qpkey_t key, size_t keylen) {
dns_fixedname_t fn; dns_fixedname_t fn;
dns_name_t *n = dns_fixedname_initname(&fn); dns_name_t *n = dns_fixedname_initname(&fn);
uint8_t d;
char txt[DNS_NAME_FORMATSIZE]; 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)); 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) ? "." : "");
} }
/**********************************************************************/ /**********************************************************************/