diff --git a/bin/named/server.c b/bin/named/server.c index dd929b881b..31c9af5572 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -1258,7 +1258,6 @@ 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 = 0; const cfg_obj_t *obj = NULL; isc_dscp_t dscp = -1; @@ -1315,7 +1314,7 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af, } } - result = dns_dispatch_createudp(named_g_dispatchmgr, &sa, attrs, &disp); + result = dns_dispatch_createudp(named_g_dispatchmgr, &sa, &disp); if (result != ISC_R_SUCCESS) { isc_sockaddr_t any; char buf[ISC_SOCKADDR_FORMATSIZE]; @@ -10330,7 +10329,6 @@ named_add_reserved_dispatch(named_server_t *server, in_port_t port; char addrbuf[ISC_SOCKADDR_FORMATSIZE]; isc_result_t result; - unsigned int attrs = 0; REQUIRE(NAMED_SERVER_VALID(server)); @@ -10358,7 +10356,7 @@ named_add_reserved_dispatch(named_server_t *server, dispatch->dispatch = NULL; result = dns_dispatch_createudp(named_g_dispatchmgr, &dispatch->addr, - attrs, &dispatch->dispatch); + &dispatch->dispatch); if (result != ISC_R_SUCCESS) { goto cleanup; } diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 320e3812c0..4aa9289cb2 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -936,14 +936,14 @@ setup_system(void) { if (have_ipv6) { isc_sockaddr_any6(&bind_any6); - result = dns_dispatch_createudp(dispatchmgr, &bind_any6, 0, + result = dns_dispatch_createudp(dispatchmgr, &bind_any6, &dispatchv6); check_result(result, "dns_dispatch_createudp (v6)"); } if (have_ipv4) { isc_sockaddr_any(&bind_any); - result = dns_dispatch_createudp(dispatchmgr, &bind_any, 0, + result = dns_dispatch_createudp(dispatchmgr, &bind_any, &dispatchv4); check_result(result, "dns_dispatch_createudp (v4)"); } diff --git a/bin/tests/system/pipelined/pipequeries.c b/bin/tests/system/pipelined/pipequeries.c index 238e04c0f1..342ff12039 100644 --- a/bin/tests/system/pipelined/pipequeries.c +++ b/bin/tests/system/pipelined/pipequeries.c @@ -270,7 +270,7 @@ main(int argc, char *argv[]) { RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr)); RUNCHECK(dns_dispatch_createudp( - dispatchmgr, have_src ? &srcaddr : &bind_any, 0, &dispatchv4)); + dispatchmgr, have_src ? &srcaddr : &bind_any, &dispatchv4)); RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4, NULL, &requestmgr)); diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c index ab10793a12..79cfdeeb2c 100644 --- a/bin/tests/system/tkey/keycreate.c +++ b/bin/tests/system/tkey/keycreate.c @@ -228,8 +228,7 @@ main(int argc, char *argv[]) { RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr)); isc_sockaddr_any(&bind_any); - RUNCHECK( - dns_dispatch_createudp(dispatchmgr, &bind_any, 0, &dispatchv4)); + RUNCHECK(dns_dispatch_createudp(dispatchmgr, &bind_any, &dispatchv4)); RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4, NULL, &requestmgr)); diff --git a/bin/tests/system/tkey/keydelete.c b/bin/tests/system/tkey/keydelete.c index c81c306a8c..f5a2a17472 100644 --- a/bin/tests/system/tkey/keydelete.c +++ b/bin/tests/system/tkey/keydelete.c @@ -171,8 +171,7 @@ main(int argc, char **argv) { RUNCHECK(isc_task_create(taskmgr, 0, &task)); RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr)); isc_sockaddr_any(&bind_any); - RUNCHECK( - dns_dispatch_createudp(dispatchmgr, &bind_any, 0, &dispatchv4)); + RUNCHECK(dns_dispatch_createudp(dispatchmgr, &bind_any, &dispatchv4)); RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4, NULL, &requestmgr)); diff --git a/bin/tools/mdig.c b/bin/tools/mdig.c index 5be81925d9..2c88c90908 100644 --- a/bin/tools/mdig.c +++ b/bin/tools/mdig.c @@ -2129,7 +2129,7 @@ main(int argc, char *argv[]) { isc_sockaddr_any6(&bind_any); } RUNCHECK(dns_dispatch_createudp( - dispatchmgr, have_src ? &srcaddr : &bind_any, 0, &dispatchvx)); + dispatchmgr, have_src ? &srcaddr : &bind_any, &dispatchvx)); RUNCHECK(dns_requestmgr_create( mctx, taskmgr, dispatchmgr, have_ipv4 ? dispatchvx : NULL, diff --git a/lib/dns/client.c b/lib/dns/client.c index 83b21bb12e..9902e2d571 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -212,7 +212,7 @@ getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, localaddr = &anyaddr; } - result = dns_dispatch_createudp(dispatchmgr, localaddr, 0, &disp); + result = dns_dispatch_createudp(dispatchmgr, localaddr, &disp); if (result == ISC_R_SUCCESS) { *dispp = disp; } diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 0475d67055..341ac86308 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -89,6 +90,7 @@ struct dns_dispentry { bool canceled; ISC_LINK(dns_dispentry_t) link; ISC_LINK(dns_dispentry_t) alink; + ISC_LINK(dns_dispentry_t) plink; }; /*% @@ -98,6 +100,12 @@ struct dns_dispentry { #define DNS_DISPATCH_UDPBUFSIZE 4096 #endif /* ifndef DNS_DISPATCH_UDPBUFSIZE */ +typedef enum { + DNS_DISPATCHSTATE_NONE = 0UL, + DNS_DISPATCHSTATE_CONNECTING, + DNS_DISPATCHSTATE_CONNECTED +} dns_dispatchstate_t; + struct dns_dispatch { /* Unlocked. */ unsigned int magic; /*%< magic */ @@ -113,10 +121,11 @@ struct dns_dispatch { /* Locked by "lock". */ isc_mutex_t lock; /*%< locks all below */ isc_socktype_t socktype; - unsigned int attributes; + atomic_uint_fast32_t state; isc_refcount_t references; unsigned int shutdown_out : 1; + ISC_LIST(dns_dispentry_t) pending; ISC_LIST(dns_dispentry_t) active; unsigned int nsockets; @@ -193,15 +202,15 @@ static void dispatch_free(dns_dispatch_t **dispp); static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, - unsigned int attributes, dns_dispatch_t **dispp); + dns_dispatch_t **dispp); 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 inline isc_nmhandle_t * -getentryhandle(dns_dispentry_t *resp); static void -startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp); +startrecv(isc_nmhandle_t *handle, dns_dispatch_t *disp, dns_dispentry_t *resp); +void +dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp, int32_t timeout); #define LVL(x) ISC_LOG_DEBUG(x) @@ -327,7 +336,13 @@ deactivate_dispentry(dns_dispatch_t *disp, dns_dispentry_t *resp) { ISC_LIST_UNLINK(disp->active, resp, alink); } + if (ISC_LINK_LINKED(resp, plink)) { + ISC_LIST_UNLINK(disp->pending, resp, plink); + } + if (resp->handle != NULL) { + INSIST(disp->socktype == isc_socktype_udp); + isc_nm_cancelread(resp->handle); isc_nmhandle_detach(&resp->handle); } @@ -418,6 +433,11 @@ dispentry_detach(dns_dispentry_t **respp) { * if event queue is not empty, queue. else, send. * restart. */ + +/* FIXME: If we read invalid packet, we never receive next that could be valid + * and we also don't notify the read callback + */ + static void udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, void *arg) { @@ -431,7 +451,6 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, isc_netaddr_t netaddr; int match; dispatch_cb_t response = NULL; - bool nomore = true; REQUIRE(VALID_RESPONSE(resp)); REQUIRE(VALID_DISPATCH(resp->disp)); @@ -461,14 +480,6 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, peer = isc_nmhandle_peeraddr(handle); isc_netaddr_fromsockaddr(&netaddr, &peer); - /* if (eresult == ISC_R_TIMEDOUT && resp->timedout != NULL) { */ - /* resp->timedout(handle, ISC_R_TIMEDOUT, resp->arg); */ - /* if (isc_nmhandle_timer_running(handle)) { */ - /* nomore = false; */ - /* goto unlock; */ - /* } */ - /* } */ - if (eresult != ISC_R_SUCCESS) { /* * This is most likely a network error on a connected @@ -547,9 +558,7 @@ unlock: response(eresult, region, resp->arg); } - if (nomore) { - dispentry_detach(&resp); - } + dispentry_detach(&resp); } /* @@ -570,9 +579,8 @@ unlock: static void tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, void *arg) { - dns_dispentry_t *resp0 = (dns_dispentry_t *)arg; + dns_dispatch_t *disp = (dns_dispatch_t *)arg; dns_dispentry_t *resp = NULL; - dns_dispatch_t *disp = NULL; dns_messageid_t id; isc_result_t dres; unsigned int flags; @@ -583,10 +591,7 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, isc_buffer_t source; isc_sockaddr_t peer; - REQUIRE(VALID_RESPONSE(resp0)); - REQUIRE(VALID_DISPATCH(resp0->disp)); - - disp = resp0->disp; + REQUIRE(VALID_DISPATCH(disp)); qid = disp->mgr->qid; @@ -597,46 +602,43 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, peer = isc_nmhandle_peeraddr(handle); - if (eresult != ISC_R_SUCCESS) { - switch (eresult) { - case ISC_R_CANCELED: - dispatch_log(disp, LVL(90), "shutting down on cancel"); - break; + switch (eresult) { + case ISC_R_SUCCESS: + /* got our answer */ + break; + case ISC_R_CANCELED: + dispatch_log(disp, LVL(90), "shutting down on cancel"); + goto unlock; - case ISC_R_EOF: - dispatch_log(disp, LVL(90), "shutting down on EOF"); - break; + case ISC_R_EOF: + dispatch_log(disp, LVL(90), "shutting down on EOF"); + goto unlock; - case ISC_R_TIMEDOUT: - /* - * Time out the first active response for which - * no event has already been sent. - * FIXME: The code doesn't match the description - */ - for (resp = ISC_LIST_HEAD(disp->active); resp != NULL; - resp = ISC_LIST_NEXT(resp, alink)) - { - ISC_LIST_UNLINK(disp->active, resp, alink); - ISC_LIST_APPEND(disp->active, resp, alink); - break; - } - break; + case ISC_R_TIMEDOUT: + /* + * Time out the first active response for which + * no event has already been sent. + */ + resp = ISC_LIST_HEAD(disp->active); + INSIST(resp != NULL); - default: - if (eresult == ISC_R_CONNECTIONRESET) { - level = ISC_LOG_INFO; - } else { - level = ISC_LOG_ERROR; - } + ISC_LIST_UNLINK(disp->active, resp, alink); + ISC_LIST_APPEND(disp->active, resp, alink); - isc_sockaddr_format(&peer, buf, sizeof(buf)); - dispatch_log(disp, level, - "shutting down due to TCP " - "receive error: %s: %s", - buf, isc_result_totext(eresult)); - break; + goto unlock; + + default: + if (eresult == ISC_R_CONNECTIONRESET) { + level = ISC_LOG_INFO; + } else { + level = ISC_LOG_ERROR; } + isc_sockaddr_format(&peer, buf, sizeof(buf)); + dispatch_log(disp, level, + "shutting down due to TCP " + "receive error: %s: %s", + buf, isc_result_totext(eresult)); goto unlock; } @@ -684,22 +686,18 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, bucket, (resp == NULL ? "not found" : "found")); UNLOCK(&qid->lock); - if (resp == NULL) { - goto unlock; - } - next: - startrecv(disp, resp0); + /* Restart the reading from the TCP socket */ + dispatch_getnext(disp, resp, -1); unlock: - isc_nmhandle_detach(&handle); UNLOCK(&disp->lock); - dispentry_detach(&resp0); - if (resp != NULL) { resp->response(eresult, region, resp->arg); } + + dns_dispatch_detach(&disp); } /*% @@ -936,8 +934,8 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) { * Allocate and set important limits. */ static void -dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type, int pf, - unsigned int attributes, dns_dispatch_t **dispp) { +dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type, + dns_dispatch_t **dispp) { dns_dispatch_t *disp = NULL; REQUIRE(VALID_DISPATCHMGR(mgr)); @@ -955,38 +953,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type, int pf, isc_refcount_init(&disp->references, 1); ISC_LINK_INIT(disp, link); ISC_LIST_INIT(disp->active); - - switch (type) { - case isc_socktype_tcp: - disp->attributes |= DNS_DISPATCHATTR_TCP; - break; - case isc_socktype_udp: - disp->attributes |= DNS_DISPATCHATTR_UDP; - break; - default: - INSIST(0); - ISC_UNREACHABLE(); - } - - switch (pf) { - case PF_INET: - disp->attributes |= DNS_DISPATCHATTR_IPV4; - break; - case PF_INET6: - disp->attributes |= DNS_DISPATCHATTR_IPV6; - break; - default: - INSIST(0); - ISC_UNREACHABLE(); - } - - /* - * Set whatever attributes were passed in that haven't been - * reset automatically by the code above. - */ - attributes &= ~(DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP | - DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6); - disp->attributes |= attributes; + ISC_LIST_INIT(disp->pending); isc_mutex_init(&disp->lock); @@ -1022,10 +989,9 @@ dispatch_free(dns_dispatch_t **dispp) { isc_result_t dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, - const isc_sockaddr_t *destaddr, unsigned int attributes, - isc_dscp_t dscp, dns_dispatch_t **dispp) { + const isc_sockaddr_t *destaddr, isc_dscp_t dscp, + dns_dispatch_t **dispp) { dns_dispatch_t *disp = NULL; - int pf; REQUIRE(VALID_DISPATCHMGR(mgr)); REQUIRE(destaddr != NULL); @@ -1034,14 +1000,15 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, LOCK(&mgr->lock); - pf = isc_sockaddr_pf(destaddr); - dispatch_allocate(mgr, isc_socktype_tcp, pf, attributes, &disp); + dispatch_allocate(mgr, isc_socktype_tcp, &disp); disp->peer = *destaddr; if (localaddr != NULL) { disp->local = *localaddr; } else { + int pf; + pf = isc_sockaddr_pf(destaddr); isc_sockaddr_anyofpf(&disp->local, pf); isc_sockaddr_setport(&disp->local, 0); } @@ -1049,6 +1016,8 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, /* * Append it to the dispatcher list. */ + + /* FIXME: There should be a lookup hashtable here */ ISC_LIST_APPEND(mgr->list, disp, link); UNLOCK(&mgr->lock); @@ -1062,28 +1031,25 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, return (ISC_R_SUCCESS); } -#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 = NULL; - unsigned int attributes, mask; REQUIRE(VALID_DISPATCHMGR(mgr)); REQUIRE(destaddr != NULL); + REQUIRE(connected != NULL); REQUIRE(dispp != NULL && *dispp == NULL); - /* First pass */ - attributes = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_CONNECTED; - mask = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_PRIVATE | - DNS_DISPATCHATTR_CONNECTED; + /* First pass, look for connected TCP dispatches */ + *connected = true; LOCK(&mgr->lock); again: - disp = ISC_LIST_HEAD(mgr->list); - while (disp != NULL && *dispp == NULL) { + for (disp = ISC_LIST_HEAD(mgr->list); disp != NULL && *dispp == NULL; + disp = ISC_LIST_NEXT(disp, link)) + { isc_sockaddr_t sockname; isc_sockaddr_t peeraddr; @@ -1097,23 +1063,41 @@ again: peeraddr = disp->peer; } - if (ATTRMATCH(disp->attributes, attributes, mask) && - (localaddr == NULL || - isc_sockaddr_eqaddr(localaddr, &disp->local))) + if (*connected == true && + atomic_load(&disp->state) != DNS_DISPATCHSTATE_CONNECTED) { - if (isc_sockaddr_equal(destaddr, &peeraddr) && - (localaddr == NULL || - isc_sockaddr_eqaddr(localaddr, &sockname))) + goto unlock; + } + + /* We don't reuse UDP sockets */ + if (disp->socktype != isc_socktype_tcp) { + goto unlock; + } + + /* Different destination address */ + if (!isc_sockaddr_equal(destaddr, &peeraddr)) { + goto unlock; + } + + /* Different local addr */ + if (localaddr != NULL) { + /* FIXME: This is weird as sockname == disp-local */ + if (!isc_sockaddr_eqaddr(localaddr, &disp->local) || + !isc_sockaddr_eqaddr(localaddr, &sockname)) { - /* attach */ - dns_dispatch_attach(disp, dispp); - if (connected != NULL) { - *connected = true; - } + goto unlock; } } + + /* + * The conditions match: + * 1. socktype is TCP + * 2. destination address is same + * 3. local address is either NULL or same + */ + dns_dispatch_attach(disp, dispp); + unlock: UNLOCK(&disp->lock); - disp = ISC_LIST_NEXT(disp, link); } if (*dispp != NULL) { @@ -1121,10 +1105,9 @@ again: return (ISC_R_SUCCESS); } - if (connected != NULL) { - /* Second pass, only if connected != NULL */ - attributes = DNS_DISPATCHATTR_TCP; - connected = NULL; + if (*connected) { + /* Second pass, look also for not-yet-connected dispatch */ + *connected = false; goto again; } @@ -1134,7 +1117,7 @@ again: isc_result_t dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, - unsigned int attributes, dns_dispatch_t **dispp) { + dns_dispatch_t **dispp) { isc_result_t result; dns_dispatch_t *disp = NULL; @@ -1143,7 +1126,7 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, REQUIRE(dispp != NULL && *dispp == NULL); LOCK(&mgr->lock); - result = dispatch_createudp(mgr, localaddr, attributes, &disp); + result = dispatch_createudp(mgr, localaddr, &disp); if (result == ISC_R_SUCCESS) { *dispp = disp; } @@ -1154,19 +1137,17 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, - unsigned int attributes, dns_dispatch_t **dispp) { + dns_dispatch_t **dispp) { isc_result_t result = ISC_R_SUCCESS; dns_dispatch_t *disp = NULL; isc_sockaddr_t sa_any; - int pf; - pf = isc_sockaddr_pf(localaddr); - dispatch_allocate(mgr, isc_socktype_udp, pf, attributes, &disp); + dispatch_allocate(mgr, isc_socktype_udp, &disp); /* * Check whether this address/port is available locally. */ - isc_sockaddr_anyofpf(&sa_any, pf); + isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr)); if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) { result = isc_nm_checkaddr(localaddr, isc_socktype_udp); if (result != ISC_R_SUCCESS) { @@ -1207,7 +1188,7 @@ cleanup: } static void -dns_dispatch_destroy(dns_dispatch_t *disp) { +dispatch_destroy(dns_dispatch_t *disp) { dns_dispatchmgr_t *mgr = disp->mgr; LOCK(&mgr->lock); @@ -1223,8 +1204,9 @@ dns_dispatch_destroy(dns_dispatch_t *disp) { dispatch_free(&disp); - /* Because dispatch uses mgr->mctx, we must detach after freeing - * dispatch, not before + /* + * Because dispatch uses mgr->mctx, we must detach after freeing + * dispatch, not before. */ dns_dispatchmgr_detach(&mgr); } @@ -1253,10 +1235,11 @@ dns_dispatch_detach(dns_dispatch_t **dispp) { dispatch_log(disp, LVL(90), "detach: refcount %" PRIuFAST32, ref - 1); if (ref == 1) { LOCK(&disp->lock); - REQUIRE(ISC_LIST_EMPTY(disp->active)); + INSIST(ISC_LIST_EMPTY(disp->pending)); + INSIST(ISC_LIST_EMPTY(disp->active)); UNLOCK(&disp->lock); - dns_dispatch_destroy(disp); + dispatch_destroy(disp); } } @@ -1321,6 +1304,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, ISC_LINK_INIT(res, link); ISC_LINK_INIT(res, alink); + ISC_LINK_INIT(res, plink); if (disp->socktype == isc_socktype_udp) { isc_result_t result = setup_socket(disp, res, dest, &localport); @@ -1393,6 +1377,40 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, return (ISC_R_SUCCESS); } +void +dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp, int32_t timeout) { + REQUIRE(timeout <= UINT16_MAX); + + /* + * FIXME: Since there's no global timeout now, any call to getnext will + * always restart the read timer, so it's possible to keep the client + * connecting until end of times by just feeding it with invalid + * packets. + */ + switch (disp->socktype) { + case isc_socktype_udp: + dispentry_attach(resp, &(dns_dispentry_t *){ NULL }); + + if (timeout > 0) { + isc_nmhandle_settimeout(resp->handle, timeout); + } + isc_nm_read(resp->handle, udp_recv, resp); + + break; + case isc_socktype_tcp: + dns_dispatch_attach(disp, &(dns_dispatch_t *){ NULL }); + + if (timeout > 0) { + isc_nmhandle_settimeout(disp->handle, timeout); + } + isc_nm_read(disp->handle, tcp_recv, disp); + break; + default: + INSIST(0); + ISC_UNREACHABLE(); + } +} + isc_result_t dns_dispatch_getnext(dns_dispentry_t *resp) { dns_dispatch_t *disp = NULL; @@ -1404,7 +1422,7 @@ dns_dispatch_getnext(dns_dispentry_t *resp) { LOCK(&disp->lock); - startrecv(disp, resp); + dispatch_getnext(disp, resp, resp->timeout); UNLOCK(&disp->lock); @@ -1456,27 +1474,23 @@ dns_dispatch_removeresponse(dns_dispentry_t **respp) { * disp must be locked. */ static void -startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp) { +startrecv(isc_nmhandle_t *handle, dns_dispatch_t *disp, dns_dispentry_t *resp) { switch (disp->socktype) { case isc_socktype_udp: - REQUIRE(resp != NULL && resp->handle != NULL); + REQUIRE(resp != NULL && resp->handle == NULL); + isc_nmhandle_attach(handle, &resp->handle); dispentry_attach(resp, &(dns_dispentry_t *){ NULL }); isc_nm_read(resp->handle, udp_recv, resp); break; case isc_socktype_tcp: REQUIRE(resp != NULL && resp->handle == NULL); - REQUIRE(disp->handle != NULL); + REQUIRE(disp != NULL && disp->handle == NULL); - if (isc_nmhandle_timer_running(disp->handle)) { - isc_nmhandle_settimeout(disp->handle, resp->timeout); - break; - } - - isc_nmhandle_attach(disp->handle, &(isc_nmhandle_t *){ NULL }); - dispentry_attach(resp, &(dns_dispentry_t *){ NULL }); - isc_nm_read(disp->handle, tcp_recv, resp); + isc_nmhandle_attach(handle, &disp->handle); + dns_dispatch_attach(disp, &(dns_dispatch_t *){ NULL }); + isc_nm_read(disp->handle, tcp_recv, disp); break; default: @@ -1485,34 +1499,30 @@ startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp) { } } +/* + * FIXME: Split into tcp_connected() and udp_connected() + */ + static void disp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { dns_dispentry_t *resp = (dns_dispentry_t *)arg; + dns_dispentry_t *pending = NULL, *next = NULL; dns_dispatch_t *disp = resp->disp; - if (resp->canceled && eresult == ISC_R_SUCCESS) { - eresult = ISC_R_CANCELED; - goto detach; - } - if (eresult == ISC_R_SUCCESS) { - switch (disp->socktype) { - case isc_socktype_udp: - isc_nmhandle_attach(handle, &resp->handle); - startrecv(disp, resp); - break; - case isc_socktype_tcp: - REQUIRE(disp->handle == NULL); - LOCK(&disp->lock); - isc_nmhandle_attach(handle, &disp->handle); - disp->attributes |= DNS_DISPATCHATTR_CONNECTED; - UNLOCK(&disp->lock); - startrecv(disp, resp); - break; - default: - INSIST(0); - ISC_UNREACHABLE(); + if (resp->canceled) { + dispentry_detach(&resp); + return; } + + if (disp->socktype == isc_socktype_tcp) { + REQUIRE(atomic_compare_exchange_strong( + &disp->state, + &(uint_fast32_t){ DNS_DISPATCHSTATE_CONNECTING }, + DNS_DISPATCHSTATE_CONNECTED)); + } + + startrecv(handle, disp, resp); } if (MGR_IS_SHUTTINGDOWN(disp->mgr)) { @@ -1523,26 +1533,64 @@ disp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { resp->connected(eresult, NULL, resp->arg); } -detach: + for (pending = ISC_LIST_HEAD(disp->pending); pending != NULL; + pending = next) { + next = ISC_LIST_NEXT(pending, plink); + ISC_LIST_UNLINK(disp->pending, pending, plink); + + if (pending->connected != NULL) { + pending->connected(eresult, NULL, pending->arg); + } + dispentry_detach(&pending); + } + dispentry_detach(&resp); } isc_result_t dns_dispatch_connect(dns_dispentry_t *resp) { dns_dispatch_t *disp = NULL; - dns_dispentry_t *tmp = NULL; + uint_fast32_t state = DNS_DISPATCHSTATE_NONE; REQUIRE(VALID_RESPONSE(resp)); disp = resp->disp; - dispentry_attach(resp, &tmp); /* detached in disp_connected */ + /* This will be detached in disp_connected() */ + dispentry_attach(resp, &(dns_dispentry_t *){ NULL }); switch (disp->socktype) { case isc_socktype_tcp: - INSIST(disp->handle == NULL); - isc_nm_tcpdnsconnect(disp->mgr->nm, &disp->local, &disp->peer, - disp_connected, resp, resp->timeout, 0); + /* + * Check whether the dispatch was already connecting. + * If so, add resp to the pending responses. + */ + atomic_compare_exchange_strong(&disp->state, + (uint_fast32_t *)&state, + DNS_DISPATCHSTATE_CONNECTING); + + switch (state) { + case DNS_DISPATCHSTATE_NONE: + /* First connection, continue with connecting */ + INSIST(disp->handle == NULL); + isc_nm_tcpdnsconnect(disp->mgr->nm, &disp->local, + &disp->peer, disp_connected, resp, + resp->timeout, 0); + break; + case DNS_DISPATCHSTATE_CONNECTING: + ISC_LIST_APPEND(disp->pending, resp, plink); + return (ISC_R_SUCCESS); + case DNS_DISPATCHSTATE_CONNECTED: + /* We are already connected, call the connected cb */ + if (resp->connected != NULL) { + resp->connected(ISC_R_SUCCESS, NULL, resp->arg); + } + return (ISC_R_SUCCESS); + default: + INSIST(0); + ISC_UNREACHABLE(); + } + break; case isc_socktype_udp: isc_nm_udpconnect(disp->mgr->nm, &resp->local, &resp->peer, @@ -1571,31 +1619,15 @@ send_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { } void -dns_dispatch_read(dns_dispentry_t *resp, uint16_t timeout) { - REQUIRE(resp != NULL); +dns_dispatch_resume(dns_dispentry_t *resp, uint16_t timeout) { + dns_dispatch_t *disp = NULL; + REQUIRE(VALID_RESPONSE(resp)); - dns_dispatch_t *disp = resp->disp; - isc_nmhandle_t *handle = NULL; + disp = resp->disp; - switch (disp->socktype) { - case isc_socktype_udp: - REQUIRE(resp->handle != NULL); + REQUIRE(VALID_DISPATCH(disp)); - handle = resp->handle; - - break; - case isc_socktype_tcp: - REQUIRE(disp != NULL && disp->handle == NULL); - - handle = disp->handle; - break; - default: - INSIST(0); - ISC_UNREACHABLE(); - } - - isc_nmhandle_settimeout(handle, timeout); - startrecv(disp, resp); + dispatch_getnext(disp, resp, timeout); } void @@ -1606,8 +1638,6 @@ dns_dispatch_send(dns_dispentry_t *resp, isc_region_t *r, isc_dscp_t dscp) { UNUSED(dscp); - handle = getentryhandle(resp); - #if 0 /* XXX: no DSCP support */ if (dscp == -1) { @@ -1622,6 +1652,12 @@ dns_dispatch_send(dns_dispentry_t *resp, isc_region_t *r, isc_dscp_t dscp) { } #endif + if (resp->disp->socktype == isc_socktype_tcp) { + handle = resp->disp->handle; + } else { + handle = resp->handle; + } + dispentry_attach(resp, &(dns_dispentry_t *){ NULL }); isc_nm_send(handle, r, send_done, resp); } @@ -1632,28 +1668,30 @@ dns_dispatch_cancel(dns_dispentry_t *resp) { resp->canceled = true; - if (resp->handle) { + /* UDP case. */ + if (resp->handle != NULL) { isc_nm_cancelread(resp->handle); - } else if (resp->disp->handle != NULL) { - isc_nm_cancelread(resp->disp->handle); - } -} - -static inline isc_nmhandle_t * -getentryhandle(dns_dispentry_t *resp) { - isc_nmhandle_t *handle = NULL; - - REQUIRE(VALID_RESPONSE(resp)); - - if (resp->disp->socktype == isc_socktype_tcp) { - handle = resp->disp->handle; - } else { - handle = resp->handle; + return; } - INSIST(handle != NULL); - - return (handle); + /* + * TCP case. We only want to cancel if this is the last resp + * listening on this TCP connection. + */ + if (ISC_LINK_LINKED(resp, plink)) { + ISC_LIST_UNLINK(resp->disp->pending, resp, plink); + if (resp->connected != NULL) { + resp->connected(ISC_R_CANCELED, NULL, resp->arg); + } + } else if (ISC_LINK_LINKED(resp, alink)) { + ISC_LIST_UNLINK(resp->disp->active, resp, alink); + if (ISC_LIST_EMPTY(resp->disp->active) && + resp->disp->handle != NULL) { + isc_nm_cancelread(resp->disp->handle); + } else if (resp->response != NULL) { + resp->response(ISC_R_CANCELED, NULL, resp->arg); + } + } } isc_result_t @@ -1686,29 +1724,6 @@ dns_dispentry_getlocaladdress(dns_dispentry_t *resp, isc_sockaddr_t *addrp) { return (ISC_R_NOTIMPLEMENTED); } -unsigned int -dns_dispatch_getattributes(dns_dispatch_t *disp) { - REQUIRE(VALID_DISPATCH(disp)); - - /* - * We don't bother locking disp here; it's the caller's - * responsibility to use only non volatile flags. - */ - return (disp->attributes); -} - -void -dns_dispatch_changeattributes(dns_dispatch_t *disp, unsigned int attributes, - unsigned int mask) { - REQUIRE(VALID_DISPATCH(disp)); - - LOCK(&disp->lock); - - disp->attributes &= ~mask; - disp->attributes |= (attributes & mask); - UNLOCK(&disp->lock); -} - dns_dispatch_t * dns_dispatchset_get(dns_dispatchset_t *dset) { dns_dispatch_t *disp = NULL; @@ -1738,7 +1753,7 @@ dns_dispatchset_create(isc_mem_t *mctx, dns_dispatch_t *source, int i, j; REQUIRE(VALID_DISPATCH(source)); - REQUIRE((source->attributes & DNS_DISPATCHATTR_UDP) != 0); + REQUIRE(source->socktype == isc_socktype_udp); REQUIRE(dsetp != NULL && *dsetp == NULL); mgr = source->mgr; @@ -1759,7 +1774,6 @@ dns_dispatchset_create(isc_mem_t *mctx, dns_dispatch_t *source, for (i = 1; i < n; i++) { dset->dispatches[i] = NULL; result = dispatch_createudp(mgr, &source->local, - source->attributes, &dset->dispatches[i]); if (result != ISC_R_SUCCESS) { goto fail; diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index a4686724fa..93f676f5f9 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -9,10 +9,9 @@ * information regarding copyright ownership. */ -#include +#pragma once -#ifndef DNS_DISPATCH_H -#define DNS_DISPATCH_H 1 +#include /***** ***** Module Info @@ -21,12 +20,12 @@ /*! \file dns/dispatch.h * \brief * DNS Dispatch Management - * Shared UDP and single-use TCP dispatches for queries and responses. + * Shared UDP and single-use TCP dispatches for queries and responses. * * MP: * - *\li All locking is performed internally to each dispatch. - * Restrictions apply to dns_dispatch_removeresponse(). + *\li All locking is performed internally to each dispatch. + * Restrictions apply to dns_dispatch_removeresponse(). * * Reliability: * @@ -72,33 +71,6 @@ struct dns_dispatchset { isc_mutex_t lock; }; -/*@{*/ -/*% - * Attributes for added dispatchers. - * - * Values with the mask 0xffff0000 are application defined. - * Values with the mask 0x0000ffff are library defined. - * - * Insane values (like setting both TCP and UDP) are not caught. Don't - * do that. - * - * _PRIVATE - * The dispatcher cannot be shared. - * - * _TCP, _UDP - * The dispatcher is a TCP or UDP socket. - * - * _IPV4, _IPV6 - * The dispatcher uses an IPv4 or IPv6 socket. - */ -#define DNS_DISPATCHATTR_PRIVATE 0x00000001U -#define DNS_DISPATCHATTR_TCP 0x00000002U -#define DNS_DISPATCHATTR_UDP 0x00000004U -#define DNS_DISPATCHATTR_IPV4 0x00000008U -#define DNS_DISPATCHATTR_IPV6 0x00000010U -#define DNS_DISPATCHATTR_CONNECTED 0x00000080U -/*@}*/ - /* */ #define DNS_DISPATCHOPT_FIXEDID 0x00000001U @@ -161,7 +133,7 @@ dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr); * without incrementing its reference count. * * Requires: - *\li mgr is a valid dispatchmgr + *\li mgr is a valid dispatchmgr * Returns: *\li A pointer to the current blackhole list, or NULL. */ @@ -195,7 +167,7 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats); isc_result_t dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, - unsigned int attributes, dns_dispatch_t **dispp); + dns_dispatch_t **dispp); /*%< * Create a new UDP dispatch. * @@ -212,8 +184,8 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, isc_result_t dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, - const isc_sockaddr_t *destaddr, unsigned int attributes, - isc_dscp_t dscp, dns_dispatch_t **dispp); + const isc_sockaddr_t *destaddr, isc_dscp_t dscp, + dns_dispatch_t **dispp); /*%< * Create a new dns_dispatch and attach it to the provided isc_socket_t. * @@ -280,7 +252,14 @@ dns_dispatch_send(dns_dispentry_t *resp, isc_region_t *r, isc_dscp_t dscp); */ void -dns_dispatch_read(dns_dispentry_t *resp, uint16_t timeout); +dns_dispatch_resume(dns_dispentry_t *resp, uint16_t timeout); +/*%< + * Reset the read timeout in the socket associated with 'resp' and + * continue reading. + * + * Requires: + *\li 'resp' is valid. + */ isc_result_t dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, @@ -375,41 +354,6 @@ dns_dispentry_getlocaladdress(dns_dispentry_t *resp, isc_sockaddr_t *addrp); *\li ISC_R_NOTIMPLEMENTED */ -unsigned int -dns_dispatch_getattributes(dns_dispatch_t *disp); -/*%< - * Return the attributes (DNS_DISPATCHATTR_xxx) of this dispatch. Only the - * non-changeable attributes are expected to be referenced by the caller. - * - * Requires: - *\li disp is valid. - */ - -void -dns_dispatch_changeattributes(dns_dispatch_t *disp, unsigned int attributes, - unsigned int mask); -/*%< - * Set the bits described by "mask" to the corresponding values in - * "attributes". - * - * That is: - * - * \code - * new = (old & ~mask) | (attributes & mask) - * \endcode - * - * This function has a side effect when #DNS_DISPATCHATTR_NOLISTEN changes. - * When the flag becomes off, the dispatch will start receiving on the - * corresponding socket. When the flag becomes on, receive events on the - * corresponding socket will be canceled. - * - * Requires: - *\li disp is valid. - * - *\li attributes are reasonable for the dispatch. That is, setting the UDP - * attribute on a TCP socket isn't reasonable. - */ - dns_dispatch_t * dns_dispatchset_get(dns_dispatchset_t *dset); /*%< @@ -417,7 +361,7 @@ dns_dispatchset_get(dns_dispatchset_t *dset); * the round-robin counter. * * Requires: - *\li dset != NULL + *\li dset != NULL */ isc_result_t @@ -429,8 +373,8 @@ dns_dispatchset_create(isc_mem_t *mctx, dns_dispatch_t *source, * source. * * Requires: - *\li source is a valid UDP dispatcher - *\li dsetp != NULL, *dsetp == NULL + *\li source is a valid UDP dispatcher + *\li dsetp != NULL, *dsetp == NULL */ void @@ -440,7 +384,7 @@ dns_dispatchset_destroy(dns_dispatchset_t **dsetp); * memory, and set *dsetp to NULL. * * Requires: - *\li dset is valid + *\li dset is valid */ isc_result_t @@ -453,5 +397,3 @@ dns_dispatch_getnext(dns_dispentry_t *resp); */ ISC_LANG_ENDDECLS - -#endif /* DNS_DISPATCH_H */ diff --git a/lib/dns/request.c b/lib/dns/request.c index 513ffcbbad..b2b569ddf1 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -137,7 +137,6 @@ dns_requestmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, dns_requestmgr_t **requestmgrp) { dns_requestmgr_t *requestmgr; int i; - unsigned int dispattr; req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create"); @@ -145,39 +144,31 @@ dns_requestmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, REQUIRE(taskmgr != NULL); REQUIRE(dispatchmgr != NULL); - if (dispatchv4 != NULL) { - dispattr = dns_dispatch_getattributes(dispatchv4); - REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0); - } - if (dispatchv6 != NULL) { - dispattr = dns_dispatch_getattributes(dispatchv6); - REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0); - } - requestmgr = isc_mem_get(mctx, sizeof(*requestmgr)); + *requestmgr = (dns_requestmgr_t){ 0 }; + isc_taskmgr_attach(taskmgr, &requestmgr->taskmgr); + dns_dispatchmgr_attach(dispatchmgr, &requestmgr->dispatchmgr); isc_mutex_init(&requestmgr->lock); for (i = 0; i < DNS_REQUEST_NLOCKS; i++) { isc_mutex_init(&requestmgr->locks[i]); } - requestmgr->taskmgr = taskmgr; - requestmgr->dispatchmgr = dispatchmgr; - requestmgr->dispatchv4 = NULL; if (dispatchv4 != NULL) { dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4); } - requestmgr->dispatchv6 = NULL; if (dispatchv6 != NULL) { dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6); } - requestmgr->mctx = NULL; isc_mem_attach(mctx, &requestmgr->mctx); + isc_refcount_init(&requestmgr->references, 1); + ISC_LIST_INIT(requestmgr->whenshutdown); ISC_LIST_INIT(requestmgr->requests); + atomic_init(&requestmgr->exiting, false); - requestmgr->hash = 0; + requestmgr->magic = REQUESTMGR_MAGIC; req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr); @@ -325,6 +316,12 @@ mgr_destroy(dns_requestmgr_t *requestmgr) { if (requestmgr->dispatchv6 != NULL) { dns_dispatch_detach(&requestmgr->dispatchv6); } + if (requestmgr->dispatchmgr != NULL) { + dns_dispatchmgr_detach(&requestmgr->dispatchmgr); + } + if (requestmgr->taskmgr != NULL) { + isc_taskmgr_detach(&requestmgr->taskmgr); + } requestmgr->magic = 0; isc_mem_putanddetach(&requestmgr->mctx, requestmgr, sizeof(*requestmgr)); @@ -417,7 +414,7 @@ tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr, } result = dns_dispatch_createtcp(requestmgr->dispatchmgr, srcaddr, - destaddr, 0, dscp, dispatchp); + destaddr, dscp, dispatchp); return (result); } @@ -446,7 +443,7 @@ udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, return (ISC_R_SUCCESS); } - return (dns_dispatch_createudp(requestmgr->dispatchmgr, srcaddr, 0, + return (dns_dispatch_createudp(requestmgr->dispatchmgr, srcaddr, dispatchp)); } @@ -589,15 +586,19 @@ again: UNLOCK(&requestmgr->lock); request->destaddr = *destaddr; - if (!tcp || !connected) { + if (tcp && connected) { + req_send(request); + req_detach(&rclone); + } else { result = dns_dispatch_connect(request->dispentry); if (result != ISC_R_SUCCESS) { goto unlink; } - request->flags |= DNS_REQUEST_F_CONNECTING | DNS_REQUEST_F_TCP; - } else { - req_send(request); - req_detach(&rclone); + request->flags |= DNS_REQUEST_F_CONNECTING; + + if (tcp) { + request->flags |= DNS_REQUEST_F_TCP; + } } req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p", request); @@ -613,6 +614,9 @@ cleanup: if (tclone != NULL) { isc_task_detach(&tclone); } + if (rclone != NULL) { + req_detach(&rclone); + } req_detach(&request); req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: failed %s", dns_result_totext(result)); @@ -755,15 +759,18 @@ use_tcp: UNLOCK(&requestmgr->lock); request->destaddr = *destaddr; - if (!tcp || !connected) { + if (tcp && connected) { + req_send(request); + req_detach(&rclone); + } else { result = dns_dispatch_connect(request->dispentry); if (result != ISC_R_SUCCESS) { goto unlink; } - request->flags |= DNS_REQUEST_F_CONNECTING | DNS_REQUEST_F_TCP; - } else { - req_send(request); - req_detach(&rclone); + request->flags |= DNS_REQUEST_F_CONNECTING; + if (tcp) { + request->flags |= DNS_REQUEST_F_TCP; + } } req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p", request); @@ -1080,7 +1087,8 @@ req_response(isc_result_t result, isc_region_t *region, void *arg) { LOCK(&request->requestmgr->locks[request->hash]); if (--request->udpcount != 0) { - dns_dispatch_read(request->dispentry, request->timeout); + dns_dispatch_resume(request->dispentry, + request->timeout); if (!DNS_REQUEST_SENDING(request)) { req_send(request); } diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 72387fdfcb..1643b3c0d6 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -1123,12 +1123,14 @@ munge: static inline void resquery_destroy(resquery_t *query) { - dns_resolver_t *res; + fetchctx_t *fctx = query->fctx; + dns_resolver_t *res = fctx->res; + unsigned int bucket = fctx->bucketnum; bool empty; - fetchctx_t *fctx; - unsigned int bucket; - REQUIRE(!ISC_LINK_LINKED(query, link)); + if (ISC_LINK_LINKED(query, link)) { + ISC_LIST_UNLINK(fctx->queries, query, link); + } if (query->tsig != NULL) { isc_buffer_free(&query->tsig); @@ -1148,10 +1150,6 @@ resquery_destroy(resquery_t *query) { isc_refcount_destroy(&query->references); - fctx = query->fctx; - res = fctx->res; - bucket = fctx->bucketnum; - LOCK(&res->buckets[bucket].lock); fctx->nqueries--; empty = fctx_decreference(query->fctx); @@ -1935,7 +1933,7 @@ resquery_timeout(resquery_t *query) { */ timeleft = isc_time_microdiff(&fctx->next_timeout, &now); if (timeleft >= US_PER_MSEC) { - dns_dispatch_read(query->dispentry, (timeleft / US_PER_MSEC)); + dns_dispatch_resume(query->dispentry, (timeleft / US_PER_MSEC)); return (ISC_R_COMPLETE); } @@ -2061,7 +2059,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, } result = dns_dispatch_createtcp(res->dispatchmgr, &addr, - &addrinfo->sockaddr, 0, + &addrinfo->sockaddr, query->dscp, &query->dispatch); if (result != ISC_R_SUCCESS) { goto cleanup_query; @@ -2082,7 +2080,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, goto cleanup_query; } result = dns_dispatch_createudp(res->dispatchmgr, &addr, - 0, &query->dispatch); + &query->dispatch); if (result != ISC_R_SUCCESS) { goto cleanup_query; } @@ -2795,12 +2793,8 @@ resquery_connected(isc_result_t eresult, isc_region_t *region, void *arg) { switch (eresult) { case ISC_R_SUCCESS: /* - * We are connected. Update the dispatcher and - * send the query. + * We are connected. Send the query. */ - dns_dispatch_changeattributes(query->dispatch, - DNS_DISPATCHATTR_CONNECTED, - DNS_DISPATCHATTR_CONNECTED); result = resquery_send(query); if (result != ISC_R_SUCCESS) {