Blame SOURCES/bind-9.11-rt37039.patch

c2d2c5
From f34cc4f62cd6730fc315ace47b9ae90a82a07ec0 Mon Sep 17 00:00:00 2001
c2d2c5
From: Mark Andrews <marka@isc.org>
c2d2c5
Date: Thu, 4 Sep 2014 10:37:45 +1000
c2d2c5
Subject: [PATCH] 3939. [func] Improve UPDATE forwarding performance by
c2d2c5
 allowing TCP connections to be shared. [RT #37039]
c2d2c5
c2d2c5
(cherry picked from commit 74717eef53ba5d6aefc80eb262bbb090ff4bb3b5)
c2d2c5
---
c2d2c5
 lib/dns/dispatch.c             | 112 ++++++++++++++++++++++++++++++++-
c2d2c5
 lib/dns/include/dns/dispatch.h |  15 +++++
c2d2c5
 lib/dns/request.c              |  46 ++++++++++----
c2d2c5
 lib/dns/win32/libdns.def       |   2 +
c2d2c5
 4 files changed, 159 insertions(+), 16 deletions(-)
c2d2c5
c2d2c5
diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c
c2d2c5
index c93651d..ee82241 100644
c2d2c5
--- a/lib/dns/dispatch.c
c2d2c5
+++ b/lib/dns/dispatch.c
c2d2c5
@@ -228,6 +228,7 @@ struct dns_dispatch {
c2d2c5
 	isc_socket_t	       *socket;		/*%< isc socket attached to */
c2d2c5
 	isc_sockaddr_t		local;		/*%< local address */
c2d2c5
 	in_port_t		localport;	/*%< local UDP port */
c2d2c5
+	isc_sockaddr_t		peer;		/*%< peer address (TCP) */
c2d2c5
 	unsigned int		maxrequests;	/*%< max requests */
c2d2c5
 	isc_event_t	       *ctlevent;
c2d2c5
 
c2d2c5
@@ -2327,7 +2328,6 @@ dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) {
c2d2c5
 
c2d2c5
 	LOCK(&mgr->lock);
c2d2c5
 	mgr->state |= MGR_SHUTTINGDOWN;
c2d2c5
-
c2d2c5
 	killit = destroy_mgr_ok(mgr);
c2d2c5
 	UNLOCK(&mgr->lock);
c2d2c5
 
c2d2c5
@@ -2601,6 +2601,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
c2d2c5
 	disp->refcount = 1;
c2d2c5
 	disp->recv_pending = 0;
c2d2c5
 	memset(&disp->local, 0, sizeof(disp->local));
c2d2c5
+	memset(&disp->peer, 0, sizeof(disp->peer));
c2d2c5
 	disp->localport = 0;
c2d2c5
 	disp->shutting_down = 0;
c2d2c5
 	disp->shutdown_out = 0;
c2d2c5
@@ -2702,6 +2703,23 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
c2d2c5
 		       unsigned int buckets, unsigned int increment,
c2d2c5
 		       unsigned int attributes, dns_dispatch_t **dispp)
c2d2c5
 {
c2d2c5
+
c2d2c5
+	attributes |= DNS_DISPATCHATTR_PRIVATE;  /* XXXMLG */
c2d2c5
+
c2d2c5
+	return (dns_dispatch_createtcp2(mgr, sock, taskmgr, NULL, NULL,
c2d2c5
+					buffersize, maxbuffers, maxrequests,
c2d2c5
+					buckets, increment, attributes,
c2d2c5
+					dispp));
c2d2c5
+}
c2d2c5
+
c2d2c5
+isc_result_t
c2d2c5
+dns_dispatch_createtcp2(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
c2d2c5
+		        isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
c2d2c5
+			isc_sockaddr_t *destaddr, unsigned int buffersize,
c2d2c5
+		        unsigned int maxbuffers, unsigned int maxrequests,
c2d2c5
+		        unsigned int buckets, unsigned int increment,
c2d2c5
+		        unsigned int attributes, dns_dispatch_t **dispp)
c2d2c5
+{
c2d2c5
 	isc_result_t result;
c2d2c5
 	dns_dispatch_t *disp;
c2d2c5
 
c2d2c5
@@ -2713,7 +2731,8 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
c2d2c5
 	REQUIRE((attributes & DNS_DISPATCHATTR_TCP) != 0);
c2d2c5
 	REQUIRE((attributes & DNS_DISPATCHATTR_UDP) == 0);
c2d2c5
 
c2d2c5
-	attributes |= DNS_DISPATCHATTR_PRIVATE;  /* XXXMLG */
c2d2c5
+	if (destaddr == NULL)
c2d2c5
+		attributes |= DNS_DISPATCHATTR_PRIVATE;  /* XXXMLG */
c2d2c5
 
c2d2c5
 	LOCK(&mgr->lock);
c2d2c5
 
c2d2c5
@@ -2760,6 +2779,23 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
c2d2c5
 
c2d2c5
 	disp->attributes = attributes;
c2d2c5
 
c2d2c5
+	if (localaddr == NULL) {
c2d2c5
+		if (destaddr != NULL) {
c2d2c5
+			switch (isc_sockaddr_pf(destaddr)) {
c2d2c5
+			case AF_INET:
c2d2c5
+				isc_sockaddr_any(&disp->local);
c2d2c5
+				break;
c2d2c5
+			case AF_INET6:
c2d2c5
+				isc_sockaddr_any6(&disp->local);
c2d2c5
+				break;
c2d2c5
+			}
c2d2c5
+		}
c2d2c5
+	} else
c2d2c5
+		disp->local = *localaddr;
c2d2c5
+
c2d2c5
+	if (destaddr != NULL)
c2d2c5
+		disp->peer = *destaddr;
c2d2c5
+
c2d2c5
 	/*
c2d2c5
 	 * Append it to the dispatcher list.
c2d2c5
 	 */
c2d2c5
@@ -2768,7 +2804,6 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
c2d2c5
 
c2d2c5
 	mgr_log(mgr, LVL(90), "created TCP dispatcher %p", disp);
c2d2c5
 	dispatch_log(disp, LVL(90), "created task %p", disp->task[0]);
c2d2c5
-
c2d2c5
 	*dispp = disp;
c2d2c5
 
c2d2c5
 	return (ISC_R_SUCCESS);
c2d2c5
@@ -2788,6 +2823,77 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
c2d2c5
 	return (result);
c2d2c5
 }
c2d2c5
 
c2d2c5
+isc_result_t
c2d2c5
+dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr,
c2d2c5
+		    isc_sockaddr_t *localaddr, dns_dispatch_t **dispp)
c2d2c5
+{
c2d2c5
+#ifdef BIND9
c2d2c5
+	dns_dispatch_t *disp;
c2d2c5
+	isc_result_t result;
c2d2c5
+	isc_sockaddr_t peeraddr;
c2d2c5
+	isc_sockaddr_t sockname;
c2d2c5
+	isc_sockaddr_t any;
c2d2c5
+	unsigned int attributes, mask;
c2d2c5
+	isc_boolean_t match = ISC_FALSE;
c2d2c5
+
c2d2c5
+	REQUIRE(VALID_DISPATCHMGR(mgr));
c2d2c5
+	REQUIRE(destaddr != NULL);
c2d2c5
+	REQUIRE(dispp != NULL && *dispp == NULL);
c2d2c5
+
c2d2c5
+	attributes = DNS_DISPATCHATTR_TCP;
c2d2c5
+	mask = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_PRIVATE |
c2d2c5
+	       DNS_DISPATCHATTR_EXCLUSIVE;
c2d2c5
+
c2d2c5
+	if (localaddr == NULL) {
c2d2c5
+		switch (isc_sockaddr_pf(destaddr)) {
c2d2c5
+		case AF_INET:
c2d2c5
+			isc_sockaddr_any(&any;;
c2d2c5
+			break;
c2d2c5
+		case AF_INET6:
c2d2c5
+			isc_sockaddr_any6(&any;;
c2d2c5
+			break;
c2d2c5
+		default:
c2d2c5
+			return (ISC_R_NOTFOUND);
c2d2c5
+		}
c2d2c5
+		localaddr = &any;
c2d2c5
+	}
c2d2c5
+
c2d2c5
+	LOCK(&mgr->lock);
c2d2c5
+	disp = ISC_LIST_HEAD(mgr->list);
c2d2c5
+	while (disp != NULL && !match) {
c2d2c5
+		LOCK(&disp->lock);
c2d2c5
+		if ((disp->shutting_down == 0) &&
c2d2c5
+		    ATTRMATCH(disp->attributes, attributes, mask) &&
c2d2c5
+		    (localaddr == NULL ||
c2d2c5
+		     isc_sockaddr_eqaddr(localaddr, &disp->local))) {
c2d2c5
+			result = isc_socket_getsockname(disp->socket,
c2d2c5
+							&sockname);
c2d2c5
+			if (result == ISC_R_SUCCESS)
c2d2c5
+				result = isc_socket_getpeername(disp->socket,
c2d2c5
+								&peeraddr);
c2d2c5
+			if (result == ISC_R_SUCCESS &&
c2d2c5
+			    isc_sockaddr_equal(destaddr, &peeraddr) &&
c2d2c5
+			    isc_sockaddr_eqaddr(localaddr, &sockname)) {
c2d2c5
+				/* attach */
c2d2c5
+				disp->refcount++;
c2d2c5
+				*dispp = disp;
c2d2c5
+				match = ISC_TRUE;
c2d2c5
+			}
c2d2c5
+		}
c2d2c5
+		UNLOCK(&disp->lock);
c2d2c5
+		disp = ISC_LIST_NEXT(disp, link);
c2d2c5
+	}
c2d2c5
+	UNLOCK(&mgr->lock);
c2d2c5
+	return (match ? ISC_R_SUCCESS : ISC_R_NOTFOUND);
c2d2c5
+#else
c2d2c5
+	UNUSED(mgr);
c2d2c5
+	UNUSED(destaddr);
c2d2c5
+	UNUSED(localaddr);
c2d2c5
+	UNUSED(dispp);
c2d2c5
+	return ISC_R_NOTIMPLEMENTED;
c2d2c5
+#endif
c2d2c5
+}
c2d2c5
+
c2d2c5
 isc_result_t
c2d2c5
 dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
c2d2c5
 		    isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
c2d2c5
diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h
c2d2c5
index 1235f7c..be9cd66 100644
c2d2c5
--- a/lib/dns/include/dns/dispatch.h
c2d2c5
+++ b/lib/dns/include/dns/dispatch.h
c2d2c5
@@ -298,6 +298,13 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
c2d2c5
 		       unsigned int maxbuffers, unsigned int maxrequests,
c2d2c5
 		       unsigned int buckets, unsigned int increment,
c2d2c5
 		       unsigned int attributes, dns_dispatch_t **dispp);
c2d2c5
+isc_result_t
c2d2c5
+dns_dispatch_createtcp2(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
c2d2c5
+                        isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
c2d2c5
+                        isc_sockaddr_t *destaddr, unsigned int buffersize,
c2d2c5
+                        unsigned int maxbuffers, unsigned int maxrequests,
c2d2c5
+                        unsigned int buckets, unsigned int increment,
c2d2c5
+                        unsigned int attributes, dns_dispatch_t **dispp);
c2d2c5
 /*%<
c2d2c5
  * Create a new dns_dispatch and attach it to the provided isc_socket_t.
c2d2c5
  *
c2d2c5
@@ -369,6 +376,14 @@ dns_dispatch_starttcp(dns_dispatch_t *disp);
c2d2c5
  *\li	'disp' is valid.
c2d2c5
  */
c2d2c5
 
c2d2c5
+isc_result_t
c2d2c5
+dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr,
c2d2c5
+                    isc_sockaddr_t *localaddr, dns_dispatch_t **dispp);
c2d2c5
+/*
c2d2c5
+ * Attempt to connect to a existing TCP connection.
c2d2c5
+ */
c2d2c5
+
c2d2c5
+
c2d2c5
 isc_result_t
