]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Limit query pipelining within each TCP connection
authorWitold Kręcicki <wpk@isc.org>
Wed, 16 Oct 2019 11:18:48 +0000 (13:18 +0200)
committerMichał Kępień <michal@isc.org>
Wed, 6 Nov 2019 15:37:13 +0000 (16:37 +0100)
Previously, there was no limit to the number of concurrently served
queries over one pipelined TCP connection; an unlimited number of
queries sent over a single TCP connection could have potentially
exhausted the server's resources.

lib/ns/client.c

index 22a0cb662890c4253db4b67dfd5aa3b2dd69c0c9..7b6f4bb4d6029af7b659329473cf8049335e3100 100644 (file)
 #define SEND_BUFFER_SIZE               4096
 #define RECV_BUFFER_SIZE               4096
 
+#define TCP_CLIENTS_PER_CONN           23
+/*%<
+ * Number of simultaneous ns_clients_t (queries in flight) for one
+ * TCP connection.  The number was arbitrarily picked and might be
+ * changed in the future.
+ */
+
 #define NMCTXS                         100
 /*%<
  * Number of 'mctx pools' for clients. (Should this be configurable?)
@@ -2669,28 +2676,39 @@ ns__client_request(isc_task_t *task, isc_event_t *event) {
        /*
         * Pipeline TCP query processing.
         */
-       if (TCP_CLIENT(client) &&
-           client->message->opcode != dns_opcode_query)
-       {
-               client->tcpconn->pipelined = false;
-       }
-       if (TCP_CLIENT(client) && client->tcpconn->pipelined) {
+       if (TCP_CLIENT(client)) {
+               if (client->message->opcode != dns_opcode_query) {
+                       client->tcpconn->pipelined = false;
+               }
+
                /*
-                * We're pipelining. Replace the client; the
-                * replacement can read the TCP socket looking
-                * for new messages and this one can process the
-                * current message asynchronously.
-                *
-                * There will now be at least three clients using this
-                * TCP socket - one accepting new connections,
-                * one reading an existing connection to get new
-                * messages, and one answering the message already
-                * received.
+                * Limit the maximum number of simultaneous pipelined
+                * queries on TCP connection to TCP_CLIENTS_PER_CONN.
                 */
-               result = ns_client_replace(client);
-               if (result != ISC_R_SUCCESS) {
+               if ((isc_refcount_current(&client->tcpconn->refs)
+                           > TCP_CLIENTS_PER_CONN))
+               {
                        client->tcpconn->pipelined = false;
                }
+
+               if (client->tcpconn->pipelined) {
+                       /*
+                        * We're pipelining. Replace the client; the
+                        * replacement can read the TCP socket looking
+                        * for new messages and this one can process the
+                        * current message asynchronously.
+                        *
+                        * There will now be at least three clients using this
+                        * TCP socket - one accepting new connections,
+                        * one reading an existing connection to get new
+                        * messages, and one answering the message already
+                        * received.
+                        */
+                       result = ns_client_replace(client);
+                       if (result != ISC_R_SUCCESS) {
+                               client->tcpconn->pipelined = false;
+                       }
+               }
        }
 
        dns_opcodestats_increment(client->sctx->opcodestats,