diff --git a/CHANGES b/CHANGES index 0517c46551..053f841bb0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +6042. [bug] ANY responses could sometimes have the wrong TTL. + [GL #3613] + 6041. [func] Set the RLIMIT_NOFILE to rlim_max returned from getrlimit() instead of trying to guess the maximum allowed value. [GL #3676] diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index 64779725c6..e208ffd08b 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -228,7 +228,7 @@ dumpnode(dns_name_t *name, dns_dbnode_t *node) { return; } - result = dns_db_allrdatasets(gdb, node, gversion, 0, &iter); + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &iter); check_result(result, "dns_db_allrdatasets"); dns_rdataset_init(&rds); @@ -1193,7 +1193,7 @@ signname(dns_dbnode_t *node, dns_name_t *name) { dns_diff_init(mctx, &del); dns_diff_init(mctx, &add); rdsiter = NULL; - result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { @@ -1267,7 +1267,7 @@ active_node(dns_dbnode_t *node) { bool found; dns_rdataset_init(&rdataset); - result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { @@ -1313,7 +1313,8 @@ active_node(dns_dbnode_t *node) { /* * Delete RRSIGs for types that no longer exist. */ - result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2); + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, + &rdsiter2); check_result(result, "dns_db_allrdatasets()"); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; @@ -1515,7 +1516,7 @@ cleannode(dns_db_t *db, dns_dbversion_t *dbversion, dns_dbnode_t *node) { } dns_rdataset_init(&set); - result = dns_db_allrdatasets(db, node, dbversion, 0, &rdsiter); + result = dns_db_allrdatasets(db, node, dbversion, 0, 0, &rdsiter); check_result(result, "dns_db_allrdatasets"); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { @@ -1837,7 +1838,7 @@ remove_records(dns_dbnode_t *node, dns_rdatatype_t which, bool checknsec) { /* * Delete any records of the given type at the apex. */ - result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) @@ -1880,7 +1881,7 @@ remove_sigs(dns_dbnode_t *node, bool delegation, dns_rdatatype_t which) { dns_rdataset_t rdataset; dns_rdataset_init(&rdataset); - result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) @@ -1944,7 +1945,8 @@ nsecify(void) { { result = dns_dbiterator_current(dbiter, &node, name); check_dns_dbiterator_current(result); - result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, + &rdsiter); check_result(result, "dns_db_allrdatasets()"); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; @@ -2355,7 +2357,8 @@ cleanup_zone(void) { { result = dns_dbiterator_current(dbiter, &node, name); check_dns_dbiterator_current(result); - result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, + &rdsiter); check_result(result, "dns_db_allrdatasets()"); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; diff --git a/bin/tests/system/dyndb/driver/db.c b/bin/tests/system/dyndb/driver/db.c index a4073a7453..f7b052fbba 100644 --- a/bin/tests/system/dyndb/driver/db.c +++ b/bin/tests/system/dyndb/driver/db.c @@ -302,13 +302,14 @@ findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, static isc_result_t allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, - isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) { + unsigned int options, isc_stdtime_t now, + dns_rdatasetiter_t **iteratorp) { sampledb_t *sampledb = (sampledb_t *)db; REQUIRE(VALID_SAMPLEDB(sampledb)); - return (dns_db_allrdatasets(sampledb->rbtdb, node, version, now, - iteratorp)); + return (dns_db_allrdatasets(sampledb->rbtdb, node, version, options, + now, iteratorp)); } static isc_result_t diff --git a/bin/tests/system/resolver/ns4/tld1.db b/bin/tests/system/resolver/ns4/tld1.db index 4bcfcf5f02..03d79088fe 100644 --- a/bin/tests/system/resolver/ns4/tld1.db +++ b/bin/tests/system/resolver/ns4/tld1.db @@ -30,3 +30,6 @@ edns-version.tld. NS ns.edns-version.tld. ns.edns-version.tld. A 10.53.0.7 cname CNAME ns7 ns7 A 10.53.0.7 +mixedttl 10 A 10.0.0.1 +mixedttl 15 TXT a TXT record +mixedttl 20 AAAA 2001:db8::1 diff --git a/bin/tests/system/resolver/ns4/tld2.db b/bin/tests/system/resolver/ns4/tld2.db index 45dc6943a5..c3a96d9f4f 100644 --- a/bin/tests/system/resolver/ns4/tld2.db +++ b/bin/tests/system/resolver/ns4/tld2.db @@ -30,3 +30,6 @@ edns-version.tld. NS ns.edns-version.tld. ns.edns-version.tld. A 10.53.0.7 cname CNAME ns7 ns7 A 10.53.0.7 +mixedttl 10 A 10.0.0.1 +mixedttl 15 TXT a TXT record +mixedttl 20 AAAA 2001:db8::1 diff --git a/bin/tests/system/resolver/tests.sh b/bin/tests/system/resolver/tests.sh index 8c0a509497..33a72383f3 100755 --- a/bin/tests/system/resolver/tests.sh +++ b/bin/tests/system/resolver/tests.sh @@ -860,5 +860,24 @@ grep "status: NOERROR" dig.out.ns9.${n} > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) +n=$((n+1)) +echo_i "check expired TTLs with qtype * (${n})" +ret=0 +dig_with_opts +tcp @10.53.0.5 mixedttl.tld any > dig.out.1.${n} || ret=1 +ttl1=$(awk '$1 == "mixedttl.tld." && $4 == "A" { print $2 + 1 }' dig.out.1.${n}) +# sleep TTL + 1 so that record has expired +sleep "${ttl1:-0}" +dig_with_opts +tcp @10.53.0.5 mixedttl.tld any > dig.out.2.${n} || ret=1 +# check preconditions +grep "ANSWER: 3," dig.out.1.${n} > /dev/null || ret=1 +lines=$(awk '$1 == "mixedttl.tld." && $2 > 30 { print }' dig.out.1.${n} | wc -l) +test ${lines:-1} -ne 0 && ret=1 +# check behaviour (there may be 1 answer on very slow machines) +grep "ANSWER: [12]," dig.out.2.${n} > /dev/null || ret=1 +lines=$(awk '$1 == "mixedttl.tld." && $2 > 30 { print }' dig.out.2.${n} | wc -l) +test ${lines:-1} -ne 0 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 diff --git a/lib/dns/cache.c b/lib/dns/cache.c index d905cdd888..7aedbb6fb5 100644 --- a/lib/dns/cache.c +++ b/lib/dns/cache.c @@ -392,7 +392,8 @@ clearnode(dns_db_t *db, dns_dbnode_t *node) { isc_result_t result; dns_rdatasetiter_t *iter = NULL; - result = dns_db_allrdatasets(db, node, NULL, (isc_stdtime_t)0, &iter); + result = dns_db_allrdatasets(db, node, NULL, DNS_DB_STALEOK, + (isc_stdtime_t)0, &iter); if (result != ISC_R_SUCCESS) { return (result); } diff --git a/lib/dns/catz.c b/lib/dns/catz.c index ec048dfd8f..fd24410594 100644 --- a/lib/dns/catz.c +++ b/lib/dns/catz.c @@ -2246,7 +2246,7 @@ dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs) { continue; } - result = dns_db_allrdatasets(db, node, oldzone->dbversion, 0, + result = dns_db_allrdatasets(db, node, oldzone->dbversion, 0, 0, &rdsiter); if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, diff --git a/lib/dns/client.c b/lib/dns/client.c index 44a0471c82..f160f7650a 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -717,7 +717,7 @@ client_resfind(resctx_t *rctx, dns_fetchevent_t *event) { int n = 0; dns_rdatasetiter_t *rdsiter = NULL; - tresult = dns_db_allrdatasets(db, node, NULL, 0, + tresult = dns_db_allrdatasets(db, node, NULL, 0, 0, &rdsiter); if (tresult != ISC_R_SUCCESS) { result = tresult; diff --git a/lib/dns/db.c b/lib/dns/db.c index 9620efb165..e0a46c9856 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -677,7 +677,8 @@ dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_result_t dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, - isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) { + unsigned int options, isc_stdtime_t now, + dns_rdatasetiter_t **iteratorp) { /* * Make '*iteratorp' an rdataset iteratator for all rdatasets at * 'node' in version 'version' of 'db'. @@ -686,7 +687,8 @@ dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, REQUIRE(DNS_DB_VALID(db)); REQUIRE(iteratorp != NULL && *iteratorp == NULL); - return ((db->methods->allrdatasets)(db, node, version, now, iteratorp)); + return ((db->methods->allrdatasets)(db, node, version, options, now, + iteratorp)); } isc_result_t diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index f1ca17973b..b15279c9ee 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -118,8 +118,8 @@ typedef struct dns_dbmethods { dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); isc_result_t (*allrdatasets)(dns_db_t *db, dns_dbnode_t *node, - dns_dbversion_t *version, - isc_stdtime_t now, + dns_dbversion_t *version, + unsigned int options, isc_stdtime_t now, dns_rdatasetiter_t **iteratorp); isc_result_t (*addrdataset)(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_stdtime_t now, @@ -302,6 +302,9 @@ struct dns_dbonupdatelistener { #define DNS_DB_NONSEC3 0x4 /*@}*/ +#define DNS_DB_STALEOK 0x01 +#define DNS_DB_EXPIREDOK 0x02 + /***** ***** Methods *****/ @@ -1156,7 +1159,8 @@ dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_result_t dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, - isc_stdtime_t now, dns_rdatasetiter_t **iteratorp); + unsigned int options, isc_stdtime_t now, + dns_rdatasetiter_t **iteratorp); /*%< * Make '*iteratorp' an rdataset iterator for all rdatasets at 'node' in * version 'version' of 'db'. @@ -1165,6 +1169,12 @@ dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, * * \li If 'version' is NULL, then the current version will be used. * + * \li 'options' controls which rdatasets are selected when interating over + * the node. + * 'DNS_DB_STALEOK' return stale rdatasets as well as current rdatasets. + * 'DNS_DB_EXPIREDOK' return expired rdatasets as well as current + * rdatasets. + * * \li The 'now' field is ignored if 'db' is a zone database. If 'db' is a * cache database, an rdataset will not be found unless it expires after * 'now'. Any ANY query will not match unless at least one rdataset at diff --git a/lib/dns/include/dns/rdatasetiter.h b/lib/dns/include/dns/rdatasetiter.h index 0d610eee74..8611d9900c 100644 --- a/lib/dns/include/dns/rdatasetiter.h +++ b/lib/dns/include/dns/rdatasetiter.h @@ -93,6 +93,7 @@ struct dns_rdatasetiter { dns_dbnode_t *node; dns_dbversion_t *version; isc_stdtime_t now; + unsigned int options; }; void diff --git a/lib/dns/journal.c b/lib/dns/journal.c index f36db188e3..fa3fdadb44 100644 --- a/lib/dns/journal.c +++ b/lib/dns/journal.c @@ -2125,7 +2125,7 @@ get_name_diff(dns_db_t *db, dns_dbversion_t *ver, isc_stdtime_t now, return (result); } - result = dns_db_allrdatasets(db, node, ver, now, &rdsiter); + result = dns_db_allrdatasets(db, node, ver, 0, now, &rdsiter); if (result != ISC_R_SUCCESS) { goto cleanup_node; } diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index 2604772d21..0c6aeb18d6 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -1669,6 +1669,11 @@ dumptostream(dns_dumpctx_t *dctx) { char *bufmem; dns_name_t *name; dns_fixedname_t fixname; + unsigned int options = DNS_DB_STALEOK; + + if ((dctx->tctx.style.flags & DNS_STYLEFLAG_EXPIRED) != 0) { + options |= DNS_DB_EXPIREDOK; + } bufmem = isc_mem_get(dctx->mctx, initial_buffer_length); @@ -1708,7 +1713,7 @@ dumptostream(dns_dumpctx_t *dctx) { RUNTIME_CHECK(result == ISC_R_SUCCESS); result = dns_db_allrdatasets(dctx->db, node, dctx->version, - dctx->now, &rdsiter); + options, dctx->now, &rdsiter); if (result != ISC_R_SUCCESS) { dns_db_detachnode(dctx->db, &node); goto cleanup; @@ -1916,6 +1921,11 @@ dns_master_dumpnodetostream(isc_mem_t *mctx, dns_db_t *db, isc_stdtime_t now; dns_totext_ctx_t ctx; dns_rdatasetiter_t *rdsiter = NULL; + unsigned int options = DNS_DB_STALEOK; + + if ((style->flags & DNS_STYLEFLAG_EXPIRED) != 0) { + options |= DNS_DB_EXPIREDOK; + } result = totext_ctx_init(style, NULL, &ctx); if (result != ISC_R_SUCCESS) { @@ -1929,7 +1939,7 @@ dns_master_dumpnodetostream(isc_mem_t *mctx, dns_db_t *db, isc_buffer_init(&buffer, bufmem, initial_buffer_length); - result = dns_db_allrdatasets(db, node, version, now, &rdsiter); + result = dns_db_allrdatasets(db, node, version, options, now, &rdsiter); if (result != ISC_R_SUCCESS) { goto failure; } diff --git a/lib/dns/nsec.c b/lib/dns/nsec.c index 94f2b26b79..35ee4db006 100644 --- a/lib/dns/nsec.c +++ b/lib/dns/nsec.c @@ -128,7 +128,7 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node, max_type = dns_rdatatype_nsec; dns_rdataset_init(&rdataset); rdsiter = NULL; - result = dns_db_allrdatasets(db, node, version, 0, &rdsiter); + result = dns_db_allrdatasets(db, node, version, 0, 0, &rdsiter); if (result != ISC_R_SUCCESS) { return (result); } diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c index 55fc52a766..a25e5e3941 100644 --- a/lib/dns/nsec3.c +++ b/lib/dns/nsec3.c @@ -118,7 +118,7 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node, } dns_rdataset_init(&rdataset); rdsiter = NULL; - result = dns_db_allrdatasets(db, node, version, 0, &rdsiter); + result = dns_db_allrdatasets(db, node, version, 0, 0, &rdsiter); if (result != ISC_R_SUCCESS) { return (result); } @@ -365,7 +365,7 @@ name_exists(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, return (result); } - result = dns_db_allrdatasets(db, node, version, (isc_stdtime_t)0, + result = dns_db_allrdatasets(db, node, version, 0, (isc_stdtime_t)0, &iter); if (result != ISC_R_SUCCESS) { goto cleanup_node; diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 15732ca87b..f765518f11 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -444,6 +444,12 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t; #define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */ +#define EXPIREDOK(rbtiterator) \ + (((rbtiterator)->common.options & DNS_DB_EXPIREDOK) != 0) + +#define STALEOK(rbtiterator) \ + (((rbtiterator)->common.options & DNS_DB_STALEOK) != 0) + /*% * Number of buckets for cache DB entries (locks, LRU lists, TTL heaps). * There is a tradeoff issue about configuring this value: if this is too @@ -6057,7 +6063,8 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, static isc_result_t allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, - isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) { + unsigned int options, isc_stdtime_t now, + dns_rdatasetiter_t **iteratorp) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node; rbtdb_version_t *rbtversion = version; @@ -6089,6 +6096,7 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, iterator->common.db = db; iterator->common.node = node; iterator->common.version = (dns_dbversion_t *)rbtversion; + iterator->common.options = options; iterator->common.now = now; isc_refcount_increment(&rbtnode->references); @@ -8832,6 +8840,35 @@ rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { *iteratorp = NULL; } +static bool +iterator_active(dns_rbtdb_t *rbtdb, rbtdb_rdatasetiter_t *rbtiterator, + rdatasetheader_t *header) { + dns_ttl_t stale_ttl = header->rdh_ttl + STALE_TTL(header, rbtdb); + + /* + * Is this a "this rdataset doesn't exist" record? + */ + if (NONEXISTENT(header)) { + return (false); + } + + /* + * If this is a zone or this header still active then return it. + */ + if (!IS_CACHE(rbtdb) || ACTIVE(header, rbtiterator->common.now)) { + return (true); + } + + /* + * If we are not returning stale records or the rdataset is + * too old don't return it. + */ + if (!STALEOK(rbtiterator) || (rbtiterator->common.now > stale_ttl)) { + return (false); + } + return (true); +} + static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator) { rbtdb_rdatasetiter_t *rbtiterator = (rbtdb_rdatasetiter_t *)iterator; @@ -8839,24 +8876,24 @@ rdatasetiter_first(dns_rdatasetiter_t *iterator) { dns_rbtnode_t *rbtnode = rbtiterator->common.node; rbtdb_version_t *rbtversion = rbtiterator->common.version; rdatasetheader_t *header, *top_next; - rbtdb_serial_t serial = 1; + rbtdb_serial_t serial = IS_CACHE(rbtdb) ? 1 : rbtversion->serial; isc_rwlocktype_t nlocktype = isc_rwlocktype_none; - if (!IS_CACHE(rbtdb)) { - serial = rbtversion->serial; - } - NODE_RDLOCK(&rbtdb->node_locks[rbtnode->locknum].lock, &nlocktype); for (header = rbtnode->data; header != NULL; header = top_next) { top_next = header->next; do { - if (header->serial <= serial && !IGNORE(header)) { - /* - * Is this a "this rdataset doesn't exist" - * record? - */ - if (NONEXISTENT(header)) { + if (EXPIREDOK(rbtiterator)) { + if (!NONEXISTENT(header)) { + break; + } + header = header->down; + } else if (header->serial <= serial && !IGNORE(header)) + { + if (!iterator_active(rbtdb, rbtiterator, + header)) + { header = NULL; } break; @@ -8887,20 +8924,17 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator) { dns_rbtnode_t *rbtnode = rbtiterator->common.node; rbtdb_version_t *rbtversion = rbtiterator->common.version; rdatasetheader_t *header, *top_next; + rbtdb_serial_t serial = IS_CACHE(rbtdb) ? 1 : rbtversion->serial; rbtdb_rdatatype_t type, negtype; dns_rdatatype_t rdtype, covers; - rbtdb_serial_t serial = 1; isc_rwlocktype_t nlocktype = isc_rwlocktype_none; + bool expiredok = EXPIREDOK(rbtiterator); header = rbtiterator->current; if (header == NULL) { return (ISC_R_NOMORE); } - if (!IS_CACHE(rbtdb)) { - serial = rbtversion->serial; - } - NODE_RDLOCK(&rbtdb->node_locks[rbtnode->locknum].lock, &nlocktype); type = header->type; @@ -8911,30 +8945,57 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator) { } else { negtype = RBTDB_RDATATYPE_VALUE(0, rdtype); } - for (header = header->next; header != NULL; header = top_next) { - top_next = header->next; + + /* + * Find the start of the header chain for the next type + * by walking back up the list. + */ + top_next = header->next; + while (top_next != NULL && + (top_next->type == type || top_next->type == negtype)) + { + top_next = top_next->next; + } + if (expiredok) { /* - * If not walking back up the down list. + * Keep walking down the list if possible or + * start the next type. */ - if (header->type != type && header->type != negtype) { - do { - if (header->serial <= serial && !IGNORE(header)) - { - /* - * Is this a "this rdataset doesn't - * exist" record? - */ - if (NONEXISTENT(header)) { - header = NULL; - } + header = header->down != NULL ? header->down : top_next; + } else { + header = top_next; + } + for (; header != NULL; header = top_next) { + top_next = header->next; + do { + if (expiredok) { + if (!NONEXISTENT(header)) { break; - } else { - header = header->down; } - } while (header != NULL); - if (header != NULL) { + header = header->down; + } else if (header->serial <= serial && !IGNORE(header)) + { + if (!iterator_active(rbtdb, rbtiterator, + header)) + { + header = NULL; + } break; + } else { + header = header->down; } + } while (header != NULL); + if (header != NULL) { + break; + } + /* + * Find the start of the header chain for the next type + * by walking back up the list. + */ + while (top_next != NULL && + (top_next->type == type || top_next->type == negtype)) + { + top_next = top_next->next; } } diff --git a/lib/dns/rootns.c b/lib/dns/rootns.c index f171a056f7..d776a78c86 100644 --- a/lib/dns/rootns.c +++ b/lib/dns/rootns.c @@ -176,7 +176,7 @@ check_hints(dns_db_t *db) { if (result != ISC_R_SUCCESS) { goto cleanup; } - result = dns_db_allrdatasets(db, node, NULL, now, &rdsiter); + result = dns_db_allrdatasets(db, node, NULL, 0, now, &rdsiter); if (result != ISC_R_SUCCESS) { goto cleanup; } diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index 3815a59de8..efe04b79e3 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -1755,7 +1755,7 @@ update_nodes(dns_rpz_zone_t *rpz, isc_ht_t *newnodes) { RUNTIME_CHECK(result == ISC_R_SUCCESS); result = dns_db_allrdatasets(rpz->updb, node, rpz->updbversion, - 0, &rdsiter); + 0, 0, &rdsiter); if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER, ISC_LOG_ERROR, diff --git a/lib/dns/rriterator.c b/lib/dns/rriterator.c index 7c6aec0cf9..93548bce4d 100644 --- a/lib/dns/rriterator.c +++ b/lib/dns/rriterator.c @@ -84,7 +84,7 @@ dns_rriterator_first(dns_rriterator_t *it) { return (it->result); } - it->result = dns_db_allrdatasets(it->db, it->node, it->ver, + it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 0, it->now, &it->rdatasetit); if (it->result != ISC_R_SUCCESS) { return (it->result); @@ -138,7 +138,7 @@ dns_rriterator_nextrrset(dns_rriterator_t *it) { if (it->result != ISC_R_SUCCESS) { return (it->result); } - it->result = dns_db_allrdatasets(it->db, it->node, it->ver, + it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 0, it->now, &it->rdatasetit); if (it->result != ISC_R_SUCCESS) { return (it->result); diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c index c31d278bec..65701a0647 100644 --- a/lib/dns/sdb.c +++ b/lib/dns/sdb.c @@ -1166,7 +1166,8 @@ findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, static isc_result_t allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, - isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) { + unsigned int options, isc_stdtime_t now, + dns_rdatasetiter_t **iteratorp) { sdb_rdatasetiter_t *iterator; REQUIRE(version == NULL || version == &dummy); @@ -1182,6 +1183,7 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, iterator->common.node = NULL; attachnode(db, node, &iterator->common.node); iterator->common.version = version; + iterator->common.options = options; iterator->common.now = now; *iteratorp = (dns_rdatasetiter_t *)iterator; diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index 8cc7eb5433..fbe4b60244 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -1009,7 +1009,8 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, static isc_result_t allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, - isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) { + unsigned int options, isc_stdtime_t now, + dns_rdatasetiter_t **iteratorp) { dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; sdlz_rdatasetiter_t *iterator; @@ -1029,6 +1030,7 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, iterator->common.node = NULL; attachnode(db, node, &iterator->common.node); iterator->common.version = version; + iterator->common.options = options; iterator->common.now = now; *iteratorp = (dns_rdatasetiter_t *)iterator; diff --git a/lib/dns/update.c b/lib/dns/update.c index 8420860fdf..079045c7ef 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -364,7 +364,7 @@ foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, } iter = NULL; - result = dns_db_allrdatasets(db, node, ver, (isc_stdtime_t)0, &iter); + result = dns_db_allrdatasets(db, node, ver, 0, (isc_stdtime_t)0, &iter); if (result != ISC_R_SUCCESS) { goto cleanup_node; } @@ -1396,7 +1396,7 @@ add_exposed_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, } iter = NULL; - result = dns_db_allrdatasets(db, node, ver, (isc_stdtime_t)0, &iter); + result = dns_db_allrdatasets(db, node, ver, 0, (isc_stdtime_t)0, &iter); if (result != ISC_R_SUCCESS) { goto cleanup_node; } diff --git a/lib/dns/zone.c b/lib/dns/zone.c index bab33f390d..34e0ee58f8 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -3279,7 +3279,7 @@ zone_check_dup(dns_zone_t *zone, dns_db_t *db) { continue; } - result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit); + result = dns_db_allrdatasets(db, node, NULL, 0, 0, &rdsit); if (result != ISC_R_SUCCESS) { continue; } @@ -7668,7 +7668,7 @@ next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname, /* * Is this node empty? */ - CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit)); + CHECK(dns_db_allrdatasets(db, node, version, 0, 0, &rdsit)); result = dns_rdatasetiter_first(rdsit); dns_db_detachnode(db, &node); dns_rdatasetiter_destroy(&rdsit); @@ -7791,7 +7791,7 @@ check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node, REQUIRE(is_bottom_of_zone != NULL); - result = dns_db_allrdatasets(db, node, version, 0, &iterator); + result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator); if (result != ISC_R_SUCCESS) { if (result == ISC_R_NOTFOUND) { result = ISC_R_SUCCESS; @@ -7848,7 +7848,7 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name, unsigned char data[1024]; bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds; - result = dns_db_allrdatasets(db, node, version, 0, &iterator); + result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator); if (result != ISC_R_SUCCESS) { if (result == ISC_R_NOTFOUND) { result = ISC_R_SUCCESS; @@ -8801,7 +8801,8 @@ zone_nsec3chain(dns_zone_t *zone) { /* * Check to see if this is a bottom of zone node. */ - result = dns_db_allrdatasets(db, node, version, 0, &iterator); + result = dns_db_allrdatasets(db, node, version, 0, 0, + &iterator); if (result == ISC_R_NOTFOUND) { /* Empty node? */ goto next_addnode; @@ -9064,7 +9065,8 @@ zone_nsec3chain(dns_zone_t *zone) { /* * Check to see if this is a bottom of zone node. */ - result = dns_db_allrdatasets(db, node, version, 0, &iterator); + result = dns_db_allrdatasets(db, node, version, 0, 0, + &iterator); if (result == ISC_R_NOTFOUND) { /* Empty node? */ goto next_removenode; @@ -9185,7 +9187,8 @@ skip_removals: bool rebuild_nsec = false, rebuild_nsec3 = false; result = dns_db_getoriginnode(db, &node); RUNTIME_CHECK(result == ISC_R_SUCCESS); - result = dns_db_allrdatasets(db, node, version, 0, &iterator); + result = dns_db_allrdatasets(db, node, version, 0, 0, + &iterator); if (result != ISC_R_SUCCESS) { dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:dns_db_allrdatasets -> %s", @@ -9486,7 +9489,7 @@ del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(name, namebuf, sizeof(namebuf)); - result = dns_db_allrdatasets(db, node, version, 0, &iterator); + result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator); if (result != ISC_R_SUCCESS) { if (result == ISC_R_NOTFOUND) { result = ISC_R_SUCCESS; @@ -17275,7 +17278,7 @@ copy_non_dnssec_records(dns_db_t *db, dns_db_t *version, dns_db_t *rawdb, goto cleanup; } - result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit); + result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, 0, &rdsit); if (result != ISC_R_SUCCESS) { goto cleanup; } diff --git a/lib/dns/zoneverify.c b/lib/dns/zoneverify.c index 997f121df5..bf2b7cc68e 100644 --- a/lib/dns/zoneverify.c +++ b/lib/dns/zoneverify.c @@ -307,7 +307,7 @@ check_no_rrsig(const vctx_t *vctx, const dns_rdataset_t *rdataset, isc_result_t result; dns_rdataset_init(&sigrdataset); - result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, &rdsiter); + result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, 0, &rdsiter); if (result != ISC_R_SUCCESS) { zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s", isc_result_totext(result)); @@ -815,7 +815,7 @@ verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name, isc_result_t result; dns_rdataset_init(&sigrdataset); - result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, &rdsiter); + result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, 0, &rdsiter); if (result != ISC_R_SUCCESS) { zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s", isc_result_totext(result)); @@ -919,7 +919,7 @@ verifynode(vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node, REQUIRE(vresult != NULL || (nsecset == NULL && nsec3paramset == NULL)); - result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, &rdsiter); + result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, 0, &rdsiter); if (result != ISC_R_SUCCESS) { zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s", isc_result_totext(result)); @@ -1011,7 +1011,7 @@ is_empty(const vctx_t *vctx, dns_dbnode_t *node) { dns_rdatasetiter_t *rdsiter = NULL; isc_result_t result; - result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, &rdsiter); + result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, 0, &rdsiter); if (result != ISC_R_SUCCESS) { zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s", isc_result_totext(result)); diff --git a/lib/ns/query.c b/lib/ns/query.c index 0c3ee43e1a..6580bd8c7a 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -3209,7 +3209,7 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype, dns_rdatasetiter_t *rdsiter; rdsiter = NULL; - result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0, + result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0, 0, &rdsiter); if (result != ISC_R_SUCCESS) { rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, @@ -7829,7 +7829,7 @@ query_respond_any(query_ctx_t *qctx) { CALL_HOOK(NS_QUERY_RESPOND_ANY_BEGIN, qctx); - result = dns_db_allrdatasets(qctx->db, qctx->node, qctx->version, 0, + result = dns_db_allrdatasets(qctx->db, qctx->node, qctx->version, 0, 0, &rdsiter); if (result != ISC_R_SUCCESS) { CCTRACE(ISC_LOG_ERROR, "query_respond_any: allrdatasets " diff --git a/lib/ns/update.c b/lib/ns/update.c index 11b3ef156d..b15bfc4f86 100644 --- a/lib/ns/update.c +++ b/lib/ns/update.c @@ -606,7 +606,7 @@ foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, } iter = NULL; - result = dns_db_allrdatasets(db, node, ver, (isc_stdtime_t)0, &iter); + result = dns_db_allrdatasets(db, node, ver, 0, (isc_stdtime_t)0, &iter); if (result != ISC_R_SUCCESS) { goto cleanup_node; } diff --git a/tests/dns/dbversion_test.c b/tests/dns/dbversion_test.c index c315516fa6..8c62436901 100644 --- a/tests/dns/dbversion_test.c +++ b/tests/dns/dbversion_test.c @@ -195,10 +195,10 @@ ISC_RUN_TEST_IMPL(allrdatasets) { res = dns_db_findnode(db1, dns_rootname, false, &node); assert_int_equal(res, ISC_R_SUCCESS); - res = dns_db_allrdatasets(db1, node, v1, 0, &iterator); + res = dns_db_allrdatasets(db1, node, v1, 0, 0, &iterator); assert_int_equal(res, ISC_R_SUCCESS); - check_assertion(dns_db_allrdatasets(db1, node, v2, 0, &iterator)); + check_assertion(dns_db_allrdatasets(db1, node, v2, 0, 0, &iterator)); dns_rdatasetiter_destroy(&iterator); assert_null(iterator);