]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
netmgr: fix TCP backlog and client quota count
authorWitold Kręcicki <wpk@isc.org>
Fri, 22 Nov 2019 12:19:45 +0000 (13:19 +0100)
committerEvan Hunt <each@isc.org>
Sat, 23 Nov 2019 00:46:32 +0000 (16:46 -0800)
 - add support for TCP backlog, using the value provided by config.
 - don't attach to TCP client quota for listening sockets, only
   connected sockets.

bin/tests/system/tcp/tests.sh
lib/isc/include/isc/netmgr.h
lib/isc/netmgr/netmgr-int.h
lib/isc/netmgr/netmgr.c
lib/isc/netmgr/tcp.c
lib/isc/netmgr/tcpdns.c
lib/ns/interfacemgr.c

index a3ce32d28b7372cfc3724e5485a47242b3ed5dab..2190ec5f40cdcf5a9d6199c184371d5640092782 100644 (file)
@@ -115,7 +115,7 @@ n=$((n + 1))
 echo_i "TCP high-water: check initial statistics ($n)"
 ret=0
 refresh_tcp_stats
-assert_int_equal "${TCP_CUR}" 1 "current TCP clients count" || ret=1
+assert_int_equal "${TCP_CUR}" 0 "current TCP clients count" || ret=1
 if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status + ret))
 
index 97bb1d6d76452913d5833151fc4795c2a59167fb..82d32f0dc614c4977c3f66f5c4c9d36d137c4f59 100644 (file)
@@ -223,7 +223,8 @@ isc_nm_send(isc_nmhandle_t *handle, isc_region_t *region,
 isc_result_t
 isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
                 isc_nm_cb_t cb, void *cbarg,
-                size_t extrahandlesize, isc_quota_t *quota,
+                size_t extrahandlesize, int backlog,
+                isc_quota_t *quota,
                 isc_nmsocket_t **sockp);
 /*%<
  * Start listening for raw messages over the TCP interface 'iface', using
@@ -255,7 +256,8 @@ isc_nm_tcp_stoplistening(isc_nmsocket_t *sock);
 isc_result_t
 isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface,
                     isc_nm_recv_cb_t cb, void *arg,
-                    size_t extrahandlesize, isc_quota_t *quota,
+                    size_t extrahandlesize, int backlog,
+                    isc_quota_t *quota,
                     isc_nmsocket_t **sockp);
 /*%<
  * Start listening for DNS messages over the TCP interface 'iface', using
index 1979a01454e9a354ebe8669b64b0bac85d85f031..0844cdcbb7d16517785af3cb9e7c1a67bac39a46 100644 (file)
@@ -286,8 +286,20 @@ struct isc_nmsocket {
        isc_nmsocket_type       type;
        isc_nm_t                *mgr;
        isc_nmsocket_t          *parent;
+
+       /*
+        * quota is the TCP client, attached when a TCP connection
+        * is established. pquota is a non-attached pointer to the
+        * TCP client quota, stored in listening sockets but only
+        * attached in connected sockets.
+        */
        isc_quota_t             *quota;
+       isc_quota_t             *pquota;
        bool                    overquota;
+
+       /*
+        * TCP read timeout timer.
+        */
        uv_timer_t              timer;
        bool                    timer_initialized;
        uint64_t                read_timeout;
@@ -307,6 +319,9 @@ struct isc_nmsocket {
        /*% extra data allocated at the end of each isc_nmhandle_t */
        size_t                  extrahandlesize;
 
+       /*% TCP backlog */
+       int backlog;
+
        /*% libuv data */
        uv_os_sock_t            fd;
        union uv_any_handle     uv_handle;
index 273200a6e32d3df199aacdbd5fe7cf1c2ce19a5f..d7699e6d97e79d56ffa5fc324d6527b9361c9adc 100644 (file)
@@ -617,6 +617,8 @@ nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree) {
                isc_quota_detach(&sock->quota);
        }
 
