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

modify dns_qp_findname_ancestor() to return found name

add a 'foundname' parameter to dns_qp_findname_ancestor(),
and use it to set the found name in dns_nametree.

this required adding a dns_qpkey_toname() function; that was
done by moving qp_test_keytoname() from the test library to qp.c.
added some more test cases and fixed bugs with the handling of
relative and empty names.
This commit is contained in:
Evan Hunt 2023-09-06 23:57:42 -07:00
parent 06ac957c4f
commit 29cf7dceb7
12 changed files with 214 additions and 117 deletions

View File

@ -56,7 +56,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
/* 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);
qp_test_keytoname(key, keylen, nameout); dns_qpkey_toname(key, keylen, nameout);
assert(dns_name_equal(namein, nameout)); assert(dns_name_equal(namein, nameout));

View File

@ -168,7 +168,7 @@ dns_fwdtable_find(dns_fwdtable_t *fwdtable, const dns_name_t *name,
REQUIRE(VALID_FWDTABLE(fwdtable)); REQUIRE(VALID_FWDTABLE(fwdtable));
dns_qpmulti_query(fwdtable->table, &qpr); dns_qpmulti_query(fwdtable->table, &qpr);
result = dns_qp_findname_ancestor(&qpr, name, 0, &pval, NULL); result = dns_qp_findname_ancestor(&qpr, name, 0, NULL, &pval, NULL);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
dns_forwarders_t *fwdrs = pval; dns_forwarders_t *fwdrs = pval;
*forwardersp = fwdrs; *forwardersp = fwdrs;

View File

@ -431,6 +431,17 @@ dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name);
* \li the length of the key * \li the length of the key
*/ */
void
dns_qpkey_toname(const dns_qpkey_t key, size_t keylen, dns_name_t *name);
/*%<
* Convert a trie lookup key back into a DNS name.
*
* Requires:
* \li `name` is a pointer to a valid `dns_name_t`
* \li `name->buffer` is not NULL
* \li `name->offsets` is not NULL
*/
isc_result_t isc_result_t
dns_qp_getkey(dns_qpreadable_t qpr, const dns_qpkey_t search_key, dns_qp_getkey(dns_qpreadable_t qpr, const dns_qpkey_t search_key,
size_t search_keylen, void **pval_r, uint32_t *ival_r); size_t search_keylen, void **pval_r, uint32_t *ival_r);
@ -469,7 +480,8 @@ dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, void **pval_r,
isc_result_t isc_result_t
dns_qp_findname_ancestor(dns_qpreadable_t qpr, const dns_name_t *name, dns_qp_findname_ancestor(dns_qpreadable_t qpr, const dns_name_t *name,
dns_qpfind_t options, void **pval_r, uint32_t *ival_r); dns_qpfind_t options, dns_name_t *foundname,
void **pval_r, uint32_t *ival_r);
/*%< /*%<
* Find a leaf in a qp-trie that is an ancestor domain of, or equal to, the * Find a leaf in a qp-trie that is an ancestor domain of, or equal to, the
* given DNS name. * given DNS name.
@ -477,12 +489,16 @@ dns_qp_findname_ancestor(dns_qpreadable_t qpr, const dns_name_t *name,
* If the DNS_QPFIND_NOEXACT option is set, find the closest ancestor * If the DNS_QPFIND_NOEXACT option is set, find the closest ancestor
* domain that is not equal to the search name. * domain that is not equal to the search name.
* *
* If 'foundname' is not NULL, it is updated to contain the name found.
*
* 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.
* *
* Requires: * Requires:
* \li `qpr` is a pointer to a readable qp-trie * \li `qpr` is a pointer to a readable qp-trie
* \li `name` is a pointer to a valid `dns_name_t` * \li `name` is a pointer to a valid `dns_name_t`
* \li `foundname` is a pointer to a valid `dns_name_t` with
* buffer and offset space available, or is NULL.
* *
* Returns: * Returns:
* \li ISC_R_SUCCESS if an exact match was found * \li ISC_R_SUCCESS if an exact match was found

View File

@ -518,7 +518,7 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
REQUIRE(foundname != NULL); REQUIRE(foundname != NULL);
dns_qpmulti_query(keytable->table, &qpr); dns_qpmulti_query(keytable->table, &qpr);
result = dns_qp_findname_ancestor(&qpr, name, 0, &pval, NULL); result = dns_qp_findname_ancestor(&qpr, name, 0, NULL, &pval, NULL);
keynode = pval; keynode = pval;
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
@ -547,7 +547,7 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name,
REQUIRE(wantdnssecp != NULL); REQUIRE(wantdnssecp != NULL);
dns_qpmulti_query(keytable->table, &qpr); dns_qpmulti_query(keytable->table, &qpr);
result = dns_qp_findname_ancestor(&qpr, name, 0, &pval, NULL); result = dns_qp_findname_ancestor(&qpr, name, 0, NULL, &pval, NULL);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
keynode = pval; keynode = pval;
if (foundname != NULL) { if (foundname != NULL) {

View File

@ -289,12 +289,9 @@ dns_nametree_covered(dns_nametree_t *nametree, const dns_name_t *name,
REQUIRE(VALID_NAMETREE(nametree)); REQUIRE(VALID_NAMETREE(nametree));
dns_qpmulti_query(nametree->table, &qpr); dns_qpmulti_query(nametree->table, &qpr);
result = dns_qp_findname_ancestor(&qpr, name, 0, (void **)&node, NULL); result = dns_qp_findname_ancestor(&qpr, name, 0, found, (void **)&node,
NULL);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
if (found != NULL) {
dns_name_copy(node->name, found);
}
switch (nametree->type) { switch (nametree->type) {
case DNS_NAMETREE_BOOL: case DNS_NAMETREE_BOOL:
ret = node->set; ret = node->set;

View File

@ -413,7 +413,7 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
RWLOCK(&ntatable->rwlock, isc_rwlocktype_read); RWLOCK(&ntatable->rwlock, isc_rwlocktype_read);
dns_qpmulti_query(ntatable->table, &qpr); dns_qpmulti_query(ntatable->table, &qpr);
result = dns_qp_findname_ancestor(&qpr, name, 0, &pval, NULL); result = dns_qp_findname_ancestor(&qpr, name, 0, NULL, &pval, NULL);
nta = pval; nta = pval;
switch (result) { switch (result) {

View File

@ -176,7 +176,7 @@ initialize_bits_for_byte(void) {
qp_shift_t letter = byte - 'A'; qp_shift_t letter = byte - 'A';
qp_shift_t bit = after_esc + skip_punct + letter; qp_shift_t bit = after_esc + skip_punct + letter;
dns_qp_bits_for_byte[byte] = bit; dns_qp_bits_for_byte[byte] = bit;
/* to simplify reverse conversion in the tests */ /* to simplify reverse conversion */
bit_two++; bit_two++;
} else { } else {
/* non-hostname characters need to be escaped */ /* non-hostname characters need to be escaped */
@ -216,7 +216,11 @@ dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name) {
dns_fixedname_t fixed; dns_fixedname_t fixed;
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC)); REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
REQUIRE(name->labels > 0);
if (name->labels == 0) {
key[0] = SHIFT_NOBYTE;
return (0);
}
if (name->offsets == NULL) { if (name->offsets == NULL) {
dns_name_t *clone = dns_fixedname_initname(&fixed); dns_name_t *clone = dns_fixedname_initname(&fixed);
@ -245,6 +249,85 @@ dns_qpkey_fromname(dns_qpkey_t key, const dns_name_t *name) {
return (len); return (len);
} }
void
dns_qpkey_toname(const dns_qpkey_t key, size_t keylen, dns_name_t *name) {
size_t locs[DNS_NAME_MAXLABELS];
size_t loc = 0, opos = 0;
size_t offset;
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
REQUIRE(name->buffer != NULL);
REQUIRE(name->offsets != NULL);
if (keylen == 0) {
dns_name_reset(name);
return;
}
isc_buffer_clear(name->buffer);
/* Scan the key looking for label boundaries */
for (offset = 0; offset <= keylen; offset++) {
INSIST(key[offset] >= SHIFT_NOBYTE &&
key[offset] < SHIFT_OFFSET);
INSIST(loc < DNS_NAME_MAXLABELS);
if (qpkey_bit(key, keylen, offset) == SHIFT_NOBYTE) {
if (qpkey_bit(key, keylen, offset + 1) == SHIFT_NOBYTE)
{
locs[loc] = offset + 1;
goto scanned;
}
locs[loc++] = offset + 1;
} else if (offset == 0) {
/* This happens for a relative name */
locs[loc++] = offset;
}
}
UNREACHABLE();
scanned:
/*
* In the key the labels are encoded in reverse order, so
* we step backward through the label boundaries, then forward
* through the labels, to create the DNS wire format data.
*/
name->labels = loc;
while (loc-- > 0) {
uint8_t len = 0, *lenp = NULL;
/* Add a length byte to the name data and set an offset */
lenp = isc_buffer_used(name->buffer);
isc_buffer_putuint8(name->buffer, 0);
name->offsets[opos++] = name->length++;
/* Convert from escaped byte ranges to ASCII */
for (offset = locs[loc]; offset < locs[loc + 1] - 1; offset++) {
uint8_t bit = qpkey_bit(key, keylen, offset);
uint8_t byte = dns_qp_byte_for_bit[bit];
if (qp_common_character(byte)) {
isc_buffer_putuint8(name->buffer, byte);
} else {
byte += key[++offset] - SHIFT_BITMAP;
isc_buffer_putuint8(name->buffer, byte);
}
len++;
}
name->length += len;
*lenp = len;
}
/* Add a root label for absolute names */
if (key[0] == SHIFT_NOBYTE) {
name->attributes.absolute = true;
isc_buffer_putuint8(name->buffer, 0);
name->offsets[opos++] = name->length++;
name->labels++;
}
name->ndata = isc_buffer_base(name->buffer);
}
/* /*
* Sentinel value for equal keys * Sentinel value for equal keys
*/ */
@ -1811,8 +1894,8 @@ dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, void **pval_r,
isc_result_t isc_result_t
dns_qp_findname_ancestor(dns_qpreadable_t qpr, const dns_name_t *name, dns_qp_findname_ancestor(dns_qpreadable_t qpr, const dns_name_t *name,
dns_qpfind_t options, void **pval_r, dns_qpfind_t options, dns_name_t *foundname,
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;
@ -1827,6 +1910,7 @@ dns_qp_findname_ancestor(dns_qpreadable_t qpr, const dns_name_t *name,
} label[DNS_NAME_MAXLABELS]; } label[DNS_NAME_MAXLABELS];
REQUIRE(QP_VALID(qp)); 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);
if ((options & DNS_QPFIND_NOEXACT) != 0) { if ((options & DNS_QPFIND_NOEXACT) != 0) {
@ -1888,6 +1972,9 @@ dns_qp_findname_ancestor(dns_qpreadable_t qpr, const dns_name_t *name,
if (offset == QPKEY_EQUAL || offset == foundlen) { if (offset == QPKEY_EQUAL || offset == foundlen) {
SET_IF_NOT_NULL(pval_r, leaf_pval(n)); SET_IF_NOT_NULL(pval_r, leaf_pval(n));
SET_IF_NOT_NULL(ival_r, leaf_ival(n)); SET_IF_NOT_NULL(ival_r, leaf_ival(n));
if (foundname != NULL) {
dns_qpkey_toname(found, foundlen, foundname);
}
if (offset == QPKEY_EQUAL) { if (offset == QPKEY_EQUAL) {
return (result); return (result);
} else { } else {
@ -1899,6 +1986,10 @@ dns_qp_findname_ancestor(dns_qpreadable_t qpr, const dns_name_t *name,
n = ref_ptr(qp, label[labels].ref); n = ref_ptr(qp, label[labels].ref);
SET_IF_NOT_NULL(pval_r, leaf_pval(n)); SET_IF_NOT_NULL(pval_r, leaf_pval(n));
SET_IF_NOT_NULL(ival_r, leaf_ival(n)); SET_IF_NOT_NULL(ival_r, leaf_ival(n));
if (foundname != NULL) {
foundlen = leaf_qpkey(qp, n, found);
dns_qpkey_toname(found, foundlen, foundname);
}
return (DNS_R_PARTIALMATCH); return (DNS_R_PARTIALMATCH);
} }
} }

View File

@ -181,9 +181,10 @@ dns_zt_find(dns_zt_t *zt, const dns_name_t *name, dns_ztfind_t options,
result = dns_qp_getname(&qpr, name, &pval, NULL); result = dns_qp_getname(&qpr, name, &pval, NULL);
} else if (exactopts == DNS_ZTFIND_NOEXACT) { } else if (exactopts == DNS_ZTFIND_NOEXACT) {
result = dns_qp_findname_ancestor( result = dns_qp_findname_ancestor(
&qpr, name, DNS_QPFIND_NOEXACT, &pval, NULL); &qpr, name, DNS_QPFIND_NOEXACT, NULL, &pval, NULL);
} else { } else {
result = dns_qp_findname_ancestor(&qpr, name, 0, &pval, NULL); result = dns_qp_findname_ancestor(&qpr, name, 0, NULL, &pval,
NULL);
} }
dns_qpread_destroy(zt->multi, &qpr); dns_qpread_destroy(zt->multi, &qpr);

View File

@ -254,7 +254,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_findname_ancestor(qp, name, 0, NULL, NULL); dns_qp_findname_ancestor(qp, name, 0, NULL, NULL, NULL);
} }
stop = isc_time_monotonic(); stop = isc_time_monotonic();
@ -280,7 +280,7 @@ main(int argc, char **argv) {
++search->ndata[1]; ++search->ndata[1];
} }
dns_qp_findname_ancestor(qp, search, 0, NULL, NULL); dns_qp_findname_ancestor(qp, search, 0, NULL, NULL, NULL);
} }
stop = isc_time_monotonic(); stop = isc_time_monotonic();

