2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 13:38:26 +00:00

Dispatch API simplification

- Many dispatch attributes can be set implicitly instead of being passed
  in. we can infer whether to set DNS_DISPATCHATTR_TCP or _UDP from
  whether we're calling dns_dispatch_createtcp() or _createudp().  we
  can also infer DNS_DISPATCHATTR_IPV4 or _IPV6 from the addresses or
  the socket that were passed in.

- We no longer use dup'd sockets in UDP dispatches, so the 'dup_socket'
  parameter has been removed from dns_dispatch_createudp(), along with
  the code implementing it. also removed isc_socket_dup() since it no
  longer has any callers.

- The 'buffersize' parameter was ignored and has now been removed;
  buffersize is now fixed at 4096.

- Maxbuffers and maxrequests don't need to be passed in on every call to
  dns_dispatch_createtcp() and _createudp().

  In all current uses, the value for mgr->maxbuffers will either be
  raised once from its default of 20000 to 32768, or else left
  alone. (passing in a value lower than 20000 does not lower it.) there
  isn't enough difference between these values for there to be any need
  to configure this.

  The value for disp->maxrequests controls both the quota of concurrent
  requests for a dispatch and also the size of the dispatch socket
  memory pool. it's not clear that this quota is necessary at all. the
  memory pool size currently starts at 32768, but is sometimes lowered
  to 4096, which is definitely unnecessary.

  This commit sets both values permanently to 32768.

- Previously TCP dispatches allocated their own separate QID table,
  which didn't incorporate a port table. this commit removes
  per-dispatch QID tables and shares the same table between all
  dispatches. since dispatches are created for each TCP socket, this may
  speed up the dispatch allocation process. there may be a slight
  increase in lock contention since all dispatches are sharing a single
  QID table, but since TCP sockets are used less often than UDP
  sockets (which were already sharing a QID table), it should not be a
  substantial change.

- The dispatch port table was being used to determine whether a port was
  already in use; if so, then a UDP socket would be bound with
  REUSEADDR. this commit removes the port table, and always binds UDP
  sockets that way.
This commit is contained in:
Evan Hunt 2020-12-17 00:43:00 -08:00 committed by Ondřej Surý
parent 9fd375217d
commit f439eb5d99
16 changed files with 273 additions and 796 deletions

View File

@ -160,10 +160,8 @@
#ifdef TUNE_LARGE #ifdef TUNE_LARGE
#define RESOLVER_NTASKS_PERCPU 32 #define RESOLVER_NTASKS_PERCPU 32
#define UDPBUFFERS 32768
#else #else
#define RESOLVER_NTASKS_PERCPU 8 #define RESOLVER_NTASKS_PERCPU 8
#define UDPBUFFERS 4096
#endif /* TUNE_LARGE */ #endif /* TUNE_LARGE */
/* RFC7828 defines timeout as 16-bit value specified in units of 100 /* RFC7828 defines timeout as 16-bit value specified in units of 100
@ -1260,9 +1258,8 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af,
isc_result_t result = ISC_R_FAILURE; isc_result_t result = ISC_R_FAILURE;
dns_dispatch_t *disp = NULL; dns_dispatch_t *disp = NULL;
isc_sockaddr_t sa; isc_sockaddr_t sa;
unsigned int attrs; unsigned int attrs = 0;
const cfg_obj_t *obj = NULL; const cfg_obj_t *obj = NULL;
unsigned int maxdispatchbuffers = UDPBUFFERS;
isc_dscp_t dscp = -1; isc_dscp_t dscp = -1;
switch (af) { switch (af) {
@ -1308,15 +1305,6 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af,
/* /*
* Try to find a dispatcher that we can share. * Try to find a dispatcher that we can share.
*/ */
attrs = DNS_DISPATCHATTR_UDP;
switch (af) {
case AF_INET:
attrs |= DNS_DISPATCHATTR_IPV4;
break;
case AF_INET6:
attrs |= DNS_DISPATCHATTR_IPV6;
break;
}
if (isc_sockaddr_getport(&sa) != 0) { if (isc_sockaddr_getport(&sa) != 0) {
INSIST(obj != NULL); INSIST(obj != NULL);
if (is_firstview) { if (is_firstview) {
@ -1327,9 +1315,8 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af,
} }
} }
result = dns_dispatch_createudp( result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_socketmgr,
named_g_dispatchmgr, named_g_socketmgr, named_g_taskmgr, &sa, named_g_taskmgr, &sa, attrs, &disp);
maxdispatchbuffers, 32768, 16411, 16433, attrs, &disp);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
isc_sockaddr_t any; isc_sockaddr_t any;
char buf[ISC_SOCKADDR_FORMATSIZE]; char buf[ISC_SOCKADDR_FORMATSIZE];
@ -10343,7 +10330,7 @@ named_add_reserved_dispatch(named_server_t *server,
in_port_t port; in_port_t port;
char addrbuf[ISC_SOCKADDR_FORMATSIZE]; char addrbuf[ISC_SOCKADDR_FORMATSIZE];
isc_result_t result; isc_result_t result;
unsigned int attrs; unsigned int attrs = 0;
REQUIRE(NAMED_SERVER_VALID(server)); REQUIRE(NAMED_SERVER_VALID(server));
@ -10370,22 +10357,8 @@ named_add_reserved_dispatch(named_server_t *server,
dispatch->dispatchgen = server->dispatchgen; dispatch->dispatchgen = server->dispatchgen;
dispatch->dispatch = NULL; dispatch->dispatch = NULL;
attrs = DNS_DISPATCHATTR_UDP;
switch (isc_sockaddr_pf(addr)) {
case AF_INET:
attrs |= DNS_DISPATCHATTR_IPV4;
break;
case AF_INET6:
attrs |= DNS_DISPATCHATTR_IPV6;
break;
default:
result = ISC_R_NOTIMPLEMENTED;
goto cleanup;
}
result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_socketmgr, result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_socketmgr,
named_g_taskmgr, &dispatch->addr, named_g_taskmgr, &dispatch->addr, attrs,
UDPBUFFERS, 32768, 16411, 16433, attrs,
&dispatch->dispatch); &dispatch->dispatch);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
goto cleanup; goto cleanup;

View File

@ -801,7 +801,6 @@ static void
setup_system(void) { setup_system(void) {
isc_result_t result; isc_result_t result;
isc_sockaddr_t bind_any, bind_any6; isc_sockaddr_t bind_any, bind_any6;
unsigned int attrs;
isc_sockaddrlist_t *nslist; isc_sockaddrlist_t *nslist;
isc_logconfig_t *logconfig = NULL; isc_logconfig_t *logconfig = NULL;
irs_resconf_t *resconf = NULL; irs_resconf_t *resconf = NULL;
@ -937,20 +936,16 @@ setup_system(void) {
set_source_ports(dispatchmgr); set_source_ports(dispatchmgr);
if (have_ipv6) { if (have_ipv6) {
attrs = (DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV6);
isc_sockaddr_any6(&bind_any6); isc_sockaddr_any6(&bind_any6);
result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
&bind_any6, 4, 2, 3, 5, attrs, &bind_any6, 0, &dispatchv6);
&dispatchv6);
check_result(result, "dns_dispatch_createudp (v6)"); check_result(result, "dns_dispatch_createudp (v6)");
} }
if (have_ipv4) { if (have_ipv4) {
attrs = (DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV4);
isc_sockaddr_any(&bind_any); isc_sockaddr_any(&bind_any);
result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
&bind_any, 4, 2, 3, 5, attrs, &bind_any, 0, &dispatchv4);
&dispatchv4);
check_result(result, "dns_dispatch_createudp (v4)"); check_result(result, "dns_dispatch_createudp (v4)");
} }

View File

@ -70,7 +70,7 @@ static void
recvresponse(isc_task_t *task, isc_event_t *event) { recvresponse(isc_task_t *task, isc_event_t *event) {
dns_requestevent_t *reqev = (dns_requestevent_t *)event; dns_requestevent_t *reqev = (dns_requestevent_t *)event;
isc_result_t result; isc_result_t result;
dns_message_t *query, *response; dns_message_t *query = NULL, *response = NULL;
isc_buffer_t outbuf; isc_buffer_t outbuf;
char output[1024]; char output[1024];
@ -86,7 +86,6 @@ recvresponse(isc_task_t *task, isc_event_t *event) {
query = reqev->ev_arg; query = reqev->ev_arg;
response = NULL;
dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
result = dns_request_getresponse(reqev->request, response, result = dns_request_getresponse(reqev->request, response,
@ -207,7 +206,6 @@ main(int argc, char *argv[]) {
isc_timermgr_t *timermgr = NULL; isc_timermgr_t *timermgr = NULL;
isc_socketmgr_t *socketmgr = NULL; isc_socketmgr_t *socketmgr = NULL;
dns_dispatchmgr_t *dispatchmgr = NULL; dns_dispatchmgr_t *dispatchmgr = NULL;
unsigned int attrs;
dns_dispatch_t *dispatchv4 = NULL; dns_dispatch_t *dispatchv4 = NULL;
dns_view_t *view = NULL; dns_view_t *view = NULL;
uint16_t port = PORT; uint16_t port = PORT;
@ -275,10 +273,9 @@ main(int argc, char *argv[]) {
RUNCHECK(isc_task_create(taskmgr, 0, &task)); RUNCHECK(isc_task_create(taskmgr, 0, &task));
RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV4;
RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
have_src ? &srcaddr : &bind_any, 4, 2, have_src ? &srcaddr : &bind_any, 0,
3, 5, attrs, &dispatchv4)); &dispatchv4));
RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
dispatchmgr, dispatchv4, NULL, dispatchmgr, dispatchv4, NULL,
&requestmgr)); &requestmgr));

View File