c2d2c5
 dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
c2d2c5
 			  isc_task_t *task, isc_taskaction_t action, void *arg,
c2d2c5
diff --git a/lib/dns/request.c b/lib/dns/request.c
c2d2c5
index 5c76f9a..9fb6f44 100644
c2d2c5
--- a/lib/dns/request.c
c2d2c5
+++ b/lib/dns/request.c
c2d2c5
@@ -510,7 +510,8 @@ isblackholed(dns_dispatchmgr_t *dispatchmgr, isc_sockaddr_t *destaddr) {
c2d2c5
 
c2d2c5
 static isc_result_t
c2d2c5
 create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
c2d2c5
-		    isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
c2d2c5
+		    isc_sockaddr_t *destaddr, isc_boolean_t *connected,
c2d2c5
+		    dns_dispatch_t **dispatchp)
c2d2c5
 {
c2d2c5
 	isc_result_t result;
c2d2c5
 	isc_socket_t *socket = NULL;
c2d2c5
@@ -518,6 +519,20 @@ create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
c2d2c5
 	unsigned int attrs;
c2d2c5
 	isc_sockaddr_t bind_any;
c2d2c5
 
c2d2c5
+	*connected = ISC_FALSE;
c2d2c5
+#ifdef BIND9
c2d2c5
+	result = dns_dispatch_gettcp(requestmgr->dispatchmgr, destaddr,
c2d2c5
+				     srcaddr, dispatchp);
c2d2c5
+	if (result == ISC_R_SUCCESS) {
c2d2c5
+		*connected = ISC_TRUE;
c2d2c5
+		char peer[ISC_SOCKADDR_FORMATSIZE];
c2d2c5
+		isc_sockaddr_format(destaddr, peer, sizeof(peer));
c2d2c5
+		req_log(ISC_LOG_DEBUG(1), "attached to existing TCP "
c2d2c5
+			"connection to %s", peer);
c2d2c5
+		return (result);
c2d2c5
+	}
c2d2c5
+#endif
c2d2c5
+
c2d2c5
 	result = isc_socket_create(requestmgr->socketmgr,
c2d2c5
 				   isc_sockaddr_pf(destaddr),
c2d2c5
 				   isc_sockettype_tcp, &socket);
c2d2c5
@@ -538,16 +553,16 @@ create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
c2d2c5
 #endif
c2d2c5
 	attrs = 0;
c2d2c5
 	attrs |= DNS_DISPATCHATTR_TCP;
c2d2c5
-	attrs |= DNS_DISPATCHATTR_PRIVATE;
c2d2c5
 	if (isc_sockaddr_pf(destaddr) == AF_INET)
c2d2c5
 		attrs |= DNS_DISPATCHATTR_IPV4;
c2d2c5
 	else
c2d2c5
 		attrs |= DNS_DISPATCHATTR_IPV6;
c2d2c5
 	attrs |= DNS_DISPATCHATTR_MAKEQUERY;
c2d2c5
-	result = dns_dispatch_createtcp(requestmgr->dispatchmgr,
c2d2c5
-					socket, requestmgr->taskmgr,
c2d2c5
-					4096, 2, 1, 1, 3, attrs,
c2d2c5
-					dispatchp);
c2d2c5
+	result = dns_dispatch_createtcp2(requestmgr->dispatchmgr,
c2d2c5
+					 socket, requestmgr->taskmgr,
c2d2c5
+					 srcaddr, destaddr,
c2d2c5
+					 4096, 32768, 32768, 16411, 16433,
c2d2c5
+					 attrs, dispatchp);
c2d2c5
 cleanup:
c2d2c5
 	isc_socket_detach(&socket);
c2d2c5
 	return (result);
c2d2c5
@@ -609,12 +624,15 @@ find_udp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
c2d2c5
 static isc_result_t
c2d2c5
 get_dispatch(isc_boolean_t tcp, dns_requestmgr_t *requestmgr,
c2d2c5
 	     isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
c2d2c5
+	     isc_boolean_t *connected,
c2d2c5
 	     dns_dispatch_t **dispatchp)
c2d2c5
 {
c2d2c5
 	isc_result_t result;
c2d2c5
+
c2d2c5
 	if (tcp)
c2d2c5
 		result = create_tcp_dispatch(requestmgr, srcaddr,
c2d2c5
-					     destaddr, dispatchp);
c2d2c5
+					     destaddr, connected,
c2d2c5
+					     dispatchp);
c2d2c5
 	else
c2d2c5
 		result = find_udp_dispatch(requestmgr, srcaddr,
c2d2c5
 					   destaddr, dispatchp);
c2d2c5
@@ -686,6 +704,7 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
c2d2c5
 	dns_messageid_t	id;
c2d2c5
 	isc_boolean_t tcp = ISC_FALSE;
c2d2c5
 	isc_region_t r;
c2d2c5
+	isc_boolean_t connected = ISC_FALSE;
c2d2c5
 
c2d2c5
 	REQUIRE(VALID_REQUESTMGR(requestmgr));
c2d2c5
 	REQUIRE(msgbuf != NULL);
c2d2c5
@@ -747,7 +766,7 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
c2d2c5
 		tcp = ISC_TRUE;
c2d2c5
 
c2d2c5
 	result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
c2d2c5
-			      &request->dispatch);
c2d2c5
+			      &connected, &request->dispatch);
c2d2c5
 	if (result != ISC_R_SUCCESS)
