diff --git a/SOURCES/bind-9.11-CVE-2018-5743-atomic.patch b/SOURCES/bind-9.11-CVE-2018-5743-atomic.patch new file mode 100644 index 0000000..6997084 --- /dev/null +++ b/SOURCES/bind-9.11-CVE-2018-5743-atomic.patch @@ -0,0 +1,131 @@ +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 new file mode 100644 index 0000000..6b8c48f --- /dev/null +++ b/SOURCES/bind-9.11-CVE-2018-5743.patch @@ -0,0 +1,864 @@ +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 new file mode 100644 index 0000000..aa11ed6 --- /dev/null +++ b/SOURCES/bind-9.11-rt37039.patch @@ -0,0 +1,380 @@ +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 new file mode 100644 index 0000000..9ae27c1 --- /dev/null +++ b/SOURCES/bind-9.11-rt37821.patch @@ -0,0 +1,1532 @@ +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/SPECS/bind.spec b/SPECS/bind.spec index 48f91b1..940c830 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: 73%{?PATCHVER}%{?PREVER}%{?dist} +Release: 74%{?PATCHVER}%{?PREVER}%{?dist}.1 Epoch: 32 Url: http://www.isc.org/products/BIND/ Buildroot:%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -174,6 +174,10 @@ 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 # Native PKCS#11 functionality from 9.10 Patch150:bind-9.9-allow_external_dnskey.patch @@ -500,6 +504,10 @@ 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 # Override upstream builtin keys cp -fp %{SOURCE29} bind.keys @@ -1207,6 +1215,12 @@ rm -rf ${RPM_BUILD_ROOT} %endif %changelog +* Thu May 23 2019 Petr Menšík - 32:9.9.4-74.1 +- Remove again broken test (CVE-2018-5743) + +* Tue May 07 2019 Petr Menšík - 32:9.9.4-74 +- Fix CVE-2018-5743 + * Fri Nov 23 2018 Petr Menšík - 32:9.9.4-73 - Fixes debug level comments (#1647539)