@ -56,20 +56,20 @@
static char *ip_address = NULL; static char *ip_address = NULL;
static int port = 0; static int port = 0;
static dst_key_t *ourkey; static dst_key_t *ourkey = NULL;
static isc_mem_t *mctx; static isc_mem_t *mctx = NULL;
static dns_tsigkey_t *tsigkey, *initialkey; static dns_tsigkey_t *tsigkey = NULL, *initialkey = NULL;
static dns_tsig_keyring_t *ring; static dns_tsig_keyring_t *ring = NULL;
static unsigned char noncedata[16]; static unsigned char noncedata[16];
static isc_buffer_t nonce; static isc_buffer_t nonce;
static dns_requestmgr_t *requestmgr; static dns_requestmgr_t *requestmgr = NULL;
static const char *ownername_str = "."; static const char *ownername_str = ".";
static void static void
recvquery(isc_task_t *task, isc_event_t *event) { recvquery(isc_task_t *task, isc_event_t *event) {
dns_requestevent_t *reqev = (dns_requestevent_t *)event; dns_requestevent_t *reqev = (dns_requestevent_t *)event;
isc_result_t result; isc_result_t result;
dns_message_t *query, *response; dns_message_t *query = NULL, *response = NULL;
char keyname[256]; char keyname[256];
isc_buffer_t keynamebuf; isc_buffer_t keynamebuf;
int type; int type;
@ -134,8 +134,8 @@ sendquery(isc_task_t *task, isc_event_t *event) {
dns_fixedname_t ownername; dns_fixedname_t ownername;
isc_buffer_t namestr, keybuf; isc_buffer_t namestr, keybuf;
unsigned char keydata[9]; unsigned char keydata[9];
dns_message_t *query; dns_message_t *query = NULL;
dns_request_t *request; dns_request_t *request = NULL;
static char keystr[] = "0123456789ab"; static char keystr[] = "0123456789ab";
isc_event_free(&event); isc_event_free(&event);
@ -166,14 +166,12 @@ sendquery(isc_task_t *task, isc_event_t *event) {
isc_buffer_usedregion(&keybuf, &r); isc_buffer_usedregion(&keybuf, &r);
initialkey = NULL;
result = dns_tsigkey_create( result = dns_tsigkey_create(
dns_fixedname_name(&keyname), DNS_TSIG_HMACMD5_NAME, dns_fixedname_name(&keyname), DNS_TSIG_HMACMD5_NAME,
isc_buffer_base(&keybuf), isc_buffer_usedlength(&keybuf), false, isc_buffer_base(&keybuf), isc_buffer_usedlength(&keybuf), false,
NULL, 0, 0, mctx, ring, &initialkey); NULL, 0, 0, mctx, ring, &initialkey);
CHECK("dns_tsigkey_create", result); CHECK("dns_tsigkey_create", result);
query = NULL;
dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query); dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
result = dns_tkey_builddhquery(query, ourkey, result = dns_tkey_builddhquery(query, ourkey,
@ -181,7 +179,6 @@ sendquery(isc_task_t *task, isc_event_t *event) {
DNS_TSIG_HMACMD5_NAME, &nonce, 3600); DNS_TSIG_HMACMD5_NAME, &nonce, 3600);
CHECK("dns_tkey_builddhquery", result); CHECK("dns_tkey_builddhquery", result);
request = NULL;
result = dns_request_create(requestmgr, query, &address, result = dns_request_create(requestmgr, query, &address,
DNS_REQUESTOPT_TCP, initialkey, TIMEOUT, DNS_REQUESTOPT_TCP, initialkey, TIMEOUT,
task, recvquery, query, &request); task, recvquery, query, &request);
@ -196,7 +193,6 @@ main(int argc, char *argv[]) {
isc_timermgr_t *timermgr = NULL; isc_timermgr_t *timermgr = NULL;
isc_socketmgr_t *socketmgr = NULL; isc_socketmgr_t *socketmgr = NULL;
isc_socket_t *sock = NULL; isc_socket_t *sock = NULL;
unsigned int attrs;
isc_sockaddr_t bind_any; isc_sockaddr_t bind_any;
dns_dispatchmgr_t *dispatchmgr = NULL; dns_dispatchmgr_t *dispatchmgr = NULL;
dns_dispatch_t *dispatchv4 = NULL; dns_dispatch_t *dispatchv4 = NULL;
@ -224,12 +220,9 @@ main(int argc, char *argv[]) {
dns_result_register(); dns_result_register();
mctx = NULL;
isc_mem_debugging = ISC_MEM_DEBUGRECORD; isc_mem_debugging = ISC_MEM_DEBUGRECORD;
isc_mem_create(&mctx); isc_mem_create(&mctx);
log = NULL;
logconfig = NULL;
isc_log_create(mctx, &log, &logconfig); isc_log_create(mctx, &log, &logconfig);
RUNCHECK(dst_lib_init(mctx, NULL)); RUNCHECK(dst_lib_init(mctx, NULL));
@ -241,32 +234,24 @@ main(int argc, char *argv[]) {
RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
isc_sockaddr_any(&bind_any); isc_sockaddr_any(&bind_any);
attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV4;
RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
&bind_any, 4, 2, 3, 5, attrs, &bind_any, 0, &dispatchv4));
&dispatchv4));
requestmgr = NULL;
RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
dispatchmgr, dispatchv4, NULL, dispatchmgr, dispatchv4, NULL,
&requestmgr)); &requestmgr));
ring = NULL;
RUNCHECK(dns_tsigkeyring_create(mctx, &ring)); RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
tctx = NULL;
RUNCHECK(dns_tkeyctx_create(mctx, &tctx)); RUNCHECK(dns_tkeyctx_create(mctx, &tctx));
view = NULL;
RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
dns_view_setkeyring(view, ring); dns_view_setkeyring(view, ring);
dns_tsigkeyring_detach(&ring); dns_tsigkeyring_detach(&ring);
sock = NULL;
RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
&sock)); &sock));
RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL)); RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL));
ourkey = NULL;
type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY; type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY;
result = dst_key_fromnamedfile(ourkeyname, NULL, type, mctx, &ourkey); result = dst_key_fromnamedfile(ourkeyname, NULL, type, mctx, &ourkey);
CHECK("dst_key_fromnamedfile", result); CHECK("dst_key_fromnamedfile", result);

View File

@ -53,18 +53,18 @@
#define TIMEOUT 30 #define TIMEOUT 30
static char *ip_address; static char *ip_address = NULL;
static int port; static int port;
static isc_mem_t *mctx; static isc_mem_t *mctx = NULL;
static dns_tsigkey_t *tsigkey; static dns_tsigkey_t *tsigkey = NULL;
static dns_tsig_keyring_t *ring; static dns_tsig_keyring_t *ring = NULL;
static dns_requestmgr_t *requestmgr; static dns_requestmgr_t *requestmgr = NULL;
static void static void
recvquery(isc_task_t *task, isc_event_t *event) { recvquery(isc_task_t *task, isc_event_t *event) {
dns_requestevent_t *reqev = (dns_requestevent_t *)event; dns_requestevent_t *reqev = (dns_requestevent_t *)event;
isc_result_t result; isc_result_t result;
dns_message_t *query, *response; dns_message_t *query = NULL, *response = NULL;
UNUSED(task); UNUSED(task);
@ -78,7 +78,6 @@ recvquery(isc_task_t *task, isc_event_t *event) {
query = reqev->ev_arg; query = reqev->ev_arg;
response = NULL;
dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
result = dns_request_getresponse(reqev->request, response, result = dns_request_getresponse(reqev->request, response,
@ -108,8 +107,8 @@ sendquery(isc_task_t *task, isc_event_t *event) {
struct in_addr inaddr; struct in_addr inaddr;
isc_sockaddr_t address; isc_sockaddr_t address;
isc_result_t result; isc_result_t result;
dns_message_t *query; dns_message_t *query = NULL;
dns_request_t *request; dns_request_t *request = NULL;
isc_event_free(&event); isc_event_free(&event);
@ -119,13 +118,11 @@ sendquery(isc_task_t *task, isc_event_t *event) {
} }
isc_sockaddr_fromin(&address, &inaddr, port); isc_sockaddr_fromin(&address, &inaddr, port);
query = NULL;
dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query); dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
result = dns_tkey_builddeletequery(query, tsigkey); result = dns_tkey_builddeletequery(query, tsigkey);
CHECK("dns_tkey_builddeletequery", result); CHECK("dns_tkey_builddeletequery", result);
request = NULL;
result = dns_request_create(requestmgr, query, &address, result = dns_request_create(requestmgr, query, &address,
DNS_REQUESTOPT_TCP, tsigkey, TIMEOUT, task, DNS_REQUESTOPT_TCP, tsigkey, TIMEOUT, task,
recvquery, query, &request); recvquery, query, &request);
@ -140,7 +137,6 @@ main(int argc, char **argv) {
isc_timermgr_t *timermgr = NULL; isc_timermgr_t *timermgr = NULL;
isc_socketmgr_t *socketmgr = NULL; isc_socketmgr_t *socketmgr = NULL;
isc_socket_t *sock = NULL; isc_socket_t *sock = NULL;
unsigned int attrs;
isc_sockaddr_t bind_any; isc_sockaddr_t bind_any;
dns_dispatchmgr_t *dispatchmgr = NULL; dns_dispatchmgr_t *dispatchmgr = NULL;
dns_dispatch_t *dispatchv4 = NULL; dns_dispatch_t *dispatchv4 = NULL;
@ -169,11 +165,8 @@ main(int argc, char **argv) {
dns_result_register(); dns_result_register();
mctx = NULL;
isc_mem_create(&mctx); isc_mem_create(&mctx);
log = NULL;
logconfig = NULL;
isc_log_create(mctx, &log, &logconfig); isc_log_create(mctx, &log, &logconfig);
RUNCHECK(dst_lib_init(mctx, NULL)); RUNCHECK(dst_lib_init(mctx, NULL));
@ -184,31 +177,23 @@ main(int argc, char **argv) {
RUNCHECK(isc_task_create(taskmgr, 0, &task)); RUNCHECK(isc_task_create(taskmgr, 0, &task));
RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
isc_sockaddr_any(&bind_any); isc_sockaddr_any(&bind_any);
attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV4;
RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
&bind_any, 4, 2, 3, 5, attrs, &bind_any, 0, &dispatchv4));
&dispatchv4));
requestmgr = NULL;
RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
dispatchmgr, dispatchv4, NULL, dispatchmgr, dispatchv4, NULL,
&requestmgr)); &requestmgr));
ring = NULL;
RUNCHECK(dns_tsigkeyring_create(mctx, &ring)); RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
tctx = NULL;
RUNCHECK(dns_tkeyctx_create(mctx, &tctx)); RUNCHECK(dns_tkeyctx_create(mctx, &tctx));
view = NULL;
RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
dns_view_setkeyring(view, ring); dns_view_setkeyring(view, ring);
sock = NULL;
RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
&sock)); &sock));
RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL)); RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL));
dstkey = NULL;
type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY; type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY;
result = dst_key_fromnamedfile(keyname, NULL, type, mctx, &dstkey); result = dst_key_fromnamedfile(keyname, NULL, type, mctx, &dstkey);
CHECK("dst_key_fromnamedfile", result); CHECK("dst_key_fromnamedfile", result);

View File

@ -2073,7 +2073,7 @@ main(int argc, char *argv[]) {
dns_dispatchmgr_t *dispatchmgr = NULL; dns_dispatchmgr_t *dispatchmgr = NULL;
dns_dispatch_t *dispatchvx = NULL; dns_dispatch_t *dispatchvx = NULL;
dns_view_t *view = NULL; dns_view_t *view = NULL;
unsigned int attrs, i; unsigned int i;
int ns; int ns;
RUNCHECK(isc_app_start()); RUNCHECK(isc_app_start());
@ -2128,17 +2128,14 @@ main(int argc, char *argv[]) {
RUNCHECK(isc_task_create(taskmgr, 0, &task)); RUNCHECK(isc_task_create(taskmgr, 0, &task));
RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
attrs = DNS_DISPATCHATTR_UDP;
if (have_ipv4) { if (have_ipv4) {
isc_sockaddr_any(&bind_any); isc_sockaddr_any(&bind_any);
attrs |= DNS_DISPATCHATTR_IPV4;
} else { } else {
isc_sockaddr_any6(&bind_any); isc_sockaddr_any6(&bind_any);
attrs |= DNS_DISPATCHATTR_IPV6;
} }
RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
have_src ? &srcaddr : &bind_any, 100, have_src ? &srcaddr : &bind_any, 0,
100, 17, 19, attrs, &dispatchvx)); &dispatchvx));
RUNCHECK(dns_requestmgr_create( RUNCHECK(dns_requestmgr_create(
mctx, timermgr, socketmgr, taskmgr, dispatchmgr, mctx, timermgr, socketmgr, taskmgr, dispatchmgr,

View File

@ -203,40 +203,18 @@ cleanup:
static isc_result_t static isc_result_t
getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr,
isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr, isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr,
bool is_shared, dns_dispatch_t **dispp, dns_dispatch_t **dispp, const isc_sockaddr_t *localaddr) {
const isc_sockaddr_t *localaddr) {
unsigned int attrs;
dns_dispatch_t *disp = NULL; dns_dispatch_t *disp = NULL;
unsigned maxbuffers, maxrequests, buckets, increment;
isc_result_t result; isc_result_t result;
isc_sockaddr_t anyaddr; isc_sockaddr_t anyaddr;
attrs = DNS_DISPATCHATTR_UDP;
switch (family) {
case AF_INET:
attrs |= DNS_DISPATCHATTR_IPV4;
break;
case AF_INET6:
attrs |= DNS_DISPATCHATTR_IPV6;
break;
default:
INSIST(0);
ISC_UNREACHABLE();
}
if (localaddr == NULL) { if (localaddr == NULL) {
isc_sockaddr_anyofpf(&anyaddr, family); isc_sockaddr_anyofpf(&anyaddr, family);
localaddr = &anyaddr; localaddr = &anyaddr;
} }
maxbuffers = is_shared ? 1000 : 8;
maxrequests = 32768;
buckets = is_shared ? 16411 : 3;
increment = is_shared ? 16433 : 5;
result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
localaddr, maxbuffers, maxrequests, localaddr, 0, &disp);
buckets, increment, attrs, &disp);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
*dispp = disp; *dispp = disp;
} }
@ -334,7 +312,7 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
client->dispatchv4 = NULL; client->dispatchv4 = NULL;
if (localaddr4 != NULL || localaddr6 == NULL) { if (localaddr4 != NULL || localaddr6 == NULL) {
result = getudpdispatch(AF_INET, dispatchmgr, socketmgr, result = getudpdispatch(AF_INET, dispatchmgr, socketmgr,
taskmgr, true, &dispatchv4, localaddr4); taskmgr, &dispatchv4, localaddr4);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
client->dispatchv4 = dispatchv4; client->dispatchv4 = dispatchv4;
} }
@ -343,7 +321,7 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
client->dispatchv6 = NULL; client->dispatchv6 = NULL;
if (localaddr6 != NULL || localaddr4 == NULL) { if (localaddr6 != NULL || localaddr4 == NULL) {
result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr, result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr,
taskmgr, true, &dispatchv6, localaddr6); taskmgr, &dispatchv6, localaddr6);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
client->dispatchv6 = dispatchv6; client->dispatchv6 = dispatchv6;
} }

