]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
"rndc fetchlimit" now also lists rate-limited domains
authorEvan Hunt <each@isc.org>
Thu, 26 May 2022 21:43:23 +0000 (14:43 -0700)
committerEvan Hunt <each@isc.org>
Thu, 7 Jul 2022 02:46:23 +0000 (19:46 -0700)
"rndc fetchlimit" now also prints a list of domain names that are
currently rate-limited by "fetches-per-zone".

The "fetchlimit" system test has been updated to use this feature
to check that domain limits are applied correctly.

bin/named/server.c
bin/rndc/rndc.rst
bin/tests/system/fetchlimit/tests.sh
doc/man/rndc.8in
lib/dns/include/dns/resolver.h
lib/dns/resolver.c

index b109683711965ed44350fb0fd62bfe76b248b928..fadab6ece27689a4ef0e5157ecf7e34dac0a0d4e 100644 (file)
@@ -16622,7 +16622,7 @@ named_server_fetchlimit(named_server_t *server, isc_lex_t *lex,
        for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
             view = ISC_LIST_NEXT(view, link))
        {
-               char tbuf[BUFSIZ];
+               char tbuf[100];
                unsigned int used;
                uint32_t val;
                int s;
@@ -16658,6 +16658,21 @@ named_server_fetchlimit(named_server_t *server, isc_lex_t *lex,
                if (used == isc_buffer_usedlength(*text)) {
                        putstr(text, "\n  None.");
                }
+
+               putstr(text, "\nRate limited servers, view ");
+               putstr(text, view->name);
+               val = dns_resolver_getfetchesperzone(view->resolver);
+               s = snprintf(tbuf, sizeof(tbuf),
+                            " (fetches-per-zone %u):", val);
+               if (s < 0 || (unsigned)s > sizeof(tbuf)) {
+                       return (ISC_R_NOSPACE);
+               }
+               putstr(text, tbuf);
+               used = isc_buffer_usedlength(*text);
+               CHECK(dns_resolver_dumpquota(view->resolver, text));
+               if (used == isc_buffer_usedlength(*text)) {
+                       putstr(text, "\n  None.");
+               }
        }
 
 cleanup:
index 2236d1d911f6343e13f46318414bed373978bace..c075bf163abb3012b5e81d2cd7892dd6f3d3e99b 100644 (file)
@@ -206,8 +206,10 @@ Currently supported commands are:
 
 .. option:: fetchlimit [view]
 
-   This command dumps a list of servers which are currently being
-   rate-limited as a result of ``fetches-per-server`` settings.
+   This command dumps a list of servers that are currently being
+   rate-limited as a result of ``fetches-per-server`` settings, and
+   a list of domain names that are currently being rate-limited as
+   a result of ``fetches-per-zone`` settings.
 
 .. option:: flush
 
index a96caafa9d21726c93c47d247917f063cf7f78af..c0da8d2d7e7351c92969e54494e108e5c0e140ef 100644 (file)
@@ -128,9 +128,10 @@ for try in 1 2 3 4 5; do
             success=$((success+1))
     grep "status: SERVFAIL" dig.out.ns3.$try > /dev/null 2>&1 && \
             fail=$(($fail+1))
-    stat 30 50 || ret=1
+    stat 40 40 || ret=1
+    allowed=$($RNDCCMD fetchlimit | awk '/lamesub/ { print $6 }')
+    [ "${allowed:-0}" -eq 40 ] || ret=1
     [ $ret -eq 1 ] && break
-    $RNDCCMD recursing 2>&1 | sed 's/^/ns3 /' | cat_i
     sleep 1
 done
 echo_i "$success successful valid queries, $fail SERVFAIL"
index c21fab7a61e6417a1647d91f1f2e17030cdc511c..a8814bfd7136cce901c4ce89e8ad80aff5732fbb 100644 (file)
@@ -227,8 +227,10 @@ Manual.)
 .INDENT 0.0
 .TP
 .B fetchlimit [view]
-This command dumps a list of servers which are currently being
-rate\-limited as a result of \fBfetches\-per\-server\fP settings.
+This command dumps a list of servers that are currently being
+rate\-limited as a result of \fBfetches\-per\-server\fP settings, and
+a list of domain names that are currently being rate\-limited as
+a result of \fBfetches\-per\-zone\fP settings.
 .UNINDENT
 .INDENT 0.0
 .TP
