From: Matthijs Mekking Date: Tue, 9 Dec 2025 11:37:20 +0000 (+0100) Subject: Implement dns_dbiterator_seek3 X-Git-Tag: v9.21.17~41^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=41159e9062b40495aca6178da54d60bbd2f34378;p=thirdparty%2Fbind9.git 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. --- diff --git a/lib/dns/dbiterator.c b/lib/dns/dbiterator.c index 626e4c45438..4732d706c8c 100644 --- a/lib/dns/dbiterator.c +++ b/lib/dns/dbiterator.c @@ -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)); diff --git a/lib/dns/include/dns/dbiterator.h b/lib/dns/include/dns/dbiterator.h index 0371401cb23..c3f92cd687e 100644 --- a/lib/dns/include/dns/dbiterator.h +++ b/lib/dns/include/dns/dbiterator.h @@ -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 diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index 50218a3e25e..94a7c8aed5f 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -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; diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index fadcd0996d9..9cd5c77c62b 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -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; diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index 22bd0ee2104..aa6e58305c7 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -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; diff --git a/tests/dns/dbiterator_test.c b/tests/dns/dbiterator_test.c index a4593bf945e..c15e460827d 100644 --- a/tests/dns/dbiterator_test.c +++ b/tests/dns/dbiterator_test.c @@ -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); }