<div dir="ltr"><div dir="ltr">On Wed, 27 Nov 2019 at 21:25, akuster808 <<a href="mailto:akuster808@gmail.com">akuster808@gmail.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
<br>
On 11/27/19 8:40 AM, Alexander Kanavin wrote:<br>
> Drop backports.<br>
><br>
> Drop 0001-gen.c-extend-DIRNAMESIZE-from-256-to-512.patch and<br>
> 0001-lib-dns-gen.c-fix-too-long-error.patch as problem is fixed<br>
<br>
Bug fix only?<br></blockquote><div><br></div><div>I don't think so, there are some new features as well:</div><div><a href="https://downloads.isc.org/isc/bind9/9.11.13/RELEASE-NOTES-bind-9.11.13.html">https://downloads.isc.org/isc/bind9/9.11.13/RELEASE-NOTES-bind-9.11.13.html</a></div><div><br></div><div>Alex<br></div><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
-armin<br>
> upstream.<br>
><br>
> Signed-off-by: Alexander Kanavin <<a href="mailto:alex.kanavin@gmail.com" target="_blank">alex.kanavin@gmail.com</a>><br>
> ---<br>
> .../bind/0001-bind-fix-CVE-2019-6471.patch | 64 --<br>
> ....in-remove-useless-L-use_openssl-lib.patch | 18 +-<br>
> ...01-fix-enforcement-of-tcp-clients-v1.patch | 60 --<br>
> ...c-extend-DIRNAMESIZE-from-256-to-512.patch | 22 -<br>
> ...001-lib-dns-gen.c-fix-too-long-error.patch | 31 -<br>
> ...p-clients-could-still-be-exceeded-v2.patch | 670 -------------<br>
> ...rence-counter-for-pipeline-groups-v3.patch | 278 ------<br>
> ...accounting-and-client-mortality-chec.patch | 512 ----------<br>
> ...a-and-pipeline-refs-allow-special-ca.patch | 911 ------------------<br>
> ...allowance-for-tcp-clients-interfaces.patch | 80 --<br>
> ...perations-in-bin-named-client.c-with.patch | 140 ---<br>
> ...ching-for-json-headers-searches-sysr.patch | 15 +-<br>
> .../{<a href="http://bind_9.11.5-P4.bb" rel="noreferrer" target="_blank">bind_9.11.5-P4.bb</a> => <a href="http://bind_9.11.13.bb" rel="noreferrer" target="_blank">bind_9.11.13.bb</a>} | 18 +-<br>
> 13 files changed, 20 insertions(+), 2799 deletions(-)<br>
> delete mode 100644 meta/recipes-connectivity/bind/bind/0001-bind-fix-CVE-2019-6471.patch<br>
> delete mode 100644 meta/recipes-connectivity/bind/bind/0001-fix-enforcement-of-tcp-clients-v1.patch<br>
> delete mode 100644 meta/recipes-connectivity/bind/bind/0001-gen.c-extend-DIRNAMESIZE-from-256-to-512.patch<br>
> delete mode 100644 meta/recipes-connectivity/bind/bind/0001-lib-dns-gen.c-fix-too-long-error.patch<br>
> delete mode 100644 meta/recipes-connectivity/bind/bind/0002-tcp-clients-could-still-be-exceeded-v2.patch<br>
> delete mode 100644 meta/recipes-connectivity/bind/bind/0003-use-reference-counter-for-pipeline-groups-v3.patch<br>
> delete mode 100644 meta/recipes-connectivity/bind/bind/0004-better-tcpquota-accounting-and-client-mortality-chec.patch<br>
> delete mode 100644 meta/recipes-connectivity/bind/bind/0005-refactor-tcpquota-and-pipeline-refs-allow-special-ca.patch<br>
> delete mode 100644 meta/recipes-connectivity/bind/bind/0006-restore-allowance-for-tcp-clients-interfaces.patch<br>
> delete mode 100644 meta/recipes-connectivity/bind/bind/0007-Replace-atomic-operations-in-bin-named-client.c-with.patch<br>
> rename meta/recipes-connectivity/bind/{<a href="http://bind_9.11.5-P4.bb" rel="noreferrer" target="_blank">bind_9.11.5-P4.bb</a> => <a href="http://bind_9.11.13.bb" rel="noreferrer" target="_blank">bind_9.11.13.bb</a>} (86%)<br>
><br>
> diff --git a/meta/recipes-connectivity/bind/bind/0001-bind-fix-CVE-2019-6471.patch b/meta/recipes-connectivity/bind/bind/0001-bind-fix-CVE-2019-6471.patch<br>
> deleted file mode 100644<br>
> index 2fed99e1bba..00000000000<br>
> --- a/meta/recipes-connectivity/bind/bind/0001-bind-fix-CVE-2019-6471.patch<br>
> +++ /dev/null<br>
> @@ -1,64 +0,0 @@<br>
> -Backport patch to fix CVE-2019-6471.<br>
> -<br>
> -Ref:<br>
> -<a href="https://security-tracker.debian.org/tracker/CVE-2019-6471" rel="noreferrer" target="_blank">https://security-tracker.debian.org/tracker/CVE-2019-6471</a><br>
> -<br>
> -CVE: CVE-2019-6471<br>
> -Upstream-Status: Backport [<a href="https://gitlab.isc.org/isc-projects/bind9/commit/3a9c7bb" rel="noreferrer" target="_blank">https://gitlab.isc.org/isc-projects/bind9/commit/3a9c7bb</a>]<br>
> -<br>
> -Signed-off-by: Kai Kang <<a href="mailto:kai.kang@windriver.com" target="_blank">kai.kang@windriver.com</a>><br>
> -<br>
> -From 3a9c7bb80d4a609b86427406d9dd783199920b5b Mon Sep 17 00:00:00 2001<br>
> -From: Mark Andrews <<a href="mailto:marka@isc.org" target="_blank">marka@isc.org</a>><br>
> -Date: Tue, 19 Mar 2019 14:14:21 +1100<br>
> -Subject: [PATCH] move item_out test inside lock in dns_dispatch_getnext()<br>
> -<br>
> -(cherry picked from commit 60c42f849d520564ed42e5ed0ba46b4b69c07712)<br>
> ----<br>
> - lib/dns/dispatch.c | 12 ++++++++----<br>
> - 1 file changed, 8 insertions(+), 4 deletions(-)<br>
> -<br>
> -diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c<br>
> -index 408beda367..3278db4a07 100644<br>
> ---- a/lib/dns/dispatch.c<br>
> -+++ b/lib/dns/dispatch.c<br>
> -@@ -134,7 +134,7 @@ struct dns_dispentry {<br>
> - isc_task_t *task;<br>
> - isc_taskaction_t action;<br>
> - void *arg;<br>
> -- bool item_out;<br>
> -+ bool item_out;<br>
> - dispsocket_t *dispsocket;<br>
> - ISC_LIST(dns_dispatchevent_t) items;<br>
> - ISC_LINK(dns_dispentry_t) link;<br>
> -@@ -3422,13 +3422,14 @@ dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent) {<br>
> - disp = resp->disp;<br>
> - REQUIRE(VALID_DISPATCH(disp));<br>
> - <br>
> -- REQUIRE(resp->item_out == true);<br>
> -- resp->item_out = false;<br>
> --<br>
> - ev = *sockevent;<br>
> - *sockevent = NULL;<br>
> - <br>
> - LOCK(&disp->lock);<br>
> -+<br>
> -+ REQUIRE(resp->item_out == true);<br>
> -+ resp->item_out = false;<br>
> -+<br>
> - if (ev->buffer.base != NULL)<br>
> - free_buffer(disp, ev->buffer.base, ev->buffer.length);<br>
> - free_devent(disp, ev);<br>
> -@@ -3573,6 +3574,9 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,<br>
> - isc_task_send(disp->task[0], &disp->ctlevent);<br>
> - }<br>
> - <br>
> -+/*<br>
> -+ * disp must be locked.<br>
> -+ */<br>
> - static void<br>
> - do_cancel(dns_dispatch_t *disp) {<br>
> - dns_dispatchevent_t *ev;<br>
> --- <br>
> -2.20.1<br>
> -<br>
> diff --git a/meta/recipes-connectivity/bind/bind/0001-configure.in-remove-useless-L-use_openssl-lib.patch b/meta/recipes-connectivity/bind/bind/0001-configure.in-remove-useless-L-use_openssl-lib.patch<br>
> index 871bb2a5f6c..9d31b980807 100644<br>
> --- a/meta/recipes-connectivity/bind/bind/0001-configure.in-remove-useless-L-use_openssl-lib.patch<br>
> +++ b/meta/recipes-connectivity/bind/bind/0001-configure.in-remove-useless-L-use_openssl-lib.patch<br>
> @@ -1,4 +1,4 @@<br>
> -From 950867d9fd3f690e271c8c807b6eed144b2935b2 Mon Sep 17 00:00:00 2001<br>
> +From 2325a92f1896a2a7f586611686801b41fbc91b50 Mon Sep 17 00:00:00 2001<br>
> From: Hongxu Jia <<a href="mailto:hongxu.jia@windriver.com" target="_blank">hongxu.jia@windriver.com</a>><br>
> Date: Mon, 27 Aug 2018 15:00:51 +0800<br>
> Subject: [PATCH] <a href="http://configure.in" rel="noreferrer" target="_blank">configure.in</a>: remove useless `-L$use_openssl/lib'<br>
> @@ -10,15 +10,16 @@ and helpful for clean up host build path in isc-config.sh<br>
> Upstream-Status: Inappropriate [oe-core specific]<br>
> <br>
> Signed-off-by: Hongxu Jia <<a href="mailto:hongxu.jia@windriver.com" target="_blank">hongxu.jia@windriver.com</a>><br>
> +<br>
> ---<br>
> - <a href="http://configure.in" rel="noreferrer" target="_blank">configure.in</a> | 2 +-<br>
> + <a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a> | 2 +-<br>
> 1 file changed, 1 insertion(+), 1 deletion(-)<br>
> <br>
> -diff --git a/<a href="http://configure.in" rel="noreferrer" target="_blank">configure.in</a> b/<a href="http://configure.in" rel="noreferrer" target="_blank">configure.in</a><br>
> -index 54efc55..76ac0eb 100644<br>
> ---- a/<a href="http://configure.in" rel="noreferrer" target="_blank">configure.in</a><br>
> -+++ b/<a href="http://configure.in" rel="noreferrer" target="_blank">configure.in</a><br>
> -@@ -1691,7 +1691,7 @@ If you don't want OpenSSL, use --without-openssl])<br>
> +diff --git a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a> b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> +index e85a5c6..2bbfc58 100644<br>
> +--- a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> ++++ b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> +@@ -1631,7 +1631,7 @@ If you don't want OpenSSL, use --without-openssl])<br>
> fi<br>
> ;;<br>
> *)<br>
> @@ -27,6 +28,3 @@ index 54efc55..76ac0eb 100644<br>
> ;;<br>
> esac<br>
> fi<br>
> --- <br>
> -2.7.4<br>
> -<br>
> diff --git a/meta/recipes-connectivity/bind/bind/0001-fix-enforcement-of-tcp-clients-v1.patch b/meta/recipes-connectivity/bind/bind/0001-fix-enforcement-of-tcp-clients-v1.patch<br>
> deleted file mode 100644<br>
> index 48ae125f845..00000000000<br>
> --- a/meta/recipes-connectivity/bind/bind/0001-fix-enforcement-of-tcp-clients-v1.patch<br>
> +++ /dev/null<br>
> @@ -1,60 +0,0 @@<br>
> -Backport patch to fix CVE-2018-5743.<br>
> -<br>
> -Ref:<br>
> -<a href="https://security-tracker.debian.org/tracker/CVE-2018-5743" rel="noreferrer" target="_blank">https://security-tracker.debian.org/tracker/CVE-2018-5743</a><br>
> -<br>
> -CVE: CVE-2018-5743<br>
> -Upstream-Status: Backport [<a href="https://gitlab.isc.org/isc-projects/bind9/commit/ec2d50d" rel="noreferrer" target="_blank">https://gitlab.isc.org/isc-projects/bind9/commit/ec2d50d</a>]<br>
> -<br>
> -Signed-off-by: Kai Kang <<a href="mailto:kai.kang@windriver.com" target="_blank">kai.kang@windriver.com</a>><br>
> -<br>
> -From ec2d50da8d81814640e28593d912f4b96c7efece Mon Sep 17 00:00:00 2001<br>
> -From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= <<a href="mailto:wpk@isc.org" target="_blank">wpk@isc.org</a>><br>
> -Date: Thu, 3 Jan 2019 14:17:43 +0100<br>
> -Subject: [PATCH 1/6] fix enforcement of tcp-clients (v1)<br>
> -<br>
> -tcp-clients settings could be exceeded in some cases by<br>
> -creating more and more active TCP clients that are over<br>
> -the set quota limit, which in the end could lead to a<br>
> -DoS attack by e.g. exhaustion of file descriptors.<br>
> -<br>
> -If TCP client we're closing went over the quota (so it's<br>
> -not attached to a quota) mark it as mortal - so that it<br>
> -will be destroyed and not set up to listen for new<br>
> -connections - unless it's the last client for a specific<br>
> -interface.<br>
> -<br>
> -(cherry picked from commit f97131d21b97381cef72b971b157345c1f9b4115)<br>
> -(cherry picked from commit 9689ffc485df8f971f0ad81ab8ab1f5389493776)<br>
> ----<br>
> - bin/named/client.c | 13 ++++++++++++-<br>
> - 1 file changed, 12 insertions(+), 1 deletion(-)<br>
> -<br>
> -diff --git a/bin/named/client.c b/bin/named/client.c<br>
> -index d482da7121..0739dd48af 100644<br>
> ---- a/bin/named/client.c<br>
> -+++ b/bin/named/client.c<br>
> -@@ -421,8 +421,19 @@ exit_check(ns_client_t *client) {<br>
> - isc_socket_detach(&client->tcpsocket);<br>
> - }<br>
> - <br>
> -- if (client->tcpquota != NULL)<br>
> -+ if (client->tcpquota != NULL) {<br>
> - isc_quota_detach(&client->tcpquota);<br>
> -+ } else {<br>
> -+ /*<br>
> -+ * We went over quota with this client, we don't<br>
> -+ * want to restart listening unless this is the<br>
> -+ * last client on this interface, which is<br>
> -+ * checked later.<br>
> -+ */<br>
> -+ if (TCP_CLIENT(client)) {<br>
> -+ client->mortal = true;<br>
> -+ }<br>
> -+ }<br>
> - <br>
> - if (client->timerset) {<br>
> - (void)isc_timer_reset(client->timer,<br>
> --- <br>
> -2.20.1<br>
> -<br>
> diff --git a/meta/recipes-connectivity/bind/bind/0001-gen.c-extend-DIRNAMESIZE-from-256-to-512.patch b/meta/recipes-connectivity/bind/bind/0001-gen.c-extend-DIRNAMESIZE-from-256-to-512.patch<br>
> deleted file mode 100644<br>
> index a8d601dcaa7..00000000000<br>
> --- a/meta/recipes-connectivity/bind/bind/0001-gen.c-extend-DIRNAMESIZE-from-256-to-512.patch<br>
> +++ /dev/null<br>
> @@ -1,22 +0,0 @@<br>
> -Upstream-Status: Pending<br>
> -<br>
> -Subject: gen.c: extend DIRNAMESIZE from 256 to 512<br>
> -<br>
> -Signed-off-by: Chen Qi <<a href="mailto:Qi.Chen@windriver.com" target="_blank">Qi.Chen@windriver.com</a>><br>
> ----<br>
> - lib/dns/gen.c | 2 +-<br>
> - 1 file changed, 1 insertion(+), 1 deletion(-)<br>
> -<br>
> -Index: bind-9.11.3/lib/dns/gen.c<br>
> -===================================================================<br>
> ---- bind-9.11.3.orig/lib/dns/gen.c<br>
> -+++ bind-9.11.3/lib/dns/gen.c<br>
> -@@ -130,7 +130,7 @@ static const char copyright[] =<br>
> - #define TYPECLASSBUF (TYPECLASSLEN + 1)<br>
> - #define TYPECLASSFMT "%" STR(TYPECLASSLEN) "[-0-9a-z]_%d"<br>
> - #define ATTRIBUTESIZE 256<br>
> --#define DIRNAMESIZE 256<br>
> -+#define DIRNAMESIZE 512<br>
> - <br>
> - static struct cc {<br>
> - struct cc *next;<br>
> diff --git a/meta/recipes-connectivity/bind/bind/0001-lib-dns-gen.c-fix-too-long-error.patch b/meta/recipes-connectivity/bind/bind/0001-lib-dns-gen.c-fix-too-long-error.patch<br>
> deleted file mode 100644<br>
> index 01874a44076..00000000000<br>
> --- a/meta/recipes-connectivity/bind/bind/0001-lib-dns-gen.c-fix-too-long-error.patch<br>
> +++ /dev/null<br>
> @@ -1,31 +0,0 @@<br>
> -From 5bc3167a8b714ec0c4a3f1c7f3b9411296ec0a23 Mon Sep 17 00:00:00 2001<br>
> -From: Robert Yang <<a href="mailto:liezhi.yang@windriver.com" target="_blank">liezhi.yang@windriver.com</a>><br>
> -Date: Wed, 16 Sep 2015 20:23:47 -0700<br>
> -Subject: [PATCH] lib/dns/gen.c: fix too long error<br>
> -<br>
> -The 512 is a little short when build in deep dir, and cause "too long"<br>
> -error, use PATH_MAX if defined.<br>
> -<br>
> -Upstream-Status: Pending<br>
> -<br>
> -Signed-off-by: Robert Yang <<a href="mailto:liezhi.yang@windriver.com" target="_blank">liezhi.yang@windriver.com</a>><br>
> ----<br>
> - lib/dns/gen.c | 4 ++++<br>
> - 1 file changed, 4 insertions(+)<br>
> -<br>
> -Index: bind-9.11.3/lib/dns/gen.c<br>
> -===================================================================<br>
> ---- bind-9.11.3.orig/lib/dns/gen.c<br>
> -+++ bind-9.11.3/lib/dns/gen.c<br>
> -@@ -130,7 +130,11 @@ static const char copyright[] =<br>
> - #define TYPECLASSBUF (TYPECLASSLEN + 1)<br>
> - #define TYPECLASSFMT "%" STR(TYPECLASSLEN) "[-0-9a-z]_%d"<br>
> - #define ATTRIBUTESIZE 256<br>
> -+#ifdef PATH_MAX<br>
> -+#define DIRNAMESIZE PATH_MAX<br>
> -+#else<br>
> - #define DIRNAMESIZE 512<br>
> -+#endif<br>
> - <br>
> - static struct cc {<br>
> - struct cc *next;<br>
> diff --git a/meta/recipes-connectivity/bind/bind/0002-tcp-clients-could-still-be-exceeded-v2.patch b/meta/recipes-connectivity/bind/bind/0002-tcp-clients-could-still-be-exceeded-v2.patch<br>
> deleted file mode 100644<br>
> index ca4e8b1a662..00000000000<br>
> --- a/meta/recipes-connectivity/bind/bind/0002-tcp-clients-could-still-be-exceeded-v2.patch<br>
> +++ /dev/null<br>
> @@ -1,670 +0,0 @@<br>
> -Backport patch to fix CVE-2018-5743.<br>
> -<br>
> -Ref:<br>
> -<a href="https://security-tracker.debian.org/tracker/CVE-2018-5743" rel="noreferrer" target="_blank">https://security-tracker.debian.org/tracker/CVE-2018-5743</a><br>
> -<br>
> -CVE: CVE-2018-5743<br>
> -Upstream-Status: Backport [<a href="https://gitlab.isc.org/isc-projects/bind9/commit/719f604" rel="noreferrer" target="_blank">https://gitlab.isc.org/isc-projects/bind9/commit/719f604</a>]<br>
> -<br>
> -Signed-off-by: Kai Kang <<a href="mailto:kai.kang@windriver.com" target="_blank">kai.kang@windriver.com</a>><br>
> -<br>
> -From 719f604e3fad5b7479bd14e2fa0ef4413f0a8fdc Mon Sep 17 00:00:00 2001<br>
> -From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= <<a href="mailto:wpk@isc.org" target="_blank">wpk@isc.org</a>><br>
> -Date: Fri, 4 Jan 2019 12:50:51 +0100<br>
> -Subject: [PATCH 2/6] tcp-clients could still be exceeded (v2)<br>
> -<br>
> -the TCP client quota could still be ineffective under some<br>
> -circumstances. this change:<br>
> -<br>
> -- improves quota accounting to ensure that TCP clients are<br>
> - properly limited, while still guaranteeing that at least one client<br>
> - is always available to serve TCP connections on each interface.<br>
> -- uses more descriptive names and removes one (ntcptarget) that<br>
> - was no longer needed<br>
> -- adds comments<br>
> -<br>
> -(cherry picked from commit 924651f1d5e605cd186d03f4f7340bcc54d77cc2)<br>
> -(cherry picked from commit 55a7a458e30e47874d34bdf1079eb863a0512396)<br>
> ----<br>
> - bin/named/client.c | 311 ++++++++++++++++++++-----<br>
> - bin/named/include/named/client.h | 14 +-<br>
> - bin/named/include/named/interfacemgr.h | 11 +-<br>
> - bin/named/interfacemgr.c | 8 +-<br>
> - 4 files changed, 267 insertions(+), 77 deletions(-)<br>
> -<br>
> -diff --git a/bin/named/client.c b/bin/named/client.c<br>
> -index 0739dd48af..a7b49a0f71 100644<br>
> ---- a/bin/named/client.c<br>
> -+++ b/bin/named/client.c<br>
> -@@ -246,10 +246,11 @@ static void ns_client_dumpmessage(ns_client_t *client, const char *reason);<br>
> - static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,<br>
> - dns_dispatch_t *disp, bool tcp);<br>
> - static isc_result_t get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp,<br>
> -- isc_socket_t *sock);<br>
> -+ isc_socket_t *sock, ns_client_t *oldclient);<br>
> - static inline bool<br>
> --allowed(isc_netaddr_t *addr, dns_name_t *signer, isc_netaddr_t *ecs_addr,<br>
> -- uint8_t ecs_addrlen, uint8_t *ecs_scope, dns_acl_t *acl);<br>
> -+allowed(isc_netaddr_t *addr, dns_name_t *signer,<br>
> -+ isc_netaddr_t *ecs_addr, uint8_t ecs_addrlen,<br>
> -+ uint8_t *ecs_scope, dns_acl_t *acl)<br>
> - static void compute_cookie(ns_client_t *client, uint32_t when,<br>
> - uint32_t nonce, const unsigned char *secret,<br>
> - isc_buffer_t *buf);<br>
> -@@ -405,8 +406,11 @@ exit_check(ns_client_t *client) {<br>
> - */<br>
> - INSIST(client->recursionquota == NULL);<br>
> - INSIST(client->newstate <= NS_CLIENTSTATE_READY);<br>
> -- if (client->nreads > 0)<br>
> -+<br>
> -+ if (client->nreads > 0) {<br>
> - dns_tcpmsg_cancelread(&client->tcpmsg);<br>
> -+ }<br>
> -+<br>
> - if (client->nreads != 0) {<br>
> - /* Still waiting for read cancel completion. */<br>
> - return (true);<br>
> -@@ -416,25 +420,58 @@ exit_check(ns_client_t *client) {<br>
> - dns_tcpmsg_invalidate(&client->tcpmsg);<br>
> - client->tcpmsg_valid = false;<br>
> - }<br>
> -+<br>
> - if (client->tcpsocket != NULL) {<br>
> - CTRACE("closetcp");<br>
> - isc_socket_detach(&client->tcpsocket);<br>
> -+<br>
> -+ if (client->tcpactive) {<br>
> -+ LOCK(&client->interface->lock);<br>
> -+ INSIST(client->interface->ntcpactive > 0);<br>
> -+ client->interface->ntcpactive--;<br>
> -+ UNLOCK(&client->interface->lock);<br>
> -+ client->tcpactive = false;<br>
> -+ }<br>
> - }<br>
> - <br>
> - if (client->tcpquota != NULL) {<br>
> -- isc_quota_detach(&client->tcpquota);<br>
> -- } else {<br>
> - /*<br>
> -- * We went over quota with this client, we don't<br>
> -- * want to restart listening unless this is the<br>
> -- * last client on this interface, which is<br>
> -- * checked later.<br>
> -+ * If we are not in a pipeline group, or<br>
> -+ * we are the last client in the group, detach from<br>
> -+ * tcpquota; otherwise, transfer the quota to<br>
> -+ * another client in the same group.<br>
> - */<br>
> -- if (TCP_CLIENT(client)) {<br>
> -- client->mortal = true;<br>
> -+ if (!ISC_LINK_LINKED(client, glink) ||<br>
> -+ (client->glink.next == NULL &&<br>
> -+ client->glink.prev == NULL))<br>
> -+ {<br>
> -+ isc_quota_detach(&client->tcpquota);<br>
> -+ } else if (client->glink.next != NULL) {<br>
> -+ INSIST(client->glink.next->tcpquota == NULL);<br>
> -+ client->glink.next->tcpquota = client->tcpquota;<br>
> -+ client->tcpquota = NULL;<br>
> -+ } else {<br>
> -+ INSIST(client->glink.prev->tcpquota == NULL);<br>
> -+ client->glink.prev->tcpquota = client->tcpquota;<br>
> -+ client->tcpquota = NULL;<br>
> - }<br>
> - }<br>
> - <br>
> -+ /*<br>
> -+ * Unlink from pipeline group.<br>
> -+ */<br>
> -+ if (ISC_LINK_LINKED(client, glink)) {<br>
> -+ if (client->glink.next != NULL) {<br>
> -+ client->glink.next->glink.prev =<br>
> -+ client->glink.prev;<br>
> -+ }<br>
> -+ if (client->glink.prev != NULL) {<br>
> -+ client->glink.prev->glink.next =<br>
> -+ client->glink.next;<br>
> -+ }<br>
> -+ ISC_LINK_INIT(client, glink);<br>
> -+ }<br>
> -+<br>
> - if (client->timerset) {<br>
> - (void)isc_timer_reset(client->timer,<br>
> - isc_timertype_inactive,<br>
> -@@ -455,15 +492,16 @@ exit_check(ns_client_t *client) {<br>
> - * that already. Check whether this client needs to remain<br>
> - * active and force it to go inactive if not.<br>
> - *<br>
> -- * UDP clients go inactive at this point, but TCP clients<br>
> -- * may remain active if we have fewer active TCP client<br>
> -- * objects than desired due to an earlier quota exhaustion.<br>
> -+ * UDP clients go inactive at this point, but a TCP client<br>
> -+ * will needs to remain active if no other clients are<br>
> -+ * listening for TCP requests on this interface, to<br>
> -+ * prevent this interface from going nonresponsive.<br>
> - */<br>
> - if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) {<br>
> - LOCK(&client->interface->lock);<br>
> -- if (client->interface->ntcpcurrent <<br>
> -- client->interface->ntcptarget)<br>
> -+ if (client->interface->ntcpaccepting == 0) {<br>
> - client->mortal = false;<br>
> -+ }<br>
> - UNLOCK(&client->interface->lock);<br>
> - }<br>
> - <br>
> -@@ -472,15 +510,17 @@ exit_check(ns_client_t *client) {<br>
> - * queue for recycling.<br>
> - */<br>
> - if (client->mortal) {<br>
> -- if (client->newstate > NS_CLIENTSTATE_INACTIVE)<br>
> -+ if (client->newstate > NS_CLIENTSTATE_INACTIVE) {<br>
> - client->newstate = NS_CLIENTSTATE_INACTIVE;<br>
> -+ }<br>
> - }<br>
> - <br>
> - if (NS_CLIENTSTATE_READY == client->newstate) {<br>
> - if (TCP_CLIENT(client)) {<br>
> - client_accept(client);<br>
> -- } else<br>
> -+ } else {<br>
> - client_udprecv(client);<br>
> -+ }<br>
> - client->newstate = NS_CLIENTSTATE_MAX;<br>
> - return (true);<br>
> - }<br>
> -@@ -492,41 +532,57 @@ exit_check(ns_client_t *client) {<br>
> - /*<br>
> - * We are trying to enter the inactive state.<br>
> - */<br>
> -- if (client->naccepts > 0)<br>
> -+ if (client->naccepts > 0) {<br>
> - isc_socket_cancel(client->tcplistener, client->task,<br>
> - ISC_SOCKCANCEL_ACCEPT);<br>
> -+ }<br>
> - <br>
> - /* Still waiting for accept cancel completion. */<br>
> -- if (! (client->naccepts == 0))<br>
> -+ if (! (client->naccepts == 0)) {<br>
> - return (true);<br>
> -+ }<br>
> - <br>
> - /* Accept cancel is complete. */<br>
> -- if (client->nrecvs > 0)<br>
> -+ if (client->nrecvs > 0) {<br>
> - isc_socket_cancel(client->udpsocket, client->task,<br>
> - ISC_SOCKCANCEL_RECV);<br>
> -+ }<br>
> - <br>
> - /* Still waiting for recv cancel completion. */<br>
> -- if (! (client->nrecvs == 0))<br>
> -+ if (! (client->nrecvs == 0)) {<br>
> - return (true);<br>
> -+ }<br>
> - <br>
> - /* Still waiting for control event to be delivered */<br>
> -- if (client->nctls > 0)<br>
> -+ if (client->nctls > 0) {<br>
> - return (true);<br>
> --<br>
> -- /* Deactivate the client. */<br>
> -- if (client->interface)<br>
> -- ns_interface_detach(&client->interface);<br>
> -+ }<br>
> - <br>
> - INSIST(client->naccepts == 0);<br>
> - INSIST(client->recursionquota == NULL);<br>
> -- if (client->tcplistener != NULL)<br>
> -+ if (client->tcplistener != NULL) {<br>
> - isc_socket_detach(&client->tcplistener);<br>
> - <br>
> -- if (client->udpsocket != NULL)<br>
> -+ if (client->tcpactive) {<br>
> -+ LOCK(&client->interface->lock);<br>
> -+ INSIST(client->interface->ntcpactive > 0);<br>
> -+ client->interface->ntcpactive--;<br>
> -+ UNLOCK(&client->interface->lock);<br>
> -+ client->tcpactive = false;<br>
> -+ }<br>
> -+ }<br>
> -+ if (client->udpsocket != NULL) {<br>
> - isc_socket_detach(&client->udpsocket);<br>
> -+ }<br>
> - <br>
> -- if (client->dispatch != NULL)<br>
> -+ /* Deactivate the client. */<br>
> -+ if (client->interface != NULL) {<br>
> -+ ns_interface_detach(&client->interface);<br>
> -+ }<br>
> -+<br>
> -+ if (client->dispatch != NULL) {<br>
> - dns_dispatch_detach(&client->dispatch);<br>
> -+ }<br>
> - <br>
> - client->attributes = 0;<br>
> - client->mortal = false;<br>
> -@@ -551,10 +607,13 @@ exit_check(ns_client_t *client) {<br>
> - client->newstate = NS_CLIENTSTATE_MAX;<br>
> - if (!ns_g_clienttest && manager != NULL &&<br>
> - !manager->exiting)<br>
> -+ {<br>
> - ISC_QUEUE_PUSH(manager->inactive, client,<br>
> - ilink);<br>
> -- if (client->needshutdown)<br>
> -+ }<br>
> -+ if (client->needshutdown) {<br>
> - isc_task_shutdown(client->task);<br>
> -+ }<br>
> - return (true);<br>
> - }<br>
> - }<br>
> -@@ -675,7 +734,6 @@ client_start(isc_task_t *task, isc_event_t *event) {<br>
> - }<br>
> - }<br>
> - <br>
> --<br>
> - /*%<br>
> - * The client's task has received a shutdown event.<br>
> - */<br>
> -@@ -2507,17 +2565,12 @@ client_request(isc_task_t *task, isc_event_t *event) {<br>
> - /*<br>
> - * Pipeline TCP query processing.<br>
> - */<br>
> -- if (client->message->opcode != dns_opcode_query)<br>
> -+ if (client->message->opcode != dns_opcode_query) {<br>
> - client->pipelined = false;<br>
> -+ }<br>
> - if (TCP_CLIENT(client) && client->pipelined) {<br>
> -- result = isc_quota_reserve(&ns_g_server->tcpquota);<br>
> -- if (result == ISC_R_SUCCESS)<br>
> -- result = ns_client_replace(client);<br>
> -+ result = ns_client_replace(client);<br>
> - if (result != ISC_R_SUCCESS) {<br>
> -- ns_client_log(client, NS_LOGCATEGORY_CLIENT,<br>
> -- NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,<br>
> -- "no more TCP clients(read): %s",<br>
> -- isc_result_totext(result));<br>
> - client->pipelined = false;<br>
> - }<br>
> - }<br>
> -@@ -3087,6 +3140,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {<br>
> - client->filter_aaaa = dns_aaaa_ok;<br>
> - #endif<br>
> - client->needshutdown = ns_g_clienttest;<br>
> -+ client->tcpactive = false;<br>
> - <br>
> - ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,<br>
> - NS_EVENT_CLIENTCONTROL, client_start, client, client,<br>
> -@@ -3100,6 +3154,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {<br>
> - client-><a href="http://formerrcache.id" rel="noreferrer" target="_blank">formerrcache.id</a> = 0;<br>
> - ISC_LINK_INIT(client, link);<br>
> - ISC_LINK_INIT(client, rlink);<br>
> -+ ISC_LINK_INIT(client, glink);<br>
> - ISC_QLINK_INIT(client, ilink);<br>
> - client->keytag = NULL;<br>
> - client->keytag_len = 0;<br>
> -@@ -3193,12 +3248,19 @@ client_newconn(isc_task_t *task, isc_event_t *event) {<br>
> - <br>
> - INSIST(client->state == NS_CLIENTSTATE_READY);<br>
> - <br>
> -+ /*<br>
> -+ * The accept() was successful and we're now establishing a new<br>
> -+ * connection. We need to make note of it in the client and<br>
> -+ * interface objects so client objects can do the right thing<br>
> -+ * when going inactive in exit_check() (see comments in<br>
> -+ * client_accept() for details).<br>
> -+ */<br>
> - INSIST(client->naccepts == 1);<br>
> - client->naccepts--;<br>
> - <br>
> - LOCK(&client->interface->lock);<br>
> -- INSIST(client->interface->ntcpcurrent > 0);<br>
> -- client->interface->ntcpcurrent--;<br>
> -+ INSIST(client->interface->ntcpaccepting > 0);<br>
> -+ client->interface->ntcpaccepting--;<br>
> - UNLOCK(&client->interface->lock);<br>
> - <br>
> - /*<br>
> -@@ -3232,6 +3294,9 @@ client_newconn(isc_task_t *task, isc_event_t *event) {<br>
> - NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),<br>
> - "accept failed: %s",<br>
> - isc_result_totext(nevent->result));<br>
> -+ if (client->tcpquota != NULL) {<br>
> -+ isc_quota_detach(&client->tcpquota);<br>
> -+ }<br>
> - }<br>
> - <br>
> - if (exit_check(client))<br>
> -@@ -3270,18 +3335,12 @@ client_newconn(isc_task_t *task, isc_event_t *event) {<br>
> - * deny service to legitimate TCP clients.<br>
> - */<br>
> - client->pipelined = false;<br>
> -- result = isc_quota_attach(&ns_g_server->tcpquota,<br>
> -- &client->tcpquota);<br>
> -- if (result == ISC_R_SUCCESS)<br>
> -- result = ns_client_replace(client);<br>
> -- if (result != ISC_R_SUCCESS) {<br>
> -- ns_client_log(client, NS_LOGCATEGORY_CLIENT,<br>
> -- NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,<br>
> -- "no more TCP clients(accept): %s",<br>
> -- isc_result_totext(result));<br>
> -- } else if (ns_g_server->keepresporder == NULL ||<br>
> -- !allowed(&netaddr, NULL, NULL, 0, NULL,<br>
> -- ns_g_server->keepresporder)) {<br>
> -+ result = ns_client_replace(client);<br>
> -+ if (result == ISC_R_SUCCESS &&<br>
> -+ (client->sctx->keepresporder == NULL ||<br>
> -+ !allowed(&netaddr, NULL, NULL, 0, NULL,<br>
> -+ ns_g_server->keepresporder)))<br>
> -+ {<br>
> - client->pipelined = true;<br>
> - }<br>
> - <br>
> -@@ -3298,12 +3357,80 @@ client_accept(ns_client_t *client) {<br>
> - <br>
> - CTRACE("accept");<br>
> - <br>
> -+ /*<br>
> -+ * The tcpquota object can only be simultaneously referenced a<br>
> -+ * pre-defined number of times; this is configured by 'tcp-clients'<br>
> -+ * in named.conf. If we can't attach to it here, that means the TCP<br>
> -+ * client quota has been exceeded.<br>
> -+ */<br>
> -+ result = isc_quota_attach(&client->sctx->tcpquota,<br>
> -+ &client->tcpquota);<br>
> -+ if (result != ISC_R_SUCCESS) {<br>
> -+ bool exit;<br>
> -+<br>
> -+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,<br>
> -+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),<br>
> -+ "no more TCP clients: %s",<br>
> -+ isc_result_totext(result));<br>
> -+<br>
> -+ /*<br>
> -+ * We have exceeded the system-wide TCP client<br>
> -+ * quota. But, we can't just block this accept<br>
> -+ * in all cases, because if we did, a heavy TCP<br>
> -+ * load on other interfaces might cause this<br>
> -+ * interface to be starved, with no clients able<br>
> -+ * to accept new connections.<br>
> -+ *<br>
> -+ * So, we check here to see if any other client<br>
> -+ * is already servicing TCP queries on this<br>
> -+ * interface (whether accepting, reading, or<br>
> -+ * processing).<br>
> -+ *<br>
> -+ * If so, then it's okay *not* to call<br>
> -+ * accept - we can let this client to go inactive<br>
> -+ * and the other one handle the next connection<br>
> -+ * when it's ready.<br>
> -+ *<br>
> -+ * But if not, then we need to be a little bit<br>
> -+ * flexible about the quota. We allow *one* extra<br>
> -+ * TCP client through, to ensure we're listening on<br>
> -+ * every interface.<br>
> -+ *<br>
> -+ * (Note: In practice this means that the *real*<br>
> -+ * TCP client quota is tcp-clients plus the number<br>
> -+ * of interfaces.)<br>
> -+ */<br>
> -+ LOCK(&client->interface->lock);<br>
> -+ exit = (client->interface->ntcpactive > 0);<br>
> -+ UNLOCK(&client->interface->lock);<br>
> -+<br>
> -+ if (exit) {<br>
> -+ client->newstate = NS_CLIENTSTATE_INACTIVE;<br>
> -+ (void)exit_check(client);<br>
> -+ return;<br>
> -+ }<br>
> -+ }<br>
> -+<br>
> -+ /*<br>
> -+ * By incrementing the interface's ntcpactive counter we signal<br>
> -+ * that there is at least one client servicing TCP queries for the<br>
> -+ * interface.<br>
> -+ *<br>
> -+ * We also make note of the fact in the client itself with the<br>
> -+ * tcpactive flag. This ensures proper accounting by preventing<br>
> -+ * us from accidentally incrementing or decrementing ntcpactive<br>
> -+ * more than once per client object.<br>
> -+ */<br>
> -+ if (!client->tcpactive) {<br>
> -+ LOCK(&client->interface->lock);<br>
> -+ client->interface->ntcpactive++;<br>
> -+ UNLOCK(&client->interface->lock);<br>
> -+ client->tcpactive = true;<br>
> -+ }<br>
> -+<br>
> - result = isc_socket_accept(client->tcplistener, client->task,<br>
> - client_newconn, client);<br>
> - if (result != ISC_R_SUCCESS) {<br>
> -- UNEXPECTED_ERROR(__FILE__, __LINE__,<br>
> -- "isc_socket_accept() failed: %s",<br>
> -- isc_result_totext(result));<br>
> - /*<br>
> - * XXXRTH What should we do? We're trying to accept but<br>
> - * it didn't work. If we just give up, then TCP<br>
> -@@ -3311,12 +3438,39 @@ client_accept(ns_client_t *client) {<br>
> - *<br>
> - * For now, we just go idle.<br>
> - */<br>
> -+ UNEXPECTED_ERROR(__FILE__, __LINE__,<br>
> -+ "isc_socket_accept() failed: %s",<br>
> -+ isc_result_totext(result));<br>
> -+ if (client->tcpquota != NULL) {<br>
> -+ isc_quota_detach(&client->tcpquota);<br>
> -+ }<br>
> - return;<br>
> - }<br>
> -+<br>
> -+ /*<br>
> -+ * The client's 'naccepts' counter indicates that this client has<br>
> -+ * called accept() and is waiting for a new connection. It should<br>
> -+ * never exceed 1.<br>
> -+ */<br>
> - INSIST(client->naccepts == 0);<br>
> - client->naccepts++;<br>
> -+<br>
> -+ /*<br>
> -+ * The interface's 'ntcpaccepting' counter is incremented when<br>
> -+ * any client calls accept(), and decremented in client_newconn()<br>
> -+ * once the connection is established.<br>
> -+ *<br>
> -+ * When the client object is shutting down after handling a TCP<br>
> -+ * request (see exit_check()), it looks to see whether this value is<br>
> -+ * non-zero. If so, that means another client has already called<br>
> -+ * accept() and is waiting to establish the next connection, which<br>
> -+ * means the first client is free to go inactive. Otherwise,<br>
> -+ * the first client must come back and call accept() again; this<br>
> -+ * guarantees there will always be at least one client listening<br>
> -+ * for new TCP connections on each interface.<br>
> -+ */<br>
> - LOCK(&client->interface->lock);<br>
> -- client->interface->ntcpcurrent++;<br>
> -+ client->interface->ntcpaccepting++;<br>
> - UNLOCK(&client->interface->lock);<br>
> - }<br>
> - <br>
> -@@ -3390,13 +3544,14 @@ ns_client_replace(ns_client_t *client) {<br>
> - tcp = TCP_CLIENT(client);<br>
> - if (tcp && client->pipelined) {<br>
> - result = get_worker(client->manager, client->interface,<br>
> -- client->tcpsocket);<br>
> -+ client->tcpsocket, client);<br>
> - } else {<br>
> - result = get_client(client->manager, client->interface,<br>
> - client->dispatch, tcp);<br>
> - }<br>
> -- if (result != ISC_R_SUCCESS)<br>
> -+ if (result != ISC_R_SUCCESS) {<br>
> - return (result);<br>
> -+ }<br>
> - <br>
> - /*<br>
> - * The responsibility for listening for new requests is hereby<br>
> -@@ -3585,6 +3740,7 @@ get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,<br>
> - client->attributes |= NS_CLIENTATTR_TCP;<br>
> - isc_socket_attach(ifp->tcpsocket,<br>
> - &client->tcplistener);<br>
> -+<br>
> - } else {<br>
> - isc_socket_t *sock;<br>
> - <br>
> -@@ -3602,7 +3758,8 @@ get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,<br>
> - }<br>
> - <br>
> - static isc_result_t<br>
> --get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock)<br>
> -+get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock,<br>
> -+ ns_client_t *oldclient)<br>
> - {<br>
> - isc_result_t result = ISC_R_SUCCESS;<br>
> - isc_event_t *ev;<br>
> -@@ -3610,6 +3767,7 @@ get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock)<br>
> - MTRACE("get worker");<br>
> - <br>
> - REQUIRE(manager != NULL);<br>
> -+ REQUIRE(oldclient != NULL);<br>
> - <br>
> - if (manager->exiting)<br>
> - return (ISC_R_SHUTTINGDOWN);<br>
> -@@ -3642,7 +3800,28 @@ get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock)<br>
> - ns_interface_attach(ifp, &client->interface);<br>
> - client->newstate = client->state = NS_CLIENTSTATE_WORKING;<br>
> - INSIST(client->recursionquota == NULL);<br>
> -- client->tcpquota = &ns_g_server->tcpquota;<br>
> -+<br>
> -+ /*<br>
> -+ * Transfer TCP quota to the new client.<br>
> -+ */<br>
> -+ INSIST(client->tcpquota == NULL);<br>
> -+ INSIST(oldclient->tcpquota != NULL);<br>
> -+ client->tcpquota = oldclient->tcpquota;<br>
> -+ oldclient->tcpquota = NULL;<br>
> -+<br>
> -+ /*<br>
> -+ * Link to a pipeline group, creating it if needed.<br>
> -+ */<br>
> -+ if (!ISC_LINK_LINKED(oldclient, glink)) {<br>
> -+ oldclient->glink.next = NULL;<br>
> -+ oldclient->glink.prev = NULL;<br>
> -+ }<br>
> -+ client->glink.next = oldclient->glink.next;<br>
> -+ client->glink.prev = oldclient;<br>
> -+ if (oldclient->glink.next != NULL) {<br>
> -+ oldclient->glink.next->glink.prev = client;<br>
> -+ }<br>
> -+ oldclient->glink.next = client;<br>
> - <br>
> - client->dscp = ifp->dscp;<br>
> - <br>
> -@@ -3656,6 +3835,12 @@ get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock)<br>
> - (void)isc_socket_getpeername(client->tcpsocket, &client->peeraddr);<br>
> - client->peeraddr_valid = true;<br>
> - <br>
> -+ LOCK(&client->interface->lock);<br>
> -+ client->interface->ntcpactive++;<br>
> -+ UNLOCK(&client->interface->lock);<br>
> -+<br>
> -+ client->tcpactive = true;<br>
> -+<br>
> - INSIST(client->tcpmsg_valid == false);<br>
> - dns_tcpmsg_init(client->mctx, client->tcpsocket, &client->tcpmsg);<br>
> - client->tcpmsg_valid = true;<br>
> -diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h<br>
> -index b23a7b191d..1f7973f9c5 100644<br>
> ---- a/bin/named/include/named/client.h<br>
> -+++ b/bin/named/include/named/client.h<br>
> -@@ -94,7 +94,8 @@ struct ns_client {<br>
> - int nupdates;<br>
> - int nctls;<br>
> - int references;<br>
> -- bool needshutdown; /*<br>
> -+ bool tcpactive;<br>
> -+ bool needshutdown; /*<br>
> - * Used by clienttest to get<br>
> - * the client to go from<br>
> - * inactive to free state<br>
> -@@ -130,9 +131,9 @@ struct ns_client {<br>
> - isc_stdtime_t now;<br>
> - isc_time_t tnow;<br>
> - dns_name_t signername; /*%< [T]SIG key name */<br>
> -- dns_name_t * signer; /*%< NULL if not valid sig */<br>
> -- bool mortal; /*%< Die after handling request */<br>
> -- bool pipelined; /*%< TCP queries not in sequence */<br>
> -+ dns_name_t *signer; /*%< NULL if not valid sig */<br>
> -+ bool mortal; /*%< Die after handling request */<br>
> -+ bool pipelined; /*%< TCP queries not in sequence */<br>
> - isc_quota_t *tcpquota;<br>
> - isc_quota_t *recursionquota;<br>
> - ns_interface_t *interface;<br>
> -@@ -143,8 +144,8 @@ struct ns_client {<br>
> - isc_sockaddr_t destsockaddr;<br>
> - <br>
> - isc_netaddr_t ecs_addr; /*%< EDNS client subnet */<br>
> -- uint8_t ecs_addrlen;<br>
> -- uint8_t ecs_scope;<br>
> -+ uint8_t ecs_addrlen;<br>
> -+ uint8_t ecs_scope;<br>
> - <br>
> - struct in6_pktinfo pktinfo;<br>
> - isc_dscp_t dscp;<br>
> -@@ -166,6 +167,7 @@ struct ns_client {<br>
> - <br>
> - ISC_LINK(ns_client_t) link;<br>
> - ISC_LINK(ns_client_t) rlink;<br>
> -+ ISC_LINK(ns_client_t) glink;<br>
> - ISC_QLINK(ns_client_t) ilink;<br>
> - unsigned char cookie[8];<br>
> - uint32_t expire;<br>
> -diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h<br>
> -index 7d1883e1e8..61b08826a6 100644<br>
> ---- a/bin/named/include/named/interfacemgr.h<br>
> -+++ b/bin/named/include/named/interfacemgr.h<br>
> -@@ -77,9 +77,14 @@ struct ns_interface {<br>
> - /*%< UDP dispatchers. */<br>
> - isc_socket_t * tcpsocket; /*%< TCP socket. */<br>
> - isc_dscp_t dscp; /*%< "listen-on" DSCP value */<br>
> -- int ntcptarget; /*%< Desired number of concurrent<br>
> -- TCP accepts */<br>
> -- int ntcpcurrent; /*%< Current ditto, locked */<br>
> -+ int ntcpaccepting; /*%< Number of clients<br>
> -+ ready to accept new<br>
> -+ TCP connections on this<br>
> -+ interface */<br>
> -+ int ntcpactive; /*%< Number of clients<br>
> -+ servicing TCP queries<br>
> -+ (whether accepting or<br>
> -+ connected) */<br>
> - int nudpdispatch; /*%< Number of UDP dispatches */<br>
> - ns_clientmgr_t * clientmgr; /*%< Client manager. */<br>
> - ISC_LINK(ns_interface_t) link;<br>
> -diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c<br>
> -index 419927bf54..955096ef47 100644<br>
> ---- a/bin/named/interfacemgr.c<br>
> -+++ b/bin/named/interfacemgr.c<br>
> -@@ -386,8 +386,8 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,<br>
> - * connections will be handled in parallel even though there is<br>
> - * only one client initially.<br>
> - */<br>
> -- ifp->ntcptarget = 1;<br>
> -- ifp->ntcpcurrent = 0;<br>
> -+ ifp->ntcpaccepting = 0;<br>
> -+ ifp->ntcpactive = 0;<br>
> - ifp->nudpdispatch = 0;<br>
> - <br>
> - ifp->dscp = -1;<br>
> -@@ -522,9 +522,7 @@ ns_interface_accepttcp(ns_interface_t *ifp) {<br>
> - */<br>
> - (void)isc_socket_filter(ifp->tcpsocket, "dataready");<br>
> - <br>
> -- result = ns_clientmgr_createclients(ifp->clientmgr,<br>
> -- ifp->ntcptarget, ifp,<br>
> -- true);<br>
> -+ result = ns_clientmgr_createclients(ifp->clientmgr, 1, ifp, true);<br>
> - if (result != ISC_R_SUCCESS) {<br>
> - UNEXPECTED_ERROR(__FILE__, __LINE__,<br>
> - "TCP ns_clientmgr_createclients(): %s",<br>
> --- <br>
> -2.20.1<br>
> -<br>
> diff --git a/meta/recipes-connectivity/bind/bind/0003-use-reference-counter-for-pipeline-groups-v3.patch b/meta/recipes-connectivity/bind/bind/0003-use-reference-counter-for-pipeline-groups-v3.patch<br>
> deleted file mode 100644<br>
> index 032cfb8c442..00000000000<br>
> --- a/meta/recipes-connectivity/bind/bind/0003-use-reference-counter-for-pipeline-groups-v3.patch<br>
> +++ /dev/null<br>
> @@ -1,278 +0,0 @@<br>
> -Backport patch to fix CVE-2018-5743.<br>
> -<br>
> -Ref:<br>
> -<a href="https://security-tracker.debian.org/tracker/CVE-2018-5743" rel="noreferrer" target="_blank">https://security-tracker.debian.org/tracker/CVE-2018-5743</a><br>
> -<br>
> -CVE: CVE-2018-5743<br>
> -Upstream-Status: Backport [<a href="https://gitlab.isc.org/isc-projects/bind9/commit/366b4e1" rel="noreferrer" target="_blank">https://gitlab.isc.org/isc-projects/bind9/commit/366b4e1</a>]<br>
> -<br>
> -Signed-off-by: Kai Kang <<a href="mailto:kai.kang@windriver.com" target="_blank">kai.kang@windriver.com</a>><br>
> -<br>
> -From 366b4e1ede8aed690e981e07137cb1cb77879c36 Mon Sep 17 00:00:00 2001<br>
> -From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= <<a href="mailto:michal@isc.org" target="_blank">michal@isc.org</a>><br>
> -Date: Thu, 17 Jan 2019 15:53:38 +0100<br>
> -Subject: [PATCH 3/6] use reference counter for pipeline groups (v3)<br>
> -<br>
> -Track pipeline groups using a shared reference counter<br>
> -instead of a linked list.<br>
> -<br>
> -(cherry picked from commit 513afd33eb17d5dc41a3f0d2d38204ef8c5f6f91)<br>
> -(cherry picked from commit 9446629b730c59c4215f08d37fbaf810282fbccb)<br>
> ----<br>
> - bin/named/client.c | 171 ++++++++++++++++++++-----------<br>
> - bin/named/include/named/client.h | 2 +-<br>
> - 2 files changed, 110 insertions(+), 63 deletions(-)<br>
> -<br>
> -diff --git a/bin/named/client.c b/bin/named/client.c<br>
> -index a7b49a0f71..277656cef0 100644<br>
> ---- a/bin/named/client.c<br>
> -+++ b/bin/named/client.c<br>
> -@@ -299,6 +299,75 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds) {<br>
> - }<br>
> - }<br>
> - <br>
> -+/*%<br>
> -+ * Allocate a reference counter that will track the number of client structures<br>
> -+ * using the TCP connection that 'client' called accept() for. This counter<br>
> -+ * will be shared between all client structures associated with this TCP<br>
> -+ * connection.<br>
> -+ */<br>
> -+static void<br>
> -+pipeline_init(ns_client_t *client) {<br>
> -+ isc_refcount_t *refs;<br>
> -+<br>
> -+ REQUIRE(client->pipeline_refs == NULL);<br>
> -+<br>
> -+ /*<br>
> -+ * A global memory context is used for the allocation as different<br>
> -+ * client structures may have different memory contexts assigned and a<br>
> -+ * reference counter allocated here might need to be freed by a<br>
> -+ * different client. The performance impact caused by memory context<br>
> -+ * contention here is expected to be negligible, given that this code<br>
> -+ * is only executed for TCP connections.<br>
> -+ */<br>
> -+ refs = isc_mem_allocate(client->sctx->mctx, sizeof(*refs));<br>
> -+ isc_refcount_init(refs, 1);<br>
> -+ client->pipeline_refs = refs;<br>
> -+}<br>
> -+<br>
> -+/*%<br>
> -+ * Increase the count of client structures using the TCP connection that<br>
> -+ * 'source' is associated with and put a pointer to that count in 'target',<br>
> -+ * thus associating it with the same TCP connection.<br>
> -+ */<br>
> -+static void<br>
> -+pipeline_attach(ns_client_t *source, ns_client_t *target) {<br>
> -+ int old_refs;<br>
> -+<br>
> -+ REQUIRE(source->pipeline_refs != NULL);<br>
> -+ REQUIRE(target->pipeline_refs == NULL);<br>
> -+<br>
> -+ old_refs = isc_refcount_increment(source->pipeline_refs);<br>
> -+ INSIST(old_refs > 0);<br>
> -+ target->pipeline_refs = source->pipeline_refs;<br>
> -+}<br>
> -+<br>
> -+/*%<br>
> -+ * Decrease the count of client structures using the TCP connection that<br>
> -+ * 'client' is associated with. If this is the last client using this TCP<br>
> -+ * connection, free the reference counter and return true; otherwise, return<br>
> -+ * false.<br>
> -+ */<br>
> -+static bool<br>
> -+pipeline_detach(ns_client_t *client) {<br>
> -+ isc_refcount_t *refs;<br>
> -+ int old_refs;<br>
> -+<br>
> -+ REQUIRE(client->pipeline_refs != NULL);<br>
> -+<br>
> -+ refs = client->pipeline_refs;<br>
> -+ client->pipeline_refs = NULL;<br>
> -+<br>
> -+ old_refs = isc_refcount_decrement(refs);<br>
> -+ INSIST(old_refs > 0);<br>
> -+<br>
> -+ if (old_refs == 1) {<br>
> -+ isc_mem_free(client->sctx->mctx, refs);<br>
> -+ return (true);<br>
> -+ }<br>
> -+<br>
> -+ return (false);<br>
> -+}<br>
> -+<br>
> - /*%<br>
> - * Check for a deactivation or shutdown request and take appropriate<br>
> - * action. Returns true if either is in progress; in this case<br>
> -@@ -421,6 +490,40 @@ exit_check(ns_client_t *client) {<br>
> - client->tcpmsg_valid = false;<br>
> - }<br>
> - <br>
> -+ if (client->tcpquota != NULL) {<br>
> -+ if (client->pipeline_refs == NULL ||<br>
> -+ pipeline_detach(client))<br>
> -+ {<br>
> -+ /*<br>
> -+ * Only detach from the TCP client quota if<br>
> -+ * there are no more client structures using<br>
> -+ * this TCP connection.<br>
> -+ *<br>
> -+ * Note that we check 'pipeline_refs' and not<br>
> -+ * 'pipelined' because in some cases (e.g.<br>
> -+ * after receiving a request with an opcode<br>
> -+ * different than QUERY) 'pipelined' is set to<br>
> -+ * false after the reference counter gets<br>
> -+ * allocated in pipeline_init() and we must<br>
> -+ * still drop our reference as failing to do so<br>
> -+ * would prevent the reference counter itself<br>
> -+ * from being freed.<br>
> -+ */<br>
> -+ isc_quota_detach(&client->tcpquota);<br>
> -+ } else {<br>
> -+ /*<br>
> -+ * There are other client structures using this<br>
> -+ * TCP connection, so we cannot detach from the<br>
> -+ * TCP client quota to prevent excess TCP<br>
> -+ * connections from being accepted. However,<br>
> -+ * this client structure might later be reused<br>
> -+ * for accepting new connections and thus must<br>
> -+ * have its 'tcpquota' field set to NULL.<br>
> -+ */<br>
> -+ client->tcpquota = NULL;<br>
> -+ }<br>
> -+ }<br>
> -+<br>
> - if (client->tcpsocket != NULL) {<br>
> - CTRACE("closetcp");<br>
> - isc_socket_detach(&client->tcpsocket);<br>
> -@@ -434,44 +537,6 @@ exit_check(ns_client_t *client) {<br>
> - }<br>
> - }<br>
> - <br>
> -- if (client->tcpquota != NULL) {<br>
> -- /*<br>
> -- * If we are not in a pipeline group, or<br>
> -- * we are the last client in the group, detach from<br>
> -- * tcpquota; otherwise, transfer the quota to<br>
> -- * another client in the same group.<br>
> -- */<br>
> -- if (!ISC_LINK_LINKED(client, glink) ||<br>
> -- (client->glink.next == NULL &&<br>
> -- client->glink.prev == NULL))<br>
> -- {<br>
> -- isc_quota_detach(&client->tcpquota);<br>
> -- } else if (client->glink.next != NULL) {<br>
> -- INSIST(client->glink.next->tcpquota == NULL);<br>
> -- client->glink.next->tcpquota = client->tcpquota;<br>
> -- client->tcpquota = NULL;<br>
> -- } else {<br>
> -- INSIST(client->glink.prev->tcpquota == NULL);<br>
> -- client->glink.prev->tcpquota = client->tcpquota;<br>
> -- client->tcpquota = NULL;<br>
> -- }<br>
> -- }<br>
> --<br>
> -- /*<br>
> -- * Unlink from pipeline group.<br>
> -- */<br>
> -- if (ISC_LINK_LINKED(client, glink)) {<br>
> -- if (client->glink.next != NULL) {<br>
> -- client->glink.next->glink.prev =<br>
> -- client->glink.prev;<br>
> -- }<br>
> -- if (client->glink.prev != NULL) {<br>
> -- client->glink.prev->glink.next =<br>
> -- client->glink.next;<br>
> -- }<br>
> -- ISC_LINK_INIT(client, glink);<br>
> -- }<br>
> --<br>
> - if (client->timerset) {<br>
> - (void)isc_timer_reset(client->timer,<br>
> - isc_timertype_inactive,<br>
> -@@ -3130,6 +3195,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {<br>
> - dns_name_init(&client->signername, NULL);<br>
> - client->mortal = false;<br>
> - client->pipelined = false;<br>
> -+ client->pipeline_refs = NULL;<br>
> - client->tcpquota = NULL;<br>
> - client->recursionquota = NULL;<br>
> - client->interface = NULL;<br>
> -@@ -3154,7 +3220,6 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {<br>
> - client-><a href="http://formerrcache.id" rel="noreferrer" target="_blank">formerrcache.id</a> = 0;<br>
> - ISC_LINK_INIT(client, link);<br>
> - ISC_LINK_INIT(client, rlink);<br>
> -- ISC_LINK_INIT(client, glink);<br>
> - ISC_QLINK_INIT(client, ilink);<br>
> - client->keytag = NULL;<br>
> - client->keytag_len = 0;<br>
> -@@ -3341,6 +3406,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) {<br>
> - !allowed(&netaddr, NULL, NULL, 0, NULL,<br>
> - ns_g_server->keepresporder)))<br>
> - {<br>
> -+ pipeline_init(client);<br>
> - client->pipelined = true;<br>
> - }<br>
> - <br>
> -@@ -3800,35 +3866,16 @@ get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock,<br>
> - ns_interface_attach(ifp, &client->interface);<br>
> - client->newstate = client->state = NS_CLIENTSTATE_WORKING;<br>
> - INSIST(client->recursionquota == NULL);<br>
> --<br>
> -- /*<br>
> -- * Transfer TCP quota to the new client.<br>
> -- */<br>
> -- INSIST(client->tcpquota == NULL);<br>
> -- INSIST(oldclient->tcpquota != NULL);<br>
> -- client->tcpquota = oldclient->tcpquota;<br>
> -- oldclient->tcpquota = NULL;<br>
> --<br>
> -- /*<br>
> -- * Link to a pipeline group, creating it if needed.<br>
> -- */<br>
> -- if (!ISC_LINK_LINKED(oldclient, glink)) {<br>
> -- oldclient->glink.next = NULL;<br>
> -- oldclient->glink.prev = NULL;<br>
> -- }<br>
> -- client->glink.next = oldclient->glink.next;<br>
> -- client->glink.prev = oldclient;<br>
> -- if (oldclient->glink.next != NULL) {<br>
> -- oldclient->glink.next->glink.prev = client;<br>
> -- }<br>
> -- oldclient->glink.next = client;<br>
> -+ client->tcpquota = &client->sctx->tcpquota;<br>
> - <br>
> - client->dscp = ifp->dscp;<br>
> - <br>
> - client->attributes |= NS_CLIENTATTR_TCP;<br>
> -- client->pipelined = true;<br>
> - client->mortal = true;<br>
> - <br>
> -+ pipeline_attach(oldclient, client);<br>
> -+ client->pipelined = true;<br>
> -+<br>
> - isc_socket_attach(ifp->tcpsocket, &client->tcplistener);<br>
> - isc_socket_attach(sock, &client->tcpsocket);<br>
> - isc_socket_setname(client->tcpsocket, "worker-tcp", NULL);<br>
> -diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h<br>
> -index 1f7973f9c5..aeed9ccdda 100644<br>
> ---- a/bin/named/include/named/client.h<br>
> -+++ b/bin/named/include/named/client.h<br>
> -@@ -134,6 +134,7 @@ struct ns_client {<br>
> - dns_name_t *signer; /*%< NULL if not valid sig */<br>
> - bool mortal; /*%< Die after handling request */<br>
> - bool pipelined; /*%< TCP queries not in sequence */<br>
> -+ isc_refcount_t *pipeline_refs;<br>
> - isc_quota_t *tcpquota;<br>
> - isc_quota_t *recursionquota;<br>
> - ns_interface_t *interface;<br>
> -@@ -167,7 +168,6 @@ struct ns_client {<br>
> - <br>
> - ISC_LINK(ns_client_t) link;<br>
> - ISC_LINK(ns_client_t) rlink;<br>
> -- ISC_LINK(ns_client_t) glink;<br>
> - ISC_QLINK(ns_client_t) ilink;<br>
> - unsigned char cookie[8];<br>
> - uint32_t expire;<br>
> --- <br>
> -2.20.1<br>
> -<br>
> diff --git a/meta/recipes-connectivity/bind/bind/0004-better-tcpquota-accounting-and-client-mortality-chec.patch b/meta/recipes-connectivity/bind/bind/0004-better-tcpquota-accounting-and-client-mortality-chec.patch<br>
> deleted file mode 100644<br>
> index 034ab13303b..00000000000<br>
> --- a/meta/recipes-connectivity/bind/bind/0004-better-tcpquota-accounting-and-client-mortality-chec.patch<br>
> +++ /dev/null<br>
> @@ -1,512 +0,0 @@<br>
> -Backport patch to fix CVE-2018-5743.<br>
> -<br>
> -Ref:<br>
> -<a href="https://security-tracker.debian.org/tracker/CVE-2018-5743" rel="noreferrer" target="_blank">https://security-tracker.debian.org/tracker/CVE-2018-5743</a><br>
> -<br>
> -CVE: CVE-2018-5743<br>
> -Upstream-Status: Backport [<a href="https://gitlab.isc.org/isc-projects/bind9/commit/2ab8a08" rel="noreferrer" target="_blank">https://gitlab.isc.org/isc-projects/bind9/commit/2ab8a08</a>]<br>
> -<br>
> -Signed-off-by: Kai Kang <<a href="mailto:kai.kang@windriver.com" target="_blank">kai.kang@windriver.com</a>><br>
> -<br>
> -From 2ab8a085b3c666f28f1f9229bd6ecb59915b26c3 Mon Sep 17 00:00:00 2001<br>
> -From: Evan Hunt <<a href="mailto:each@isc.org" target="_blank">each@isc.org</a>><br>
> -Date: Fri, 5 Apr 2019 16:12:18 -0700<br>
> -Subject: [PATCH 4/6] better tcpquota accounting and client mortality checks<br>
> -<br>
> -- ensure that tcpactive is cleaned up correctly when accept() fails.<br>
> -- set 'client->tcpattached' when the client is attached to the tcpquota.<br>
> - carry this value on to new clients sharing the same pipeline group.<br>
> - don't call isc_quota_detach() on the tcpquota unless tcpattached is<br>
> - set. this way clients that were allowed to accept TCP connections<br>
> - despite being over quota (and therefore, were never attached to the<br>
> - quota) will not inadvertently detach from it and mess up the<br>
> - accounting.<br>
> -- simplify the code for tcpquota disconnection by using a new function<br>
> - tcpquota_disconnect().<br>
> -- before deciding whether to reject a new connection due to quota<br>
> - exhaustion, check to see whether there are at least two active<br>
> - clients. previously, this was "at least one", but that could be<br>
> - insufficient if there was one other client in READING state (waiting<br>
> - for messages on an open connection) but none in READY (listening<br>
> - for new connections).<br>
> -- before deciding whether a TCP client object can to go inactive, we<br>
> - must ensure there are enough other clients to maintain service<br>
> - afterward -- both accepting new connections and reading/processing new<br>
> - queries. A TCP client can't shut down unless at least one<br>
> - client is accepting new connections and (in the case of pipelined<br>
> - clients) at least one additional client is waiting to read.<br>
> -<br>
> -(cherry picked from commit c7394738b2445c16f728a88394864dd61baad900)<br>
> -(cherry picked from commit e965d5f11d3d0f6d59704e614fceca2093cb1856)<br>
> -(cherry picked from commit 87d431161450777ea093821212abfb52d51b36e3)<br>
> ----<br>
> - bin/named/client.c | 244 +++++++++++++++++++------------<br>
> - bin/named/include/named/client.h | 3 +-<br>
> - 2 files changed, 152 insertions(+), 95 deletions(-)<br>
> -<br>
> -diff --git a/bin/named/client.c b/bin/named/client.c<br>
> -index 277656cef0..61e96dd28c 100644<br>
> ---- a/bin/named/client.c<br>
> -+++ b/bin/named/client.c<br>
> -@@ -244,13 +244,14 @@ static void client_start(isc_task_t *task, isc_event_t *event);<br>
> - static void client_request(isc_task_t *task, isc_event_t *event);<br>
> - static void ns_client_dumpmessage(ns_client_t *client, const char *reason);<br>
> - static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,<br>
> -- dns_dispatch_t *disp, bool tcp);<br>
> -+ dns_dispatch_t *disp, ns_client_t *oldclient,<br>
> -+ bool tcp);<br>
> - static isc_result_t get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp,<br>
> - isc_socket_t *sock, ns_client_t *oldclient);<br>
> - static inline bool<br>
> - allowed(isc_netaddr_t *addr, dns_name_t *signer,<br>
> - isc_netaddr_t *ecs_addr, uint8_t ecs_addrlen,<br>
> -- uint8_t *ecs_scope, dns_acl_t *acl)<br>
> -+ uint8_t *ecs_scope, dns_acl_t *acl);<br>
> - static void compute_cookie(ns_client_t *client, uint32_t when,<br>
> - uint32_t nonce, const unsigned char *secret,<br>
> - isc_buffer_t *buf);<br>
> -@@ -319,7 +320,7 @@ pipeline_init(ns_client_t *client) {<br>
> - * contention here is expected to be negligible, given that this code<br>
> - * is only executed for TCP connections.<br>
> - */<br>
> -- refs = isc_mem_allocate(client->sctx->mctx, sizeof(*refs));<br>
> -+ refs = isc_mem_allocate(ns_g_mctx, sizeof(*refs));<br>
> - isc_refcount_init(refs, 1);<br>
> - client->pipeline_refs = refs;<br>
> - }<br>
> -@@ -331,13 +332,13 @@ pipeline_init(ns_client_t *client) {<br>
> - */<br>
> - static void<br>
> - pipeline_attach(ns_client_t *source, ns_client_t *target) {<br>
> -- int old_refs;<br>
> -+ int refs;<br>
> - <br>
> - REQUIRE(source->pipeline_refs != NULL);<br>
> - REQUIRE(target->pipeline_refs == NULL);<br>
> - <br>
> -- old_refs = isc_refcount_increment(source->pipeline_refs);<br>
> -- INSIST(old_refs > 0);<br>
> -+ isc_refcount_increment(source->pipeline_refs, &refs);<br>
> -+ INSIST(refs > 1);<br>
> - target->pipeline_refs = source->pipeline_refs;<br>
> - }<br>
> - <br>
> -@@ -349,25 +350,51 @@ pipeline_attach(ns_client_t *source, ns_client_t *target) {<br>
> - */<br>
> - static bool<br>
> - pipeline_detach(ns_client_t *client) {<br>
> -- isc_refcount_t *refs;<br>
> -- int old_refs;<br>
> -+ isc_refcount_t *refcount;<br>
> -+ int refs;<br>
> - <br>
> - REQUIRE(client->pipeline_refs != NULL);<br>
> - <br>
> -- refs = client->pipeline_refs;<br>
> -+ refcount = client->pipeline_refs;<br>
> - client->pipeline_refs = NULL;<br>
> - <br>
> -- old_refs = isc_refcount_decrement(refs);<br>
> -- INSIST(old_refs > 0);<br>
> -+ isc_refcount_decrement(refcount, refs);<br>
> - <br>
> -- if (old_refs == 1) {<br>
> -- isc_mem_free(client->sctx->mctx, refs);<br>
> -+ if (refs == 0) {<br>
> -+ isc_mem_free(ns_g_mctx, refs);<br>
> - return (true);<br>
> - }<br>
> - <br>
> - return (false);<br>
> - }<br>
> - <br>
> -+/*<br>
> -+ * Detach a client from the TCP client quota if appropriate, and set<br>
> -+ * the quota pointer to NULL.<br>
> -+ *<br>
> -+ * Sometimes when the TCP client quota is exhausted but there are no other<br>
> -+ * clients servicing the interface, a client will be allowed to continue<br>
> -+ * running despite not having been attached to the quota. In this event,<br>
> -+ * the TCP quota was never attached to the client, so when the client (or<br>
> -+ * associated pipeline group) shuts down, the quota must NOT be detached.<br>
> -+ *<br>
> -+ * Otherwise, if the quota pointer is set, it should be detached. If not<br>
> -+ * set at all, we just return without doing anything.<br>
> -+ */<br>
> -+static void<br>
> -+tcpquota_disconnect(ns_client_t *client) {<br>
> -+ if (client->tcpquota == NULL) {<br>
> -+ return;<br>
> -+ }<br>
> -+<br>
> -+ if (client->tcpattached) {<br>
> -+ isc_quota_detach(&client->tcpquota);<br>
> -+ client->tcpattached = false;<br>
> -+ } else {<br>
> -+ client->tcpquota = NULL;<br>
> -+ }<br>
> -+}<br>
> -+<br>
> - /*%<br>
> - * Check for a deactivation or shutdown request and take appropriate<br>
> - * action. Returns true if either is in progress; in this case<br>
> -@@ -490,38 +517,31 @@ exit_check(ns_client_t *client) {<br>
> - client->tcpmsg_valid = false;<br>
> - }<br>
> - <br>
> -- if (client->tcpquota != NULL) {<br>
> -- if (client->pipeline_refs == NULL ||<br>
> -- pipeline_detach(client))<br>
> -- {<br>
> -- /*<br>
> -- * Only detach from the TCP client quota if<br>
> -- * there are no more client structures using<br>
> -- * this TCP connection.<br>
> -- *<br>
> -- * Note that we check 'pipeline_refs' and not<br>
> -- * 'pipelined' because in some cases (e.g.<br>
> -- * after receiving a request with an opcode<br>
> -- * different than QUERY) 'pipelined' is set to<br>
> -- * false after the reference counter gets<br>
> -- * allocated in pipeline_init() and we must<br>
> -- * still drop our reference as failing to do so<br>
> -- * would prevent the reference counter itself<br>
> -- * from being freed.<br>
> -- */<br>
> -- isc_quota_detach(&client->tcpquota);<br>
> -- } else {<br>
> -- /*<br>
> -- * There are other client structures using this<br>
> -- * TCP connection, so we cannot detach from the<br>
> -- * TCP client quota to prevent excess TCP<br>
> -- * connections from being accepted. However,<br>
> -- * this client structure might later be reused<br>
> -- * for accepting new connections and thus must<br>
> -- * have its 'tcpquota' field set to NULL.<br>
> -- */<br>
> -- client->tcpquota = NULL;<br>
> -- }<br>
> -+ /*<br>
> -+ * Detach from pipeline group and from TCP client quota,<br>
> -+ * if appropriate.<br>
> -+ *<br>
> -+ * - If no pipeline group is active, attempt to<br>
> -+ * detach from the TCP client quota.<br>
> -+ *<br>
> -+ * - If a pipeline group is active, detach from it;<br>
> -+ * if the return code indicates that there no more<br>
> -+ * clients left if this pipeline group, we also detach<br>
> -+ * from the TCP client quota.<br>
> -+ *<br>
> -+ * - Otherwise we don't try to detach, we just set the<br>
> -+ * TCP quota pointer to NULL if it wasn't NULL already.<br>
> -+ *<br>
> -+ * tcpquota_disconnect() will set tcpquota to NULL, either<br>
> -+ * by detaching it or by assignment, depending on the<br>
> -+ * needs of the client. See the comments on that function<br>
> -+ * for further information.<br>
> -+ */<br>
> -+ if (client->pipeline_refs == NULL || pipeline_detach(client)) {<br>
> -+ tcpquota_disconnect(client);<br>
> -+ } else {<br>
> -+ client->tcpquota = NULL;<br>
> -+ client->tcpattached = false;<br>
> - }<br>
> - <br>
> - if (client->tcpsocket != NULL) {<br>
> -@@ -544,8 +564,6 @@ exit_check(ns_client_t *client) {<br>
> - client->timerset = false;<br>
> - }<br>
> - <br>
> -- client->pipelined = false;<br>
> --<br>
> - client->peeraddr_valid = false;<br>
> - <br>
> - client->state = NS_CLIENTSTATE_READY;<br>
> -@@ -558,18 +576,27 @@ exit_check(ns_client_t *client) {<br>
> - * active and force it to go inactive if not.<br>
> - *<br>
> - * UDP clients go inactive at this point, but a TCP client<br>
> -- * will needs to remain active if no other clients are<br>
> -- * listening for TCP requests on this interface, to<br>
> -- * prevent this interface from going nonresponsive.<br>
> -+ * may need to remain active and go into ready state if<br>
> -+ * no other clients are available to listen for TCP<br>
> -+ * requests on this interface or (in the case of pipelined<br>
> -+ * clients) to read for additional messages on the current<br>
> -+ * connection.<br>
> - */<br>
> - if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) {<br>
> - LOCK(&client->interface->lock);<br>
> -- if (client->interface->ntcpaccepting == 0) {<br>
> -+ if ((client->interface->ntcpaccepting == 0 ||<br>
> -+ (client->pipelined &&<br>
> -+ client->interface->ntcpactive < 2)) &&<br>
> -+ client->newstate != NS_CLIENTSTATE_FREED)<br>
> -+ {<br>
> - client->mortal = false;<br>
> -+ client->newstate = NS_CLIENTSTATE_READY;<br>
> - }<br>
> - UNLOCK(&client->interface->lock);<br>
> - }<br>
> - <br>
> -+ client->pipelined = false;<br>
> -+<br>
> - /*<br>
> - * We don't need the client; send it to the inactive<br>
> - * queue for recycling.<br>
> -@@ -2634,6 +2661,18 @@ client_request(isc_task_t *task, isc_event_t *event) {<br>
> - client->pipelined = false;<br>
> - }<br>
> - if (TCP_CLIENT(client) && client->pipelined) {<br>
> -+ /*<br>
> -+ * We're pipelining. Replace the client; the<br>
> -+ * the replacement can read the TCP socket looking<br>
> -+ * for new messages and this client can process the<br>
> -+ * current message asynchronously.<br>
> -+ *<br>
> -+ * There are now at least three clients using this<br>
> -+ * TCP socket - one accepting new connections,<br>
> -+ * one reading an existing connection to get new<br>
> -+ * messages, and one answering the message already<br>
> -+ * received.<br>
> -+ */<br>
> - result = ns_client_replace(client);<br>
> - if (result != ISC_R_SUCCESS) {<br>
> - client->pipelined = false;<br>
> -@@ -3197,6 +3236,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {<br>
> - client->pipelined = false;<br>
> - client->pipeline_refs = NULL;<br>
> - client->tcpquota = NULL;<br>
> -+ client->tcpattached = false;<br>
> - client->recursionquota = NULL;<br>
> - client->interface = NULL;<br>
> - client->peeraddr_valid = false;<br>
> -@@ -3359,9 +3399,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) {<br>
> - NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),<br>
> - "accept failed: %s",<br>
> - isc_result_totext(nevent->result));<br>
> -- if (client->tcpquota != NULL) {<br>
> -- isc_quota_detach(&client->tcpquota);<br>
> -- }<br>
> -+ tcpquota_disconnect(client);<br>
> - }<br>
> - <br>
> - if (exit_check(client))<br>
> -@@ -3402,7 +3440,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) {<br>
> - client->pipelined = false;<br>
> - result = ns_client_replace(client);<br>
> - if (result == ISC_R_SUCCESS &&<br>
> -- (client->sctx->keepresporder == NULL ||<br>
> -+ (ns_g_server->keepresporder == NULL ||<br>
> - !allowed(&netaddr, NULL, NULL, 0, NULL,<br>
> - ns_g_server->keepresporder)))<br>
> - {<br>
> -@@ -3429,7 +3467,7 @@ client_accept(ns_client_t *client) {<br>
> - * in named.conf. If we can't attach to it here, that means the TCP<br>
> - * client quota has been exceeded.<br>
> - */<br>
> -- result = isc_quota_attach(&client->sctx->tcpquota,<br>
> -+ result = isc_quota_attach(&ns_g_server->tcpquota,<br>
> - &client->tcpquota);<br>
> - if (result != ISC_R_SUCCESS) {<br>
> - bool exit;<br>
> -@@ -3447,27 +3485,27 @@ client_accept(ns_client_t *client) {<br>
> - * interface to be starved, with no clients able<br>
> - * to accept new connections.<br>
> - *<br>
> -- * So, we check here to see if any other client<br>
> -- * is already servicing TCP queries on this<br>
> -+ * So, we check here to see if any other clients<br>
> -+ * are already servicing TCP queries on this<br>
> - * interface (whether accepting, reading, or<br>
> -- * processing).<br>
> -- *<br>
> -- * If so, then it's okay *not* to call<br>
> -- * accept - we can let this client to go inactive<br>
> -- * and the other one handle the next connection<br>
> -- * when it's ready.<br>
> -+ * processing). If there are at least two<br>
> -+ * (one reading and one processing a request)<br>
> -+ * then it's okay *not* to call accept - we<br>
> -+ * can let this client go inactive and another<br>
> -+ * one will resume accepting when it's done.<br>
> - *<br>
> -- * But if not, then we need to be a little bit<br>
> -- * flexible about the quota. We allow *one* extra<br>
> -- * TCP client through, to ensure we're listening on<br>
> -- * every interface.<br>
> -+ * If there aren't enough active clients on the<br>
> -+ * interface, then we can be a little bit<br>
> -+ * flexible about the quota. We'll allow *one*<br>
> -+ * extra client through to ensure we're listening<br>
> -+ * on every interface.<br>
> - *<br>
> -- * (Note: In practice this means that the *real*<br>
> -- * TCP client quota is tcp-clients plus the number<br>
> -- * of interfaces.)<br>
> -+ * (Note: In practice this means that the real<br>
> -+ * TCP client quota is tcp-clients plus the<br>
> -+ * number of listening interfaces plus 2.)<br>
> - */<br>
> - LOCK(&client->interface->lock);<br>
> -- exit = (client->interface->ntcpactive > 0);<br>
> -+ exit = (client->interface->ntcpactive > 1);<br>
> - UNLOCK(&client->interface->lock);<br>
> - <br>
> - if (exit) {<br>
> -@@ -3475,6 +3513,9 @@ client_accept(ns_client_t *client) {<br>
> - (void)exit_check(client);<br>
> - return;<br>
> - }<br>
> -+<br>
> -+ } else {<br>
> -+ client->tcpattached = true;<br>
> - }<br>
> - <br>
> - /*<br>
> -@@ -3507,9 +3548,16 @@ client_accept(ns_client_t *client) {<br>
> - UNEXPECTED_ERROR(__FILE__, __LINE__,<br>
> - "isc_socket_accept() failed: %s",<br>
> - isc_result_totext(result));<br>
> -- if (client->tcpquota != NULL) {<br>
> -- isc_quota_detach(&client->tcpquota);<br>
> -+<br>
> -+ tcpquota_disconnect(client);<br>
> -+<br>
> -+ if (client->tcpactive) {<br>
> -+ LOCK(&client->interface->lock);<br>
> -+ client->interface->ntcpactive--;<br>
> -+ UNLOCK(&client->interface->lock);<br>
> -+ client->tcpactive = false;<br>
> - }<br>
> -+<br>
> - return;<br>
> - }<br>
> - <br>
> -@@ -3527,13 +3575,12 @@ client_accept(ns_client_t *client) {<br>
> - * once the connection is established.<br>
> - *<br>
> - * When the client object is shutting down after handling a TCP<br>
> -- * request (see exit_check()), it looks to see whether this value is<br>
> -- * non-zero. If so, that means another client has already called<br>
> -- * accept() and is waiting to establish the next connection, which<br>
> -- * means the first client is free to go inactive. Otherwise,<br>
> -- * the first client must come back and call accept() again; this<br>
> -- * guarantees there will always be at least one client listening<br>
> -- * for new TCP connections on each interface.<br>
> -+ * request (see exit_check()), if this value is at least one, that<br>
> -+ * means another client has called accept() and is waiting to<br>
> -+ * establish the next connection. That means the client may be<br>
> -+ * be free to become inactive; otherwise it may need to start<br>
> -+ * listening for connections itself to prevent the interface<br>
> -+ * going dead.<br>
> - */<br>
> - LOCK(&client->interface->lock);<br>
> - client->interface->ntcpaccepting++;<br>
> -@@ -3613,19 +3660,19 @@ ns_client_replace(ns_client_t *client) {<br>
> - client->tcpsocket, client);<br>
> - } else {<br>
> - result = get_client(client->manager, client->interface,<br>
> -- client->dispatch, tcp);<br>
> -+ client->dispatch, client, tcp);<br>
> -+<br>
> -+ /*<br>
> -+ * The responsibility for listening for new requests is hereby<br>
> -+ * transferred to the new client. Therefore, the old client<br>
> -+ * should refrain from listening for any more requests.<br>
> -+ */<br>
> -+ client->mortal = true;<br>
> - }<br>
> - if (result != ISC_R_SUCCESS) {<br>
> - return (result);<br>
> - }<br>
> - <br>
> -- /*<br>
> -- * The responsibility for listening for new requests is hereby<br>
> -- * transferred to the new client. Therefore, the old client<br>
> -- * should refrain from listening for any more requests.<br>
> -- */<br>
> -- client->mortal = true;<br>
> --<br>
> - return (ISC_R_SUCCESS);<br>
> - }<br>
> - <br>
> -@@ -3759,7 +3806,7 @@ ns_clientmgr_destroy(ns_clientmgr_t **managerp) {<br>
> - <br>
> - static isc_result_t<br>
> - get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,<br>
> -- dns_dispatch_t *disp, bool tcp)<br>
> -+ dns_dispatch_t *disp, ns_client_t *oldclient, bool tcp)<br>
> - {<br>
> - isc_result_t result = ISC_R_SUCCESS;<br>
> - isc_event_t *ev;<br>
> -@@ -3803,6 +3850,16 @@ get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,<br>
> - client->dscp = ifp->dscp;<br>
> - <br>
> - if (tcp) {<br>
> -+ client->tcpattached = false;<br>
> -+ if (oldclient != NULL) {<br>
> -+ client->tcpattached = oldclient->tcpattached;<br>
> -+ }<br>
> -+<br>
> -+ LOCK(&client->interface->lock);<br>
> -+ client->interface->ntcpactive++;<br>
> -+ UNLOCK(&client->interface->lock);<br>
> -+ client->tcpactive = true;<br>
> -+<br>
> - client->attributes |= NS_CLIENTATTR_TCP;<br>
> - isc_socket_attach(ifp->tcpsocket,<br>
> - &client->tcplistener);<br>
> -@@ -3866,7 +3923,8 @@ get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock,<br>
> - ns_interface_attach(ifp, &client->interface);<br>
> - client->newstate = client->state = NS_CLIENTSTATE_WORKING;<br>
> - INSIST(client->recursionquota == NULL);<br>
> -- client->tcpquota = &client->sctx->tcpquota;<br>
> -+ client->tcpquota = &ns_g_server->tcpquota;<br>
> -+ client->tcpattached = oldclient->tcpattached;<br>
> - <br>
> - client->dscp = ifp->dscp;<br>
> - <br>
> -@@ -3885,7 +3943,6 @@ get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock,<br>
> - LOCK(&client->interface->lock);<br>
> - client->interface->ntcpactive++;<br>
> - UNLOCK(&client->interface->lock);<br>
> --<br>
> - client->tcpactive = true;<br>
> - <br>
> - INSIST(client->tcpmsg_valid == false);<br>
> -@@ -3913,7 +3970,8 @@ ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,<br>
> - MTRACE("createclients");<br>
> - <br>
> - for (disp = 0; disp < n; disp++) {<br>
> -- result = get_client(manager, ifp, ifp->udpdispatch[disp], tcp);<br>
> -+ result = get_client(manager, ifp, ifp->udpdispatch[disp],<br>
> -+ NULL, tcp);<br>
> - if (result != ISC_R_SUCCESS)<br>
> - break;<br>
> - }<br>
> -diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h<br>
> -index aeed9ccdda..e2c40acd28 100644<br>
> ---- a/bin/named/include/named/client.h<br>
> -+++ b/bin/named/include/named/client.h<br>
> -@@ -9,8 +9,6 @@<br>
> - * information regarding copyright ownership.<br>
> - */<br>
> - <br>
> --/* $Id: client.h,v 1.96 2012/01/31 23:47:31 tbox Exp $ */<br>
> --<br>
> - #ifndef NAMED_CLIENT_H<br>
> - #define NAMED_CLIENT_H 1<br>
> - <br>
> -@@ -136,6 +134,7 @@ struct ns_client {<br>
> - bool pipelined; /*%< TCP queries not in sequence */<br>
> - isc_refcount_t *pipeline_refs;<br>
> - isc_quota_t *tcpquota;<br>
> -+ bool tcpattached;<br>
> - isc_quota_t *recursionquota;<br>
> - ns_interface_t *interface;<br>
> - <br>
> --- <br>
> -2.20.1<br>
> -<br>
> diff --git a/meta/recipes-connectivity/bind/bind/0005-refactor-tcpquota-and-pipeline-refs-allow-special-ca.patch b/meta/recipes-connectivity/bind/bind/0005-refactor-tcpquota-and-pipeline-refs-allow-special-ca.patch<br>
> deleted file mode 100644<br>
> index 987e75bc0ee..00000000000<br>
> --- a/meta/recipes-connectivity/bind/bind/0005-refactor-tcpquota-and-pipeline-refs-allow-special-ca.patch<br>
> +++ /dev/null<br>
> @@ -1,911 +0,0 @@<br>
> -Backport patch to fix CVE-2018-5743.<br>
> -<br>
> -Ref:<br>
> -<a href="https://security-tracker.debian.org/tracker/CVE-2018-5743" rel="noreferrer" target="_blank">https://security-tracker.debian.org/tracker/CVE-2018-5743</a><br>
> -<br>
> -CVE: CVE-2018-5743<br>
> -Upstream-Status: Backport [<a href="https://gitlab.isc.org/isc-projects/bind9/commit/c47ccf6" rel="noreferrer" target="_blank">https://gitlab.isc.org/isc-projects/bind9/commit/c47ccf6</a>]<br>
> -<br>
> -Signed-off-by: Kai Kang <<a href="mailto:kai.kang@windriver.com" target="_blank">kai.kang@windriver.com</a>><br>
> -<br>
> -From c47ccf630f147378568b33e8fdb7b754f228c346 Mon Sep 17 00:00:00 2001<br>
> -From: Evan Hunt <<a href="mailto:each@isc.org" target="_blank">each@isc.org</a>><br>
> -Date: Fri, 5 Apr 2019 16:26:05 -0700<br>
> -Subject: [PATCH 5/6] refactor tcpquota and pipeline refs; allow special-case<br>
> - overrun in isc_quota<br>
> -<br>
> -- if the TCP quota has been exceeded but there are no clients listening<br>
> - for new connections on the interface, we can now force attachment to the<br>
> - quota using isc_quota_force(), instead of carrying on with the quota not<br>
> - attached.<br>
> -- the TCP client quota is now referenced via a reference-counted<br>
> - 'ns_tcpconn' object, one of which is created whenever a client begins<br>
> - listening for new connections, and attached to by members of that<br>
> - client's pipeline group. when the last reference to the tcpconn<br>
> - object is detached, it is freed and the TCP quota slot is released.<br>
> -- reduce code duplication by adding mark_tcp_active() function.<br>
> -- convert counters to atomic.<br>
> -<br>
> -(cherry picked from commit 7e8222378ca24f1302a0c1c638565050ab04681b)<br>
> -(cherry picked from commit 4939451275722bfda490ea86ca13e84f6bc71e46)<br>
> -(cherry picked from commit 13f7c918b8720d890408f678bd73c20e634539d9)<br>
> ----<br>
> - bin/named/client.c | 444 +++++++++++--------------<br>
> - bin/named/include/named/client.h | 12 +-<br>
> - bin/named/include/named/interfacemgr.h | 6 +-<br>
> - bin/named/interfacemgr.c | 1 +<br>
> - lib/isc/include/isc/quota.h | 7 +<br>
> - lib/isc/quota.c | 33 +-<br>
> - lib/isc/win32/<a href="http://libisc.def.in" rel="noreferrer" target="_blank">libisc.def.in</a> | 1 +<br>
> - 7 files changed, 236 insertions(+), 268 deletions(-)<br>
> -<br>
> -diff --git a/bin/named/client.c b/bin/named/client.c<br>
> -index 61e96dd28c..d826ab32bf 100644<br>
> ---- a/bin/named/client.c<br>
> -+++ b/bin/named/client.c<br>
> -@@ -244,8 +244,7 @@ static void client_start(isc_task_t *task, isc_event_t *event);<br>
> - static void client_request(isc_task_t *task, isc_event_t *event);<br>
> - static void ns_client_dumpmessage(ns_client_t *client, const char *reason);<br>
> - static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,<br>
> -- dns_dispatch_t *disp, ns_client_t *oldclient,<br>
> -- bool tcp);<br>
> -+ dns_dispatch_t *disp, bool tcp);<br>
> - static isc_result_t get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp,<br>
> - isc_socket_t *sock, ns_client_t *oldclient);<br>
> - static inline bool<br>
> -@@ -301,16 +300,32 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds) {<br>
> - }<br>
> - <br>
> - /*%<br>
> -- * Allocate a reference counter that will track the number of client structures<br>
> -- * using the TCP connection that 'client' called accept() for. This counter<br>
> -- * will be shared between all client structures associated with this TCP<br>
> -- * connection.<br>
> -+ * Allocate a reference-counted object that will maintain a single pointer to<br>
> -+ * the (also reference-counted) TCP client quota, shared between all the<br>
> -+ * clients processing queries on a single TCP connection, so that all<br>
> -+ * clients sharing the one socket will together consume only one slot in<br>
> -+ * the 'tcp-clients' quota.<br>
> - */<br>
> --static void<br>
> --pipeline_init(ns_client_t *client) {<br>
> -- isc_refcount_t *refs;<br>
> -+static isc_result_t<br>
> -+tcpconn_init(ns_client_t *client, bool force) {<br>
> -+ isc_result_t result;<br>
> -+ isc_quota_t *quota = NULL;<br>
> -+ ns_tcpconn_t *tconn = NULL;<br>
> - <br>
> -- REQUIRE(client->pipeline_refs == NULL);<br>
> -+ REQUIRE(client->tcpconn == NULL);<br>
> -+<br>
> -+ /*<br>
> -+ * Try to attach to the quota first, so we won't pointlessly<br>
> -+ * allocate memory for a tcpconn object if we can't get one.<br>
> -+ */<br>
> -+ if (force) {<br>
> -+ result = isc_quota_force(&ns_g_server->tcpquota, &quota);<br>
> -+ } else {<br>
> -+ result = isc_quota_attach(&ns_g_server->tcpquota, &quota);<br>
> -+ }<br>
> -+ if (result != ISC_R_SUCCESS) {<br>
> -+ return (result);<br>
> -+ }<br>
> - <br>
> - /*<br>
> - * A global memory context is used for the allocation as different<br>
> -@@ -320,78 +335,80 @@ pipeline_init(ns_client_t *client) {<br>
> - * contention here is expected to be negligible, given that this code<br>
> - * is only executed for TCP connections.<br>
> - */<br>
> -- refs = isc_mem_allocate(ns_g_mctx, sizeof(*refs));<br>
> -- isc_refcount_init(refs, 1);<br>
> -- client->pipeline_refs = refs;<br>
> -+ tconn = isc_mem_allocate(ns_g_mctx, sizeof(*tconn));<br>
> -+<br>
> -+ isc_refcount_init(&tconn->refs, 1);<br>
> -+ tconn->tcpquota = quota;<br>
> -+ quota = NULL;<br>
> -+ tconn->pipelined = false;<br>
> -+<br>
> -+ client->tcpconn = tconn;<br>
> -+<br>
> -+ return (ISC_R_SUCCESS);<br>
> - }<br>
> - <br>
> - /*%<br>
> -- * Increase the count of client structures using the TCP connection that<br>
> -- * 'source' is associated with and put a pointer to that count in 'target',<br>
> -- * thus associating it with the same TCP connection.<br>
> -+ * Increase the count of client structures sharing the TCP connection<br>
> -+ * that 'source' is associated with; add a pointer to the same tcpconn<br>
> -+ * to 'target', thus associating it with the same TCP connection.<br>
> - */<br>
> - static void<br>
> --pipeline_attach(ns_client_t *source, ns_client_t *target) {<br>
> -+tcpconn_attach(ns_client_t *source, ns_client_t *target) {<br>
> - int refs;<br>
> - <br>
> -- REQUIRE(source->pipeline_refs != NULL);<br>
> -- REQUIRE(target->pipeline_refs == NULL);<br>
> -+ REQUIRE(source->tcpconn != NULL);<br>
> -+ REQUIRE(target->tcpconn == NULL);<br>
> -+ REQUIRE(source->tcpconn->pipelined);<br>
> - <br>
> -- isc_refcount_increment(source->pipeline_refs, &refs);<br>
> -+ isc_refcount_increment(&source->tcpconn->refs, &refs);<br>
> - INSIST(refs > 1);<br>
> -- target->pipeline_refs = source->pipeline_refs;<br>
> -+ target->tcpconn = source->tcpconn;<br>
> - }<br>
> - <br>
> - /*%<br>
> -- * Decrease the count of client structures using the TCP connection that<br>
> -+ * Decrease the count of client structures sharing the TCP connection that<br>
> - * 'client' is associated with. If this is the last client using this TCP<br>
> -- * connection, free the reference counter and return true; otherwise, return<br>
> -- * false.<br>
> -+ * connection, we detach from the TCP quota and free the tcpconn<br>
> -+ * object. Either way, client->tcpconn is set to NULL.<br>
> - */<br>
> --static bool<br>
> --pipeline_detach(ns_client_t *client) {<br>
> -- isc_refcount_t *refcount;<br>
> -+static void<br>
> -+tcpconn_detach(ns_client_t *client) {<br>
> -+ ns_tcpconn_t *tconn = NULL;<br>
> - int refs;<br>
> - <br>
> -- REQUIRE(client->pipeline_refs != NULL);<br>
> --<br>
> -- refcount = client->pipeline_refs;<br>
> -- client->pipeline_refs = NULL;<br>
> -+ REQUIRE(client->tcpconn != NULL);<br>
> - <br>
> -- isc_refcount_decrement(refcount, refs);<br>
> -+ tconn = client->tcpconn;<br>
> -+ client->tcpconn = NULL;<br>
> - <br>
> -+ isc_refcount_decrement(&tconn->refs, &refs);<br>
> - if (refs == 0) {<br>
> -- isc_mem_free(ns_g_mctx, refs);<br>
> -- return (true);<br>
> -+ isc_quota_detach(&tconn->tcpquota);<br>
> -+ isc_mem_free(ns_g_mctx, tconn);<br>
> - }<br>
> --<br>
> -- return (false);<br>
> - }<br>
> - <br>
> --/*<br>
> -- * Detach a client from the TCP client quota if appropriate, and set<br>
> -- * the quota pointer to NULL.<br>
> -- *<br>
> -- * Sometimes when the TCP client quota is exhausted but there are no other<br>
> -- * clients servicing the interface, a client will be allowed to continue<br>
> -- * running despite not having been attached to the quota. In this event,<br>
> -- * the TCP quota was never attached to the client, so when the client (or<br>
> -- * associated pipeline group) shuts down, the quota must NOT be detached.<br>
> -+/*%<br>
> -+ * Mark a client as active and increment the interface's 'ntcpactive'<br>
> -+ * counter, as a signal that there is at least one client servicing<br>
> -+ * TCP queries for the interface. If we reach the TCP client quota at<br>
> -+ * some point, this will be used to determine whether a quota overrun<br>
> -+ * should be permitted.<br>
> - *<br>
> -- * Otherwise, if the quota pointer is set, it should be detached. If not<br>
> -- * set at all, we just return without doing anything.<br>
> -+ * Marking the client active with the 'tcpactive' flag ensures proper<br>
> -+ * accounting, by preventing us from incrementing or decrementing<br>
> -+ * 'ntcpactive' more than once per client.<br>
> - */<br>
> - static void<br>
> --tcpquota_disconnect(ns_client_t *client) {<br>
> -- if (client->tcpquota == NULL) {<br>
> -- return;<br>
> -- }<br>
> --<br>
> -- if (client->tcpattached) {<br>
> -- isc_quota_detach(&client->tcpquota);<br>
> -- client->tcpattached = false;<br>
> -- } else {<br>
> -- client->tcpquota = NULL;<br>
> -+mark_tcp_active(ns_client_t *client, bool active) {<br>
> -+ if (active && !client->tcpactive) {<br>
> -+ isc_atomic_xadd(&client->interface->ntcpactive, 1);<br>
> -+ client->tcpactive = active;<br>
> -+ } else if (!active && client->tcpactive) {<br>
> -+ uint32_t old =<br>
> -+ isc_atomic_xadd(&client->interface->ntcpactive, -1);<br>
> -+ INSIST(old > 0);<br>
> -+ client->tcpactive = active;<br>
> - }<br>
> - }<br>
> - <br>
> -@@ -484,7 +501,8 @@ exit_check(ns_client_t *client) {<br>
> - INSIST(client->recursionquota == NULL);<br>
> - <br>
> - if (NS_CLIENTSTATE_READING == client->newstate) {<br>
> -- if (!client->pipelined) {<br>
> -+ INSIST(client->tcpconn != NULL);<br>
> -+ if (!client->tcpconn->pipelined) {<br>
> - client_read(client);<br>
> - client->newstate = NS_CLIENTSTATE_MAX;<br>
> - return (true); /* We're done. */<br>
> -@@ -507,8 +525,8 @@ exit_check(ns_client_t *client) {<br>
> - dns_tcpmsg_cancelread(&client->tcpmsg);<br>
> - }<br>
> - <br>
> -- if (client->nreads != 0) {<br>
> -- /* Still waiting for read cancel completion. */<br>
> -+ /* Still waiting for read cancel completion. */<br>
> -+ if (client->nreads > 0) {<br>
> - return (true);<br>
> - }<br>
> - <br>
> -@@ -518,43 +536,45 @@ exit_check(ns_client_t *client) {<br>
> - }<br>
> - <br>
> - /*<br>
> -- * Detach from pipeline group and from TCP client quota,<br>
> -- * if appropriate.<br>
> -+ * Soon the client will be ready to accept a new TCP<br>
> -+ * connection or UDP request, but we may have enough<br>
> -+ * clients doing that already. Check whether this client<br>
> -+ * needs to remain active and allow it go inactive if<br>
> -+ * not.<br>
> - *<br>
> -- * - If no pipeline group is active, attempt to<br>
> -- * detach from the TCP client quota.<br>
> -+ * UDP clients always go inactive at this point, but a TCP<br>
> -+ * client may need to stay active and return to READY<br>
> -+ * state if no other clients are available to listen<br>
> -+ * for TCP requests on this interface.<br>
> - *<br>
> -- * - If a pipeline group is active, detach from it;<br>
> -- * if the return code indicates that there no more<br>
> -- * clients left if this pipeline group, we also detach<br>
> -- * from the TCP client quota.<br>
> -- *<br>
> -- * - Otherwise we don't try to detach, we just set the<br>
> -- * TCP quota pointer to NULL if it wasn't NULL already.<br>
> -- *<br>
> -- * tcpquota_disconnect() will set tcpquota to NULL, either<br>
> -- * by detaching it or by assignment, depending on the<br>
> -- * needs of the client. See the comments on that function<br>
> -- * for further information.<br>
> -+ * Regardless, if we're going to FREED state, that means<br>
> -+ * the system is shutting down and we don't need to<br>
> -+ * retain clients.<br>
> - */<br>
> -- if (client->pipeline_refs == NULL || pipeline_detach(client)) {<br>
> -- tcpquota_disconnect(client);<br>
> -- } else {<br>
> -- client->tcpquota = NULL;<br>
> -- client->tcpattached = false;<br>
> -+ if (client->mortal && TCP_CLIENT(client) &&<br>
> -+ client->newstate != NS_CLIENTSTATE_FREED &&<br>
> -+ !ns_g_clienttest &&<br>
> -+ isc_atomic_xadd(&client->interface->ntcpaccepting, 0) == 0)<br>
> -+ {<br>
> -+ /* Nobody else is accepting */<br>
> -+ client->mortal = false;<br>
> -+ client->newstate = NS_CLIENTSTATE_READY;<br>
> -+ }<br>
> -+<br>
> -+ /*<br>
> -+ * Detach from TCP connection and TCP client quota,<br>
> -+ * if appropriate. If this is the last reference to<br>
> -+ * the TCP connection in our pipeline group, the<br>
> -+ * TCP quota slot will be released.<br>
> -+ */<br>
> -+ if (client->tcpconn) {<br>
> -+ tcpconn_detach(client);<br>
> - }<br>
> - <br>
> - if (client->tcpsocket != NULL) {<br>
> - CTRACE("closetcp");<br>
> - isc_socket_detach(&client->tcpsocket);<br>
> --<br>
> -- if (client->tcpactive) {<br>
> -- LOCK(&client->interface->lock);<br>
> -- INSIST(client->interface->ntcpactive > 0);<br>
> -- client->interface->ntcpactive--;<br>
> -- UNLOCK(&client->interface->lock);<br>
> -- client->tcpactive = false;<br>
> -- }<br>
> -+ mark_tcp_active(client, false);<br>
> - }<br>
> - <br>
> - if (client->timerset) {<br>
> -@@ -567,35 +587,6 @@ exit_check(ns_client_t *client) {<br>
> - client->peeraddr_valid = false;<br>
> - <br>
> - client->state = NS_CLIENTSTATE_READY;<br>
> -- INSIST(client->recursionquota == NULL);<br>
> --<br>
> -- /*<br>
> -- * Now the client is ready to accept a new TCP connection<br>
> -- * or UDP request, but we may have enough clients doing<br>
> -- * that already. Check whether this client needs to remain<br>
> -- * active and force it to go inactive if not.<br>
> -- *<br>
> -- * UDP clients go inactive at this point, but a TCP client<br>
> -- * may need to remain active and go into ready state if<br>
> -- * no other clients are available to listen for TCP<br>
> -- * requests on this interface or (in the case of pipelined<br>
> -- * clients) to read for additional messages on the current<br>
> -- * connection.<br>
> -- */<br>
> -- if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) {<br>
> -- LOCK(&client->interface->lock);<br>
> -- if ((client->interface->ntcpaccepting == 0 ||<br>
> -- (client->pipelined &&<br>
> -- client->interface->ntcpactive < 2)) &&<br>
> -- client->newstate != NS_CLIENTSTATE_FREED)<br>
> -- {<br>
> -- client->mortal = false;<br>
> -- client->newstate = NS_CLIENTSTATE_READY;<br>
> -- }<br>
> -- UNLOCK(&client->interface->lock);<br>
> -- }<br>
> --<br>
> -- client->pipelined = false;<br>
> - <br>
> - /*<br>
> - * We don't need the client; send it to the inactive<br>
> -@@ -630,7 +621,7 @@ exit_check(ns_client_t *client) {<br>
> - }<br>
> - <br>
> - /* Still waiting for accept cancel completion. */<br>
> -- if (! (client->naccepts == 0)) {<br>
> -+ if (client->naccepts > 0) {<br>
> - return (true);<br>
> - }<br>
> - <br>
> -@@ -641,7 +632,7 @@ exit_check(ns_client_t *client) {<br>
> - }<br>
> - <br>
> - /* Still waiting for recv cancel completion. */<br>
> -- if (! (client->nrecvs == 0)) {<br>
> -+ if (client->nrecvs > 0) {<br>
> - return (true);<br>
> - }<br>
> - <br>
> -@@ -654,14 +645,7 @@ exit_check(ns_client_t *client) {<br>
> - INSIST(client->recursionquota == NULL);<br>
> - if (client->tcplistener != NULL) {<br>
> - isc_socket_detach(&client->tcplistener);<br>
> --<br>
> -- if (client->tcpactive) {<br>
> -- LOCK(&client->interface->lock);<br>
> -- INSIST(client->interface->ntcpactive > 0);<br>
> -- client->interface->ntcpactive--;<br>
> -- UNLOCK(&client->interface->lock);<br>
> -- client->tcpactive = false;<br>
> -- }<br>
> -+ mark_tcp_active(client, false);<br>
> - }<br>
> - if (client->udpsocket != NULL) {<br>
> - isc_socket_detach(&client->udpsocket);<br>
> -@@ -816,7 +800,7 @@ client_start(isc_task_t *task, isc_event_t *event) {<br>
> - return;<br>
> - <br>
> - if (TCP_CLIENT(client)) {<br>
> -- if (client->pipelined) {<br>
> -+ if (client->tcpconn != NULL) {<br>
> - client_read(client);<br>
> - } else {<br>
> - client_accept(client);<br>
> -@@ -2470,6 +2454,7 @@ client_request(isc_task_t *task, isc_event_t *event) {<br>
> - client->nrecvs--;<br>
> - } else {<br>
> - INSIST(TCP_CLIENT(client));<br>
> -+ INSIST(client->tcpconn != NULL);<br>
> - REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);<br>
> - REQUIRE(event->ev_sender == &client->tcpmsg);<br>
> - buffer = &client->tcpmsg.buffer;<br>
> -@@ -2657,17 +2642,19 @@ client_request(isc_task_t *task, isc_event_t *event) {<br>
> - /*<br>
> - * Pipeline TCP query processing.<br>
> - */<br>
> -- if (client->message->opcode != dns_opcode_query) {<br>
> -- client->pipelined = false;<br>
> -+ if (TCP_CLIENT(client) &&<br>
> -+ client->message->opcode != dns_opcode_query)<br>
> -+ {<br>
> -+ client->tcpconn->pipelined = false;<br>
> - }<br>
> -- if (TCP_CLIENT(client) && client->pipelined) {<br>
> -+ if (TCP_CLIENT(client) && client->tcpconn->pipelined) {<br>
> - /*<br>
> - * We're pipelining. Replace the client; the<br>
> -- * the replacement can read the TCP socket looking<br>
> -- * for new messages and this client can process the<br>
> -+ * replacement can read the TCP socket looking<br>
> -+ * for new messages and this one can process the<br>
> - * current message asynchronously.<br>
> - *<br>
> -- * There are now at least three clients using this<br>
> -+ * There will now be at least three clients using this<br>
> - * TCP socket - one accepting new connections,<br>
> - * one reading an existing connection to get new<br>
> - * messages, and one answering the message already<br>
> -@@ -2675,7 +2662,7 @@ client_request(isc_task_t *task, isc_event_t *event) {<br>
> - */<br>
> - result = ns_client_replace(client);<br>
> - if (result != ISC_R_SUCCESS) {<br>
> -- client->pipelined = false;<br>
> -+ client->tcpconn->pipelined = false;<br>
> - }<br>
> - }<br>
> - <br>
> -@@ -3233,10 +3220,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {<br>
> - client->signer = NULL;<br>
> - dns_name_init(&client->signername, NULL);<br>
> - client->mortal = false;<br>
> -- client->pipelined = false;<br>
> -- client->pipeline_refs = NULL;<br>
> -- client->tcpquota = NULL;<br>
> -- client->tcpattached = false;<br>
> -+ client->tcpconn = NULL;<br>
> - client->recursionquota = NULL;<br>
> - client->interface = NULL;<br>
> - client->peeraddr_valid = false;<br>
> -@@ -3341,9 +3325,10 @@ client_read(ns_client_t *client) {<br>
> - <br>
> - static void<br>
> - client_newconn(isc_task_t *task, isc_event_t *event) {<br>
> -+ isc_result_t result;<br>
> - ns_client_t *client = event->ev_arg;<br>
> - isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;<br>
> -- isc_result_t result;<br>
> -+ uint32_t old;<br>
> - <br>
> - REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);<br>
> - REQUIRE(NS_CLIENT_VALID(client));<br>
> -@@ -3363,10 +3348,8 @@ client_newconn(isc_task_t *task, isc_event_t *event) {<br>
> - INSIST(client->naccepts == 1);<br>
> - client->naccepts--;<br>
> - <br>
> -- LOCK(&client->interface->lock);<br>
> -- INSIST(client->interface->ntcpaccepting > 0);<br>
> -- client->interface->ntcpaccepting--;<br>
> -- UNLOCK(&client->interface->lock);<br>
> -+ old = isc_atomic_xadd(&client->interface->ntcpaccepting, -1);<br>
> -+ INSIST(old > 0);<br>
> - <br>
> - /*<br>
> - * We must take ownership of the new socket before the exit<br>
> -@@ -3399,7 +3382,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) {<br>
> - NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),<br>
> - "accept failed: %s",<br>
> - isc_result_totext(nevent->result));<br>
> -- tcpquota_disconnect(client);<br>
> -+ tcpconn_detach(client);<br>
> - }<br>
> - <br>
> - if (exit_check(client))<br>
> -@@ -3437,15 +3420,13 @@ client_newconn(isc_task_t *task, isc_event_t *event) {<br>
> - * telnetting to port 53 (once per CPU) will<br>
> - * deny service to legitimate TCP clients.<br>
> - */<br>
> -- client->pipelined = false;<br>
> - result = ns_client_replace(client);<br>
> - if (result == ISC_R_SUCCESS &&<br>
> - (ns_g_server->keepresporder == NULL ||<br>
> - !allowed(&netaddr, NULL, NULL, 0, NULL,<br>
> - ns_g_server->keepresporder)))<br>
> - {<br>
> -- pipeline_init(client);<br>
> -- client->pipelined = true;<br>
> -+ client->tcpconn->pipelined = true;<br>
> - }<br>
> - <br>
> - client_read(client);<br>
> -@@ -3462,78 +3443,59 @@ client_accept(ns_client_t *client) {<br>
> - CTRACE("accept");<br>
> - <br>
> - /*<br>
> -- * The tcpquota object can only be simultaneously referenced a<br>
> -- * pre-defined number of times; this is configured by 'tcp-clients'<br>
> -- * in named.conf. If we can't attach to it here, that means the TCP<br>
> -- * client quota has been exceeded.<br>
> -+ * Set up a new TCP connection. This means try to attach to the<br>
> -+ * TCP client quota (tcp-clients), but fail if we're over quota.<br>
> - */<br>
> -- result = isc_quota_attach(&ns_g_server->tcpquota,<br>
> -- &client->tcpquota);<br>
> -+ result = tcpconn_init(client, false);<br>
> - if (result != ISC_R_SUCCESS) {<br>
> -- bool exit;<br>
> -+ bool exit;<br>
> - <br>
> -- ns_client_log(client, NS_LOGCATEGORY_CLIENT,<br>
> -- NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),<br>
> -- "no more TCP clients: %s",<br>
> -- isc_result_totext(result));<br>
> --<br>
> -- /*<br>
> -- * We have exceeded the system-wide TCP client<br>
> -- * quota. But, we can't just block this accept<br>
> -- * in all cases, because if we did, a heavy TCP<br>
> -- * load on other interfaces might cause this<br>
> -- * interface to be starved, with no clients able<br>
> -- * to accept new connections.<br>
> -- *<br>
> -- * So, we check here to see if any other clients<br>
> -- * are already servicing TCP queries on this<br>
> -- * interface (whether accepting, reading, or<br>
> -- * processing). If there are at least two<br>
> -- * (one reading and one processing a request)<br>
> -- * then it's okay *not* to call accept - we<br>
> -- * can let this client go inactive and another<br>
> -- * one will resume accepting when it's done.<br>
> -- *<br>
> -- * If there aren't enough active clients on the<br>
> -- * interface, then we can be a little bit<br>
> -- * flexible about the quota. We'll allow *one*<br>
> -- * extra client through to ensure we're listening<br>
> -- * on every interface.<br>
> -- *<br>
> -- * (Note: In practice this means that the real<br>
> -- * TCP client quota is tcp-clients plus the<br>
> -- * number of listening interfaces plus 2.)<br>
> -- */<br>
> -- LOCK(&client->interface->lock);<br>
> -- exit = (client->interface->ntcpactive > 1);<br>
> -- UNLOCK(&client->interface->lock);<br>
> -+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,<br>
> -+ NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,<br>
> -+ "TCP client quota reached: %s",<br>
> -+ isc_result_totext(result));<br>
> - <br>
> -- if (exit) {<br>
> -- client->newstate = NS_CLIENTSTATE_INACTIVE;<br>
> -- (void)exit_check(client);<br>
> -- return;<br>
> -- }<br>
> -+ /*<br>
> -+ * We have exceeded the system-wide TCP client quota. But,<br>
> -+ * we can't just block this accept in all cases, because if<br>
> -+ * we did, a heavy TCP load on other interfaces might cause<br>
> -+ * this interface to be starved, with no clients able to<br>
> -+ * accept new connections.<br>
> -+ *<br>
> -+ * So, we check here to see if any other clients are<br>
> -+ * already servicing TCP queries on this interface (whether<br>
> -+ * accepting, reading, or processing). If we find at least<br>
> -+ * one, then it's okay *not* to call accept - we can let this<br>
> -+ * client go inactive and another will take over when it's<br>
> -+ * done.<br>
> -+ *<br>
> -+ * If there aren't enough active clients on the interface,<br>
> -+ * then we can be a little bit flexible about the quota.<br>
> -+ * We'll allow *one* extra client through to ensure we're<br>
> -+ * listening on every interface; we do this by setting the<br>
> -+ * 'force' option to tcpconn_init().<br>
> -+ *<br>
> -+ * (Note: In practice this means that the real TCP client<br>
> -+ * quota is tcp-clients plus the number of listening<br>
> -+ * interfaces plus 1.)<br>
> -+ */<br>
> -+ exit = (isc_atomic_xadd(&client->interface->ntcpactive, 0) > 0);<br>
> -+ if (exit) {<br>
> -+ client->newstate = NS_CLIENTSTATE_INACTIVE;<br>
> -+ (void)exit_check(client);<br>
> -+ return;<br>
> -+ }<br>
> - <br>
> -- } else {<br>
> -- client->tcpattached = true;<br>
> -+ result = tcpconn_init(client, true);<br>
> -+ RUNTIME_CHECK(result == ISC_R_SUCCESS);<br>
> - }<br>
> - <br>
> - /*<br>
> -- * By incrementing the interface's ntcpactive counter we signal<br>
> -- * that there is at least one client servicing TCP queries for the<br>
> -- * interface.<br>
> -- *<br>
> -- * We also make note of the fact in the client itself with the<br>
> -- * tcpactive flag. This ensures proper accounting by preventing<br>
> -- * us from accidentally incrementing or decrementing ntcpactive<br>
> -- * more than once per client object.<br>
> -+ * If this client was set up using get_client() or get_worker(),<br>
> -+ * then TCP is already marked active. However, if it was restarted<br>
> -+ * from exit_check(), it might not be, so we take care of it now.<br>
> - */<br>
> -- if (!client->tcpactive) {<br>
> -- LOCK(&client->interface->lock);<br>
> -- client->interface->ntcpactive++;<br>
> -- UNLOCK(&client->interface->lock);<br>
> -- client->tcpactive = true;<br>
> -- }<br>
> -+ mark_tcp_active(client, true);<br>
> - <br>
> - result = isc_socket_accept(client->tcplistener, client->task,<br>
> - client_newconn, client);<br>
> -@@ -3549,15 +3511,8 @@ client_accept(ns_client_t *client) {<br>
> - "isc_socket_accept() failed: %s",<br>
> - isc_result_totext(result));<br>
> - <br>
> -- tcpquota_disconnect(client);<br>
> --<br>
> -- if (client->tcpactive) {<br>
> -- LOCK(&client->interface->lock);<br>
> -- client->interface->ntcpactive--;<br>
> -- UNLOCK(&client->interface->lock);<br>
> -- client->tcpactive = false;<br>
> -- }<br>
> --<br>
> -+ tcpconn_detach(client);<br>
> -+ mark_tcp_active(client, false);<br>
> - return;<br>
> - }<br>
> - <br>
> -@@ -3582,9 +3537,7 @@ client_accept(ns_client_t *client) {<br>
> - * listening for connections itself to prevent the interface<br>
> - * going dead.<br>
> - */<br>
> -- LOCK(&client->interface->lock);<br>
> -- client->interface->ntcpaccepting++;<br>
> -- UNLOCK(&client->interface->lock);<br>
> -+ isc_atomic_xadd(&client->interface->ntcpaccepting, 1);<br>
> - }<br>
> - <br>
> - static void<br>
> -@@ -3655,24 +3608,25 @@ ns_client_replace(ns_client_t *client) {<br>
> - REQUIRE(client->manager != NULL);<br>
> - <br>
> - tcp = TCP_CLIENT(client);<br>
> -- if (tcp && client->pipelined) {<br>
> -+ if (tcp && client->tcpconn != NULL && client->tcpconn->pipelined) {<br>
> - result = get_worker(client->manager, client->interface,<br>
> - client->tcpsocket, client);<br>
> - } else {<br>
> - result = get_client(client->manager, client->interface,<br>
> -- client->dispatch, client, tcp);<br>
> -+ client->dispatch, tcp);<br>
> - <br>
> -- /*<br>
> -- * The responsibility for listening for new requests is hereby<br>
> -- * transferred to the new client. Therefore, the old client<br>
> -- * should refrain from listening for any more requests.<br>
> -- */<br>
> -- client->mortal = true;<br>
> - }<br>
> - if (result != ISC_R_SUCCESS) {<br>
> - return (result);<br>
> - }<br>
> - <br>
> -+ /*<br>
> -+ * The responsibility for listening for new requests is hereby<br>
> -+ * transferred to the new client. Therefore, the old client<br>
> -+ * should refrain from listening for any more requests.<br>
> -+ */<br>
> -+ client->mortal = true;<br>
> -+<br>
> - return (ISC_R_SUCCESS);<br>
> - }<br>
> - <br>
> -@@ -3806,7 +3760,7 @@ ns_clientmgr_destroy(ns_clientmgr_t **managerp) {<br>
> - <br>
> - static isc_result_t<br>
> - get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,<br>
> -- dns_dispatch_t *disp, ns_client_t *oldclient, bool tcp)<br>
> -+ dns_dispatch_t *disp, bool tcp)<br>
> - {<br>
> - isc_result_t result = ISC_R_SUCCESS;<br>
> - isc_event_t *ev;<br>
> -@@ -3850,15 +3804,7 @@ get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,<br>
> - client->dscp = ifp->dscp;<br>
> - <br>
> - if (tcp) {<br>
> -- client->tcpattached = false;<br>
> -- if (oldclient != NULL) {<br>
> -- client->tcpattached = oldclient->tcpattached;<br>
> -- }<br>
> --<br>
> -- LOCK(&client->interface->lock);<br>
> -- client->interface->ntcpactive++;<br>
> -- UNLOCK(&client->interface->lock);<br>
> -- client->tcpactive = true;<br>
> -+ mark_tcp_active(client, true);<br>
> - <br>
> - client->attributes |= NS_CLIENTATTR_TCP;<br>
> - isc_socket_attach(ifp->tcpsocket,<br>
> -@@ -3923,16 +3869,14 @@ get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock,<br>
> - ns_interface_attach(ifp, &client->interface);<br>
> - client->newstate = client->state = NS_CLIENTSTATE_WORKING;<br>
> - INSIST(client->recursionquota == NULL);<br>
> -- client->tcpquota = &ns_g_server->tcpquota;<br>
> -- client->tcpattached = oldclient->tcpattached;<br>
> - <br>
> - client->dscp = ifp->dscp;<br>
> - <br>
> - client->attributes |= NS_CLIENTATTR_TCP;<br>
> - client->mortal = true;<br>
> - <br>
> -- pipeline_attach(oldclient, client);<br>
> -- client->pipelined = true;<br>
> -+ tcpconn_attach(oldclient, client);<br>
> -+ mark_tcp_active(client, true);<br>
> - <br>
> - isc_socket_attach(ifp->tcpsocket, &client->tcplistener);<br>
> - isc_socket_attach(sock, &client->tcpsocket);<br>
> -@@ -3940,11 +3884,6 @@ get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock,<br>
> - (void)isc_socket_getpeername(client->tcpsocket, &client->peeraddr);<br>
> - client->peeraddr_valid = true;<br>
> - <br>
> -- LOCK(&client->interface->lock);<br>
> -- client->interface->ntcpactive++;<br>
> -- UNLOCK(&client->interface->lock);<br>
> -- client->tcpactive = true;<br>
> --<br>
> - INSIST(client->tcpmsg_valid == false);<br>
> - dns_tcpmsg_init(client->mctx, client->tcpsocket, &client->tcpmsg);<br>
> - client->tcpmsg_valid = true;<br>
> -@@ -3970,8 +3909,7 @@ ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,<br>
> - MTRACE("createclients");<br>
> - <br>
> - for (disp = 0; disp < n; disp++) {<br>
> -- result = get_client(manager, ifp, ifp->udpdispatch[disp],<br>
> -- NULL, tcp);<br>
> -+ result = get_client(manager, ifp, ifp->udpdispatch[disp], tcp);<br>
> - if (result != ISC_R_SUCCESS)<br>
> - break;<br>
> - }<br>
> -diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h<br>
> -index e2c40acd28..969ee4c08f 100644<br>
> ---- a/bin/named/include/named/client.h<br>
> -+++ b/bin/named/include/named/client.h<br>
> -@@ -78,6 +78,13 @@<br>
> - *** Types<br>
> - ***/<br>
> - <br>
> -+/*% reference-counted TCP connection object */<br>
> -+typedef struct ns_tcpconn {<br>
> -+ isc_refcount_t refs;<br>
> -+ isc_quota_t *tcpquota;<br>
> -+ bool pipelined;<br>
> -+} ns_tcpconn_t;<br>
> -+<br>
> - /*% nameserver client structure */<br>
> - struct ns_client {<br>
> - unsigned int magic;<br>
> -@@ -131,10 +138,7 @@ struct ns_client {<br>
> - dns_name_t signername; /*%< [T]SIG key name */<br>
> - dns_name_t *signer; /*%< NULL if not valid sig */<br>
> - bool mortal; /*%< Die after handling request */<br>
> -- bool pipelined; /*%< TCP queries not in sequence */<br>
> -- isc_refcount_t *pipeline_refs;<br>
> -- isc_quota_t *tcpquota;<br>
> -- bool tcpattached;<br>
> -+ ns_tcpconn_t *tcpconn;<br>
> - isc_quota_t *recursionquota;<br>
> - ns_interface_t *interface;<br>
> - <br>
> -diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h<br>
> -index 61b08826a6..3535ef22a8 100644<br>
> ---- a/bin/named/include/named/interfacemgr.h<br>
> -+++ b/bin/named/include/named/interfacemgr.h<br>
> -@@ -9,8 +9,6 @@<br>
> - * information regarding copyright ownership.<br>
> - */<br>
> - <br>
> --/* $Id: interfacemgr.h,v 1.35 2011/07/28 23:47:58 tbox Exp $ */<br>
> --<br>
> - #ifndef NAMED_INTERFACEMGR_H<br>
> - #define NAMED_INTERFACEMGR_H 1<br>
> - <br>
> -@@ -77,11 +75,11 @@ struct ns_interface {<br>
> - /*%< UDP dispatchers. */<br>
> - isc_socket_t * tcpsocket; /*%< TCP socket. */<br>
> - isc_dscp_t dscp; /*%< "listen-on" DSCP value */<br>
> -- int ntcpaccepting; /*%< Number of clients<br>
> -+ int32_t ntcpaccepting; /*%< Number of clients<br>
> - ready to accept new<br>
> - TCP connections on this<br>
> - interface */<br>
> -- int ntcpactive; /*%< Number of clients<br>
> -+ int32_t ntcpactive; /*%< Number of clients<br>
> - servicing TCP queries<br>
> - (whether accepting or<br>
> - connected) */<br>
> -diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c<br>
> -index 955096ef47..d9f6df5802 100644<br>
> ---- a/bin/named/interfacemgr.c<br>
> -+++ b/bin/named/interfacemgr.c<br>
> -@@ -388,6 +388,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,<br>
> - */<br>
> - ifp->ntcpaccepting = 0;<br>
> - ifp->ntcpactive = 0;<br>
> -+<br>
> - ifp->nudpdispatch = 0;<br>
> - <br>
> - ifp->dscp = -1;<br>
> -diff --git a/lib/isc/include/isc/quota.h b/lib/isc/include/isc/quota.h<br>
> -index b9bf59877a..36c5830242 100644<br>
> ---- a/lib/isc/include/isc/quota.h<br>
> -+++ b/lib/isc/include/isc/quota.h<br>
> -@@ -100,6 +100,13 @@ isc_quota_attach(isc_quota_t *quota, isc_quota_t **p);<br>
> - * quota if successful (ISC_R_SUCCESS or ISC_R_SOFTQUOTA).<br>
> - */<br>
> - <br>
> -+isc_result_t<br>
> -+isc_quota_force(isc_quota_t *quota, isc_quota_t **p);<br>
> -+/*%<<br>
> -+ * Like isc_quota_attach, but will attach '*p' to the quota<br>
> -+ * even if the hard quota has been exceeded.<br>
> -+ */<br>
> -+<br>
> - void<br>
> - isc_quota_detach(isc_quota_t **p);<br>
> - /*%<<br>
> -diff --git a/lib/isc/quota.c b/lib/isc/quota.c<br>
> -index 3ddff0d875..556a61f21d 100644<br>
> ---- a/lib/isc/quota.c<br>
> -+++ b/lib/isc/quota.c<br>
> -@@ -74,20 +74,39 @@ isc_quota_release(isc_quota_t *quota) {<br>
> - UNLOCK(&quota->lock);<br>
> - }<br>
> - <br>
> --isc_result_t<br>
> --isc_quota_attach(isc_quota_t *quota, isc_quota_t **p)<br>
> --{<br>
> -+static isc_result_t<br>
> -+doattach(isc_quota_t *quota, isc_quota_t **p, bool force) {<br>
> - isc_result_t result;<br>
> -- INSIST(p != NULL && *p == NULL);<br>
> -+ REQUIRE(p != NULL && *p == NULL);<br>
> -+<br>
> - result = isc_quota_reserve(quota);<br>
> -- if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA)<br>
> -+ if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA) {<br>
> -+ *p = quota;<br>
> -+ } else if (result == ISC_R_QUOTA && force) {<br>
> -+ /* attach anyway */<br>
> -+ LOCK(&quota->lock);<br>
> -+ quota->used++;<br>
> -+ UNLOCK(&quota->lock);<br>
> -+<br>
> - *p = quota;<br>
> -+ result = ISC_R_SUCCESS;<br>
> -+ }<br>
> -+<br>
> - return (result);<br>
> - }<br>
> - <br>
> -+isc_result_t<br>
> -+isc_quota_attach(isc_quota_t *quota, isc_quota_t **p) {<br>
> -+ return (doattach(quota, p, false));<br>
> -+}<br>
> -+<br>
> -+isc_result_t<br>
> -+isc_quota_force(isc_quota_t *quota, isc_quota_t **p) {<br>
> -+ return (doattach(quota, p, true));<br>
> -+}<br>
> -+<br>
> - void<br>
> --isc_quota_detach(isc_quota_t **p)<br>
> --{<br>
> -+isc_quota_detach(isc_quota_t **p) {<br>
> - INSIST(p != NULL && *p != NULL);<br>
> - isc_quota_release(*p);<br>
> - *p = NULL;<br>
> -diff --git a/lib/isc/win32/<a href="http://libisc.def.in" rel="noreferrer" target="_blank">libisc.def.in</a> b/lib/isc/win32/<a href="http://libisc.def.in" rel="noreferrer" target="_blank">libisc.def.in</a><br>
> -index a82facec0f..7b9f23d776 100644<br>
> ---- a/lib/isc/win32/<a href="http://libisc.def.in" rel="noreferrer" target="_blank">libisc.def.in</a><br>
> -+++ b/lib/isc/win32/<a href="http://libisc.def.in" rel="noreferrer" target="_blank">libisc.def.in</a><br>
> -@@ -519,6 +519,7 @@ isc_portset_removerange<br>
> - isc_quota_attach<br>
> - isc_quota_destroy<br>
> - isc_quota_detach<br>
> -+isc_quota_force<br>
> - isc_quota_init<br>
> - isc_quota_max<br>
> - isc_quota_release<br>
> --- <br>
> -2.20.1<br>
> -<br>
> diff --git a/meta/recipes-connectivity/bind/bind/0006-restore-allowance-for-tcp-clients-interfaces.patch b/meta/recipes-connectivity/bind/bind/0006-restore-allowance-for-tcp-clients-interfaces.patch<br>
> deleted file mode 100644<br>
> index 3821d185012..00000000000<br>
> --- a/meta/recipes-connectivity/bind/bind/0006-restore-allowance-for-tcp-clients-interfaces.patch<br>
> +++ /dev/null<br>
> @@ -1,80 +0,0 @@<br>
> -Backport patch to fix CVE-2018-5743.<br>
> -<br>
> -Ref:<br>
> -<a href="https://security-tracker.debian.org/tracker/CVE-2018-5743" rel="noreferrer" target="_blank">https://security-tracker.debian.org/tracker/CVE-2018-5743</a><br>
> -<br>
> -CVE: CVE-2018-5743<br>
> -Upstream-Status: Backport [<a href="https://gitlab.isc.org/isc-projects/bind9/commit/59434b9" rel="noreferrer" target="_blank">https://gitlab.isc.org/isc-projects/bind9/commit/59434b9</a>]<br>
> -<br>
> -Signed-off-by: Kai Kang <<a href="mailto:kai.kang@windriver.com" target="_blank">kai.kang@windriver.com</a>><br>
> -<br>
> -From 59434b987e8eb436b08c24e559ee094c4e939daa Mon Sep 17 00:00:00 2001<br>
> -From: Evan Hunt <<a href="mailto:each@isc.org" target="_blank">each@isc.org</a>><br>
> -Date: Fri, 5 Apr 2019 16:26:19 -0700<br>
> -Subject: [PATCH 6/6] restore allowance for tcp-clients < interfaces<br>
> -<br>
> -in the "refactor tcpquota and pipeline refs" commit, the counting<br>
> -of active interfaces was tightened in such a way that named could<br>
> -fail to listen on an interface if there were more interfaces than<br>
> -tcp-clients. when checking the quota to start accepting on an<br>
> -interface, if the number of active clients was above zero, then<br>
> -it was presumed that some other client was able to handle accepting<br>
> -new connections. this, however, ignored the fact that the current client<br>
> -could be included in that count, so if the quota was already exceeded<br>
> -before all the interfaces were listening, some interfaces would never<br>
> -listen.<br>
> -<br>
> -we now check whether the current client has been marked active; if so,<br>
> -then the number of active clients on the interface must be greater<br>
> -than 1, not 0.<br>
> -<br>
> -(cherry picked from commit 0b4e2cd4c3192ba88569dd344f542a8cc43742b5)<br>
> -(cherry picked from commit d01023aaac35543daffbdf48464e320150235d41)<br>
> ----<br>
> - bin/named/client.c | 8 +++++---<br>
> - doc/arm/Bv9ARM-book.xml | 3 ++-<br>
> - 2 files changed, 7 insertions(+), 4 deletions(-)<br>
> -<br>
> -diff --git a/bin/named/client.c b/bin/named/client.c<br>
> -index d826ab32bf..845326abc0 100644<br>
> ---- a/bin/named/client.c<br>
> -+++ b/bin/named/client.c<br>
> -@@ -3464,8 +3464,9 @@ client_accept(ns_client_t *client) {<br>
> - *<br>
> - * So, we check here to see if any other clients are<br>
> - * already servicing TCP queries on this interface (whether<br>
> -- * accepting, reading, or processing). If we find at least<br>
> -- * one, then it's okay *not* to call accept - we can let this<br>
> -+ * accepting, reading, or processing). If we find that at<br>
> -+ * least one client other than this one is active, then<br>
> -+ * it's okay *not* to call accept - we can let this<br>
> - * client go inactive and another will take over when it's<br>
> - * done.<br>
> - *<br>
> -@@ -3479,7 +3480,8 @@ client_accept(ns_client_t *client) {<br>
> - * quota is tcp-clients plus the number of listening<br>
> - * interfaces plus 1.)<br>
> - */<br>
> -- exit = (isc_atomic_xadd(&client->interface->ntcpactive, 0) > 0);<br>
> -+ exit = (isc_atomic_xadd(&client->interface->ntcpactive, 0) ><br>
> -+ (client->tcpactive ? 1 : 0));<br>
> - if (exit) {<br>
> - client->newstate = NS_CLIENTSTATE_INACTIVE;<br>
> - (void)exit_check(client);<br>
> -diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml<br>
> -index 381768d540..9c76d3cd6f 100644<br>
> ---- a/doc/arm/Bv9ARM-book.xml<br>
> -+++ b/doc/arm/Bv9ARM-book.xml<br>
> -@@ -8493,7 +8493,8 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };<br>
> - <para><br>
> - The number of file descriptors reserved for TCP, stdio,<br>
> - etc. This needs to be big enough to cover the number of<br>
> -- interfaces <command>named</command> listens on, <command>tcp-clients</command> as well as<br>
> -+ interfaces <command>named</command> listens on plus<br>
> -+ <command>tcp-clients</command>, as well as<br>
> - to provide room for outgoing TCP queries and incoming zone<br>
> - transfers. The default is <literal>512</literal>.<br>
> - The minimum value is <literal>128</literal> and the<br>
> --- <br>
> -2.20.1<br>
> -<br>
> diff --git a/meta/recipes-connectivity/bind/bind/0007-Replace-atomic-operations-in-bin-named-client.c-with.patch b/meta/recipes-connectivity/bind/bind/0007-Replace-atomic-operations-in-bin-named-client.c-with.patch<br>
> deleted file mode 100644<br>
> index 1a84eca58a7..00000000000<br>
> --- a/meta/recipes-connectivity/bind/bind/0007-Replace-atomic-operations-in-bin-named-client.c-with.patch<br>
> +++ /dev/null<br>
> @@ -1,140 +0,0 @@<br>
> -Backport commit to fix compile error on arm caused by commits which are<br>
> -to fix CVE-2018-5743.<br>
> -<br>
> -CVE: CVE-2018-5743<br>
> -Upstream-Status: Backport [<a href="https://gitlab.isc.org/isc-projects/bind9/commit/ef49780" rel="noreferrer" target="_blank">https://gitlab.isc.org/isc-projects/bind9/commit/ef49780</a>]<br>
> -<br>
> -Signed-off-by: Kai Kang <<a href="mailto:kai.kang@windriver.com" target="_blank">kai.kang@windriver.com</a>><br>
> -<br>
> -From ef49780d30d3ddc5735cfc32561b678a634fa72f Mon Sep 17 00:00:00 2001<br>
> -From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= <<a href="mailto:ondrej@sury.org" target="_blank">ondrej@sury.org</a>><br>
> -Date: Wed, 17 Apr 2019 15:22:27 +0200<br>
> -Subject: [PATCH] Replace atomic operations in bin/named/client.c with<br>
> - isc_refcount reference counting<br>
> -<br>
> ----<br>
> - bin/named/client.c | 18 +++++++-----------<br>
> - bin/named/include/named/interfacemgr.h | 5 +++--<br>
> - bin/named/interfacemgr.c | 7 +++++--<br>
> - 3 files changed, 15 insertions(+), 15 deletions(-)<br>
> -<br>
> -diff --git a/bin/named/client.c b/bin/named/client.c<br>
> -index 845326abc0..29fecadca8 100644<br>
> ---- a/bin/named/client.c<br>
> -+++ b/bin/named/client.c<br>
> -@@ -402,12 +402,10 @@ tcpconn_detach(ns_client_t *client) {<br>
> - static void<br>
> - mark_tcp_active(ns_client_t *client, bool active) {<br>
> - if (active && !client->tcpactive) {<br>
> -- isc_atomic_xadd(&client->interface->ntcpactive, 1);<br>
> -+ isc_refcount_increment0(&client->interface->ntcpactive, NULL);<br>
> - client->tcpactive = active;<br>
> - } else if (!active && client->tcpactive) {<br>
> -- uint32_t old =<br>
> -- isc_atomic_xadd(&client->interface->ntcpactive, -1);<br>
> -- INSIST(old > 0);<br>
> -+ isc_refcount_decrement(&client->interface->ntcpactive, NULL);<br>
> - client->tcpactive = active;<br>
> - }<br>
> - }<br>
> -@@ -554,7 +552,7 @@ exit_check(ns_client_t *client) {<br>
> - if (client->mortal && TCP_CLIENT(client) &&<br>
> - client->newstate != NS_CLIENTSTATE_FREED &&<br>
> - !ns_g_clienttest &&<br>
> -- isc_atomic_xadd(&client->interface->ntcpaccepting, 0) == 0)<br>
> -+ isc_refcount_current(&client->interface->ntcpaccepting) == 0)<br>
> - {<br>
> - /* Nobody else is accepting */<br>
> - client->mortal = false;<br>
> -@@ -3328,7 +3326,6 @@ client_newconn(isc_task_t *task, isc_event_t *event) {<br>
> - isc_result_t result;<br>
> - ns_client_t *client = event->ev_arg;<br>
> - isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;<br>
> -- uint32_t old;<br>
> - <br>
> - REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);<br>
> - REQUIRE(NS_CLIENT_VALID(client));<br>
> -@@ -3348,8 +3345,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) {<br>
> - INSIST(client->naccepts == 1);<br>
> - client->naccepts--;<br>
> - <br>
> -- old = isc_atomic_xadd(&client->interface->ntcpaccepting, -1);<br>
> -- INSIST(old > 0);<br>
> -+ isc_refcount_decrement(&client->interface->ntcpaccepting, NULL);<br>
> - <br>
> - /*<br>
> - * We must take ownership of the new socket before the exit<br>
> -@@ -3480,8 +3476,8 @@ client_accept(ns_client_t *client) {<br>
> - * quota is tcp-clients plus the number of listening<br>
> - * interfaces plus 1.)<br>
> - */<br>
> -- exit = (isc_atomic_xadd(&client->interface->ntcpactive, 0) ><br>
> -- (client->tcpactive ? 1 : 0));<br>
> -+ exit = (isc_refcount_current(&client->interface->ntcpactive) ><br>
> -+ (client->tcpactive ? 1U : 0U));<br>
> - if (exit) {<br>
> - client->newstate = NS_CLIENTSTATE_INACTIVE;<br>
> - (void)exit_check(client);<br>
> -@@ -3539,7 +3535,7 @@ client_accept(ns_client_t *client) {<br>
> - * listening for connections itself to prevent the interface<br>
> - * going dead.<br>
> - */<br>
> -- isc_atomic_xadd(&client->interface->ntcpaccepting, 1);<br>
> -+ isc_refcount_increment0(&client->interface->ntcpaccepting, NULL);<br>
> - }<br>
> - <br>
> - static void<br>
> -diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h<br>
> -index 3535ef22a8..6e10f210fd 100644<br>
> ---- a/bin/named/include/named/interfacemgr.h<br>
> -+++ b/bin/named/include/named/interfacemgr.h<br>
> -@@ -45,6 +45,7 @@<br>
> - #include <isc/magic.h><br>
> - #include <isc/mem.h><br>
> - #include <isc/socket.h><br>
> -+#include <isc/refcount.h><br>
> - <br>
> - #include <dns/result.h><br>
> - <br>
> -@@ -75,11 +76,11 @@ struct ns_interface {<br>
> - /*%< UDP dispatchers. */<br>
> - isc_socket_t * tcpsocket; /*%< TCP socket. */<br>
> - isc_dscp_t dscp; /*%< "listen-on" DSCP value */<br>
> -- int32_t ntcpaccepting; /*%< Number of clients<br>
> -+ isc_refcount_t ntcpaccepting; /*%< Number of clients<br>
> - ready to accept new<br>
> - TCP connections on this<br>
> - interface */<br>
> -- int32_t ntcpactive; /*%< Number of clients<br>
> -+ isc_refcount_t ntcpactive; /*%< Number of clients<br>
> - servicing TCP queries<br>
> - (whether accepting or<br>
> - connected) */<br>
> -diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c<br>
> -index d9f6df5802..135533be6b 100644<br>
> ---- a/bin/named/interfacemgr.c<br>
> -+++ b/bin/named/interfacemgr.c<br>
> -@@ -386,8 +386,8 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,<br>
> - * connections will be handled in parallel even though there is<br>
> - * only one client initially.<br>
> - */<br>
> -- ifp->ntcpaccepting = 0;<br>
> -- ifp->ntcpactive = 0;<br>
> -+ isc_refcount_init(&ifp->ntcpaccepting, 0);<br>
> -+ isc_refcount_init(&ifp->ntcpactive, 0);<br>
> - <br>
> - ifp->nudpdispatch = 0;<br>
> - <br>
> -@@ -618,6 +618,9 @@ ns_interface_destroy(ns_interface_t *ifp) {<br>
> - <br>
> - ns_interfacemgr_detach(&ifp->mgr);<br>
> - <br>
> -+ isc_refcount_destroy(&ifp->ntcpactive);<br>
> -+ isc_refcount_destroy(&ifp->ntcpaccepting);<br>
> -+<br>
> - ifp->magic = 0;<br>
> - isc_mem_put(mctx, ifp, sizeof(*ifp));<br>
> - }<br>
> --- <br>
> -2.20.1<br>
> -<br>
> diff --git a/meta/recipes-connectivity/bind/bind/bind-ensure-searching-for-json-headers-searches-sysr.patch b/meta/recipes-connectivity/bind/bind/bind-ensure-searching-for-json-headers-searches-sysr.patch<br>
> index 37e210e6da9..84559e5f378 100644<br>
> --- a/meta/recipes-connectivity/bind/bind/bind-ensure-searching-for-json-headers-searches-sysr.patch<br>
> +++ b/meta/recipes-connectivity/bind/bind/bind-ensure-searching-for-json-headers-searches-sysr.patch<br>
> @@ -1,4 +1,4 @@<br>
> -From 9473d29843579802e96b0293a3e953fed93de82c Mon Sep 17 00:00:00 2001<br>
> +From edda20fb5a6e88548f85e39d34d6c074306e15bc Mon Sep 17 00:00:00 2001<br>
> From: Paul Gortmaker <<a href="mailto:paul.gortmaker@windriver.com" target="_blank">paul.gortmaker@windriver.com</a>><br>
> Date: Tue, 9 Jun 2015 11:22:00 -0400<br>
> Subject: [PATCH] bind: ensure searching for json headers searches sysroot<br>
> @@ -27,15 +27,16 @@ to make use of the combination some day.<br>
> <br>
> Upstream-Status: Inappropriate [OE Specific]<br>
> Signed-off-by: Paul Gortmaker <<a href="mailto:paul.gortmaker@windriver.com" target="_blank">paul.gortmaker@windriver.com</a>><br>
> +<br>
> ---<br>
> - <a href="http://configure.in" rel="noreferrer" target="_blank">configure.in</a> | 2 +-<br>
> + <a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a> | 2 +-<br>
> 1 file changed, 1 insertion(+), 1 deletion(-)<br>
> <br>
> -Index: bind-9.11.3/<a href="http://configure.in" rel="noreferrer" target="_blank">configure.in</a><br>
> -===================================================================<br>
> ---- bind-9.11.3.orig/<a href="http://configure.in" rel="noreferrer" target="_blank">configure.in</a><br>
> -+++ bind-9.11.3/<a href="http://configure.in" rel="noreferrer" target="_blank">configure.in</a><br>
> -@@ -2574,7 +2574,7 @@ case "$use_libjson" in<br>
> +diff --git a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a> b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> +index 17392fd..e85a5c6 100644<br>
> +--- a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> ++++ b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> +@@ -2449,7 +2449,7 @@ case "$use_libjson" in<br>
> libjson_libs=""<br>
> ;;<br>
> auto|yes)<br>
> diff --git a/meta/recipes-connectivity/bind/<a href="http://bind_9.11.5-P4.bb" rel="noreferrer" target="_blank">bind_9.11.5-P4.bb</a> b/meta/recipes-connectivity/bind/<a href="http://bind_9.11.13.bb" rel="noreferrer" target="_blank">bind_9.11.13.bb</a><br>
> similarity index 86%<br>
> rename from meta/recipes-connectivity/bind/<a href="http://bind_9.11.5-P4.bb" rel="noreferrer" target="_blank">bind_9.11.5-P4.bb</a><br>
> rename to meta/recipes-connectivity/bind/<a href="http://bind_9.11.13.bb" rel="noreferrer" target="_blank">bind_9.11.13.bb</a><br>
> index 0897706346b..338d6c717a6 100644<br>
> --- a/meta/recipes-connectivity/bind/<a href="http://bind_9.11.5-P4.bb" rel="noreferrer" target="_blank">bind_9.11.5-P4.bb</a><br>
> +++ b/meta/recipes-connectivity/bind/<a href="http://bind_9.11.13.bb" rel="noreferrer" target="_blank">bind_9.11.13.bb</a><br>
> @@ -15,23 +15,13 @@ SRC_URI = "<a href="https://ftp.isc.org/isc/bind9/$%7BPV%7D/$%7BBPN%7D-$%7BPV%7D.tar.gz" rel="noreferrer" target="_blank">https://ftp.isc.org/isc/bind9/${PV}/${BPN}-${PV}.tar.gz</a> \<br>
> file://make-etc-initd-bind-stop-work.patch \<br>
> file://init.d-add-support-for-read-only-rootfs.patch \<br>
> file://bind-ensure-searching-for-json-headers-searches-sysr.patch \<br>
> - file://0001-gen.c-extend-DIRNAMESIZE-from-256-to-512.patch \<br>
> - file://0001-lib-dns-gen.c-fix-too-long-error.patch \<br>
> file://0001-configure.in-remove-useless-L-use_openssl-lib.patch \<br>
> file://0001-named-lwresd-V-and-start-log-hide-build-options.patch \<br>
> file://0001-avoid-start-failure-with-bind-user.patch \<br>
> - file://0001-bind-fix-CVE-2019-6471.patch \<br>
> - file://0001-fix-enforcement-of-tcp-clients-v1.patch \<br>
> - file://0002-tcp-clients-could-still-be-exceeded-v2.patch \<br>
> - file://0003-use-reference-counter-for-pipeline-groups-v3.patch \<br>
> - file://0004-better-tcpquota-accounting-and-client-mortality-chec.patch \<br>
> - file://0005-refactor-tcpquota-and-pipeline-refs-allow-special-ca.patch \<br>
> - file://0006-restore-allowance-for-tcp-clients-interfaces.patch \<br>
> - file://0007-Replace-atomic-operations-in-bin-named-client.c-with.patch \<br>
> -"<br>
> -<br>
> -SRC_URI[md5sum] = "8ddab4b61fa4516fe404679c74e37960"<br>
> -SRC_URI[sha256sum] = "7e8c08192bcbaeb6e9f2391a70e67583b027b90e8c4bc1605da6eb126edde434"<br>
> + "<br>
> +<br>
> +SRC_URI[md5sum] = "17de0d024ab1eac377f1c2854dc25057"<br>
> +SRC_URI[sha256sum] = "fd3f3cc9fcfcdaa752db35eb24598afa1fdcc2509d3227fc90a8631b7b400f7d"<br>
> <br>
> UPSTREAM_CHECK_URI = "<a href="https://ftp.isc.org/isc/bind9/" rel="noreferrer" target="_blank">https://ftp.isc.org/isc/bind9/</a>"<br>
> # stay at 9.11 until 9.16, from 9.16 follow the ESV versions divisible by 4<br>
<br>
</blockquote></div></div>