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().
This commit is contained in:
Evan Hunt 2020-12-16 01:32:06 -08:00 committed by Ondřej Surý
parent 300392ae2f
commit 5dcf55da03
13 changed files with 235 additions and 645 deletions

View file

@ -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;
}

View file

@ -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,

View file

@ -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();

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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;
}

View file

@ -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, &region, 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, &region, 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, &region, 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;

View file

@ -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);
/*%<

View file

@ -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);

View file

@ -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);

View file

@ -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));

View file

@ -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);