+       sock->pquota = NULL;
+
        if (sock->timer_initialized) {
                uv_close((uv_handle_t *)&sock->timer, NULL);
                sock->timer_initialized = false;
index 56e8600f5780184d024d0bb2c9d8f7b2a71d56b4..5283740f5ebd54ba8f98df1497e34e43984c2d0f 100644 (file)
@@ -130,7 +130,8 @@ tcp_connect_cb(uv_connect_t *uvreq, int status) {
 isc_result_t
 isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
                 isc_nm_cb_t cb, void *cbarg,
-                size_t extrahandlesize, isc_quota_t *quota,
+                size_t extrahandlesize, int backlog,
+                isc_quota_t *quota,
                 isc_nmsocket_t **sockp)
 {
        isc__netievent_tcplisten_t *ievent = NULL;
@@ -144,15 +145,13 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
        nsock->rcb.accept = cb;
        nsock->rcbarg = cbarg;
        nsock->extrahandlesize = extrahandlesize;
+       nsock->backlog = backlog;
        if (quota != NULL) {
                /*
-                * We need to force it to make sure we get it attached.
-                * An example failure mode would be server under attack
-                * reconfiguring interfaces - that might cause weak attach
-                * to fail and leave this listening socket without limits.
-                * We can ignore the result.
+                * We don't attach to quota, just assign - to avoid
+                * increasing quota unnecesarily.
                 */
-               isc_quota_force(quota, &nsock->quota);
+               nsock->pquota = quota;
        }
        nsock->tid = isc_random_uniform(mgr->nworkers);
 
@@ -185,7 +184,7 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ievent0) {
        }
 
        uv_tcp_bind(&sock->uv_handle.tcp, &sock->iface->addr.type.sa, 0);
-       r = uv_listen((uv_stream_t *) &sock->uv_handle.tcp, 10,
+       r = uv_listen((uv_stream_t *) &sock->uv_handle.tcp, sock->backlog,
                      tcp_connection_cb);
        if (r != 0) {
                return;
@@ -219,9 +218,7 @@ stoplistening_cb(uv_handle_t *handle) {
        SIGNAL(&sock->cond);
        UNLOCK(&sock->lock);
 
-       if (sock->quota != NULL) {
-               isc_quota_detach(&sock->quota);
-       }
+       sock->pquota = NULL;
 
        isc_nmsocket_detach(&sock);
 }
@@ -446,8 +443,8 @@ accept_connection(isc_nmsocket_t *ssock) {
                return (ISC_R_CANCELED);
        }
 
-       if (ssock->quota != NULL) {
-               result = isc_quota_attach(ssock->quota, &quota);
+       if (ssock->pquota != NULL) {
+               result = isc_quota_attach(ssock->pquota, &quota);
                if (result != ISC_R_SUCCESS) {
                        return (result);
                }
index c3f87a3d4d391f3a4e1839bcf10ede61e97e20b6..d75fdda94395689be9a4114477d73d12a0f46006 100644 (file)
@@ -275,7 +275,8 @@ dnslisten_readcb(isc_nmhandle_t *handle, isc_region_t *region, void *arg) {
 isc_result_t
 isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface,
                    isc_nm_recv_cb_t cb, void *cbarg,
-                   size_t extrahandlesize, isc_quota_t *quota,
+                   size_t extrahandlesize, int backlog,
+                   isc_quota_t *quota,
                    isc_nmsocket_t **sockp)
 {
        /* A 'wrapper' socket object with outer set to true TCP socket */
@@ -293,7 +294,7 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface,
 
        /* We set dnslistensock->outer to a true listening socket */
        result = isc_nm_listentcp(mgr, iface, dnslisten_acceptcb,
-                                 dnslistensock, extrahandlesize,
+                                 dnslistensock, extrahandlesize, backlog,
                                  quota, &dnslistensock->outer);
 
        atomic_store(&dnslistensock->listening, true);
index 8096d5ffefb707942e981c2fb90b2f1fb644f7c8..2dd03a0eee943d7e1c07368d118c0f83e8798802 100644 (file)
@@ -461,6 +461,7 @@ ns_interface_listentcp(ns_interface_t *ifp) {
                                     (isc_nmiface_t *) &ifp->addr,
                                     ns__client_request, ifp,
                                     sizeof(ns_client_t),
+                                    ifp->mgr->backlog,
                                     &ifp->mgr->sctx->tcpquota,
                                     &ifp->tcplistensocket);
        if (result != ISC_R_SUCCESS) {