chg: dev: Prepend qpkey with namespace (normal vs denial of existence)

Merge the three qp tries (tree, nsec, nsec3) into one, add the namespace to the qpkey.

Merge branch 'matthijs-one-trie-for-zone-and-nsec3' into 'main'

See merge request isc-projects/bind9!10480
This commit is contained in:
Matthijs Mekking 2025-07-10 13:53:07 +00:00
commit 15653c54a0
19 changed files with 1908 additions and 594 deletions

View file

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

View file

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

View file

@ -163,7 +163,8 @@ dns_fwdtable_find(dns_fwdtable_t *fwdtable, const dns_name_t *name,
REQUIRE(VALID_FWDTABLE(fwdtable));
dns_qpmulti_query(fwdtable->table, &qpr);
result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, &pval, NULL);
result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL,
NULL, &pval, NULL);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
dns_forwarders_t *fwdrs = pval;
*forwardersp = fwdrs;
@ -233,7 +234,7 @@ static size_t
qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) {
dns_forwarders_t *fwd = pval;
return dns_qpkey_fromname(key, &fwd->name);
return dns_qpkey_fromname(key, &fwd->name, DNS_DBNAMESPACE_NORMAL);
}
static void

View file

@ -233,15 +233,15 @@ struct dns_dbonupdatelistener {
};
/*%
* Used in composite databases such as RBTDB to indicate whether a node
* exists in a specal tree for NSEC or NSEC3.
* Used in QP keys to indicate whether a node is in a special namespace
* such as NSEC or NSEC3. These values will be mapped to characters at
* the beginning of the key, converting them to '0', '1', and '2'.
*/
enum {
DNS_DB_NSEC_NORMAL = 0, /* in main tree */
DNS_DB_NSEC_HAS_NSEC = 1, /* also has node in nsec tree */
DNS_DB_NSEC_NSEC = 2, /* in nsec tree */
DNS_DB_NSEC_NSEC3 = 3 /* in nsec3 tree */
};
typedef enum {
DNS_DBNAMESPACE_NORMAL = 0, /* regular namespace */
DNS_DBNAMESPACE_NSEC = 1, /* nsec namespace */
DNS_DBNAMESPACE_NSEC3 = 2, /* nsec3 namespace */
} dns_namespace_t;
/*@{*/
/*%

View file

@ -86,6 +86,7 @@
#include <isc/attributes.h>
#include <dns/db.h>
#include <dns/name.h>
#include <dns/types.h>
@ -181,8 +182,11 @@ typedef union dns_qpreadable {
* A domain name can be up to 255 bytes. When converted to a key, each
* character in the name corresponds to one byte in the key if it is a
* common hostname character; otherwise unusual characters are escaped,
* using two bytes in the key. So we allow keys to be up to 512 bytes.
* (The actual max is (255 - 5) * 2 + 6 == 506)
* using two bytes in the key. Because the maximum label length is 63
* characters, the actual max is (255 - 5) * 2 + 6 == 506. Then, we need
* one more byte to prepend the namespace.
*
* Note: this gives us 5 bytes available space to store more data.
*/
#define DNS_QP_MAXKEY 512
@ -470,9 +474,10 @@ dns_qpmulti_memusage(dns_qpmulti_t *multi);
*/
size_t
dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name);
dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name,
dns_namespace_t space);
/*%<
* Convert a DNS name into a trie lookup key.
* Convert a DNS name into a trie lookup key in the right namespace.
*
* Requires:
* \li `name` is a pointer to a valid `dns_name_t`
@ -485,10 +490,13 @@ dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name);
*/
void
dns_qpkey_toname(const dns_qpkey_t key, size_t keylen, dns_name_t *name);
dns_qpkey_toname(const dns_qpkey_t key, size_t keylen, dns_name_t *name,
dns_namespace_t *space);
/*%<
* Convert a trie lookup key back into a DNS name.
*
* 'space' stores whether the key is for a normal name, or denial of existence.
*
* Requires:
* \li `name` is a pointer to a valid `dns_name_t`
* \li `name->buffer` is not NULL
@ -514,10 +522,10 @@ dns_qp_getkey(dns_qpreadable_t qpr, const dns_qpkey_t search_key,
*/
isc_result_t
dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, void **pval_r,
uint32_t *ival_r);
dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name,
dns_namespace_t space, void **pval_r, uint32_t *ival_r);
/*%<
* Find a leaf in a qp-trie that matches the given DNS name
* Find a leaf in a qp-trie that matches the given DNS name, and namespace.
*
* The leaf values are assigned to whichever of `*pval_r` and `*ival_r`
* are not null, unless the return value is ISC_R_NOTFOUND.
@ -533,11 +541,11 @@ dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, void **pval_r,
isc_result_t
dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name,
dns_name_t *foundname, dns_qpiter_t *iter, dns_qpchain_t *chain,
void **pval_r, uint32_t *ival_r);
dns_namespace_t space, dns_name_t *foundname, dns_qpiter_t *iter,
dns_qpchain_t *chain, void **pval_r, uint32_t *ival_r);
/*%<
* Look up a leaf in a qp-trie that is equal to, or an ancestor domain of,
* 'name'.
* 'name' in the namespace 'space'.
*
* If 'foundname' is not NULL, it will be updated to contain the name
* that was found (if any). The return code, ISC_R_SUCCESS or
@ -609,10 +617,10 @@ dns_qp_deletekey(dns_qp_t *qp, const dns_qpkey_t key, size_t keylen,
*/
isc_result_t
dns_qp_deletename(dns_qp_t *qp, const dns_name_t *name, void **pval_r,
uint32_t *ival_r);
dns_qp_deletename(dns_qp_t *qp, const dns_name_t *name, dns_namespace_t space,
void **pval_r, uint32_t *ival_r);
/*%<
* Delete a leaf from a qp-trie that matches the given DNS name
* Delete a leaf from a qp-trie that matches the given DNS name, and namespace.
*
* The leaf values are assigned to whichever of `*pval_r` and `*ival_r`
* are not null, unless the return value is ISC_R_NOTFOUND.

View file

@ -273,7 +273,8 @@ delete_ds(dns_qp_t *qp, dns_keytable_t *keytable, dns_keynode_t *knode,
}
}
result = dns_qp_deletename(qp, &knode->name, &pval, NULL);
result = dns_qp_deletename(qp, &knode->name, DNS_DBNAMESPACE_NORMAL,
&pval, NULL);
INSIST(result == ISC_R_SUCCESS);
INSIST(pval == knode);
@ -343,7 +344,8 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
dns_qpmulti_write(keytable->table, &qp);
result = dns_qp_getname(qp, keyname, &pval, NULL);
result = dns_qp_getname(qp, keyname, DNS_DBNAMESPACE_NORMAL, &pval,
NULL);
if (result != ISC_R_SUCCESS) {
/*
* There was no match for "keyname" in "keytable" yet, so one
@ -400,7 +402,8 @@ dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname,
REQUIRE(keyname != NULL);
dns_qpmulti_write(keytable->table, &qp);
result = dns_qp_deletename(qp, keyname, &pval, NULL);
result = dns_qp_deletename(qp, keyname, DNS_DBNAMESPACE_NORMAL, &pval,
NULL);
if (result == ISC_R_SUCCESS) {
dns_keynode_t *n = pval;
if (callback != NULL) {
@ -430,7 +433,8 @@ dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname,
REQUIRE(dnskey != NULL);
dns_qpmulti_write(keytable->table, &qp);
result = dns_qp_getname(qp, keyname, &pval, NULL);
result = dns_qp_getname(qp, keyname, DNS_DBNAMESPACE_NORMAL, &pval,
NULL);
if (result != ISC_R_SUCCESS) {
goto finish;
}
@ -479,7 +483,8 @@ dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname,
REQUIRE(keynodep != NULL && *keynodep == NULL);
dns_qpmulti_query(keytable->table, &qpr);
result = dns_qp_getname(&qpr, keyname, &pval, NULL);
result = dns_qp_getname(&qpr, keyname, DNS_DBNAMESPACE_NORMAL, &pval,
NULL);
if (result == ISC_R_SUCCESS) {
dns_keynode_t *knode = pval;
dns_keynode_attach(knode, keynodep);
@ -506,7 +511,8 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
REQUIRE(foundname != NULL);
dns_qpmulti_query(keytable->table, &qpr);
result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, &pval, NULL);
result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL,
NULL, &pval, NULL);
keynode = pval;
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
@ -535,7 +541,8 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name,
REQUIRE(wantdnssecp != NULL);
dns_qpmulti_query(keytable->table, &qpr);
result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, &pval, NULL);
result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL,
NULL, &pval, NULL);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
keynode = pval;
if (foundname != NULL) {
@ -830,7 +837,7 @@ static size_t
qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) {
dns_keynode_t *keynode = pval;
return dns_qpkey_fromname(key, &keynode->name);
return dns_qpkey_fromname(key, &keynode->name, DNS_DBNAMESPACE_NORMAL);
}
static void

View file

@ -164,14 +164,16 @@ dns_nametree_add(dns_nametree_t *nametree, const dns_name_t *name,
case DNS_NAMETREE_COUNT:
new = newnode(nametree->mctx, name);
new->set = true;
result = dns_qp_deletename(qp, name, (void **)&old, &count);
result = dns_qp_deletename(qp, name, DNS_DBNAMESPACE_NORMAL,
(void **)&old, &count);
if (result == ISC_R_SUCCESS) {
count += 1;
}
break;
case DNS_NAMETREE_BITS:
result = dns_qp_getname(qp, name, (void **)&old, NULL);
result = dns_qp_getname(qp, name, DNS_DBNAMESPACE_NORMAL,
(void **)&old, NULL);
if (result == ISC_R_SUCCESS && matchbit(old->bits, value)) {
goto out;
}
@ -187,7 +189,8 @@ dns_nametree_add(dns_nametree_t *nametree, const dns_name_t *name,
new->bits = isc_mem_cget(nametree->mctx, size, sizeof(char));
if (result == ISC_R_SUCCESS) {
memmove(new->bits, old->bits, old->bits[0]);
result = dns_qp_deletename(qp, name, NULL, NULL);
result = dns_qp_deletename(
qp, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL);
INSIST(result == ISC_R_SUCCESS);
}
@ -222,7 +225,8 @@ dns_nametree_delete(dns_nametree_t *nametree, const dns_name_t *name) {
REQUIRE(name != NULL);
dns_qpmulti_write(nametree->table, &qp);
result = dns_qp_deletename(qp, name, (void **)&old, &count);
result = dns_qp_deletename(qp, name, DNS_DBNAMESPACE_NORMAL,
(void **)&old, &count);
switch (nametree->type) {
case DNS_NAMETREE_BOOL:
case DNS_NAMETREE_BITS:
@ -258,7 +262,8 @@ dns_nametree_find(dns_nametree_t *nametree, const dns_name_t *name,
REQUIRE(ntnodep != NULL && *ntnodep == NULL);
dns_qpmulti_query(nametree->table, &qpr);
result = dns_qp_getname(&qpr, name, (void **)&node, NULL);
result = dns_qp_getname(&qpr, name, DNS_DBNAMESPACE_NORMAL,
(void **)&node, NULL);
if (result == ISC_R_SUCCESS) {
dns_ntnode_attach(node, ntnodep);
}
@ -278,8 +283,8 @@ dns_nametree_covered(dns_nametree_t *nametree, const dns_name_t *name,
REQUIRE(VALID_NAMETREE(nametree));
dns_qpmulti_query(nametree->table, &qpr);
result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, (void **)&node,
NULL);
result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL,
NULL, (void **)&node, NULL);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
if (found != NULL) {
dns_name_copy(&node->name, found);
@ -319,7 +324,7 @@ static size_t
qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) {
dns_ntnode_t *ntnode = pval;
return dns_qpkey_fromname(key, &ntnode->name);
return dns_qpkey_fromname(key, &ntnode->name, DNS_DBNAMESPACE_NORMAL);
}
static void

View file

@ -316,7 +316,8 @@ dns_ntatable_add(dns_ntatable_t *ntatable, const dns_name_t *name, bool force,
result = dns_qp_insert(qp, nta, 0);
switch (result) {
case ISC_R_EXISTS:
result = dns_qp_getname(qp, &nta->name, &pval, NULL);
result = dns_qp_getname(qp, &nta->name, DNS_DBNAMESPACE_NORMAL,
&pval, NULL);
if (result == ISC_R_SUCCESS) {
/*
* an NTA already existed: throw away the
@ -355,7 +356,8 @@ dns_ntatable_delete(dns_ntatable_t *ntatable, const dns_name_t *name) {
REQUIRE(name != NULL);
dns_qpmulti_write(ntatable->table, &qp);
result = dns_qp_deletename(qp, name, &pval, NULL);
result = dns_qp_deletename(qp, name, DNS_DBNAMESPACE_NORMAL, &pval,
NULL);
if (result == ISC_R_SUCCESS) {
dns__nta_t *n = pval;
dns__nta_shutdown(n);
@ -379,7 +381,8 @@ delete_expired(void *arg) {
RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
dns_qpmulti_write(ntatable->table, &qp);
result = dns_qp_getname(qp, &nta->name, &pval, NULL);
result = dns_qp_getname(qp, &nta->name, DNS_DBNAMESPACE_NORMAL, &pval,
NULL);
if (result == ISC_R_SUCCESS &&
((dns__nta_t *)pval)->expiry == nta->expiry && !nta->shuttingdown)
{
@ -387,7 +390,8 @@ delete_expired(void *arg) {
dns_name_format(&nta->name, nb, sizeof(nb));
isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_NTA,
ISC_LOG_INFO, "deleting expired NTA at %s", nb);
dns_qp_deletename(qp, &nta->name, NULL, NULL);
dns_qp_deletename(qp, &nta->name, DNS_DBNAMESPACE_NORMAL, NULL,
NULL);
dns__nta_shutdown(nta);
dns__nta_unref(nta);
}
@ -412,7 +416,8 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
RWLOCK(&ntatable->rwlock, isc_rwlocktype_read);
dns_qpmulti_query(ntatable->table, &qpr);
result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, &pval, NULL);
result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL,
NULL, &pval, NULL);
nta = pval;
switch (result) {
@ -649,7 +654,7 @@ static size_t
qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) {
dns__nta_t *nta = pval;
return dns_qpkey_fromname(key, &nta->name);
return dns_qpkey_fromname(key, &nta->name, DNS_DBNAMESPACE_NORMAL);
}
static void

View file

@ -115,6 +115,16 @@ ISC_REFCOUNT_STATIC_DECL(dns_qpmulti);
* converting DNS names to trie keys
*/
/*
* Convert the namespace value. We map namespace values to numerical
* digits so they can be represented in a single byte in the QP key;
* thus namespace 0 becomes '0', etc.
*/
#define ENCODE_NAMESPACE(c) dns_qp_bits_for_byte[(c) + (uint8_t)'0']
#define DECODE_NAMESPACE(c) dns_qp_byte_for_bit[(c)] - (uint8_t)'0'
#define NAME_OFFSET 1
/*
* Number of distinct byte values, i.e. 256
*/
@ -228,18 +238,22 @@ dns__qp_shutdown(void) {
* dot in a zone file).
*/
size_t
dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name) {
dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name,
dns_namespace_t space) {
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
dns_offsets_t offsets;
size_t labels = dns_name_offsets(name, offsets);
size_t len = 0;
/* namespace */
key[len++] = ENCODE_NAMESPACE(space);
/* name */
if (labels == 0) {
key[0] = SHIFT_NOBYTE;
return 0;
key[len] = SHIFT_NOBYTE;
return len;
}
size_t len = 0;
size_t label = labels;
while (label-- > 0) {
const uint8_t *ldata = name->ndata + offsets[label];
@ -261,22 +275,26 @@ dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name) {
}
void
dns_qpkey_toname(const dns_qpkey_t key, size_t keylen, dns_name_t *name) {
dns_qpkey_toname(const dns_qpkey_t key, size_t keylen, dns_name_t *name,
dns_namespace_t *space) {
size_t locs[DNS_NAME_MAXLABELS];
size_t loc = 0;
size_t offset;
size_t offset = 0;
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
REQUIRE(name->buffer != NULL);
REQUIRE(keylen > 0);
dns_name_reset(name);
if (keylen == 0) {
SET_IF_NOT_NULL(space, DECODE_NAMESPACE(key[offset++]));
if (keylen == NAME_OFFSET) {
return;
}
/* Scan the key looking for label boundaries */
for (offset = 0; offset <= keylen; offset++) {
for (; offset <= keylen; offset++) {
INSIST(key[offset] >= SHIFT_NOBYTE &&
key[offset] < SHIFT_OFFSET);
INSIST(loc < DNS_NAME_MAXLABELS);
@ -287,7 +305,7 @@ dns_qpkey_toname(const dns_qpkey_t key, size_t keylen, dns_name_t *name) {
goto scanned;
}
locs[loc++] = offset + 1;
} else if (offset == 0) {
} else if (offset == NAME_OFFSET) {
/* This happens for a relative name */
locs[loc++] = offset;
}
@ -330,7 +348,7 @@ scanned:
}
/* Add a root label for absolute names */
if (key[0] == SHIFT_NOBYTE) {
if (key[NAME_OFFSET] == SHIFT_NOBYTE) {
name->attributes.absolute = true;
isc_buffer_putuint8(name->buffer, 0);
name->length++;
@ -1826,10 +1844,10 @@ dns_qp_deletekey(dns_qp_t *qp, const dns_qpkey_t search_key,
}
isc_result_t
dns_qp_deletename(dns_qp_t *qp, const dns_name_t *name, void **pval_r,
uint32_t *ival_r) {
dns_qp_deletename(dns_qp_t *qp, const dns_name_t *name, dns_namespace_t space,
void **pval_r, uint32_t *ival_r) {
dns_qpkey_t key;
size_t keylen = dns_qpkey_fromname(key, name);
size_t keylen = dns_qpkey_fromname(key, name, space);
return dns_qp_deletekey(qp, key, keylen, pval_r, ival_r);
}
@ -1847,7 +1865,7 @@ maybe_set_name(dns_qpreader_t *qp, dns_qpnode_t *node, dns_name_t *name) {
dns_name_reset(name);
len = leaf_qpkey(qp, node, key);
dns_qpkey_toname(key, len, name);
dns_qpkey_toname(key, len, name, NULL);
}
void
@ -2089,10 +2107,10 @@ dns_qp_getkey(dns_qpreadable_t qpr, const dns_qpkey_t search_key,
}
isc_result_t
dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, void **pval_r,
uint32_t *ival_r) {
dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name,
dns_namespace_t space, void **pval_r, uint32_t *ival_r) {
dns_qpkey_t key;
size_t keylen = dns_qpkey_fromname(key, name);
size_t keylen = dns_qpkey_fromname(key, name, space);
return dns_qp_getkey(qpr, key, keylen, pval_r, ival_r);
}
@ -2268,8 +2286,8 @@ fix_chain(dns_qpchain_t *chain, size_t offset) {
isc_result_t
dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name,
dns_name_t *foundname, dns_qpiter_t *iter, dns_qpchain_t *chain,
void **pval_r, uint32_t *ival_r) {
dns_namespace_t space, dns_name_t *foundname, dns_qpiter_t *iter,
dns_qpchain_t *chain, void **pval_r, uint32_t *ival_r) {
dns_qpreader_t *qp = dns_qpreader(qpr);
dns_qpkey_t search, found;
size_t searchlen, foundlen;
@ -2284,7 +2302,7 @@ dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name,
REQUIRE(QP_VALID(qp));
REQUIRE(foundname == NULL || ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
searchlen = dns_qpkey_fromname(search, name);
searchlen = dns_qpkey_fromname(search, name, space);
if (chain == NULL) {
chain = &oc;

View file

@ -150,7 +150,8 @@ struct qpcnode {
uint8_t : 0;
unsigned int delegating : 1;
unsigned int nsec : 2; /*%< range is 0..3 */
unsigned int nspace : 2; /*%< range is 0..3 */
unsigned int havensec : 1;
uint8_t : 0;
uint16_t locknum;
@ -357,7 +358,7 @@ static size_t
qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) {
qpcnode_t *data = pval;
return dns_qpkey_fromname(key, &data->name);
return dns_qpkey_fromname(key, &data->name, data->nspace);
}
static void
@ -602,26 +603,31 @@ delete_node(qpcache_t *qpdb, qpcnode_t *node) {
printname, node->locknum);
}
switch (node->nsec) {
case DNS_DB_NSEC_HAS_NSEC:
/*
* Delete the corresponding node from the auxiliary NSEC
* tree before deleting from the main tree.
*/
result = dns_qp_deletename(qpdb->nsec, &node->name, NULL, NULL);
if (result != ISC_R_SUCCESS) {
isc_log_write(DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_CACHE, ISC_LOG_WARNING,
"delete_node(): "
"dns_qp_deletename: %s",
isc_result_totext(result));
switch (node->nspace) {
case DNS_DBNAMESPACE_NORMAL:
if (node->havensec) {
/*
* Delete the corresponding node from the auxiliary NSEC
* tree before deleting from the main tree.
*/
result = dns_qp_deletename(qpdb->nsec, &node->name,
DNS_DBNAMESPACE_NSEC, NULL,
NULL);
if (result != ISC_R_SUCCESS) {
isc_log_write(DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_CACHE,
ISC_LOG_WARNING,
"delete_node(): "
"dns_qp_deletename: %s",
isc_result_totext(result));
}
}
/* FALLTHROUGH */
case DNS_DB_NSEC_NORMAL:
result = dns_qp_deletename(qpdb->tree, &node->name, NULL, NULL);
result = dns_qp_deletename(qpdb->tree, &node->name,
node->nspace, NULL, NULL);
break;
case DNS_DB_NSEC_NSEC:
result = dns_qp_deletename(qpdb->nsec, &node->name, NULL, NULL);
case DNS_DBNAMESPACE_NSEC:
result = dns_qp_deletename(qpdb->nsec, &node->name,
node->nspace, NULL, NULL);
break;
}
if (result != ISC_R_SUCCESS) {
@ -1389,8 +1395,8 @@ find_coveringnsec(qpc_search_t *search, const dns_name_t *name,
/*
* Look for the node in the auxilary tree.
*/
result = dns_qp_lookup(search->qpdb->nsec, name, NULL, &iter, NULL,
(void **)&node, NULL);
result = dns_qp_lookup(search->qpdb->nsec, name, DNS_DBNAMESPACE_NSEC,
NULL, &iter, NULL, (void **)&node, NULL);
if (result != DNS_R_PARTIALMATCH) {
return ISC_R_NOTFOUND;
}
@ -1410,8 +1416,8 @@ find_coveringnsec(qpc_search_t *search, const dns_name_t *name,
* Lookup the predecessor in the main tree.
*/
node = NULL;
result = dns_qp_getname(search->qpdb->tree, predecessor, (void **)&node,
NULL);
result = dns_qp_getname(search->qpdb->tree, predecessor,
DNS_DBNAMESPACE_NORMAL, (void **)&node, NULL);
if (result != ISC_R_SUCCESS) {
return result;
}
@ -1518,8 +1524,8 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
/*
* Search down from the root of the tree.
*/
result = dns_qp_lookup(search.qpdb->tree, name, NULL, NULL,
&search.chain, (void **)&node, NULL);
result = dns_qp_lookup(search.qpdb->tree, name, DNS_DBNAMESPACE_NORMAL,
NULL, NULL, &search.chain, (void **)&node, NULL);
if (result != ISC_R_NOTFOUND && foundname != NULL) {
dns_name_copy(&node->name, foundname);
}
@ -1958,8 +1964,8 @@ qpcache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
/*
* Search down from the root of the tree.
*/
result = dns_qp_lookup(search.qpdb->tree, name, NULL, NULL,
&search.chain, (void **)&node, NULL);
result = dns_qp_lookup(search.qpdb->tree, name, DNS_DBNAMESPACE_NORMAL,
NULL, NULL, &search.chain, (void **)&node, NULL);
switch (result) {
case ISC_R_SUCCESS:
@ -2321,10 +2327,11 @@ reactivate_node(qpcache_t *qpdb, qpcnode_t *node,
}
static qpcnode_t *
new_qpcnode(qpcache_t *qpdb, const dns_name_t *name) {
new_qpcnode(qpcache_t *qpdb, const dns_name_t *name, dns_namespace_t nspace) {
qpcnode_t *newdata = isc_mem_get(qpdb->common.mctx, sizeof(*newdata));
*newdata = (qpcnode_t){
.name = DNS_NAME_INITEMPTY,
.nspace = nspace,
.references = ISC_REFCOUNT_INITIALIZER(1),
.locknum = isc_random_uniform(qpdb->buckets_count),
};
@ -2346,9 +2353,10 @@ qpcache_findnode(dns_db_t *db, const dns_name_t *name, bool create,
qpcnode_t *node = NULL;
isc_result_t result;
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
dns_namespace_t nspace = DNS_DBNAMESPACE_NORMAL;
TREE_RDLOCK(&qpdb->tree_lock, &tlocktype);
result = dns_qp_getname(qpdb->tree, name, (void **)&node, NULL);
result = dns_qp_getname(qpdb->tree, name, nspace, (void **)&node, NULL);
if (result != ISC_R_SUCCESS) {
if (!create) {
goto unlock;
@ -2357,9 +2365,10 @@ qpcache_findnode(dns_db_t *db, const dns_name_t *name, bool create,
* Try to upgrade the lock and if that fails unlock then relock.
*/
TREE_FORCEUPGRADE(&qpdb->tree_lock, &tlocktype);
result = dns_qp_getname(qpdb->tree, name, (void **)&node, NULL);
result = dns_qp_getname(qpdb->tree, name, nspace,
(void **)&node, NULL);
if (result != ISC_R_SUCCESS) {
node = new_qpcnode(qpdb, name);
node = new_qpcnode(qpdb, name, nspace);
result = dns_qp_insert(qpdb->tree, node, 0);
INSIST(result == ISC_R_SUCCESS);
qpcnode_unref(node);
@ -3007,7 +3016,7 @@ qpcache_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
*/
if (rdataset->type == dns_rdatatype_nsec) {
NODE_RDLOCK(nlock, &nlocktype);
if (qpnode->nsec != DNS_DB_NSEC_HAS_NSEC) {
if (!qpnode->havensec) {
newnsec = true;
}
NODE_UNLOCK(nlock, &nlocktype);
@ -3033,20 +3042,20 @@ qpcache_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
expire_ttl_headers(qpdb, qpnode->locknum, &nlocktype, &tlocktype,
now DNS__DB_FLARG_PASS);
if (newnsec && qpnode->nsec != DNS_DB_NSEC_HAS_NSEC) {
if (newnsec && !qpnode->havensec) {
qpcnode_t *nsecnode = NULL;
result = dns_qp_getname(qpdb->nsec, name, (void **)&nsecnode,
NULL);
result = dns_qp_getname(qpdb->nsec, name, DNS_DBNAMESPACE_NSEC,
(void **)&nsecnode, NULL);
if (result != ISC_R_SUCCESS) {
INSIST(nsecnode == NULL);
nsecnode = new_qpcnode(qpdb, name);
nsecnode->nsec = DNS_DB_NSEC_NSEC;
nsecnode = new_qpcnode(qpdb, name,
DNS_DBNAMESPACE_NSEC);
result = dns_qp_insert(qpdb->nsec, nsecnode, 0);
INSIST(result == ISC_R_SUCCESS);
qpcnode_detach(&nsecnode);
}
qpnode->nsec = DNS_DB_NSEC_HAS_NSEC;
qpnode->havensec = true;
}
result = add(qpdb, qpnode, name, newheader, options, addedrdataset, now,
@ -3418,7 +3427,8 @@ resume_iteration(qpc_dbit_t *qpdbiter, bool continuing) {
*/
if (continuing && qpdbiter->node != NULL) {
isc_result_t result;
result = dns_qp_lookup(qpdb->tree, qpdbiter->name, NULL,
result = dns_qp_lookup(qpdb->tree, qpdbiter->name,
DNS_DBNAMESPACE_NORMAL, NULL,
&qpdbiter->iter, NULL, NULL, NULL);
INSIST(result == ISC_R_SUCCESS);
}
@ -3546,8 +3556,9 @@ dbiterator_seek(dns_dbiterator_t *iterator,
dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
result = dns_qp_lookup(qpdb->tree, name, NULL, &qpdbiter->iter, NULL,
(void **)&qpdbiter->node, NULL);
result = dns_qp_lookup(qpdb->tree, name, DNS_DBNAMESPACE_NORMAL, NULL,
&qpdbiter->iter, NULL, (void **)&qpdbiter->node,
NULL);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
dns_name_copy(&qpdbiter->node->name, qpdbiter->name);

File diff suppressed because it is too large Load diff

View file

@ -1422,7 +1422,8 @@ add_nm(dns_rpz_zones_t *rpzs, dns_name_t *trig_name, const nmdata_t *new_data) {
dns_qp_t *qp = NULL;
dns_qpmulti_write(rpzs->table, &qp);
result = dns_qp_getname(qp, trig_name, (void **)&data, NULL);
result = dns_qp_getname(qp, trig_name, DNS_DBNAMESPACE_NORMAL,
(void **)&data, NULL);
if (result != ISC_R_SUCCESS) {
INSIST(data == NULL);
data = new_nmdata(rpzs->mctx, trig_name, new_data);
@ -2291,7 +2292,8 @@ del_name(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
trig_name = dns_fixedname_initname(&trig_namef);
name2data(rpz, rpz_type, src_name, trig_name, &del_data);
result = dns_qp_getname(qp, trig_name, (void **)&data, NULL);
result = dns_qp_getname(qp, trig_name, DNS_DBNAMESPACE_NORMAL,
(void **)&data, NULL);
if (result != ISC_R_SUCCESS) {
return;
}
@ -2314,7 +2316,8 @@ del_name(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
if (data->set.qname == 0 && data->set.ns == 0 &&
data->wild.qname == 0 && data->wild.ns == 0)
{
result = dns_qp_deletename(qp, trig_name, NULL, NULL);
result = dns_qp_deletename(qp, trig_name,
DNS_DBNAMESPACE_NORMAL, NULL, NULL);
if (result != ISC_R_SUCCESS) {
/*
* bin/tests/system/rpz/tests.sh looks for
@ -2516,8 +2519,8 @@ dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type,
dns_qpmulti_query(rpzs->table, &qpr);
dns_qpchain_init(&qpr, &chain);
result = dns_qp_lookup(&qpr, trig_name, NULL, NULL, &chain,
(void **)&data, NULL);
result = dns_qp_lookup(&qpr, trig_name, DNS_DBNAMESPACE_NORMAL, NULL,
NULL, &chain, (void **)&data, NULL);
switch (result) {
case ISC_R_SUCCESS:
INSIST(data != NULL);
@ -2667,7 +2670,7 @@ static size_t
qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) {
nmdata_t *data = pval;
return dns_qpkey_fromname(key, &data->name);
return dns_qpkey_fromname(key, &data->name, DNS_DBNAMESPACE_NORMAL);
}
static void

View file

@ -77,7 +77,7 @@ ztqpmakekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) {
dns_zone_t *zone = pval;
dns_name_t *name = dns_zone_getorigin(zone);
return dns_qpkey_fromname(key, name);
return dns_qpkey_fromname(key, name, DNS_DBNAMESPACE_NORMAL);
}
static void
@ -156,7 +156,8 @@ dns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone) {
REQUIRE(VALID_ZT(zt));
dns_qpmulti_write(zt->multi, &qp);
result = dns_qp_deletename(qp, dns_zone_getorigin(zone), NULL, NULL);
result = dns_qp_deletename(qp, dns_zone_getorigin(zone),
DNS_DBNAMESPACE_NORMAL, NULL, NULL);
dns_qp_compact(qp, DNS_QPGC_MAYBE);
dns_qpmulti_commit(zt->multi, &qp);
@ -179,10 +180,11 @@ dns_zt_find(dns_zt_t *zt, const dns_name_t *name, dns_ztfind_t options,
dns_qpmulti_query(zt->multi, &qpr);
if (exactopts == DNS_ZTFIND_EXACT) {
result = dns_qp_getname(&qpr, name, &pval, NULL);
result = dns_qp_getname(&qpr, name, DNS_DBNAMESPACE_NORMAL,
&pval, NULL);
} else {
result = dns_qp_lookup(&qpr, name, NULL, NULL, &chain, &pval,
NULL);
result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL,
NULL, &chain, &pval, NULL);
if (exactopts == DNS_ZTFIND_NOEXACT && result == ISC_R_SUCCESS)
{
/* get pval from the previous chain link */

View file

@ -66,7 +66,8 @@ static size_t
item_makekey(dns_qpkey_t key, void *ctx, void *pval, uint32_t ival) {
UNUSED(ctx);
assert(pval == &item[ival]);
return dns_qpkey_fromname(key, &item[ival].fixed.name);
return dns_qpkey_fromname(key, &item[ival].fixed.name,
DNS_DBNAMESPACE_NORMAL);
}
static void
@ -325,7 +326,8 @@ sqz_qp(void *qp) {
static isc_result_t
get_qp(void *qp, size_t count, void **pval) {
return dns_qp_getname(qp, &item[count].fixed.name, pval, NULL);
return dns_qp_getname(qp, &item[count].fixed.name,
DNS_DBNAMESPACE_NORMAL, pval, NULL);
}
static void *

View file

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

View file

@ -81,7 +81,7 @@ qpkey_from_smallname(dns_qpkey_t key, void *ctx, void *pval, uint32_t ival) {
UNUSED(ctx);
dns_name_t name = DNS_NAME_INITEMPTY;
name_from_smallname(&name, pval, ival);
return dns_qpkey_fromname(key, &name);
return dns_qpkey_fromname(key, &name, DNS_DBNAMESPACE_NORMAL);
}
static void
@ -228,7 +228,7 @@ main(int argc, char **argv) {
start = isc_time_monotonic();
for (i = 0; i < n; i++) {
name = dns_fixedname_name(&items[i]);
dns_qp_getname(qp, name, NULL, NULL);
dns_qp_getname(qp, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL);
}
stop = isc_time_monotonic();
@ -238,7 +238,8 @@ main(int argc, char **argv) {
start = isc_time_monotonic();
for (i = 0; i < n; i++) {
name = dns_fixedname_name(&items[i]);
dns_qp_lookup(qp, name, 0, NULL, NULL, NULL, NULL);
dns_qp_lookup(qp, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL,
NULL, NULL, NULL);
}
stop = isc_time_monotonic();
@ -263,7 +264,8 @@ main(int argc, char **argv) {
++search->ndata[1];
}
dns_qp_lookup(qp, search, 0, NULL, NULL, NULL, NULL);
dns_qp_lookup(qp, search, DNS_DBNAMESPACE_NORMAL, NULL, NULL,
NULL, NULL, NULL);
}
stop = isc_time_monotonic();

View file

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

File diff suppressed because it is too large Load diff

View file

@ -23,6 +23,7 @@
#include <isc/urcu.h>
#include <isc/util.h>
#include <dns/db.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/qp.h>
@ -55,7 +56,7 @@ qp_test_bittoascii(dns_qpshift_t bit) {
const char *
qp_test_keytoascii(dns_qpkey_t key, size_t len) {
for (size_t offset = 0; offset < len; offset++) {
for (size_t offset = 1; offset < len; offset++) {
key[offset] = qp_test_bittoascii(key[offset]);
}
key[len] = '\0';
@ -342,11 +343,16 @@ void
qp_test_printkey(const dns_qpkey_t key, size_t keylen) {
dns_fixedname_t fn;
dns_name_t *n = dns_fixedname_initname(&fn);
dns_namespace_t s;
char txt[DNS_NAME_FORMATSIZE];
dns_qpkey_toname(key, keylen, n);
dns_qpkey_toname(key, keylen, n, &s);
dns_name_format(n, txt, sizeof(txt));
printf("%s%s\n", txt, dns_name_isabsolute(n) ? "." : "");
printf("%s%s%s\n", txt,
s == DNS_DBNAMESPACE_NSEC3
? "NSEC3:"
: (s == DNS_DBNAMESPACE_NSEC ? "NSEC" : ""),
dns_name_isabsolute(n) ? "." : "");
}
/**********************************************************************/