]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add dns_db_allrdatasets options
authorMark Andrews <marka@isc.org>
Wed, 16 Nov 2022 00:40:33 +0000 (11:40 +1100)
committerMark Andrews <marka@isc.org>
Wed, 7 Dec 2022 22:20:02 +0000 (22:20 +0000)
'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.

lib/dns/cache.c
lib/dns/include/dns/db.h
lib/dns/masterdump.c
lib/dns/rbtdb.c

index 966485b50e75f3035974f33a715589a28a6df320..7aedbb6fb56156697661a90d7670cd05305bf95b 100644 (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);
        }
index 9673f967f07578018daca73317c2a524477415e8..b15279c9eef34b554d84830f816bc4814453dd63 100644 (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
index 2fdda1ce8df431f669240187eec54714c4ce230a..0c6aeb18d6a90969fb921d3209caf9abadf11a1b 100644 (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;
        }
index aae127b6fbcbad70d62c1460de67f2cfdd1d843e..388e754037664ce9a27ed611c6c03c84777b2ae4 100644 (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;
-                                       }
+               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;
-                               } else {
-                                       header = header->down;
                                }
-                       } while (header != NULL);
-                       if (header != NULL) {
+                               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;
                }
        }