]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
rctx_resend() increment query counters
authorColin Vidal <colin@isc.org>
Tue, 7 Apr 2026 20:18:58 +0000 (22:18 +0200)
committerMichał Kępień <michal@isc.org>
Thu, 7 May 2026 11:32:15 +0000 (13:32 +0200)
Calls to `rctx_resend()` are done internally within the resolver, in
flow which are not supposed to happens more than once. For instance,
if some query fails, and a specific flag "F" wasn't set, then set the
flag and try again. This wouldn't occur more than once because if the
query fails the next attempt, the flag "F" would be set already, so the
resolver would move to the next server (or give up).

However, a subtle bug missing checking a flag, for instance, could lead
to an unbounded loop re-trying to query the same server. This is now
impossible as `rctx_resend()` also increment the query counters (so if
such case occurs, it would stop once the maximum limit is reached).

The dns_resstatscounter_retry are also only incremented if the
`fctx_query()` succeeds, similar to as is done in `fctx_try()`.

lib/dns/resolver.c

index 5fed2760decab4919148c4e913c307655594bfbb..d7418d494ad888199a460358a3dc28890d3caa14 100644 (file)
@@ -9467,9 +9467,9 @@ rctx_nextserver(respctx_t *rctx, dns_message_t *message,
  * rctx_resend():
  *
  * Resend the query, probably with the options changed. Calls
- * fctx_query(), passing rctx->retryopts (which is based on
- * query->options, but may have been updated since the last time
- * fctx_query() was called).
+ * fctx_query(), unless query counter limits are hit, passing
+ * rctx->retryopts (which is based on query->options, but may have
+ * been updated since the last time fctx_query() was called).
  */
 static void
 rctx_resend(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo) {
@@ -9477,8 +9477,15 @@ rctx_resend(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo) {
        isc_result_t result;
 
        FCTXTRACE("resend");
-       inc_stats(fctx->res, dns_resstatscounter_retry);
+
+       CHECK(incr_query_counters(fctx));
+
        result = fctx_query(fctx, addrinfo, rctx->retryopts);
+       if (result == ISC_R_SUCCESS) {
+               inc_stats(fctx->res, dns_resstatscounter_retry);
+       }
+
+cleanup:
        if (result != ISC_R_SUCCESS) {
                fctx_failure_detach(&rctx->fctx, result);
        }