]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Drop expired but not accepted TCP connections
authorArtem Boldariev <artem@boldariev.com>
Tue, 2 Jul 2024 13:16:59 +0000 (16:16 +0300)
committerArtem Boldariev <artem@boldariev.com>
Wed, 3 Jul 2024 12:03:02 +0000 (15:03 +0300)
This commit ensures that we are not attempting to accept an expired
TCP connection as we are not interested in any data that could have
been accumulated in its internal buffers. Now we just drop them for
good.

lib/isc/netmgr/netmgr-int.h
lib/isc/netmgr/tcp.c

index 51bcf9430e9f2b96f635077384625d96d781d9cd..51da0a309ed9b93d719c8195601b8729b1678255 100644 (file)
@@ -36,6 +36,7 @@
 #include <isc/stats.h>
 #include <isc/thread.h>
 #include <isc/tid.h>
+#include <isc/time.h>
 #include <isc/tls.h>
 #include <isc/util.h>
 #include <isc/uv.h>
@@ -641,6 +642,12 @@ struct isc_nmsocket {
        bool reading;
        bool timedout;
 
+       /*%
+        * A timestamp of when the connection acceptance was delayed due
+        * to quota.
+        */
+       isc_nanosecs_t quota_accept_ts;
+
        /*%
         * Established an outgoing connection, as client not server.
         */
index c6bb2812ffa8036de708161044a6d42fef9be980..5b475bbebc0d47ec7fd543ca2f34108878f6a467 100644 (file)
@@ -549,6 +549,7 @@ tcp_connection_cb(uv_stream_t *server, int status) {
                                              &csock->quotacb, quota_accept_cb,
                                              csock);
                if (result == ISC_R_QUOTA) {
+                       csock->quota_accept_ts = isc_time_monotonic();
                        isc__nm_incstats(ssock, STATID_ACCEPTFAIL);
                        goto done;
                }
@@ -901,6 +902,28 @@ accept_connection(isc_nmsocket_t *csock) {
                goto failure;
        }
 
+       /* Check if the connection is not expired */
+       if (csock->quota_accept_ts != 0) {
+               /* The timestamp is given in nanoseconds */
+               const uint64_t time_elapsed_ms =
+                       (isc_time_monotonic() - csock->quota_accept_ts) /
+                       NS_PER_MS;
+
+               if (time_elapsed_ms >= csock->read_timeout) {
+                       /*
+                        * At this point we have received a connection from a
+                        * queue of accepted connections (via uv_accept()), but
+                        * it has expired. We cannot do anything better than
+                        * drop it on the floor at this point.
+                        */
+                       result = ISC_R_TIMEDOUT;
+                       goto failure;
+               } else {
+                       /* Adjust the initial read timeout accordingly */
+                       csock->read_timeout -= time_elapsed_ms;
+               }
+       }
+
        r = uv_tcp_getpeername(&csock->uv_handle.tcp, (struct sockaddr *)&ss,
                               &(int){ sizeof(ss) });
        if (r != 0) {