c2d2c5
 		goto cleanup;
c2d2c5
 
c2d2c5
@@ -794,14 +813,14 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
c2d2c5
 		goto unlink;
c2d2c5
 
c2d2c5
 	request->destaddr = *destaddr;
c2d2c5
-	if (tcp) {
c2d2c5
+	if (tcp && !connected) {
c2d2c5
 		result = isc_socket_connect(socket, destaddr, task,
c2d2c5
 					    req_connected, request);
c2d2c5
 		if (result != ISC_R_SUCCESS)
c2d2c5
 			goto unlink;
c2d2c5
 		request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
c2d2c5
 	} else {
c2d2c5
-		result = req_send(request, task, destaddr);
c2d2c5
+		result = req_send(request, task, connected ? NULL : destaddr);
c2d2c5
 		if (result != ISC_R_SUCCESS)
c2d2c5
 			goto unlink;
c2d2c5
 	}
c2d2c5
@@ -886,6 +905,7 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
c2d2c5
 	dns_messageid_t	id;
c2d2c5
 	isc_boolean_t tcp;
c2d2c5
 	isc_boolean_t setkey = ISC_TRUE;
c2d2c5
+	isc_boolean_t connected = ISC_FALSE;
c2d2c5
 
c2d2c5
 	REQUIRE(VALID_REQUESTMGR(requestmgr));
c2d2c5
 	REQUIRE(message != NULL);
c2d2c5
@@ -944,7 +964,7 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
c2d2c5
  use_tcp:
c2d2c5
 	tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0);
