diff --git a/bin/named/server.c b/bin/named/server.c index c7638f8fb1..857609dd5a 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -4708,8 +4708,6 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, /* * Resolver. - * - * XXXRTH Hardwired number of tasks. */ CHECK(get_view_querysource_dispatch( maps, AF_INET, &dispatch4, &dscp4, @@ -4719,7 +4717,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, (ISC_LIST_PREV(view, link) == NULL))); if (dispatch4 == NULL && dispatch6 == NULL) { UNEXPECTED_ERROR(__FILE__, __LINE__, - "unable to obtain neither an IPv4 nor" + "unable to obtain either an IPv4 or" " an IPv6 dispatch"); result = ISC_R_UNEXPECTED; goto cleanup; @@ -9898,8 +9896,8 @@ run_server(isc_task_t *task, isc_event_t *event) { CHECKFATAL(ns_interfacemgr_create( named_g_mctx, server->sctx, named_g_taskmgr, named_g_timermgr, named_g_socketmgr, named_g_netmgr, - named_g_dispatchmgr, server->task, named_g_udpdisp, - geoip, named_g_cpus, &server->interfacemgr), + named_g_dispatchmgr, server->task, geoip, + named_g_cpus, &server->interfacemgr), "creating interface manager"); CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive, diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index e8de005bc5..1bbff39504 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -79,6 +79,7 @@ struct dns_dispatchmgr { /*% * Locked by qid->lock if qid exists; otherwise, can be used without * being locked. + * * Memory footprint considerations: this is a simple implementation of * available ports, i.e., an ordered array of the actual port numbers. * This will require about 256KB of memory in the worst case (128KB for @@ -151,7 +152,6 @@ struct dispsocket { isc_socket_t *socket; dns_dispatch_t *disp; isc_sockaddr_t host; - in_port_t localport; /* XXX: should be removed later */ dispportentry_t *portentry; dns_dispentry_t *resp; isc_task_t *task; @@ -199,7 +199,6 @@ struct dns_dispatch { isc_sockaddr_t local; /*%< local address */ in_port_t localport; /*%< local UDP port */ isc_sockaddr_t peer; /*%< peer address (TCP) */ - isc_dscp_t dscp; /*%< "listen-on" DSCP value */ unsigned int maxrequests; /*%< max requests */ isc_event_t *ctlevent; @@ -212,7 +211,7 @@ struct dns_dispatch { isc_mutex_t lock; /*%< locks all below */ isc_sockettype_t socktype; unsigned int attributes; - unsigned int refcount; /*%< number of users */ + 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? * @@ -324,7 +323,7 @@ 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, bool duponly); + isc_socket_t *dup_socket); static bool portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock, isc_sockaddr_t *sockaddrp); @@ -444,7 +443,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; + dns_dispentry_t *ret = NULL; unsigned int bucket; bucket = 0; @@ -466,7 +465,7 @@ linear_first(dns_qid_t *qid) { */ static dns_dispentry_t * linear_next(dns_qid_t *qid, dns_dispentry_t *resp) { - dns_dispentry_t *ret; + dns_dispentry_t *ret = NULL; unsigned int bucket; ret = ISC_LIST_NEXT(resp, link); @@ -492,7 +491,7 @@ linear_next(dns_qid_t *qid, dns_dispentry_t *resp) { */ static bool destroy_disp_ok(dns_dispatch_t *disp) { - if (disp->refcount != 0) { + if (isc_refcount_current(&disp->refcount) != 0) { return (false); } @@ -519,10 +518,10 @@ destroy_disp_ok(dns_dispatch_t *disp) { */ static void destroy_disp(isc_task_t *task, isc_event_t *event) { - dns_dispatch_t *disp; - dns_dispatchmgr_t *mgr; + dns_dispatch_t *disp = NULL; + dns_dispatchmgr_t *mgr = NULL; bool killmgr; - dispsocket_t *dispsocket; + dispsocket_t *dispsocket = NULL; int i; INSIST(event->ev_type == DNS_EVENT_DISPATCHCONTROL); @@ -570,7 +569,7 @@ destroy_disp(isc_task_t *task, isc_event_t *event) { */ static dispportentry_t * port_search(dns_dispatch_t *disp, in_port_t port) { - dispportentry_t *portentry; + dispportentry_t *portentry = NULL; REQUIRE(disp->port_table != NULL); @@ -588,8 +587,8 @@ port_search(dns_dispatch_t *disp, in_port_t port) { static dispportentry_t * new_portentry(dns_dispatch_t *disp, in_port_t port) { - dispportentry_t *portentry; - dns_qid_t *qid; + dispportentry_t *portentry = NULL; + dns_qid_t *qid = NULL; REQUIRE(disp->port_table != NULL); @@ -632,7 +631,7 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) { static dispsocket_t * socket_search(dns_qid_t *qid, const isc_sockaddr_t *dest, in_port_t port, unsigned int bucket) { - dispsocket_t *dispsock; + dispsocket_t *dispsock = NULL; REQUIRE(VALID_QID(qid)); REQUIRE(bucket < qid->qid_nbuckets); @@ -667,19 +666,19 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, in_port_t port; isc_sockaddr_t localaddr; unsigned int bucket = 0; - dispsocket_t *dispsock; + dispsocket_t *dispsock = NULL; unsigned int nports; - in_port_t *ports; + in_port_t *ports = NULL; isc_socket_options_t bindoptions; dispportentry_t *portentry = NULL; - dns_qid_t *qid; + dns_qid_t *qid = NULL; if (isc_sockaddr_pf(&disp->local) == AF_INET) { - nports = disp->mgr->nv4ports; - ports = disp->mgr->v4ports; + nports = mgr->nv4ports; + ports = mgr->v4ports; } else { - nports = disp->mgr->nv6ports; - ports = disp->mgr->v6ports; + nports = mgr->nv6ports; + ports = mgr->v6ports; } if (nports == 0) { return (ISC_R_ADDRNOTAVAIL); @@ -694,11 +693,8 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, dispsock = isc_mem_get(mgr->mctx, sizeof(*dispsock)); disp->nsockets++; - dispsock->socket = NULL; - dispsock->disp = disp; - dispsock->resp = NULL; - dispsock->portentry = NULL; - dispsock->task = NULL; + + *dispsock = (dispsocket_t){ .disp = disp }; isc_task_attach(disp->task[isc_random_uniform(disp->ntasks)], &dispsock->task); ISC_LINK_INIT(dispsock, link); @@ -732,7 +728,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, bindoptions |= ISC_SOCKET_REUSEADDRESS; } result = open_socket(sockmgr, &localaddr, bindoptions, &sock, - NULL, false); + NULL); if (result == ISC_R_SUCCESS) { if (portentry == NULL) { portentry = new_portentry(disp, port); @@ -781,7 +777,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; + dispsocket_t *dispsock = NULL; dns_qid_t *qid = DNS_QID(disp); /* @@ -871,7 +867,7 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { static dns_dispentry_t * entry_search(dns_qid_t *qid, const isc_sockaddr_t *dest, dns_messageid_t id, in_port_t port, unsigned int bucket) { - dns_dispentry_t *res; + dns_dispentry_t *res = NULL; REQUIRE(VALID_QID(qid)); REQUIRE(bucket < qid->qid_nbuckets); @@ -936,7 +932,7 @@ free_sevent(isc_event_t *ev) { static inline isc_socketevent_t * allocate_sevent(dns_dispatch_t *disp, isc_socket_t *sock, isc_eventtype_t type, isc_taskaction_t action, const void *arg) { - isc_socketevent_t *ev; + isc_socketevent_t *ev = NULL; void *deconst_arg; ev = isc_mem_get(disp->sepool, sizeof(*ev)); @@ -968,13 +964,12 @@ free_devent(dns_dispatch_t *disp, dns_dispatchevent_t *ev) { static inline dns_dispatchevent_t * allocate_devent(dns_dispatch_t *disp) { - dns_dispatchevent_t *ev; + dns_dispatchevent_t *ev = NULL; ev = isc_mem_get(disp->mgr->mctx, sizeof(*ev)); isc_refcount_increment0(&disp->mgr->irefs); ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, 0, NULL, NULL, NULL, NULL, NULL); - return (ev); } @@ -1020,12 +1015,12 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { isc_buffer_t source; unsigned int flags; dns_dispentry_t *resp = NULL; - dns_dispatchevent_t *rev; + dns_dispatchevent_t *rev = NULL; unsigned int bucket; bool killit; bool queue_response; - dns_dispatchmgr_t *mgr; - dns_qid_t *qid; + dns_dispatchmgr_t *mgr = NULL; + dns_qid_t *qid = NULL; isc_netaddr_t netaddr; int match; int result; @@ -1085,25 +1080,25 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { } if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { - if (dispsock != NULL) { - 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 (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) { free_buffer(disp, ev->region.base, ev->region.length); @@ -1244,10 +1239,6 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { sendresponse: queue_response = resp->item_out; rev = allocate_devent(resp->disp); - if (rev == NULL) { - free_buffer(disp, ev->region.base, ev->region.length); - goto unlock; - } /* * At this point, rev contains the event we want to fill in, and @@ -1318,12 +1309,12 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { dns_messageid_t id; isc_result_t dres; unsigned int flags; - dns_dispentry_t *resp; - dns_dispatchevent_t *rev; + dns_dispentry_t *resp = NULL; + dns_dispatchevent_t *rev = NULL; unsigned int bucket; bool killit; bool queue_response; - dns_qid_t *qid; + dns_qid_t *qid = NULL; int level; char buf[ISC_SOCKADDR_FORMATSIZE]; @@ -1342,7 +1333,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { INSIST(disp->recv_pending != 0); disp->recv_pending = 0; - if (disp->refcount == 0) { + if (isc_refcount_current(&disp->refcount) == 0) { /* * This dispatcher is shutting down. Force cancellation. */ @@ -1437,15 +1428,12 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { resp = entry_search(qid, &tcpmsg->address, id, disp->localport, bucket); dispatch_log(disp, LVL(90), "search for response in bucket %d: %s", bucket, (resp == NULL ? "not found" : "found")); - if (resp == NULL) { goto unlock; } + queue_response = resp->item_out; rev = allocate_devent(disp); - if (rev == NULL) { - goto unlock; - } /* * At this point, rev contains the event we want to fill in, and @@ -1489,7 +1477,7 @@ static isc_result_t startrecv(dns_dispatch_t *disp, dispsocket_t *dispsock) { isc_result_t res; isc_region_t region; - isc_socket_t *sock; + isc_socket_t *sock = NULL; if (disp->shutting_down == 1) { return (ISC_R_SUCCESS); @@ -1526,10 +1514,6 @@ startrecv(dns_dispatch_t *disp, dispsocket_t *dispsock) { isc_socketevent_t *sev = allocate_sevent( disp, sock, ISC_SOCKEVENT_RECVDONE, udp_exrecv, dispsock); - if (sev == NULL) { - free_buffer(disp, region.base, region.length); - return (ISC_R_NOMEMORY); - } res = isc_socket_recv2(sock, ®ion, 1, dt, sev, 0); if (res != ISC_R_SUCCESS) { @@ -1541,10 +1525,6 @@ startrecv(dns_dispatch_t *disp, dispsocket_t *dispsock) { isc_socketevent_t *sev = allocate_sevent( disp, sock, ISC_SOCKEVENT_RECVDONE, udp_shrecv, disp); - if (sev == NULL) { - free_buffer(disp, region.base, region.length); - return (ISC_R_NOMEMORY); - } res = isc_socket_recv2(sock, ®ion, 1, dt, sev, 0); if (res != ISC_R_SUCCESS) { @@ -1605,7 +1585,7 @@ destroy_mgr_ok(dns_dispatchmgr_t *mgr) { */ static void destroy_mgr(dns_dispatchmgr_t **mgrp) { - dns_dispatchmgr_t *mgr; + dns_dispatchmgr_t *mgr = NULL; mgr = *mgrp; *mgrp = NULL; @@ -1642,8 +1622,8 @@ 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, bool duponly) { - isc_socket_t *sock; + isc_socket_t *dup_socket) { + isc_socket_t *sock = NULL; isc_result_t result; sock = *sockp; @@ -1652,8 +1632,7 @@ 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() || duponly)) { + } else if (dup_socket != NULL && !isc_socket_hasreuseport()) { result = isc_socket_dup(dup_socket, &sock); if (result != ISC_R_SUCCESS) { return (result); @@ -1867,7 +1846,7 @@ dispatchmgr_setudp(dns_dispatchmgr_t *mgr, unsigned int maxbuffers, void dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) { - dns_dispatchmgr_t *mgr; + dns_dispatchmgr_t *mgr = NULL; bool killit; REQUIRE(mgrp != NULL); @@ -1953,12 +1932,10 @@ unlock: return (available); } -#define ATTRMATCH(_a1, _a2, _mask) (((_a1) & (_mask)) == ((_a2) & (_mask))) - static isc_result_t qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets, unsigned int increment, dns_qid_t **qidp, bool needsocktable) { - dns_qid_t *qid; + dns_qid_t *qid = NULL; unsigned int i; REQUIRE(VALID_DISPATCHMGR(mgr)); @@ -1995,7 +1972,7 @@ qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets, static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) { - dns_qid_t *qid; + dns_qid_t *qid = NULL; REQUIRE(qidp != NULL); qid = *qidp; @@ -2020,8 +1997,7 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) { static isc_result_t dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests, dns_dispatch_t **dispp) { - dns_dispatch_t *disp; - isc_result_t result; + dns_dispatch_t *disp = NULL; REQUIRE(VALID_DISPATCHMGR(mgr)); REQUIRE(dispp != NULL && *dispp == NULL); @@ -2034,52 +2010,20 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests, disp = isc_mem_get(mgr->mctx, sizeof(*disp)); isc_refcount_increment0(&mgr->irefs); - disp->magic = 0; - disp->mgr = mgr; - disp->maxrequests = maxrequests; - disp->attributes = 0; + *disp = (dns_dispatch_t){ .mgr = mgr, + .maxrequests = maxrequests, + .shutdown_why = ISC_R_UNEXPECTED }; + isc_refcount_init(&disp->refcount, 1); ISC_LINK_INIT(disp, link); - disp->refcount = 1; - disp->recv_pending = 0; - memset(&disp->local, 0, sizeof(disp->local)); - memset(&disp->peer, 0, sizeof(disp->peer)); - disp->localport = 0; - disp->shutting_down = 0; - disp->shutdown_out = 0; - disp->connected = 0; - disp->tcpmsg_valid = 0; - disp->shutdown_why = ISC_R_UNEXPECTED; - disp->requests = 0; - disp->tcpbuffers = 0; - disp->qid = NULL; ISC_LIST_INIT(disp->activesockets); ISC_LIST_INIT(disp->inactivesockets); - disp->nsockets = 0; - disp->port_table = NULL; - disp->dscp = -1; isc_mutex_init(&disp->lock); - disp->failsafe_ev = allocate_devent(disp); - if (disp->failsafe_ev == NULL) { - result = ISC_R_NOMEMORY; - goto kill_lock; - } - disp->magic = DISPATCH_MAGIC; *dispp = disp; return (ISC_R_SUCCESS); - - /* - * error returns - */ -kill_lock: - isc_mutex_destroy(&disp->lock); - isc_refcount_decrement(&mgr->irefs); - isc_mem_put(mgr->mctx, disp, sizeof(*disp)); - - return (result); } /* @@ -2087,8 +2031,8 @@ kill_lock: */ static void dispatch_free(dns_dispatch_t **dispp) { - dns_dispatch_t *disp; - dns_dispatchmgr_t *mgr; + dns_dispatch_t *disp = NULL; + dns_dispatchmgr_t *mgr = NULL; REQUIRE(VALID_DISPATCH(*dispp)); disp = *dispp; @@ -2140,7 +2084,7 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, unsigned int buckets, unsigned int increment, unsigned int attributes, dns_dispatch_t **dispp) { isc_result_t result; - dns_dispatch_t *disp; + dns_dispatch_t *disp = NULL; UNUSED(maxbuffers); UNUSED(buffersize); @@ -2221,8 +2165,12 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, ISC_LIST_APPEND(mgr->list, disp, link); UNLOCK(&mgr->lock); - mgr_log(mgr, LVL(90), "created TCP dispatcher %p", disp); - dispatch_log(disp, LVL(90), "created task %p", disp->task[0]); + if (isc_log_wouldlog(dns_lctx, 90)) { + mgr_log(mgr, LVL(90), + "dns_dispatch_createtcp: created TCP dispatch %p", + disp); + dispatch_log(disp, LVL(90), "created task %p", disp->task[0]); + } *dispp = disp; return (ISC_R_SUCCESS); @@ -2237,11 +2185,13 @@ deallocate_dispatch: return (result); } +#define ATTRMATCH(_a1, _a2, _mask) (((_a1) & (_mask)) == ((_a2) & (_mask))) + isc_result_t dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, const isc_sockaddr_t *localaddr, bool *connected, dns_dispatch_t **dispp) { - dns_dispatch_t *disp; + dns_dispatch_t *disp = NULL; isc_result_t result; isc_sockaddr_t peeraddr; isc_sockaddr_t sockname; @@ -2278,7 +2228,7 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, isc_sockaddr_eqaddr(localaddr, &sockname))) { /* attach */ - disp->refcount++; + isc_refcount_increment(&disp->refcount); *dispp = disp; match = true; if (connected != NULL) { @@ -2307,7 +2257,7 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, isc_sockaddr_equal(destaddr, &disp->peer)) { /* attach */ - disp->refcount++; + isc_refcount_increment(&disp->refcount); *dispp = disp; match = true; } @@ -2350,11 +2300,11 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, } /* - * Nope, create one. + * 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); @@ -2383,62 +2333,16 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, isc_sockaddr_t localaddr_bound; isc_socket_t *sock = NULL; isc_result_t result = ISC_R_SUCCESS; - bool anyport; + unsigned int nports; + in_port_t *ports = NULL; - INSIST(sockp != NULL && *sockp == NULL); + REQUIRE(sockp != NULL && *sockp == NULL); - localaddr_bound = *localaddr; - anyport = (isc_sockaddr_getport(localaddr) == 0); - - if (anyport) { - unsigned int nports; - in_port_t *ports; - - /* - * If no port is specified, we first try to pick up a random - * port by ourselves. - */ - if (isc_sockaddr_pf(localaddr) == AF_INET) { - nports = disp->mgr->nv4ports; - ports = disp->mgr->v4ports; - } else { - nports = disp->mgr->nv6ports; - ports = disp->mgr->v6ports; - } - if (nports == 0) { - return (ISC_R_ADDRNOTAVAIL); - } - - 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, false); - /* - * Continue if the port chosen is already in use - * or the OS has reserved it. - */ - 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 - * choosing one. - */ - } else { + 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, - true); - + ISC_SOCKET_REUSEADDRESS, &sock, + dup_socket); if (result == ISC_R_SUCCESS) { *sockp = sock; } @@ -2446,11 +2350,50 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, 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, false); + result = open_socket(sockmgr, localaddr, 0, &sock, NULL); if (result != ISC_R_SUCCESS) { goto end; } else if (portavailable(mgr, sock, NULL)) { @@ -2465,6 +2408,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, i = 0; } } + if (j == 0xffffU) { mgr_log(mgr, ISC_LOG_ERROR, "avoid-v%s-udp-ports: unable to allocate " @@ -2491,7 +2435,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, unsigned int maxrequests, unsigned int attributes, dns_dispatch_t **dispp, isc_socket_t *dup_socket) { isc_result_t result; - dns_dispatch_t *disp; + dns_dispatch_t *disp = NULL; isc_socket_t *sock = NULL; int i = 0; @@ -2519,8 +2463,8 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, isc_sockaddr_format(localaddr, addrbuf, ISC_SOCKADDR_FORMATSIZE); mgr_log(mgr, LVL(90), - "dns_dispatch_createudp: Created" - " UDP dispatch for %s with socket fd %d", + "dispatch_createudp: created shared " + "UDP dispatch for %s with socket fd %d", addrbuf, isc_socket_getfd(sock)); } } else { @@ -2534,8 +2478,8 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, */ isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr)); if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) { - result = open_socket(sockmgr, localaddr, 0, &sock, NULL, - false); + result = open_socket(sockmgr, localaddr, 0, &sock, + NULL); if (sock != NULL) { isc_socket_detach(&sock); } @@ -2617,10 +2561,7 @@ dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp) { REQUIRE(VALID_DISPATCH(disp)); REQUIRE(dispp != NULL && *dispp == NULL); - LOCK(&disp->lock); - disp->refcount++; - UNLOCK(&disp->lock); - + isc_refcount_increment(&disp->refcount); *dispp = disp; } @@ -2633,8 +2574,8 @@ dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp) { */ void dns_dispatch_detach(dns_dispatch_t **dispp) { - dns_dispatch_t *disp; - dispsocket_t *dispsock; + dns_dispatch_t *disp = NULL; + dispsocket_t *dispsock = NULL; bool killit; REQUIRE(dispp != NULL && VALID_DISPATCH(*dispp)); @@ -2643,10 +2584,7 @@ dns_dispatch_detach(dns_dispatch_t **dispp) { *dispp = NULL; LOCK(&disp->lock); - - INSIST(disp->refcount > 0); - disp->refcount--; - if (disp->refcount == 0) { + if (isc_refcount_decrement(&disp->refcount) == 1) { if (disp->recv_pending > 0) { isc_socket_cancel(disp->socket, disp->task[0], ISC_SOCKCANCEL_RECV); @@ -2660,7 +2598,8 @@ dns_dispatch_detach(dns_dispatch_t **dispp) { disp->shutting_down = 1; } - dispatch_log(disp, LVL(90), "detach: refcount %d", disp->refcount); + dispatch_log(disp, LVL(90), "detach: refcount %" PRIuFAST32, + isc_refcount_current(&disp->refcount)); killit = destroy_disp_ok(disp); UNLOCK(&disp->lock); @@ -2675,13 +2614,13 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, isc_taskaction_t action, void *arg, dns_messageid_t *idp, dns_dispentry_t **resp, isc_socketmgr_t *sockmgr) { - dns_dispentry_t *res; + dns_dispentry_t *res = NULL; unsigned int bucket; in_port_t localport = 0; dns_messageid_t id; - int i; - bool ok; - dns_qid_t *qid; + int i = 0; + bool ok = false; + dns_qid_t *qid = NULL; dispsocket_t *dispsocket = NULL; isc_result_t result; @@ -2709,9 +2648,9 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0 && disp->nsockets > DNS_DISPATCH_SOCKSQUOTA) { - dispsocket_t *oldestsocket; - dns_dispentry_t *oldestresp; - dns_dispatchevent_t *rev; + dispsocket_t *oldestsocket = NULL; + dns_dispentry_t *oldestresp = NULL; + dns_dispatchevent_t *rev = NULL; /* * Kill oldest outstanding query if the number of sockets @@ -2721,21 +2660,15 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, oldestresp = oldestsocket->resp; if (oldestresp != NULL && !oldestresp->item_out) { rev = allocate_devent(oldestresp->disp); - if (rev != NULL) { - rev->buffer.base = NULL; - rev->result = ISC_R_CANCELED; - rev->id = oldestresp->id; - ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, - DNS_EVENT_DISPATCH, - oldestresp->action, - oldestresp->arg, oldestresp, - NULL, NULL); - oldestresp->item_out = true; - isc_task_send(oldestresp->task, - ISC_EVENT_PTR(&rev)); - inc_stats(disp->mgr, - dns_resstatscounter_dispabort); - } + rev->buffer.base = NULL; + rev->result = ISC_R_CANCELED; + rev->id = oldestresp->id; + ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, + DNS_EVENT_DISPATCH, oldestresp->action, + oldestresp->arg, oldestresp, NULL, NULL); + oldestresp->item_out = true; + isc_task_send(oldestresp->task, ISC_EVENT_PTR(&rev)); + inc_stats(disp->mgr, dns_resstatscounter_dispabort); } /* @@ -2764,21 +2697,22 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, } /* - * Try somewhat hard to find a unique ID, unless - * DNS_DISPATCHOPT_FIXEDID is set, in which case we - * use the ID passed in via *idp. + * Try somewhat hard to find a unique ID. Start with + * a random number unless DNS_DISPATCHOPT_FIXEDID is set, + * in which case we start with the ID passed in via *idp. */ - LOCK(&qid->lock); if ((options & DNS_DISPATCHOPT_FIXEDID) != 0) { id = *idp; } else { id = (dns_messageid_t)isc_random16(); } - ok = false; - i = 0; + + LOCK(&qid->lock); do { + dns_dispentry_t *entry = NULL; bucket = dns_hash(qid, dest, id, localport); - if (entry_search(qid, dest, id, localport, bucket) == NULL) { + entry = entry_search(qid, dest, id, localport, bucket); + if (entry == NULL) { ok = true; break; } @@ -2794,27 +2728,26 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, res = isc_mem_get(disp->mgr->mctx, sizeof(*res)); isc_refcount_increment0(&disp->mgr->irefs); - - disp->refcount++; - disp->requests++; - res->task = NULL; + *res = (dns_dispentry_t){ .disp = disp, + .id = id, + .port = localport, + .bucket = bucket, + .host = *dest, + .action = action, + .arg = arg, + .dispsocket = dispsocket }; isc_task_attach(task, &res->task); - res->disp = disp; - res->id = id; - res->port = localport; - res->bucket = bucket; - res->host = *dest; - res->action = action; - res->arg = arg; - res->dispsocket = dispsocket; - if (dispsocket != NULL) { - dispsocket->resp = res; - } - res->item_out = false; ISC_LIST_INIT(res->items); ISC_LINK_INIT(res, link); res->magic = RESPONSE_MAGIC; + isc_refcount_increment(&disp->refcount); + disp->requests++; + + if (dispsocket != NULL) { + dispsocket->resp = res; + } + LOCK(&qid->lock); ISC_LIST_APPEND(qid->qid_table[bucket], res, link); UNLOCK(&qid->lock); @@ -2838,7 +2771,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, destroy_dispsocket(disp, &dispsocket); } - disp->refcount--; + isc_refcount_decrement(&disp->refcount); disp->requests--; dec_stats(disp->mgr, @@ -2886,8 +2819,8 @@ dns_dispatch_starttcp(dns_dispatch_t *disp) { isc_result_t dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent) { - dns_dispatch_t *disp; - dns_dispatchevent_t *ev; + dns_dispatch_t *disp = NULL; + dns_dispatchevent_t *ev = NULL; REQUIRE(VALID_RESPONSE(resp)); REQUIRE(sockevent != NULL && *sockevent != NULL); @@ -2930,16 +2863,16 @@ dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent) { void dns_dispatch_removeresponse(dns_dispentry_t **resp, dns_dispatchevent_t **sockevent) { - dns_dispatchmgr_t *mgr; - dns_dispatch_t *disp; - dns_dispentry_t *res; - dispsocket_t *dispsock; - dns_dispatchevent_t *ev; + dns_dispatchmgr_t *mgr = NULL; + dns_dispatch_t *disp = NULL; + dns_dispentry_t *res = NULL; + dispsocket_t *dispsock = NULL; + dns_dispatchevent_t *ev = NULL; unsigned int bucket; bool killit; unsigned int n; isc_eventlist_t events; - dns_qid_t *qid; + dns_qid_t *qid = NULL; REQUIRE(resp != NULL); REQUIRE(VALID_RESPONSE(*resp)); @@ -2969,9 +2902,8 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, dec_stats(disp->mgr, (qid == disp->mgr->qid) ? dns_resstatscounter_disprequdp : dns_resstatscounter_dispreqtcp); - INSIST(disp->refcount > 0); - disp->refcount--; - if (disp->refcount == 0) { + + if (isc_refcount_decrement(&disp->refcount) == 1) { if (disp->recv_pending > 0) { isc_socket_cancel(disp->socket, disp->task[0], ISC_SOCKCANCEL_RECV); @@ -3057,9 +2989,9 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, */ static void do_cancel(dns_dispatch_t *disp) { - dns_dispatchevent_t *ev; - dns_dispentry_t *resp; - dns_qid_t *qid; + dns_dispatchevent_t *ev = NULL; + dns_dispentry_t *resp = NULL; + dns_qid_t *qid = NULL; if (disp->shutdown_out == 1) { return; @@ -3151,10 +3083,6 @@ dns_dispatch_changeattributes(dns_dispatch_t *disp, unsigned int attributes, /* Exclusive attribute can only be set on creation */ REQUIRE((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0); - /* XXXMLG - * Should check for valid attributes here! - */ - LOCK(&disp->lock); disp->attributes &= ~mask; @@ -3164,7 +3092,7 @@ dns_dispatch_changeattributes(dns_dispatch_t *disp, unsigned int attributes, dns_dispatch_t * dns_dispatchset_get(dns_dispatchset_t *dset) { - dns_dispatch_t *disp; + dns_dispatch_t *disp = NULL; /* check that dispatch set is configured */ if (dset == NULL || dset->ndisp == 0) { @@ -3187,8 +3115,8 @@ dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr, isc_taskmgr_t *taskmgr, dns_dispatch_t *source, dns_dispatchset_t **dsetp, int n) { isc_result_t result; - dns_dispatchset_t *dset; - dns_dispatchmgr_t *mgr; + dns_dispatchset_t *dset = NULL; + dns_dispatchmgr_t *mgr = NULL; int i, j; REQUIRE(VALID_DISPATCH(source)); @@ -3198,15 +3126,13 @@ dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr, mgr = source->mgr; dset = isc_mem_get(mctx, sizeof(dns_dispatchset_t)); - memset(dset, 0, sizeof(*dset)); + *dset = (dns_dispatchset_t){ .ndisp = n }; isc_mutex_init(&dset->lock); dset->dispatches = isc_mem_get(mctx, sizeof(dns_dispatch_t *) * n); isc_mem_attach(mctx, &dset->mctx); - dset->ndisp = n; - dset->cur = 0; dset->dispatches[0] = NULL; dns_dispatch_attach(source, &dset->dispatches[0]); @@ -3251,7 +3177,7 @@ dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task) { REQUIRE(dset != NULL); for (i = 0; i < dset->ndisp; i++) { - isc_socket_t *sock; + isc_socket_t *sock = NULL; sock = dns_dispatch_getsocket(dset->dispatches[i]); isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL); } @@ -3259,7 +3185,7 @@ dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task) { void dns_dispatchset_destroy(dns_dispatchset_t **dsetp) { - dns_dispatchset_t *dset; + dns_dispatchset_t *dset = NULL; int i; REQUIRE(dsetp != NULL && *dsetp != NULL); diff --git a/lib/dns/request.c b/lib/dns/request.c index bbff2d6b0e..953023a22e 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -543,7 +543,6 @@ create_tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr, if (result != ISC_R_SUCCESS) { return (result); } -#ifndef BROKEN_TCP_BIND_BEFORE_CONNECT if (srcaddr == NULL) { isc_sockaddr_anyofpf(&bind_any, isc_sockaddr_pf(destaddr)); result = isc_socket_bind(sock, &bind_any, 0); @@ -555,16 +554,13 @@ create_tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr, if (result != ISC_R_SUCCESS) { goto cleanup; } -#endif /* ifndef BROKEN_TCP_BIND_BEFORE_CONNECT */ - attrs = 0; - attrs |= DNS_DISPATCHATTR_TCP; + attrs = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_MAKEQUERY; if (isc_sockaddr_pf(destaddr) == AF_INET) { attrs |= DNS_DISPATCHATTR_IPV4; } else { attrs |= DNS_DISPATCHATTR_IPV6; } - attrs |= DNS_DISPATCHATTR_MAKEQUERY; isc_socket_dscp(sock, dscp); result = dns_dispatch_createtcp( diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 4652f04370..a47edf9ab2 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -518,14 +518,8 @@ struct dns_resolver { uint32_t lame_ttl; ISC_LIST(alternate_t) alternates; uint16_t udpsize; -#if USE_ALGLOCK - isc_rwlock_t alglock; -#endif /* if USE_ALGLOCK */ dns_rbt_t *algorithms; dns_rbt_t *digests; -#if USE_MBSLOCK - isc_rwlock_t mbslock; -#endif /* if USE_MBSLOCK */ dns_rbt_t *mustbesecure; unsigned int spillatmax; unsigned int spillatmin; @@ -2060,21 +2054,19 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, INSIST(ISC_LIST_EMPTY(fctx->validators)); query = isc_mem_get(fctx->mctx, sizeof(*query)); - query->rmessage = NULL; - dns_message_create(fctx->mctx, DNS_MESSAGE_INTENTPARSE, - &query->rmessage); - query->mctx = fctx->mctx; - query->options = options; - query->attributes = 0; - query->sends = 0; - query->connects = 0; - query->dscp = addrinfo->dscp; - query->udpsize = 0; + *query = (resquery_t){ .mctx = fctx->mctx, + .options = options, + .dscp = addrinfo->dscp, + .addrinfo = addrinfo, + .dispatchmgr = res->dispatchmgr }; + /* * Note that the caller MUST guarantee that 'addrinfo' will remain * valid until this query is canceled. */ - query->addrinfo = addrinfo; + + dns_message_create(fctx->mctx, DNS_MESSAGE_INTENTPARSE, + &query->rmessage); TIME_NOW(&query->start); /* @@ -2083,9 +2075,6 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, * shared dispatch. */ query->dispatchmgr = res->dispatchmgr; - query->dispatch = NULL; - query->exclusivesocket = false; - query->tcpsocket = NULL; if (res->view->peers != NULL) { dns_peer_t *peer = NULL; isc_netaddr_t dstip; @@ -2146,12 +2135,10 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, goto cleanup_query; } -#ifndef BROKEN_TCP_BIND_BEFORE_CONNECT result = isc_socket_bind(query->tcpsocket, &addr, 0); if (result != ISC_R_SUCCESS) { goto cleanup_socket; } -#endif /* ifndef BROKEN_TCP_BIND_BEFORE_CONNECT */ /* * A dispatch will be created once the connect succeeds. @@ -2215,10 +2202,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, INSIST(query->dispatch != NULL); } - query->dispentry = NULL; query->fctx = fctx; /* reference added by caller */ - query->tsig = NULL; - query->tsigkey = NULL; ISC_LINK_INIT(query, link); query->magic = QUERY_MAGIC; @@ -4971,13 +4955,13 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, const isc_sockaddr_t *client, unsigned int options, unsigned int bucketnum, unsigned int depth, isc_counter_t *qc, fetchctx_t **fctxp) { - fetchctx_t *fctx; + fetchctx_t *fctx = NULL; isc_result_t result; isc_result_t iresult; isc_interval_t interval; unsigned int findoptions = 0; char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + 1]; - isc_mem_t *mctx; + isc_mem_t *mctx = NULL; size_t p; bool try_stale; @@ -4988,8 +4972,23 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, mctx = res->buckets[bucketnum].mctx; fctx = isc_mem_get(mctx, sizeof(*fctx)); + *fctx = (fetchctx_t){ + .res = res, + .type = type, + .qmintype = type, + .options = options, + .bucketnum = bucketnum, + .dbucketnum = RES_NOBUCKET, + .state = fetchstate_init, + .depth = depth, + .qmin_labels = 1, + .fwdpolicy = dns_fwdpolicy_none, + .result = ISC_R_FAILURE, + .exitline = -1 /* sentinel */ + }; + + FCTXTRACE("create"); - fctx->qc = NULL; if (qc != NULL) { isc_counter_attach(qc, &fctx->qc); } else { @@ -5010,7 +5009,6 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_format(type, buf + p, sizeof(buf) - p); fctx->info = isc_mem_strdup(mctx, buf); - FCTXTRACE("create"); dns_name_init(&fctx->name, NULL); dns_name_dup(name, mctx, &fctx->name); dns_name_init(&fctx->qminname, NULL); @@ -5018,28 +5016,12 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, dns_name_init(&fctx->domain, NULL); dns_rdataset_init(&fctx->nameservers); - fctx->type = type; - fctx->qmintype = type; - fctx->options = options; /* * Note! We do not attach to the task. We are relying on the * resolver to ensure that this task doesn't go away while we are * using it. */ - fctx->res = res; isc_refcount_init(&fctx->references, 0); - fctx->bucketnum = bucketnum; - fctx->dbucketnum = RES_NOBUCKET; - fctx->state = fetchstate_init; - fctx->want_shutdown = false; - fctx->cloned = false; - fctx->depth = depth; - fctx->minimized = false; - fctx->ip6arpaskip = false; - fctx->forwarding = false; - fctx->qmin_labels = 1; - fctx->qmin_warning = ISC_R_SUCCESS; - fctx->qminfetch = NULL; dns_rdataset_init(&fctx->qminrrset); dns_name_init(&fctx->qmindcname, NULL); isc_stdtime_get(&fctx->now); @@ -5049,49 +5031,21 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, ISC_LIST_INIT(fctx->forwaddrs); ISC_LIST_INIT(fctx->altaddrs); ISC_LIST_INIT(fctx->forwarders); - fctx->fwdpolicy = dns_fwdpolicy_none; ISC_LIST_INIT(fctx->bad); ISC_LIST_INIT(fctx->edns); ISC_LIST_INIT(fctx->bad_edns); ISC_LIST_INIT(fctx->validators); - fctx->validator = NULL; - fctx->find = NULL; - fctx->altfind = NULL; - fctx->pending = 0; - fctx->restarts = 0; - fctx->querysent = 0; - fctx->referrals = 0; TIME_NOW(&fctx->start); - fctx->timeouts = 0; - fctx->lamecount = 0; - fctx->quotacount = 0; - fctx->adberr = 0; - fctx->neterr = 0; - fctx->badresp = 0; - fctx->findfail = 0; - fctx->valfail = 0; - fctx->result = ISC_R_FAILURE; - fctx->vresult = ISC_R_SUCCESS; - fctx->exitline = -1; /* sentinel */ - fctx->logged = false; atomic_init(&fctx->attributes, 0); - fctx->spilled = false; - fctx->nqueries = 0; - fctx->rand_buf = 0; - fctx->rand_bits = 0; - fctx->timeout = false; - fctx->addrinfo = NULL; + if (client != NULL) { isc_sockaddr_format(client, fctx->clientstr, sizeof(fctx->clientstr)); } else { strlcpy(fctx->clientstr, "", sizeof(fctx->clientstr)); } - fctx->ns_ttl = 0; - fctx->ns_ttl_ok = false; dns_name_init(&fctx->nsname, NULL); - fctx->nsfetch = NULL; dns_rdataset_init(&fctx->nsrrset); if (domain == NULL) { @@ -10235,12 +10189,6 @@ destroy(dns_resolver_t *res) { dns_resolver_reset_ds_digests(res); dns_badcache_destroy(&res->badcache); dns_resolver_resetmustbesecure(res); -#if USE_ALGLOCK - isc_rwlock_destroy(&res->alglock); -#endif /* if USE_ALGLOCK */ -#if USE_MBSLOCK - isc_rwlock_destroy(&res->mbslock); -#endif /* if USE_MBSLOCK */ isc_timer_detach(&res->spillattimer); res->magic = 0; isc_mem_put(res->mctx, res, sizeof(*res)); @@ -10322,7 +10270,7 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, unsigned int options, dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, dns_resolver_t **resp) { - dns_resolver_t *res; + dns_resolver_t *res = NULL; isc_result_t result = ISC_R_SUCCESS; unsigned int i, buckets_created = 0, dbuckets_created = 0; isc_task_t *task = NULL; @@ -10340,46 +10288,51 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, REQUIRE(dispatchmgr != NULL); REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL); - res = isc_mem_get(view->mctx, sizeof(*res)); RTRACE("create"); - res->mctx = view->mctx; - res->rdclass = view->rdclass; - res->socketmgr = socketmgr; - res->timermgr = timermgr; - res->taskmgr = taskmgr; - res->dispatchmgr = dispatchmgr; - res->view = view; - res->options = options; - res->lame_ttl = 0; + res = isc_mem_get(view->mctx, sizeof(*res)); + *res = (dns_resolver_t){ .mctx = view->mctx, + .rdclass = view->rdclass, + .socketmgr = socketmgr, + .timermgr = timermgr, + .taskmgr = taskmgr, + .dispatchmgr = dispatchmgr, + .view = view, + .options = options, + .udpsize = DEFAULT_EDNS_BUFSIZE, + .spillatmin = 10, + .spillat = 10, + .spillatmax = 100, + .retryinterval = 30000, + .nonbackofftries = 3, + .query_timeout = DEFAULT_QUERY_TIMEOUT, + .maxdepth = DEFAULT_RECURSION_DEPTH, + .maxqueries = DEFAULT_MAX_QUERIES, + .nbuckets = ntasks, + .activebuckets = ntasks, + .querydscp4 = -1, + .querydscp6 = -1 }; + + res->quotaresp[dns_quotatype_zone] = DNS_R_DROP; + res->quotaresp[dns_quotatype_server] = DNS_R_SERVFAIL; + isc_refcount_init(&res->references, 1); + atomic_init(&res->exiting, false); + atomic_init(&res->priming, false); + atomic_init(&res->zspill, 0); + atomic_init(&res->nfctx, 0); + ISC_LIST_INIT(res->whenshutdown); ISC_LIST_INIT(res->alternates); - res->udpsize = DEFAULT_EDNS_BUFSIZE; - res->algorithms = NULL; - res->digests = NULL; - res->badcache = NULL; + result = dns_badcache_init(res->mctx, DNS_RESOLVER_BADCACHESIZE, &res->badcache); if (result != ISC_R_SUCCESS) { goto cleanup_res; } - res->mustbesecure = NULL; - res->spillatmin = res->spillat = 10; - res->spillatmax = 100; - res->spillattimer = NULL; - atomic_init(&res->zspill, 0); - res->zero_no_soa_ttl = false; - res->retryinterval = 30000; - res->nonbackofftries = 3; - res->query_timeout = DEFAULT_QUERY_TIMEOUT; - res->maxdepth = DEFAULT_RECURSION_DEPTH; - res->maxqueries = DEFAULT_MAX_QUERIES; - res->quotaresp[dns_quotatype_zone] = DNS_R_DROP; - res->quotaresp[dns_quotatype_server] = DNS_R_SERVFAIL; - res->nbuckets = ntasks; + if (view->resstats != NULL) { isc_stats_set(view->resstats, ntasks, dns_resstatscounter_buckets); } - res->activebuckets = ntasks; + res->buckets = isc_mem_get(view->mctx, ntasks * sizeof(fctxbucket_t)); for (i = 0; i < ntasks; i++) { isc_mutex_init(&res->buckets[i].lock); @@ -10414,7 +10367,6 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, dbuckets_created++; } - res->dispatches4 = NULL; if (dispatchv4 != NULL) { dns_dispatchset_create(view->mctx, socketmgr, taskmgr, dispatchv4, &res->dispatches4, ndisp); @@ -10422,7 +10374,6 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, res->exclusivev4 = (dispattr & DNS_DISPATCHATTR_EXCLUSIVE); } - res->dispatches6 = NULL; if (dispatchv6 != NULL) { dns_dispatchset_create(view->mctx, socketmgr, taskmgr, dispatchv6, &res->dispatches6, ndisp); @@ -10430,21 +10381,9 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, res->exclusivev6 = (dispattr & DNS_DISPATCHATTR_EXCLUSIVE); } - res->querydscp4 = -1; - res->querydscp6 = -1; - isc_refcount_init(&res->references, 1); - atomic_init(&res->exiting, false); - res->frozen = false; - ISC_LIST_INIT(res->whenshutdown); - atomic_init(&res->priming, false); - res->primefetch = NULL; - - atomic_init(&res->nfctx, 0); - isc_mutex_init(&res->lock); isc_mutex_init(&res->primelock); - task = NULL; result = isc_task_create(taskmgr, 0, &task); if (result != ISC_R_SUCCESS) { goto cleanup_primelock; @@ -10459,13 +10398,6 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, goto cleanup_primelock; } -#if USE_ALGLOCK - isc_rwlock_init(&res->alglock, 0, 0); -#endif /* if USE_ALGLOCK */ -#if USE_MBSLOCK - isc_rwlock_init(&res->mbslock, 0, 0); -#endif /* if USE_MBSLOCK */ - res->magic = RES_MAGIC; *resp = res; @@ -11279,15 +11211,9 @@ void dns_resolver_reset_algorithms(dns_resolver_t *resolver) { REQUIRE(VALID_RESOLVER(resolver)); -#if USE_ALGLOCK - RWLOCK(&resolver->alglock, isc_rwlocktype_write); -#endif /* if USE_ALGLOCK */ if (resolver->algorithms != NULL) { dns_rbt_destroy(&resolver->algorithms); } -#if USE_ALGLOCK - RWUNLOCK(&resolver->alglock, isc_rwlocktype_write); -#endif /* if USE_ALGLOCK */ } isc_result_t @@ -11310,9 +11236,6 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, const dns_name_t *name, return (ISC_R_RANGE); } -#if USE_ALGLOCK - RWLOCK(&resolver->alglock, isc_rwlocktype_write); -#endif /* if USE_ALGLOCK */ if (resolver->algorithms == NULL) { result = dns_rbt_create(resolver->mctx, free_algorithm, resolver->mctx, &resolver->algorithms); @@ -11359,9 +11282,6 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, const dns_name_t *name, } result = ISC_R_SUCCESS; cleanup: -#if USE_ALGLOCK - RWUNLOCK(&resolver->alglock, isc_rwlocktype_write); -#endif /* if USE_ALGLOCK */ return (result); } @@ -11383,9 +11303,6 @@ dns_resolver_algorithm_supported(dns_resolver_t *resolver, return (false); } -#if USE_ALGLOCK - RWLOCK(&resolver->alglock, isc_rwlocktype_read); -#endif /* if USE_ALGLOCK */ if (resolver->algorithms == NULL) { goto unlock; } @@ -11399,9 +11316,6 @@ dns_resolver_algorithm_supported(dns_resolver_t *resolver, } } unlock: -#if USE_ALGLOCK - RWUNLOCK(&resolver->alglock, isc_rwlocktype_read); -#endif /* if USE_ALGLOCK */ if (found) { return (false); } @@ -11421,15 +11335,9 @@ void dns_resolver_reset_ds_digests(dns_resolver_t *resolver) { REQUIRE(VALID_RESOLVER(resolver)); -#if USE_ALGLOCK - RWLOCK(&resolver->alglock, isc_rwlocktype_write); -#endif /* if USE_ALGLOCK */ if (resolver->digests != NULL) { dns_rbt_destroy(&resolver->digests); } -#if USE_ALGLOCK - RWUNLOCK(&resolver->alglock, isc_rwlocktype_write); -#endif /* if USE_ALGLOCK */ } isc_result_t @@ -11451,9 +11359,6 @@ dns_resolver_disable_ds_digest(dns_resolver_t *resolver, const dns_name_t *name, return (ISC_R_RANGE); } -#if USE_ALGLOCK - RWLOCK(&resolver->alglock, isc_rwlocktype_write); -#endif /* if USE_ALGLOCK */ if (resolver->digests == NULL) { result = dns_rbt_create(resolver->mctx, free_digest, resolver->mctx, &resolver->digests); @@ -11496,9 +11401,6 @@ dns_resolver_disable_ds_digest(dns_resolver_t *resolver, const dns_name_t *name, } result = ISC_R_SUCCESS; cleanup: -#if USE_ALGLOCK - RWUNLOCK(&resolver->alglock, isc_rwlocktype_write); -#endif /* if USE_ALGLOCK */ return (result); } @@ -11514,9 +11416,6 @@ dns_resolver_ds_digest_supported(dns_resolver_t *resolver, REQUIRE(VALID_RESOLVER(resolver)); -#if USE_ALGLOCK - RWLOCK(&resolver->alglock, isc_rwlocktype_read); -#endif /* if USE_ALGLOCK */ if (resolver->digests == NULL) { goto unlock; } @@ -11530,9 +11429,6 @@ dns_resolver_ds_digest_supported(dns_resolver_t *resolver, } } unlock: -#if USE_ALGLOCK - RWUNLOCK(&resolver->alglock, isc_rwlocktype_read); -#endif /* if USE_ALGLOCK */ if (found) { return (false); } @@ -11543,15 +11439,9 @@ void dns_resolver_resetmustbesecure(dns_resolver_t *resolver) { REQUIRE(VALID_RESOLVER(resolver)); -#if USE_MBSLOCK - RWLOCK(&resolver->mbslock, isc_rwlocktype_write); -#endif /* if USE_MBSLOCK */ if (resolver->mustbesecure != NULL) { dns_rbt_destroy(&resolver->mustbesecure); } -#if USE_MBSLOCK - RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write); -#endif /* if USE_MBSLOCK */ } static bool yes = true, no = false; @@ -11563,9 +11453,6 @@ dns_resolver_setmustbesecure(dns_resolver_t *resolver, const dns_name_t *name, REQUIRE(VALID_RESOLVER(resolver)); -#if USE_MBSLOCK - RWLOCK(&resolver->mbslock, isc_rwlocktype_write); -#endif /* if USE_MBSLOCK */ if (resolver->mustbesecure == NULL) { result = dns_rbt_create(resolver->mctx, NULL, NULL, &resolver->mustbesecure); @@ -11576,9 +11463,6 @@ dns_resolver_setmustbesecure(dns_resolver_t *resolver, const dns_name_t *name, result = dns_rbt_addname(resolver->mustbesecure, name, value ? &yes : &no); cleanup: -#if USE_MBSLOCK - RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write); -#endif /* if USE_MBSLOCK */ return (result); } @@ -11590,9 +11474,6 @@ dns_resolver_getmustbesecure(dns_resolver_t *resolver, const dns_name_t *name) { REQUIRE(VALID_RESOLVER(resolver)); -#if USE_MBSLOCK - RWLOCK(&resolver->mbslock, isc_rwlocktype_read); -#endif /* if USE_MBSLOCK */ if (resolver->mustbesecure == NULL) { goto unlock; } @@ -11601,9 +11482,6 @@ dns_resolver_getmustbesecure(dns_resolver_t *resolver, const dns_name_t *name) { value = *(bool *)data; } unlock: -#if USE_MBSLOCK - RWUNLOCK(&resolver->mbslock, isc_rwlocktype_read); -#endif /* if USE_MBSLOCK */ return (value); } diff --git a/lib/ns/include/ns/interfacemgr.h b/lib/ns/include/ns/interfacemgr.h index 9a975c6eb5..9dbde5f76c 100644 --- a/lib/ns/include/ns/interfacemgr.h +++ b/lib/ns/include/ns/interfacemgr.h @@ -74,23 +74,21 @@ struct ns_interface { isc_sockaddr_t addr; /*%< Address and port. */ unsigned int flags; /*%< Interface flags */ char name[32]; /*%< Null terminated. */ - dns_dispatch_t * udpdispatch[MAX_UDP_DISPATCH]; - /*%< UDP dispatchers. */ - isc_socket_t * tcpsocket; /*%< TCP socket. */ - isc_nmsocket_t *udplistensocket; - isc_nmsocket_t *tcplistensocket; - isc_nmsocket_t *http_listensocket; - isc_nmsocket_t *http_secure_listensocket; - isc_dscp_t dscp; /*%< "listen-on" DSCP value */ - isc_refcount_t ntcpaccepting; /*%< Number of clients - * ready to accept new - * TCP connections on this - * interface */ - isc_refcount_t ntcpactive; /*%< Number of clients - * servicing TCP queries - * (whether accepting or - * connected) */ - int nudpdispatch; /*%< Number of UDP dispatches */ + isc_socket_t * tcpsocket; /*%< TCP socket. */ + isc_nmsocket_t * udplistensocket; + isc_nmsocket_t * tcplistensocket; + isc_nmsocket_t * http_listensocket; + isc_nmsocket_t * http_secure_listensocket; + isc_dscp_t dscp; /*%< "listen-on" DSCP value */ + isc_refcount_t ntcpaccepting; /*%< Number of clients + * ready to accept new + * TCP connections on this + * interface */ + isc_refcount_t ntcpactive; /*%< Number of clients + * servicing TCP queries + * (whether accepting or + * connected) */ + ns_clientmgr_t *clientmgr; /*%< Client manager. */ ISC_LINK(ns_interface_t) link; }; @@ -103,8 +101,8 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr, isc_nm_t *nm, dns_dispatchmgr_t *dispatchmgr, isc_task_t *task, - unsigned int udpdisp, dns_geoip_databases_t *geoip, - int ncpus, ns_interfacemgr_t **mgrp); + dns_geoip_databases_t *geoip, int ncpus, + ns_interfacemgr_t **mgrp); /*%< * Create a new interface manager. * diff --git a/lib/ns/interfacemgr.c b/lib/ns/interfacemgr.c index 6f94d39173..045c74f9cc 100644 --- a/lib/ns/interfacemgr.c +++ b/lib/ns/interfacemgr.c @@ -86,7 +86,6 @@ struct ns_interfacemgr { ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces */ ISC_LIST(isc_sockaddr_t) listenon; int backlog; /*%< Listen queue size */ - unsigned int udpdisp; /*%< UDP dispatch count */ atomic_bool shuttingdown; /*%< Interfacemgr shutting down */ ns_clientmgr_t **clientmgrs; /*%< Client managers */ #ifdef USE_ROUTE_SOCKET @@ -183,8 +182,8 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr, isc_nm_t *nm, dns_dispatchmgr_t *dispatchmgr, isc_task_t *task, - unsigned int udpdisp, dns_geoip_databases_t *geoip, - int ncpus, ns_interfacemgr_t **mgrp) { + dns_geoip_databases_t *geoip, int ncpus, + ns_interfacemgr_t **mgrp) { isc_result_t result; ns_interfacemgr_t *mgr; @@ -220,7 +219,6 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx, mgr->generation = 1; mgr->listenon4 = NULL; mgr->listenon6 = NULL; - mgr->udpdisp = udpdisp; mgr->ncpus = ncpus; atomic_init(&mgr->shuttingdown, false); @@ -404,8 +402,7 @@ ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) { static isc_result_t ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name, ns_interface_t **ifpret) { - ns_interface_t *ifp; - int disp; + ns_interface_t *ifp = NULL; REQUIRE(NS_INTERFACEMGR_VALID(mgr)); @@ -418,10 +415,6 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, isc_mutex_init(&ifp->lock); - for (disp = 0; disp < MAX_UDP_DISPATCH; disp++) { - ifp->udpdispatch[disp] = NULL; - } - /* * Create a single TCP client object. It will replace itself * with a new one as soon as it gets a connection, so the actual @@ -705,12 +698,6 @@ ns_interface_destroy(ns_interface_t *ifp) { ns_interface_shutdown(ifp); - for (int disp = 0; disp < ifp->nudpdispatch; disp++) { - if (ifp->udpdispatch[disp] != NULL) { - dns_dispatch_detach(&(ifp->udpdispatch[disp])); - } - } - if (ifp->tcpsocket != NULL) { isc_socket_detach(&ifp->tcpsocket); } diff --git a/lib/ns/tests/nstest.c b/lib/ns/tests/nstest.c index 50f6e2ad3c..ffcf23adfa 100644 --- a/lib/ns/tests/nstest.c +++ b/lib/ns/tests/nstest.c @@ -236,8 +236,8 @@ create_managers(void) { CHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); CHECK(ns_interfacemgr_create(mctx, sctx, taskmgr, timermgr, socketmgr, - netmgr, dispatchmgr, maintask, ncpus, NULL, - ncpus, &interfacemgr)); + netmgr, dispatchmgr, maintask, NULL, ncpus, + &interfacemgr)); CHECK(ns_listenlist_default(mctx, port, -1, true, &listenon)); ns_interfacemgr_setlistenon4(interfacemgr, listenon);