Fix the incoming transfers' "Needs Refresh" state in stats channel

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.
This commit is contained in:
Aram Sargsyan 2023-09-19 09:38:35 +00:00
parent 621a1461d9
commit 93088fbf8b
3 changed files with 33 additions and 6 deletions

View 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);

View 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

View 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);