index d1edc8e446edf18e940b706b23bee2ea4e7c6f37..a9c2ce953fa5858ef334628ae9c9d368d520692f 100644 (file)
@@ -534,6 +534,9 @@ dns_resolver_setclientsperquery(dns_resolver_t *resolver, uint32_t min,
 void
 dns_resolver_setfetchesperzone(dns_resolver_t *resolver, uint32_t clients);
 
+uint32_t
+dns_resolver_getfetchesperzone(dns_resolver_t *resolver);
+
 void
 dns_resolver_getclientsperquery(dns_resolver_t *resolver, uint32_t *cur,
                                uint32_t *min, uint32_t *max);
@@ -703,6 +706,8 @@ dns_resolver_getquotaresponse(dns_resolver_t *resolver, dns_quotatype_t which);
 void
 dns_resolver_dumpfetches(dns_resolver_t *resolver, isc_statsformat_t format,
                         FILE *fp);
+isc_result_t
+dns_resolver_dumpquota(dns_resolver_t *res, isc_buffer_t **buf);
 
 #ifdef ENABLE_AFL
 /*%
index ba258a82feba335150c4840ec6962e606f509dc1..984765e19f472c0759526b579a4d40d5c73fbace 100644 (file)
@@ -10075,6 +10075,7 @@ destroy(dns_resolver_t *res) {
        }
        isc_mem_put(res->mctx, res->tasks, res->ntasks * sizeof(res->tasks[0]));
 
+       RWLOCK(&res->hash_lock, isc_rwlocktype_write);
        isc_ht_iter_create(res->buckets, &it);
        for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS;
             result = isc_ht_iter_delcurrent_next(it))
@@ -10088,8 +10089,10 @@ destroy(dns_resolver_t *res) {
        }
        isc_ht_iter_destroy(&it);
        isc_ht_destroy(&res->buckets);
+       RWUNLOCK(&res->hash_lock, isc_rwlocktype_write);
        isc_rwlock_destroy(&res->hash_lock);
 
+       RWLOCK(&res->zonehash_lock, isc_rwlocktype_write);
        isc_ht_iter_create(res->zonebuckets, &it);
        for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS;
             result = isc_ht_iter_delcurrent_next(it))
@@ -10109,6 +10112,7 @@ destroy(dns_resolver_t *res) {
        }
        isc_ht_iter_destroy(&it);
        isc_ht_destroy(&res->zonebuckets);
+       RWUNLOCK(&res->zonehash_lock, isc_rwlocktype_write);
        isc_rwlock_destroy(&res->zonehash_lock);
 
        if (res->dispatches4 != NULL) {
@@ -11352,6 +11356,13 @@ dns_resolver_setfetchesperzone(dns_resolver_t *resolver, uint32_t clients) {
        atomic_store_release(&resolver->zspill, clients);
 }
 
+uint32_t
+dns_resolver_getfetchesperzone(dns_resolver_t *resolver) {
+       REQUIRE(VALID_RESOLVER(resolver));
+
+       return (atomic_load_relaxed(&resolver->zspill));
+}
+
 bool
 dns_resolver_getzeronosoattl(dns_resolver_t *resolver) {
        REQUIRE(VALID_RESOLVER(resolver));
@@ -11486,6 +11497,61 @@ dns_resolver_dumpfetches(dns_resolver_t *res, isc_statsformat_t format,
        isc_ht_iter_destroy(&it);
 }
 
+isc_result_t
+dns_resolver_dumpquota(dns_resolver_t *res, isc_buffer_t **buf) {
+       isc_result_t result;
+       isc_ht_iter_t *it = NULL;
+       uint_fast32_t spill;
+
+       REQUIRE(VALID_RESOLVER(res));
+
+       spill = atomic_load_acquire(&res->zspill);
+       if (spill == 0) {
+               return (ISC_R_SUCCESS);
+       }
+
+       RWLOCK(&res->zonehash_lock, isc_rwlocktype_read);
+       isc_ht_iter_create(res->zonebuckets, &it);
+       for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS;
+            result = isc_ht_iter_next(it))
+       {
+               zonebucket_t *bucket = NULL;
+
+               isc_ht_iter_current(it, (void **)&bucket);
+               LOCK(&bucket->lock);
+               for (fctxcount_t *fc = ISC_LIST_HEAD(bucket->list); fc != NULL;
+                    fc = ISC_LIST_NEXT(fc, link))
+               {
+                       char nb[DNS_NAME_FORMATSIZE], text[BUFSIZ];
+
+                       if (fc->count < spill) {
+                               continue;
+                       }
+
+                       dns_name_format(fc->domain, nb, sizeof(nb));
+                       snprintf(text, sizeof(text),
+                                "\n- %s: %u active (allowed %u spilled %u)",
+                                nb, fc->count, fc->allowed, fc->dropped);
+
+                       result = isc_buffer_reserve(buf, strlen(text));
+                       if (result != ISC_R_SUCCESS) {
+                               UNLOCK(&bucket->lock);
+                               goto cleanup;
+                       }
+                       isc_buffer_putstr(*buf, text);
+               }
+               UNLOCK(&bucket->lock);
+       }
+       if (result == ISC_R_NOMORE) {
+               result = ISC_R_SUCCESS;
+       }
+
+cleanup:
+       RWUNLOCK(&res->zonehash_lock, isc_rwlocktype_read);
+       isc_ht_iter_destroy(&it);
+       return (result);
+}
+
 void
 dns_resolver_setquotaresponse(dns_resolver_t *resolver, dns_quotatype_t which,
                              isc_result_t resp) {