From 5dcf55da03d707d2b1ea763308fa995292bb3d55 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Wed, 16 Dec 2020 01:32:06 -0800 Subject: [PATCH] Remove support for shared UDP dispatch sockets Currently the netmgr doesn't support unconnected, shared UDP sockets, so there's no reason to retain that functionality in the dispatcher prior to porting to the netmgr. In this commit, the DNS_DISPATCHATTR_EXCLUSIVE attribute has been removed as it is now non-optional; UDP dispatches are alwasy exclusive. Code implementing non-exclusive UDP dispatches has been removed. dns_dispatch_getentrysocket() now always returns the dispsocket for UDP dispatches and the dispatch socket for TCP dispatches. There is no longer any need to search for existing dispatches from dns_dispatch_getudp(), so the 'mask' option has been removed, and the function renamed to the more descriptive dns_dispatch_createudp(). --- bin/named/server.c | 32 +- bin/nsupdate/nsupdate.c | 26 +- bin/tests/system/pipelined/pipequeries.c | 38 +- bin/tests/system/tkey/keycreate.c | 6 +- bin/tests/system/tkey/keydelete.c | 6 +- bin/tools/mdig.c | 13 +- lib/dns/client.c | 12 +- lib/dns/dispatch.c | 591 +++++------------------ lib/dns/include/dns/dispatch.h | 25 +- lib/dns/request.c | 45 +- lib/dns/resolver.c | 70 +-- lib/dns/tests/dispatch_test.c | 12 +- lib/dns/tests/resolver_test.c | 4 +- 13 files changed, 235 insertions(+), 645 deletions(-) diff --git a/bin/named/server.c b/bin/named/server.c index 857609dd5a..57930b5040 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -161,11 +161,9 @@ #ifdef TUNE_LARGE #define RESOLVER_NTASKS_PERCPU 32 #define UDPBUFFERS 32768 -#define EXCLBUFFERS 32768 #else #define RESOLVER_NTASKS_PERCPU 8 -#define UDPBUFFERS 1000 -#define EXCLBUFFERS 4096 +#define UDPBUFFERS 4096 #endif /* TUNE_LARGE */ /* RFC7828 defines timeout as 16-bit value specified in units of 100 @@ -1260,7 +1258,7 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af, dns_dispatch_t **dispatchp, isc_dscp_t *dscpp, bool is_firstview) { isc_result_t result = ISC_R_FAILURE; - dns_dispatch_t *disp; + dns_dispatch_t *disp = NULL; isc_sockaddr_t sa; unsigned int attrs; const cfg_obj_t *obj = NULL; @@ -1310,8 +1308,7 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af, /* * Try to find a dispatcher that we can share. */ - attrs = 0; - attrs |= DNS_DISPATCHATTR_UDP; + attrs = DNS_DISPATCHATTR_UDP; switch (af) { case AF_INET: attrs |= DNS_DISPATCHATTR_IPV4; @@ -1320,10 +1317,7 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af, attrs |= DNS_DISPATCHATTR_IPV6; break; } - if (isc_sockaddr_getport(&sa) == 0) { - attrs |= DNS_DISPATCHATTR_EXCLUSIVE; - maxdispatchbuffers = EXCLBUFFERS; - } else { + if (isc_sockaddr_getport(&sa) != 0) { INSIST(obj != NULL); if (is_firstview) { cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, @@ -1333,10 +1327,9 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af, } } - disp = NULL; - result = dns_dispatch_getudp(named_g_dispatchmgr, named_g_socketmgr, - named_g_taskmgr, &sa, maxdispatchbuffers, - 32768, 16411, 16433, attrs, &disp); + result = dns_dispatch_createudp( + named_g_dispatchmgr, named_g_socketmgr, named_g_taskmgr, &sa, + maxdispatchbuffers, 32768, 16411, 16433, attrs, &disp); if (result != ISC_R_SUCCESS) { isc_sockaddr_t any; char buf[ISC_SOCKADDR_FORMATSIZE]; @@ -10377,8 +10370,7 @@ named_add_reserved_dispatch(named_server_t *server, dispatch->dispatchgen = server->dispatchgen; dispatch->dispatch = NULL; - attrs = 0; - attrs |= DNS_DISPATCHATTR_UDP; + attrs = DNS_DISPATCHATTR_UDP; switch (isc_sockaddr_pf(addr)) { case AF_INET: attrs |= DNS_DISPATCHATTR_IPV4; @@ -10391,10 +10383,10 @@ named_add_reserved_dispatch(named_server_t *server, goto cleanup; } - result = dns_dispatch_getudp(named_g_dispatchmgr, named_g_socketmgr, - named_g_taskmgr, &dispatch->addr, - UDPBUFFERS, 32768, 16411, 16433, attrs, - &dispatch->dispatch); + result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_socketmgr, + named_g_taskmgr, &dispatch->addr, + UDPBUFFERS, 32768, 16411, 16433, attrs, + &dispatch->dispatch); if (result != ISC_R_SUCCESS) { goto cleanup; } diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index bc39de6725..ce2a48c4d0 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -937,25 +937,23 @@ setup_system(void) { set_source_ports(dispatchmgr); if (have_ipv6) { - attrs = DNS_DISPATCHATTR_UDP; - attrs |= DNS_DISPATCHATTR_MAKEQUERY; - attrs |= DNS_DISPATCHATTR_IPV6; + attrs = (DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY | + DNS_DISPATCHATTR_IPV6); isc_sockaddr_any6(&bind_any6); - result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, - &bind_any6, 4, 2, 3, 5, attrs, - &dispatchv6); - check_result(result, "dns_dispatch_getudp (v6)"); + result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, + &bind_any6, 4, 2, 3, 5, attrs, + &dispatchv6); + check_result(result, "dns_dispatch_createudp (v6)"); } if (have_ipv4) { - attrs = DNS_DISPATCHATTR_UDP; - attrs |= DNS_DISPATCHATTR_MAKEQUERY; - attrs |= DNS_DISPATCHATTR_IPV4; + attrs = (DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY | + DNS_DISPATCHATTR_IPV4); isc_sockaddr_any(&bind_any); - result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, - &bind_any, 4, 2, 3, 5, attrs, - &dispatchv4); - check_result(result, "dns_dispatch_getudp (v4)"); + result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, + &bind_any, 4, 2, 3, 5, attrs, + &dispatchv4); + check_result(result, "dns_dispatch_createudp (v4)"); } result = dns_requestmgr_create(gmctx, timermgr, socketmgr, taskmgr, diff --git a/bin/tests/system/pipelined/pipequeries.c b/bin/tests/system/pipelined/pipequeries.c index f9371e7c0d..e8aa99dbd1 100644 --- a/bin/tests/system/pipelined/pipequeries.c +++ b/bin/tests/system/pipelined/pipequeries.c @@ -59,8 +59,8 @@ #define PORT 5300 #define TIMEOUT 30 -static isc_mem_t *mctx; -static dns_requestmgr_t *requestmgr; +static isc_mem_t *mctx = NULL; +static dns_requestmgr_t *requestmgr = NULL; static bool have_src = false; static isc_sockaddr_t srcaddr; static isc_sockaddr_t dstaddr; @@ -126,10 +126,10 @@ recvresponse(isc_task_t *task, isc_event_t *event) { static isc_result_t sendquery(isc_task_t *task) { - dns_request_t *request; - dns_message_t *message; - dns_name_t *qname; - dns_rdataset_t *qrdataset; + dns_request_t *request = NULL; + dns_message_t *message = NULL; + dns_name_t *qname = NULL; + dns_rdataset_t *qrdataset = NULL; isc_result_t result; dns_fixedname_t queryname; isc_buffer_t buf; @@ -150,7 +150,6 @@ sendquery(isc_task_t *task) { dns_rootname, 0, NULL); CHECK("dns_name_fromtext", result); - message = NULL; dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message); message->opcode = dns_opcode_query; @@ -158,11 +157,9 @@ sendquery(isc_task_t *task) { message->rdclass = dns_rdataclass_in; message->id = (unsigned short)(random() & 0xFFFF); - qname = NULL; result = dns_message_gettempname(message, &qname); CHECK("dns_message_gettempname", result); - qrdataset = NULL; result = dns_message_gettemprdataset(message, &qrdataset); CHECK("dns_message_gettemprdataset", result); @@ -172,7 +169,6 @@ sendquery(isc_task_t *task) { ISC_LIST_APPEND(qname->list, qrdataset, link); dns_message_addname(message, qname, DNS_SECTION_QUESTION); - request = NULL; result = dns_request_createvia(requestmgr, message, have_src ? &srcaddr : NULL, &dstaddr, -1, DNS_REQUESTOPT_TCP, NULL, TIMEOUT, 0, 0, @@ -203,8 +199,8 @@ main(int argc, char *argv[]) { isc_sockaddr_t bind_any; struct in_addr inaddr; isc_result_t result; - isc_log_t *lctx; - isc_logconfig_t *lcfg; + isc_log_t *lctx = NULL; + isc_logconfig_t *lcfg = NULL; isc_nm_t *netmgr = NULL; isc_taskmgr_t *taskmgr = NULL; isc_task_t *task = NULL; @@ -212,8 +208,8 @@ main(int argc, char *argv[]) { isc_socketmgr_t *socketmgr = NULL; dns_dispatchmgr_t *dispatchmgr = NULL; unsigned int attrs; - dns_dispatch_t *dispatchv4; - dns_view_t *view; + dns_dispatch_t *dispatchv4 = NULL; + dns_view_t *view = NULL; uint16_t port = PORT; int c; @@ -267,11 +263,8 @@ main(int argc, char *argv[]) { } isc_sockaddr_fromin(&dstaddr, &inaddr, port); - mctx = NULL; isc_mem_create(&mctx); - lctx = NULL; - lcfg = NULL; isc_log_create(mctx, &lctx, &lcfg); RUNCHECK(dst_lib_init(mctx, NULL)); @@ -284,18 +277,15 @@ main(int argc, char *argv[]) { attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY | DNS_DISPATCHATTR_IPV4; - dispatchv4 = NULL; - RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, - have_src ? &srcaddr : &bind_any, 4, 2, 3, - 5, attrs, &dispatchv4)); - requestmgr = NULL; + + RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, + have_src ? &srcaddr : &bind_any, 4, 2, + 3, 5, attrs, &dispatchv4)); RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, dispatchmgr, dispatchv4, NULL, &requestmgr)); - view = NULL; RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); - RUNCHECK(isc_app_onrun(mctx, task, sendqueries, NULL)); (void)isc_app_run(); diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c index 14fb88857b..1b9d500893 100644 --- a/bin/tests/system/tkey/keycreate.c +++ b/bin/tests/system/tkey/keycreate.c @@ -243,9 +243,9 @@ main(int argc, char *argv[]) { isc_sockaddr_any(&bind_any); attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY | DNS_DISPATCHATTR_IPV4; - dispatchv4 = NULL; - RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &bind_any, - 4, 2, 3, 5, attrs, &dispatchv4)); + RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, + &bind_any, 4, 2, 3, 5, attrs, + &dispatchv4)); requestmgr = NULL; RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, dispatchmgr, dispatchv4, NULL, diff --git a/bin/tests/system/tkey/keydelete.c b/bin/tests/system/tkey/keydelete.c index 605be6ecc0..eabb3f0c7e 100644 --- a/bin/tests/system/tkey/keydelete.c +++ b/bin/tests/system/tkey/keydelete.c @@ -186,9 +186,9 @@ main(int argc, char **argv) { isc_sockaddr_any(&bind_any); attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY | DNS_DISPATCHATTR_IPV4; - dispatchv4 = NULL; - RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &bind_any, - 4, 2, 3, 5, attrs, &dispatchv4)); + RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, + &bind_any, 4, 2, 3, 5, attrs, + &dispatchv4)); requestmgr = NULL; RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, dispatchmgr, dispatchv4, NULL, diff --git a/bin/tools/mdig.c b/bin/tools/mdig.c index c07e64b032..d379285ed7 100644 --- a/bin/tools/mdig.c +++ b/bin/tools/mdig.c @@ -2071,11 +2071,10 @@ main(int argc, char *argv[]) { isc_timermgr_t *timermgr = NULL; isc_socketmgr_t *socketmgr = NULL; dns_dispatchmgr_t *dispatchmgr = NULL; - unsigned int attrs; dns_dispatch_t *dispatchvx = NULL; dns_view_t *view = NULL; + unsigned int attrs, i; int ns; - unsigned int i; RUNCHECK(isc_app_start()); @@ -2094,7 +2093,6 @@ main(int argc, char *argv[]) { preparse_args(argc, argv); isc_mem_create(&mctx); - isc_log_create(mctx, &lctx, &lcfg); RUNCHECK(dst_lib_init(mctx, NULL)); @@ -2128,7 +2126,6 @@ main(int argc, char *argv[]) { &socketmgr); RUNCHECK(isc_task_create(taskmgr, 0, &task)); - RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY; @@ -2139,10 +2136,10 @@ main(int argc, char *argv[]) { isc_sockaddr_any6(&bind_any); attrs |= DNS_DISPATCHATTR_IPV6; } - dispatchvx = NULL; - RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, - have_src ? &srcaddr : &bind_any, 100, 100, - 17, 19, attrs, &dispatchvx)); + RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, + have_src ? &srcaddr : &bind_any, 100, + 100, 17, 19, attrs, &dispatchvx)); + RUNCHECK(dns_requestmgr_create( mctx, timermgr, socketmgr, taskmgr, dispatchmgr, have_ipv4 ? dispatchvx : NULL, have_ipv6 ? dispatchvx : NULL, diff --git a/lib/dns/client.c b/lib/dns/client.c index ce2c7e325c..3547d3cc81 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -206,13 +206,12 @@ getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, bool is_shared, dns_dispatch_t **dispp, const isc_sockaddr_t *localaddr) { unsigned int attrs; - dns_dispatch_t *disp; + dns_dispatch_t *disp = NULL; unsigned maxbuffers, maxrequests, buckets, increment; isc_result_t result; isc_sockaddr_t anyaddr; - attrs = 0; - attrs |= DNS_DISPATCHATTR_UDP; + attrs = DNS_DISPATCHATTR_UDP; switch (family) { case AF_INET: attrs |= DNS_DISPATCHATTR_IPV4; @@ -235,10 +234,9 @@ getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, buckets = is_shared ? 16411 : 3; increment = is_shared ? 16433 : 5; - disp = NULL; - result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, localaddr, - maxbuffers, maxrequests, buckets, - increment, attrs, &disp); + result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, + localaddr, maxbuffers, maxrequests, + buckets, increment, attrs, &disp); if (result == ISC_R_SUCCESS) { *dispp = disp; } diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 1bbff39504..5a3bbad899 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -275,11 +275,7 @@ destroy_dispsocket(dns_dispatch_t *, dispsocket_t **); static void deactivate_dispsocket(dns_dispatch_t *, dispsocket_t *); static void -udp_exrecv(isc_task_t *, isc_event_t *); -static void -udp_shrecv(isc_task_t *, isc_event_t *); -static void -udp_recv(isc_event_t *, dns_dispatch_t *, dispsocket_t *); +udp_recv(isc_task_t *, isc_event_t *); static void tcp_recv(isc_task_t *, isc_event_t *); static isc_result_t @@ -303,14 +299,10 @@ linear_next(dns_qid_t *disp, dns_dispentry_t *resp); static void dispatch_free(dns_dispatch_t **dispp); static isc_result_t -get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, - isc_socketmgr_t *sockmgr, const isc_sockaddr_t *localaddr, - isc_socket_t **sockp, isc_socket_t *dup_socket); -static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, unsigned int maxrequests, unsigned int attributes, - dns_dispatch_t **dispp, isc_socket_t *dup_socket); + dns_dispatch_t **dispp); static bool destroy_mgr_ok(dns_dispatchmgr_t *mgr); static void @@ -324,9 +316,6 @@ static isc_result_t open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local, unsigned int options, isc_socket_t **sockp, isc_socket_t *dup_socket); -static bool -portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock, - isc_sockaddr_t *sockaddrp); #define LVL(x) ISC_LOG_DEBUG(x) @@ -534,9 +523,8 @@ destroy_disp(isc_task_t *task, isc_event_t *event) { LOCK(&mgr->lock); ISC_LIST_UNLINK(mgr->list, disp, link); - dispatch_log(disp, LVL(90), - "shutting down; detaching from sock %p, task %p", - disp->socket, disp->task[0]); /* XXXX */ + dispatch_log(disp, LVL(90), "shutting down; detaching from sock %p", + disp->socket); if (disp->sepool != NULL) { isc_mem_destroy(&disp->sepool); @@ -747,29 +735,25 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, } } - if (result == ISC_R_SUCCESS) { - dispsock->socket = sock; - dispsock->host = *dest; - dispsock->bucket = bucket; - LOCK(&qid->lock); - dispsock->portentry = portentry; - ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink); - UNLOCK(&qid->lock); - *dispsockp = dispsock; - *portp = port; - } else { - /* - * We could keep it in the inactive list, but since this should - * be an exceptional case and might be resource shortage, we'd - * rather destroy it. - */ + if (result != ISC_R_SUCCESS) { if (sock != NULL) { isc_socket_detach(&sock); } destroy_dispsocket(disp, &dispsock); + return (result); } - return (result); + dispsock->socket = sock; + dispsock->host = *dest; + dispsock->bucket = bucket; + LOCK(&qid->lock); + dispsock->portentry = portentry; + ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink); + UNLOCK(&qid->lock); + *dispsockp = dispsock; + *portp = port; + + return (ISC_R_SUCCESS); } /*% @@ -973,26 +957,6 @@ allocate_devent(dns_dispatch_t *disp) { return (ev); } -static void -udp_exrecv(isc_task_t *task, isc_event_t *ev) { - dispsocket_t *dispsock = ev->ev_arg; - - UNUSED(task); - - REQUIRE(VALID_DISPSOCK(dispsock)); - udp_recv(ev, dispsock->disp, dispsock); -} - -static void -udp_shrecv(isc_task_t *task, isc_event_t *ev) { - dns_dispatch_t *disp = ev->ev_arg; - - UNUSED(task); - - REQUIRE(VALID_DISPATCH(disp)); - udp_recv(ev, disp, NULL); -} - /* * General flow: * @@ -1008,28 +972,36 @@ udp_shrecv(isc_task_t *task, isc_event_t *ev) { * restart. */ static void -udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { +udp_recv(isc_task_t *task, isc_event_t *ev_in) { isc_socketevent_t *ev = (isc_socketevent_t *)ev_in; + dispsocket_t *dispsock = NULL; + dns_dispatch_t *disp = NULL; dns_messageid_t id; isc_result_t dres; isc_buffer_t source; unsigned int flags; dns_dispentry_t *resp = NULL; dns_dispatchevent_t *rev = NULL; - unsigned int bucket; bool killit; bool queue_response; dns_dispatchmgr_t *mgr = NULL; - dns_qid_t *qid = NULL; isc_netaddr_t netaddr; int match; int result; - bool qidlocked = false; + + UNUSED(task); + + REQUIRE(ev->ev_type == ISC_SOCKEVENT_RECVDONE); + + dispsock = ev_in->ev_arg; + + REQUIRE(VALID_DISPSOCK(dispsock)); + + disp = dispsock->disp; LOCK(&disp->lock); mgr = disp->mgr; - qid = mgr->qid; LOCK(&disp->mgr->buffer_lock); dispatch_log(disp, LVL(90), @@ -1037,24 +1009,12 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { disp->requests, disp->mgr->buffers, disp->recv_pending); UNLOCK(&disp->mgr->buffer_lock); - if (dispsock == NULL && ev->ev_type == ISC_SOCKEVENT_RECVDONE) { - /* - * Unless the receive event was imported from a listening - * interface, in which case the event type is - * DNS_EVENT_IMPORTRECVDONE, receive operation must be pending. - */ - INSIST(disp->recv_pending != 0); - disp->recv_pending = 0; - } - - if (dispsock != NULL && - (ev->result == ISC_R_CANCELED || dispsock->resp == NULL)) - { + if (ev->result == ISC_R_CANCELED || dispsock->resp == NULL) { /* * dispsock->resp can be NULL if this transaction was canceled * just after receiving a response. Since this socket is * exclusively used and there should be at most one receive - * event the canceled event should have been no effect. So + * event the canceled event should have no effect. So * we can (and should) deactivate the socket right now. */ deactivate_dispsocket(disp, dispsock); @@ -1079,40 +1039,26 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { return; } - if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { - if (dispsock == NULL) { - free_buffer(disp, ev->region.base, ev->region.length); - - isc_event_free(&ev_in); - UNLOCK(&disp->lock); - return; - } - - resp = dispsock->resp; - id = resp->id; - if (ev->result != ISC_R_SUCCESS) { - /* - * This is most likely a network error on a - * connected socket. It makes no sense to - * check the address or parse the packet, but it - * will help to return the error to the caller. - */ - goto sendresponse; - } - } else if (ev->result != ISC_R_SUCCESS) { + if (dispsock == NULL) { free_buffer(disp, ev->region.base, ev->region.length); - - if (ev->result != ISC_R_CANCELED) { - dispatch_log(disp, ISC_LOG_ERROR, - "odd socket result in udp_recv(): %s", - isc_result_totext(ev->result)); - } - isc_event_free(&ev_in); UNLOCK(&disp->lock); return; } + resp = dispsock->resp; + id = resp->id; + + if (ev->result != ISC_R_SUCCESS) { + /* + * This is most likely a network error on a + * connected socket. It makes no sense to + * check the address or parse the packet, but it + * will help to return the error to the caller. + */ + goto sendresponse; + } + /* * If this is from a blackholed address, drop it. */ @@ -1160,33 +1106,13 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { } /* - * Search for the corresponding response. If we are using an exclusive - * socket, we've already identified it and we can skip the search; but - * the ID and the address must match the expected ones. + * The QID and the address must match the expected ones. */ - if (resp == NULL) { - bucket = dns_hash(qid, &ev->address, id, disp->localport); - LOCK(&qid->lock); - qidlocked = true; - resp = entry_search(qid, &ev->address, id, disp->localport, - bucket); - dispatch_log(disp, LVL(90), - "search for response in bucket %d: %s", bucket, - (resp == NULL ? "not found" : "found")); - - } else if (resp->id != id || - !isc_sockaddr_equal(&ev->address, &resp->host)) { - dispatch_log(disp, LVL(90), - "response to an exclusive socket doesn't match"); + if (resp->id != id || !isc_sockaddr_equal(&ev->address, &resp->host)) { + dispatch_log(disp, LVL(90), "response doesn't match"); inc_stats(mgr, dns_resstatscounter_mismatch); free_buffer(disp, ev->region.base, ev->region.length); - goto unlock; - } - - if (resp == NULL) { - inc_stats(mgr, dns_resstatscounter_mismatch); - free_buffer(disp, ev->region.base, ev->region.length); - goto unlock; + goto restart; } /* @@ -1206,7 +1132,7 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { isc_sockaddr_getport(&resp->disp->local)) { free_buffer(disp, ev->region.base, ev->region.length); - goto unlock; + goto restart; } /* @@ -1223,7 +1149,7 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { isc_sockaddr_pf(&disp->local) != PF_INET6) { free_buffer(disp, ev->region.base, ev->region.length); - goto unlock; + goto restart; } isc_sockaddr_anyofpf(&a1, isc_sockaddr_pf(&resp->disp->local)); isc_sockaddr_anyofpf(&a2, isc_sockaddr_pf(&disp->local)); @@ -1232,7 +1158,7 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { !isc_sockaddr_eqaddr(&a2, &disp->local)) { free_buffer(disp, ev->region.base, ev->region.length); - goto unlock; + goto restart; } } @@ -1264,23 +1190,13 @@ sendresponse: resp->item_out = true; isc_task_send(resp->task, ISC_EVENT_PTR(&rev)); } -unlock: - if (qidlocked) { - UNLOCK(&qid->lock); - } /* * Restart recv() to get the next packet. */ restart: result = startrecv(disp, dispsock); - if (result != ISC_R_SUCCESS && dispsock != NULL) { - /* - * XXX: wired. There seems to be no recovery process other than - * deactivate this socket anyway (since we cannot start - * receiving, we won't be able to receive a cancel event - * from the user). - */ + if (result != ISC_R_SUCCESS) { deactivate_dispsocket(disp, dispsock); } isc_event_free(&ev_in); @@ -1478,26 +1394,21 @@ startrecv(dns_dispatch_t *disp, dispsocket_t *dispsock) { isc_result_t res; isc_region_t region; isc_socket_t *sock = NULL; + isc_socketevent_t *sev = NULL; if (disp->shutting_down == 1) { return (ISC_R_SUCCESS); } - if (disp->recv_pending != 0 && dispsock == NULL) { - return (ISC_R_SUCCESS); - } - - if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0 && - dispsock == NULL) { - return (ISC_R_SUCCESS); - } - - if (dispsock != NULL) { - sock = dispsock->socket; - } else { + if (dispsock == NULL) { + if (disp->socktype == isc_sockettype_udp || + disp->recv_pending != 0) { + return (ISC_R_SUCCESS); + } sock = disp->socket; + } else { + sock = dispsock->socket; } - INSIST(sock != NULL); switch (disp->socktype) { /* @@ -1509,33 +1420,13 @@ startrecv(dns_dispatch_t *disp, dispsocket_t *dispsock) { if (region.base == NULL) { return (ISC_R_NOMEMORY); } - if (dispsock != NULL) { - isc_task_t *dt = dispsock->task; - isc_socketevent_t *sev = allocate_sevent( - disp, sock, ISC_SOCKEVENT_RECVDONE, udp_exrecv, - dispsock); - - res = isc_socket_recv2(sock, ®ion, 1, dt, sev, 0); - if (res != ISC_R_SUCCESS) { - free_buffer(disp, region.base, region.length); - return (res); - } - } else { - isc_task_t *dt = disp->task[0]; - isc_socketevent_t *sev = allocate_sevent( - disp, sock, ISC_SOCKEVENT_RECVDONE, udp_shrecv, - disp); - - res = isc_socket_recv2(sock, ®ion, 1, dt, sev, 0); - if (res != ISC_R_SUCCESS) { - free_buffer(disp, region.base, region.length); - disp->shutdown_why = res; - disp->shutting_down = 1; - do_cancel(disp); - return (ISC_R_SUCCESS); /* recover by cancel */ - } - INSIST(disp->recv_pending == 0); - disp->recv_pending = 1; + sev = allocate_sevent(disp, sock, ISC_SOCKEVENT_RECVDONE, + udp_recv, dispsock); + res = isc_socket_recv2(sock, ®ion, 1, dispsock->task, sev, + 0); + if (res != ISC_R_SUCCESS) { + free_buffer(disp, region.base, region.length); + return (res); } break; @@ -1876,62 +1767,6 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats) { isc_stats_attach(stats, &mgr->stats); } -static int -port_cmp(const void *key, const void *ent) { - in_port_t p1 = *(const in_port_t *)key; - in_port_t p2 = *(const in_port_t *)ent; - - if (p1 < p2) { - return (-1); - } else if (p1 == p2) { - return (0); - } else { - return (1); - } -} - -static bool -portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock, - isc_sockaddr_t *sockaddrp) { - isc_sockaddr_t sockaddr; - isc_result_t result; - in_port_t *ports, port; - unsigned int nports; - bool available = false; - - REQUIRE(sock != NULL || sockaddrp != NULL); - - PORTBUFLOCK(mgr); - if (sock != NULL) { - sockaddrp = &sockaddr; - result = isc_socket_getsockname(sock, sockaddrp); - if (result != ISC_R_SUCCESS) { - goto unlock; - } - } - - if (isc_sockaddr_pf(sockaddrp) == AF_INET) { - ports = mgr->v4ports; - nports = mgr->nv4ports; - } else { - ports = mgr->v6ports; - nports = mgr->nv6ports; - } - if (ports == NULL) { - goto unlock; - } - - port = isc_sockaddr_getport(sockaddrp); - if (bsearch(&port, ports, nports, sizeof(in_port_t), port_cmp) != NULL) - { - available = true; - } - -unlock: - PORTBUFUNLOCK(mgr); - return (available); -} - static isc_result_t qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets, unsigned int increment, dns_qid_t **qidp, bool needsocktable) { @@ -2120,8 +1955,6 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, disp->socket = NULL; isc_socket_attach(sock, &disp->socket); - disp->sepool = NULL; - disp->ntasks = 1; disp->task[0] = NULL; result = isc_task_create(taskmgr, 50, &disp->task[0]); @@ -2140,6 +1973,12 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, disp->attributes = attributes; + if (destaddr == NULL) { + (void)isc_socket_getpeername(sock, &disp->peer); + } else { + disp->peer = *destaddr; + } + if (localaddr == NULL) { if (destaddr != NULL) { switch (isc_sockaddr_pf(destaddr)) { @@ -2150,15 +1989,13 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, isc_sockaddr_any6(&disp->local); break; } + } else { + (void)isc_socket_getsockname(sock, &disp->local); } } else { disp->local = *localaddr; } - if (destaddr != NULL) { - disp->peer = *destaddr; - } - /* * Append it to the dispatcher list. */ @@ -2205,7 +2042,7 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, /* First pass */ attributes = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_CONNECTED; mask = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_PRIVATE | - DNS_DISPATCHATTR_EXCLUSIVE | DNS_DISPATCHATTR_CONNECTED; + DNS_DISPATCHATTR_CONNECTED; LOCK(&mgr->lock); disp = ISC_LIST_HEAD(mgr->list); @@ -2269,11 +2106,11 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, } isc_result_t -dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, - 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) { +dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, + 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) { isc_result_t result; dns_dispatch_t *disp = NULL; @@ -2294,149 +2131,26 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, } LOCK(&mgr->lock); - - if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { - REQUIRE(isc_sockaddr_getport(localaddr) == 0); - } - - /* - * We need an exclusive-socket dispatch, or else we didn't - * find a suitable shared one and need to create it. - */ result = dispatch_createudp(mgr, sockmgr, taskmgr, localaddr, - maxrequests, attributes, &disp, NULL); - if (result != ISC_R_SUCCESS) { - UNLOCK(&mgr->lock); - return (result); + maxrequests, attributes, &disp); + + if (result == ISC_R_SUCCESS) { + *dispp = disp; } UNLOCK(&mgr->lock); - *dispp = disp; - return (ISC_R_SUCCESS); } -/* - * mgr should be locked. - */ - -#ifndef DNS_DISPATCH_HELD -#define DNS_DISPATCH_HELD 20U -#endif /* ifndef DNS_DISPATCH_HELD */ - -static isc_result_t -get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, - isc_socketmgr_t *sockmgr, const isc_sockaddr_t *localaddr, - isc_socket_t **sockp, isc_socket_t *dup_socket) { - unsigned int i, j; - isc_socket_t *held[DNS_DISPATCH_HELD]; - isc_sockaddr_t localaddr_bound; - isc_socket_t *sock = NULL; - isc_result_t result = ISC_R_SUCCESS; - unsigned int nports; - in_port_t *ports = NULL; - - REQUIRE(sockp != NULL && *sockp == NULL); - - if (isc_sockaddr_getport(localaddr) != 0) { - /* Allow to reuse address for non-random ports. */ - result = open_socket(sockmgr, localaddr, - ISC_SOCKET_REUSEADDRESS, &sock, - dup_socket); - if (result == ISC_R_SUCCESS) { - *sockp = sock; - } - - return (result); - } - - /* - * If no port is specified, we first try to pick up a random - * port by ourselves. - */ - if (isc_sockaddr_pf(localaddr) == AF_INET) { - nports = mgr->nv4ports; - ports = mgr->v4ports; - } else { - nports = mgr->nv6ports; - ports = mgr->v6ports; - } - if (nports == 0) { - return (ISC_R_ADDRNOTAVAIL); - } - - localaddr_bound = *localaddr; - - for (i = 0; i < 1024; i++) { - in_port_t prt; - - prt = ports[isc_random_uniform(nports)]; - isc_sockaddr_setport(&localaddr_bound, prt); - result = open_socket(sockmgr, &localaddr_bound, 0, &sock, NULL); - /* - * If the port chosen is already in use or the OS has - * reserved it, try again. - */ - if (result == ISC_R_NOPERM || result == ISC_R_ADDRINUSE) { - continue; - } - disp->localport = prt; - *sockp = sock; - return (result); - } - - /* - * If this fails 1024 times, we then ask the kernel for - * help choosing one. - */ - memset(held, 0, sizeof(held)); - i = 0; - - for (j = 0; j < 0xffffU; j++) { - result = open_socket(sockmgr, localaddr, 0, &sock, NULL); - if (result != ISC_R_SUCCESS) { - goto end; - } else if (portavailable(mgr, sock, NULL)) { - break; - } - if (held[i] != NULL) { - isc_socket_detach(&held[i]); - } - held[i++] = sock; - sock = NULL; - if (i == DNS_DISPATCH_HELD) { - i = 0; - } - } - - if (j == 0xffffU) { - mgr_log(mgr, ISC_LOG_ERROR, - "avoid-v%s-udp-ports: unable to allocate " - "an available port", - isc_sockaddr_pf(localaddr) == AF_INET ? "4" : "6"); - result = ISC_R_FAILURE; - goto end; - } - *sockp = sock; - -end: - for (i = 0; i < DNS_DISPATCH_HELD; i++) { - if (held[i] != NULL) { - isc_socket_detach(&held[i]); - } - } - - return (result); -} - static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, unsigned int maxrequests, unsigned int attributes, - dns_dispatch_t **dispp, isc_socket_t *dup_socket) { + dns_dispatch_t **dispp) { isc_result_t result; dns_dispatch_t *disp = NULL; isc_socket_t *sock = NULL; + isc_sockaddr_t sa_any; int i = 0; /* @@ -2450,59 +2164,44 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, disp->socktype = isc_sockettype_udp; - if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0) { - result = get_udpsocket(mgr, disp, sockmgr, localaddr, &sock, - dup_socket); + /* + * For dispatches with a specified source address, we open a + * socket to make sure that address is available on the system, + * but we don't keep it open; sockets used for sending requests + * will be created later on demand. + */ + isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr)); + if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) { + result = open_socket(sockmgr, localaddr, 0, &sock, NULL); + if (sock != NULL) { + isc_socket_detach(&sock); + } if (result != ISC_R_SUCCESS) { goto deallocate_dispatch; } - - if (isc_log_wouldlog(dns_lctx, 90)) { - char addrbuf[ISC_SOCKADDR_FORMATSIZE]; - - isc_sockaddr_format(localaddr, addrbuf, - ISC_SOCKADDR_FORMATSIZE); - mgr_log(mgr, LVL(90), - "dispatch_createudp: created shared " - "UDP dispatch for %s with socket fd %d", - addrbuf, isc_socket_getfd(sock)); - } - } else { - isc_sockaddr_t sa_any; - - /* - * For dispatches using exclusive sockets with a specific - * source address, we only check if the specified address is - * available on the system. Query sockets will be created later - * on demand. - */ - isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr)); - if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) { - result = open_socket(sockmgr, localaddr, 0, &sock, - NULL); - if (sock != NULL) { - isc_socket_detach(&sock); - } - if (result != ISC_R_SUCCESS) { - goto deallocate_dispatch; - } - } - - 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]); - } } + + 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)) { + char addrbuf[ISC_SOCKADDR_FORMATSIZE]; + + isc_sockaddr_format(localaddr, addrbuf, + ISC_SOCKADDR_FORMATSIZE); + mgr_log(mgr, LVL(90), + "dispatch_createudp: created UDP dispatch for %s", + addrbuf); + } + disp->socket = sock; disp->local = *localaddr; + disp->ntasks = MAX_INTERNAL_TASKS; - if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { - disp->ntasks = MAX_INTERNAL_TASKS; - } else { - disp->ntasks = 1; - } for (i = 0; i < disp->ntasks; i++) { disp->task[i] = NULL; result = isc_task_create(taskmgr, 0, &disp->task[i]); @@ -2565,13 +2264,6 @@ dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp) { *dispp = disp; } -/* - * It is important to lock the manager while we are deleting the dispatch, - * since dns_dispatch_getudp will call dispatch_find, which returns to - * the caller a dispatch but does not attach to it until later. _getudp - * locks the manager, however, so locking it here will keep us from attaching - * to a dispatcher that is in the process of going away. - */ void dns_dispatch_detach(dns_dispatch_t **dispp) { dns_dispatch_t *disp = NULL; @@ -2629,9 +2321,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, REQUIRE(dest != NULL); REQUIRE(resp != NULL && *resp == NULL); REQUIRE(idp != NULL); - if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { - REQUIRE(sockmgr != NULL); - } + REQUIRE(disp->socktype == isc_sockettype_tcp || sockmgr != NULL); LOCK(&disp->lock); @@ -2645,7 +2335,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, return (ISC_R_QUOTA); } - if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0 && + if (disp->socktype == isc_sockettype_udp && disp->nsockets > DNS_DISPATCH_SOCKSQUOTA) { dispsocket_t *oldestsocket = NULL; @@ -2681,7 +2371,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, qid = DNS_QID(disp); - if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { + if (disp->socktype == isc_sockettype_udp) { /* * Get a separate UDP socket with a random port number. */ @@ -2692,8 +2382,6 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, inc_stats(disp->mgr, dns_resstatscounter_dispsockfail); return (result); } - } else { - localport = disp->localport; } /* @@ -2793,13 +2481,11 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, UNLOCK(&disp->lock); + INSIST(disp->socktype == isc_sockettype_tcp || res->dispsocket != NULL); + *idp = id; *resp = res; - if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { - INSIST(res->dispsocket != NULL); - } - return (ISC_R_SUCCESS); } @@ -3046,7 +2732,9 @@ isc_socket_t * dns_dispatch_getentrysocket(dns_dispentry_t *resp) { REQUIRE(VALID_RESPONSE(resp)); - if (resp->dispsocket != NULL) { + if (resp->disp->socktype == isc_sockettype_tcp) { + return (resp->disp->socket); + } else if (resp->dispsocket != NULL) { return (resp->dispsocket->socket); } else { return (NULL); @@ -3080,8 +2768,6 @@ void dns_dispatch_changeattributes(dns_dispatch_t *disp, unsigned int attributes, unsigned int mask) { REQUIRE(VALID_DISPATCH(disp)); - /* Exclusive attribute can only be set on creation */ - REQUIRE((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0); LOCK(&disp->lock); @@ -3140,10 +2826,10 @@ dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr, LOCK(&mgr->lock); for (i = 1; i < n; i++) { dset->dispatches[i] = NULL; - result = dispatch_createudp( - mgr, sockmgr, taskmgr, &source->local, - source->maxrequests, source->attributes, - &dset->dispatches[i], source->socket); + result = dispatch_createudp(mgr, sockmgr, taskmgr, + &source->local, source->maxrequests, + source->attributes, + &dset->dispatches[i]); if (result != ISC_R_SUCCESS) { goto fail; } @@ -3170,19 +2856,6 @@ fail: return (result); } -void -dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task) { - int i; - - REQUIRE(dset != NULL); - - for (i = 0; i < dset->ndisp; i++) { - isc_socket_t *sock = NULL; - sock = dns_dispatch_getsocket(dset->dispatches[i]); - isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL); - } -} - void dns_dispatchset_destroy(dns_dispatchset_t **dsetp) { dns_dispatchset_t *dset = NULL; diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index ddedac07b5..e4fc0cc727 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -118,9 +118,6 @@ struct dns_dispatchset { * _MAKEQUERY * The dispatcher can be used to issue queries to other servers, and * accept replies from them. - * - * _EXCLUSIVE - * A separate socket will be used on-demand for each transaction. */ #define DNS_DISPATCHATTR_PRIVATE 0x00000001U #define DNS_DISPATCHATTR_TCP 0x00000002U @@ -129,7 +126,6 @@ struct dns_dispatchset { #define DNS_DISPATCHATTR_IPV6 0x00000010U #define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U #define DNS_DISPATCHATTR_CONNECTED 0x00000080U -#define DNS_DISPATCHATTR_EXCLUSIVE 0x00000200U /*@}*/ /* @@ -214,14 +210,13 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats); */ isc_result_t -dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, - 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); +dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, + 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); /*%< - * Attach to existing dns_dispatch_t if one is found with dns_dispatchmgr_find, - * otherwise create a new UDP dispatch. + * Create a new UDP dispatch. * * Requires: *\li All pointer parameters be valid for their respective types. @@ -394,7 +389,7 @@ dns_dispatch_getentrysocket(dns_dispentry_t *resp); isc_socket_t * dns_dispatch_getsocket(dns_dispatch_t *disp); /*%< - * Return the socket associated with this dispatcher. + * Return the socket associated with dispatcher or dispatch entry. * * Requires: *\li disp is valid. @@ -477,12 +472,6 @@ dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr, *\li dsetp != NULL, *dsetp == NULL */ -void -dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task); -/*%< - * Cancel socket operations for the dispatches in 'dset'. - */ - void dns_dispatchset_destroy(dns_dispatchset_t **dsetp); /*%< diff --git a/lib/dns/request.c b/lib/dns/request.c index 953023a22e..a4ca668e18 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -415,13 +415,14 @@ static inline isc_result_t req_send(dns_request_t *request, isc_task_t *task, const isc_sockaddr_t *address) { isc_region_t r; - isc_socket_t *sock; - isc_socketevent_t *sendevent; + isc_socket_t *sock = NULL; + isc_socketevent_t *sendevent = NULL; isc_result_t result; req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request); REQUIRE(VALID_REQUEST(request)); + sock = req_getsocket(request); isc_buffer_usedregion(request->query, &r); /* @@ -596,8 +597,7 @@ find_udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, dns_dispatch_attach(disp, dispatchp); return (ISC_R_SUCCESS); } - attrs = 0; - attrs |= DNS_DISPATCHATTR_UDP; + attrs = DNS_DISPATCHATTR_UDP; switch (isc_sockaddr_pf(srcaddr)) { case PF_INET: attrs |= DNS_DISPATCHATTR_IPV4; @@ -610,10 +610,11 @@ find_udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, default: return (ISC_R_NOTIMPLEMENTED); } - return (dns_dispatch_getudp(requestmgr->dispatchmgr, - requestmgr->socketmgr, requestmgr->taskmgr, - srcaddr, 32768, 32768, 16411, 16433, attrs, - dispatchp)); + + return (dns_dispatch_createudp(requestmgr->dispatchmgr, + requestmgr->socketmgr, + requestmgr->taskmgr, srcaddr, 32768, + 32768, 16411, 16433, attrs, dispatchp)); } static isc_result_t @@ -1242,18 +1243,7 @@ dns_request_destroy(dns_request_t **requestp) { static isc_socket_t * req_getsocket(dns_request_t *request) { - unsigned int dispattr; - isc_socket_t *sock; - - dispattr = dns_dispatch_getattributes(request->dispatch); - if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { - INSIST(request->dispentry != NULL); - sock = dns_dispatch_getentrysocket(request->dispentry); - } else { - sock = dns_dispatch_getsocket(request->dispatch); - } - - return (sock); + return (dns_dispatch_getentrysocket(request->dispentry)); } static void @@ -1460,8 +1450,7 @@ req_destroy(dns_request_t *request) { */ static void req_cancel(dns_request_t *request) { - isc_socket_t *sock; - unsigned int dispattr; + isc_socket_t *sock = NULL; REQUIRE(VALID_REQUEST(request)); @@ -1475,16 +1464,10 @@ req_cancel(dns_request_t *request) { if (request->timer != NULL) { isc_timer_detach(&request->timer); } - dispattr = dns_dispatch_getattributes(request->dispatch); - sock = NULL; + if (DNS_REQUEST_CONNECTING(request) || DNS_REQUEST_SENDING(request)) { - if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { - if (request->dispentry != NULL) { - sock = dns_dispatch_getentrysocket( - request->dispentry); - } - } else { - sock = dns_dispatch_getsocket(request->dispatch); + if (request->dispentry != NULL) { + sock = dns_dispatch_getentrysocket(request->dispentry); } if (DNS_REQUEST_CONNECTING(request) && sock != NULL) { isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_CONNECT); diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index a47edf9ab2..66bebaaa6f 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -227,7 +227,6 @@ typedef struct query { isc_mem_t *mctx; dns_dispatchmgr_t *dispatchmgr; dns_dispatch_t *dispatch; - bool exclusivesocket; dns_adbaddrinfo_t *addrinfo; isc_socket_t *tcpsocket; isc_time_t start; @@ -507,11 +506,9 @@ struct dns_resolver { unsigned int options; dns_dispatchmgr_t *dispatchmgr; dns_dispatchset_t *dispatches4; - bool exclusivev4; dns_dispatchset_t *dispatches6; isc_dscp_t querydscp4; isc_dscp_t querydscp6; - bool exclusivev6; unsigned int nbuckets; fctxbucket_t *buckets; zonebucket_t *dbuckets; @@ -1434,7 +1431,6 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, isc_socket_cancel(query->tcpsocket, NULL, ISC_SOCKCANCEL_CONNECT); } else if (query->dispentry != NULL) { - INSIST(query->exclusivesocket); sock = dns_dispatch_getentrysocket(query->dispentry); if (sock != NULL) { isc_socket_cancel(sock, NULL, @@ -1446,7 +1442,7 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, /* * Cancel the pending send. */ - if (query->exclusivesocket && query->dispentry != NULL) { + if (query->dispentry != NULL) { sock = dns_dispatch_getentrysocket(query->dispentry); } else { sock = dns_dispatch_getsocket(query->dispatch); @@ -2074,7 +2070,6 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, * a dispatch for it here. Otherwise we use the resolver's * shared dispatch. */ - query->dispatchmgr = res->dispatchmgr; if (res->view->peers != NULL) { dns_peer_t *peer = NULL; isc_netaddr_t dstip; @@ -2160,7 +2155,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, result = ISC_R_NOTIMPLEMENTED; goto cleanup_query; } - result = dns_dispatch_getudp( + result = dns_dispatch_createudp( res->dispatchmgr, res->socketmgr, res->taskmgr, &addr, 20000, 32768, 16411, 16433, attrs, &query->dispatch); @@ -2173,14 +2168,12 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_dispatch_attach( dns_resolver_dispatchv4(res), &query->dispatch); - query->exclusivesocket = res->exclusivev4; dscp = dns_resolver_getquerydscp4(fctx->res); break; case PF_INET6: dns_dispatch_attach( dns_resolver_dispatchv6(res), &query->dispatch); - query->exclusivesocket = res->exclusivev6; dscp = dns_resolver_getquerydscp6(fctx->res); break; default: @@ -2364,11 +2357,7 @@ addr2buf(void *buf, const size_t bufsize, const isc_sockaddr_t *sockaddr) { static inline isc_socket_t * query2sock(const resquery_t *query) { - if (query->exclusivesocket) { - return (dns_dispatch_getentrysocket(query->dispentry)); - } else { - return (dns_dispatch_getsocket(query->dispatch)); - } + return (dns_dispatch_getentrysocket(query->dispentry)); } static inline size_t @@ -2864,15 +2853,12 @@ resquery_send(resquery_t *query) { */ if (!tcp) { address = &query->addrinfo->sockaddr; - if (query->exclusivesocket) { - result = isc_socket_connect(sock, address, task, - resquery_udpconnected, - query); - if (result != ISC_R_SUCCESS) { - goto cleanup_message; - } - query->connects++; + result = isc_socket_connect(sock, address, task, + resquery_udpconnected, query); + if (result != ISC_R_SUCCESS) { + goto cleanup_message; } + query->connects++; } isc_buffer_usedregion(buffer, &r); @@ -3011,17 +2997,16 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { * We are connected. Create a dispatcher and * send the query. */ - attrs = 0; - attrs |= DNS_DISPATCHATTR_TCP; - attrs |= DNS_DISPATCHATTR_PRIVATE; - attrs |= DNS_DISPATCHATTR_CONNECTED; + attrs = DNS_DISPATCHATTR_TCP | + DNS_DISPATCHATTR_PRIVATE | + DNS_DISPATCHATTR_CONNECTED | + DNS_DISPATCHATTR_MAKEQUERY; if (isc_sockaddr_pf(&query->addrinfo->sockaddr) == AF_INET) { attrs |= DNS_DISPATCHATTR_IPV4; } else { attrs |= DNS_DISPATCHATTR_IPV6; } - attrs |= DNS_DISPATCHATTR_MAKEQUERY; result = dns_dispatch_createtcp( query->dispatchmgr, query->tcpsocket, @@ -8129,17 +8114,15 @@ rctx_dispfail(respctx_t *rctx) { rctx->next_server = true; /* - * If this is a network error on an exclusive query - * socket, mark the server as bad so that we won't try - * it for this fetch again. Also adjust finish and - * no_response so that we penalize this address in SRTT - * adjustment later. + * If this is a network error, mark the server as bad so + * that we won't try it for this fetch again. Also adjust + * finish and no_response so that we penalize this address + * in SRTT adjustment later. */ - if (query->exclusivesocket && - (devent->result == ISC_R_HOSTUNREACH || - devent->result == ISC_R_NETUNREACH || - devent->result == ISC_R_CONNREFUSED || - devent->result == ISC_R_CANCELED)) + if (devent->result == ISC_R_HOSTUNREACH || + devent->result == ISC_R_NETUNREACH || + devent->result == ISC_R_CONNREFUSED || + devent->result == ISC_R_CANCELED) { rctx->broken_server = devent->result; rctx->broken_type = badns_unreachable; @@ -10275,7 +10258,6 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, unsigned int i, buckets_created = 0, dbuckets_created = 0; isc_task_t *task = NULL; char name[16]; - unsigned dispattr; /* * Create a resolver. @@ -10370,15 +10352,11 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, if (dispatchv4 != NULL) { dns_dispatchset_create(view->mctx, socketmgr, taskmgr, dispatchv4, &res->dispatches4, ndisp); - dispattr = dns_dispatch_getattributes(dispatchv4); - res->exclusivev4 = (dispattr & DNS_DISPATCHATTR_EXCLUSIVE); } if (dispatchv6 != NULL) { dns_dispatchset_create(view->mctx, socketmgr, taskmgr, dispatchv6, &res->dispatches6, ndisp); - dispattr = dns_dispatch_getattributes(dispatchv6); - res->exclusivev6 = (dispattr & DNS_DISPATCHATTR_EXCLUSIVE); } isc_mutex_init(&res->lock); @@ -10617,14 +10595,6 @@ dns_resolver_shutdown(dns_resolver_t *res) { { fctx_shutdown(fctx); } - if (res->dispatches4 != NULL && !res->exclusivev4) { - dns_dispatchset_cancelall(res->dispatches4, - res->buckets[i].task); - } - if (res->dispatches6 != NULL && !res->exclusivev6) { - dns_dispatchset_cancelall(res->dispatches6, - res->buckets[i].task); - } atomic_store(&res->buckets[i].exiting, true); if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) { INSIST(res->activebuckets > 0); diff --git a/lib/dns/tests/dispatch_test.c b/lib/dns/tests/dispatch_test.c index 5bc81a2cd5..fb79fcf40b 100644 --- a/lib/dns/tests/dispatch_test.c +++ b/lib/dns/tests/dispatch_test.c @@ -76,8 +76,8 @@ make_dispatchset(unsigned int ndisps) { isc_sockaddr_any(&any); attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP; - result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &any, 6, - 1024, 17, 19, attrs, &disp); + result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &any, + 6, 1024, 17, 19, attrs, &disp); if (result != ISC_R_SUCCESS) { return (result); } @@ -241,7 +241,7 @@ startit(isc_task_t *task, isc_event_t *event) { isc_result_t result; isc_socket_t *sock = NULL; - isc_socket_attach(dns_dispatch_getsocket(dispatch), &sock); + isc_socket_attach(dns_dispatch_getentrysocket(dispentry), &sock); result = isc_socket_sendto(sock, event->ev_arg, task, senddone, sock, &local, NULL); assert_int_equal(result, ISC_R_SUCCESS); @@ -274,8 +274,8 @@ dispatch_getnext(void **state) { ina.s_addr = htonl(INADDR_LOOPBACK); isc_sockaddr_fromin(&local, &ina, 0); attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP; - result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &local, 6, - 1024, 17, 19, attrs, &dispatch); + result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &local, + 6, 1024, 17, 19, attrs, &dispatch); assert_int_equal(result, ISC_R_SUCCESS); /* @@ -299,7 +299,7 @@ dispatch_getnext(void **state) { assert_int_equal(result, ISC_R_SUCCESS); result = dns_dispatch_addresponse(dispatch, 0, &local, task, response, - NULL, &id, &dispentry, NULL); + NULL, &id, &dispentry, socketmgr); assert_int_equal(result, ISC_R_SUCCESS); memset(message, 0, sizeof(message)); diff --git a/lib/dns/tests/resolver_test.c b/lib/dns/tests/resolver_test.c index b144e09f84..5b4b7e8b81 100644 --- a/lib/dns/tests/resolver_test.c +++ b/lib/dns/tests/resolver_test.c @@ -57,8 +57,8 @@ _setup(void **state) { assert_int_equal(result, ISC_R_SUCCESS); isc_sockaddr_any(&local); - result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &local, - 100, 100, 100, 500, 0, &dispatch); + result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &local, + 100, 100, 100, 500, 0, &dispatch); assert_int_equal(result, ISC_R_SUCCESS); return (0);