]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix the incoming transfers' "Needs Refresh" state in stats channel
authorAram Sargsyan <aram@isc.org>
Tue, 19 Sep 2023 09:38:35 +0000 (09:38 +0000)
committerAram Sargsyan <aram@isc.org>
Fri, 22 Sep 2023 11:47:26 +0000 (11:47 +0000)
The "Needs Refresh" flag is exposed in two places in the statistics
channel: first - there is a state called "Needs Refresh", when the
process hasn't started yet, but the zone needs a refresh, and second
- there there is a field called "Additional Refresh Queued", when the
process is ongoing, but another refresh is queued for the same zone.

The DNS_ZONEFLG_NEEDREFRESH flag, however, is set only when there is
an ongoing zone transfer and a new notify is received. That is, the
flag is not set for the first case above.

In order to fix the issue, use the DNS_ZONEFLG_NEEDREFRESH flag only
when the zone transfer is running, otherwise, decide whether a zone
needs a refresh using its refresh and expire times.

bin/named/statschannel.c
doc/arm/reference.rst
lib/dns/zone.c

index 2ba5614790c9f3e9a80ce34b188d38d7c6759ee6..f44eddce7139869e1fdeb9e81a131b6da7ddbb1e 100644 (file)
@@ -1564,7 +1564,8 @@ xfrin_xmlrender(dns_zone_t *zone, void *arg) {
 
        TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "refreshqueued"));
        TRY0(xmlTextWriterWriteString(
-               writer, ISC_XMLCHAR(needs_refresh ? "Yes" : "No")));
+               writer,
+               ISC_XMLCHAR(is_running && needs_refresh ? "Yes" : "No")));
        TRY0(xmlTextWriterEndElement(writer));
 
        TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "localaddr"));
@@ -2605,7 +2606,8 @@ xfrin_jsonrender(dns_zone_t *zone, void *arg) {
 
        json_object_object_add(
                xfrinobj, "refreshqueued",
-               json_object_new_string(needs_refresh ? "Yes" : "No"));
+               json_object_new_string(is_running && needs_refresh ? "Yes"
+                                                                  : "No"));
 
        if (is_running) {
                addrp = dns_xfrin_getsourceaddr(xfr);
index dcd87b5968fb798b674e042d88a8a05d084def3d..e22a255cec492b6053d062b7e81360ec624cd0d4 100644 (file)
@@ -7576,8 +7576,9 @@ Incoming Zone Transfers
       this zone. Possible values and their meanings are:
 
          ``Needs Refresh``
-            The zone is flagged for a refresh, but the process
-            hasn't started yet.
+            The zone needs a refresh, but the process hasn't started yet,
+            which can be due to different factors, like the retry interval of
+            the zone.
 
          ``Pending``
             The zone is flagged for a refresh, but the process is currently
@@ -7592,7 +7593,9 @@ Incoming Zone Transfers
             Otherwise, the zone transfer procedure can still be initiated,
             and the SOA request will be attempted using the same transport as
             the zone transfer. The ``Duration (s)`` timer restarts before
-            entering this state, and for each attempted primary server.
+            entering this state, and for each attempted connection (note that
+            in UDP mode there can be several retries during one "connection"
+            attempt).
 
          ``Deferred``
             The zone is going to be refreshed, but the process was
index c500cbfde299b63eb189b2a86696d04310343cb2..bf49b693b436669560ac9b9bcdd48f868afe80db 100644 (file)
@@ -19297,6 +19297,7 @@ dns_zone_getxfr(dns_zone_t *zone, dns_xfrin_t **xfrp, bool *is_running,
        *is_deferred = false;
        *is_presoa = false;
        *is_pending = false;
+       *needs_refresh = false;
 
        RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
        LOCK_ZONE(zone);
@@ -19305,6 +19306,11 @@ dns_zone_getxfr(dns_zone_t *zone, dns_xfrin_t **xfrp, bool *is_running,
        }
        if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
                *is_running = true;
+               /*
+                * The NEEDREFRESH flag is set only when a notify was received
+                * while the current zone transfer is running.
+                */
+               *needs_refresh = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
        } else if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
                *is_deferred = true;
        } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
@@ -19313,8 +19319,24 @@ dns_zone_getxfr(dns_zone_t *zone, dns_xfrin_t **xfrp, bool *is_running,
                } else {
                        *is_pending = true;
                }
+       } else {
+               /*
+                * No operation is ongoing or pending, just check if the zone
+                * needs a refresh by looking at the refresh and expire times.
+                */
+               if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
+                   (zone->type == dns_zone_secondary ||
+                    zone->type == dns_zone_mirror ||
+                    zone->type == dns_zone_stub))
+               {
+                       isc_time_t now = isc_time_now();
+                       if (isc_time_compare(&now, &zone->refreshtime) >= 0 ||
+                           isc_time_compare(&now, &zone->expiretime) >= 0)
+                       {
+                               *needs_refresh = true;
+                       }
+               }
        }
-       *needs_refresh = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
        UNLOCK_ZONE(zone);
        RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);