mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-29 13:38:26 +00:00
Dispatch API simplification
- Many dispatch attributes can be set implicitly instead of being passed in. we can infer whether to set DNS_DISPATCHATTR_TCP or _UDP from whether we're calling dns_dispatch_createtcp() or _createudp(). we can also infer DNS_DISPATCHATTR_IPV4 or _IPV6 from the addresses or the socket that were passed in. - We no longer use dup'd sockets in UDP dispatches, so the 'dup_socket' parameter has been removed from dns_dispatch_createudp(), along with the code implementing it. also removed isc_socket_dup() since it no longer has any callers. - The 'buffersize' parameter was ignored and has now been removed; buffersize is now fixed at 4096. - Maxbuffers and maxrequests don't need to be passed in on every call to dns_dispatch_createtcp() and _createudp(). In all current uses, the value for mgr->maxbuffers will either be raised once from its default of 20000 to 32768, or else left alone. (passing in a value lower than 20000 does not lower it.) there isn't enough difference between these values for there to be any need to configure this. The value for disp->maxrequests controls both the quota of concurrent requests for a dispatch and also the size of the dispatch socket memory pool. it's not clear that this quota is necessary at all. the memory pool size currently starts at 32768, but is sometimes lowered to 4096, which is definitely unnecessary. This commit sets both values permanently to 32768. - Previously TCP dispatches allocated their own separate QID table, which didn't incorporate a port table. this commit removes per-dispatch QID tables and shares the same table between all dispatches. since dispatches are created for each TCP socket, this may speed up the dispatch allocation process. there may be a slight increase in lock contention since all dispatches are sharing a single QID table, but since TCP sockets are used less often than UDP sockets (which were already sharing a QID table), it should not be a substantial change. - The dispatch port table was being used to determine whether a port was already in use; if so, then a UDP socket would be bound with REUSEADDR. this commit removes the port table, and always binds UDP sockets that way.
This commit is contained in:
parent
9fd375217d
commit
f439eb5d99
@ -160,10 +160,8 @@
|
||||
|
||||
#ifdef TUNE_LARGE
|
||||
#define RESOLVER_NTASKS_PERCPU 32
|
||||
#define UDPBUFFERS 32768
|
||||
#else
|
||||
#define RESOLVER_NTASKS_PERCPU 8
|
||||
#define UDPBUFFERS 4096
|
||||
#endif /* TUNE_LARGE */
|
||||
|
||||
/* RFC7828 defines timeout as 16-bit value specified in units of 100
|
||||
@ -1260,9 +1258,8 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af,
|
||||
isc_result_t result = ISC_R_FAILURE;
|
||||
dns_dispatch_t *disp = NULL;
|
||||
isc_sockaddr_t sa;
|
||||
unsigned int attrs;
|
||||
unsigned int attrs = 0;
|
||||
const cfg_obj_t *obj = NULL;
|
||||
unsigned int maxdispatchbuffers = UDPBUFFERS;
|
||||
isc_dscp_t dscp = -1;
|
||||
|
||||
switch (af) {
|
||||
@ -1308,15 +1305,6 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af,
|
||||
/*
|
||||
* Try to find a dispatcher that we can share.
|
||||
*/
|
||||
attrs = DNS_DISPATCHATTR_UDP;
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
attrs |= DNS_DISPATCHATTR_IPV4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
attrs |= DNS_DISPATCHATTR_IPV6;
|
||||
break;
|
||||
}
|
||||
if (isc_sockaddr_getport(&sa) != 0) {
|
||||
INSIST(obj != NULL);
|
||||
if (is_firstview) {
|
||||
@ -1327,9 +1315,8 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af,
|
||||
}
|
||||
}
|
||||
|
||||
result = dns_dispatch_createudp(
|
||||
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, attrs, &disp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_sockaddr_t any;
|
||||
char buf[ISC_SOCKADDR_FORMATSIZE];
|
||||
@ -10343,7 +10330,7 @@ named_add_reserved_dispatch(named_server_t *server,
|
||||
in_port_t port;
|
||||
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
isc_result_t result;
|
||||
unsigned int attrs;
|
||||
unsigned int attrs = 0;
|
||||
|
||||
REQUIRE(NAMED_SERVER_VALID(server));
|
||||
|
||||
@ -10370,22 +10357,8 @@ named_add_reserved_dispatch(named_server_t *server,
|
||||
dispatch->dispatchgen = server->dispatchgen;
|
||||
dispatch->dispatch = NULL;
|
||||
|
||||
attrs = DNS_DISPATCHATTR_UDP;
|
||||
switch (isc_sockaddr_pf(addr)) {
|
||||
case AF_INET:
|
||||
attrs |= DNS_DISPATCHATTR_IPV4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
attrs |= DNS_DISPATCHATTR_IPV6;
|
||||
break;
|
||||
default:
|
||||
result = ISC_R_NOTIMPLEMENTED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_socketmgr,
|
||||
named_g_taskmgr, &dispatch->addr,
|
||||
UDPBUFFERS, 32768, 16411, 16433, attrs,
|
||||
named_g_taskmgr, &dispatch->addr, attrs,
|
||||
&dispatch->dispatch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
|
@ -801,7 +801,6 @@ static void
|
||||
setup_system(void) {
|
||||
isc_result_t result;
|
||||
isc_sockaddr_t bind_any, bind_any6;
|
||||
unsigned int attrs;
|
||||
isc_sockaddrlist_t *nslist;
|
||||
isc_logconfig_t *logconfig = NULL;
|
||||
irs_resconf_t *resconf = NULL;
|
||||
@ -937,20 +936,16 @@ setup_system(void) {
|
||||
set_source_ports(dispatchmgr);
|
||||
|
||||
if (have_ipv6) {
|
||||
attrs = (DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV6);
|
||||
isc_sockaddr_any6(&bind_any6);
|
||||
result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
|
||||
&bind_any6, 4, 2, 3, 5, attrs,
|
||||
&dispatchv6);
|
||||
&bind_any6, 0, &dispatchv6);
|
||||
check_result(result, "dns_dispatch_createudp (v6)");
|
||||
}
|
||||
|
||||
if (have_ipv4) {
|
||||
attrs = (DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV4);
|
||||
isc_sockaddr_any(&bind_any);
|
||||
result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
|
||||
&bind_any, 4, 2, 3, 5, attrs,
|
||||
&dispatchv4);
|
||||
&bind_any, 0, &dispatchv4);
|
||||
check_result(result, "dns_dispatch_createudp (v4)");
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ static void
|
||||
recvresponse(isc_task_t *task, isc_event_t *event) {
|
||||
dns_requestevent_t *reqev = (dns_requestevent_t *)event;
|
||||
isc_result_t result;
|
||||
dns_message_t *query, *response;
|
||||
dns_message_t *query = NULL, *response = NULL;
|
||||
isc_buffer_t outbuf;
|
||||
char output[1024];
|
||||
|
||||
@ -86,7 +86,6 @@ recvresponse(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
query = reqev->ev_arg;
|
||||
|
||||
response = NULL;
|
||||
dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
|
||||
|
||||
result = dns_request_getresponse(reqev->request, response,
|
||||
@ -207,7 +206,6 @@ 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 *dispatchv4 = NULL;
|
||||
dns_view_t *view = NULL;
|
||||
uint16_t port = PORT;
|
||||
@ -275,10 +273,9 @@ main(int argc, char *argv[]) {
|
||||
RUNCHECK(isc_task_create(taskmgr, 0, &task));
|
||||
RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
|
||||
|
||||
attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV4;
|
||||
RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
|
||||
have_src ? &srcaddr : &bind_any, 4, 2,
|
||||
3, 5, attrs, &dispatchv4));
|
||||
have_src ? &srcaddr : &bind_any, 0,
|
||||
&dispatchv4));
|
||||
RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
|
||||
dispatchmgr, dispatchv4, NULL,
|
||||
&requestmgr));
|
||||
|
@ -56,20 +56,20 @@
|
||||
static char *ip_address = NULL;
|
||||
static int port = 0;
|
||||
|
||||
static dst_key_t *ourkey;
|
||||
static isc_mem_t *mctx;
|
||||
static dns_tsigkey_t *tsigkey, *initialkey;
|
||||
static dns_tsig_keyring_t *ring;
|
||||
static dst_key_t *ourkey = NULL;
|
||||
static isc_mem_t *mctx = NULL;
|
||||
static dns_tsigkey_t *tsigkey = NULL, *initialkey = NULL;
|
||||
static dns_tsig_keyring_t *ring = NULL;
|
||||
static unsigned char noncedata[16];
|
||||
static isc_buffer_t nonce;
|
||||
static dns_requestmgr_t *requestmgr;
|
||||
static dns_requestmgr_t *requestmgr = NULL;
|
||||
static const char *ownername_str = ".";
|
||||
|
||||
static void
|
||||
recvquery(isc_task_t *task, isc_event_t *event) {
|
||||
dns_requestevent_t *reqev = (dns_requestevent_t *)event;
|
||||
isc_result_t result;
|
||||
dns_message_t *query, *response;
|
||||
dns_message_t *query = NULL, *response = NULL;
|
||||
char keyname[256];
|
||||
isc_buffer_t keynamebuf;
|
||||
int type;
|
||||
@ -134,8 +134,8 @@ sendquery(isc_task_t *task, isc_event_t *event) {
|
||||
dns_fixedname_t ownername;
|
||||
isc_buffer_t namestr, keybuf;
|
||||
unsigned char keydata[9];
|
||||
dns_message_t *query;
|
||||
dns_request_t *request;
|
||||
dns_message_t *query = NULL;
|
||||
dns_request_t *request = NULL;
|
||||
static char keystr[] = "0123456789ab";
|
||||
|
||||
isc_event_free(&event);
|
||||
@ -166,14 +166,12 @@ sendquery(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
isc_buffer_usedregion(&keybuf, &r);
|
||||
|
||||
initialkey = NULL;
|
||||
result = dns_tsigkey_create(
|
||||
dns_fixedname_name(&keyname), DNS_TSIG_HMACMD5_NAME,
|
||||
isc_buffer_base(&keybuf), isc_buffer_usedlength(&keybuf), false,
|
||||
NULL, 0, 0, mctx, ring, &initialkey);
|
||||
CHECK("dns_tsigkey_create", result);
|
||||
|
||||
query = NULL;
|
||||
dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
|
||||
|
||||
result = dns_tkey_builddhquery(query, ourkey,
|
||||
@ -181,7 +179,6 @@ sendquery(isc_task_t *task, isc_event_t *event) {
|
||||
DNS_TSIG_HMACMD5_NAME, &nonce, 3600);
|
||||
CHECK("dns_tkey_builddhquery", result);
|
||||
|
||||
request = NULL;
|
||||
result = dns_request_create(requestmgr, query, &address,
|
||||
DNS_REQUESTOPT_TCP, initialkey, TIMEOUT,
|
||||
task, recvquery, query, &request);
|
||||
@ -196,7 +193,6 @@ main(int argc, char *argv[]) {
|
||||
isc_timermgr_t *timermgr = NULL;
|
||||
isc_socketmgr_t *socketmgr = NULL;
|
||||
isc_socket_t *sock = NULL;
|
||||
unsigned int attrs;
|
||||
isc_sockaddr_t bind_any;
|
||||
dns_dispatchmgr_t *dispatchmgr = NULL;
|
||||
dns_dispatch_t *dispatchv4 = NULL;
|
||||
@ -224,12 +220,9 @@ main(int argc, char *argv[]) {
|
||||
|
||||
dns_result_register();
|
||||
|
||||
mctx = NULL;
|
||||
isc_mem_debugging = ISC_MEM_DEBUGRECORD;
|
||||
isc_mem_create(&mctx);
|
||||
|
||||
log = NULL;
|
||||
logconfig = NULL;
|
||||
isc_log_create(mctx, &log, &logconfig);
|
||||
|
||||
RUNCHECK(dst_lib_init(mctx, NULL));
|
||||
@ -241,32 +234,24 @@ main(int argc, char *argv[]) {
|
||||
RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
|
||||
|
||||
isc_sockaddr_any(&bind_any);
|
||||
attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV4;
|
||||
RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
|
||||
&bind_any, 4, 2, 3, 5, attrs,
|
||||
&dispatchv4));
|
||||
requestmgr = NULL;
|
||||
&bind_any, 0, &dispatchv4));
|
||||
RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
|
||||
dispatchmgr, dispatchv4, NULL,
|
||||
&requestmgr));
|
||||
|
||||
ring = NULL;
|
||||
RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
|
||||
tctx = NULL;
|
||||
RUNCHECK(dns_tkeyctx_create(mctx, &tctx));
|
||||
|
||||
view = NULL;
|
||||
RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
|
||||
dns_view_setkeyring(view, ring);
|
||||
dns_tsigkeyring_detach(&ring);
|
||||
|
||||
sock = NULL;
|
||||
RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
|
||||
&sock));
|
||||
|
||||
RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL));
|
||||
|
||||
ourkey = NULL;
|
||||
type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY;
|
||||
result = dst_key_fromnamedfile(ourkeyname, NULL, type, mctx, &ourkey);
|
||||
CHECK("dst_key_fromnamedfile", result);
|
||||
|
@ -53,18 +53,18 @@
|
||||
|
||||
#define TIMEOUT 30
|
||||
|
||||
static char *ip_address;
|
||||
static char *ip_address = NULL;
|
||||
static int port;
|
||||
static isc_mem_t *mctx;
|
||||
static dns_tsigkey_t *tsigkey;
|
||||
static dns_tsig_keyring_t *ring;
|
||||
static dns_requestmgr_t *requestmgr;
|
||||
static isc_mem_t *mctx = NULL;
|
||||
static dns_tsigkey_t *tsigkey = NULL;
|
||||
static dns_tsig_keyring_t *ring = NULL;
|
||||
static dns_requestmgr_t *requestmgr = NULL;
|
||||
|
||||
static void
|
||||
recvquery(isc_task_t *task, isc_event_t *event) {
|
||||
dns_requestevent_t *reqev = (dns_requestevent_t *)event;
|
||||
isc_result_t result;
|
||||
dns_message_t *query, *response;
|
||||
dns_message_t *query = NULL, *response = NULL;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
@ -78,7 +78,6 @@ recvquery(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
query = reqev->ev_arg;
|
||||
|
||||
response = NULL;
|
||||
dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
|
||||
|
||||
result = dns_request_getresponse(reqev->request, response,
|
||||
@ -108,8 +107,8 @@ sendquery(isc_task_t *task, isc_event_t *event) {
|
||||
struct in_addr inaddr;
|
||||
isc_sockaddr_t address;
|
||||
isc_result_t result;
|
||||
dns_message_t *query;
|
||||
dns_request_t *request;
|
||||
dns_message_t *query = NULL;
|
||||
dns_request_t *request = NULL;
|
||||
|
||||
isc_event_free(&event);
|
||||
|
||||
@ -119,13 +118,11 @@ sendquery(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
isc_sockaddr_fromin(&address, &inaddr, port);
|
||||
|
||||
query = NULL;
|
||||
dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
|
||||
|
||||
result = dns_tkey_builddeletequery(query, tsigkey);
|
||||
CHECK("dns_tkey_builddeletequery", result);
|
||||
|
||||
request = NULL;
|
||||
result = dns_request_create(requestmgr, query, &address,
|
||||
DNS_REQUESTOPT_TCP, tsigkey, TIMEOUT, task,
|
||||
recvquery, query, &request);
|
||||
@ -140,7 +137,6 @@ main(int argc, char **argv) {
|
||||
isc_timermgr_t *timermgr = NULL;
|
||||
isc_socketmgr_t *socketmgr = NULL;
|
||||
isc_socket_t *sock = NULL;
|
||||
unsigned int attrs;
|
||||
isc_sockaddr_t bind_any;
|
||||
dns_dispatchmgr_t *dispatchmgr = NULL;
|
||||
dns_dispatch_t *dispatchv4 = NULL;
|
||||
@ -169,11 +165,8 @@ main(int argc, char **argv) {
|
||||
|
||||
dns_result_register();
|
||||
|
||||
mctx = NULL;
|
||||
isc_mem_create(&mctx);
|
||||
|
||||
log = NULL;
|
||||
logconfig = NULL;
|
||||
isc_log_create(mctx, &log, &logconfig);
|
||||
|
||||
RUNCHECK(dst_lib_init(mctx, NULL));
|
||||
@ -184,31 +177,23 @@ main(int argc, char **argv) {
|
||||
RUNCHECK(isc_task_create(taskmgr, 0, &task));
|
||||
RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
|
||||
isc_sockaddr_any(&bind_any);
|
||||
attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV4;
|
||||
RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
|
||||
&bind_any, 4, 2, 3, 5, attrs,
|
||||
&dispatchv4));
|
||||
requestmgr = NULL;
|
||||
&bind_any, 0, &dispatchv4));
|
||||
RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
|
||||
dispatchmgr, dispatchv4, NULL,
|
||||
&requestmgr));
|
||||
|
||||
ring = NULL;
|
||||
RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
|
||||
tctx = NULL;
|
||||
RUNCHECK(dns_tkeyctx_create(mctx, &tctx));
|
||||
|
||||
view = NULL;
|
||||
RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
|
||||
dns_view_setkeyring(view, ring);
|
||||
|
||||
sock = NULL;
|
||||
RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
|
||||
&sock));
|
||||
|
||||
RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL));
|
||||
|
||||
dstkey = NULL;
|
||||
type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY;
|
||||
result = dst_key_fromnamedfile(keyname, NULL, type, mctx, &dstkey);
|
||||
CHECK("dst_key_fromnamedfile", result);
|
||||
|
@ -2073,7 +2073,7 @@ main(int argc, char *argv[]) {
|
||||
dns_dispatchmgr_t *dispatchmgr = NULL;
|
||||
dns_dispatch_t *dispatchvx = NULL;
|
||||
dns_view_t *view = NULL;
|
||||
unsigned int attrs, i;
|
||||
unsigned int i;
|
||||
int ns;
|
||||
|
||||
RUNCHECK(isc_app_start());
|
||||
@ -2128,17 +2128,14 @@ main(int argc, char *argv[]) {
|
||||
RUNCHECK(isc_task_create(taskmgr, 0, &task));
|
||||
RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
|
||||
|
||||
attrs = DNS_DISPATCHATTR_UDP;
|
||||
if (have_ipv4) {
|
||||
isc_sockaddr_any(&bind_any);
|
||||
attrs |= DNS_DISPATCHATTR_IPV4;
|
||||
} else {
|
||||
isc_sockaddr_any6(&bind_any);
|
||||
attrs |= DNS_DISPATCHATTR_IPV6;
|
||||
}
|
||||
RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
|
||||
have_src ? &srcaddr : &bind_any, 100,
|
||||
100, 17, 19, attrs, &dispatchvx));
|
||||
have_src ? &srcaddr : &bind_any, 0,
|
||||
&dispatchvx));
|
||||
|
||||
RUNCHECK(dns_requestmgr_create(
|
||||
mctx, timermgr, socketmgr, taskmgr, dispatchmgr,
|
||||
|
@ -203,40 +203,18 @@ cleanup:
|
||||
static isc_result_t
|
||||
getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr,
|
||||
isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr,
|
||||
bool is_shared, dns_dispatch_t **dispp,
|
||||
const isc_sockaddr_t *localaddr) {
|
||||
unsigned int attrs;
|
||||
dns_dispatch_t **dispp, const isc_sockaddr_t *localaddr) {
|
||||
dns_dispatch_t *disp = NULL;
|
||||
unsigned maxbuffers, maxrequests, buckets, increment;
|
||||
isc_result_t result;
|
||||
isc_sockaddr_t anyaddr;
|
||||
|
||||
attrs = DNS_DISPATCHATTR_UDP;
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
attrs |= DNS_DISPATCHATTR_IPV4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
attrs |= DNS_DISPATCHATTR_IPV6;
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
}
|
||||
|
||||
if (localaddr == NULL) {
|
||||
isc_sockaddr_anyofpf(&anyaddr, family);
|
||||
localaddr = &anyaddr;
|
||||
}
|
||||
|
||||
maxbuffers = is_shared ? 1000 : 8;
|
||||
maxrequests = 32768;
|
||||
buckets = is_shared ? 16411 : 3;
|
||||
increment = is_shared ? 16433 : 5;
|
||||
|
||||
result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr,
|
||||
localaddr, maxbuffers, maxrequests,
|
||||
buckets, increment, attrs, &disp);
|
||||
localaddr, 0, &disp);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
*dispp = disp;
|
||||
}
|
||||
@ -334,7 +312,7 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
|
||||
client->dispatchv4 = NULL;
|
||||
if (localaddr4 != NULL || localaddr6 == NULL) {
|
||||
result = getudpdispatch(AF_INET, dispatchmgr, socketmgr,
|
||||
taskmgr, true, &dispatchv4, localaddr4);
|
||||
taskmgr, &dispatchv4, localaddr4);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
client->dispatchv4 = dispatchv4;
|
||||
}
|
||||
@ -343,7 +321,7 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
|
||||
client->dispatchv6 = NULL;
|
||||
if (localaddr6 != NULL || localaddr4 == NULL) {
|
||||
result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr,
|
||||
taskmgr, true, &dispatchv6, localaddr6);
|
||||
taskmgr, &dispatchv6, localaddr6);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
client->dispatchv6 = dispatchv6;
|
||||
}
|
||||
|
@ -43,9 +43,6 @@ typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
|
||||
typedef struct dispsocket dispsocket_t;
|
||||
typedef ISC_LIST(dispsocket_t) dispsocketlist_t;
|
||||
|
||||
typedef struct dispportentry dispportentry_t;
|
||||
typedef ISC_LIST(dispportentry_t) dispportlist_t;
|
||||
|
||||
typedef struct dns_qid {
|
||||
unsigned int magic;
|
||||
unsigned int qid_nbuckets; /*%< hash table size */
|
||||
@ -72,7 +69,6 @@ struct dns_dispatchmgr {
|
||||
isc_mutex_t buffer_lock;
|
||||
unsigned int buffers; /*%< allocated buffers */
|
||||
unsigned int buffersize; /*%< size of each buffer */
|
||||
unsigned int maxbuffers; /*%< max buffers */
|
||||
|
||||
isc_refcount_t irefs;
|
||||
|
||||
@ -101,8 +97,6 @@ struct dns_dispatchmgr {
|
||||
#define MGR_SHUTTINGDOWN 0x00000001U
|
||||
#define MGR_IS_SHUTTINGDOWN(l) (((l)->state & MGR_SHUTTINGDOWN) != 0)
|
||||
|
||||
#define IS_PRIVATE(d) (((d)->attributes & DNS_DISPATCHATTR_PRIVATE) != 0)
|
||||
|
||||
struct dns_dispentry {
|
||||
unsigned int magic;
|
||||
dns_dispatch_t *disp;
|
||||
@ -119,27 +113,6 @@ struct dns_dispentry {
|
||||
ISC_LINK(dns_dispentry_t) link;
|
||||
};
|
||||
|
||||
/*%
|
||||
* Maximum number of dispatch sockets that can be pooled for reuse. The
|
||||
* appropriate value may vary, but experiments have shown a busy caching server
|
||||
* may need more than 1000 sockets concurrently opened. The maximum allowable
|
||||
* number of dispatch sockets (per manager) will be set to the double of this
|
||||
* value.
|
||||
*/
|
||||
#ifndef DNS_DISPATCH_POOLSOCKS
|
||||
#define DNS_DISPATCH_POOLSOCKS 2048
|
||||
#endif /* ifndef DNS_DISPATCH_POOLSOCKS */
|
||||
|
||||
/*%
|
||||
* Quota to control the number of dispatch sockets. If a dispatch has more
|
||||
* than the quota of sockets, new queries will purge oldest ones, so that
|
||||
* a massive number of outstanding queries won't prevent subsequent queries
|
||||
* (especially if the older ones take longer time and result in timeout).
|
||||
*/
|
||||
#ifndef DNS_DISPATCH_SOCKSQUOTA
|
||||
#define DNS_DISPATCH_SOCKSQUOTA 3072
|
||||
#endif /* ifndef DNS_DISPATCH_SOCKSQUOTA */
|
||||
|
||||
/*%
|
||||
* Fixed UDP buffer size.
|
||||
*/
|
||||
@ -152,31 +125,14 @@ struct dispsocket {
|
||||
isc_socket_t *socket;
|
||||
dns_dispatch_t *disp;
|
||||
isc_sockaddr_t host;
|
||||
dispportentry_t *portentry;
|
||||
dns_dispentry_t *resp;
|
||||
isc_task_t *task;
|
||||
in_port_t port;
|
||||
ISC_LINK(dispsocket_t) link;
|
||||
unsigned int bucket;
|
||||
ISC_LINK(dispsocket_t) blink;
|
||||
};
|
||||
|
||||
/*%
|
||||
* A port table entry. We remember every port we first open in a table with a
|
||||
* reference counter so that we can 'reuse' the same port (with different
|
||||
* destination addresses) using the SO_REUSEADDR socket option.
|
||||
*/
|
||||
struct dispportentry {
|
||||
in_port_t port;
|
||||
isc_refcount_t refs;
|
||||
ISC_LINK(struct dispportentry) link;
|
||||
};
|
||||
|
||||
#ifndef DNS_DISPATCH_PORTTABLESIZE
|
||||
#define DNS_DISPATCH_PORTTABLESIZE 1024
|
||||
#endif /* ifndef DNS_DISPATCH_PORTTABLESIZE */
|
||||
|
||||
#define INVALID_BUCKET (0xffffdead)
|
||||
|
||||
/*%
|
||||
* Number of tasks for each dispatch that use separate sockets for different
|
||||
* transactions. This must be a power of 2 as it will divide 32 bit numbers
|
||||
@ -195,11 +151,10 @@ struct dns_dispatch {
|
||||
* 1st task (task[0]) for internal control events.
|
||||
*/
|
||||
isc_task_t *task[MAX_INTERNAL_TASKS];
|
||||
isc_socket_t *socket; /*%< isc socket attached to */
|
||||
isc_sockaddr_t local; /*%< local address */
|
||||
in_port_t localport; /*%< local UDP port */
|
||||
isc_sockaddr_t peer; /*%< peer address (TCP) */
|
||||
unsigned int maxrequests; /*%< max requests */
|
||||
isc_socket_t *socket; /*%< isc socket attached to */
|
||||
isc_sockaddr_t local; /*%< local address */
|
||||
in_port_t localport; /*%< local UDP port */
|
||||
isc_sockaddr_t peer; /*%< peer address (TCP) */
|
||||
isc_event_t *ctlevent;
|
||||
|
||||
isc_mem_t *sepool; /*%< pool for socket events */
|
||||
@ -214,8 +169,7 @@ struct dns_dispatch {
|
||||
isc_refcount_t refcount;
|
||||
dns_dispatchevent_t *failsafe_ev; /*%< failsafe cancel event */
|
||||
unsigned int shutting_down : 1, shutdown_out : 1, connected : 1,
|
||||
tcpmsg_valid : 1, recv_pending : 1; /*%< is a recv() pending? *
|
||||
*/
|
||||
tcpmsg_valid : 1, recv_pending : 1;
|
||||
isc_result_t shutdown_why;
|
||||
ISC_LIST(dispsocket_t) activesockets;
|
||||
ISC_LIST(dispsocket_t) inactivesockets;
|
||||
@ -223,8 +177,6 @@ struct dns_dispatch {
|
||||
unsigned int requests; /*%< how many requests we have */
|
||||
unsigned int tcpbuffers; /*%< allocated buffers */
|
||||
dns_tcpmsg_t tcpmsg; /*%< for tcp streams */
|
||||
dns_qid_t *qid;
|
||||
dispportlist_t *port_table; /*%< hold ports 'owned' by us */
|
||||
};
|
||||
|
||||
#define QID_MAGIC ISC_MAGIC('Q', 'i', 'd', ' ')
|
||||
@ -242,23 +194,65 @@ struct dns_dispatch {
|
||||
#define DNS_DISPATCHMGR_MAGIC ISC_MAGIC('D', 'M', 'g', 'r')
|
||||
#define VALID_DISPATCHMGR(e) ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC)
|
||||
|
||||
#define DNS_QID(disp) \
|
||||
((disp)->socktype == isc_sockettype_tcp) ? (disp)->qid \
|
||||
: (disp)->mgr->qid
|
||||
/*%
|
||||
* Maximum number of dispatch sockets that can be pooled for reuse. The
|
||||
* appropriate value may vary, but experiments have shown a busy caching server
|
||||
* may need more than 1000 sockets concurrently opened. The maximum allowable
|
||||
* number of dispatch sockets (per manager) will be set to the double of this
|
||||
* value.
|
||||
*/
|
||||
#ifndef DNS_DISPATCH_POOLSOCKS
|
||||
#define DNS_DISPATCH_POOLSOCKS 2048
|
||||
#endif /* ifndef DNS_DISPATCH_POOLSOCKS */
|
||||
|
||||
/*%
|
||||
* Locking a query port buffer is a bit tricky. We access the buffer without
|
||||
* locking until qid is created. Technically, there is a possibility of race
|
||||
* between the creation of qid and access to the port buffer; in practice,
|
||||
* however, this should be safe because qid isn't created until the first
|
||||
* dispatch is created and there should be no contending situation until then.
|
||||
* Quota to control the number of UDP dispatch sockets. If a dispatch has
|
||||
* more than the quota of sockets, new queries will purge oldest ones, so
|
||||
* that a massive number of outstanding queries won't prevent subsequent
|
||||
* queries (especially if the older ones take longer time and result in
|
||||
* timeout).
|
||||
*/
|
||||
#define PORTBUFLOCK(mgr) \
|
||||
if ((mgr)->qid != NULL) \
|
||||
LOCK(&((mgr)->qid->lock))
|
||||
#define PORTBUFUNLOCK(mgr) \
|
||||
if ((mgr)->qid != NULL) \
|
||||
UNLOCK((&(mgr)->qid->lock))
|
||||
#ifndef DNS_DISPATCH_SOCKSQUOTA
|
||||
#define DNS_DISPATCH_SOCKSQUOTA 3072
|
||||
#endif /* ifndef DNS_DISPATCH_SOCKSQUOTA */
|
||||
|
||||
/*%
|
||||
* Number of buffers available for all dispatches in the buffery memory
|
||||
* pool.
|
||||
*/
|
||||
#ifndef DNS_DISPATCH_MAXBUFFERS
|
||||
#define DNS_DISPATCH_MAXBUFFERS 32768
|
||||
#endif /* ifndef DNS_DISPATCH_MAXBUFFERS */
|
||||
|
||||
/*%
|
||||
* Number of dispatch sockets available for all dispatches in the
|
||||
* socket memory pool.
|
||||
*/
|
||||
#ifndef DNS_DISPATCH_MAXSOCKETS
|
||||
#define DNS_DISPATCH_MAXSOCKETS 32768
|
||||
#endif /* ifndef DNS_DISPATCH_MAXSOCKETS */
|
||||
|
||||
/*%
|
||||
* Quota to control the number of concurrent requests that can be handled
|
||||
* by each TCP dispatch. (UDP dispatches do not currently support socket
|
||||
* sharing.)
|
||||
*/
|
||||
#ifndef DNS_DISPATCH_MAXREQUESTS
|
||||
#define DNS_DISPATCH_MAXREQUESTS 32768
|
||||
#endif /* ifndef DNS_DISPATCH_MAXREQUESTS */
|
||||
|
||||
/*%
|
||||
* Number of buckets in the QID hash table, and the value to
|
||||
* increment the QID by when attempting to avoid collisions.
|
||||
* The number of buckets should be prime, and the increment
|
||||
* should be the next higher prime number.
|
||||
*/
|
||||
#ifndef DNS_QID_BUCKETS
|
||||
#define DNS_QID_BUCKETS 16411
|
||||
#endif /* ifndef DNS_QID_BUCKETS */
|
||||
#ifndef DNS_QID_INCREMENT
|
||||
#define DNS_QID_INCREMENT 16433
|
||||
#endif /* ifndef DNS_QID_INCREMENT */
|
||||
|
||||
/*
|
||||
* Statics.
|
||||
@ -301,21 +295,18 @@ dispatch_free(dns_dispatch_t **dispp);
|
||||
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);
|
||||
unsigned int attributes, dns_dispatch_t **dispp);
|
||||
static bool
|
||||
destroy_mgr_ok(dns_dispatchmgr_t *mgr);
|
||||
static void
|
||||
destroy_mgr(dns_dispatchmgr_t **mgrp);
|
||||
static isc_result_t
|
||||
qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
|
||||
unsigned int increment, dns_qid_t **qidp, bool needaddrtable);
|
||||
static void
|
||||
qid_allocate(dns_dispatchmgr_t *mgr, dns_qid_t **qidp);
|
||||
static void
|
||||
qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
|
||||
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);
|
||||
unsigned int options, isc_socket_t **sockp);
|
||||
|
||||
#define LVL(x) ISC_LOG_DEBUG(x)
|
||||
|
||||
@ -433,9 +424,7 @@ dns_hash(dns_qid_t *qid, const isc_sockaddr_t *dest, dns_messageid_t id,
|
||||
static dns_dispentry_t *
|
||||
linear_first(dns_qid_t *qid) {
|
||||
dns_dispentry_t *ret = NULL;
|
||||
unsigned int bucket;
|
||||
|
||||
bucket = 0;
|
||||
unsigned int bucket = 0;
|
||||
|
||||
while (bucket < qid->qid_nbuckets) {
|
||||
ret = ISC_LIST_HEAD(qid->qid_table[bucket]);
|
||||
@ -462,8 +451,7 @@ linear_next(dns_qid_t *qid, dns_dispentry_t *resp) {
|
||||
return (ret);
|
||||
}
|
||||
|
||||
bucket = resp->bucket;
|
||||
bucket++;
|
||||
bucket = resp->bucket + 1;
|
||||
while (bucket < qid->qid_nbuckets) {
|
||||
ret = ISC_LIST_HEAD(qid->qid_table[bucket]);
|
||||
if (ret != NULL) {
|
||||
@ -551,67 +539,6 @@ destroy_disp(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
}
|
||||
|
||||
/*%
|
||||
* Manipulate port table per dispatch: find an entry for a given port number,
|
||||
* create a new entry, and decrement a given entry with possible clean-up.
|
||||
*/
|
||||
static dispportentry_t *
|
||||
port_search(dns_dispatch_t *disp, in_port_t port) {
|
||||
dispportentry_t *portentry = NULL;
|
||||
|
||||
REQUIRE(disp->port_table != NULL);
|
||||
|
||||
portentry = ISC_LIST_HEAD(
|
||||
disp->port_table[port % DNS_DISPATCH_PORTTABLESIZE]);
|
||||
while (portentry != NULL) {
|
||||
if (portentry->port == port) {
|
||||
return (portentry);
|
||||
}
|
||||
portentry = ISC_LIST_NEXT(portentry, link);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static dispportentry_t *
|
||||
new_portentry(dns_dispatch_t *disp, in_port_t port) {
|
||||
dispportentry_t *portentry = NULL;
|
||||
dns_qid_t *qid = NULL;
|
||||
|
||||
REQUIRE(disp->port_table != NULL);
|
||||
|
||||
portentry = isc_mem_get(disp->mgr->mctx, sizeof(*portentry));
|
||||
portentry->port = port;
|
||||
isc_refcount_init(&portentry->refs, 1);
|
||||
ISC_LINK_INIT(portentry, link);
|
||||
qid = DNS_QID(disp);
|
||||
LOCK(&qid->lock);
|
||||
ISC_LIST_APPEND(disp->port_table[port % DNS_DISPATCH_PORTTABLESIZE],
|
||||
portentry, link);
|
||||
UNLOCK(&qid->lock);
|
||||
|
||||
return (portentry);
|
||||
}
|
||||
|
||||
/*%
|
||||
* The caller must hold the qid->lock.
|
||||
*/
|
||||
static void
|
||||
deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
|
||||
dispportentry_t *portentry = *portentryp;
|
||||
*portentryp = NULL;
|
||||
|
||||
REQUIRE(disp->port_table != NULL);
|
||||
REQUIRE(portentry != NULL);
|
||||
|
||||
if (isc_refcount_decrement(&portentry->refs) == 1) {
|
||||
ISC_LIST_UNLINK(disp->port_table[portentry->port %
|
||||
DNS_DISPATCH_PORTTABLESIZE],
|
||||
portentry, link);
|
||||
isc_mem_put(disp->mgr->mctx, portentry, sizeof(*portentry));
|
||||
}
|
||||
}
|
||||
|
||||
/*%
|
||||
* Find a dispsocket for socket address 'dest', and port number 'port'.
|
||||
* Return NULL if no such entry exists. Requires qid->lock to be held.
|
||||
@ -627,10 +554,8 @@ socket_search(dns_qid_t *qid, const isc_sockaddr_t *dest, in_port_t port,
|
||||
dispsock = ISC_LIST_HEAD(qid->sock_table[bucket]);
|
||||
|
||||
while (dispsock != NULL) {
|
||||
if (dispsock->portentry != NULL &&
|
||||
dispsock->portentry->port == port &&
|
||||
isc_sockaddr_equal(dest, &dispsock->host))
|
||||
{
|
||||
if (dispsock->port == port &&
|
||||
isc_sockaddr_equal(dest, &dispsock->host)) {
|
||||
return (dispsock);
|
||||
}
|
||||
dispsock = ISC_LIST_NEXT(dispsock, blink);
|
||||
@ -649,6 +574,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
|
||||
in_port_t *portp) {
|
||||
int i;
|
||||
dns_dispatchmgr_t *mgr = disp->mgr;
|
||||
dns_qid_t *qid = mgr->qid;
|
||||
isc_socket_t *sock = NULL;
|
||||
isc_result_t result = ISC_R_FAILURE;
|
||||
in_port_t port;
|
||||
@ -657,9 +583,6 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
|
||||
dispsocket_t *dispsock = NULL;
|
||||
unsigned int nports;
|
||||
in_port_t *ports = NULL;
|
||||
isc_socket_options_t bindoptions;
|
||||
dispportentry_t *portentry = NULL;
|
||||
dns_qid_t *qid = NULL;
|
||||
|
||||
if (isc_sockaddr_pf(&disp->local) == AF_INET) {
|
||||
nports = mgr->nv4ports;
|
||||
@ -696,7 +619,6 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
|
||||
* very likely to fail in bind(2) or connect(2).
|
||||
*/
|
||||
localaddr = disp->local;
|
||||
qid = DNS_QID(disp);
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
port = ports[isc_random_uniform(nports)];
|
||||
@ -709,20 +631,9 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
|
||||
continue;
|
||||
}
|
||||
UNLOCK(&qid->lock);
|
||||
bindoptions = 0;
|
||||
portentry = port_search(disp, port);
|
||||
|
||||
if (portentry != NULL) {
|
||||
bindoptions |= ISC_SOCKET_REUSEADDRESS;
|
||||
}
|
||||
result = open_socket(sockmgr, &localaddr, bindoptions, &sock,
|
||||
NULL);
|
||||
result = open_socket(sockmgr, &localaddr,
|
||||
ISC_SOCKET_REUSEADDRESS, &sock);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
if (portentry == NULL) {
|
||||
portentry = new_portentry(disp, port);
|
||||
} else {
|
||||
isc_refcount_increment(&portentry->refs);
|
||||
}
|
||||
break;
|
||||
} else if (result == ISC_R_NOPERM) {
|
||||
char buf[ISC_SOCKADDR_FORMATSIZE];
|
||||
@ -746,8 +657,9 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
|
||||
dispsock->socket = sock;
|
||||
dispsock->host = *dest;
|
||||
dispsock->bucket = bucket;
|
||||
dispsock->port = port;
|
||||
|
||||
LOCK(&qid->lock);
|
||||
dispsock->portentry = portentry;
|
||||
ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink);
|
||||
UNLOCK(&qid->lock);
|
||||
*dispsockp = dispsock;
|
||||
@ -762,7 +674,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
|
||||
static void
|
||||
destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
|
||||
dispsocket_t *dispsock = NULL;
|
||||
dns_qid_t *qid = DNS_QID(disp);
|
||||
dns_qid_t *qid = disp->mgr->qid;
|
||||
|
||||
/*
|
||||
* The dispatch must be locked.
|
||||
@ -775,11 +687,6 @@ destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
|
||||
|
||||
disp->nsockets--;
|
||||
dispsock->magic = 0;
|
||||
if (dispsock->portentry != NULL) {
|
||||
LOCK(&qid->lock);
|
||||
deref_portentry(disp, &dispsock->portentry);
|
||||
UNLOCK(&qid->lock);
|
||||
}
|
||||
if (dispsock->socket != NULL) {
|
||||
isc_socket_detach(&dispsock->socket);
|
||||
}
|
||||
@ -802,7 +709,7 @@ destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
|
||||
static void
|
||||
deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) {
|
||||
isc_result_t result;
|
||||
dns_qid_t *qid = DNS_QID(disp);
|
||||
dns_qid_t *qid = disp->mgr->qid;
|
||||
|
||||
/*
|
||||
* The dispatch must be locked.
|
||||
@ -813,12 +720,6 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) {
|
||||
dispsock->resp->dispsocket = NULL;
|
||||
}
|
||||
|
||||
INSIST(dispsock->portentry != NULL);
|
||||
|
||||
LOCK(&qid->lock);
|
||||
deref_portentry(disp, &dispsock->portentry);
|
||||
UNLOCK(&qid->lock);
|
||||
|
||||
if (disp->nsockets > DNS_DISPATCH_POOLSOCKS) {
|
||||
destroy_dispsocket(disp, &dispsock);
|
||||
} else {
|
||||
@ -896,7 +797,7 @@ free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {
|
||||
static void *
|
||||
allocate_udp_buffer(dns_dispatch_t *disp) {
|
||||
LOCK(&disp->mgr->buffer_lock);
|
||||
if (disp->mgr->buffers >= disp->mgr->maxbuffers) {
|
||||
if (disp->mgr->buffers >= DNS_DISPATCH_MAXBUFFERS) {
|
||||
UNLOCK(&disp->mgr->buffer_lock);
|
||||
return (NULL);
|
||||
}
|
||||
@ -1238,7 +1139,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
|
||||
|
||||
REQUIRE(VALID_DISPATCH(disp));
|
||||
|
||||
qid = disp->qid;
|
||||
qid = disp->mgr->qid;
|
||||
|
||||
LOCK(&disp->lock);
|
||||
|
||||
@ -1512,8 +1413,7 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
|
||||
|
||||
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) {
|
||||
unsigned int options, isc_socket_t **sockp) {
|
||||
isc_socket_t *sock = NULL;
|
||||
isc_result_t result;
|
||||
|
||||
@ -1523,15 +1423,6 @@ open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
} else if (dup_socket != NULL && !isc_socket_hasreuseport()) {
|
||||
result = isc_socket_dup(dup_socket, &sock);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_socket_setname(sock, "dispatcher", NULL);
|
||||
*sockp = sock;
|
||||
return (ISC_R_SUCCESS);
|
||||
} else {
|
||||
result = isc_socket_create(mgr, isc_sockaddr_pf(local),
|
||||
isc_sockettype_udp, &sock);
|
||||
@ -1601,7 +1492,6 @@ setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
|
||||
} while (p++ < 65535);
|
||||
INSIST(i4 == nv4ports && i6 == nv6ports);
|
||||
|
||||
PORTBUFLOCK(mgr);
|
||||
if (mgr->v4ports != NULL) {
|
||||
isc_mem_put(mgr->mctx, mgr->v4ports,
|
||||
mgr->nv4ports * sizeof(in_port_t));
|
||||
@ -1615,7 +1505,6 @@ setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
|
||||
}
|
||||
mgr->v6ports = v6ports;
|
||||
mgr->nv6ports = nv6ports;
|
||||
PORTBUFUNLOCK(mgr);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
@ -1634,7 +1523,7 @@ dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp) {
|
||||
REQUIRE(mgrp != NULL && *mgrp == NULL);
|
||||
|
||||
mgr = isc_mem_get(mctx, sizeof(dns_dispatchmgr_t));
|
||||
*mgr = (dns_dispatchmgr_t){ .maxbuffers = 20000 };
|
||||
*mgr = (dns_dispatchmgr_t){ 0 };
|
||||
|
||||
isc_mem_attach(mctx, &mgr->mctx);
|
||||
|
||||
@ -1653,6 +1542,7 @@ dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp) {
|
||||
isc_portset_destroy(mctx, &v4portset);
|
||||
isc_portset_destroy(mctx, &v6portset);
|
||||
|
||||
qid_allocate(mgr, &mgr->qid);
|
||||
mgr->magic = DNS_DISPATCHMGR_MAGIC;
|
||||
|
||||
*mgrp = mgr;
|
||||
@ -1681,60 +1571,6 @@ dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
|
||||
return (setavailports(mgr, v4portset, v6portset));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
dispatchmgr_setudp(dns_dispatchmgr_t *mgr, unsigned int maxbuffers,
|
||||
unsigned int maxrequests, unsigned int buckets,
|
||||
unsigned int increment) {
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(VALID_DISPATCHMGR(mgr));
|
||||
REQUIRE(maxbuffers > 0);
|
||||
REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
|
||||
REQUIRE(increment > buckets);
|
||||
UNUSED(maxrequests);
|
||||
|
||||
/*
|
||||
* Keep some number of items around. This should be a config
|
||||
* option. For now, keep 8, but later keep at least two even
|
||||
* if the caller wants less. This allows us to ensure certain
|
||||
* things, like an event can be "freed" and the next allocation
|
||||
* will always succeed.
|
||||
*
|
||||
* Note that if limits are placed on anything here, we use one
|
||||
* event internally, so the actual limit should be "wanted + 1."
|
||||
*
|
||||
* XXXMLG
|
||||
*/
|
||||
|
||||
if (maxbuffers < 8) {
|
||||
maxbuffers = 8;
|
||||
}
|
||||
|
||||
/* Adjust buffer pool if needed
|
||||
*
|
||||
* We only increase maxbuffers to avoid accidental buffer
|
||||
* shortage. Ideally we'd separate the manager-wide maximum
|
||||
* from per-dispatch limits and respect the latter within the
|
||||
* global limit. But at this moment that's deemed to be
|
||||
* overkilling and isn't worth additional implementation
|
||||
* complexity.
|
||||
*/
|
||||
LOCK(&mgr->buffer_lock);
|
||||
if (maxbuffers > mgr->maxbuffers) {
|
||||
mgr->maxbuffers = maxbuffers;
|
||||
}
|
||||
UNLOCK(&mgr->buffer_lock);
|
||||
|
||||
if (mgr->qid == NULL) {
|
||||
result = qid_allocate(mgr, buckets, increment, &mgr->qid, true);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) {
|
||||
dns_dispatchmgr_t *mgr = NULL;
|
||||
@ -1767,42 +1603,31 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats) {
|
||||
isc_stats_attach(stats, &mgr->stats);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
|
||||
unsigned int increment, dns_qid_t **qidp, bool needsocktable) {
|
||||
static void
|
||||
qid_allocate(dns_dispatchmgr_t *mgr, dns_qid_t **qidp) {
|
||||
dns_qid_t *qid = NULL;
|
||||
unsigned int i;
|
||||
|
||||
REQUIRE(VALID_DISPATCHMGR(mgr));
|
||||
REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
|
||||
REQUIRE(increment > buckets);
|
||||
REQUIRE(qidp != NULL && *qidp == NULL);
|
||||
|
||||
qid = isc_mem_get(mgr->mctx, sizeof(*qid));
|
||||
*qid = (dns_qid_t){ .qid_nbuckets = DNS_QID_BUCKETS,
|
||||
.qid_increment = DNS_QID_INCREMENT };
|
||||
|
||||
qid->qid_table = isc_mem_get(mgr->mctx,
|
||||
buckets * sizeof(dns_displist_t));
|
||||
|
||||
qid->sock_table = NULL;
|
||||
if (needsocktable) {
|
||||
qid->sock_table = isc_mem_get(
|
||||
mgr->mctx, buckets * sizeof(dispsocketlist_t));
|
||||
}
|
||||
DNS_QID_BUCKETS * sizeof(dns_displist_t));
|
||||
qid->sock_table = isc_mem_get(
|
||||
mgr->mctx, DNS_QID_BUCKETS * sizeof(dispsocketlist_t));
|
||||
|
||||
isc_mutex_init(&qid->lock);
|
||||
|
||||
for (i = 0; i < buckets; i++) {
|
||||
for (i = 0; i < qid->qid_nbuckets; i++) {
|
||||
ISC_LIST_INIT(qid->qid_table[i]);
|
||||
if (qid->sock_table != NULL) {
|
||||
ISC_LIST_INIT(qid->sock_table[i]);
|
||||
}
|
||||
ISC_LIST_INIT(qid->sock_table[i]);
|
||||
}
|
||||
|
||||
qid->qid_nbuckets = buckets;
|
||||
qid->qid_increment = increment;
|
||||
qid->magic = QID_MAGIC;
|
||||
*qidp = qid;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1818,10 +1643,8 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) {
|
||||
qid->magic = 0;
|
||||
isc_mem_put(mctx, qid->qid_table,
|
||||
qid->qid_nbuckets * sizeof(dns_displist_t));
|
||||
if (qid->sock_table != NULL) {
|
||||
isc_mem_put(mctx, qid->sock_table,
|
||||
qid->qid_nbuckets * sizeof(dispsocketlist_t));
|
||||
}
|
||||
isc_mem_put(mctx, qid->sock_table,
|
||||
qid->qid_nbuckets * sizeof(dispsocketlist_t));
|
||||
isc_mutex_destroy(&qid->lock);
|
||||
isc_mem_put(mctx, qid, sizeof(*qid));
|
||||
}
|
||||
@ -1830,8 +1653,7 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) {
|
||||
* Allocate and set important limits.
|
||||
*/
|
||||
static isc_result_t
|
||||
dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
|
||||
dns_dispatch_t **dispp) {
|
||||
dispatch_allocate(dns_dispatchmgr_t *mgr, dns_dispatch_t **dispp) {
|
||||
dns_dispatch_t *disp = NULL;
|
||||
|
||||
REQUIRE(VALID_DISPATCHMGR(mgr));
|
||||
@ -1846,7 +1668,6 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
|
||||
isc_refcount_increment0(&mgr->irefs);
|
||||
|
||||
*disp = (dns_dispatch_t){ .mgr = mgr,
|
||||
.maxrequests = maxrequests,
|
||||
.shutdown_why = ISC_R_UNEXPECTED };
|
||||
isc_refcount_init(&disp->refcount, 1);
|
||||
ISC_LINK_INIT(disp, link);
|
||||
@ -1891,19 +1712,6 @@ dispatch_free(dns_dispatch_t **dispp) {
|
||||
isc_mem_put(mgr->mctx, disp->failsafe_ev, sizeof(*disp->failsafe_ev));
|
||||
disp->failsafe_ev = NULL;
|
||||
|
||||
if (disp->qid != NULL) {
|
||||
qid_destroy(mgr->mctx, &disp->qid);
|
||||
}
|
||||
|
||||
if (disp->port_table != NULL) {
|
||||
for (int i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++) {
|
||||
INSIST(ISC_LIST_EMPTY(disp->port_table[i]));
|
||||
}
|
||||
isc_mem_put(mgr->mctx, disp->port_table,
|
||||
sizeof(disp->port_table[0]) *
|
||||
DNS_DISPATCH_PORTTABLESIZE);
|
||||
}
|
||||
|
||||
disp->mgr = NULL;
|
||||
isc_mutex_destroy(&disp->lock);
|
||||
disp->magic = 0;
|
||||
@ -1914,52 +1722,34 @@ dispatch_free(dns_dispatch_t **dispp) {
|
||||
isc_result_t
|
||||
dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
|
||||
isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
|
||||
const isc_sockaddr_t *destaddr, unsigned int buffersize,
|
||||
unsigned int maxbuffers, unsigned int maxrequests,
|
||||
unsigned int buckets, unsigned int increment,
|
||||
unsigned int attributes, dns_dispatch_t **dispp) {
|
||||
const isc_sockaddr_t *destaddr, unsigned int attributes,
|
||||
dns_dispatch_t **dispp) {
|
||||
isc_result_t result;
|
||||
dns_dispatch_t *disp = NULL;
|
||||
|
||||
UNUSED(maxbuffers);
|
||||
UNUSED(buffersize);
|
||||
int pf;
|
||||
|
||||
REQUIRE(VALID_DISPATCHMGR(mgr));
|
||||
REQUIRE(isc_socket_gettype(sock) == isc_sockettype_tcp);
|
||||
REQUIRE((attributes & DNS_DISPATCHATTR_TCP) != 0);
|
||||
REQUIRE((attributes & DNS_DISPATCHATTR_UDP) == 0);
|
||||
|
||||
if (destaddr == NULL) {
|
||||
attributes |= DNS_DISPATCHATTR_PRIVATE; /* XXXMLG */
|
||||
}
|
||||
attributes |= DNS_DISPATCHATTR_TCP;
|
||||
attributes &= ~DNS_DISPATCHATTR_UDP;
|
||||
|
||||
LOCK(&mgr->lock);
|
||||
|
||||
/*
|
||||
* dispatch_allocate() checks mgr for us.
|
||||
* qid_allocate() checks buckets and increment for us.
|
||||
*/
|
||||
disp = NULL;
|
||||
result = dispatch_allocate(mgr, maxrequests, &disp);
|
||||
result = dispatch_allocate(mgr, &disp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNLOCK(&mgr->lock);
|
||||
return (result);
|
||||
}
|
||||
|
||||
result = qid_allocate(mgr, buckets, increment, &disp->qid, false);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto deallocate_dispatch;
|
||||
}
|
||||
|
||||
disp->socktype = isc_sockettype_tcp;
|
||||
disp->socket = NULL;
|
||||
isc_socket_attach(sock, &disp->socket);
|
||||
|
||||
disp->ntasks = 1;
|
||||
disp->task[0] = NULL;
|
||||
result = isc_task_create(taskmgr, 50, &disp->task[0]);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto kill_socket;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
disp->ctlevent =
|
||||
@ -1971,17 +1761,18 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
|
||||
dns_tcpmsg_init(mgr->mctx, disp->socket, &disp->tcpmsg);
|
||||
disp->tcpmsg_valid = 1;
|
||||
|
||||
disp->attributes = attributes;
|
||||
|
||||
if (destaddr == NULL) {
|
||||
(void)isc_socket_getpeername(sock, &disp->peer);
|
||||
attributes |= DNS_DISPATCHATTR_PRIVATE;
|
||||
} else {
|
||||
disp->peer = *destaddr;
|
||||
}
|
||||
|
||||
pf = isc_sockaddr_pf(&disp->peer);
|
||||
|
||||
if (localaddr == NULL) {
|
||||
if (destaddr != NULL) {
|
||||
switch (isc_sockaddr_pf(destaddr)) {
|
||||
switch (pf) {
|
||||
case AF_INET:
|
||||
isc_sockaddr_any(&disp->local);
|
||||
break;
|
||||
@ -1996,6 +1787,22 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
|
||||
disp->local = *localaddr;
|
||||
}
|
||||
|
||||
switch (pf) {
|
||||
case PF_INET:
|
||||
attributes |= DNS_DISPATCHATTR_IPV4;
|
||||
break;
|
||||
|
||||
case PF_INET6:
|
||||
attributes |= DNS_DISPATCHATTR_IPV6;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = ISC_R_NOTIMPLEMENTED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
disp->attributes = attributes;
|
||||
|
||||
/*
|
||||
* Append it to the dispatcher list.
|
||||
*/
|
||||
@ -2012,9 +1819,8 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
kill_socket:
|
||||
cleanup:
|
||||
isc_socket_detach(&disp->socket);
|
||||
deallocate_dispatch:
|
||||
dispatch_free(&disp);
|
||||
|
||||
UNLOCK(&mgr->lock);
|
||||
@ -2108,8 +1914,6 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr,
|
||||
isc_result_t
|
||||
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;
|
||||
@ -2118,21 +1922,14 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
REQUIRE(sockmgr != NULL);
|
||||
REQUIRE(localaddr != NULL);
|
||||
REQUIRE(taskmgr != NULL);
|
||||
REQUIRE(maxbuffers > 0);
|
||||
REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
|
||||
REQUIRE(increment > buckets);
|
||||
REQUIRE(dispp != NULL && *dispp == NULL);
|
||||
REQUIRE((attributes & DNS_DISPATCHATTR_TCP) == 0);
|
||||
|
||||
result = dispatchmgr_setudp(mgr, maxbuffers, maxrequests, buckets,
|
||||
increment);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
attributes |= DNS_DISPATCHATTR_UDP;
|
||||
attributes &= ~DNS_DISPATCHATTR_TCP;
|
||||
|
||||
LOCK(&mgr->lock);
|
||||
result = dispatch_createudp(mgr, sockmgr, taskmgr, localaddr,
|
||||
maxrequests, attributes, &disp);
|
||||
attributes, &disp);
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
*dispp = disp;
|
||||
@ -2145,23 +1942,24 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
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) {
|
||||
unsigned int attributes, 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;
|
||||
int pf, i = 0;
|
||||
|
||||
/*
|
||||
* dispatch_allocate() checks mgr for us.
|
||||
*/
|
||||
disp = NULL;
|
||||
result = dispatch_allocate(mgr, maxrequests, &disp);
|
||||
result = dispatch_allocate(mgr, &disp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
pf = isc_sockaddr_pf(localaddr);
|
||||
|
||||
disp->socktype = isc_sockettype_udp;
|
||||
|
||||
/*
|
||||
@ -2170,9 +1968,9 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
* but we don't keep it open; sockets used for sending requests
|
||||
* will be created later on demand.
|
||||
*/
|
||||
isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr));
|
||||
isc_sockaddr_anyofpf(&sa_any, pf);
|
||||
if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) {
|
||||
result = open_socket(sockmgr, localaddr, 0, &sock, NULL);
|
||||
result = open_socket(sockmgr, localaddr, 0, &sock);
|
||||
if (sock != NULL) {
|
||||
isc_socket_detach(&sock);
|
||||
}
|
||||
@ -2181,13 +1979,6 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
}
|
||||
}
|
||||
|
||||
disp->port_table = isc_mem_get(mgr->mctx,
|
||||
sizeof(disp->port_table[0]) *
|
||||
DNS_DISPATCH_PORTTABLESIZE);
|
||||
for (i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++) {
|
||||
ISC_LIST_INIT(disp->port_table[i]);
|
||||
}
|
||||
|
||||
if (isc_log_wouldlog(dns_lctx, 90)) {
|
||||
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
|
||||
@ -2225,6 +2016,21 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
|
||||
attributes &= ~DNS_DISPATCHATTR_TCP;
|
||||
attributes |= DNS_DISPATCHATTR_UDP;
|
||||
|
||||
switch (pf) {
|
||||
case PF_INET:
|
||||
attributes |= DNS_DISPATCHATTR_IPV4;
|
||||
break;
|
||||
|
||||
case PF_INET6:
|
||||
attributes |= DNS_DISPATCHATTR_IPV6;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = ISC_R_NOTIMPLEMENTED;
|
||||
goto kill_socket;
|
||||
}
|
||||
|
||||
disp->attributes = attributes;
|
||||
|
||||
/*
|
||||
@ -2330,11 +2136,13 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
|
||||
return (ISC_R_SHUTTINGDOWN);
|
||||
}
|
||||
|
||||
if (disp->requests >= disp->maxrequests) {
|
||||
if (disp->requests >= DNS_DISPATCH_MAXREQUESTS) {
|
||||
UNLOCK(&disp->lock);
|
||||
return (ISC_R_QUOTA);
|
||||
}
|
||||
|
||||
qid = disp->mgr->qid;
|
||||
|
||||
if (disp->socktype == isc_sockettype_udp &&
|
||||
disp->nsockets > DNS_DISPATCH_SOCKSQUOTA)
|
||||
{
|
||||
@ -2369,8 +2177,6 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
|
||||
ISC_LIST_APPEND(disp->activesockets, oldestsocket, link);
|
||||
}
|
||||
|
||||
qid = DNS_QID(disp);
|
||||
|
||||
if (disp->socktype == isc_sockettype_udp) {
|
||||
/*
|
||||
* Get a separate UDP socket with a random port number.
|
||||
@ -2440,7 +2246,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
|
||||
ISC_LIST_APPEND(qid->qid_table[bucket], res, link);
|
||||
UNLOCK(&qid->lock);
|
||||
|
||||
inc_stats(disp->mgr, (qid == disp->mgr->qid)
|
||||
inc_stats(disp->mgr, (disp->socktype == isc_sockettype_udp)
|
||||
? dns_resstatscounter_disprequdp
|
||||
: dns_resstatscounter_dispreqtcp);
|
||||
|
||||
@ -2463,7 +2269,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
|
||||
disp->requests--;
|
||||
|
||||
dec_stats(disp->mgr,
|
||||
(qid == disp->mgr->qid)
|
||||
(disp->socktype == isc_sockettype_udp)
|
||||
? dns_resstatscounter_disprequdp
|
||||
: dns_resstatscounter_dispreqtcp);
|
||||
|
||||
@ -2570,8 +2376,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
|
||||
REQUIRE(VALID_DISPATCH(disp));
|
||||
mgr = disp->mgr;
|
||||
REQUIRE(VALID_DISPATCHMGR(mgr));
|
||||
|
||||
qid = DNS_QID(disp);
|
||||
qid = mgr->qid;
|
||||
|
||||
if (sockevent != NULL) {
|
||||
REQUIRE(*sockevent != NULL);
|
||||
@ -2585,7 +2390,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
|
||||
|
||||
INSIST(disp->requests > 0);
|
||||
disp->requests--;
|
||||
dec_stats(disp->mgr, (qid == disp->mgr->qid)
|
||||
dec_stats(disp->mgr, (disp->socktype == isc_sockettype_udp)
|
||||
? dns_resstatscounter_disprequdp
|
||||
: dns_resstatscounter_dispreqtcp);
|
||||
|
||||
@ -2677,14 +2482,12 @@ static void
|
||||
do_cancel(dns_dispatch_t *disp) {
|
||||
dns_dispatchevent_t *ev = NULL;
|
||||
dns_dispentry_t *resp = NULL;
|
||||
dns_qid_t *qid = NULL;
|
||||
dns_qid_t *qid = disp->mgr->qid;
|
||||
|
||||
if (disp->shutdown_out == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
qid = DNS_QID(disp);
|
||||
|
||||
/*
|
||||
* Search for the first response handler without packets outstanding
|
||||
* unless a specific handler is given.
|
||||
@ -2827,8 +2630,7 @@ dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr,
|
||||
for (i = 1; i < n; i++) {
|
||||
dset->dispatches[i] = NULL;
|
||||
result = dispatch_createudp(mgr, sockmgr, taskmgr,
|
||||
&source->local, source->maxrequests,
|
||||
source->attributes,
|
||||
&source->local, source->attributes,
|
||||
&dset->dispatches[i]);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto fail;
|
||||
|
@ -207,8 +207,6 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats);
|
||||
isc_result_t
|
||||
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);
|
||||
/*%<
|
||||
* Create a new UDP dispatch.
|
||||
@ -218,16 +216,6 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
*
|
||||
*\li dispp != NULL && *disp == NULL
|
||||
*
|
||||
*\li 512 <= buffersize <= 64k
|
||||
*
|
||||
*\li maxbuffers > 0
|
||||
*
|
||||
*\li buckets < 2097169
|
||||
*
|
||||
*\li increment > buckets
|
||||
*
|
||||
*\li (attributes & DNS_DISPATCHATTR_TCP) == 0
|
||||
*
|
||||
* Returns:
|
||||
*\li ISC_R_SUCCESS -- success.
|
||||
*
|
||||
@ -237,25 +225,11 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
isc_result_t
|
||||
dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
|
||||
isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
|
||||
const isc_sockaddr_t *destaddr, unsigned int buffersize,
|
||||
unsigned int maxbuffers, unsigned int maxrequests,
|
||||
unsigned int buckets, unsigned int increment,
|
||||
unsigned int attributes, dns_dispatch_t **dispp);
|
||||
const isc_sockaddr_t *destaddr, unsigned int attributes,
|
||||
dns_dispatch_t **dispp);
|
||||
/*%<
|
||||
* Create a new dns_dispatch and attach it to the provided isc_socket_t.
|
||||
*
|
||||
* For all dispatches, "buffersize" is the maximum packet size we will
|
||||
* accept.
|
||||
*
|
||||
* "maxbuffers" and "maxrequests" control the number of buffers in the
|
||||
* overall system and the number of buffers which can be allocated to
|
||||
* requests.
|
||||
*
|
||||
* "buckets" is the number of buckets to use, and should be prime.
|
||||
*
|
||||
* "increment" is used in a collision avoidance function, and needs to be
|
||||
* a prime > buckets, and not 2.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li mgr is a valid dispatch manager.
|
||||
@ -264,19 +238,6 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
|
||||
*
|
||||
*\li task is a valid task that can be used internally to this dispatcher.
|
||||
*
|
||||
* \li 512 <= buffersize <= 64k
|
||||
*
|
||||
*\li maxbuffers > 0.
|
||||
*
|
||||
*\li maxrequests <= maxbuffers.
|
||||
*
|
||||
*\li buckets < 2097169 (the next prime after 65536 * 32)
|
||||
*
|
||||
*\li increment > buckets (and prime).
|
||||
*
|
||||
*\li attributes includes #DNS_DISPATCHATTR_TCP and does not include
|
||||
* #DNS_DISPATCHATTR_UDP.
|
||||
*
|
||||
* Returns:
|
||||
*\li ISC_R_SUCCESS -- success.
|
||||
*
|
||||
|
@ -119,8 +119,6 @@ static void
|
||||
req_response(isc_task_t *task, isc_event_t *event);
|
||||
static void
|
||||
req_timeout(isc_task_t *task, isc_event_t *event);
|
||||
static isc_socket_t *
|
||||
req_getsocket(dns_request_t *request);
|
||||
static void
|
||||
req_connected(isc_task_t *task, isc_event_t *event);
|
||||
static void
|
||||
@ -423,8 +421,9 @@ req_send(dns_request_t *request, isc_task_t *task,
|
||||
|
||||
REQUIRE(VALID_REQUEST(request));
|
||||
|
||||
sock = req_getsocket(request);
|
||||
sock = dns_dispatch_getentrysocket(request->dispentry);
|
||||
isc_buffer_usedregion(request->query, &r);
|
||||
|
||||
/*
|
||||
* We could connect the socket when we are using an exclusive dispatch
|
||||
* as we do in resolver.c, but we prefer implementation simplicity
|
||||
@ -456,29 +455,11 @@ new_request(isc_mem_t *mctx, dns_request_t **requestp) {
|
||||
dns_request_t *request;
|
||||
|
||||
request = isc_mem_get(mctx, sizeof(*request));
|
||||
|
||||
/*
|
||||
* Zero structure.
|
||||
*/
|
||||
request->magic = 0;
|
||||
request->mctx = NULL;
|
||||
request->flags = 0;
|
||||
*request = (dns_request_t){ .dscp = -1 };
|
||||
ISC_LINK_INIT(request, link);
|
||||
request->query = NULL;
|
||||
request->answer = NULL;
|
||||
request->event = NULL;
|
||||
request->dispatch = NULL;
|
||||
request->dispentry = NULL;
|
||||
request->timer = NULL;
|
||||
request->requestmgr = NULL;
|
||||
request->tsig = NULL;
|
||||
request->tsigkey = NULL;
|
||||
request->dscp = -1;
|
||||
ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL,
|
||||
DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL, NULL,
|
||||
NULL);
|
||||
request->canceling = false;
|
||||
request->udpcount = 0;
|
||||
|
||||
isc_mem_attach(mctx, &request->mctx);
|
||||
|
||||
@ -513,14 +494,12 @@ isblackholed(dns_dispatchmgr_t *dispatchmgr, const isc_sockaddr_t *destaddr) {
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
create_tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr,
|
||||
const isc_sockaddr_t *srcaddr,
|
||||
const isc_sockaddr_t *destaddr, isc_dscp_t dscp,
|
||||
bool *connected, dns_dispatch_t **dispatchp) {
|
||||
tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr,
|
||||
const isc_sockaddr_t *srcaddr, const isc_sockaddr_t *destaddr,
|
||||
isc_dscp_t dscp, bool *connected, dns_dispatch_t **dispatchp) {
|
||||
isc_result_t result;
|
||||
isc_socket_t *sock = NULL;
|
||||
isc_sockaddr_t src;
|
||||
unsigned int attrs;
|
||||
isc_sockaddr_t bind_any;
|
||||
|
||||
if (!newtcp) {
|
||||
@ -556,27 +535,20 @@ create_tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
attrs = DNS_DISPATCHATTR_TCP;
|
||||
if (isc_sockaddr_pf(destaddr) == AF_INET) {
|
||||
attrs |= DNS_DISPATCHATTR_IPV4;
|
||||
} else {
|
||||
attrs |= DNS_DISPATCHATTR_IPV6;
|
||||
}
|
||||
|
||||
isc_socket_dscp(sock, dscp);
|
||||
result = dns_dispatch_createtcp(
|
||||
requestmgr->dispatchmgr, sock, requestmgr->taskmgr, srcaddr,
|
||||
destaddr, 4096, 32768, 32768, 16411, 16433, attrs, dispatchp);
|
||||
result = dns_dispatch_createtcp(requestmgr->dispatchmgr, sock,
|
||||
requestmgr->taskmgr, srcaddr, destaddr,
|
||||
0, dispatchp);
|
||||
|
||||
cleanup:
|
||||
isc_socket_detach(&sock);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
find_udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr,
|
||||
const isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp) {
|
||||
udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr,
|
||||
const isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp) {
|
||||
dns_dispatch_t *disp = NULL;
|
||||
unsigned int attrs;
|
||||
|
||||
if (srcaddr == NULL) {
|
||||
switch (isc_sockaddr_pf(destaddr)) {
|
||||
@ -597,24 +569,10 @@ find_udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr,
|
||||
dns_dispatch_attach(disp, dispatchp);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
attrs = DNS_DISPATCHATTR_UDP;
|
||||
switch (isc_sockaddr_pf(srcaddr)) {
|
||||
case PF_INET:
|
||||
attrs |= DNS_DISPATCHATTR_IPV4;
|
||||
break;
|
||||
|
||||
case PF_INET6:
|
||||
attrs |= DNS_DISPATCHATTR_IPV6;
|
||||
break;
|
||||
|
||||
default:
|
||||
return (ISC_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
return (dns_dispatch_createudp(requestmgr->dispatchmgr,
|
||||
requestmgr->socketmgr,
|
||||
requestmgr->taskmgr, srcaddr, 32768,
|
||||
32768, 16411, 16433, attrs, dispatchp));
|
||||
return (dns_dispatch_createudp(
|
||||
requestmgr->dispatchmgr, requestmgr->socketmgr,
|
||||
requestmgr->taskmgr, srcaddr, 0, dispatchp));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
@ -624,12 +582,10 @@ get_dispatch(bool tcp, bool newtcp, dns_requestmgr_t *requestmgr,
|
||||
isc_result_t result;
|
||||
|
||||
if (tcp) {
|
||||
result = create_tcp_dispatch(newtcp, requestmgr, srcaddr,
|
||||
destaddr, dscp, connected,
|
||||
dispatchp);
|
||||
result = tcp_dispatch(newtcp, requestmgr, srcaddr, destaddr,
|
||||
dscp, connected, dispatchp);
|
||||
} else {
|
||||
result = find_udp_dispatch(requestmgr, srcaddr, destaddr,
|
||||
dispatchp);
|
||||
result = udp_dispatch(requestmgr, srcaddr, destaddr, dispatchp);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
@ -760,7 +716,7 @@ again:
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
sock = req_getsocket(request);
|
||||
sock = dns_dispatch_getentrysocket(request->dispentry);
|
||||
INSIST(sock != NULL);
|
||||
|
||||
isc_buffer_allocate(mctx, &request->query, r.length + (tcp ? 2 : 0));
|
||||
@ -931,7 +887,7 @@ use_tcp:
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
sock = req_getsocket(request);
|
||||
sock = dns_dispatch_getentrysocket(request->dispentry);
|
||||
INSIST(sock != NULL);
|
||||
|
||||
message->id = id;
|
||||
@ -1240,12 +1196,6 @@ dns_request_destroy(dns_request_t **requestp) {
|
||||
/***
|
||||
*** Private: request.
|
||||
***/
|
||||
|
||||
static isc_socket_t *
|
||||
req_getsocket(dns_request_t *request) {
|
||||
return (dns_dispatch_getentrysocket(request->dispentry));
|
||||
}
|
||||
|
||||
static void
|
||||
req_connected(isc_task_t *task, isc_event_t *event) {
|
||||
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
|
||||
|
@ -2140,15 +2140,11 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
||||
*/
|
||||
} else {
|
||||
if (have_addr) {
|
||||
unsigned int attrs;
|
||||
attrs = DNS_DISPATCHATTR_UDP;
|
||||
switch (isc_sockaddr_pf(&addr)) {
|
||||
case AF_INET:
|
||||
attrs |= DNS_DISPATCHATTR_IPV4;
|
||||
dscp = dns_resolver_getquerydscp4(fctx->res);
|
||||
break;
|
||||
case AF_INET6:
|
||||
attrs |= DNS_DISPATCHATTR_IPV6;
|
||||
dscp = dns_resolver_getquerydscp6(fctx->res);
|
||||
break;
|
||||
default:
|
||||
@ -2157,8 +2153,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
||||
}
|
||||
result = dns_dispatch_createudp(
|
||||
res->dispatchmgr, res->socketmgr, res->taskmgr,
|
||||
&addr, 20000, 32768, 16411, 16433, attrs,
|
||||
&query->dispatch);
|
||||
&addr, 0, &query->dispatch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_query;
|
||||
}
|
||||
@ -2941,7 +2936,6 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
|
||||
bool retry = false;
|
||||
isc_interval_t interval;
|
||||
isc_result_t result;
|
||||
unsigned int attrs;
|
||||
fetchctx_t *fctx;
|
||||
|
||||
REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
|
||||
@ -2970,6 +2964,8 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
|
||||
isc_socket_detach(&query->tcpsocket);
|
||||
resquery_destroy(&query);
|
||||
} else {
|
||||
int attrs = 0;
|
||||
|
||||
switch (sevent->result) {
|
||||
case ISC_R_SUCCESS:
|
||||
|
||||
@ -2997,20 +2993,11 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
|
||||
* We are connected. Create a dispatcher and
|
||||
* send the query.
|
||||
*/
|
||||
attrs = DNS_DISPATCHATTR_TCP |
|
||||
DNS_DISPATCHATTR_PRIVATE |
|
||||
DNS_DISPATCHATTR_CONNECTED;
|
||||
if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==
|
||||
AF_INET) {
|
||||
attrs |= DNS_DISPATCHATTR_IPV4;
|
||||
} else {
|
||||
attrs |= DNS_DISPATCHATTR_IPV6;
|
||||
}
|
||||
|
||||
attrs = DNS_DISPATCHATTR_CONNECTED;
|
||||
result = dns_dispatch_createtcp(
|
||||
query->dispatchmgr, query->tcpsocket,
|
||||
query->fctx->res->taskmgr, NULL, NULL, 4096, 2,
|
||||
1, 1, 3, attrs, &query->dispatch);
|
||||
query->fctx->res->taskmgr, NULL, NULL, attrs,
|
||||
&query->dispatch);
|
||||
|
||||
/*
|
||||
* Regardless of whether dns_dispatch_create()
|
||||
|
@ -66,7 +66,6 @@ static isc_result_t
|
||||
make_dispatchset(unsigned int ndisps) {
|
||||
isc_result_t result;
|
||||
isc_sockaddr_t any;
|
||||
unsigned int attrs;
|
||||
dns_dispatch_t *disp = NULL;
|
||||
|
||||
result = dns_dispatchmgr_create(dt_mctx, &dispatchmgr);
|
||||
@ -75,9 +74,8 @@ make_dispatchset(unsigned int ndisps) {
|
||||
}
|
||||
|
||||
isc_sockaddr_any(&any);
|
||||
attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
|
||||
result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &any,
|
||||
6, 1024, 17, 19, attrs, &disp);
|
||||
0, &disp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
@ -258,7 +256,6 @@ dispatch_getnext(void **state) {
|
||||
uint16_t id;
|
||||
struct in_addr ina;
|
||||
unsigned char message[12];
|
||||
unsigned int attrs;
|
||||
unsigned char rbuf[12];
|
||||
|
||||
UNUSED(state);
|
||||
@ -273,9 +270,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_createudp(dispatchmgr, socketmgr, taskmgr, &local,
|
||||
6, 1024, 17, 19, attrs, &dispatch);
|
||||
0, &dispatch);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
|
@ -58,7 +58,7 @@ _setup(void **state) {
|
||||
|
||||
isc_sockaddr_any(&local);
|
||||
result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &local,
|
||||
100, 100, 100, 500, 0, &dispatch);
|
||||
0, &dispatch);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
return (0);
|
||||
|
@ -225,12 +225,6 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
||||
*\li #ISC_R_UNEXPECTED
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_socket_dup(isc_socket_t *sock0, isc_socket_t **socketp);
|
||||
/*%<
|
||||
* Duplicate an existing socket, reusing its file descriptor.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how);
|
||||
/*%<
|
||||
|
140
lib/isc/socket.c
140
lib/isc/socket.c
@ -350,8 +350,8 @@ struct isc_socket {
|
||||
unsigned int listener : 1, /* listener socket */
|
||||
connected : 1, connecting : 1, /* connect pending
|
||||
* */
|
||||
bound : 1, /* bound to local addr */
|
||||
dupped : 1, active : 1, /* currently active */
|
||||
bound : 1, /* bound to local addr */
|
||||
active : 1, /* currently active */
|
||||
pktdscp : 1; /* per packet dscp */
|
||||
|
||||
#ifdef ISC_PLATFORM_RECVOVERFLOW
|
||||
@ -434,7 +434,7 @@ struct isc__socketthread {
|
||||
|
||||
static isc_result_t
|
||||
socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
|
||||
isc_socket_t **socketp, isc_socket_t *dup_socket);
|
||||
isc_socket_t **socketp);
|
||||
static void
|
||||
send_recvdone_event(isc_socket_t *, isc_socketevent_t **);
|
||||
static void
|
||||
@ -1881,7 +1881,6 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
|
||||
sock->fd = -1;
|
||||
sock->threadid = -1;
|
||||
sock->dscp = 0; /* TOS/TCLASS is zero until set. */
|
||||
sock->dupped = 0;
|
||||
sock->statsindex = NULL;
|
||||
sock->active = 0;
|
||||
|
||||
@ -2123,8 +2122,7 @@ set_ip_disable_pmtud(isc_socket_t *sock) {
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
opensocket(isc_socketmgr_t *manager, isc_socket_t *sock,
|
||||
isc_socket_t *dup_socket) {
|
||||
opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) {
|
||||
isc_result_t result;
|
||||
char strbuf[ISC_STRERRORSIZE];
|
||||
const char *err = "socket";
|
||||
@ -2138,60 +2136,52 @@ opensocket(isc_socketmgr_t *manager, isc_socket_t *sock,
|
||||
#endif
|
||||
|
||||
again:
|
||||
if (dup_socket == NULL) {
|
||||
switch (sock->type) {
|
||||
case isc_sockettype_udp:
|
||||
sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
|
||||
break;
|
||||
case isc_sockettype_tcp:
|
||||
sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
|
||||
break;
|
||||
case isc_sockettype_unix:
|
||||
sock->fd = socket(sock->pf, SOCK_STREAM, 0);
|
||||
break;
|
||||
case isc_sockettype_raw:
|
||||
errno = EPFNOSUPPORT;
|
||||
/*
|
||||
* PF_ROUTE is a alias for PF_NETLINK on linux.
|
||||
*/
|
||||
switch (sock->type) {
|
||||
case isc_sockettype_udp:
|
||||
sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
|
||||
break;
|
||||
case isc_sockettype_tcp:
|
||||
sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
|
||||
break;
|
||||
case isc_sockettype_unix:
|
||||
sock->fd = socket(sock->pf, SOCK_STREAM, 0);
|
||||
break;
|
||||
case isc_sockettype_raw:
|
||||
errno = EPFNOSUPPORT;
|
||||
/*
|
||||
* PF_ROUTE is a alias for PF_NETLINK on linux.
|
||||
*/
|
||||
#if defined(PF_ROUTE)
|
||||
if (sock->fd == -1 && sock->pf == PF_ROUTE) {
|
||||
if (sock->fd == -1 && sock->pf == PF_ROUTE) {
|
||||
#ifdef NETLINK_ROUTE
|
||||
sock->fd = socket(sock->pf, SOCK_RAW,
|
||||
NETLINK_ROUTE);
|
||||
sock->fd = socket(sock->pf, SOCK_RAW, NETLINK_ROUTE);
|
||||
#else /* ifdef NETLINK_ROUTE */
|
||||
sock->fd = socket(sock->pf, SOCK_RAW, 0);
|
||||
sock->fd = socket(sock->pf, SOCK_RAW, 0);
|
||||
#endif /* ifdef NETLINK_ROUTE */
|
||||
if (sock->fd != -1) {
|
||||
if (sock->fd != -1) {
|
||||
#ifdef NETLINK_ROUTE
|
||||
struct sockaddr_nl sa;
|
||||
int n;
|
||||
struct sockaddr_nl sa;
|
||||
int n;
|
||||
|
||||
/*
|
||||
* Do an implicit bind.
|
||||
*/
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.nl_family = AF_NETLINK;
|
||||
sa.nl_groups = RTMGRP_IPV4_IFADDR |
|
||||
RTMGRP_IPV6_IFADDR;
|
||||
n = bind(sock->fd,
|
||||
(struct sockaddr *)&sa,
|
||||
sizeof(sa));
|
||||
if (n < 0) {
|
||||
close(sock->fd);
|
||||
sock->fd = -1;
|
||||
}
|
||||
#endif /* ifdef NETLINK_ROUTE */
|
||||
sock->bound = 1;
|
||||
/*
|
||||
* Do an implicit bind.
|
||||
*/
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.nl_family = AF_NETLINK;
|
||||
sa.nl_groups = RTMGRP_IPV4_IFADDR |
|
||||
RTMGRP_IPV6_IFADDR;
|
||||
n = bind(sock->fd, (struct sockaddr *)&sa,
|
||||
sizeof(sa));
|
||||
if (n < 0) {
|
||||
close(sock->fd);
|
||||
sock->fd = -1;
|
||||
}
|
||||
#endif /* ifdef NETLINK_ROUTE */
|
||||
sock->bound = 1;
|
||||
}
|
||||
#endif /* if defined(PF_ROUTE) */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sock->fd = dup(dup_socket->fd);
|
||||
sock->dupped = 1;
|
||||
sock->bound = dup_socket->bound;
|
||||
#endif /* if defined(PF_ROUTE) */
|
||||
break;
|
||||
}
|
||||
if (sock->fd == -1 && errno == EINTR && tries++ < 42) {
|
||||
goto again;
|
||||
@ -2268,10 +2258,6 @@ again:
|
||||
}
|
||||
}
|
||||
|
||||
if (dup_socket != NULL) {
|
||||
goto setup_done;
|
||||
}
|
||||
|
||||
result = make_nonblock(sock->fd);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
(void)close(sock->fd);
|
||||
@ -2410,7 +2396,6 @@ again:
|
||||
|
||||
set_ip_disable_pmtud(sock);
|
||||
|
||||
setup_done:
|
||||
inc_stats(manager->stats, sock->statsindex[STATID_OPEN]);
|
||||
if (sock->active == 0) {
|
||||
inc_stats(manager->stats, sock->statsindex[STATID_ACTIVE]);
|
||||
@ -2421,14 +2406,13 @@ setup_done:
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a 'type' socket or duplicate an existing socket, managed
|
||||
* by 'manager'. Events will be posted to 'task' and when dispatched
|
||||
* 'action' will be called with 'arg' as the arg value. The new
|
||||
* socket is returned in 'socketp'.
|
||||
* Create a 'type' socket, managed by 'manager'. Events will be posted to
|
||||
* 'task' and when dispatched 'action' will be called with 'arg' as the arg
|
||||
* value. The new socket is returned in 'socketp'.
|
||||
*/
|
||||
static isc_result_t
|
||||
socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
||||
isc_socket_t **socketp, isc_socket_t *dup_socket) {
|
||||
isc_socket_t **socketp) {
|
||||
isc_socket_t *sock = NULL;
|
||||
isc__socketthread_t *thread;
|
||||
isc_result_t result;
|
||||
@ -2466,7 +2450,7 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
||||
|
||||
sock->pf = pf;
|
||||
|
||||
result = opensocket(manager, sock, dup_socket);
|
||||
result = opensocket(manager, sock);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
free_socket(&sock);
|
||||
return (result);
|
||||
@ -2507,8 +2491,7 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
||||
#endif /* ifdef USE_SELECT */
|
||||
UNLOCK(&manager->lock);
|
||||
|
||||
socket_log(sock, NULL, CREATION,
|
||||
dup_socket != NULL ? "dupped" : "created");
|
||||
socket_log(sock, NULL, CREATION, "created");
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
@ -2520,22 +2503,9 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
||||
* in 'socketp'.
|
||||
*/
|
||||
isc_result_t
|
||||
isc_socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
|
||||
isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
||||
isc_socket_t **socketp) {
|
||||
return (socket_create(manager0, pf, type, socketp, NULL));
|
||||
}
|
||||
|
||||
/*%
|
||||
* Duplicate an existing socket. The new socket is returned
|
||||
* in 'socketp'.
|
||||
*/
|
||||
isc_result_t
|
||||
isc_socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
|
||||
REQUIRE(VALID_SOCKET(sock));
|
||||
REQUIRE(socketp != NULL && *socketp == NULL);
|
||||
|
||||
return (socket_create(sock->manager, sock->pf, sock->type, socketp,
|
||||
sock));
|
||||
return (socket_create(manager, pf, type, socketp));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
@ -2551,7 +2521,7 @@ isc_socket_open(isc_socket_t *sock) {
|
||||
REQUIRE(sock->fd == -1);
|
||||
REQUIRE(sock->threadid == -1);
|
||||
|
||||
result = opensocket(sock->manager, sock, NULL);
|
||||
result = opensocket(sock->manager, sock);
|
||||
|
||||
UNLOCK(&sock->lock);
|
||||
|
||||
@ -2642,7 +2612,6 @@ isc_socket_close(isc_socket_t *sock) {
|
||||
sock->fd = -1;
|
||||
sock->threadid = -1;
|
||||
|
||||
sock->dupped = 0;
|
||||
memset(sock->name, 0, sizeof(sock->name));
|
||||
sock->tag = NULL;
|
||||
sock->listener = 0;
|
||||
@ -4334,7 +4303,6 @@ isc_socket_bind(isc_socket_t *sock, const isc_sockaddr_t *sockaddr,
|
||||
LOCK(&sock->lock);
|
||||
|
||||
INSIST(!sock->bound);
|
||||
INSIST(!sock->dupped);
|
||||
|
||||
if (sock->pf != sockaddr->type.sa.sa_family) {
|
||||
UNLOCK(&sock->lock);
|
||||
@ -5078,7 +5046,6 @@ isc_socket_ipv6only(isc_socket_t *sock, bool yes) {
|
||||
#endif /* if defined(IPV6_V6ONLY) */
|
||||
|
||||
REQUIRE(VALID_SOCKET(sock));
|
||||
INSIST(!sock->dupped);
|
||||
|
||||
#ifdef IPV6_V6ONLY
|
||||
if (sock->pf == AF_INET6) {
|
||||
@ -5151,10 +5118,6 @@ isc_socket_dscp(isc_socket_t *sock, isc_dscp_t dscp) {
|
||||
}
|
||||
#endif /* if !defined(IP_TOS) && !defined(IPV6_TCLASS) */
|
||||
|
||||
#ifdef notyet
|
||||
REQUIRE(!sock->dupped);
|
||||
#endif /* ifdef notyet */
|
||||
|
||||
setdscp(sock, dscp);
|
||||
}
|
||||
|
||||
@ -5200,8 +5163,7 @@ static void
|
||||
init_hasreuseport(void) {
|
||||
/*
|
||||
* SO_REUSEPORT works very differently on *BSD and on Linux (because why not).
|
||||
* We only want to use it on Linux, if it's available. On BSD we want to dup()
|
||||
* sockets instead of re-binding them.
|
||||
* We only want to use it on Linux, if it's available.
|
||||
*/
|
||||
#if (defined(SO_REUSEPORT) && defined(__linux__)) || \
|
||||
(defined(SO_REUSEPORT_LB) && defined(__FreeBSD_kernel__))
|
||||
|
@ -218,89 +218,6 @@ udp_sendto_test(void **state) {
|
||||
assert_string_equal(recvbuf, "Hello");
|
||||
}
|
||||
|
||||
/* Test UDP sendto/recv with duplicated socket */
|
||||
static void
|
||||
udp_dup_test(void **state) {
|
||||
isc_result_t result;
|
||||
isc_sockaddr_t addr1, addr2;
|
||||
struct in_addr in;
|
||||
char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
|
||||
completion_t completion;
|
||||
isc_region_t r;
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
in.s_addr = inet_addr("127.0.0.1");
|
||||
isc_sockaddr_fromin(&addr1, &in, 0);
|
||||
isc_sockaddr_fromin(&addr2, &in, 0);
|
||||
|
||||
result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
result = isc_socket_bind(s1, &addr1, 0);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
result = isc_socket_getsockname(s1, &addr1);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_true(isc_sockaddr_getport(&addr1) != 0);
|
||||
|
||||
result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
result = isc_socket_bind(s2, &addr2, 0);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
result = isc_socket_getsockname(s2, &addr2);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_true(isc_sockaddr_getport(&addr2) != 0);
|
||||
|
||||
result = isc_socket_dup(s2, &s3);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_task_create(taskmgr, 0, &test_task);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
snprintf(sendbuf, sizeof(sendbuf), "Hello");
|
||||
r.base = (void *)sendbuf;
|
||||
r.length = strlen(sendbuf) + 1;
|
||||
|
||||
completion_init(&completion);
|
||||
result = isc_socket_sendto(s1, &r, test_task, event_done, &completion,
|
||||
&addr2, NULL);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
waitfor(&completion);
|
||||
assert_true(atomic_load(&completion.done));
|
||||
assert_int_equal(completion.result, ISC_R_SUCCESS);
|
||||
|
||||
snprintf(sendbuf, sizeof(sendbuf), "World");
|
||||
r.base = (void *)sendbuf;
|
||||
r.length = strlen(sendbuf) + 1;
|
||||
|
||||
completion_init(&completion);
|
||||
result = isc_socket_sendto(s1, &r, test_task, event_done, &completion,
|
||||
&addr2, NULL);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
waitfor(&completion);
|
||||
assert_true(atomic_load(&completion.done));
|
||||
assert_int_equal(completion.result, ISC_R_SUCCESS);
|
||||
|
||||
r.base = (void *)recvbuf;
|
||||
r.length = BUFSIZ;
|
||||
completion_init(&completion);
|
||||
result = isc_socket_recv(s2, &r, 1, test_task, event_done, &completion);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
waitfor(&completion);
|
||||
assert_true(atomic_load(&completion.done));
|
||||
assert_int_equal(completion.result, ISC_R_SUCCESS);
|
||||
assert_string_equal(recvbuf, "Hello");
|
||||
|
||||
r.base = (void *)recvbuf;
|
||||
r.length = BUFSIZ;
|
||||
completion_init(&completion);
|
||||
result = isc_socket_recv(s3, &r, 1, test_task, event_done, &completion);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
waitfor(&completion);
|
||||
assert_true(atomic_load(&completion.done));
|
||||
assert_int_equal(completion.result, ISC_R_SUCCESS);
|
||||
assert_string_equal(recvbuf, "World");
|
||||
}
|
||||
|
||||
/* Test UDP sendto/recv (IPv4) */
|
||||
static void
|
||||
udp_dscp_v4_test(void **state) {
|
||||
@ -787,8 +704,6 @@ main(void) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(udp_sendto_test, _setup,
|
||||
_teardown),
|
||||
cmocka_unit_test_setup_teardown(udp_dup_test, _setup,
|
||||
_teardown),
|
||||
cmocka_unit_test_setup_teardown(tcp_dscp_v4_test, _setup,
|
||||
_teardown),
|
||||
cmocka_unit_test_setup_teardown(tcp_dscp_v6_test, _setup,
|
||||
|
Loading…
x
Reference in New Issue
Block a user