c2d2c5
 	result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
c2d2c5
-			      &request->dispatch);
c2d2c5
+			      &connected, &request->dispatch);
c2d2c5
 	if (result != ISC_R_SUCCESS)
c2d2c5
 		goto cleanup;
c2d2c5
 
c2d2c5
@@ -1000,14 +1020,14 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
c2d2c5
 		goto unlink;
c2d2c5
 
c2d2c5
 	request->destaddr = *destaddr;
c2d2c5
-	if (tcp) {
c2d2c5
+	if (tcp && !connected) {
c2d2c5
 		result = isc_socket_connect(socket, destaddr, task,
c2d2c5
 					    req_connected, request);
c2d2c5
 		if (result != ISC_R_SUCCESS)
c2d2c5
 			goto unlink;
c2d2c5
 		request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
c2d2c5
 	} else {
c2d2c5
-		result = req_send(request, task, destaddr);
c2d2c5
+		result = req_send(request, task, connected ? NULL : destaddr);
c2d2c5
 		if (result != ISC_R_SUCCESS)
c2d2c5
 			goto unlink;
c2d2c5
 	}
c2d2c5
diff --git a/lib/dns/win32/libdns.def b/lib/dns/win32/libdns.def
c2d2c5
index 5e20491..9aebe16 100644
c2d2c5
--- a/lib/dns/win32/libdns.def
c2d2c5
+++ b/lib/dns/win32/libdns.def
c2d2c5
@@ -176,9 +176,11 @@ dns_dispatch_attach
c2d2c5
 dns_dispatch_cancel
c2d2c5
 dns_dispatch_changeattributes
c2d2c5
 dns_dispatch_createtcp
c2d2c5
+dns_dispatch_createtcp2
c2d2c5
 dns_dispatch_detach
c2d2c5
 dns_dispatch_getlocaladdress
c2d2c5
 dns_dispatch_getsocket
c2d2c5
+dns_dispatch_gettcp
c2d2c5
 dns_dispatch_getudp
c2d2c5
 dns_dispatch_getudp_dup
c2d2c5
 dns_dispatch_importrecv
c2d2c5
-- 
c2d2c5
2.20.1
c2d2c5