View File

@ -44,6 +44,11 @@ ISC_RUN_TEST_IMPL(qpkey_name) {
uint8_t key[512]; uint8_t key[512];
size_t len; size_t len;
} testcases[] = { } testcases[] = {
{
.namestr = "",
.key = { 0x02 },
.len = 0,
},
{ {
.namestr = ".", .namestr = ".",
.key = { 0x02, 0x02 }, .key = { 0x02, 0x02 },
@ -54,6 +59,16 @@ ISC_RUN_TEST_IMPL(qpkey_name) {
.key = { 0x03, 0x03, 0x02, 0x02 }, .key = { 0x03, 0x03, 0x02, 0x02 },
.len = 3, .len = 3,
}, },
{
.namestr = "com",
.key = { 0x16, 0x22, 0x20, 0x02 },
.len = 4,
},
{
.namestr = "com.",
.key = { 0x02, 0x16, 0x22, 0x20, 0x02 },
.len = 5,
},
{ {
.namestr = "example.com.", .namestr = "example.com.",
.key = { 0x02, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14, .key = { 0x02, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14,
@ -80,15 +95,21 @@ 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;
dns_test_namefromstring(testcases[i].namestr, &fn1); in = dns_fixedname_initname(&fn1);
in = dns_fixedname_name(&fn1); if (testcases[i].len != 0) {
dns_test_namefromstring(testcases[i].namestr, &fn1);
}
len = dns_qpkey_fromname(key, in); len = dns_qpkey_fromname(key, in);
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);
qp_test_keytoname(key, len, out); dns_qpkey_toname(key, len, out);
assert_true(dns_name_equal(in, out)); assert_true(dns_name_equal(in, out));
} }
} }
@ -258,19 +279,47 @@ static void
check_partialmatch(dns_qp_t *qp, struct check_partialmatch check[]) { check_partialmatch(dns_qp_t *qp, struct check_partialmatch check[]) {
for (int i = 0; check[i].query != NULL; i++) { for (int i = 0; check[i].query != NULL; i++) {
isc_result_t result; isc_result_t result;
dns_fixedname_t fixed; dns_fixedname_t fn1, fn2;
dns_name_t *name = dns_fixedname_name(&fixed); dns_name_t *name = dns_fixedname_initname(&fn1);
dns_name_t *foundname = dns_fixedname_initname(&fn2);
void *pval = NULL; void *pval = NULL;
dns_test_namefromstring(check[i].query, &fn1);
result = dns_qp_findname_ancestor(qp, name, check[i].options,
foundname, &pval, NULL);
#if 0 #if 0
fprintf(stderr, "%s %u %s %s\n", check[i].query, fprintf(stderr, "%s (flags %u) %s (expected %s) "
check[i].options, isc_result_totext(check[i].result), "value \"%s\" (expected \"%s\")\n",
check[i].query, check[i].options,
isc_result_totext(result),
isc_result_totext(check[i].result), (char *)pval,
check[i].found); check[i].found);
#endif #endif
dns_test_namefromstring(check[i].query, &fixed);
result = dns_qp_findname_ancestor(qp, name, check[i].options,
&pval, NULL);
assert_int_equal(result, check[i].result); assert_int_equal(result, check[i].result);
if (result == ISC_R_SUCCESS) {
assert_true(dns_name_equal(name, foundname));
} else if (result == DNS_R_PARTIALMATCH) {
/*
* there are cases where we may have passed a
* query name that was relative to the zone apex,
* and gotten back an absolute name from the
* partial match. it's also possible for an
* absolute query to get a partial match on a
* node that had an empty name. in these cases,
* sanity checking the relations between name
* and foundname can trigger an assertion, so
* let's just skip them.
*/
if (dns_name_isabsolute(name) ==
dns_name_isabsolute(foundname))
{
assert_false(dns_name_equal(name, foundname));
assert_true(
dns_name_issubdomain(name, foundname));
}
}
if (check[i].found == NULL) { if (check[i].found == NULL) {
assert_null(pval); assert_null(pval);
} else { } else {
@ -291,6 +340,7 @@ insert_str(dns_qp_t *qp, const char *str) {
ISC_RUN_TEST_IMPL(partialmatch) { ISC_RUN_TEST_IMPL(partialmatch) {
isc_result_t result; isc_result_t result;
dns_qp_t *qp = NULL; dns_qp_t *qp = NULL;
int i = 0;
dns_qp_create(mctx, &string_methods, NULL, &qp); dns_qp_create(mctx, &string_methods, NULL, &qp);
@ -302,7 +352,10 @@ ISC_RUN_TEST_IMPL(partialmatch) {
"fooo.bar.", "web.foo.bar.", ".", "", "fooo.bar.", "web.foo.bar.", ".", "",
}; };
int i = 0; /*
* omit the root node for now, otherwise we'll get "partial match"
* results when we want "not found".
*/
while (insert[i][0] != '.') { while (insert[i][0] != '.') {
insert_str(qp, insert[i++]); insert_str(qp, insert[i++]);
} }
@ -340,21 +393,41 @@ ISC_RUN_TEST_IMPL(partialmatch) {
{ "bar.", 0, DNS_R_PARTIALMATCH, "." }, { "bar.", 0, DNS_R_PARTIALMATCH, "." },
{ "foo.bar.", 0, ISC_R_SUCCESS, "foo.bar." }, { "foo.bar.", 0, ISC_R_SUCCESS, "foo.bar." },
{ "foo.bar.", DNS_QPFIND_NOEXACT, DNS_R_PARTIALMATCH, "." }, { "foo.bar.", DNS_QPFIND_NOEXACT, DNS_R_PARTIALMATCH, "." },
{ "bar", 0, ISC_R_NOTFOUND, NULL },
{ "bar", DNS_QPFIND_NOEXACT, DNS_R_PARTIALMATCH, "." },
{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
}; };
check_partialmatch(qp, check2); check_partialmatch(qp, check2);
/* 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?
*/
dns_qpkey_t rootkey = { SHIFT_NOBYTE }; dns_qpkey_t rootkey = { 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[]){
{ "bar", 0, ISC_R_NOTFOUND, NULL },
{ "bar", DNS_QPFIND_NOEXACT, ISC_R_NOTFOUND, NULL },
{ "bar.", 0, ISC_R_NOTFOUND, NULL },
{ "bar.", DNS_QPFIND_NOEXACT, ISC_R_NOTFOUND, NULL },
{ NULL, 0, 0, NULL },
});
/* what if there's a root node with an empty key? */
INSIST(insert[i][0] == '\0'); INSIST(insert[i][0] == '\0');
insert_str(qp, insert[i++]); insert_str(qp, insert[i++]);
check_partialmatch(qp, (struct check_partialmatch[]){ check_partialmatch(
{ "bar", 0, DNS_R_PARTIALMATCH, "" }, qp,
{ "bar.", 0, DNS_R_PARTIALMATCH, "" }, (struct check_partialmatch[]){
{ NULL, 0, 0, NULL }, { "bar", 0, DNS_R_PARTIALMATCH, "" },
}); { "bar", DNS_QPFIND_NOEXACT, DNS_R_PARTIALMATCH, "" },
{ "bar.", 0, DNS_R_PARTIALMATCH, "" },
{ "bar.", DNS_QPFIND_NOEXACT, DNS_R_PARTIALMATCH, "" },
{ NULL, 0, 0, NULL },
});
dns_qp_destroy(&qp); dns_qp_destroy(&qp);
} }

View File

@ -29,13 +29,6 @@ qp_test_bittoascii(uint8_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);
/*
* Convert a trie lookup key back into a DNS name. Unlike the previous
* functions, this is a complete inverse of dns_qpkey_fromname().
*/
void
qp_test_keytoname(const dns_qpkey_t key, size_t len, dns_name_t *name);
/* /*
* The maximum height of the trie * The maximum height of the trie
*/ */

View File

@ -61,80 +61,6 @@ qp_test_keytoascii(dns_qpkey_t key, size_t len) {
return ((const char *)key); return ((const char *)key);
} }
void
qp_test_keytoname(const dns_qpkey_t key, size_t keylen, dns_name_t *name) {
size_t locs[DNS_NAME_MAXLABELS];
size_t loc = 0, opos = 0;
size_t offset;
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
REQUIRE(name->buffer != NULL);
REQUIRE(name->offsets != NULL);
isc_buffer_clear(name->buffer);
/* Scan the key looking for label boundaries */
for (offset = 0; offset <= keylen; offset++) {
INSIST(key[offset] >= SHIFT_NOBYTE &&
key[offset] < SHIFT_OFFSET);
INSIST(loc < DNS_NAME_MAXLABELS);
if (qpkey_bit(key, keylen, offset) == SHIFT_NOBYTE) {
if (qpkey_bit(key, keylen, offset + 1) == SHIFT_NOBYTE)
{
locs[loc] = offset + 1;
goto scanned;
}
locs[loc++] = offset + 1;
} else if (offset == 0) {
/* This happens for a relative name */
locs[loc++] = offset;
}
}
UNREACHABLE();
scanned:
/*
* In the key the labels are encoded in reverse order, so
* we step backward through the label boundaries, then forward
* through the labels, to create the DNS wire format data.
*/
name->labels = loc;
while (loc-- > 0) {
uint8_t len = 0, *lenp = NULL;
/* Add a length byte to the name data and set an offset */
lenp = isc_buffer_used(name->buffer);
isc_buffer_putuint8(name->buffer, 0);
name->offsets[opos++] = name->length++;
/* Convert from escaped byte ranges to ASCII */
for (offset = locs[loc]; offset < locs[loc + 1] - 1; offset++) {
uint8_t bit = qpkey_bit(key, keylen, offset);
uint8_t byte = dns_qp_byte_for_bit[bit];
if (qp_common_character(byte)) {
isc_buffer_putuint8(name->buffer, byte);
} else {
byte += key[++offset] - SHIFT_BITMAP;
isc_buffer_putuint8(name->buffer, byte);
}
len++;
}
name->length += len;
*lenp = len;
}
/* Add a root label for absolute names */
if (key[0] == SHIFT_NOBYTE) {
name->attributes.absolute = true;
isc_buffer_putuint8(name->buffer, 0);
name->length++;
name->labels++;
}
name->ndata = isc_buffer_base(name->buffer);
}
/*********************************************************************** /***********************************************************************
* *
* trie properties * trie properties