View File

@ -43,9 +43,6 @@ typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
typedef struct dispsocket dispsocket_t; typedef struct dispsocket dispsocket_t;
typedef ISC_LIST(dispsocket_t) dispsocketlist_t; typedef ISC_LIST(dispsocket_t) dispsocketlist_t;
typedef struct dispportentry dispportentry_t;
typedef ISC_LIST(dispportentry_t) dispportlist_t;
typedef struct dns_qid { typedef struct dns_qid {
unsigned int magic; unsigned int magic;
unsigned int qid_nbuckets; /*%< hash table size */ unsigned int qid_nbuckets; /*%< hash table size */
@ -72,7 +69,6 @@ struct dns_dispatchmgr {
isc_mutex_t buffer_lock; isc_mutex_t buffer_lock;
unsigned int buffers; /*%< allocated buffers */ unsigned int buffers; /*%< allocated buffers */
unsigned int buffersize; /*%< size of each buffer */ unsigned int buffersize; /*%< size of each buffer */
unsigned int maxbuffers; /*%< max buffers */
isc_refcount_t irefs; isc_refcount_t irefs;
@ -101,8 +97,6 @@ struct dns_dispatchmgr {
#define MGR_SHUTTINGDOWN 0x00000001U #define MGR_SHUTTINGDOWN 0x00000001U
#define MGR_IS_SHUTTINGDOWN(l) (((l)->state & MGR_SHUTTINGDOWN) != 0) #define MGR_IS_SHUTTINGDOWN(l) (((l)->state & MGR_SHUTTINGDOWN) != 0)
#define IS_PRIVATE(d) (((d)->attributes & DNS_DISPATCHATTR_PRIVATE) != 0)
struct dns_dispentry { struct dns_dispentry {
unsigned int magic; unsigned int magic;
dns_dispatch_t *disp; dns_dispatch_t *disp;
@ -119,27 +113,6 @@ struct dns_dispentry {
ISC_LINK(dns_dispentry_t) link; ISC_LINK(dns_dispentry_t) link;
}; };
/*%
* Maximum number of dispatch sockets that can be pooled for reuse. The
* appropriate value may vary, but experiments have shown a busy caching server
* may need more than 1000 sockets concurrently opened. The maximum allowable
* number of dispatch sockets (per manager) will be set to the double of this
* value.
*/
#ifndef DNS_DISPATCH_POOLSOCKS
#define DNS_DISPATCH_POOLSOCKS 2048
#endif /* ifndef DNS_DISPATCH_POOLSOCKS */
/*%
* Quota to control the number of dispatch sockets. If a dispatch has more
* than the quota of sockets, new queries will purge oldest ones, so that
* a massive number of outstanding queries won't prevent subsequent queries
* (especially if the older ones take longer time and result in timeout).
*/
#ifndef DNS_DISPATCH_SOCKSQUOTA
#define DNS_DISPATCH_SOCKSQUOTA 3072
#endif /* ifndef DNS_DISPATCH_SOCKSQUOTA */
/*% /*%
* Fixed UDP buffer size. * Fixed UDP buffer size.
*/ */
@ -152,31 +125,14 @@ struct dispsocket {
isc_socket_t *socket; isc_socket_t *socket;
dns_dispatch_t *disp; dns_dispatch_t *disp;
isc_sockaddr_t host; isc_sockaddr_t host;
dispportentry_t *portentry;
dns_dispentry_t *resp; dns_dispentry_t *resp;
isc_task_t *task; isc_task_t *task;
in_port_t port;
ISC_LINK(dispsocket_t) link; ISC_LINK(dispsocket_t) link;
unsigned int bucket; unsigned int bucket;
ISC_LINK(dispsocket_t) blink; ISC_LINK(dispsocket_t) blink;
}; };
/*%
* A port table entry. We remember every port we first open in a table with a
* reference counter so that we can 'reuse' the same port (with different
* destination addresses) using the SO_REUSEADDR socket option.
*/
struct dispportentry {
in_port_t port;
isc_refcount_t refs;
ISC_LINK(struct dispportentry) link;
};
#ifndef DNS_DISPATCH_PORTTABLESIZE
#define DNS_DISPATCH_PORTTABLESIZE 1024
#endif /* ifndef DNS_DISPATCH_PORTTABLESIZE */
#define INVALID_BUCKET (0xffffdead)
/*% /*%
* Number of tasks for each dispatch that use separate sockets for different * Number of tasks for each dispatch that use separate sockets for different
* transactions. This must be a power of 2 as it will divide 32 bit numbers * transactions. This must be a power of 2 as it will divide 32 bit numbers
@ -195,11 +151,10 @@ struct dns_dispatch {
* 1st task (task[0]) for internal control events. * 1st task (task[0]) for internal control events.
*/ */
isc_task_t *task[MAX_INTERNAL_TASKS]; isc_task_t *task[MAX_INTERNAL_TASKS];
isc_socket_t *socket; /*%< isc socket attached to */ isc_socket_t *socket; /*%< isc socket attached to */
isc_sockaddr_t local; /*%< local address */ isc_sockaddr_t local; /*%< local address */
in_port_t localport; /*%< local UDP port */ in_port_t localport; /*%< local UDP port */
isc_sockaddr_t peer; /*%< peer address (TCP) */ isc_sockaddr_t peer; /*%< peer address (TCP) */
unsigned int maxrequests; /*%< max requests */
isc_event_t *ctlevent; isc_event_t *ctlevent;
isc_mem_t *sepool; /*%< pool for socket events */ isc_mem_t *sepool; /*%< pool for socket events */
@ -214,8 +169,7 @@ struct dns_dispatch {
isc_refcount_t refcount; isc_refcount_t refcount;
dns_dispatchevent_t *failsafe_ev; /*%< failsafe cancel event */ dns_dispatchevent_t *failsafe_ev; /*%< failsafe cancel event */
unsigned int shutting_down : 1, shutdown_out : 1, connected : 1, unsigned int shutting_down : 1, shutdown_out : 1, connected : 1,
tcpmsg_valid : 1, recv_pending : 1; /*%< is a recv() pending? * tcpmsg_valid : 1, recv_pending : 1;
*/
isc_result_t shutdown_why; isc_result_t shutdown_why;
ISC_LIST(dispsocket_t) activesockets; ISC_LIST(dispsocket_t) activesockets;
ISC_LIST(dispsocket_t) inactivesockets; ISC_LIST(dispsocket_t) inactivesockets;
@ -223,8 +177,6 @@ struct dns_dispatch {
unsigned int requests; /*%< how many requests we have */ unsigned int requests; /*%< how many requests we have */
unsigned int tcpbuffers; /*%< allocated buffers */ unsigned int tcpbuffers; /*%< allocated buffers */
dns_tcpmsg_t tcpmsg; /*%< for tcp streams */ dns_tcpmsg_t tcpmsg; /*%< for tcp streams */
dns_qid_t *qid;
dispportlist_t *port_table; /*%< hold ports 'owned' by us */
}; };
#define QID_MAGIC ISC_MAGIC('Q', 'i', 'd', ' ') #define QID_MAGIC ISC_MAGIC('Q', 'i', 'd', ' ')
@ -242,23 +194,65 @@ struct dns_dispatch {
#define DNS_DISPATCHMGR_MAGIC ISC_MAGIC('D', 'M', 'g', 'r') #define DNS_DISPATCHMGR_MAGIC ISC_MAGIC('D', 'M', 'g', 'r')
#define VALID_DISPATCHMGR(e) ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC) #define VALID_DISPATCHMGR(e) ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC)
#define DNS_QID(disp) \ /*%
((disp)->socktype == isc_sockettype_tcp) ? (disp)->qid \ * Maximum number of dispatch sockets that can be pooled for reuse. The
: (disp)->mgr->qid * appropriate value may vary, but experiments have shown a busy caching server
* may need more than 1000 sockets concurrently opened. The maximum allowable
* number of dispatch sockets (per manager) will be set to the double of this
* value.
*/
#ifndef DNS_DISPATCH_POOLSOCKS
#define DNS_DISPATCH_POOLSOCKS 2048
#endif /* ifndef DNS_DISPATCH_POOLSOCKS */
/*% /*%
* Locking a query port buffer is a bit tricky. We access the buffer without * Quota to control the number of UDP dispatch sockets. If a dispatch has
* locking until qid is created. Technically, there is a possibility of race * more than the quota of sockets, new queries will purge oldest ones, so
* between the creation of qid and access to the port buffer; in practice, * that a massive number of outstanding queries won't prevent subsequent
* however, this should be safe because qid isn't created until the first * queries (especially if the older ones take longer time and result in
* dispatch is created and there should be no contending situation until then. * timeout).
*/ */
#define PORTBUFLOCK(mgr) \ #ifndef DNS_DISPATCH_SOCKSQUOTA
if ((mgr)->qid != NULL) \ #define DNS_DISPATCH_SOCKSQUOTA 3072
LOCK(&((mgr)->qid->lock)) #endif /* ifndef DNS_DISPATCH_SOCKSQUOTA */
#define PORTBUFUNLOCK(mgr) \
if ((mgr)->qid != NULL) \ /*%
UNLOCK((&(mgr)->qid->lock)) * Number of buffers available for all dispatches in the buffery memory
* pool.
*/
#ifndef DNS_DISPATCH_MAXBUFFERS
#define DNS_DISPATCH_MAXBUFFERS 32768
#endif /* ifndef DNS_DISPATCH_MAXBUFFERS */
/*%
* Number of dispatch sockets available for all dispatches in the
* socket memory pool.
*/
#ifndef DNS_DISPATCH_MAXSOCKETS
#define DNS_DISPATCH_MAXSOCKETS 32768
#endif /* ifndef DNS_DISPATCH_MAXSOCKETS */
/*%
* Quota to control the number of concurrent requests that can be handled
* by each TCP dispatch. (UDP dispatches do not currently support socket
* sharing.)
*/
#ifndef DNS_DISPATCH_MAXREQUESTS
#define DNS_DISPATCH_MAXREQUESTS 32768
#endif /* ifndef DNS_DISPATCH_MAXREQUESTS */
/*%
* Number of buckets in the QID hash table, and the value to
* increment the QID by when attempting to avoid collisions.
* The number of buckets should be prime, and the increment
* should be the next higher prime number.
*/
#ifndef DNS_QID_BUCKETS
#define DNS_QID_BUCKETS 16411
#endif /* ifndef DNS_QID_BUCKETS */
#ifndef DNS_QID_INCREMENT
#define DNS_QID_INCREMENT 16433
#endif /* ifndef DNS_QID_INCREMENT */
/* /*
* Statics. * Statics.
@ -301,21 +295,18 @@ dispatch_free(dns_dispatch_t **dispp);
static isc_result_t static isc_result_t
dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
unsigned int maxrequests, unsigned int attributes, unsigned int attributes, dns_dispatch_t **dispp);
dns_dispatch_t **dispp);
static bool static bool
destroy_mgr_ok(dns_dispatchmgr_t *mgr); destroy_mgr_ok(dns_dispatchmgr_t *mgr);
static void static void
destroy_mgr(dns_dispatchmgr_t **mgrp); destroy_mgr(dns_dispatchmgr_t **mgrp);
static isc_result_t static void
qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets, qid_allocate(dns_dispatchmgr_t *mgr, dns_qid_t **qidp);
unsigned int increment, dns_qid_t **qidp, bool needaddrtable);
static void static void
qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp); qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
static isc_result_t static isc_result_t
open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local, open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
unsigned int options, isc_socket_t **sockp, unsigned int options, isc_socket_t **sockp);
isc_socket_t *dup_socket);
#define LVL(x) ISC_LOG_DEBUG(x) #define LVL(x) ISC_LOG_DEBUG(x)
@ -433,9 +424,7 @@ dns_hash(dns_qid_t *qid, const isc_sockaddr_t *dest, dns_messageid_t id,
static dns_dispentry_t * static dns_dispentry_t *
linear_first(dns_qid_t *qid) { linear_first(dns_qid_t *qid) {
dns_dispentry_t *ret = NULL; dns_dispentry_t *ret = NULL;
unsigned int bucket; unsigned int bucket = 0;
bucket = 0;
while (bucket < qid->qid_nbuckets) { while (bucket < qid->qid_nbuckets) {
ret = ISC_LIST_HEAD(qid->qid_table[bucket]); ret = ISC_LIST_HEAD(qid->qid_table[bucket]);
@ -462,8 +451,7 @@ linear_next(dns_qid_t *qid, dns_dispentry_t *resp) {
return (ret); return (ret);
} }
bucket = resp->bucket; bucket = resp->bucket + 1;
bucket++;
while (bucket < qid->qid_nbuckets) { while (bucket < qid->qid_nbuckets) {
ret = ISC_LIST_HEAD(qid->qid_table[bucket]); ret = ISC_LIST_HEAD(qid->qid_table[bucket]);
if (ret != NULL) { if (ret != NULL) {
@ -551,67 +539,6 @@ destroy_disp(isc_task_t *task, isc_event_t *event) {
} }
} }
/*%
* Manipulate port table per dispatch: find an entry for a given port number,
* create a new entry, and decrement a given entry with possible clean-up.
*/
static dispportentry_t *
port_search(dns_dispatch_t *disp, in_port_t port) {
dispportentry_t *portentry = NULL;
REQUIRE(disp->port_table != NULL);
portentry = ISC_LIST_HEAD(
disp->port_table[port % DNS_DISPATCH_PORTTABLESIZE]);
while (portentry != NULL) {
if (portentry->port == port) {
return (portentry);
}
portentry = ISC_LIST_NEXT(portentry, link);
}
return (NULL);
}
static dispportentry_t *
new_portentry(dns_dispatch_t *disp, in_port_t port) {
dispportentry_t *portentry = NULL;
dns_qid_t *qid = NULL;
REQUIRE(disp->port_table != NULL);
portentry = isc_mem_get(disp->mgr->mctx, sizeof(*portentry));
portentry->port = port;
isc_refcount_init(&portentry->refs, 1);
ISC_LINK_INIT(portentry, link);
qid = DNS_QID(disp);
LOCK(&qid->lock);
ISC_LIST_APPEND(disp->port_table[port % DNS_DISPATCH_PORTTABLESIZE],
portentry, link);
UNLOCK(&qid->lock);
return (portentry);
}
/*%
* The caller must hold the qid->lock.
*/
static void
deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
dispportentry_t *portentry = *portentryp;
*portentryp = NULL;
REQUIRE(disp->port_table != NULL);
REQUIRE(portentry != NULL);
if (isc_refcount_decrement(&portentry->refs) == 1) {
ISC_LIST_UNLINK(disp->port_table[portentry->port %
DNS_DISPATCH_PORTTABLESIZE],
portentry, link);
isc_mem_put(disp->mgr->mctx, portentry, sizeof(*portentry));
}
}
/*% /*%
* Find a dispsocket for socket address 'dest', and port number 'port'. * Find a dispsocket for socket address 'dest', and port number 'port'.
* Return NULL if no such entry exists. Requires qid->lock to be held. * Return NULL if no such entry exists. Requires qid->lock to be held.
@ -627,10 +554,8 @@ socket_search(dns_qid_t *qid, const isc_sockaddr_t *dest, in_port_t port,
dispsock = ISC_LIST_HEAD(qid->sock_table[bucket]); dispsock = ISC_LIST_HEAD(qid->sock_table[bucket]);
while (dispsock != NULL) { while (dispsock != NULL) {
if (dispsock->portentry != NULL && if (dispsock->port == port &&
dispsock->portentry->port == port && isc_sockaddr_equal(dest, &dispsock->host)) {
isc_sockaddr_equal(dest, &dispsock->host))
{
return (dispsock); return (dispsock);
} }
dispsock = ISC_LIST_NEXT(dispsock, blink); dispsock = ISC_LIST_NEXT(dispsock, blink);
@ -649,6 +574,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
in_port_t *portp) { in_port_t *portp) {
int i; int i;
dns_dispatchmgr_t *mgr = disp->mgr; dns_dispatchmgr_t *mgr = disp->mgr;
dns_qid_t *qid = mgr->qid;
isc_socket_t *sock = NULL; isc_socket_t *sock = NULL;
isc_result_t result = ISC_R_FAILURE; isc_result_t result = ISC_R_FAILURE;
in_port_t port; in_port_t port;
@ -657,9 +583,6 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
dispsocket_t *dispsock = NULL; dispsocket_t *dispsock = NULL;
unsigned int nports; unsigned int nports;
in_port_t *ports = NULL; in_port_t *ports = NULL;
isc_socket_options_t bindoptions;
dispportentry_t *portentry = NULL;
dns_qid_t *qid = NULL;
if (isc_sockaddr_pf(&disp->local) == AF_INET) { if (isc_sockaddr_pf(&disp->local) == AF_INET) {
nports = mgr->nv4ports; nports = mgr->nv4ports;
@ -696,7 +619,6 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
* very likely to fail in bind(2) or connect(2). * very likely to fail in bind(2) or connect(2).
*/ */
localaddr = disp->local; localaddr = disp->local;
qid = DNS_QID(disp);
for (i = 0; i < 64; i++) { for (i = 0; i < 64; i++) {
port = ports[isc_random_uniform(nports)]; port = ports[isc_random_uniform(nports)];
@ -709,20 +631,9 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
continue; continue;
} }
UNLOCK(&qid->lock); UNLOCK(&qid->lock);
bindoptions = 0; result = open_socket(sockmgr, &localaddr,
portentry = port_search(disp, port); ISC_SOCKET_REUSEADDRESS, &sock);
if (portentry != NULL) {
bindoptions |= ISC_SOCKET_REUSEADDRESS;
}
result = open_socket(sockmgr, &localaddr, bindoptions, &sock,
NULL);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
if (portentry == NULL) {
portentry = new_portentry(disp, port);
} else {
isc_refcount_increment(&portentry->refs);
}
break; break;
} else if (result == ISC_R_NOPERM) { } else if (result == ISC_R_NOPERM) {
char buf[ISC_SOCKADDR_FORMATSIZE]; char buf[ISC_SOCKADDR_FORMATSIZE];
@ -746,8 +657,9 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
dispsock->socket = sock; dispsock->socket = sock;
dispsock->host = *dest; dispsock->host = *dest;
dispsock->bucket = bucket; dispsock->bucket = bucket;
dispsock->port = port;
LOCK(&qid->lock); LOCK(&qid->lock);
dispsock->portentry = portentry;
ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink); ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink);
UNLOCK(&qid->lock); UNLOCK(&qid->lock);
*dispsockp = dispsock; *dispsockp = dispsock;
@ -762,7 +674,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
static void static void
destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) { destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
dispsocket_t *dispsock = NULL; dispsocket_t *dispsock = NULL;
dns_qid_t *qid = DNS_QID(disp); dns_qid_t *qid = disp->mgr->qid;
/* /*
* The dispatch must be locked. * The dispatch must be locked.
@ -775,11 +687,6 @@ destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
disp->nsockets--; disp->nsockets--;
dispsock->magic = 0; dispsock->magic = 0;
if (dispsock->portentry != NULL) {
LOCK(&qid->lock);
deref_portentry(disp, &dispsock->portentry);
UNLOCK(&qid->lock);
}
if (dispsock->socket != NULL) { if (dispsock->socket != NULL) {
isc_socket_detach(&dispsock->socket); isc_socket_detach(&dispsock->socket);
} }
@ -802,7 +709,7 @@ destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
static void static void
deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) {
isc_result_t result; isc_result_t result;
dns_qid_t *qid = DNS_QID(disp); dns_qid_t *qid = disp->mgr->qid;
/* /*
* The dispatch must be locked. * The dispatch must be locked.
@ -813,12 +720,6 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) {
dispsock->resp->dispsocket = NULL; dispsock->resp->dispsocket = NULL;
} }
INSIST(dispsock->portentry != NULL);
LOCK(&qid->lock);
deref_portentry(disp, &dispsock->portentry);
UNLOCK(&qid->lock);
if (disp->nsockets > DNS_DISPATCH_POOLSOCKS) { if (disp->nsockets > DNS_DISPATCH_POOLSOCKS) {
destroy_dispsocket(disp, &dispsock); destroy_dispsocket(disp, &dispsock);
} else { } else {
@ -896,7 +797,7 @@ free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {
static void * static void *
allocate_udp_buffer(dns_dispatch_t *disp) { allocate_udp_buffer(dns_dispatch_t *disp) {
LOCK(&disp->mgr->buffer_lock); LOCK(&disp->mgr->buffer_lock);
if (disp->mgr->buffers >= disp->mgr->maxbuffers) { if (disp->mgr->buffers >= DNS_DISPATCH_MAXBUFFERS) {
UNLOCK(&disp->mgr->buffer_lock); UNLOCK(&disp->mgr->buffer_lock);
return (NULL); return (NULL);
} }
@ -1238,7 +1139,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
REQUIRE(VALID_DISPATCH(disp)); REQUIRE(VALID_DISPATCH(disp));
qid = disp->qid; qid = disp->mgr->qid;
LOCK(&disp->lock); LOCK(&disp->lock);
@ -1512,8 +1413,7 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
static isc_result_t static isc_result_t
open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local, open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
unsigned int options, isc_socket_t **sockp, unsigned int options, isc_socket_t **sockp) {
isc_socket_t *dup_socket) {
isc_socket_t *sock = NULL; isc_socket_t *sock = NULL;
isc_result_t result; isc_result_t result;
@ -1523,15 +1423,6 @@ open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
return (result); return (result);
} }
} else if (dup_socket != NULL && !isc_socket_hasreuseport()) {
result = isc_socket_dup(dup_socket, &sock);
if (result != ISC_R_SUCCESS) {
return (result);
}
isc_socket_setname(sock, "dispatcher", NULL);
*sockp = sock;
return (ISC_R_SUCCESS);
} else { } else {
result = isc_socket_create(mgr, isc_sockaddr_pf(local), result = isc_socket_create(mgr, isc_sockaddr_pf(local),
isc_sockettype_udp, &sock); isc_sockettype_udp, &sock);
@ -1601,7 +1492,6 @@ setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
} while (p++ < 65535); } while (p++ < 65535);
INSIST(i4 == nv4ports && i6 == nv6ports); INSIST(i4 == nv4ports && i6 == nv6ports);
PORTBUFLOCK(mgr);
if (mgr->v4ports != NULL) { if (mgr->v4ports != NULL) {
isc_mem_put(mgr->mctx, mgr->v4ports, isc_mem_put(mgr->mctx, mgr->v4ports,
mgr->nv4ports * sizeof(in_port_t)); mgr->nv4ports * sizeof(in_port_t));
@ -1615,7 +1505,6 @@ setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
} }
mgr->v6ports = v6ports; mgr->v6ports = v6ports;
mgr->nv6ports = nv6ports; mgr->nv6ports = nv6ports;
PORTBUFUNLOCK(mgr);
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
@ -1634,7 +1523,7 @@ dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp) {
REQUIRE(mgrp != NULL && *mgrp == NULL); REQUIRE(mgrp != NULL && *mgrp == NULL);
mgr = isc_mem_get(mctx, sizeof(dns_dispatchmgr_t)); mgr = isc_mem_get(mctx, sizeof(dns_dispatchmgr_t));
*mgr = (dns_dispatchmgr_t){ .maxbuffers = 20000 }; *mgr = (dns_dispatchmgr_t){ 0 };
isc_mem_attach(mctx, &mgr->mctx); isc_mem_attach(mctx, &mgr->mctx);
@ -1653,6 +1542,7 @@ dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp) {
isc_portset_destroy(mctx, &v4portset); isc_portset_destroy(mctx, &v4portset);
isc_portset_destroy(mctx, &v6portset); isc_portset_destroy(mctx, &v6portset);
qid_allocate(mgr, &mgr->qid);
mgr->magic = DNS_DISPATCHMGR_MAGIC; mgr->magic = DNS_DISPATCHMGR_MAGIC;
*mgrp = mgr; *mgrp = mgr;
@ -1681,60 +1571,6 @@ dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
return (setavailports(mgr, v4portset, v6portset)); return (setavailports(mgr, v4portset, v6portset));
} }
static isc_result_t
dispatchmgr_setudp(dns_dispatchmgr_t *mgr, unsigned int maxbuffers,
unsigned int maxrequests, unsigned int buckets,
unsigned int increment) {
isc_result_t result;
REQUIRE(VALID_DISPATCHMGR(mgr));
REQUIRE(maxbuffers > 0);
REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
REQUIRE(increment > buckets);
UNUSED(maxrequests);
/*
* Keep some number of items around. This should be a config
* option. For now, keep 8, but later keep at least two even
* if the caller wants less. This allows us to ensure certain
* things, like an event can be "freed" and the next allocation
* will always succeed.
*
* Note that if limits are placed on anything here, we use one
* event internally, so the actual limit should be "wanted + 1."
*
* XXXMLG
*/
if (maxbuffers < 8) {
maxbuffers = 8;
}
/* Adjust buffer pool if needed
*
* We only increase maxbuffers to avoid accidental buffer
* shortage. Ideally we'd separate the manager-wide maximum
* from per-dispatch limits and respect the latter within the
* global limit. But at this moment that's deemed to be
* overkilling and isn't worth additional implementation
* complexity.
*/
LOCK(&mgr->buffer_lock);
if (maxbuffers > mgr->maxbuffers) {
mgr->maxbuffers = maxbuffers;
}
UNLOCK(&mgr->buffer_lock);
if (mgr->qid == NULL) {
result = qid_allocate(mgr, buckets, increment, &mgr->qid, true);
if (result != ISC_R_SUCCESS) {
return (result);
}
}
return (ISC_R_SUCCESS);
}
void void
dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) { dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) {
dns_dispatchmgr_t *mgr = NULL; dns_dispatchmgr_t *mgr = NULL;
@ -1767,42 +1603,31 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats) {
isc_stats_attach(stats, &mgr->stats); isc_stats_attach(stats, &mgr->stats);
} }
static isc_result_t static void
qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets, qid_allocate(dns_dispatchmgr_t *mgr, dns_qid_t **qidp) {
unsigned int increment, dns_qid_t **qidp, bool needsocktable) {
dns_qid_t *qid = NULL; dns_qid_t *qid = NULL;
unsigned int i; unsigned int i;
REQUIRE(VALID_DISPATCHMGR(mgr));
REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
REQUIRE(increment > buckets);
REQUIRE(qidp != NULL && *qidp == NULL); REQUIRE(qidp != NULL && *qidp == NULL);
qid = isc_mem_get(mgr->mctx, sizeof(*qid)); qid = isc_mem_get(mgr->mctx, sizeof(*qid));
*qid = (dns_qid_t){ .qid_nbuckets = DNS_QID_BUCKETS,
.qid_increment = DNS_QID_INCREMENT };
qid->qid_table = isc_mem_get(mgr->mctx, qid->qid_table = isc_mem_get(mgr->mctx,
buckets * sizeof(dns_displist_t)); DNS_QID_BUCKETS * sizeof(dns_displist_t));
qid->sock_table = isc_mem_get(
qid->sock_table = NULL; mgr->mctx, DNS_QID_BUCKETS * sizeof(dispsocketlist_t));
if (needsocktable) {
qid->sock_table = isc_mem_get(
mgr->mctx, buckets * sizeof(dispsocketlist_t));
}
isc_mutex_init(&qid->lock); isc_mutex_init(&qid->lock);
for (i = 0; i < buckets; i++) { for (i = 0; i < qid->qid_nbuckets; i++) {
ISC_LIST_INIT(qid->qid_table[i]); ISC_LIST_INIT(qid->qid_table[i]);
if (qid->sock_table != NULL) { ISC_LIST_INIT(qid->sock_table[i]);
ISC_LIST_INIT(qid->sock_table[i]);
}
} }
qid->qid_nbuckets = buckets;
qid->qid_increment = increment;
qid->magic = QID_MAGIC; qid->magic = QID_MAGIC;
*qidp = qid; *qidp = qid;
return (ISC_R_SUCCESS);
} }
static void static void
@ -1818,10 +1643,8 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) {
qid->magic = 0; qid->magic = 0;
isc_mem_put(mctx, qid->qid_table, isc_mem_put(mctx, qid->qid_table,
qid->qid_nbuckets * sizeof(dns_displist_t)); qid->qid_nbuckets * sizeof(dns_displist_t));
if (qid->sock_table != NULL) { isc_mem_put(mctx, qid->sock_table,
isc_mem_put(mctx, qid->sock_table, qid->qid_nbuckets * sizeof(dispsocketlist_t));
qid->qid_nbuckets * sizeof(dispsocketlist_t));
}
isc_mutex_destroy(&qid->lock); isc_mutex_destroy(&qid->lock);
isc_mem_put(mctx, qid, sizeof(*qid)); isc_mem_put(mctx, qid, sizeof(*qid));
} }
@ -1830,8 +1653,7 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) {
* Allocate and set important limits. * Allocate and set important limits.
*/ */
static isc_result_t static isc_result_t
dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests, dispatch_allocate(dns_dispatchmgr_t *mgr, dns_dispatch_t **dispp) {
dns_dispatch_t **dispp) {
dns_dispatch_t *disp = NULL; dns_dispatch_t *disp = NULL;
REQUIRE(VALID_DISPATCHMGR(mgr)); REQUIRE(VALID_DISPATCHMGR(mgr));
@ -1846,7 +1668,6 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
isc_refcount_increment0(&mgr->irefs); isc_refcount_increment0(&mgr->irefs);
*disp = (dns_dispatch_t){ .mgr = mgr, *disp = (dns_dispatch_t){ .mgr = mgr,
.maxrequests = maxrequests,
.shutdown_why = ISC_R_UNEXPECTED }; .shutdown_why = ISC_R_UNEXPECTED };
isc_refcount_init(&disp->refcount, 1); isc_refcount_init(&disp->refcount, 1);
ISC_LINK_INIT(disp, link); ISC_LINK_INIT(disp, link);
@ -1891,19 +1712,6 @@ dispatch_free(dns_dispatch_t **dispp) {
isc_mem_put(mgr->mctx, disp->failsafe_ev, sizeof(*disp->failsafe_ev)); isc_mem_put(mgr->mctx, disp->failsafe_ev, sizeof(*disp->failsafe_ev));
disp->failsafe_ev = NULL; disp->failsafe_ev = NULL;
if (disp->qid != NULL) {
qid_destroy(mgr->mctx, &disp->qid);
}
if (disp->port_table != NULL) {
for (int i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++) {
INSIST(ISC_LIST_EMPTY(disp->port_table[i]));
}
isc_mem_put(mgr->mctx, disp->port_table,
sizeof(disp->port_table[0]) *
DNS_DISPATCH_PORTTABLESIZE);
}
disp->mgr = NULL; disp->mgr = NULL;
isc_mutex_destroy(&disp->lock); isc_mutex_destroy(&disp->lock);
disp->magic = 0; disp->magic = 0;
@ -1914,52 +1722,34 @@ dispatch_free(dns_dispatch_t **dispp) {
isc_result_t isc_result_t
dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
const isc_sockaddr_t *destaddr, unsigned int buffersize, const isc_sockaddr_t *destaddr, unsigned int attributes,
unsigned int maxbuffers, unsigned int maxrequests, dns_dispatch_t **dispp) {
unsigned int buckets, unsigned int increment,
unsigned int attributes, dns_dispatch_t **dispp) {
isc_result_t result; isc_result_t result;
dns_dispatch_t *disp = NULL; dns_dispatch_t *disp = NULL;
int pf;
UNUSED(maxbuffers);
UNUSED(buffersize);
REQUIRE(VALID_DISPATCHMGR(mgr)); REQUIRE(VALID_DISPATCHMGR(mgr));
REQUIRE(isc_socket_gettype(sock) == isc_sockettype_tcp); REQUIRE(isc_socket_gettype(sock) == isc_sockettype_tcp);
REQUIRE((attributes & DNS_DISPATCHATTR_TCP) != 0);
REQUIRE((attributes & DNS_DISPATCHATTR_UDP) == 0);
if (destaddr == NULL) { attributes |= DNS_DISPATCHATTR_TCP;
attributes |= DNS_DISPATCHATTR_PRIVATE; /* XXXMLG */ attributes &= ~DNS_DISPATCHATTR_UDP;
}
LOCK(&mgr->lock); LOCK(&mgr->lock);
/* result = dispatch_allocate(mgr, &disp);
* dispatch_allocate() checks mgr for us.
* qid_allocate() checks buckets and increment for us.
*/
disp = NULL;
result = dispatch_allocate(mgr, maxrequests, &disp);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
UNLOCK(&mgr->lock); UNLOCK(&mgr->lock);
return (result); return (result);
} }
result = qid_allocate(mgr, buckets, increment, &disp->qid, false);
if (result != ISC_R_SUCCESS) {
goto deallocate_dispatch;
}
disp->socktype = isc_sockettype_tcp; disp->socktype = isc_sockettype_tcp;
disp->socket = NULL;
isc_socket_attach(sock, &disp->socket); isc_socket_attach(sock, &disp->socket);
disp->ntasks = 1; disp->ntasks = 1;
disp->task[0] = NULL; disp->task[0] = NULL;
result = isc_task_create(taskmgr, 50, &disp->task[0]); result = isc_task_create(taskmgr, 50, &disp->task[0]);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
goto kill_socket; goto cleanup;
} }
disp->ctlevent = disp->ctlevent =
@ -1971,17 +1761,18 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
dns_tcpmsg_init(mgr->mctx, disp->socket, &disp->tcpmsg); dns_tcpmsg_init(mgr->mctx, disp->socket, &disp->tcpmsg);
disp->tcpmsg_valid = 1; disp->tcpmsg_valid = 1;
disp->attributes = attributes;
if (destaddr == NULL) { if (destaddr == NULL) {
(void)isc_socket_getpeername(sock, &disp->peer); (void)isc_socket_getpeername(sock, &disp->peer);
attributes |= DNS_DISPATCHATTR_PRIVATE;
} else { } else {
disp->peer = *destaddr; disp->peer = *destaddr;
} }
pf = isc_sockaddr_pf(&disp->peer);
if (localaddr == NULL) { if (localaddr == NULL) {
if (destaddr != NULL) { if (destaddr != NULL) {
switch (isc_sockaddr_pf(destaddr)) { switch (pf) {
case AF_INET: case AF_INET:
isc_sockaddr_any(&disp->local); isc_sockaddr_any(&disp->local);
break; break;
@ -1996,6 +1787,22 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
disp->local = *localaddr; disp->local = *localaddr;
} }
switch (pf) {
case PF_INET:
attributes |= DNS_DISPATCHATTR_IPV4;
break;
case PF_INET6:
attributes |= DNS_DISPATCHATTR_IPV6;
break;
default:
result = ISC_R_NOTIMPLEMENTED;
goto cleanup;
}
disp->attributes = attributes;
/* /*
* Append it to the dispatcher list. * Append it to the dispatcher list.
*/ */
@ -2012,9 +1819,8 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
kill_socket: cleanup:
isc_socket_detach(&disp->socket); isc_socket_detach(&disp->socket);
deallocate_dispatch:
dispatch_free(&disp); dispatch_free(&disp);
UNLOCK(&mgr->lock); UNLOCK(&mgr->lock);
@ -2108,8 +1914,6 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr,
isc_result_t isc_result_t
dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
unsigned int maxbuffers, unsigned int maxrequests,
unsigned int buckets, unsigned int increment,
unsigned int attributes, dns_dispatch_t **dispp) { unsigned int attributes, dns_dispatch_t **dispp) {
isc_result_t result; isc_result_t result;
dns_dispatch_t *disp = NULL; dns_dispatch_t *disp = NULL;
@ -2118,21 +1922,14 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
REQUIRE(sockmgr != NULL); REQUIRE(sockmgr != NULL);
REQUIRE(localaddr != NULL); REQUIRE(localaddr != NULL);
REQUIRE(taskmgr != NULL); REQUIRE(taskmgr != NULL);
REQUIRE(maxbuffers > 0);
REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
REQUIRE(increment > buckets);
REQUIRE(dispp != NULL && *dispp == NULL); REQUIRE(dispp != NULL && *dispp == NULL);
REQUIRE((attributes & DNS_DISPATCHATTR_TCP) == 0);
result = dispatchmgr_setudp(mgr, maxbuffers, maxrequests, buckets, attributes |= DNS_DISPATCHATTR_UDP;
increment); attributes &= ~DNS_DISPATCHATTR_TCP;
if (result != ISC_R_SUCCESS) {
return (result);
}
LOCK(&mgr->lock); LOCK(&mgr->lock);
result = dispatch_createudp(mgr, sockmgr, taskmgr, localaddr, result = dispatch_createudp(mgr, sockmgr, taskmgr, localaddr,
maxrequests, attributes, &disp); attributes, &disp);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
*dispp = disp; *dispp = disp;
@ -2145,23 +1942,24 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
static isc_result_t static isc_result_t
dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
unsigned int maxrequests, unsigned int attributes, unsigned int attributes, dns_dispatch_t **dispp) {
dns_dispatch_t **dispp) {
isc_result_t result; isc_result_t result;
dns_dispatch_t *disp = NULL; dns_dispatch_t *disp = NULL;
isc_socket_t *sock = NULL; isc_socket_t *sock = NULL;
isc_sockaddr_t sa_any; isc_sockaddr_t sa_any;
int i = 0; int pf, i = 0;
/* /*
* dispatch_allocate() checks mgr for us. * dispatch_allocate() checks mgr for us.
*/ */
disp = NULL; disp = NULL;
result = dispatch_allocate(mgr, maxrequests, &disp); result = dispatch_allocate(mgr, &disp);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
return (result); return (result);
} }
pf = isc_sockaddr_pf(localaddr);
disp->socktype = isc_sockettype_udp; disp->socktype = isc_sockettype_udp;
/* /*
@ -2170,9 +1968,9 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
* but we don't keep it open; sockets used for sending requests * but we don't keep it open; sockets used for sending requests
* will be created later on demand. * will be created later on demand.
*/ */
isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr)); isc_sockaddr_anyofpf(&sa_any, pf);
if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) { if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) {
result = open_socket(sockmgr, localaddr, 0, &sock, NULL); result = open_socket(sockmgr, localaddr, 0, &sock);
if (sock != NULL) { if (sock != NULL) {
isc_socket_detach(&sock); isc_socket_detach(&sock);
} }
@ -2181,13 +1979,6 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
} }
} }
disp->port_table = isc_mem_get(mgr->mctx,
sizeof(disp->port_table[0]) *
DNS_DISPATCH_PORTTABLESIZE);
for (i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++) {
ISC_LIST_INIT(disp->port_table[i]);
}
if (isc_log_wouldlog(dns_lctx, 90)) { if (isc_log_wouldlog(dns_lctx, 90)) {
char addrbuf[ISC_SOCKADDR_FORMATSIZE]; char addrbuf[ISC_SOCKADDR_FORMATSIZE];
@ -2225,6 +2016,21 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
attributes &= ~DNS_DISPATCHATTR_TCP; attributes &= ~DNS_DISPATCHATTR_TCP;
attributes |= DNS_DISPATCHATTR_UDP; attributes |= DNS_DISPATCHATTR_UDP;
switch (pf) {
case PF_INET:
attributes |= DNS_DISPATCHATTR_IPV4;
break;
case PF_INET6:
attributes |= DNS_DISPATCHATTR_IPV6;
break;
default:
result = ISC_R_NOTIMPLEMENTED;
goto kill_socket;
}
disp->attributes = attributes; disp->attributes = attributes;
/* /*
@ -2330,11 +2136,13 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
return (ISC_R_SHUTTINGDOWN); return (ISC_R_SHUTTINGDOWN);
} }
if (disp->requests >= disp->maxrequests) { if (disp->requests >= DNS_DISPATCH_MAXREQUESTS) {
UNLOCK(&disp->lock); UNLOCK(&disp->lock);
return (ISC_R_QUOTA); return (ISC_R_QUOTA);
} }
qid = disp->mgr->qid;
if (disp->socktype == isc_sockettype_udp && if (disp->socktype == isc_sockettype_udp &&
disp->nsockets > DNS_DISPATCH_SOCKSQUOTA) disp->nsockets > DNS_DISPATCH_SOCKSQUOTA)
{ {
@ -2369,8 +2177,6 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
ISC_LIST_APPEND(disp->activesockets, oldestsocket, link); ISC_LIST_APPEND(disp->activesockets, oldestsocket, link);
} }
qid = DNS_QID(disp);
if (disp->socktype == isc_sockettype_udp) { if (disp->socktype == isc_sockettype_udp) {
/* /*
* Get a separate UDP socket with a random port number. * Get a separate UDP socket with a random port number.
@ -2440,7 +2246,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
ISC_LIST_APPEND(qid->qid_table[bucket], res, link); ISC_LIST_APPEND(qid->qid_table[bucket], res, link);
UNLOCK(&qid->lock); UNLOCK(&qid->lock);
inc_stats(disp->mgr, (qid == disp->mgr->qid) inc_stats(disp->mgr, (disp->socktype == isc_sockettype_udp)
? dns_resstatscounter_disprequdp ? dns_resstatscounter_disprequdp
: dns_resstatscounter_dispreqtcp); : dns_resstatscounter_dispreqtcp);
@ -2463,7 +2269,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
disp->requests--; disp->requests--;
dec_stats(disp->mgr, dec_stats(disp->mgr,
(qid == disp->mgr->qid) (disp->socktype == isc_sockettype_udp)
? dns_resstatscounter_disprequdp ? dns_resstatscounter_disprequdp
: dns_resstatscounter_dispreqtcp); : dns_resstatscounter_dispreqtcp);
@ -2570,8 +2376,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
REQUIRE(VALID_DISPATCH(disp)); REQUIRE(VALID_DISPATCH(disp));
mgr = disp->mgr; mgr = disp->mgr;
REQUIRE(VALID_DISPATCHMGR(mgr)); REQUIRE(VALID_DISPATCHMGR(mgr));
qid = mgr->qid;
qid = DNS_QID(disp);
if (sockevent != NULL) { if (sockevent != NULL) {
REQUIRE(*sockevent != NULL); REQUIRE(*sockevent != NULL);
@ -2585,7 +2390,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
INSIST(disp->requests > 0); INSIST(disp->requests > 0);
disp->requests--; disp->requests--;
dec_stats(disp->mgr, (qid == disp->mgr->qid) dec_stats(disp->mgr, (disp->socktype == isc_sockettype_udp)
? dns_resstatscounter_disprequdp ? dns_resstatscounter_disprequdp
: dns_resstatscounter_dispreqtcp); : dns_resstatscounter_dispreqtcp);
@ -2677,14 +2482,12 @@ static void
do_cancel(dns_dispatch_t *disp) { do_cancel(dns_dispatch_t *disp) {
dns_dispatchevent_t *ev = NULL; dns_dispatchevent_t *ev = NULL;
dns_dispentry_t *resp = NULL; dns_dispentry_t *resp = NULL;
dns_qid_t *qid = NULL; dns_qid_t *qid = disp->mgr->qid;
if (disp->shutdown_out == 1) { if (disp->shutdown_out == 1) {
return; return;
} }
qid = DNS_QID(disp);
/* /*
* Search for the first response handler without packets outstanding * Search for the first response handler without packets outstanding
* unless a specific handler is given. * unless a specific handler is given.
@ -2827,8 +2630,7 @@ dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr,
for (i = 1; i < n; i++) { for (i = 1; i < n; i++) {
dset->dispatches[i] = NULL; dset->dispatches[i] = NULL;
result = dispatch_createudp(mgr, sockmgr, taskmgr, result = dispatch_createudp(mgr, sockmgr, taskmgr,
&source->local, source->maxrequests, &source->local, source->attributes,
source->attributes,
&dset->dispatches[i]); &dset->dispatches[i]);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
goto fail; goto fail;

View File

@ -207,8 +207,6 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats);
isc_result_t isc_result_t
dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
unsigned int maxbuffers, unsigned int maxrequests,
unsigned int buckets, unsigned int increment,
unsigned int attributes, dns_dispatch_t **dispp); unsigned int attributes, dns_dispatch_t **dispp);
/*%< /*%<
* Create a new UDP dispatch. * Create a new UDP dispatch.
@ -218,16 +216,6 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
* *
*\li dispp != NULL && *disp == NULL *\li dispp != NULL && *disp == NULL
* *
*\li 512 <= buffersize <= 64k
*
*\li maxbuffers > 0
*
*\li buckets < 2097169
*
*\li increment > buckets
*
*\li (attributes & DNS_DISPATCHATTR_TCP) == 0
*
* Returns: * Returns:
*\li ISC_R_SUCCESS -- success. *\li ISC_R_SUCCESS -- success.
* *
@ -237,25 +225,11 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
isc_result_t isc_result_t
dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
const isc_sockaddr_t *destaddr, unsigned int buffersize, const isc_sockaddr_t *destaddr, unsigned int attributes,
unsigned int maxbuffers, unsigned int maxrequests, dns_dispatch_t **dispp);
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. * Create a new dns_dispatch and attach it to the provided isc_socket_t.
* *
* For all dispatches, "buffersize" is the maximum packet size we will
* accept.
*
* "maxbuffers" and "maxrequests" control the number of buffers in the
* overall system and the number of buffers which can be allocated to
* requests.
*
* "buckets" is the number of buckets to use, and should be prime.
*
* "increment" is used in a collision avoidance function, and needs to be
* a prime > buckets, and not 2.
*
* Requires: * Requires:
* *
*\li mgr is a valid dispatch manager. *\li mgr is a valid dispatch manager.
@ -264,19 +238,6 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
* *
*\li task is a valid task that can be used internally to this dispatcher. *\li task is a valid task that can be used internally to this dispatcher.
* *
* \li 512 <= buffersize <= 64k
*
*\li maxbuffers > 0.
*
*\li maxrequests <= maxbuffers.
*
*\li buckets < 2097169 (the next prime after 65536 * 32)
*
*\li increment > buckets (and prime).
*
*\li attributes includes #DNS_DISPATCHATTR_TCP and does not include
* #DNS_DISPATCHATTR_UDP.
*
* Returns: * Returns:
*\li ISC_R_SUCCESS -- success. *\li ISC_R_SUCCESS -- success.
* *

View File

@ -119,8 +119,6 @@ static void
req_response(isc_task_t *task, isc_event_t *event); req_response(isc_task_t *task, isc_event_t *event);
static void static void
req_timeout(isc_task_t *task, isc_event_t *event); req_timeout(isc_task_t *task, isc_event_t *event);
static isc_socket_t *
req_getsocket(dns_request_t *request);
static void static void
req_connected(isc_task_t *task, isc_event_t *event); req_connected(isc_task_t *task, isc_event_t *event);
static void static void
@ -423,8 +421,9 @@ req_send(dns_request_t *request, isc_task_t *task,
REQUIRE(VALID_REQUEST(request)); REQUIRE(VALID_REQUEST(request));
sock = req_getsocket(request); sock = dns_dispatch_getentrysocket(request->dispentry);
isc_buffer_usedregion(request->query, &r); isc_buffer_usedregion(request->query, &r);
/* /*
* We could connect the socket when we are using an exclusive dispatch * We could connect the socket when we are using an exclusive dispatch
* as we do in resolver.c, but we prefer implementation simplicity * as we do in resolver.c, but we prefer implementation simplicity
@ -456,29 +455,11 @@ new_request(isc_mem_t *mctx, dns_request_t **requestp) {
dns_request_t *request; dns_request_t *request;
request = isc_mem_get(mctx, sizeof(*request)); request = isc_mem_get(mctx, sizeof(*request));
*request = (dns_request_t){ .dscp = -1 };
/*
* Zero structure.
*/
request->magic = 0;
request->mctx = NULL;
request->flags = 0;
ISC_LINK_INIT(request, link); ISC_LINK_INIT(request, link);
request->query = NULL;
request->answer = NULL;
request->event = NULL;
request->dispatch = NULL;
request->dispentry = NULL;
request->timer = NULL;
request->requestmgr = NULL;
request->tsig = NULL;
request->tsigkey = NULL;
request->dscp = -1;
ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL, ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL,
DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL, NULL, DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL, NULL,
NULL); NULL);
request->canceling = false;
request->udpcount = 0;
isc_mem_attach(mctx, &request->mctx); isc_mem_attach(mctx, &request->mctx);
@ -513,14 +494,12 @@ isblackholed(dns_dispatchmgr_t *dispatchmgr, const isc_sockaddr_t *destaddr) {
} }
static isc_result_t static isc_result_t
create_tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr, tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr,
const isc_sockaddr_t *srcaddr, const isc_sockaddr_t *srcaddr, const isc_sockaddr_t *destaddr,
const isc_sockaddr_t *destaddr, isc_dscp_t dscp, isc_dscp_t dscp, bool *connected, dns_dispatch_t **dispatchp) {
bool *connected, dns_dispatch_t **dispatchp) {
isc_result_t result; isc_result_t result;
isc_socket_t *sock = NULL; isc_socket_t *sock = NULL;
isc_sockaddr_t src; isc_sockaddr_t src;
unsigned int attrs;
isc_sockaddr_t bind_any; isc_sockaddr_t bind_any;
if (!newtcp) { if (!newtcp) {
@ -556,27 +535,20 @@ create_tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr,
goto cleanup; goto cleanup;
} }
attrs = DNS_DISPATCHATTR_TCP;
if (isc_sockaddr_pf(destaddr) == AF_INET) {
attrs |= DNS_DISPATCHATTR_IPV4;
} else {
attrs |= DNS_DISPATCHATTR_IPV6;
}
isc_socket_dscp(sock, dscp); isc_socket_dscp(sock, dscp);
result = dns_dispatch_createtcp( result = dns_dispatch_createtcp(requestmgr->dispatchmgr, sock,
requestmgr->dispatchmgr, sock, requestmgr->taskmgr, srcaddr, requestmgr->taskmgr, srcaddr, destaddr,
destaddr, 4096, 32768, 32768, 16411, 16433, attrs, dispatchp); 0, dispatchp);
cleanup: cleanup:
isc_socket_detach(&sock); isc_socket_detach(&sock);
return (result); return (result);
} }
static isc_result_t static isc_result_t
find_udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr,
const isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp) { const isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp) {
dns_dispatch_t *disp = NULL; dns_dispatch_t *disp = NULL;
unsigned int attrs;
if (srcaddr == NULL) { if (srcaddr == NULL) {
switch (isc_sockaddr_pf(destaddr)) { switch (isc_sockaddr_pf(destaddr)) {
@ -597,24 +569,10 @@ find_udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr,
dns_dispatch_attach(disp, dispatchp); dns_dispatch_attach(disp, dispatchp);
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
attrs = DNS_DISPATCHATTR_UDP;
switch (isc_sockaddr_pf(srcaddr)) {
case PF_INET:
attrs |= DNS_DISPATCHATTR_IPV4;
break;
case PF_INET6: return (dns_dispatch_createudp(
attrs |= DNS_DISPATCHATTR_IPV6; requestmgr->dispatchmgr, requestmgr->socketmgr,
break; requestmgr->taskmgr, srcaddr, 0, dispatchp));
default:
return (ISC_R_NOTIMPLEMENTED);
}
return (dns_dispatch_createudp(requestmgr->dispatchmgr,
requestmgr->socketmgr,
requestmgr->taskmgr, srcaddr, 32768,
32768, 16411, 16433, attrs, dispatchp));
} }
static isc_result_t static isc_result_t
@ -624,12 +582,10 @@ get_dispatch(bool tcp, bool newtcp, dns_requestmgr_t *requestmgr,
isc_result_t result; isc_result_t result;
if (tcp) { if (tcp) {
result = create_tcp_dispatch(newtcp, requestmgr, srcaddr, result = tcp_dispatch(newtcp, requestmgr, srcaddr, destaddr,
destaddr, dscp, connected, dscp, connected, dispatchp);
dispatchp);
} else { } else {
result = find_udp_dispatch(requestmgr, srcaddr, destaddr, result = udp_dispatch(requestmgr, srcaddr, destaddr, dispatchp);
dispatchp);
} }
return (result); return (result);
} }
@ -760,7 +716,7 @@ again:
goto cleanup; goto cleanup;
} }
sock = req_getsocket(request); sock = dns_dispatch_getentrysocket(request->dispentry);
INSIST(sock != NULL); INSIST(sock != NULL);
isc_buffer_allocate(mctx, &request->query, r.length + (tcp ? 2 : 0)); isc_buffer_allocate(mctx, &request->query, r.length + (tcp ? 2 : 0));
@ -931,7 +887,7 @@ use_tcp:
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
goto cleanup; goto cleanup;
} }
sock = req_getsocket(request); sock = dns_dispatch_getentrysocket(request->dispentry);
INSIST(sock != NULL); INSIST(sock != NULL);
message->id = id; message->id = id;
@ -1240,12 +1196,6 @@ dns_request_destroy(dns_request_t **requestp) {
/*** /***
*** Private: request. *** Private: request.
***/ ***/
static isc_socket_t *
req_getsocket(dns_request_t *request) {
return (dns_dispatch_getentrysocket(request->dispentry));
}
static void static void
req_connected(isc_task_t *task, isc_event_t *event) { req_connected(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent = (isc_socketevent_t *)event; isc_socketevent_t *sevent = (isc_socketevent_t *)event;

View File

@ -2140,15 +2140,11 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
*/ */
} else { } else {
if (have_addr) { if (have_addr) {
unsigned int attrs;
attrs = DNS_DISPATCHATTR_UDP;
switch (isc_sockaddr_pf(&addr)) { switch (isc_sockaddr_pf(&addr)) {
case AF_INET: case AF_INET:
attrs |= DNS_DISPATCHATTR_IPV4;
dscp = dns_resolver_getquerydscp4(fctx->res); dscp = dns_resolver_getquerydscp4(fctx->res);
break; break;
case AF_INET6: case AF_INET6:
attrs |= DNS_DISPATCHATTR_IPV6;
dscp = dns_resolver_getquerydscp6(fctx->res); dscp = dns_resolver_getquerydscp6(fctx->res);
break; break;
default: default:
@ -2157,8 +2153,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
} }
result = dns_dispatch_createudp( result = dns_dispatch_createudp(
res->dispatchmgr, res->socketmgr, res->taskmgr, res->dispatchmgr, res->socketmgr, res->taskmgr,
&addr, 20000, 32768, 16411, 16433, attrs, &addr, 0, &query->dispatch);
&query->dispatch);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
goto cleanup_query; goto cleanup_query;
} }
@ -2941,7 +2936,6 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
bool retry = false; bool retry = false;
isc_interval_t interval; isc_interval_t interval;
isc_result_t result; isc_result_t result;
unsigned int attrs;
fetchctx_t *fctx; fetchctx_t *fctx;
REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
@ -2970,6 +2964,8 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
isc_socket_detach(&query->tcpsocket); isc_socket_detach(&query->tcpsocket);
resquery_destroy(&query); resquery_destroy(&query);
} else { } else {
int attrs = 0;
switch (sevent->result) { switch (sevent->result) {
case ISC_R_SUCCESS: case ISC_R_SUCCESS:
@ -2997,20 +2993,11 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
* We are connected. Create a dispatcher and * We are connected. Create a dispatcher and
* send the query. * send the query.
*/ */
attrs = DNS_DISPATCHATTR_TCP | attrs = DNS_DISPATCHATTR_CONNECTED;
DNS_DISPATCHATTR_PRIVATE |
DNS_DISPATCHATTR_CONNECTED;
if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==
AF_INET) {
attrs |= DNS_DISPATCHATTR_IPV4;
} else {
attrs |= DNS_DISPATCHATTR_IPV6;
}
result = dns_dispatch_createtcp( result = dns_dispatch_createtcp(
query->dispatchmgr, query->tcpsocket, query->dispatchmgr, query->tcpsocket,
query->fctx->res->taskmgr, NULL, NULL, 4096, 2, query->fctx->res->taskmgr, NULL, NULL, attrs,
1, 1, 3, attrs, &query->dispatch); &query->dispatch);
/* /*
* Regardless of whether dns_dispatch_create() * Regardless of whether dns_dispatch_create()

View File

@ -66,7 +66,6 @@ static isc_result_t
make_dispatchset(unsigned int ndisps) { make_dispatchset(unsigned int ndisps) {
isc_result_t result; isc_result_t result;
isc_sockaddr_t any; isc_sockaddr_t any;
unsigned int attrs;
dns_dispatch_t *disp = NULL; dns_dispatch_t *disp = NULL;
result = dns_dispatchmgr_create(dt_mctx, &dispatchmgr); result = dns_dispatchmgr_create(dt_mctx, &dispatchmgr);
@ -75,9 +74,8 @@ make_dispatchset(unsigned int ndisps) {
} }
isc_sockaddr_any(&any); isc_sockaddr_any(&any);
attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &any, result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &any,
6, 1024, 17, 19, attrs, &disp); 0, &disp);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
return (result); return (result);
} }
@ -258,7 +256,6 @@ dispatch_getnext(void **state) {
uint16_t id; uint16_t id;
struct in_addr ina; struct in_addr ina;
unsigned char message[12]; unsigned char message[12];
unsigned int attrs;
unsigned char rbuf[12]; unsigned char rbuf[12];
UNUSED(state); UNUSED(state);
@ -273,9 +270,8 @@ dispatch_getnext(void **state) {
ina.s_addr = htonl(INADDR_LOOPBACK); ina.s_addr = htonl(INADDR_LOOPBACK);
isc_sockaddr_fromin(&local, &ina, 0); isc_sockaddr_fromin(&local, &ina, 0);
attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &local, result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &local,
6, 1024, 17, 19, attrs, &dispatch); 0, &dispatch);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
/* /*

View File

@ -58,7 +58,7 @@ _setup(void **state) {
isc_sockaddr_any(&local); isc_sockaddr_any(&local);
result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &local, result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &local,
100, 100, 100, 500, 0, &dispatch); 0, &dispatch);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
return (0); return (0);

View File

@ -225,12 +225,6 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
*\li #ISC_R_UNEXPECTED *\li #ISC_R_UNEXPECTED
*/ */
isc_result_t
isc_socket_dup(isc_socket_t *sock0, isc_socket_t **socketp);
/*%<
* Duplicate an existing socket, reusing its file descriptor.
*/
void void
isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how); isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how);
/*%< /*%<

View File

@ -350,8 +350,8 @@ struct isc_socket {
unsigned int listener : 1, /* listener socket */ unsigned int listener : 1, /* listener socket */
connected : 1, connecting : 1, /* connect pending connected : 1, connecting : 1, /* connect pending
* */ * */
bound : 1, /* bound to local addr */ bound : 1, /* bound to local addr */
dupped : 1, active : 1, /* currently active */ active : 1, /* currently active */
pktdscp : 1; /* per packet dscp */ pktdscp : 1; /* per packet dscp */
#ifdef ISC_PLATFORM_RECVOVERFLOW #ifdef ISC_PLATFORM_RECVOVERFLOW
@ -434,7 +434,7 @@ struct isc__socketthread {
static isc_result_t static isc_result_t
socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
isc_socket_t **socketp, isc_socket_t *dup_socket); isc_socket_t **socketp);
static void static void
send_recvdone_event(isc_socket_t *, isc_socketevent_t **); send_recvdone_event(isc_socket_t *, isc_socketevent_t **);
static void static void
@ -1881,7 +1881,6 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
sock->fd = -1; sock->fd = -1;
sock->threadid = -1; sock->threadid = -1;
sock->dscp = 0; /* TOS/TCLASS is zero until set. */ sock->dscp = 0; /* TOS/TCLASS is zero until set. */
sock->dupped = 0;
sock->statsindex = NULL; sock->statsindex = NULL;
sock->active = 0; sock->active = 0;
@ -2123,8 +2122,7 @@ set_ip_disable_pmtud(isc_socket_t *sock) {
} }
static isc_result_t static isc_result_t
opensocket(isc_socketmgr_t *manager, isc_socket_t *sock, opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) {
isc_socket_t *dup_socket) {
isc_result_t result; isc_result_t result;
char strbuf[ISC_STRERRORSIZE]; char strbuf[ISC_STRERRORSIZE];
const char *err = "socket"; const char *err = "socket";
@ -2138,60 +2136,52 @@ opensocket(isc_socketmgr_t *manager, isc_socket_t *sock,
#endif #endif
again: again:
if (dup_socket == NULL) { switch (sock->type) {
switch (sock->type) { case isc_sockettype_udp:
case isc_sockettype_udp: sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP); break;
break; case isc_sockettype_tcp:
case isc_sockettype_tcp: sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP); break;
break; case isc_sockettype_unix:
case isc_sockettype_unix: sock->fd = socket(sock->pf, SOCK_STREAM, 0);
sock->fd = socket(sock->pf, SOCK_STREAM, 0); break;
break; case isc_sockettype_raw:
case isc_sockettype_raw: errno = EPFNOSUPPORT;
errno = EPFNOSUPPORT; /*
/* * PF_ROUTE is a alias for PF_NETLINK on linux.
* PF_ROUTE is a alias for PF_NETLINK on linux. */
*/
#if defined(PF_ROUTE) #if defined(PF_ROUTE)
if (sock->fd == -1 && sock->pf == PF_ROUTE) { if (sock->fd == -1 && sock->pf == PF_ROUTE) {
#ifdef NETLINK_ROUTE #ifdef NETLINK_ROUTE
sock->fd = socket(sock->pf, SOCK_RAW, sock->fd = socket(sock->pf, SOCK_RAW, NETLINK_ROUTE);
NETLINK_ROUTE);
#else /* ifdef NETLINK_ROUTE */ #else /* ifdef NETLINK_ROUTE */
sock->fd = socket(sock->pf, SOCK_RAW, 0); sock->fd = socket(sock->pf, SOCK_RAW, 0);
#endif /* ifdef NETLINK_ROUTE */ #endif /* ifdef NETLINK_ROUTE */
if (sock->fd != -1) { if (sock->fd != -1) {
#ifdef NETLINK_ROUTE #ifdef NETLINK_ROUTE
struct sockaddr_nl sa; struct sockaddr_nl sa;
int n; int n;
/* /*
* Do an implicit bind. * Do an implicit bind.
*/ */
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK; sa.nl_family = AF_NETLINK;
sa.nl_groups = RTMGRP_IPV4_IFADDR | sa.nl_groups = RTMGRP_IPV4_IFADDR |
RTMGRP_IPV6_IFADDR; RTMGRP_IPV6_IFADDR;
n = bind(sock->fd, n = bind(sock->fd, (struct sockaddr *)&sa,
(struct sockaddr *)&sa, sizeof(sa));
sizeof(sa)); if (n < 0) {
if (n < 0) { close(sock->fd);
close(sock->fd); sock->fd = -1;
sock->fd = -1;
}
#endif /* ifdef NETLINK_ROUTE */
sock->bound = 1;
} }
#endif /* ifdef NETLINK_ROUTE */
sock->bound = 1;
} }
#endif /* if defined(PF_ROUTE) */
break;
} }
} else { #endif /* if defined(PF_ROUTE) */
sock->fd = dup(dup_socket->fd); break;
sock->dupped = 1;
sock->bound = dup_socket->bound;
} }
if (sock->fd == -1 && errno == EINTR && tries++ < 42) { if (sock->fd == -1 && errno == EINTR && tries++ < 42) {
goto again; goto again;
@ -2268,10 +2258,6 @@ again:
} }
} }
if (dup_socket != NULL) {
goto setup_done;
}
result = make_nonblock(sock->fd); result = make_nonblock(sock->fd);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
(void)close(sock->fd); (void)close(sock->fd);
@ -2410,7 +2396,6 @@ again:
set_ip_disable_pmtud(sock); set_ip_disable_pmtud(sock);
setup_done:
inc_stats(manager->stats, sock->statsindex[STATID_OPEN]); inc_stats(manager->stats, sock->statsindex[STATID_OPEN]);
if (sock->active == 0) { if (sock->active == 0) {
inc_stats(manager->stats, sock->statsindex[STATID_ACTIVE]); inc_stats(manager->stats, sock->statsindex[STATID_ACTIVE]);
@ -2421,14 +2406,13 @@ setup_done:
} }
/* /*
* Create a 'type' socket or duplicate an existing socket, managed * Create a 'type' socket, managed by 'manager'. Events will be posted to
* by 'manager'. Events will be posted to 'task' and when dispatched * 'task' and when dispatched 'action' will be called with 'arg' as the arg
* 'action' will be called with 'arg' as the arg value. The new * value. The new socket is returned in 'socketp'.
* socket is returned in 'socketp'.
*/ */
static isc_result_t static isc_result_t
socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
isc_socket_t **socketp, isc_socket_t *dup_socket) { isc_socket_t **socketp) {
isc_socket_t *sock = NULL; isc_socket_t *sock = NULL;
isc__socketthread_t *thread; isc__socketthread_t *thread;
isc_result_t result; isc_result_t result;
@ -2466,7 +2450,7 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
sock->pf = pf; sock->pf = pf;
result = opensocket(manager, sock, dup_socket); result = opensocket(manager, sock);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
free_socket(&sock); free_socket(&sock);
return (result); return (result);
@ -2507,8 +2491,7 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#endif /* ifdef USE_SELECT */ #endif /* ifdef USE_SELECT */
UNLOCK(&manager->lock); UNLOCK(&manager->lock);
socket_log(sock, NULL, CREATION, socket_log(sock, NULL, CREATION, "created");
dup_socket != NULL ? "dupped" : "created");
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
@ -2520,22 +2503,9 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
* in 'socketp'. * in 'socketp'.
*/ */
isc_result_t isc_result_t
isc_socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
isc_socket_t **socketp) { isc_socket_t **socketp) {
return (socket_create(manager0, pf, type, socketp, NULL)); return (socket_create(manager, pf, type, socketp));
}
/*%
* Duplicate an existing socket. The new socket is returned
* in 'socketp'.
*/
isc_result_t
isc_socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
REQUIRE(VALID_SOCKET(sock));
REQUIRE(socketp != NULL && *socketp == NULL);
return (socket_create(sock->manager, sock->pf, sock->type, socketp,
sock));
} }
isc_result_t isc_result_t
@ -2551,7 +2521,7 @@ isc_socket_open(isc_socket_t *sock) {
REQUIRE(sock->fd == -1); REQUIRE(sock->fd == -1);
REQUIRE(sock->threadid == -1); REQUIRE(sock->threadid == -1);
result = opensocket(sock->manager, sock, NULL); result = opensocket(sock->manager, sock);
UNLOCK(&sock->lock); UNLOCK(&sock->lock);
@ -2642,7 +2612,6 @@ isc_socket_close(isc_socket_t *sock) {
sock->fd = -1; sock->fd = -1;
sock->threadid = -1; sock->threadid = -1;
sock->dupped = 0;
memset(sock->name, 0, sizeof(sock->name)); memset(sock->name, 0, sizeof(sock->name));
sock->tag = NULL; sock->tag = NULL;
sock->listener = 0; sock->listener = 0;
@ -4334,7 +4303,6 @@ isc_socket_bind(isc_socket_t *sock, const isc_sockaddr_t *sockaddr,
LOCK(&sock->lock); LOCK(&sock->lock);
INSIST(!sock->bound); INSIST(!sock->bound);
INSIST(!sock->dupped);
if (sock->pf != sockaddr->type.sa.sa_family) { if (sock->pf != sockaddr->type.sa.sa_family) {
UNLOCK(&sock->lock); UNLOCK(&sock->lock);
@ -5078,7 +5046,6 @@ isc_socket_ipv6only(isc_socket_t *sock, bool yes) {
#endif /* if defined(IPV6_V6ONLY) */ #endif /* if defined(IPV6_V6ONLY) */
REQUIRE(VALID_SOCKET(sock)); REQUIRE(VALID_SOCKET(sock));
INSIST(!sock->dupped);
#ifdef IPV6_V6ONLY #ifdef IPV6_V6ONLY
if (sock->pf == AF_INET6) { if (sock->pf == AF_INET6) {
@ -5151,10 +5118,6 @@ isc_socket_dscp(isc_socket_t *sock, isc_dscp_t dscp) {
} }
#endif /* if !defined(IP_TOS) && !defined(IPV6_TCLASS) */ #endif /* if !defined(IP_TOS) && !defined(IPV6_TCLASS) */
#ifdef notyet
REQUIRE(!sock->dupped);
#endif /* ifdef notyet */
setdscp(sock, dscp); setdscp(sock, dscp);
} }
@ -5200,8 +5163,7 @@ static void
init_hasreuseport(void) { init_hasreuseport(void) {
/* /*
* SO_REUSEPORT works very differently on *BSD and on Linux (because why not). * SO_REUSEPORT works very differently on *BSD and on Linux (because why not).
* We only want to use it on Linux, if it's available. On BSD we want to dup() * We only want to use it on Linux, if it's available.
* sockets instead of re-binding them.
*/ */
#if (defined(SO_REUSEPORT) && defined(__linux__)) || \ #if (defined(SO_REUSEPORT) && defined(__linux__)) || \
(defined(SO_REUSEPORT_LB) && defined(__FreeBSD_kernel__)) (defined(SO_REUSEPORT_LB) && defined(__FreeBSD_kernel__))

View File

@ -218,89 +218,6 @@ udp_sendto_test(void **state) {
assert_string_equal(recvbuf, "Hello"); assert_string_equal(recvbuf, "Hello");
} }
/* Test UDP sendto/recv with duplicated socket */
static void
udp_dup_test(void **state) {
isc_result_t result;
isc_sockaddr_t addr1, addr2;
struct in_addr in;
char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
completion_t completion;
isc_region_t r;
UNUSED(state);
in.s_addr = inet_addr("127.0.0.1");
isc_sockaddr_fromin(&addr1, &in, 0);
isc_sockaddr_fromin(&addr2, &in, 0);
result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_socket_bind(s1, &addr1, 0);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_socket_getsockname(s1, &addr1);
assert_int_equal(result, ISC_R_SUCCESS);
assert_true(isc_sockaddr_getport(&addr1) != 0);
result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_socket_bind(s2, &addr2, 0);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_socket_getsockname(s2, &addr2);
assert_int_equal(result, ISC_R_SUCCESS);
assert_true(isc_sockaddr_getport(&addr2) != 0);
result = isc_socket_dup(s2, &s3);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_task_create(taskmgr, 0, &test_task);
assert_int_equal(result, ISC_R_SUCCESS);
snprintf(sendbuf, sizeof(sendbuf), "Hello");
r.base = (void *)sendbuf;
r.length = strlen(sendbuf) + 1;
completion_init(&completion);
result = isc_socket_sendto(s1, &r, test_task, event_done, &completion,
&addr2, NULL);
assert_int_equal(result, ISC_R_SUCCESS);
waitfor(&completion);
assert_true(atomic_load(&completion.done));
assert_int_equal(completion.result, ISC_R_SUCCESS);
snprintf(sendbuf, sizeof(sendbuf), "World");
r.base = (void *)sendbuf;
r.length = strlen(sendbuf) + 1;
completion_init(&completion);
result = isc_socket_sendto(s1, &r, test_task, event_done, &completion,
&addr2, NULL);
assert_int_equal(result, ISC_R_SUCCESS);
waitfor(&completion);
assert_true(atomic_load(&completion.done));
assert_int_equal(completion.result, ISC_R_SUCCESS);
r.base = (void *)recvbuf;
r.length = BUFSIZ;
completion_init(&completion);
result = isc_socket_recv(s2, &r, 1, test_task, event_done, &completion);
assert_int_equal(result, ISC_R_SUCCESS);
waitfor(&completion);
assert_true(atomic_load(&completion.done));
assert_int_equal(completion.result, ISC_R_SUCCESS);
assert_string_equal(recvbuf, "Hello");
r.base = (void *)recvbuf;
r.length = BUFSIZ;
completion_init(&completion);
result = isc_socket_recv(s3, &r, 1, test_task, event_done, &completion);
assert_int_equal(result, ISC_R_SUCCESS);
waitfor(&completion);
assert_true(atomic_load(&completion.done));
assert_int_equal(completion.result, ISC_R_SUCCESS);
assert_string_equal(recvbuf, "World");
}
/* Test UDP sendto/recv (IPv4) */ /* Test UDP sendto/recv (IPv4) */
static void static void
udp_dscp_v4_test(void **state) { udp_dscp_v4_test(void **state) {
@ -787,8 +704,6 @@ main(void) {
const struct CMUnitTest tests[] = { const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(udp_sendto_test, _setup, cmocka_unit_test_setup_teardown(udp_sendto_test, _setup,
_teardown), _teardown),
cmocka_unit_test_setup_teardown(udp_dup_test, _setup,
_teardown),
cmocka_unit_test_setup_teardown(tcp_dscp_v4_test, _setup, cmocka_unit_test_setup_teardown(tcp_dscp_v4_test, _setup,
_teardown), _teardown),
cmocka_unit_test_setup_teardown(tcp_dscp_v6_test, _setup, cmocka_unit_test_setup_teardown(tcp_dscp_v6_test, _setup,