Add dns_db_allrdatasets options

'DNS_DB_STALEOK' returns stale rdatasets as well as current rdatasets.

'DNS_DB_EXPIREDOK' returns expired rdatasets as well as current
rdatasets. This option is currently only set when DNS_DB_STALEOK is
also set.
This commit is contained in:
Mark Andrews 2022-11-16 11:40:33 +11:00
parent 7695c36a5d
commit 85048ddeee
4 changed files with 100 additions and 36 deletions

View file

@ -392,8 +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, 0, (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);
}

View file

@ -302,6 +302,9 @@ struct dns_dbonupdatelistener {
#define DNS_DB_NONSEC3 0x4
/*@}*/
#define DNS_DB_STALEOK 0x01
#define DNS_DB_EXPIREDOK 0x02
/*****
***** Methods
*****/
@ -1168,6 +1171,9 @@ dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
*
* \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

View file

@ -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);
@ -1707,8 +1712,8 @@ dumptostream(dns_dumpctx_t *dctx) {
result = dns_dbiterator_pause(dctx->dbiter);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = dns_db_allrdatasets(dctx->db, node, dctx->version, 0,
dctx->now, &rdsiter);
result = dns_db_allrdatasets(dctx->db, node, dctx->version,
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, 0, now, &rdsiter);
result = dns_db_allrdatasets(db, node, version, options, now, &rdsiter);
if (result != ISC_R_SUCCESS) {
goto failure;
}

View file

@ -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
@ -8858,7 +8864,17 @@ rdatasetiter_first(dns_rdatasetiter_t *iterator) {
for (header = rbtnode->data; header != NULL; header = top_next) {
top_next = header->next;
do {
if (header->serial <= serial && !IGNORE(header)) {
dns_ttl_t stale_ttl = header->rdh_ttl;
if (STALEOK(rbtiterator)) {
stale_ttl += STALE_TTL(header, rbtdb);
}
if (EXPIREDOK(rbtiterator)) {
if (!NONEXISTENT(header)) {
break;
}
header = header->down;
} else if (header->serial <= serial && !IGNORE(header))
{
/*
* Is this a "this rdataset doesn't exist"
* record? Or is it too old in the cache?
@ -8869,8 +8885,7 @@ rdatasetiter_first(dns_rdatasetiter_t *iterator) {
* queries for 0 TTL rdatasets to work.
*/
if (NONEXISTENT(header) ||
(now != 0 && now > header->rdh_ttl))
{
(now != 0 && now > stale_ttl)) {
header = NULL;
}
break;
@ -8906,6 +8921,7 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator) {
rbtdb_rdatatype_t type, negtype;
dns_rdatatype_t rdtype, covers;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
bool expiredok = EXPIREDOK(rbtiterator);
header = rbtiterator->current;
if (header == NULL) {
@ -8930,37 +8946,69 @@ 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?
*
* Note: unlike everywhere else, we
* check for now > header->ttl instead
* of ">=". This allows ANY and RRSIG
* queries for 0 TTL rdatasets to work.
*/
if (NONEXISTENT(header) ||
(now != 0 && now > header->rdh_ttl))
{
header = NULL;
}
break;
} else {
header = header->down;
}
} while (header != NULL);
if (header != NULL) {
break;
header = header->down != NULL ? header->down : top_next;
} else {
header = top_next;
}
for (; header != NULL; header = top_next) {
top_next = header->next;
do {
dns_ttl_t stale_ttl = header->rdh_ttl;
if (STALEOK(rbtiterator)) {
stale_ttl += STALE_TTL(header, rbtdb);
}
if (expiredok) {
if (!NONEXISTENT(header)) {
break;
}
header = header->down;
} else if (header->serial <= serial && !IGNORE(header))
{
/*
* Is this a "this rdataset doesn't
* exist" record?
*
* Note: unlike everywhere else, we
* check for now > header->ttl instead
* of ">=". This allows ANY and RRSIG
* queries for 0 TTL rdatasets to work.
*/
if (NONEXISTENT(header) ||
(now != 0 && now > stale_ttl)) {
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;
}
}