Implement dns_dbiterator_seek3

This is a new seek function for dbiterator that is meant to find an
NSEC3 node in a zone database. The difference with dns_dbiterator_seek
is that if the node does not exist, this seek function will point the
iterator to the next NSEC3 name.
This commit is contained in:
Matthijs Mekking 2025-12-09 12:37:20 +01:00
parent 5e704bbb59
commit 41159e9062
6 changed files with 137 additions and 18 deletions

View file

@ -58,6 +58,14 @@ dns__dbiterator_seek(dns_dbiterator_t *iterator,
return iterator->methods->seek(iterator, name DNS__DB_FLARG_PASS);
}
isc_result_t
dns__dbiterator_seek3(dns_dbiterator_t *iterator,
const dns_name_t *name DNS__DB_FLARG) {
REQUIRE(DNS_DBITERATOR_VALID(iterator));
return iterator->methods->seek3(iterator, name DNS__DB_FLARG_PASS);
}
isc_result_t
dns__dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG) {
REQUIRE(DNS_DBITERATOR_VALID(iterator));

View file

@ -70,6 +70,8 @@ typedef struct dns_dbiteratormethods {
isc_result_t (*last)(dns_dbiterator_t *iterator DNS__DB_FLARG);
isc_result_t (*seek)(dns_dbiterator_t *iterator,
const dns_name_t *name DNS__DB_FLARG);
isc_result_t (*seek3)(dns_dbiterator_t *iterator,
const dns_name_t *name DNS__DB_FLARG);
isc_result_t (*prev)(dns_dbiterator_t *iterator DNS__DB_FLARG);
isc_result_t (*next)(dns_dbiterator_t *iterator DNS__DB_FLARG);
isc_result_t (*current)(dns_dbiterator_t *iterator,
@ -189,6 +191,30 @@ dns__dbiterator_seek(dns_dbiterator_t *iterator,
*\li Other results are possible, depending on the DB implementation.
*/
#define dns_dbiterator_seek3(iterator, name) \
dns__dbiterator_seek3(iterator, name DNS__DB_FILELINE)
isc_result_t
dns__dbiterator_seek3(dns_dbiterator_t *iterator,
const dns_name_t *name DNS__DB_FLARG);
/*%<
* Move the node cursor to the node with NSEC3 name 'name'.
* If not found, the iterator is set to the next name.
*
* Requires:
*\li 'iterator' is a valid iterator.
*
*\li 'name' is a valid name.
*
* Returns:
*\li #ISC_R_SUCCESS
*\li #ISC_R_NOTFOUND
*\li #ISC_R_NOMORE There are no NSEC3 nodes in the database.
*\li #ISC_R_NOTIMPLEMENTED
* (this function is only implemented for NSEC3 only iterators)
*
*\li Other results are possible, depending on the DB implementation.
*/
#define dns_dbiterator_prev(iterator) \
dns__dbiterator_prev(iterator DNS__DB_FILELINE)
isc_result_t

View file

@ -374,6 +374,9 @@ static isc_result_t
dbiterator_seek(dns_dbiterator_t *iterator,
const dns_name_t *name DNS__DB_FLARG);
static isc_result_t
dbiterator_seek3(dns_dbiterator_t *iterator,
const dns_name_t *name DNS__DB_FLARG);
static isc_result_t
dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG);
static isc_result_t
dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG);
@ -386,9 +389,10 @@ static isc_result_t
dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
static dns_dbiteratormethods_t dbiterator_methods = {
dbiterator_destroy, dbiterator_first, dbiterator_last,
dbiterator_seek, dbiterator_prev, dbiterator_next,
dbiterator_current, dbiterator_pause, dbiterator_origin
dbiterator_destroy, dbiterator_first, dbiterator_last,
dbiterator_seek, dbiterator_seek3, dbiterator_prev,
dbiterator_next, dbiterator_current, dbiterator_pause,
dbiterator_origin
};
/*
@ -3634,6 +3638,12 @@ dbiterator_seek(dns_dbiterator_t *iterator,
return result;
}
static isc_result_t
dbiterator_seek3(dns_dbiterator_t *iterator ISC_ATTR_UNUSED,
const dns_name_t *name ISC_ATTR_UNUSED DNS__DB_FLARG) {
return ISC_R_NOTIMPLEMENTED;
}
static isc_result_t
dbiterator_prev(dns_dbiterator_t *iterator ISC_ATTR_UNUSED DNS__DB_FLARG) {
return ISC_R_NOTIMPLEMENTED;

View file

@ -345,6 +345,9 @@ static isc_result_t
dbiterator_seek(dns_dbiterator_t *iterator,
const dns_name_t *name DNS__DB_FLARG);
static isc_result_t
dbiterator_seek3(dns_dbiterator_t *iterator,
const dns_name_t *name DNS__DB_FLARG);
static isc_result_t
dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG);
static isc_result_t
dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG);
@ -357,9 +360,10 @@ static isc_result_t
dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
static dns_dbiteratormethods_t dbiterator_methods = {
dbiterator_destroy, dbiterator_first, dbiterator_last,
dbiterator_seek, dbiterator_prev, dbiterator_next,
dbiterator_current, dbiterator_pause, dbiterator_origin
dbiterator_destroy, dbiterator_first, dbiterator_last,
dbiterator_seek, dbiterator_seek3, dbiterator_prev,
dbiterator_next, dbiterator_current, dbiterator_pause,
dbiterator_origin
};
typedef struct qpdb_dbiterator {
@ -4357,6 +4361,53 @@ dbiterator_seek(dns_dbiterator_t *iterator,
return result;
}
static isc_result_t
dbiterator_seek3(dns_dbiterator_t *iterator,
const dns_name_t *name DNS__DB_FLARG) {
isc_result_t result;
qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
if (qpdbiter->result != ISC_R_SUCCESS &&
qpdbiter->result != ISC_R_NOTFOUND &&
qpdbiter->result != DNS_R_PARTIALMATCH &&
qpdbiter->result != ISC_R_NOMORE)
{
return qpdbiter->result;
}
if (qpdbiter->nsec3mode != nsec3only) {
return ISC_R_NOTIMPLEMENTED;
}
dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
result = dns_qp_lookup(qpdbiter->snap, name, DNS_DBNAMESPACE_NSEC3,
&qpdbiter->iter, NULL, (void **)&qpdbiter->node,
NULL);
switch (result) {
case ISC_R_SUCCESS:
reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
break;
case DNS_R_PARTIALMATCH:
/* dbiterator_next() will dereference the node */
reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
result = dbiterator_next(iterator);
if (result == ISC_R_NOMORE) {
result = dbiterator_first(iterator);
}
break;
case ISC_R_NOTFOUND:
default:
break;
}
qpdbiter->result = result;
return qpdbiter->result;
}
static isc_result_t
dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG) {
isc_result_t result;

View file

@ -210,6 +210,9 @@ static isc_result_t
dbiterator_seek(dns_dbiterator_t *iterator,
const dns_name_t *name DNS__DB_FLARG);
static isc_result_t
dbiterator_seek3(dns_dbiterator_t *iterator,
const dns_name_t *name DNS__DB_FLARG);
static isc_result_t
dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG);
static isc_result_t
dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG);
@ -222,9 +225,10 @@ static isc_result_t
dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
static dns_dbiteratormethods_t dbiterator_methods = {
dbiterator_destroy, dbiterator_first, dbiterator_last,
dbiterator_seek, dbiterator_prev, dbiterator_next,
dbiterator_current, dbiterator_pause, dbiterator_origin
dbiterator_destroy, dbiterator_first, dbiterator_last,
dbiterator_seek, dbiterator_seek3, dbiterator_prev,
dbiterator_next, dbiterator_current, dbiterator_pause,
dbiterator_origin
};
/*
@ -1149,6 +1153,12 @@ dbiterator_seek(dns_dbiterator_t *iterator,
return ISC_R_NOTFOUND;
}
static isc_result_t
dbiterator_seek3(dns_dbiterator_t *iterator ISC_ATTR_UNUSED,
const dns_name_t *name ISC_ATTR_UNUSED DNS__DB_FLARG) {
return ISC_R_NOTIMPLEMENTED;
}
static isc_result_t
dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG) {
sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;

View file

@ -182,10 +182,10 @@ ISC_RUN_TEST_IMPL(reverse_nsec3) {
/* seek: walk database starting at a particular node */
static void
test_seek_node(const char *filename, int flags, int nodes) {
isc_result_t result;
test_seek_node(const char *filename, bool nsec3, int flags, int nodes) {
isc_result_t result, result3;
dns_db_t *db = NULL;
dns_dbiterator_t *iter = NULL;
dns_dbiterator_t *iter = NULL, *iter3 = NULL;
dns_dbnode_t *node = NULL;
dns_name_t *name, *seekname;
dns_fixedname_t f1, f2;
@ -200,6 +200,9 @@ test_seek_node(const char *filename, int flags, int nodes) {
result = dns_db_createiterator(db, flags, &iter);
assert_int_equal(result, ISC_R_SUCCESS);
result3 = dns_db_createiterator(db, flags, &iter3);
assert_int_equal(result3, ISC_R_SUCCESS);
result = make_name("c." TEST_ORIGIN, seekname);
assert_int_equal(result, ISC_R_SUCCESS);
@ -207,6 +210,14 @@ test_seek_node(const char *filename, int flags, int nodes) {
if (flags == DNS_DB_NSEC3ONLY) {
/* "c" isn't in the NSEC3 tree but the origin node is */
assert_int_equal(result, DNS_R_PARTIALMATCH);
/* NSEC3 iterator */
result3 = dns_dbiterator_seek3(iter3, seekname);
if (nsec3) {
assert_int_equal(result3, ISC_R_SUCCESS);
} else {
assert_int_equal(result3, ISC_R_NOMORE);
}
} else {
assert_int_equal(result, ISC_R_SUCCESS);
}
@ -244,26 +255,29 @@ test_seek_node(const char *filename, int flags, int nodes) {
assert_int_equal(i, nodes);
dns_dbiterator_destroy(&iter);
dns_dbiterator_destroy(&iter3);
dns_db_detach(&db);
}
ISC_RUN_TEST_IMPL(seek_node) {
UNUSED(state);
test_seek_node(TESTS_DIR "/testdata/dbiterator/zone1.data", 0, 9);
test_seek_node(TESTS_DIR "/testdata/dbiterator/zone1.data",
test_seek_node(TESTS_DIR "/testdata/dbiterator/zone1.data", false, 0,
9);
test_seek_node(TESTS_DIR "/testdata/dbiterator/zone1.data", false,
DNS_DB_NONSEC3, 9);
test_seek_node(TESTS_DIR "/testdata/dbiterator/zone1.data",
test_seek_node(TESTS_DIR "/testdata/dbiterator/zone1.data", false,
DNS_DB_NSEC3ONLY, 0);
}
ISC_RUN_TEST_IMPL(seek_node_nsec3) {
UNUSED(state);
test_seek_node(TESTS_DIR "/testdata/dbiterator/zone2.data", 0, 29);
test_seek_node(TESTS_DIR "/testdata/dbiterator/zone2.data",
test_seek_node(TESTS_DIR "/testdata/dbiterator/zone2.data", true, 0,
29);
test_seek_node(TESTS_DIR "/testdata/dbiterator/zone2.data", true,
DNS_DB_NONSEC3, 9);
test_seek_node(TESTS_DIR "/testdata/dbiterator/zone2.data",
test_seek_node(TESTS_DIR "/testdata/dbiterator/zone2.data", true,
DNS_DB_NSEC3ONLY, 0);
}