diff --git a/SOURCES/bind-9.11-CVE-2018-5743-atomic.patch b/SOURCES/bind-9.11-CVE-2018-5743-atomic.patch deleted file mode 100644 index 6997084..0000000 --- a/SOURCES/bind-9.11-CVE-2018-5743-atomic.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 8f02da17a14f5f502bb456b206fd65ecd7d6ca1a Mon Sep 17 00:00:00 2001 -From: Petr Mensik -Date: Wed, 24 Apr 2019 21:10:26 +0200 -Subject: [PATCH 4/4] Missing atomic fix to original CVE patch - ---- - bin/named/client.c | 18 +++++++----------- - bin/named/include/named/interfacemgr.h | 5 +++-- - bin/named/interfacemgr.c | 7 +++++-- - 3 files changed, 15 insertions(+), 15 deletions(-) - -diff --git a/bin/named/client.c b/bin/named/client.c -index a2e1fde9b8..c247f027d9 100644 ---- a/bin/named/client.c -+++ b/bin/named/client.c -@@ -389,12 +389,10 @@ tcpconn_detach(ns_client_t *client) { - static void - mark_tcp_active(ns_client_t *client, isc_boolean_t active) { - if (active && !client->tcpactive) { -- isc_atomic_xadd(&client->interface->ntcpactive, 1); -+ isc_refcount_increment0(&client->interface->ntcpactive, NULL); - client->tcpactive = active; - } else if (!active && client->tcpactive) { -- uint32_t old = -- isc_atomic_xadd(&client->interface->ntcpactive, -1); -- INSIST(old > 0); -+ isc_refcount_decrement(&client->interface->ntcpactive, NULL); - client->tcpactive = active; - } - } -@@ -540,7 +538,7 @@ exit_check(ns_client_t *client) { - if (client->mortal && TCP_CLIENT(client) && - client->newstate != NS_CLIENTSTATE_FREED && - !ns_g_clienttest && -- isc_atomic_xadd(&client->interface->ntcpaccepting, 0) == 0) -+ isc_refcount_current(&client->interface->ntcpaccepting) == 0) - { - /* Nobody else is accepting */ - client->mortal = ISC_FALSE; -@@ -2433,7 +2431,6 @@ client_newconn(isc_task_t *task, isc_event_t *event) { - isc_result_t result; - ns_client_t *client = event->ev_arg; - isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event; -- uint32_t old; - - REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN); - REQUIRE(NS_CLIENT_VALID(client)); -@@ -2453,8 +2450,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { - INSIST(client->naccepts == 1); - client->naccepts--; - -- old = isc_atomic_xadd(&client->interface->ntcpaccepting, -1); -- INSIST(old > 0); -+ isc_refcount_decrement(&client->interface->ntcpaccepting, NULL); - - /* - * We must take ownership of the new socket before the exit -@@ -2585,8 +2581,8 @@ client_accept(ns_client_t *client) { - * quota is tcp-clients plus the number of listening - * interfaces plus 1.) - */ -- exit = (isc_atomic_xadd(&client->interface->ntcpactive, 0) > -- (client->tcpactive ? 1 : 0)); -+ exit = (isc_refcount_current(&client->interface->ntcpactive) > -+ (client->tcpactive ? 1U : 0U)); - if (exit) { - client->newstate = NS_CLIENTSTATE_INACTIVE; - (void)exit_check(client); -@@ -2644,7 +2640,7 @@ client_accept(ns_client_t *client) { - * listening for connections itself to prevent the interface - * going dead. - */ -- isc_atomic_xadd(&client->interface->ntcpaccepting, 1); -+ isc_refcount_increment0(&client->interface->ntcpaccepting, NULL); - } - - static void -diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h -index a34286698b..28d1b79027 100644 ---- a/bin/named/include/named/interfacemgr.h -+++ b/bin/named/include/named/interfacemgr.h -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - - #include - -@@ -78,11 +79,11 @@ struct ns_interface { - dns_dispatch_t * udpdispatch[MAX_UDP_DISPATCH]; - /*%< UDP dispatchers. */ - isc_socket_t * tcpsocket; /*%< TCP socket. */ -- int32_t ntcpaccepting; /*%< Number of clients -+ isc_refcount_t ntcpaccepting; /*%< Number of clients - ready to accept new - TCP connections on this - interface */ -- int32_t ntcpactive; /*%< Number of clients -+ isc_refcount_t ntcpactive; /*%< Number of clients - servicing TCP queries - (whether accepting or - connected) */ -diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c -index ebec0c4059..a59e9afd58 100644 ---- a/bin/named/interfacemgr.c -+++ b/bin/named/interfacemgr.c -@@ -380,8 +380,8 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, - * connections will be handled in parallel even though there is - * only one client initially. - */ -- ifp->ntcpaccepting = 0; -- ifp->ntcpactive = 0; -+ isc_refcount_init(&ifp->ntcpaccepting, 0); -+ isc_refcount_init(&ifp->ntcpactive, 0); - - ifp->nudpdispatch = 0; - -@@ -595,6 +595,9 @@ ns_interface_destroy(ns_interface_t *ifp) { - - ns_interfacemgr_detach(&ifp->mgr); - -+ isc_refcount_destroy(&ifp->ntcpactive); -+ isc_refcount_destroy(&ifp->ntcpaccepting); -+ - ifp->magic = 0; - isc_mem_put(mctx, ifp, sizeof(*ifp)); - } --- -2.20.1 - diff --git a/SOURCES/bind-9.11-CVE-2018-5743.patch b/SOURCES/bind-9.11-CVE-2018-5743.patch deleted file mode 100644 index 6b8c48f..0000000 --- a/SOURCES/bind-9.11-CVE-2018-5743.patch +++ /dev/null @@ -1,864 +0,0 @@ -From 05bf4fa9056d85782dad528bba3d0fa90946d4d8 Mon Sep 17 00:00:00 2001 -From: Petr Mensik -Date: Wed, 24 Apr 2019 20:09:07 +0200 -Subject: [PATCH] 5200. [security] tcp-clients settings could be exceeded in - some cases, which could lead to exhaustion of file descriptors. - (CVE-2018-5743) [GL #615] ---- - bin/named/client.c | 428 +++++++++++++++++++------ - bin/named/include/named/client.h | 13 +- - bin/named/include/named/interfacemgr.h | 13 +- - bin/named/interfacemgr.c | 9 +- - lib/isc/include/isc/quota.h | 7 + - lib/isc/quota.c | 33 +- - 6 files changed, 389 insertions(+), 114 deletions(-) - -diff --git a/bin/named/client.c b/bin/named/client.c -index f014b61..0ba383b 100644 ---- a/bin/named/client.c -+++ b/bin/named/client.c -@@ -234,7 +234,9 @@ static void ns_client_dumpmessage(ns_client_t *client, const char *reason); - static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, - dns_dispatch_t *disp, isc_boolean_t tcp); - static isc_result_t get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, -- isc_socket_t *socket); -+ isc_socket_t *sock, ns_client_t *oldclient); -+static inline isc_boolean_t -+allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl); - - void - ns_client_recursing(ns_client_t *client) { -@@ -280,6 +282,119 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds) { - } - } - -+/*% -+ * Allocate a reference-counted object that will maintain a single pointer to -+ * the (also reference-counted) TCP client quota, shared between all the -+ * clients processing queries on a single TCP connection, so that all -+ * clients sharing the one socket will together consume only one slot in -+ * the 'tcp-clients' quota. -+ */ -+static isc_result_t -+tcpconn_init(ns_client_t *client, isc_boolean_t force) { -+ isc_result_t result; -+ isc_quota_t *quota = NULL; -+ ns_tcpconn_t *tconn = NULL; -+ -+ REQUIRE(client->tcpconn == NULL); -+ -+ /* -+ * Try to attach to the quota first, so we won't pointlessly -+ * allocate memory for a tcpconn object if we can't get one. -+ */ -+ if (force) { -+ result = isc_quota_force(&ns_g_server->tcpquota, "a); -+ } else { -+ result = isc_quota_attach(&ns_g_server->tcpquota, "a); -+ } -+ if (result != ISC_R_SUCCESS) { -+ return (result); -+ } -+ -+ /* -+ * A global memory context is used for the allocation as different -+ * client structures may have different memory contexts assigned and a -+ * reference counter allocated here might need to be freed by a -+ * different client. The performance impact caused by memory context -+ * contention here is expected to be negligible, given that this code -+ * is only executed for TCP connections. -+ */ -+ tconn = isc_mem_allocate(ns_g_mctx, sizeof(*tconn)); -+ -+ isc_refcount_init(&tconn->refs, 1); -+ tconn->tcpquota = quota; -+ quota = NULL; -+ tconn->pipelined = ISC_FALSE; -+ -+ client->tcpconn = tconn; -+ -+ return (ISC_R_SUCCESS); -+} -+ -+/*% -+ * Increase the count of client structures sharing the TCP connection -+ * that 'source' is associated with; add a pointer to the same tcpconn -+ * to 'target', thus associating it with the same TCP connection. -+ */ -+static void -+tcpconn_attach(ns_client_t *source, ns_client_t *target) { -+ int refs; -+ -+ REQUIRE(source->tcpconn != NULL); -+ REQUIRE(target->tcpconn == NULL); -+ REQUIRE(source->tcpconn->pipelined); -+ -+ isc_refcount_increment(&source->tcpconn->refs, &refs); -+ INSIST(refs > 1); -+ target->tcpconn = source->tcpconn; -+} -+ -+/*% -+ * Decrease the count of client structures sharing the TCP connection that -+ * 'client' is associated with. If this is the last client using this TCP -+ * connection, we detach from the TCP quota and free the tcpconn -+ * object. Either way, client->tcpconn is set to NULL. -+ */ -+static void -+tcpconn_detach(ns_client_t *client) { -+ ns_tcpconn_t *tconn = NULL; -+ int refs; -+ -+ REQUIRE(client->tcpconn != NULL); -+ -+ tconn = client->tcpconn; -+ client->tcpconn = NULL; -+ -+ isc_refcount_decrement(&tconn->refs, &refs); -+ if (refs == 0) { -+ isc_quota_detach(&tconn->tcpquota); -+ isc_mem_free(ns_g_mctx, tconn); -+ } -+} -+ -+/*% -+ * Mark a client as active and increment the interface's 'ntcpactive' -+ * counter, as a signal that there is at least one client servicing -+ * TCP queries for the interface. If we reach the TCP client quota at -+ * some point, this will be used to determine whether a quota overrun -+ * should be permitted. -+ * -+ * Marking the client active with the 'tcpactive' flag ensures proper -+ * accounting, by preventing us from incrementing or decrementing -+ * 'ntcpactive' more than once per client. -+ */ -+static void -+mark_tcp_active(ns_client_t *client, isc_boolean_t active) { -+ if (active && !client->tcpactive) { -+ isc_atomic_xadd(&client->interface->ntcpactive, 1); -+ client->tcpactive = active; -+ } else if (!active && client->tcpactive) { -+ uint32_t old = -+ isc_atomic_xadd(&client->interface->ntcpactive, -1); -+ INSIST(old > 0); -+ client->tcpactive = active; -+ } -+} -+ - /*% - * Check for a deactivation or shutdown request and take appropriate - * action. Returns ISC_TRUE if either is in progress; in this case -@@ -369,7 +484,8 @@ exit_check(ns_client_t *client) { - INSIST(client->recursionquota == NULL); - - if (NS_CLIENTSTATE_READING == client->newstate) { -- if (!client->pipelined) { -+ INSIST(client->tcpconn != NULL); -+ if (!client->tcpconn->pipelined) { - client_read(client); - client->newstate = NS_CLIENTSTATE_MAX; - return (ISC_TRUE); /* We're done. */ -@@ -386,10 +502,13 @@ exit_check(ns_client_t *client) { - */ - INSIST(client->recursionquota == NULL); - INSIST(client->newstate <= NS_CLIENTSTATE_READY); -- if (client->nreads > 0) -+ -+ if (client->nreads > 0) { - dns_tcpmsg_cancelread(&client->tcpmsg); -- if (! client->nreads == 0) { -- /* Still waiting for read cancel completion. */ -+ } -+ -+ /* Still waiting for read cancel completion. */ -+ if (client->nreads > 0) { - return (ISC_TRUE); - } - -@@ -397,14 +516,49 @@ exit_check(ns_client_t *client) { - dns_tcpmsg_invalidate(&client->tcpmsg); - client->tcpmsg_valid = ISC_FALSE; - } -+ -+ /* -+ * Soon the client will be ready to accept a new TCP -+ * connection or UDP request, but we may have enough -+ * clients doing that already. Check whether this client -+ * needs to remain active and allow it go inactive if -+ * not. -+ * -+ * UDP clients always go inactive at this point, but a TCP -+ * client may need to stay active and return to READY -+ * state if no other clients are available to listen -+ * for TCP requests on this interface. -+ * -+ * Regardless, if we're going to FREED state, that means -+ * the system is shutting down and we don't need to -+ * retain clients. -+ */ -+ if (client->mortal && TCP_CLIENT(client) && -+ client->newstate != NS_CLIENTSTATE_FREED && -+ !ns_g_clienttest && -+ isc_atomic_xadd(&client->interface->ntcpaccepting, 0) == 0) -+ { -+ /* Nobody else is accepting */ -+ client->mortal = ISC_FALSE; -+ client->newstate = NS_CLIENTSTATE_READY; -+ } -+ -+ /* -+ * Detach from TCP connection and TCP client quota, -+ * if appropriate. If this is the last reference to -+ * the TCP connection in our pipeline group, the -+ * TCP quota slot will be released. -+ */ -+ if (client->tcpconn) { -+ tcpconn_detach(client); -+ } -+ - if (client->tcpsocket != NULL) { - CTRACE("closetcp"); - isc_socket_detach(&client->tcpsocket); -+ mark_tcp_active(client, ISC_FALSE); - } - -- if (client->tcpquota != NULL) -- isc_quota_detach(&client->tcpquota); -- - if (client->timerset) { - (void)isc_timer_reset(client->timer, - isc_timertype_inactive, -@@ -412,45 +566,26 @@ exit_check(ns_client_t *client) { - client->timerset = ISC_FALSE; - } - -- client->pipelined = ISC_FALSE; -- - client->peeraddr_valid = ISC_FALSE; - - client->state = NS_CLIENTSTATE_READY; -- INSIST(client->recursionquota == NULL); -- -- /* -- * Now the client is ready to accept a new TCP connection -- * or UDP request, but we may have enough clients doing -- * that already. Check whether this client needs to remain -- * active and force it to go inactive if not. -- * -- * UDP clients go inactive at this point, but TCP clients -- * may remain active if we have fewer active TCP client -- * objects than desired due to an earlier quota exhaustion. -- */ -- if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) { -- LOCK(&client->interface->lock); -- if (client->interface->ntcpcurrent < -- client->interface->ntcptarget) -- client->mortal = ISC_FALSE; -- UNLOCK(&client->interface->lock); -- } - - /* - * We don't need the client; send it to the inactive - * queue for recycling. - */ - if (client->mortal) { -- if (client->newstate > NS_CLIENTSTATE_INACTIVE) -+ if (client->newstate > NS_CLIENTSTATE_INACTIVE) { - client->newstate = NS_CLIENTSTATE_INACTIVE; -+ } - } - - if (NS_CLIENTSTATE_READY == client->newstate) { - if (TCP_CLIENT(client)) { - client_accept(client); -- } else -+ } else { - client_udprecv(client); -+ } - client->newstate = NS_CLIENTSTATE_MAX; - return (ISC_TRUE); - } -@@ -462,41 +597,51 @@ exit_check(ns_client_t *client) { - /* - * We are trying to enter the inactive state. - */ -- if (client->naccepts > 0) -+ if (client->naccepts > 0) { - isc_socket_cancel(client->tcplistener, client->task, - ISC_SOCKCANCEL_ACCEPT); -+ } - - /* Still waiting for accept cancel completion. */ -- if (! (client->naccepts == 0)) -+ if (client->naccepts > 0) { - return (ISC_TRUE); -+ } - - /* Accept cancel is complete. */ -- if (client->nrecvs > 0) -+ if (client->nrecvs > 0) { - isc_socket_cancel(client->udpsocket, client->task, - ISC_SOCKCANCEL_RECV); -+ } - - /* Still waiting for recv cancel completion. */ -- if (! (client->nrecvs == 0)) -+ if (client->nrecvs > 0) { - return (ISC_TRUE); -+ } - - /* Still waiting for control event to be delivered */ -- if (client->nctls > 0) -+ if (client->nctls > 0) { - return (ISC_TRUE); -- -- /* Deactivate the client. */ -- if (client->interface) -- ns_interface_detach(&client->interface); -+ } - - INSIST(client->naccepts == 0); - INSIST(client->recursionquota == NULL); -- if (client->tcplistener != NULL) -+ if (client->tcplistener != NULL) { - isc_socket_detach(&client->tcplistener); -+ mark_tcp_active(client, ISC_FALSE); -+ } - -- if (client->udpsocket != NULL) -+ if (client->udpsocket != NULL) { - isc_socket_detach(&client->udpsocket); -+ } - -- if (client->dispatch != NULL) -+ /* Deactivate the client. */ -+ if (client->interface != NULL) { -+ ns_interface_detach(&client->interface); -+ } -+ -+ if (client->dispatch != NULL) { - dns_dispatch_detach(&client->dispatch); -+ } - - client->attributes = 0; - client->mortal = ISC_FALSE; -@@ -515,10 +660,13 @@ exit_check(ns_client_t *client) { - client->newstate = NS_CLIENTSTATE_MAX; - if (!ns_g_clienttest && manager != NULL && - !manager->exiting) -+ { - ISC_QUEUE_PUSH(manager->inactive, client, - ilink); -- if (client->needshutdown) -+ } -+ if (client->needshutdown) { - isc_task_shutdown(client->task); -+ } - return (ISC_TRUE); - } - } -@@ -613,7 +761,7 @@ client_start(isc_task_t *task, isc_event_t *event) { - return; - - if (TCP_CLIENT(client)) { -- if (client->pipelined) { -+ if (client->tcpconn != NULL) { - client_read(client); - } else { - client_accept(client); -@@ -623,7 +771,6 @@ client_start(isc_task_t *task, isc_event_t *event) { - } - } - -- - /*% - * The client's task has received a shutdown event. - */ -@@ -1511,6 +1658,7 @@ client_request(isc_task_t *task, isc_event_t *event) { - client->nrecvs--; - } else { - INSIST(TCP_CLIENT(client)); -+ INSIST(client->tcpconn != NULL); - REQUIRE(event->ev_type == DNS_EVENT_TCPMSG); - REQUIRE(event->ev_sender == &client->tcpmsg); - buffer = &client->tcpmsg.buffer; -@@ -1653,18 +1801,27 @@ client_request(isc_task_t *task, isc_event_t *event) { - /* - * Pipeline TCP query processing. - */ -- if (client->message->opcode != dns_opcode_query) -- client->pipelined = ISC_FALSE; -- if (TCP_CLIENT(client) && client->pipelined) { -- result = isc_quota_reserve(&ns_g_server->tcpquota); -- if (result == ISC_R_SUCCESS) -- result = ns_client_replace(client); -+ if (TCP_CLIENT(client) && -+ client->message->opcode != dns_opcode_query) -+ { -+ client->tcpconn->pipelined = ISC_FALSE; -+ } -+ if (TCP_CLIENT(client) && client->tcpconn->pipelined) { -+ /* -+ * We're pipelining. Replace the client; the -+ * replacement can read the TCP socket looking -+ * for new messages and this one can process the -+ * current message asynchronously. -+ * -+ * There will now be at least three clients using this -+ * TCP socket - one accepting new connections, -+ * one reading an existing connection to get new -+ * messages, and one answering the message already -+ * received. -+ */ -+ result = ns_client_replace(client); - if (result != ISC_R_SUCCESS) { -- ns_client_log(client, NS_LOGCATEGORY_CLIENT, -- NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, -- "no more TCP clients(read): %s", -- isc_result_totext(result)); -- client->pipelined = ISC_FALSE; -+ client->tcpconn->pipelined = ISC_FALSE; - } - } - -@@ -2168,8 +2325,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { - client->signer = NULL; - dns_name_init(&client->signername, NULL); - client->mortal = ISC_FALSE; -- client->pipelined = ISC_FALSE; -- client->tcpquota = NULL; -+ client->tcpconn = NULL; - client->recursionquota = NULL; - client->interface = NULL; - client->peeraddr_valid = ISC_FALSE; -@@ -2177,6 +2333,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { - client->filter_aaaa = dns_v4_aaaa_ok; - #endif - client->needshutdown = ns_g_clienttest; -+ client->tcpactive = ISC_FALSE; - - ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL, - NS_EVENT_CLIENTCONTROL, client_start, client, client, -@@ -2269,9 +2426,10 @@ client_read(ns_client_t *client) { - - static void - client_newconn(isc_task_t *task, isc_event_t *event) { -+ isc_result_t result; - ns_client_t *client = event->ev_arg; - isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event; -- isc_result_t result; -+ uint32_t old; - - REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN); - REQUIRE(NS_CLIENT_VALID(client)); -@@ -2281,13 +2439,18 @@ client_newconn(isc_task_t *task, isc_event_t *event) { - - INSIST(client->state == NS_CLIENTSTATE_READY); - -+ /* -+ * The accept() was successful and we're now establishing a new -+ * connection. We need to make note of it in the client and -+ * interface objects so client objects can do the right thing -+ * when going inactive in exit_check() (see comments in -+ * client_accept() for details). -+ */ - INSIST(client->naccepts == 1); - client->naccepts--; - -- LOCK(&client->interface->lock); -- INSIST(client->interface->ntcpcurrent > 0); -- client->interface->ntcpcurrent--; -- UNLOCK(&client->interface->lock); -+ old = isc_atomic_xadd(&client->interface->ntcpaccepting, -1); -+ INSIST(old > 0); - - /* - * We must take ownership of the new socket before the exit -@@ -2320,6 +2483,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { - NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), - "accept failed: %s", - isc_result_totext(nevent->result)); -+ tcpconn_detach(client); - } - - if (exit_check(client)) -@@ -2357,20 +2521,13 @@ client_newconn(isc_task_t *task, isc_event_t *event) { - * telnetting to port 53 (once per CPU) will - * deny service to legitimate TCP clients. - */ -- client->pipelined = ISC_FALSE; -- result = isc_quota_attach(&ns_g_server->tcpquota, -- &client->tcpquota); -- if (result == ISC_R_SUCCESS) -- result = ns_client_replace(client); -- if (result != ISC_R_SUCCESS) { -- ns_client_log(client, NS_LOGCATEGORY_CLIENT, -- NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, -- "no more TCP clients(accept): %s", -- isc_result_totext(result)); -- } else if (ns_g_server->keepresporder == NULL || -- !allowed(&netaddr, NULL, NULL, 0, NULL, -- ns_g_server->keepresporder)) { -- client->pipelined = ISC_TRUE; -+ result = ns_client_replace(client); -+ if (result == ISC_R_SUCCESS && -+ (ns_g_server->keepresporder == NULL || -+ !allowed(&netaddr, NULL, -+ ns_g_server->keepresporder))) -+ { -+ client->tcpconn->pipelined = ISC_TRUE; - } - - client_read(client); -@@ -2386,12 +2543,66 @@ client_accept(ns_client_t *client) { - - CTRACE("accept"); - -+ /* -+ * Set up a new TCP connection. This means try to attach to the -+ * TCP client quota (tcp-clients), but fail if we're over quota. -+ */ -+ result = tcpconn_init(client, ISC_FALSE); -+ if (result != ISC_R_SUCCESS) { -+ isc_boolean_t exit; -+ -+ ns_client_log(client, NS_LOGCATEGORY_CLIENT, -+ NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, -+ "TCP client quota reached: %s", -+ isc_result_totext(result)); -+ -+ /* -+ * We have exceeded the system-wide TCP client quota. But, -+ * we can't just block this accept in all cases, because if -+ * we did, a heavy TCP load on other interfaces might cause -+ * this interface to be starved, with no clients able to -+ * accept new connections. -+ * -+ * So, we check here to see if any other clients are -+ * already servicing TCP queries on this interface (whether -+ * accepting, reading, or processing). If we find that at -+ * least one client other than this one is active, then -+ * it's okay *not* to call accept - we can let this -+ * client go inactive and another will take over when it's -+ * done. -+ * -+ * If there aren't enough active clients on the interface, -+ * then we can be a little bit flexible about the quota. -+ * We'll allow *one* extra client through to ensure we're -+ * listening on every interface; we do this by setting the -+ * 'force' option to tcpconn_init(). -+ * -+ * (Note: In practice this means that the real TCP client -+ * quota is tcp-clients plus the number of listening -+ * interfaces plus 1.) -+ */ -+ exit = (isc_atomic_xadd(&client->interface->ntcpactive, 0) > -+ (client->tcpactive ? 1 : 0)); -+ if (exit) { -+ client->newstate = NS_CLIENTSTATE_INACTIVE; -+ (void)exit_check(client); -+ return; -+ } -+ -+ result = tcpconn_init(client, ISC_TRUE); -+ RUNTIME_CHECK(result == ISC_R_SUCCESS); -+ } -+ -+ /* -+ * If this client was set up using get_client() or get_worker(), -+ * then TCP is already marked active. However, if it was restarted -+ * from exit_check(), it might not be, so we take care of it now. -+ */ -+ mark_tcp_active(client, ISC_TRUE); -+ - result = isc_socket_accept(client->tcplistener, client->task, - client_newconn, client); - if (result != ISC_R_SUCCESS) { -- UNEXPECTED_ERROR(__FILE__, __LINE__, -- "isc_socket_accept() failed: %s", -- isc_result_totext(result)); - /* - * XXXRTH What should we do? We're trying to accept but - * it didn't work. If we just give up, then TCP -@@ -2399,13 +2610,37 @@ client_accept(ns_client_t *client) { - * - * For now, we just go idle. - */ -+ UNEXPECTED_ERROR(__FILE__, __LINE__, -+ "isc_socket_accept() failed: %s", -+ isc_result_totext(result)); -+ -+ tcpconn_detach(client); -+ mark_tcp_active(client, ISC_FALSE); - return; - } -+ -+ /* -+ * The client's 'naccepts' counter indicates that this client has -+ * called accept() and is waiting for a new connection. It should -+ * never exceed 1. -+ */ - INSIST(client->naccepts == 0); - client->naccepts++; -- LOCK(&client->interface->lock); -- client->interface->ntcpcurrent++; -- UNLOCK(&client->interface->lock); -+ -+ /* -+ * The interface's 'ntcpaccepting' counter is incremented when -+ * any client calls accept(), and decremented in client_newconn() -+ * once the connection is established. -+ * -+ * When the client object is shutting down after handling a TCP -+ * request (see exit_check()), if this value is at least one, that -+ * means another client has called accept() and is waiting to -+ * establish the next connection. That means the client may be -+ * be free to become inactive; otherwise it may need to start -+ * listening for connections itself to prevent the interface -+ * going dead. -+ */ -+ isc_atomic_xadd(&client->interface->ntcpaccepting, 1); - } - - static void -@@ -2476,15 +2711,17 @@ ns_client_replace(ns_client_t *client) { - REQUIRE(client->manager != NULL); - - tcp = TCP_CLIENT(client); -- if (tcp && client->pipelined) { -+ if (tcp && client->tcpconn != NULL && client->tcpconn->pipelined) { - result = get_worker(client->manager, client->interface, -- client->tcpsocket); -+ client->tcpsocket, client); - } else { - result = get_client(client->manager, client->interface, - client->dispatch, tcp); -+ - } -- if (result != ISC_R_SUCCESS) -+ if (result != ISC_R_SUCCESS) { - return (result); -+ } - - /* - * The responsibility for listening for new requests is hereby -@@ -2668,9 +2905,12 @@ get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, - INSIST(client->recursionquota == NULL); - - if (tcp) { -+ mark_tcp_active(client, ISC_TRUE); -+ - client->attributes |= NS_CLIENTATTR_TCP; - isc_socket_attach(ifp->tcpsocket, - &client->tcplistener); -+ - } else { - isc_socket_t *sock; - -@@ -2688,7 +2928,8 @@ get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, - } - - static isc_result_t --get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *socket) -+get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock, -+ ns_client_t *oldclient) - { - isc_result_t result = ISC_R_SUCCESS; - isc_event_t *ev; -@@ -2696,6 +2937,7 @@ get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *socket) - MTRACE("get worker"); - - REQUIRE(manager != NULL); -+ REQUIRE(oldclient != NULL); - - if (manager->exiting) - return (ISC_R_SHUTTINGDOWN); -@@ -2728,15 +2970,15 @@ get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *socket) - ns_interface_attach(ifp, &client->interface); - client->newstate = client->state = NS_CLIENTSTATE_WORKING; - INSIST(client->recursionquota == NULL); -- client->tcpquota = &ns_g_server->tcpquota; -- -- client->dscp = ifp->dscp; - - client->attributes |= NS_CLIENTATTR_TCP; -- client->pipelined = ISC_TRUE; -+ client->mortal = ISC_TRUE; -+ -+ tcpconn_attach(oldclient, client); -+ mark_tcp_active(client, ISC_TRUE); - - isc_socket_attach(ifp->tcpsocket, &client->tcplistener); -- isc_socket_attach(socket, &client->tcpsocket); -+ isc_socket_attach(sock, &client->tcpsocket); - isc_socket_setname(client->tcpsocket, "worker-tcp", NULL); - (void)isc_socket_getpeername(client->tcpsocket, &client->peeraddr); - client->peeraddr_valid = ISC_TRUE; -diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h -index bf4d201..ef55a7a 100644 ---- a/bin/named/include/named/client.h -+++ b/bin/named/include/named/client.h -@@ -15,8 +15,6 @@ - * PERFORMANCE OF THIS SOFTWARE. - */ - --/* $Id$ */ -- - #ifndef NAMED_CLIENT_H - #define NAMED_CLIENT_H 1 - -@@ -83,6 +81,13 @@ - *** Types - ***/ - -+/*% reference-counted TCP connection object */ -+typedef struct ns_tcpconn { -+ isc_refcount_t refs; -+ isc_quota_t *tcpquota; -+ isc_boolean_t pipelined; -+} ns_tcpconn_t; -+ - /*% nameserver client structure */ - struct ns_client { - unsigned int magic; -@@ -133,8 +138,8 @@ struct ns_client { - dns_name_t signername; /*%< [T]SIG key name */ - dns_name_t * signer; /*%< NULL if not valid sig */ - isc_boolean_t mortal; /*%< Die after handling request */ -- isc_boolean_t pipelined; /*%< TCP queries not in sequence */ -- isc_quota_t *tcpquota; -+ isc_boolean_t tcpactive; -+ ns_tcpconn_t *tcpconn; - isc_quota_t *recursionquota; - ns_interface_t *interface; - isc_sockaddr_t peeraddr; -diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h -index 380dbed..a342866 100644 ---- a/bin/named/include/named/interfacemgr.h -+++ b/bin/named/include/named/interfacemgr.h -@@ -15,8 +15,6 @@ - * PERFORMANCE OF THIS SOFTWARE. - */ - --/* $Id: interfacemgr.h,v 1.35 2011/07/28 23:47:58 tbox Exp $ */ -- - #ifndef NAMED_INTERFACEMGR_H - #define NAMED_INTERFACEMGR_H 1 - -@@ -80,9 +78,14 @@ struct ns_interface { - dns_dispatch_t * udpdispatch[MAX_UDP_DISPATCH]; - /*%< UDP dispatchers. */ - isc_socket_t * tcpsocket; /*%< TCP socket. */ -- int ntcptarget; /*%< Desired number of concurrent -- TCP accepts */ -- int ntcpcurrent; /*%< Current ditto, locked */ -+ int32_t ntcpaccepting; /*%< Number of clients -+ ready to accept new -+ TCP connections on this -+ interface */ -+ int32_t ntcpactive; /*%< Number of clients -+ servicing TCP queries -+ (whether accepting or -+ connected) */ - int nudpdispatch; /*%< Number of UDP dispatches */ - ns_clientmgr_t * clientmgr; /*%< Client manager. */ - ISC_LINK(ns_interface_t) link; -diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c -index 4aee47a..ebec0c4 100644 ---- a/bin/named/interfacemgr.c -+++ b/bin/named/interfacemgr.c -@@ -380,8 +380,9 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, - * connections will be handled in parallel even though there is - * only one client initially. - */ -- ifp->ntcptarget = 1; -- ifp->ntcpcurrent = 0; -+ ifp->ntcpaccepting = 0; -+ ifp->ntcpactive = 0; -+ - ifp->nudpdispatch = 0; - - ISC_LINK_INIT(ifp, link); -@@ -510,9 +511,7 @@ ns_interface_accepttcp(ns_interface_t *ifp) { - */ - (void)isc_socket_filter(ifp->tcpsocket, "dataready"); - -- result = ns_clientmgr_createclients(ifp->clientmgr, -- ifp->ntcptarget, ifp, -- ISC_TRUE); -+ result = ns_clientmgr_createclients(ifp->clientmgr, 1, ifp, ISC_TRUE); - if (result != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "TCP ns_clientmgr_createclients(): %s", -diff --git a/lib/isc/include/isc/quota.h b/lib/isc/include/isc/quota.h -index 7b0d0d9..bb1a927 100644 ---- a/lib/isc/include/isc/quota.h -+++ b/lib/isc/include/isc/quota.h -@@ -107,6 +107,13 @@ isc_quota_attach(isc_quota_t *quota, isc_quota_t **p); - * quota if successful (ISC_R_SUCCESS or ISC_R_SOFTQUOTA). - */ - -+isc_result_t -+isc_quota_force(isc_quota_t *quota, isc_quota_t **p); -+/*%< -+ * Like isc_quota_attach, but will attach '*p' to the quota -+ * even if the hard quota has been exceeded. -+ */ -+ - void - isc_quota_detach(isc_quota_t **p); - /*%< -diff --git a/lib/isc/quota.c b/lib/isc/quota.c -index 5e5c50c..ca4c478 100644 ---- a/lib/isc/quota.c -+++ b/lib/isc/quota.c -@@ -81,20 +81,39 @@ isc_quota_release(isc_quota_t *quota) { - UNLOCK("a->lock); - } - --isc_result_t --isc_quota_attach(isc_quota_t *quota, isc_quota_t **p) --{ -+static isc_result_t -+doattach(isc_quota_t *quota, isc_quota_t **p, isc_boolean_t force) { - isc_result_t result; -- INSIST(p != NULL && *p == NULL); -+ REQUIRE(p != NULL && *p == NULL); -+ - result = isc_quota_reserve(quota); -- if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA) -+ if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA) { -+ *p = quota; -+ } else if (result == ISC_R_QUOTA && force) { -+ /* attach anyway */ -+ LOCK("a->lock); -+ quota->used++; -+ UNLOCK("a->lock); -+ - *p = quota; -+ result = ISC_R_SUCCESS; -+ } -+ - return (result); - } - -+isc_result_t -+isc_quota_attach(isc_quota_t *quota, isc_quota_t **p) { -+ return (doattach(quota, p, ISC_FALSE)); -+} -+ -+isc_result_t -+isc_quota_force(isc_quota_t *quota, isc_quota_t **p) { -+ return (doattach(quota, p, ISC_TRUE)); -+} -+ - void --isc_quota_detach(isc_quota_t **p) --{ -+isc_quota_detach(isc_quota_t **p) { - INSIST(p != NULL && *p != NULL); - isc_quota_release(*p); - *p = NULL; --- -2.20.1 - diff --git a/SOURCES/bind-9.11-rt37039.patch b/SOURCES/bind-9.11-rt37039.patch deleted file mode 100644 index aa11ed6..0000000 --- a/SOURCES/bind-9.11-rt37039.patch +++ /dev/null @@ -1,380 +0,0 @@ -From f34cc4f62cd6730fc315ace47b9ae90a82a07ec0 Mon Sep 17 00:00:00 2001 -From: Mark Andrews -Date: Thu, 4 Sep 2014 10:37:45 +1000 -Subject: [PATCH] 3939. [func] Improve UPDATE forwarding performance by - allowing TCP connections to be shared. [RT #37039] - -(cherry picked from commit 74717eef53ba5d6aefc80eb262bbb090ff4bb3b5) ---- - lib/dns/dispatch.c | 112 ++++++++++++++++++++++++++++++++- - lib/dns/include/dns/dispatch.h | 15 +++++ - lib/dns/request.c | 46 ++++++++++---- - lib/dns/win32/libdns.def | 2 + - 4 files changed, 159 insertions(+), 16 deletions(-) - -diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c -index c93651d..ee82241 100644 ---- a/lib/dns/dispatch.c -+++ b/lib/dns/dispatch.c -@@ -228,6 +228,7 @@ struct dns_dispatch { - isc_socket_t *socket; /*%< isc socket attached to */ - isc_sockaddr_t local; /*%< local address */ - in_port_t localport; /*%< local UDP port */ -+ isc_sockaddr_t peer; /*%< peer address (TCP) */ - unsigned int maxrequests; /*%< max requests */ - isc_event_t *ctlevent; - -@@ -2327,7 +2328,6 @@ dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) { - - LOCK(&mgr->lock); - mgr->state |= MGR_SHUTTINGDOWN; -- - killit = destroy_mgr_ok(mgr); - UNLOCK(&mgr->lock); - -@@ -2601,6 +2601,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests, - disp->refcount = 1; - disp->recv_pending = 0; - memset(&disp->local, 0, sizeof(disp->local)); -+ memset(&disp->peer, 0, sizeof(disp->peer)); - disp->localport = 0; - disp->shutting_down = 0; - disp->shutdown_out = 0; -@@ -2702,6 +2703,23 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, - unsigned int buckets, unsigned int increment, - unsigned int attributes, dns_dispatch_t **dispp) - { -+ -+ attributes |= DNS_DISPATCHATTR_PRIVATE; /* XXXMLG */ -+ -+ return (dns_dispatch_createtcp2(mgr, sock, taskmgr, NULL, NULL, -+ buffersize, maxbuffers, maxrequests, -+ buckets, increment, attributes, -+ dispp)); -+} -+ -+isc_result_t -+dns_dispatch_createtcp2(dns_dispatchmgr_t *mgr, isc_socket_t *sock, -+ isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr, -+ isc_sockaddr_t *destaddr, unsigned int buffersize, -+ unsigned int maxbuffers, unsigned int maxrequests, -+ unsigned int buckets, unsigned int increment, -+ unsigned int attributes, dns_dispatch_t **dispp) -+{ - isc_result_t result; - dns_dispatch_t *disp; - -@@ -2713,7 +2731,8 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, - REQUIRE((attributes & DNS_DISPATCHATTR_TCP) != 0); - REQUIRE((attributes & DNS_DISPATCHATTR_UDP) == 0); - -- attributes |= DNS_DISPATCHATTR_PRIVATE; /* XXXMLG */ -+ if (destaddr == NULL) -+ attributes |= DNS_DISPATCHATTR_PRIVATE; /* XXXMLG */ - - LOCK(&mgr->lock); - -@@ -2760,6 +2779,23 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, - - disp->attributes = attributes; - -+ if (localaddr == NULL) { -+ if (destaddr != NULL) { -+ switch (isc_sockaddr_pf(destaddr)) { -+ case AF_INET: -+ isc_sockaddr_any(&disp->local); -+ break; -+ case AF_INET6: -+ isc_sockaddr_any6(&disp->local); -+ break; -+ } -+ } -+ } else -+ disp->local = *localaddr; -+ -+ if (destaddr != NULL) -+ disp->peer = *destaddr; -+ - /* - * Append it to the dispatcher list. - */ -@@ -2768,7 +2804,6 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, - - mgr_log(mgr, LVL(90), "created TCP dispatcher %p", disp); - dispatch_log(disp, LVL(90), "created task %p", disp->task[0]); -- - *dispp = disp; - - return (ISC_R_SUCCESS); -@@ -2788,6 +2823,77 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, - return (result); - } - -+isc_result_t -+dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr, -+ isc_sockaddr_t *localaddr, dns_dispatch_t **dispp) -+{ -+#ifdef BIND9 -+ dns_dispatch_t *disp; -+ isc_result_t result; -+ isc_sockaddr_t peeraddr; -+ isc_sockaddr_t sockname; -+ isc_sockaddr_t any; -+ unsigned int attributes, mask; -+ isc_boolean_t match = ISC_FALSE; -+ -+ REQUIRE(VALID_DISPATCHMGR(mgr)); -+ REQUIRE(destaddr != NULL); -+ REQUIRE(dispp != NULL && *dispp == NULL); -+ -+ attributes = DNS_DISPATCHATTR_TCP; -+ mask = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_PRIVATE | -+ DNS_DISPATCHATTR_EXCLUSIVE; -+ -+ if (localaddr == NULL) { -+ switch (isc_sockaddr_pf(destaddr)) { -+ case AF_INET: -+ isc_sockaddr_any(&any); -+ break; -+ case AF_INET6: -+ isc_sockaddr_any6(&any); -+ break; -+ default: -+ return (ISC_R_NOTFOUND); -+ } -+ localaddr = &any; -+ } -+ -+ LOCK(&mgr->lock); -+ disp = ISC_LIST_HEAD(mgr->list); -+ while (disp != NULL && !match) { -+ LOCK(&disp->lock); -+ if ((disp->shutting_down == 0) && -+ ATTRMATCH(disp->attributes, attributes, mask) && -+ (localaddr == NULL || -+ isc_sockaddr_eqaddr(localaddr, &disp->local))) { -+ result = isc_socket_getsockname(disp->socket, -+ &sockname); -+ if (result == ISC_R_SUCCESS) -+ result = isc_socket_getpeername(disp->socket, -+ &peeraddr); -+ if (result == ISC_R_SUCCESS && -+ isc_sockaddr_equal(destaddr, &peeraddr) && -+ isc_sockaddr_eqaddr(localaddr, &sockname)) { -+ /* attach */ -+ disp->refcount++; -+ *dispp = disp; -+ match = ISC_TRUE; -+ } -+ } -+ UNLOCK(&disp->lock); -+ disp = ISC_LIST_NEXT(disp, link); -+ } -+ UNLOCK(&mgr->lock); -+ return (match ? ISC_R_SUCCESS : ISC_R_NOTFOUND); -+#else -+ UNUSED(mgr); -+ UNUSED(destaddr); -+ UNUSED(localaddr); -+ UNUSED(dispp); -+ return ISC_R_NOTIMPLEMENTED; -+#endif -+} -+ - isc_result_t - dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, - isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr, -diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h -index 1235f7c..be9cd66 100644 ---- a/lib/dns/include/dns/dispatch.h -+++ b/lib/dns/include/dns/dispatch.h -@@ -298,6 +298,13 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, - unsigned int maxbuffers, unsigned int maxrequests, - unsigned int buckets, unsigned int increment, - unsigned int attributes, dns_dispatch_t **dispp); -+isc_result_t -+dns_dispatch_createtcp2(dns_dispatchmgr_t *mgr, isc_socket_t *sock, -+ isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr, -+ isc_sockaddr_t *destaddr, unsigned int buffersize, -+ unsigned int maxbuffers, unsigned int maxrequests, -+ unsigned int buckets, unsigned int increment, -+ unsigned int attributes, dns_dispatch_t **dispp); - /*%< - * Create a new dns_dispatch and attach it to the provided isc_socket_t. - * -@@ -369,6 +376,14 @@ dns_dispatch_starttcp(dns_dispatch_t *disp); - *\li 'disp' is valid. - */ - -+isc_result_t -+dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr, -+ isc_sockaddr_t *localaddr, dns_dispatch_t **dispp); -+/* -+ * Attempt to connect to a existing TCP connection. -+ */ -+ -+ - isc_result_t - dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, - isc_task_t *task, isc_taskaction_t action, void *arg, -diff --git a/lib/dns/request.c b/lib/dns/request.c -index 5c76f9a..9fb6f44 100644 ---- a/lib/dns/request.c -+++ b/lib/dns/request.c -@@ -510,7 +510,8 @@ isblackholed(dns_dispatchmgr_t *dispatchmgr, isc_sockaddr_t *destaddr) { - - static isc_result_t - create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr, -- isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp) -+ isc_sockaddr_t *destaddr, isc_boolean_t *connected, -+ dns_dispatch_t **dispatchp) - { - isc_result_t result; - isc_socket_t *socket = NULL; -@@ -518,6 +519,20 @@ create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr, - unsigned int attrs; - isc_sockaddr_t bind_any; - -+ *connected = ISC_FALSE; -+#ifdef BIND9 -+ result = dns_dispatch_gettcp(requestmgr->dispatchmgr, destaddr, -+ srcaddr, dispatchp); -+ if (result == ISC_R_SUCCESS) { -+ *connected = ISC_TRUE; -+ char peer[ISC_SOCKADDR_FORMATSIZE]; -+ isc_sockaddr_format(destaddr, peer, sizeof(peer)); -+ req_log(ISC_LOG_DEBUG(1), "attached to existing TCP " -+ "connection to %s", peer); -+ return (result); -+ } -+#endif -+ - result = isc_socket_create(requestmgr->socketmgr, - isc_sockaddr_pf(destaddr), - isc_sockettype_tcp, &socket); -@@ -538,16 +553,16 @@ create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr, - #endif - attrs = 0; - attrs |= DNS_DISPATCHATTR_TCP; -- attrs |= DNS_DISPATCHATTR_PRIVATE; - if (isc_sockaddr_pf(destaddr) == AF_INET) - attrs |= DNS_DISPATCHATTR_IPV4; - else - attrs |= DNS_DISPATCHATTR_IPV6; - attrs |= DNS_DISPATCHATTR_MAKEQUERY; -- result = dns_dispatch_createtcp(requestmgr->dispatchmgr, -- socket, requestmgr->taskmgr, -- 4096, 2, 1, 1, 3, attrs, -- dispatchp); -+ result = dns_dispatch_createtcp2(requestmgr->dispatchmgr, -+ socket, requestmgr->taskmgr, -+ srcaddr, destaddr, -+ 4096, 32768, 32768, 16411, 16433, -+ attrs, dispatchp); - cleanup: - isc_socket_detach(&socket); - return (result); -@@ -609,12 +624,15 @@ find_udp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr, - static isc_result_t - get_dispatch(isc_boolean_t tcp, dns_requestmgr_t *requestmgr, - isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, -+ isc_boolean_t *connected, - dns_dispatch_t **dispatchp) - { - isc_result_t result; -+ - if (tcp) - result = create_tcp_dispatch(requestmgr, srcaddr, -- destaddr, dispatchp); -+ destaddr, connected, -+ dispatchp); - else - result = find_udp_dispatch(requestmgr, srcaddr, - destaddr, dispatchp); -@@ -686,6 +704,7 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, - dns_messageid_t id; - isc_boolean_t tcp = ISC_FALSE; - isc_region_t r; -+ isc_boolean_t connected = ISC_FALSE; - - REQUIRE(VALID_REQUESTMGR(requestmgr)); - REQUIRE(msgbuf != NULL); -@@ -747,7 +766,7 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, - tcp = ISC_TRUE; - - result = get_dispatch(tcp, requestmgr, srcaddr, destaddr, -- &request->dispatch); -+ &connected, &request->dispatch); - if (result != ISC_R_SUCCESS) - goto cleanup; - -@@ -794,14 +813,14 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, - goto unlink; - - request->destaddr = *destaddr; -- if (tcp) { -+ if (tcp && !connected) { - result = isc_socket_connect(socket, destaddr, task, - req_connected, request); - if (result != ISC_R_SUCCESS) - goto unlink; - request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP; - } else { -- result = req_send(request, task, destaddr); -+ result = req_send(request, task, connected ? NULL : destaddr); - if (result != ISC_R_SUCCESS) - goto unlink; - } -@@ -886,6 +905,7 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message, - dns_messageid_t id; - isc_boolean_t tcp; - isc_boolean_t setkey = ISC_TRUE; -+ isc_boolean_t connected = ISC_FALSE; - - REQUIRE(VALID_REQUESTMGR(requestmgr)); - REQUIRE(message != NULL); -@@ -944,7 +964,7 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message, - use_tcp: - tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0); - result = get_dispatch(tcp, requestmgr, srcaddr, destaddr, -- &request->dispatch); -+ &connected, &request->dispatch); - if (result != ISC_R_SUCCESS) - goto cleanup; - -@@ -1000,14 +1020,14 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message, - goto unlink; - - request->destaddr = *destaddr; -- if (tcp) { -+ if (tcp && !connected) { - result = isc_socket_connect(socket, destaddr, task, - req_connected, request); - if (result != ISC_R_SUCCESS) - goto unlink; - request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP; - } else { -- result = req_send(request, task, destaddr); -+ result = req_send(request, task, connected ? NULL : destaddr); - if (result != ISC_R_SUCCESS) - goto unlink; - } -diff --git a/lib/dns/win32/libdns.def b/lib/dns/win32/libdns.def -index 5e20491..9aebe16 100644 ---- a/lib/dns/win32/libdns.def -+++ b/lib/dns/win32/libdns.def -@@ -176,9 +176,11 @@ dns_dispatch_attach - dns_dispatch_cancel - dns_dispatch_changeattributes - dns_dispatch_createtcp -+dns_dispatch_createtcp2 - dns_dispatch_detach - dns_dispatch_getlocaladdress - dns_dispatch_getsocket -+dns_dispatch_gettcp - dns_dispatch_getudp - dns_dispatch_getudp_dup - dns_dispatch_importrecv --- -2.20.1 - diff --git a/SOURCES/bind-9.11-rt37821.patch b/SOURCES/bind-9.11-rt37821.patch deleted file mode 100644 index 9ae27c1..0000000 --- a/SOURCES/bind-9.11-rt37821.patch +++ /dev/null @@ -1,1532 +0,0 @@ -From 4d55e959839e1bc8e43124648742056ac2c802e7 Mon Sep 17 00:00:00 2001 -From: Evan Hunt -Date: Tue, 20 Jan 2015 16:10:30 -0800 -Subject: [PATCH] add TCP pipelining support - -4040. [func] Added server-side support for pipelined TCP - queries. TCP connections are no longer closed after - the first query received from a client. (The new - "keep-response-order" option allows clients to be - specified for which the old behavior will still be - used.) [RT #37821] - -(cherry picked from commit 761d135ed686601f36fe3d0d4aaa6bf41287bb0f) - -Modified default value of keep-response-order ACL to any, for best backward -compatibility. Upstream default is none; ---- - bin/named/client.c | 123 ++++++- - bin/named/config.c | 3 +- - bin/named/include/named/client.h | 1 + - bin/named/include/named/server.h | 1 + - bin/named/named.conf.docbook | 1 + - bin/named/server.c | 8 + - bin/tests/named.conf | 3 +- - bin/tests/system/Makefile.in | 4 +- - .../checkconf/bad-keep-response-order.conf | 21 ++ - bin/tests/system/checkconf/bad-many.conf | 3 +- - bin/tests/system/checkconf/good.conf | 3 + - bin/tests/system/conf.sh.in | 2 +- - bin/tests/system/pipelined/Makefile.in | 51 +++ - bin/tests/system/pipelined/clean.sh | 19 + - bin/tests/system/pipelined/input | 8 + - bin/tests/system/pipelined/inputb | 8 + - bin/tests/system/pipelined/ns1/named.conf | 43 +++ - bin/tests/system/pipelined/ns1/root.db | 30 ++ - bin/tests/system/pipelined/ns2/examplea.db | 35 ++ - bin/tests/system/pipelined/ns2/named.conf | 49 +++ - bin/tests/system/pipelined/ns3/exampleb.db | 35 ++ - bin/tests/system/pipelined/ns3/named.args | 1 + - bin/tests/system/pipelined/ns3/named.conf | 49 +++ - bin/tests/system/pipelined/ns4/named.conf | 45 +++ - bin/tests/system/pipelined/pipequeries.c | 346 ++++++++++++++++++ - bin/tests/system/pipelined/ref | 8 + - bin/tests/system/pipelined/refb | 8 + - bin/tests/system/pipelined/setup.sh | 22 ++ - bin/tests/system/pipelined/tests.sh | 41 +++ - configure | 1 + - configure.in | 1 + - doc/arm/Bv9ARM-book.xml | 19 +- - doc/misc/options | 1 + - lib/bind9/check.c | 4 +- - lib/dns/dispatch.c | 22 +- - lib/isccfg/namedconf.c | 1 + - 36 files changed, 985 insertions(+), 35 deletions(-) - create mode 100644 bin/tests/system/checkconf/bad-keep-response-order.conf - create mode 100644 bin/tests/system/pipelined/Makefile.in - create mode 100644 bin/tests/system/pipelined/clean.sh - create mode 100644 bin/tests/system/pipelined/input - create mode 100644 bin/tests/system/pipelined/inputb - create mode 100644 bin/tests/system/pipelined/ns1/named.conf - create mode 100644 bin/tests/system/pipelined/ns1/root.db - create mode 100644 bin/tests/system/pipelined/ns2/examplea.db - create mode 100644 bin/tests/system/pipelined/ns2/named.conf - create mode 100644 bin/tests/system/pipelined/ns3/exampleb.db - create mode 100644 bin/tests/system/pipelined/ns3/named.args - create mode 100644 bin/tests/system/pipelined/ns3/named.conf - create mode 100644 bin/tests/system/pipelined/ns4/named.conf - create mode 100644 bin/tests/system/pipelined/pipequeries.c - create mode 100644 bin/tests/system/pipelined/ref - create mode 100644 bin/tests/system/pipelined/refb - create mode 100644 bin/tests/system/pipelined/setup.sh - create mode 100644 bin/tests/system/pipelined/tests.sh - -diff --git a/bin/named/client.c b/bin/named/client.c -index 9adf36b..f014b61 100644 ---- a/bin/named/client.c -+++ b/bin/named/client.c -@@ -233,6 +233,8 @@ static void client_request(isc_task_t *task, isc_event_t *event); - static void ns_client_dumpmessage(ns_client_t *client, const char *reason); - static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, - dns_dispatch_t *disp, isc_boolean_t tcp); -+static isc_result_t get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, -+ isc_socket_t *socket); - - void - ns_client_recursing(ns_client_t *client) { -@@ -367,9 +369,13 @@ exit_check(ns_client_t *client) { - INSIST(client->recursionquota == NULL); - - if (NS_CLIENTSTATE_READING == client->newstate) { -- client_read(client); -- client->newstate = NS_CLIENTSTATE_MAX; -- return (ISC_TRUE); /* We're done. */ -+ if (!client->pipelined) { -+ client_read(client); -+ client->newstate = NS_CLIENTSTATE_MAX; -+ return (ISC_TRUE); /* We're done. */ -+ } else if (client->mortal) { -+ client->newstate = NS_CLIENTSTATE_INACTIVE; -+ } - } - } - -@@ -406,6 +412,8 @@ exit_check(ns_client_t *client) { - client->timerset = ISC_FALSE; - } - -+ client->pipelined = ISC_FALSE; -+ - client->peeraddr_valid = ISC_FALSE; - - client->state = NS_CLIENTSTATE_READY; -@@ -605,7 +613,11 @@ client_start(isc_task_t *task, isc_event_t *event) { - return; - - if (TCP_CLIENT(client)) { -- client_accept(client); -+ if (client->pipelined) { -+ client_read(client); -+ } else { -+ client_accept(client); -+ } - } else { - client_udprecv(client); - } -@@ -1638,6 +1650,24 @@ client_request(isc_task_t *task, isc_event_t *event) { - goto cleanup; - } - -+ /* -+ * Pipeline TCP query processing. -+ */ -+ if (client->message->opcode != dns_opcode_query) -+ client->pipelined = ISC_FALSE; -+ if (TCP_CLIENT(client) && client->pipelined) { -+ result = isc_quota_reserve(&ns_g_server->tcpquota); -+ if (result == ISC_R_SUCCESS) -+ result = ns_client_replace(client); -+ if (result != ISC_R_SUCCESS) { -+ ns_client_log(client, NS_LOGCATEGORY_CLIENT, -+ NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, -+ "no more TCP clients(read): %s", -+ isc_result_totext(result)); -+ client->pipelined = ISC_FALSE; -+ } -+ } -+ - dns_opcodestats_increment(ns_g_server->opcodestats, - client->message->opcode); - switch (client->message->opcode) { -@@ -2138,6 +2168,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { - client->signer = NULL; - dns_name_init(&client->signername, NULL); - client->mortal = ISC_FALSE; -+ client->pipelined = ISC_FALSE; - client->tcpquota = NULL; - client->recursionquota = NULL; - client->interface = NULL; -@@ -2326,6 +2357,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { - * telnetting to port 53 (once per CPU) will - * deny service to legitimate TCP clients. - */ -+ client->pipelined = ISC_FALSE; - result = isc_quota_attach(&ns_g_server->tcpquota, - &client->tcpquota); - if (result == ISC_R_SUCCESS) -@@ -2333,8 +2365,12 @@ client_newconn(isc_task_t *task, isc_event_t *event) { - if (result != ISC_R_SUCCESS) { - ns_client_log(client, NS_LOGCATEGORY_CLIENT, - NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, -- "no more TCP clients: %s", -+ "no more TCP clients(accept): %s", - isc_result_totext(result)); -+ } else if (ns_g_server->keepresporder == NULL || -+ !allowed(&netaddr, NULL, NULL, 0, NULL, -+ ns_g_server->keepresporder)) { -+ client->pipelined = ISC_TRUE; - } - - client_read(client); -@@ -2432,14 +2468,21 @@ ns_client_shuttingdown(ns_client_t *client) { - isc_result_t - ns_client_replace(ns_client_t *client) { - isc_result_t result; -+ isc_boolean_t tcp; - - CTRACE("replace"); - - REQUIRE(client != NULL); - REQUIRE(client->manager != NULL); - -- result = get_client(client->manager, client->interface, -- client->dispatch, TCP_CLIENT(client)); -+ tcp = TCP_CLIENT(client); -+ if (tcp && client->pipelined) { -+ result = get_worker(client->manager, client->interface, -+ client->tcpsocket); -+ } else { -+ result = get_client(client->manager, client->interface, -+ client->dispatch, tcp); -+ } - if (result != ISC_R_SUCCESS) - return (result); - -@@ -2644,6 +2687,72 @@ get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, - return (ISC_R_SUCCESS); - } - -+static isc_result_t -+get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *socket) -+{ -+ isc_result_t result = ISC_R_SUCCESS; -+ isc_event_t *ev; -+ ns_client_t *client; -+ MTRACE("get worker"); -+ -+ REQUIRE(manager != NULL); -+ -+ if (manager->exiting) -+ return (ISC_R_SHUTTINGDOWN); -+ -+ /* -+ * Allocate a client. First try to get a recycled one; -+ * if that fails, make a new one. -+ */ -+ client = NULL; -+ if (!ns_g_clienttest) -+ ISC_QUEUE_POP(manager->inactive, ilink, client); -+ -+ if (client != NULL) -+ MTRACE("recycle"); -+ else { -+ MTRACE("create new"); -+ -+ LOCK(&manager->lock); -+ result = client_create(manager, &client); -+ UNLOCK(&manager->lock); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ -+ LOCK(&manager->listlock); -+ ISC_LIST_APPEND(manager->clients, client, link); -+ UNLOCK(&manager->listlock); -+ } -+ -+ client->manager = manager; -+ ns_interface_attach(ifp, &client->interface); -+ client->newstate = client->state = NS_CLIENTSTATE_WORKING; -+ INSIST(client->recursionquota == NULL); -+ client->tcpquota = &ns_g_server->tcpquota; -+ -+ client->dscp = ifp->dscp; -+ -+ client->attributes |= NS_CLIENTATTR_TCP; -+ client->pipelined = ISC_TRUE; -+ -+ isc_socket_attach(ifp->tcpsocket, &client->tcplistener); -+ isc_socket_attach(socket, &client->tcpsocket); -+ isc_socket_setname(client->tcpsocket, "worker-tcp", NULL); -+ (void)isc_socket_getpeername(client->tcpsocket, &client->peeraddr); -+ client->peeraddr_valid = ISC_TRUE; -+ -+ INSIST(client->tcpmsg_valid == ISC_FALSE); -+ dns_tcpmsg_init(client->mctx, client->tcpsocket, &client->tcpmsg); -+ client->tcpmsg_valid = ISC_TRUE; -+ -+ INSIST(client->nctls == 0); -+ client->nctls++; -+ ev = &client->ctlevent; -+ isc_task_send(client->task, &ev); -+ -+ return (ISC_R_SUCCESS); -+} -+ - isc_result_t - ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n, - ns_interface_t *ifp, isc_boolean_t tcp) -diff --git a/bin/named/config.c b/bin/named/config.c -index 22d8a85..f0db926 100644 ---- a/bin/named/config.c -+++ b/bin/named/config.c -@@ -72,6 +72,7 @@ options {\n\ - heartbeat-interval 60;\n\ - host-statistics no;\n\ - interface-interval 60;\n\ -+# keep-response-order {any;};\n\ - listen-on {any;};\n\ - listen-on-v6 {none;};\n\ - match-mapped-addresses no;\n\ -@@ -101,7 +102,7 @@ options {\n\ - server-id none;\n\ - statistics-file \"named.stats\";\n\ - statistics-interval 60;\n\ -- tcp-clients 100;\n\ -+ tcp-clients 150;\n\ - tcp-listen-queue 10;\n\ - # tkey-dhkey \n\ - # tkey-gssapi-credential \n\ -diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h -index 98e79df..bf4d201 100644 ---- a/bin/named/include/named/client.h -+++ b/bin/named/include/named/client.h -@@ -133,6 +133,7 @@ struct ns_client { - dns_name_t signername; /*%< [T]SIG key name */ - dns_name_t * signer; /*%< NULL if not valid sig */ - isc_boolean_t mortal; /*%< Die after handling request */ -+ isc_boolean_t pipelined; /*%< TCP queries not in sequence */ - isc_quota_t *tcpquota; - isc_quota_t *recursionquota; - ns_interface_t *interface; -diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h -index 0107b51..5f36177 100644 ---- a/bin/named/include/named/server.h -+++ b/bin/named/include/named/server.h -@@ -53,6 +53,7 @@ struct ns_server { - isc_quota_t tcpquota; - isc_quota_t recursionquota; - dns_acl_t *blackholeacl; -+ dns_acl_t *keepresporder; - char * statsfile; /*%< Statistics file name */ - char * dumpfile; /*%< Dump file name */ - char * secrootsfile; /*%< Secroots file name */ -diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook -index a8cd31e..4d502ac 100644 ---- a/bin/named/named.conf.docbook -+++ b/bin/named/named.conf.docbook -@@ -209,6 +209,7 @@ options { - host-statistics-max number; // not implemented - hostname ( quoted_string | none ); - interface-interval integer; -+ keep-response-order { address_match_element; ... }; - listen-on port integer { address_match_element; ... }; - listen-on-v6 port integer { address_match_element; ... }; - match-mapped-addresses boolean; -diff --git a/bin/named/server.c b/bin/named/server.c -index e8f19d3..e30bf16 100644 ---- a/bin/named/server.c -+++ b/bin/named/server.c -@@ -5207,6 +5207,10 @@ load_configuration(const char *filename, ns_server_t *server, - dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, - server->blackholeacl); - -+ CHECK(configure_view_acl(NULL, config, "keep-response-order", NULL, -+ ns_g_aclconfctx, ns_g_mctx, -+ &server->keepresporder)); -+ - obj = NULL; - result = ns_config_get(maps, "match-mapped-addresses", &obj); - INSIST(result == ISC_R_SUCCESS); -@@ -6208,6 +6212,9 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { - dns_name_free(&ns_g_sessionkeyname, server->mctx); - } - -+ if (server->keepresporder != NULL) -+ dns_acl_detach(&server->keepresporder); -+ - if (server->blackholeacl != NULL) - dns_acl_detach(&server->blackholeacl); - -@@ -6259,6 +6266,7 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { - ISC_LIST_INIT(server->viewlist); - server->in_roothints = NULL; - server->blackholeacl = NULL; -+ server->keepresporder = NULL; - - /* Must be first. */ - CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy, -diff --git a/bin/tests/named.conf b/bin/tests/named.conf -index 722d262..5b40045 100644 ---- a/bin/tests/named.conf -+++ b/bin/tests/named.conf -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2004, 2007, 2011 Internet Systems Consortium, Inc. ("ISC") -+ * Copyright (C) 2004, 2007, 2011, 2014 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any -@@ -116,6 +116,7 @@ options { - allow-transfer { any; }; - allow-recursion { !any; }; - blackhole { 45/24; }; -+ keep-response-order { 46/24; }; - - listen-on { - 10/24; -diff --git a/bin/tests/system/Makefile.in b/bin/tests/system/Makefile.in -index afee71b..e7eaef7 100644 ---- a/bin/tests/system/Makefile.in -+++ b/bin/tests/system/Makefile.in -@@ -21,8 +21,8 @@ top_srcdir = @top_srcdir@ - - @BIND9_MAKE_INCLUDES@ - --SUBDIRS = dlzexternal dyndb filter-aaaa geoip lwresd rpz rrl \ -- rsabigexponent tkey tsiggss -+SUBDIRS = dlzexternal dyndb filter-aaaa geoip lwresd pipelined \ -+ rpz rrl rsabigexponent tkey tsiggss - CINCLUDES = ${ISC_INCLUDES} ${DNS_INCLUDES} - - CDEFINES = @USE_GSSAPI@ -diff --git a/bin/tests/system/checkconf/bad-keep-response-order.conf b/bin/tests/system/checkconf/bad-keep-response-order.conf -new file mode 100644 -index 0000000..24c1f6c ---- /dev/null -+++ b/bin/tests/system/checkconf/bad-keep-response-order.conf -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+options { -+ keep-response-order { -+ does_not_exist; -+ }; -+}; -diff --git a/bin/tests/system/checkconf/bad-many.conf b/bin/tests/system/checkconf/bad-many.conf -index cfc4d02..09add87 100644 ---- a/bin/tests/system/checkconf/bad-many.conf -+++ b/bin/tests/system/checkconf/bad-many.conf -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2005, 2012 Internet Systems Consortium, Inc. ("ISC") -+ * Copyright (C) 2005, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above -@@ -33,6 +33,7 @@ options { - host-statistics-max 100; - hostname none; - interface-interval 30; -+ keep-response-order { 10.0.0.10/24; }; - listen-on port 90 { any; }; - listen-on port 100 { 127.0.0.1; }; - listen-on-v6 port 53 { none; }; -diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf -index cf7c745..43b0638 100644 ---- a/bin/tests/system/checkconf/good.conf -+++ b/bin/tests/system/checkconf/good.conf -@@ -44,6 +44,9 @@ options { - host-statistics-max 100; - hostname none; - interface-interval 30; -+ keep-response-order { -+ 10.0.0.10/24; -+ }; - listen-on port 90 { - "any"; - }; -diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in -index 420320c..0d966b3 100644 ---- a/bin/tests/system/conf.sh.in -+++ b/bin/tests/system/conf.sh.in -@@ -68,7 +68,7 @@ SUBDIRS="acl additional allow_query addzone autosign builtin - cacheclean checkconf @CHECKDS@ checknames checkzone @COVERAGE@ @KEYMGR@ - database digdelv dlv dlvauto dlz dlzexternal dname dns64 dnssec dyndb - ecdsa formerr forward glue gost ixfr inline limits logfileconfig -- lwresd masterfile masterformat metadata notify nsupdate pending -+ lwresd masterfile masterformat metadata notify nsupdate pending pipelined - @PKCS11_TEST@ redirect resolver rndc rpz rrl rrsetorder rsabigexponent - smartsign sortlist spf staticstub stub tkey tsig tsiggss unknown - upforwd verify views wildcard xfer xferquota zero zonechecks geoip filter-aaaa" -diff --git a/bin/tests/system/pipelined/Makefile.in b/bin/tests/system/pipelined/Makefile.in -new file mode 100644 -index 0000000..4d16d78 ---- /dev/null -+++ b/bin/tests/system/pipelined/Makefile.in -@@ -0,0 +1,51 @@ -+# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+srcdir = @srcdir@ -+VPATH = @srcdir@ -+top_srcdir = @top_srcdir@ -+ -+@BIND9_VERSION@ -+ -+@BIND9_MAKE_INCLUDES@ -+ -+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} -+ -+CDEFINES = -+CWARNINGS = -+ -+DNSLIBS = ../../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ -+ISCLIBS = ../../../../lib/isc/libisc.@A@ -+ -+DNSDEPLIBS = ../../../../lib/dns/libdns.@A@ -+ISCDEPLIBS = ../../../../lib/isc/libisc.@A@ -+ -+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} -+ -+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ -+ -+TARGETS = pipequeries@EXEEXT@ -+ -+SRCS = pipequeries.c -+ -+@BIND9_MAKE_RULES@ -+ -+all: pipequeries@EXEEXT@ -+ -+pipequeries@EXEEXT@: pipequeries.@O@ ${DEPLIBS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ pipequeries.@O@ ${LIBS} -+ -+clean distclean:: -+ rm -f ${TARGETS} -+ -diff --git a/bin/tests/system/pipelined/clean.sh b/bin/tests/system/pipelined/clean.sh -new file mode 100644 -index 0000000..1cca633 ---- /dev/null -+++ b/bin/tests/system/pipelined/clean.sh -@@ -0,0 +1,19 @@ -+#!/bin/sh -+# -+# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+rm -f */named.memstats -+rm -f */named.run -+rm -f raw* output* -diff --git a/bin/tests/system/pipelined/input b/bin/tests/system/pipelined/input -new file mode 100644 -index 0000000..485cf81 ---- /dev/null -+++ b/bin/tests/system/pipelined/input -@@ -0,0 +1,8 @@ -+a.examplea -+a.exampleb -+b.examplea -+b.exampleb -+c.examplea -+c.exampleb -+d.examplea -+d.exampleb -diff --git a/bin/tests/system/pipelined/inputb b/bin/tests/system/pipelined/inputb -new file mode 100644 -index 0000000..6ea367e ---- /dev/null -+++ b/bin/tests/system/pipelined/inputb -@@ -0,0 +1,8 @@ -+e.examplea -+e.exampleb -+f.examplea -+f.exampleb -+g.examplea -+g.exampleb -+h.examplea -+h.exampleb -diff --git a/bin/tests/system/pipelined/ns1/named.conf b/bin/tests/system/pipelined/ns1/named.conf -new file mode 100644 -index 0000000..1bbf401 ---- /dev/null -+++ b/bin/tests/system/pipelined/ns1/named.conf -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.1; -+ notify-source 10.53.0.1; -+ transfer-source 10.53.0.1; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.1; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ notify yes; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-sha256; -+}; -+ -+controls { -+ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+zone "." { -+ type master; -+ file "root.db"; -+}; -diff --git a/bin/tests/system/pipelined/ns1/root.db b/bin/tests/system/pipelined/ns1/root.db -new file mode 100644 -index 0000000..b5186e5 ---- /dev/null -+++ b/bin/tests/system/pipelined/ns1/root.db -@@ -0,0 +1,30 @@ -+; Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+; -+; Permission to use, copy, modify, and/or distribute this software for any -+; purpose with or without fee is hereby granted, provided that the above -+; copyright notice and this permission notice appear in all copies. -+; -+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+; PERFORMANCE OF THIS SOFTWARE. -+ -+$TTL 300 -+. IN SOA gson.nominum.com. a.root.servers.nil. ( -+ 2000042100 ; serial -+ 600 ; refresh -+ 600 ; retry -+ 1200 ; expire -+ 600 ; minimum -+ ) -+. NS a.root-servers.nil. -+a.root-servers.nil. A 10.53.0.1 -+ -+examplea. NS ns2.examplea. -+ns2.examplea. A 10.53.0.2 -+ -+exampleb. NS ns3.exampleb. -+ns3.exampleb. A 10.53.0.3 -diff --git a/bin/tests/system/pipelined/ns2/examplea.db b/bin/tests/system/pipelined/ns2/examplea.db -new file mode 100644 -index 0000000..678034a ---- /dev/null -+++ b/bin/tests/system/pipelined/ns2/examplea.db -@@ -0,0 +1,35 @@ -+; Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+; -+; Permission to use, copy, modify, and/or distribute this software for any -+; purpose with or without fee is hereby granted, provided that the above -+; copyright notice and this permission notice appear in all copies. -+; -+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+; PERFORMANCE OF THIS SOFTWARE. -+ -+$ORIGIN . -+$TTL 300 ; 5 minutes -+examplea IN SOA mname1. . ( -+ 1 ; serial -+ 20 ; refresh (20 seconds) -+ 20 ; retry (20 seconds) -+ 1814400 ; expire (3 weeks) -+ 3600 ; minimum (1 hour) -+ ) -+examplea. NS ns2.examplea. -+ns2.examplea. A 10.53.0.2 -+ -+$ORIGIN examplea. -+a A 10.0.1.1 -+b A 10.0.1.2 -+c A 10.0.1.3 -+d A 10.0.1.4 -+e A 10.0.1.5 -+f A 10.0.1.6 -+g A 10.0.1.7 -+h A 10.0.1.8 -diff --git a/bin/tests/system/pipelined/ns2/named.conf b/bin/tests/system/pipelined/ns2/named.conf -new file mode 100644 -index 0000000..83a9ec7 ---- /dev/null -+++ b/bin/tests/system/pipelined/ns2/named.conf -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion yes; -+ notify yes; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-sha256; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+zone "." { -+ type hint; -+ file "../../common/root.hint"; -+}; -+ -+zone "examplea" { -+ type master; -+ file "examplea.db"; -+ allow-update { any; }; -+}; -diff --git a/bin/tests/system/pipelined/ns3/exampleb.db b/bin/tests/system/pipelined/ns3/exampleb.db -new file mode 100644 -index 0000000..7d10493 ---- /dev/null -+++ b/bin/tests/system/pipelined/ns3/exampleb.db -@@ -0,0 +1,35 @@ -+; Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+; -+; Permission to use, copy, modify, and/or distribute this software for any -+; purpose with or without fee is hereby granted, provided that the above -+; copyright notice and this permission notice appear in all copies. -+; -+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+; PERFORMANCE OF THIS SOFTWARE. -+ -+$ORIGIN . -+$TTL 300 ; 5 minutes -+exampleb IN SOA mname1. . ( -+ 1 ; serial -+ 20 ; refresh (20 seconds) -+ 20 ; retry (20 seconds) -+ 1814400 ; expire (3 weeks) -+ 3600 ; minimum (1 hour) -+ ) -+exampleb. NS ns3.exampleb. -+ns3.exampleb. A 10.53.0.3 -+ -+$ORIGIN exampleb. -+a A 10.0.2.1 -+b A 10.0.2.2 -+c A 10.0.2.3 -+d A 10.0.2.4 -+e A 10.0.2.5 -+f A 10.0.2.6 -+g A 10.0.2.7 -+h A 10.0.2.8 -diff --git a/bin/tests/system/pipelined/ns3/named.args b/bin/tests/system/pipelined/ns3/named.args -new file mode 100644 -index 0000000..a6b0f54 ---- /dev/null -+++ b/bin/tests/system/pipelined/ns3/named.args -@@ -0,0 +1 @@ -+-m record,size,mctx -c named.conf -d 99 -g -T delay=200 -diff --git a/bin/tests/system/pipelined/ns3/named.conf b/bin/tests/system/pipelined/ns3/named.conf -new file mode 100644 -index 0000000..8b15622 ---- /dev/null -+++ b/bin/tests/system/pipelined/ns3/named.conf -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.3; -+ notify-source 10.53.0.3; -+ transfer-source 10.53.0.3; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.3; }; -+ listen-on-v6 { none; }; -+ recursion yes; -+ notify yes; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-sha256; -+}; -+ -+controls { -+ inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+zone "." { -+ type hint; -+ file "../../common/root.hint"; -+}; -+ -+zone "exampleb" { -+ type master; -+ file "exampleb.db"; -+ allow-update { any; }; -+}; -diff --git a/bin/tests/system/pipelined/ns4/named.conf b/bin/tests/system/pipelined/ns4/named.conf -new file mode 100644 -index 0000000..7e7923a ---- /dev/null -+++ b/bin/tests/system/pipelined/ns4/named.conf -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.4; -+ notify-source 10.53.0.4; -+ transfer-source 10.53.0.4; -+ port 5300; -+ directory "."; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.4; }; -+ listen-on-v6 { none; }; -+ keep-response-order { 10.53.0.7/32; }; -+ recursion yes; -+ notify yes; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-sha256; -+}; -+ -+controls { -+ inet 10.53.0.4 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+zone "." { -+ type hint; -+ file "../../common/root.hint"; -+}; -diff --git a/bin/tests/system/pipelined/pipequeries.c b/bin/tests/system/pipelined/pipequeries.c -new file mode 100644 -index 0000000..d34dedd ---- /dev/null -+++ b/bin/tests/system/pipelined/pipequeries.c -@@ -0,0 +1,346 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define CHECK(str, x) { \ -+ if ((x) != ISC_R_SUCCESS) { \ -+ fprintf(stderr, "I:%s: %s\n", (str), isc_result_totext(x)); \ -+ exit(-1); \ -+ } \ -+} -+ -+#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS) -+ -+#define PORT 5300 -+#define TIMEOUT 30 -+ -+static isc_mem_t *mctx; -+static dns_requestmgr_t *requestmgr; -+isc_sockaddr_t address; -+static int onfly; -+ -+static void -+recvresponse(isc_task_t *task, isc_event_t *event) { -+ dns_requestevent_t *reqev = (dns_requestevent_t *)event; -+ isc_result_t result; -+ dns_message_t *query, *response; -+ isc_buffer_t outbuf; -+ char output[1024]; -+ -+ UNUSED(task); -+ -+ REQUIRE(reqev != NULL); -+ -+ if (reqev->result != ISC_R_SUCCESS) { -+ fprintf(stderr, "I:request event result: %s\n", -+ isc_result_totext(reqev->result)); -+ exit(-1); -+ } -+ -+ query = reqev->ev_arg; -+ -+ response = NULL; -+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); -+ CHECK("dns_message_create", result); -+ -+ result = dns_request_getresponse(reqev->request, response, -+ DNS_MESSAGEPARSE_PRESERVEORDER); -+ CHECK("dns_request_getresponse", result); -+ -+ if (response->rcode != dns_rcode_noerror) { -+ result = ISC_RESULTCLASS_DNSRCODE + response->rcode; -+ fprintf(stderr, "I:response rcode: %s\n", -+ isc_result_totext(result)); -+ exit(-1); -+ } -+ if (response->counts[DNS_SECTION_ANSWER] != 1U) { -+ fprintf(stderr, "I:response answer count (%u!=1)\n", -+ response->counts[DNS_SECTION_ANSWER]); -+ } -+ -+ isc_buffer_init(&outbuf, output, sizeof(output)); -+ result = dns_message_sectiontotext(response, DNS_SECTION_ANSWER, -+ &dns_master_style_simple, -+ DNS_MESSAGETEXTFLAG_NOCOMMENTS, -+ &outbuf); -+ CHECK("dns_message_sectiontotext", result); -+ printf("%.*s", (int)isc_buffer_usedlength(&outbuf), -+ (char *)isc_buffer_base(&outbuf)); -+ fflush(stdout); -+ -+ dns_message_destroy(&query); -+ dns_message_destroy(&response); -+ dns_request_destroy(&reqev->request); -+ isc_event_free(&event); -+ -+ if (--onfly == 0) -+ isc_app_shutdown(); -+ return; -+} -+ -+static isc_result_t -+sendquery(isc_task_t *task) -+{ -+ dns_request_t *request; -+ dns_message_t *message; -+ dns_name_t *qname; -+ dns_rdataset_t *qrdataset; -+ isc_result_t result; -+ dns_fixedname_t queryname; -+ isc_buffer_t buf; -+ static char host[256]; -+ int c; -+ -+ c = scanf("%255s", host); -+ if (c == EOF) -+ return ISC_R_NOMORE; -+ -+ onfly++; -+ -+ dns_fixedname_init(&queryname); -+ isc_buffer_init(&buf, host, strlen(host)); -+ isc_buffer_add(&buf, strlen(host)); -+ result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf, -+ dns_rootname, 0, NULL); -+ CHECK("dns_name_fromtext", result); -+ -+ message = NULL; -+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message); -+ CHECK("dns_message_create", result); -+ -+ message->opcode = dns_opcode_query; -+ message->flags |= DNS_MESSAGEFLAG_RD; -+ message->rdclass = dns_rdataclass_in; -+ message->id = (unsigned short)(random() & 0xFFFF); -+ -+ qname = NULL; -+ result = dns_message_gettempname(message, &qname); -+ CHECK("dns_message_gettempname", result); -+ -+ qrdataset = NULL; -+ result = dns_message_gettemprdataset(message, &qrdataset); -+ CHECK("dns_message_gettemprdataset", result); -+ -+ dns_name_init(qname, NULL); -+ dns_name_clone(dns_fixedname_name(&queryname), qname); -+ dns_rdataset_init(qrdataset); -+ dns_rdataset_makequestion(qrdataset, dns_rdataclass_in, -+ dns_rdatatype_a); -+ ISC_LIST_APPEND(qname->list, qrdataset, link); -+ dns_message_addname(message, qname, DNS_SECTION_QUESTION); -+ -+ request = NULL; -+ result = dns_request_create(requestmgr, message, &address, -+ DNS_REQUESTOPT_TCP, NULL, -+ TIMEOUT, task, recvresponse, -+ message, &request); -+ CHECK("dns_request_create", result); -+ -+ return ISC_R_SUCCESS; -+} -+ -+static void -+sendqueries(isc_task_t *task, isc_event_t *event) -+{ -+ isc_result_t result; -+ -+ isc_event_free(&event); -+ -+ do { -+ result = sendquery(task); -+ } while (result == ISC_R_SUCCESS); -+ -+ if (onfly == 0) -+ isc_app_shutdown(); -+ return; -+} -+ -+static void -+connecting(isc_task_t *task, isc_event_t *event) -+{ -+ isc_socket_t *sock = (isc_socket_t *)(event->ev_arg); -+ -+ RUNCHECK(isc_socket_connect(sock, &address, task, sendqueries, NULL)); -+ -+ isc_event_free(&event); -+} -+ -+int -+main(int argc, char *argv[]) -+{ -+ isc_taskmgr_t *taskmgr; -+ isc_timermgr_t *timermgr; -+ isc_socketmgr_t *socketmgr; -+ isc_socket_t *sock; -+ unsigned int attrs, attrmask; -+ isc_sockaddr_t bind_addr; -+ dns_dispatchmgr_t *dispatchmgr; -+ dns_dispatch_t *dispatchv4; -+ dns_dispatch_t *tcpdispatch; -+ dns_view_t *view; -+ isc_entropy_t *ectx; -+ isc_task_t *task; -+ isc_log_t *lctx; -+ isc_logconfig_t *lcfg; -+ struct in_addr inaddr; -+ isc_result_t result; -+ -+ UNUSED(argv); -+ -+ RUNCHECK(isc_app_start()); -+ -+ dns_result_register(); -+ -+ mctx = NULL; -+ RUNCHECK(isc_mem_create(0, 0, &mctx)); -+ -+ lctx = NULL; -+ lcfg = NULL; -+ RUNCHECK(isc_log_create(mctx, &lctx, &lcfg)); -+ -+ ectx = NULL; -+ RUNCHECK(isc_entropy_create(mctx, &ectx)); -+ RUNCHECK(isc_entropy_createfilesource(ectx, "../random.data")); -+ RUNCHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)); -+ -+ RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY)); -+ -+ taskmgr = NULL; -+ RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr)); -+ task = NULL; -+ RUNCHECK(isc_task_create(taskmgr, 0, &task)); -+ timermgr = NULL; -+ -+ RUNCHECK(isc_timermgr_create(mctx, &timermgr)); -+ socketmgr = NULL; -+ RUNCHECK(isc_socketmgr_create(mctx, &socketmgr)); -+ dispatchmgr = NULL; -+ RUNCHECK(dns_dispatchmgr_create(mctx, ectx, &dispatchmgr)); -+ if (argc == 1) { -+ isc_sockaddr_any(&bind_addr); -+ } else { -+ result = ISC_R_FAILURE; -+ if (inet_pton(AF_INET, "10.53.0.7", &inaddr) != 1) -+ CHECK("inet_pton", result); -+ isc_sockaddr_fromin(&bind_addr, &inaddr, 0); -+ } -+ attrs = DNS_DISPATCHATTR_UDP | -+ DNS_DISPATCHATTR_MAKEQUERY | -+ DNS_DISPATCHATTR_IPV4; -+ attrmask = DNS_DISPATCHATTR_UDP | -+ DNS_DISPATCHATTR_TCP | -+ DNS_DISPATCHATTR_IPV4 | -+ DNS_DISPATCHATTR_IPV6; -+ dispatchv4 = NULL; -+ RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, -+ &bind_addr, 4096, 4, 2, 3, 5, -+ attrs, attrmask, &dispatchv4)); -+ requestmgr = NULL; -+ RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, -+ dispatchmgr, dispatchv4, NULL, -+ &requestmgr)); -+ -+ view = NULL; -+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); -+ -+ sock = NULL; -+ RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_tcp, -+ &sock)); -+ RUNCHECK(isc_socket_bind(sock, &bind_addr, 0)); -+ -+ result = ISC_R_FAILURE; -+ if (inet_pton(AF_INET, "10.53.0.4", &inaddr) != 1) -+ CHECK("inet_pton", result); -+ isc_sockaddr_fromin(&address, &inaddr, PORT); -+ -+ attrs = 0; -+ attrs |= DNS_DISPATCHATTR_TCP; -+ attrs |= DNS_DISPATCHATTR_IPV4; -+ attrs |= DNS_DISPATCHATTR_MAKEQUERY; -+ attrs |= DNS_DISPATCHATTR_CONNECTED; -+ tcpdispatch = NULL; -+ RUNCHECK(dns_dispatch_createtcp2(dispatchmgr, sock, taskmgr, -+ &bind_addr, &address, -+ 4096, 20, 10, 3, 5, -+ attrs, &tcpdispatch)); -+ -+ RUNCHECK(isc_app_onrun(mctx, task, connecting, sock)); -+ -+ isc_socket_detach(&sock); -+ -+ (void)isc_app_run(); -+ -+ dns_view_detach(&view); -+ -+ dns_requestmgr_shutdown(requestmgr); -+ dns_requestmgr_detach(&requestmgr); -+ -+ dns_dispatch_detach(&dispatchv4); -+ dns_dispatch_detach(&tcpdispatch); -+ dns_dispatchmgr_destroy(&dispatchmgr); -+ -+ isc_socketmgr_destroy(&socketmgr); -+ isc_timermgr_destroy(&timermgr); -+ -+ isc_task_shutdown(task); -+ isc_task_detach(&task); -+ isc_taskmgr_destroy(&taskmgr); -+ -+ dst_lib_destroy(); -+ isc_hash_destroy(); -+ isc_entropy_detach(&ectx); -+ -+ isc_log_destroy(&lctx); -+ -+ isc_mem_destroy(&mctx); -+ -+ isc_app_finish(); -+ -+ return (0); -+} -+ -diff --git a/bin/tests/system/pipelined/ref b/bin/tests/system/pipelined/ref -new file mode 100644 -index 0000000..fe123f6 ---- /dev/null -+++ b/bin/tests/system/pipelined/ref -@@ -0,0 +1,8 @@ -+a.examplea. 10.0.1.1 -+a.exampleb. 10.0.2.1 -+b.examplea. 10.0.1.2 -+b.exampleb. 10.0.2.2 -+c.examplea. 10.0.1.3 -+c.exampleb. 10.0.2.3 -+d.examplea. 10.0.1.4 -+d.exampleb. 10.0.2.4 -diff --git a/bin/tests/system/pipelined/refb b/bin/tests/system/pipelined/refb -new file mode 100644 -index 0000000..a24c6bc ---- /dev/null -+++ b/bin/tests/system/pipelined/refb -@@ -0,0 +1,8 @@ -+e.examplea. 10.0.1.5 -+e.exampleb. 10.0.2.5 -+f.examplea. 10.0.1.6 -+f.exampleb. 10.0.2.6 -+g.examplea. 10.0.1.7 -+g.exampleb. 10.0.2.7 -+h.examplea. 10.0.1.8 -+h.exampleb. 10.0.2.8 -diff --git a/bin/tests/system/pipelined/setup.sh b/bin/tests/system/pipelined/setup.sh -new file mode 100644 -index 0000000..6fc981d ---- /dev/null -+++ b/bin/tests/system/pipelined/setup.sh -@@ -0,0 +1,22 @@ -+#!/bin/sh -+# -+# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+SYSTEMTESTTOP=.. -+. $SYSTEMTESTTOP/conf.sh -+ -+$SHELL clean.sh -+ -+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE -diff --git a/bin/tests/system/pipelined/tests.sh b/bin/tests/system/pipelined/tests.sh -new file mode 100644 -index 0000000..a34e573 ---- /dev/null -+++ b/bin/tests/system/pipelined/tests.sh -@@ -0,0 +1,41 @@ -+#!/bin/sh -+# -+# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+SYSTEMTESTTOP=.. -+. $SYSTEMTESTTOP/conf.sh -+ -+status=0 -+ -+echo "I:check pipelined TCP queries" -+ret=0 -+./pipequeries < input > raw || ret=1 -+awk '{ print $1 " " $5 }' < raw > output -+sort < output > output-sorted -+diff ref output-sorted || { ret=1 ; echo "I: diff sorted failed"; } -+diff ref output > /dev/null && { ret=1 ; echo "I: diff out of order failed"; } -+if [ $ret != 0 ]; then echo "I:failed"; fi -+status=`expr $status + $ret` -+ -+echo "I:check keep response order" -+ret=0 -+./pipequeries ++ < inputb > rawb || ret=1 -+awk '{ print $1 " " $5 }' < rawb > outputb -+diff refb outputb || ret=1 -+if [ $ret != 0 ]; then echo "I:failed"; fi -+status=`expr $status + $ret` -+ -+echo "I:exit status: $status" -+exit $status -diff --git a/configure b/configure -index a299aac..7f5c7da 100755 ---- a/configure -+++ b/configure -@@ -22330,6 +22330,7 @@ do - "bin/tests/system/geoip/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/geoip/Makefile" ;; - "bin/tests/system/gost/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/gost/prereq.sh" ;; - "bin/tests/system/lwresd/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/lwresd/Makefile" ;; -+ "bin/tests/system/pipelined/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/pipelined/Makefile" ;; - "bin/tests/system/rpz/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/rpz/Makefile" ;; - "bin/tests/system/rrl/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/rrl/Makefile" ;; - "bin/tests/system/rsabigexponent/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/rsabigexponent/Makefile" ;; -diff --git a/configure.in b/configure.in -index ee38901..9c5a9db 100644 ---- a/configure.in -+++ b/configure.in -@@ -4099,6 +4099,7 @@ AC_CONFIG_FILES([ - bin/tests/system/geoip/Makefile - bin/tests/system/gost/prereq.sh - bin/tests/system/lwresd/Makefile -+ bin/tests/system/pipelined/Makefile - bin/tests/system/rpz/Makefile - bin/tests/system/rrl/Makefile - bin/tests/system/rsabigexponent/Makefile -diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml -index af194d9..74394a0 100644 ---- a/doc/arm/Bv9ARM-book.xml -+++ b/doc/arm/Bv9ARM-book.xml -@@ -3025,8 +3025,9 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. - allow-query-cache-on, - allow-transfer, - allow-update, -- allow-update-forwarding, and -- blackhole all use address match -+ allow-update-forwarding, -+ blackhole, and -+ keep-response-order all use address match - lists. Similarly, the listen-on option will cause the - server to refuse queries on any of the machine's - addresses which do not match the list. -@@ -4829,6 +4830,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] - try-tcp-refresh yes_or_no; - allow-v6-synthesis { address_match_list }; - blackhole { address_match_list }; -+ keep-response-order { address_match_list }; - use-v4-udp-ports { port_list }; - avoid-v4-udp-ports { port_list }; - use-v6-udp-ports { port_list }; -@@ -7248,6 +7250,19 @@ options { - Specifies a list of addresses to which - filter-aaaa-on-v4 - is applies. The default is any. -+ -+ -+ -+ -+ -+ keep-response-order -+ -+ -+ Specifies a list of addresses to which the server -+ will send responses to TCP queries in the same order -+ in which they were received. This disables the -+ processing of TCP queries in parallel. The default -+ is any. - - - -diff --git a/doc/misc/options b/doc/misc/options -index 1827bd7..3c0f01f 100644 ---- a/doc/misc/options -+++ b/doc/misc/options -@@ -147,6 +147,7 @@ options { - inline-signing ; - interface-interval ; - ixfr-from-differences ; -+ keep-response-order { ; ... }; - key-directory ; - lame-ttl ; - listen-on [ port ] { ; ... }; -diff --git a/lib/bind9/check.c b/lib/bind9/check.c -index 00c4b3e..d4803e2 100644 ---- a/lib/bind9/check.c -+++ b/lib/bind9/check.c -@@ -403,8 +403,8 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, - - static const char *acls[] = { "allow-query", "allow-query-on", - "allow-query-cache", "allow-query-cache-on", -- "blackhole", "match-clients", "match-destinations", -- "sortlist", "filter-aaaa", NULL }; -+ "blackhole", "keep-response-order", "match-clients", -+ "match-destinations", "sortlist", "filter-aaaa", NULL }; - - while (acls[i] != NULL) { - tresult = checkacl(acls[i++], actx, NULL, voptions, config, -diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c -index b9f34eb..088c500 100644 ---- a/lib/dns/dispatch.c -+++ b/lib/dns/dispatch.c -@@ -2831,7 +2831,6 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr, - isc_result_t result; - isc_sockaddr_t peeraddr; - isc_sockaddr_t sockname; -- isc_sockaddr_t any; - unsigned int attributes, mask; - isc_boolean_t match = ISC_FALSE; - -@@ -2839,23 +2838,9 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr, - REQUIRE(destaddr != NULL); - REQUIRE(dispp != NULL && *dispp == NULL); - -- attributes = DNS_DISPATCHATTR_TCP; -+ attributes = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_CONNECTED; - mask = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_PRIVATE | -- DNS_DISPATCHATTR_EXCLUSIVE; -- -- if (localaddr == NULL) { -- switch (isc_sockaddr_pf(destaddr)) { -- case AF_INET: -- isc_sockaddr_any(&any); -- break; -- case AF_INET6: -- isc_sockaddr_any6(&any); -- break; -- default: -- return (ISC_R_NOTFOUND); -- } -- localaddr = &any; -- } -+ DNS_DISPATCHATTR_EXCLUSIVE | DNS_DISPATCHATTR_CONNECTED; - - LOCK(&mgr->lock); - disp = ISC_LIST_HEAD(mgr->list); -@@ -2872,7 +2857,8 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr, - &peeraddr); - if (result == ISC_R_SUCCESS && - isc_sockaddr_equal(destaddr, &peeraddr) && -- isc_sockaddr_eqaddr(localaddr, &sockname)) { -+ (localaddr == NULL || -+ isc_sockaddr_eqaddr(localaddr, &sockname))) { - /* attach */ - disp->refcount++; - *dispp = disp; -diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c -index d9b1df1..f357c63 100644 ---- a/lib/isccfg/namedconf.c -+++ b/lib/isccfg/namedconf.c -@@ -959,6 +959,7 @@ options_clauses[] = { - { "host-statistics-max", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP }, - { "hostname", &cfg_type_qstringornone, 0 }, - { "interface-interval", &cfg_type_uint32, 0 }, -+ { "keep-response-order", &cfg_type_bracketed_aml, 0 }, - { "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI }, - { "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI }, - { "managed-keys-directory", &cfg_type_qstring, 0 }, --- -2.20.1 - diff --git a/SOURCES/bind99-CVE-2018-5743-option.patch b/SOURCES/bind99-CVE-2018-5743-option.patch new file mode 100644 index 0000000..264b157 --- /dev/null +++ b/SOURCES/bind99-CVE-2018-5743-option.patch @@ -0,0 +1,170 @@ +From 7e7fc71357309c1646eee51d82ab515472c62346 Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Tue, 20 Jan 2015 16:10:30 -0800 +Subject: [PATCH] add keep-response-order option warning + +Support keep-response-order ACL on input, but do not take any action +setting it. Used as backward compatibility after support for pipelining +and TCP connection reusage were again removed. +--- + bin/named/config.c | 1 + + bin/named/server.c | 11 ++++++++++ + bin/tests/named.conf | 3 ++- + .../checkconf/bad-keep-response-order.conf | 21 +++++++++++++++++++ + bin/tests/system/checkconf/bad-many.conf | 3 ++- + bin/tests/system/checkconf/good.conf | 3 +++ + lib/bind9/check.c | 4 ++-- + lib/isccfg/namedconf.c | 1 + + 8 files changed, 43 insertions(+), 4 deletions(-) + create mode 100644 bin/tests/system/checkconf/bad-keep-response-order.conf + +diff --git a/bin/named/config.c b/bin/named/config.c +index 22d8a85..515cc4f 100644 +--- a/bin/named/config.c ++++ b/bin/named/config.c +@@ -72,6 +72,7 @@ options {\n\ + heartbeat-interval 60;\n\ + host-statistics no;\n\ + interface-interval 60;\n\ ++# keep-response-order {any;};\n\ + listen-on {any;};\n\ + listen-on-v6 {none;};\n\ + match-mapped-addresses no;\n\ +diff --git a/bin/named/server.c b/bin/named/server.c +index e8f19d3..0ee47af 100644 +--- a/bin/named/server.c ++++ b/bin/named/server.c +@@ -4987,6 +4987,7 @@ load_configuration(const char *filename, ns_server_t *server, + const cfg_obj_t *options; + const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports; + const cfg_obj_t *views; ++ dns_acl_t *keepresporder=NULL; + dns_view_t *view = NULL; + dns_view_t *view_next; + dns_viewlist_t tmpviewlist; +@@ -5207,6 +5208,16 @@ load_configuration(const char *filename, ns_server_t *server, + dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, + server->blackholeacl); + ++ CHECK(configure_view_acl(NULL, config, "keep-response-order", NULL, ++ ns_g_aclconfctx, ns_g_mctx, ++ &keepresporder)); ++ if (keepresporder != NULL) { ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, ++ NS_LOGMODULE_SERVER, ISC_LOG_WARNING, ++ "keep-response-order option is ignored and can be safely removed"); ++ dns_acl_detach(&keepresporder); ++ } ++ + obj = NULL; + result = ns_config_get(maps, "match-mapped-addresses", &obj); + INSIST(result == ISC_R_SUCCESS); +diff --git a/bin/tests/named.conf b/bin/tests/named.conf +index 722d262..5b40045 100644 +--- a/bin/tests/named.conf ++++ b/bin/tests/named.conf +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2004, 2007, 2011 Internet Systems Consortium, Inc. ("ISC") ++ * Copyright (C) 2004, 2007, 2011, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or distribute this software for any +@@ -116,6 +116,7 @@ options { + allow-transfer { any; }; + allow-recursion { !any; }; + blackhole { 45/24; }; ++ keep-response-order { 46/24; }; + + listen-on { + 10/24; +diff --git a/bin/tests/system/checkconf/bad-keep-response-order.conf b/bin/tests/system/checkconf/bad-keep-response-order.conf +new file mode 100644 +index 0000000..24c1f6c +--- /dev/null ++++ b/bin/tests/system/checkconf/bad-keep-response-order.conf +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH ++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, ++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE ++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ++ * PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++options { ++ keep-response-order { ++ does_not_exist; ++ }; ++}; +diff --git a/bin/tests/system/checkconf/bad-many.conf b/bin/tests/system/checkconf/bad-many.conf +index cfc4d02..09add87 100644 +--- a/bin/tests/system/checkconf/bad-many.conf ++++ b/bin/tests/system/checkconf/bad-many.conf +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2005, 2012 Internet Systems Consortium, Inc. ("ISC") ++ * Copyright (C) 2005, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -33,6 +33,7 @@ options { + host-statistics-max 100; + hostname none; + interface-interval 30; ++ keep-response-order { 10.0.0.10/24; }; + listen-on port 90 { any; }; + listen-on port 100 { 127.0.0.1; }; + listen-on-v6 port 53 { none; }; +diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf +index cf7c745..43b0638 100644 +--- a/bin/tests/system/checkconf/good.conf ++++ b/bin/tests/system/checkconf/good.conf +@@ -44,6 +44,9 @@ options { + host-statistics-max 100; + hostname none; + interface-interval 30; ++ keep-response-order { ++ 10.0.0.10/24; ++ }; + listen-on port 90 { + "any"; + }; +diff --git a/lib/bind9/check.c b/lib/bind9/check.c +index 00c4b3e..d4803e2 100644 +--- a/lib/bind9/check.c ++++ b/lib/bind9/check.c +@@ -403,8 +403,8 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, + + static const char *acls[] = { "allow-query", "allow-query-on", + "allow-query-cache", "allow-query-cache-on", +- "blackhole", "match-clients", "match-destinations", +- "sortlist", "filter-aaaa", NULL }; ++ "blackhole", "keep-response-order", "match-clients", ++ "match-destinations", "sortlist", "filter-aaaa", NULL }; + + while (acls[i] != NULL) { + tresult = checkacl(acls[i++], actx, NULL, voptions, config, +diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c +index d9b1df1..f357c63 100644 +--- a/lib/isccfg/namedconf.c ++++ b/lib/isccfg/namedconf.c +@@ -959,6 +959,7 @@ options_clauses[] = { + { "host-statistics-max", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP }, + { "hostname", &cfg_type_qstringornone, 0 }, + { "interface-interval", &cfg_type_uint32, 0 }, ++ { "keep-response-order", &cfg_type_bracketed_aml, 0 }, + { "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI }, + { "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI }, + { "managed-keys-directory", &cfg_type_qstring, 0 }, +-- +2.20.1 + diff --git a/SOURCES/bind99-CVE-2018-5743.patch b/SOURCES/bind99-CVE-2018-5743.patch new file mode 100644 index 0000000..c1fa5f0 --- /dev/null +++ b/SOURCES/bind99-CVE-2018-5743.patch @@ -0,0 +1,717 @@ +From c8292710c84e40eeaea6a51df2842fc5f34458d5 Mon Sep 17 00:00:00 2001 +From: Petr Mensik +Date: Wed, 5 Jun 2019 15:57:14 +0200 +Subject: [PATCH] Fix CVE-2018-5743 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Squashed commit of the following: + +commit f8e5335ea483c72341093f02d964b1ea9290077d +Author: Petr Mensik +Date: Tue Jun 4 17:19:20 2019 +0200 + + Remove pipelined parameter and tcpconn structure with reference counter + + It is not ever used in this version. Is not required to work. + + TCP connection is never shared in this version. Do not use reference + counter, just attach and detach tcpquota to given client. + +commit e3521d5531054b51e897e5458b09392cc752797d +Author: Evan Hunt +Date: Fri Apr 5 16:26:19 2019 -0700 + + restore allowance for tcp-clients < interfaces + + in the "refactor tcpquota and pipeline refs" commit, the counting + of active interfaces was tightened in such a way that named could + fail to listen on an interface if there were more interfaces than + tcp-clients. when checking the quota to start accepting on an + interface, if the number of active clients was above zero, then + it was presumed that some other client was able to handle accepting + new connections. this, however, ignored the fact that the current client + could be included in that count, so if the quota was already exceeded + before all the interfaces were listening, some interfaces would never + listen. + + we now check whether the current client has been marked active; if so, + then the number of active clients on the interface must be greater + than 1, not 0. + + (cherry picked from commit 0b4e2cd4c3192ba88569dd344f542a8cc43742b5) + (cherry picked from commit d01023aaac35543daffbdf48464e320150235d41) + (cherry picked from commit 59434b987e8eb436b08c24e559ee094c4e939daa) + +commit 934effeb8a76f735ca1b07fbd00bc5c8e8d285a3 +Author: Evan Hunt +Date: Fri Apr 5 16:26:05 2019 -0700 + + refactor tcpquota and pipeline refs; allow special-case overrun in isc_quota + + - if the TCP quota has been exceeded but there are no clients listening + for new connections on the interface, we can now force attachment to the + quota using isc_quota_force(), instead of carrying on with the quota not + attached. + - the TCP client quota is now referenced via a reference-counted + 'ns_tcpconn' object, one of which is created whenever a client begins + listening for new connections, and attached to by members of that + client's pipeline group. when the last reference to the tcpconn + object is detached, it is freed and the TCP quota slot is released. + - reduce code duplication by adding mark_tcp_active() function. + - convert counters to atomic. + + (cherry picked from commit 7e8222378ca24f1302a0c1c638565050ab04681b) + (cherry picked from commit 4939451275722bfda490ea86ca13e84f6bc71e46) + (cherry picked from commit 13f7c918b8720d890408f678bd73c20e634539d9) + (cherry picked from commit c47ccf630f147378568b33e8fdb7b754f228c346) + + Remove usage of atomic operations, use classic locks + +commit adb720fd828327ef7452fbe9248ab6a2e0c99d8f +Author: Evan Hunt +Date: Fri Apr 5 16:12:18 2019 -0700 + + better tcpquota accounting and client mortality checks + + - ensure that tcpactive is cleaned up correctly when accept() fails. + - set 'client->tcpattached' when the client is attached to the tcpquota. + carry this value on to new clients sharing the same pipeline group. + don't call isc_quota_detach() on the tcpquota unless tcpattached is + set. this way clients that were allowed to accept TCP connections + despite being over quota (and therefore, were never attached to the + quota) will not inadvertently detach from it and mess up the + accounting. + - simplify the code for tcpquota disconnection by using a new function + tcpquota_disconnect(). + - before deciding whether to reject a new connection due to quota + exhaustion, check to see whether there are at least two active + clients. previously, this was "at least one", but that could be + insufficient if there was one other client in READING state (waiting + for messages on an open connection) but none in READY (listening + for new connections). + - before deciding whether a TCP client object can to go inactive, we + must ensure there are enough other clients to maintain service + afterward -- both accepting new connections and reading/processing new + queries. A TCP client can't shut down unless at least one + client is accepting new connections and (in the case of pipelined + clients) at least one additional client is waiting to read. + + (cherry picked from commit c7394738b2445c16f728a88394864dd61baad900) + (cherry picked from commit e965d5f11d3d0f6d59704e614fceca2093cb1856) + (cherry picked from commit 87d431161450777ea093821212abfb52d51b36e3) + (cherry picked from commit 2ab8a085b3c666f28f1f9229bd6ecb59915b26c3) + +commit a2c8804aec66f3e44d7dbb6a1b0f64d6cd7110dd +Author: Witold Kręcicki +Date: Fri Jan 4 12:50:51 2019 +0100 + + tcp-clients could still be exceeded (v2) + + the TCP client quota could still be ineffective under some + circumstances. this change: + + - improves quota accounting to ensure that TCP clients are + properly limited, while still guaranteeing that at least one client + is always available to serve TCP connections on each interface. + - uses more descriptive names and removes one (ntcptarget) that + was no longer needed + - adds comments + + (cherry picked from commit 924651f1d5e605cd186d03f4f7340bcc54d77cc2) + (cherry picked from commit 55a7a458e30e47874d34bdf1079eb863a0512396) + (cherry picked from commit 719f604e3fad5b7479bd14e2fa0ef4413f0a8fdc) + + Removed some unused parts + +Patch: bind98-CVE-2018-5743.patch +PatchNumber: 199 +--- + bin/named/client.c | 273 ++++++++++++++++++++----- + bin/named/include/named/client.h | 4 +- + bin/named/include/named/interfacemgr.h | 11 +- + bin/named/interfacemgr.c | 8 +- + doc/arm/Bv9ARM-book.xml | 3 +- + lib/isc/include/isc/quota.h | 7 + + lib/isc/quota.c | 33 ++- + 7 files changed, 275 insertions(+), 64 deletions(-) + +diff --git a/bin/named/client.c b/bin/named/client.c +index 9adf36b..c21b449 100644 +--- a/bin/named/client.c ++++ b/bin/named/client.c +@@ -279,6 +279,76 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds) { + } + + /*% ++ * Allocate a reference-counted object that will maintain a single pointer to ++ * the (also reference-counted) TCP client quota, shared between all the ++ * clients processing queries on a single TCP connection. ++ */ ++static isc_result_t ++tcpconn_init(ns_client_t *client, isc_boolean_t force) { ++ isc_result_t result; ++ isc_quota_t *quota = NULL; ++ ++ REQUIRE(client->tcpquota == NULL); ++ ++ /* ++ * Try to attach to the quota first, so we won't pointlessly ++ * allocate memory for a tcpconn object if we can't get one. ++ */ ++ if (force) { ++ result = isc_quota_force(&ns_g_server->tcpquota, "a); ++ } else { ++ result = isc_quota_attach(&ns_g_server->tcpquota, "a); ++ } ++ if (result != ISC_R_SUCCESS) { ++ return (result); ++ } ++ ++ client->tcpquota = quota; ++ quota = NULL; ++ ++ return (ISC_R_SUCCESS); ++} ++ ++/*% ++ * Decrease the count of client structures sharing the TCP connection that ++ * 'client' is associated with. If this is the last client using this TCP ++ * connection, we detach from the TCP quota. ++ */ ++static void ++tcpconn_detach(ns_client_t *client) { ++ REQUIRE(client->tcpquota != NULL); ++ ++ isc_quota_detach(&client->tcpquota); ++} ++ ++/*% ++ * Mark a client as active and increment the interface's 'ntcpactive' ++ * counter, as a signal that there is at least one client servicing ++ * TCP queries for the interface. If we reach the TCP client quota at ++ * some point, this will be used to determine whether a quota overrun ++ * should be permitted. ++ * ++ * Marking the client active with the 'tcpactive' flag ensures proper ++ * accounting, by preventing us from incrementing or decrementing ++ * 'ntcpactive' more than once per client. ++ */ ++static void ++mark_tcp_active(ns_client_t *client, isc_boolean_t active) { ++ if (active && !client->tcpactive) { ++ LOCK(&client->interface->lock); ++ client->interface->ntcpactive++; ++ client->tcpactive = active; ++ UNLOCK(&client->interface->lock); ++ } else if (!active && client->tcpactive) { ++ LOCK(&client->interface->lock); ++ INSIST(client->interface->ntcpactive > 0); ++ client->interface->ntcpactive--; ++ client->tcpactive = active; ++ UNLOCK(&client->interface->lock); ++ } ++} ++ ++/* + * Check for a deactivation or shutdown request and take appropriate + * action. Returns ISC_TRUE if either is in progress; in this case + * the caller must no longer use the client object as it may have been +@@ -367,6 +437,7 @@ exit_check(ns_client_t *client) { + INSIST(client->recursionquota == NULL); + + if (NS_CLIENTSTATE_READING == client->newstate) { ++ INSIST(client->tcpquota != NULL); + client_read(client); + client->newstate = NS_CLIENTSTATE_MAX; + return (ISC_TRUE); /* We're done. */ +@@ -380,10 +451,12 @@ exit_check(ns_client_t *client) { + */ + INSIST(client->recursionquota == NULL); + INSIST(client->newstate <= NS_CLIENTSTATE_READY); ++ + if (client->nreads > 0) + dns_tcpmsg_cancelread(&client->tcpmsg); +- if (! client->nreads == 0) { +- /* Still waiting for read cancel completion. */ ++ ++ /* Still waiting for read cancel completion. */ ++ if (client->nreads > 0) { + return (ISC_TRUE); + } + +@@ -391,14 +464,50 @@ exit_check(ns_client_t *client) { + dns_tcpmsg_invalidate(&client->tcpmsg); + client->tcpmsg_valid = ISC_FALSE; + } ++ ++ /* ++ * Soon the client will be ready to accept a new TCP ++ * connection or UDP request, but we may have enough ++ * clients doing that already. Check whether this client ++ * needs to remain active and allow it go inactive if ++ * not. ++ * ++ * UDP clients always go inactive at this point, but a TCP ++ * client may need to stay active and return to READY ++ * state if no other clients are available to listen ++ * for TCP requests on this interface. ++ * ++ * Regardless, if we're going to FREED state, that means ++ * the system is shutting down and we don't need to ++ * retain clients. ++ */ ++ LOCK(&client->interface->lock); ++ if (client->mortal && TCP_CLIENT(client) && ++ client->newstate != NS_CLIENTSTATE_FREED && ++ !ns_g_clienttest && ++ client->interface->ntcpaccepting == 0) ++ { ++ /* Nobody else is accepting */ ++ client->mortal = ISC_FALSE; ++ client->newstate = NS_CLIENTSTATE_READY; ++ } ++ UNLOCK(&client->interface->lock); ++ ++ /* ++ * Detach from TCP connection and TCP client quota, ++ * if appropriate. If this is the last reference to ++ * the TCP connection in our pipeline group, the ++ * TCP quota slot will be released. ++ */ ++ if (client->tcpquota) { ++ tcpconn_detach(client); ++ } + if (client->tcpsocket != NULL) { + CTRACE("closetcp"); + isc_socket_detach(&client->tcpsocket); ++ mark_tcp_active(client, ISC_FALSE); + } + +- if (client->tcpquota != NULL) +- isc_quota_detach(&client->tcpquota); +- + if (client->timerset) { + (void)isc_timer_reset(client->timer, + isc_timertype_inactive, +@@ -411,24 +520,6 @@ exit_check(ns_client_t *client) { + client->state = NS_CLIENTSTATE_READY; + INSIST(client->recursionquota == NULL); + +- /* +- * Now the client is ready to accept a new TCP connection +- * or UDP request, but we may have enough clients doing +- * that already. Check whether this client needs to remain +- * active and force it to go inactive if not. +- * +- * UDP clients go inactive at this point, but TCP clients +- * may remain active if we have fewer active TCP client +- * objects than desired due to an earlier quota exhaustion. +- */ +- if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) { +- LOCK(&client->interface->lock); +- if (client->interface->ntcpcurrent < +- client->interface->ntcptarget) +- client->mortal = ISC_FALSE; +- UNLOCK(&client->interface->lock); +- } +- + /* + * We don't need the client; send it to the inactive + * queue for recycling. +@@ -475,18 +566,20 @@ exit_check(ns_client_t *client) { + if (client->nctls > 0) + return (ISC_TRUE); + +- /* Deactivate the client. */ +- if (client->interface) +- ns_interface_detach(&client->interface); +- + INSIST(client->naccepts == 0); + INSIST(client->recursionquota == NULL); +- if (client->tcplistener != NULL) ++ if (client->tcplistener != NULL) { + isc_socket_detach(&client->tcplistener); ++ mark_tcp_active(client, ISC_FALSE); ++ } + + if (client->udpsocket != NULL) + isc_socket_detach(&client->udpsocket); + ++ /* Deactivate the client. */ ++ if (client->interface) ++ ns_interface_detach(&client->interface); ++ + if (client->dispatch != NULL) + dns_dispatch_detach(&client->dispatch); + +@@ -605,13 +698,16 @@ client_start(isc_task_t *task, isc_event_t *event) { + return; + + if (TCP_CLIENT(client)) { +- client_accept(client); ++ if (client->tcpquota != NULL) { ++ client_read(client); ++ } else { ++ client_accept(client); ++ } + } else { + client_udprecv(client); + } + } + +- + /*% + * The client's task has received a shutdown event. + */ +@@ -1499,6 +1595,7 @@ client_request(isc_task_t *task, isc_event_t *event) { + client->nrecvs--; + } else { + INSIST(TCP_CLIENT(client)); ++ INSIST(client->tcpquota != NULL); + REQUIRE(event->ev_type == DNS_EVENT_TCPMSG); + REQUIRE(event->ev_sender == &client->tcpmsg); + buffer = &client->tcpmsg.buffer; +@@ -2146,6 +2243,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { + client->filter_aaaa = dns_v4_aaaa_ok; + #endif + client->needshutdown = ns_g_clienttest; ++ client->tcpactive = ISC_FALSE; + + ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL, + NS_EVENT_CLIENTCONTROL, client_start, client, client, +@@ -2240,22 +2338,29 @@ static void + client_newconn(isc_task_t *task, isc_event_t *event) { + ns_client_t *client = event->ev_arg; + isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event; +- isc_result_t result; + + REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN); + REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(client->task == task); ++ REQUIRE(client->interface != NULL); + + UNUSED(task); + + INSIST(client->state == NS_CLIENTSTATE_READY); + ++ /* ++ * The accept() was successful and we're now establishing a new ++ * connection. We need to make note of it in the client and ++ * interface objects so client objects can do the right thing ++ * when going inactive in exit_check() (see comments in ++ * client_accept() for details). ++ */ + INSIST(client->naccepts == 1); + client->naccepts--; + + LOCK(&client->interface->lock); +- INSIST(client->interface->ntcpcurrent > 0); +- client->interface->ntcpcurrent--; ++ INSIST(client->interface->ntcpaccepting > 0); ++ client->interface->ntcpaccepting--; + UNLOCK(&client->interface->lock); + + /* +@@ -2289,6 +2394,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { + NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), + "accept failed: %s", + isc_result_totext(nevent->result)); ++ tcpconn_detach(client); + } + + if (exit_check(client)) +@@ -2326,16 +2432,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { + * telnetting to port 53 (once per CPU) will + * deny service to legitimate TCP clients. + */ +- result = isc_quota_attach(&ns_g_server->tcpquota, +- &client->tcpquota); +- if (result == ISC_R_SUCCESS) +- result = ns_client_replace(client); +- if (result != ISC_R_SUCCESS) { +- ns_client_log(client, NS_LOGCATEGORY_CLIENT, +- NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, +- "no more TCP clients: %s", +- isc_result_totext(result)); +- } ++ (void)ns_client_replace(client); + + client_read(client); + } +@@ -2350,12 +2447,67 @@ client_accept(ns_client_t *client) { + + CTRACE("accept"); + ++ /* ++ * Set up a new TCP connection. This means try to attach to the ++ * TCP client quota (tcp-clients), but fail if we're over quota. ++ */ ++ result = tcpconn_init(client, ISC_FALSE); ++ if (result != ISC_R_SUCCESS) { ++ isc_boolean_t exit; ++ ++ ns_client_log(client, NS_LOGCATEGORY_CLIENT, ++ NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, ++ "TCP client quota reached: %s", ++ isc_result_totext(result)); ++ ++ /* ++ * We have exceeded the system-wide TCP client quota. But, ++ * we can't just block this accept in all cases, because if ++ * we did, a heavy TCP load on other interfaces might cause ++ * this interface to be starved, with no clients able to ++ * accept new connections. ++ * ++ * So, we check here to see if any other clients are ++ * already servicing TCP queries on this interface (whether ++ * accepting, reading, or processing). If we find that at ++ * least one client other than this one is active, then ++ * it's okay *not* to call accept - we can let this ++ * client go inactive and another will take over when it's ++ * done. ++ * ++ * If there aren't enough active clients on the interface, ++ * then we can be a little bit flexible about the quota. ++ * We'll allow *one* extra client through to ensure we're ++ * listening on every interface; we do this by setting the ++ * 'force' option to tcpconn_init(). ++ * ++ * (Note: In practice this means that the real TCP client ++ * quota is tcp-clients plus the number of listening ++ * interfaces plus 1.) ++ */ ++ LOCK(&client->interface->lock); ++ exit = ISC_TF(client->interface->ntcpactive > (client->tcpactive ? 1 : 0)); ++ UNLOCK(&client->interface->lock); ++ if (exit) { ++ client->newstate = NS_CLIENTSTATE_INACTIVE; ++ (void)exit_check(client); ++ return; ++ } ++ ++ result = tcpconn_init(client, ISC_TRUE); ++ RUNTIME_CHECK(result == ISC_R_SUCCESS); ++ } ++ ++ /* ++ * If this client was set up using get_client() or get_worker(), ++ * then TCP is already marked active. However, if it was restarted ++ * from exit_check(), it might not be, so we take care of it now. ++ */ ++ mark_tcp_active(client, ISC_TRUE); ++ + result = isc_socket_accept(client->tcplistener, client->task, + client_newconn, client); + if (result != ISC_R_SUCCESS) { +- UNEXPECTED_ERROR(__FILE__, __LINE__, +- "isc_socket_accept() failed: %s", +- isc_result_totext(result)); + /* + * XXXRTH What should we do? We're trying to accept but + * it didn't work. If we just give up, then TCP +@@ -2363,12 +2515,38 @@ client_accept(ns_client_t *client) { + * + * For now, we just go idle. + */ ++ UNEXPECTED_ERROR(__FILE__, __LINE__, ++ "isc_socket_accept() failed: %s", ++ isc_result_totext(result)); ++ ++ tcpconn_detach(client); ++ mark_tcp_active(client, ISC_FALSE); + return; + } ++ ++ /* ++ * The client's 'naccepts' counter indicates that this client has ++ * called accept() and is waiting for a new connection. It should ++ * never exceed 1. ++ */ + INSIST(client->naccepts == 0); + client->naccepts++; ++ ++ /* ++ * The interface's 'ntcpaccepting' counter is incremented when ++ * any client calls accept(), and decremented in client_newconn() ++ * once the connection is established. ++ * ++ * When the client object is shutting down after handling a TCP ++ * request (see exit_check()), if this value is at least one, that ++ * means another client has called accept() and is waiting to ++ * establish the next connection. That means the client may be ++ * be free to become inactive; otherwise it may need to start ++ * listening for connections itself to prevent the interface ++ * going dead. ++ */ + LOCK(&client->interface->lock); +- client->interface->ntcpcurrent++; ++ client->interface->ntcpaccepting++; + UNLOCK(&client->interface->lock); + } + +@@ -2626,6 +2804,7 @@ get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, + + if (tcp) { + client->attributes |= NS_CLIENTATTR_TCP; ++ mark_tcp_active(client, ISC_TRUE); + isc_socket_attach(ifp->tcpsocket, + &client->tcplistener); + } else { +diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h +index 98e79df..b210e61 100644 +--- a/bin/named/include/named/client.h ++++ b/bin/named/include/named/client.h +@@ -131,7 +131,7 @@ struct ns_client { + isc_stdtime_t requesttime; + isc_stdtime_t now; + dns_name_t signername; /*%< [T]SIG key name */ +- dns_name_t * signer; /*%< NULL if not valid sig */ ++ dns_name_t *signer; /*%< NULL if not valid sig */ + isc_boolean_t mortal; /*%< Die after handling request */ + isc_quota_t *tcpquota; + isc_quota_t *recursionquota; +@@ -159,6 +159,8 @@ struct ns_client { + ISC_LINK(ns_client_t) link; + ISC_LINK(ns_client_t) rlink; + ISC_QLINK(ns_client_t) ilink; ++ ++ isc_boolean_t tcpactive; + }; + + typedef ISC_QUEUE(ns_client_t) client_queue_t; +diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h +index 380dbed..56d953c 100644 +--- a/bin/named/include/named/interfacemgr.h ++++ b/bin/named/include/named/interfacemgr.h +@@ -80,9 +80,14 @@ struct ns_interface { + dns_dispatch_t * udpdispatch[MAX_UDP_DISPATCH]; + /*%< UDP dispatchers. */ + isc_socket_t * tcpsocket; /*%< TCP socket. */ +- int ntcptarget; /*%< Desired number of concurrent +- TCP accepts */ +- int ntcpcurrent; /*%< Current ditto, locked */ ++ int32_t ntcpaccepting; /*%< Number of clients ++ ready to accept new ++ TCP connections on this ++ interface */ ++ int32_t ntcpactive; /*%< Number of clients ++ servicing TCP queries ++ (whether accepting or ++ connected) */ + int nudpdispatch; /*%< Number of UDP dispatches */ + ns_clientmgr_t * clientmgr; /*%< Client manager. */ + ISC_LINK(ns_interface_t) link; +diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c +index 4aee47a..e3f8cee 100644 +--- a/bin/named/interfacemgr.c ++++ b/bin/named/interfacemgr.c +@@ -380,8 +380,8 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, + * connections will be handled in parallel even though there is + * only one client initially. + */ +- ifp->ntcptarget = 1; +- ifp->ntcpcurrent = 0; ++ ifp->ntcpaccepting = 0; ++ ifp->ntcpactive = 0; + ifp->nudpdispatch = 0; + + ISC_LINK_INIT(ifp, link); +@@ -510,9 +510,7 @@ ns_interface_accepttcp(ns_interface_t *ifp) { + */ + (void)isc_socket_filter(ifp->tcpsocket, "dataready"); + +- result = ns_clientmgr_createclients(ifp->clientmgr, +- ifp->ntcptarget, ifp, +- ISC_TRUE); ++ result = ns_clientmgr_createclients(ifp->clientmgr, 1, ifp, ISC_TRUE); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "TCP ns_clientmgr_createclients(): %s", +diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml +index af194d9..aa567aa 100644 +--- a/doc/arm/Bv9ARM-book.xml ++++ b/doc/arm/Bv9ARM-book.xml +@@ -8067,7 +8067,8 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; + + The number of file descriptors reserved for TCP, stdio, + etc. This needs to be big enough to cover the number of +- interfaces named listens on, tcp-clients as well as ++ interfaces named listens on plus ++ tcp-clients, as well as + to provide room for outgoing TCP queries and incoming zone + transfers. The default is 512. + The minimum value is 128 and the +diff --git a/lib/isc/include/isc/quota.h b/lib/isc/include/isc/quota.h +index 7b0d0d9..bb1a927 100644 +--- a/lib/isc/include/isc/quota.h ++++ b/lib/isc/include/isc/quota.h +@@ -107,6 +107,13 @@ isc_quota_attach(isc_quota_t *quota, isc_quota_t **p); + * quota if successful (ISC_R_SUCCESS or ISC_R_SOFTQUOTA). + */ + ++isc_result_t ++isc_quota_force(isc_quota_t *quota, isc_quota_t **p); ++/*%< ++ * Like isc_quota_attach, but will attach '*p' to the quota ++ * even if the hard quota has been exceeded. ++ */ ++ + void + isc_quota_detach(isc_quota_t **p); + /*%< +diff --git a/lib/isc/quota.c b/lib/isc/quota.c +index 5e5c50c..ca4c478 100644 +--- a/lib/isc/quota.c ++++ b/lib/isc/quota.c +@@ -81,20 +81,39 @@ isc_quota_release(isc_quota_t *quota) { + UNLOCK("a->lock); + } + +-isc_result_t +-isc_quota_attach(isc_quota_t *quota, isc_quota_t **p) +-{ ++static isc_result_t ++doattach(isc_quota_t *quota, isc_quota_t **p, isc_boolean_t force) { + isc_result_t result; +- INSIST(p != NULL && *p == NULL); ++ REQUIRE(p != NULL && *p == NULL); ++ + result = isc_quota_reserve(quota); +- if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA) ++ if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA) { ++ *p = quota; ++ } else if (result == ISC_R_QUOTA && force) { ++ /* attach anyway */ ++ LOCK("a->lock); ++ quota->used++; ++ UNLOCK("a->lock); ++ + *p = quota; ++ result = ISC_R_SUCCESS; ++ } ++ + return (result); + } + ++isc_result_t ++isc_quota_attach(isc_quota_t *quota, isc_quota_t **p) { ++ return (doattach(quota, p, ISC_FALSE)); ++} ++ ++isc_result_t ++isc_quota_force(isc_quota_t *quota, isc_quota_t **p) { ++ return (doattach(quota, p, ISC_TRUE)); ++} ++ + void +-isc_quota_detach(isc_quota_t **p) +-{ ++isc_quota_detach(isc_quota_t **p) { + INSIST(p != NULL && *p != NULL); + isc_quota_release(*p); + *p = NULL; +-- +2.20.1 + diff --git a/SPECS/bind.spec b/SPECS/bind.spec index 940c830..82eb8f5 100644 --- a/SPECS/bind.spec +++ b/SPECS/bind.spec @@ -26,7 +26,7 @@ Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) serv Name: bind License: ISC Version: 9.9.4 -Release: 74%{?PATCHVER}%{?PREVER}%{?dist}.1 +Release: 74%{?PATCHVER}%{?PREVER}%{?dist}.2 Epoch: 32 Url: http://www.isc.org/products/BIND/ Buildroot:%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -174,10 +174,9 @@ Patch196: bind99-rh1549130.patch Patch197: bind99-rh1549130-2.patch Patch198: bind99-CVE-2018-5740.patch Patch199: bind99-rh1647539.patch -Patch200: bind-9.11-rt37039.patch -Patch201: bind-9.11-rt37821.patch -Patch202: bind-9.11-CVE-2018-5743.patch -Patch203: bind-9.11-CVE-2018-5743-atomic.patch +Patch200: bind99-CVE-2018-5743.patch +# Accept keep-response-order support & warning +Patch201: bind99-CVE-2018-5743-option.patch # Native PKCS#11 functionality from 9.10 Patch150:bind-9.9-allow_external_dnskey.patch @@ -504,10 +503,8 @@ tar -xf %{SOURCE48} -C bin/tests/system/geoip/data %patch197 -p1 -b .rh1549130-2 %patch198 -p1 -b .CVE-2018-5740 %patch199 -p1 -b .rh1647539 -%patch200 -p1 -b .tcp-share -%patch201 -p1 -b .tcp-pipeline -%patch202 -p1 -b .CVE-2018-5743 -%patch203 -p1 -b .CVE-2018-5743-atomic +%patch200 -p1 -b .CVE-2018-5743 +%patch201 -p1 -b .keep-response-order # Override upstream builtin keys cp -fp %{SOURCE29} bind.keys @@ -1215,6 +1212,10 @@ rm -rf ${RPM_BUILD_ROOT} %endif %changelog +* Fri Jun 21 2019 Petr Menšík - 32:9.9.4-74.2 +- Fix unstable zone transfers (#1724071) +- Understand keep-response-order for backward compatibility + * Thu May 23 2019 Petr Menšík - 32:9.9.4-74.1 - Remove again broken test (CVE-2018-5743)