From 64ffbe82c01c12ed921accf6f669e8322d6bcebd Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Wed, 30 Oct 2024 09:23:33 +0000 Subject: [PATCH] Separate the connect and the read timeouts in dispatch The network manager layer has two different timers with their own timeout values for TCP connections: connect timeout and read timeout. Separate the connect and the read TCP timeouts in the dispatch module too. --- bin/delv/delv.c | 10 ++- bin/nsupdate/nsupdate.c | 29 ++++---- bin/tests/system/pipelined/pipequeries.c | 2 +- bin/tools/mdig.c | 6 +- lib/dns/dispatch.c | 36 ++++++++-- lib/dns/include/dns/dispatch.h | 25 +++++-- lib/dns/include/dns/request.h | 43 ++++++------ lib/dns/request.c | 45 +++++++------ lib/dns/resolver.c | 12 ++-- lib/dns/xfrin.c | 36 ++++++---- lib/dns/zone.c | 50 +++++++------- tests/dns/dispatch_test.c | 86 +++++++++++++----------- 12 files changed, 226 insertions(+), 154 deletions(-) diff --git a/bin/delv/delv.c b/bin/delv/delv.c index dd5513fdb2..c757a41246 100644 --- a/bin/delv/delv.c +++ b/bin/delv/delv.c @@ -2142,9 +2142,15 @@ sendquery(void *arg) { &requestmgr)); dns_view_attach(view, &(dns_view_t *){ NULL }); + + uint32_t initial; + isc_nm_gettimeouts(netmgr, &initial, NULL, NULL, NULL); + const unsigned int connect_timeout = initial, timeout = initial; + CHECK(dns_request_create(requestmgr, message, NULL, &peer, NULL, NULL, - DNS_REQUESTOPT_TCP, NULL, 1, 0, 0, isc_loop(), - recvresponse, message, &request)); + DNS_REQUESTOPT_TCP, NULL, connect_timeout, + timeout, 0, 0, isc_loop(), recvresponse, + message, &request)); return; cleanup: diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 2f1da21209..2491b9b9df 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -2665,9 +2665,9 @@ send_update(dns_name_t *zone, isc_sockaddr_t *primary) { result = dns_request_create(requestmgr, updatemsg, srcaddr, primary, req_transport, req_tls_ctx_cache, options, - tsigkey, timeout, udp_timeout, udp_retries, - isc_loop_main(loopmgr), update_completed, - NULL, &request); + tsigkey, timeout, timeout, udp_timeout, + udp_retries, isc_loop_main(loopmgr), + update_completed, NULL, &request); check_result(result, "dns_request_create"); if (debugging) { @@ -2770,11 +2770,11 @@ recvsoa(void *arg) { srcaddr = localaddr4; } - result = dns_request_create(requestmgr, soaquery, srcaddr, addr, - req_transport, req_tls_ctx_cache, - options, NULL, timeout, udp_timeout, - udp_retries, isc_loop_main(loopmgr), - recvsoa, reqinfo, &request); + result = dns_request_create( + requestmgr, soaquery, srcaddr, addr, req_transport, + req_tls_ctx_cache, options, NULL, timeout, timeout, + udp_timeout, udp_retries, isc_loop_main(loopmgr), + recvsoa, reqinfo, &request); check_result(result, "dns_request_create"); requests++; return; @@ -3009,8 +3009,8 @@ sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, result = dns_request_create( requestmgr, msg, srcaddr, destaddr, req_transport, req_tls_ctx_cache, options, default_servers ? NULL : tsigkey, - timeout, udp_timeout, udp_retries, isc_loop_main(loopmgr), - recvsoa, reqinfo, request); + timeout, timeout, udp_timeout, udp_retries, + isc_loop_main(loopmgr), recvsoa, reqinfo, request); check_result(result, "dns_request_create"); requests++; } @@ -3210,10 +3210,11 @@ send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, srcaddr = localaddr4; } - result = dns_request_create( - requestmgr, msg, srcaddr, destaddr, req_transport, - req_tls_ctx_cache, options, tsigkey, timeout, udp_timeout, - udp_retries, isc_loop_main(loopmgr), recvgss, reqinfo, request); + result = dns_request_create(requestmgr, msg, srcaddr, destaddr, + req_transport, req_tls_ctx_cache, options, + tsigkey, timeout, timeout, udp_timeout, + udp_retries, isc_loop_main(loopmgr), + recvgss, reqinfo, request); check_result(result, "dns_request_create"); if (debugging) { show_message(stdout, msg, "Outgoing update query:"); diff --git a/bin/tests/system/pipelined/pipequeries.c b/bin/tests/system/pipelined/pipequeries.c index f1474dd1e3..0119bf718a 100644 --- a/bin/tests/system/pipelined/pipequeries.c +++ b/bin/tests/system/pipelined/pipequeries.c @@ -162,7 +162,7 @@ sendquery(void) { result = dns_request_create( requestmgr, message, have_src ? &srcaddr : NULL, &dstaddr, NULL, - NULL, DNS_REQUESTOPT_TCP, NULL, TIMEOUT, 0, 0, + NULL, DNS_REQUESTOPT_TCP, NULL, TIMEOUT, TIMEOUT, 0, 0, isc_loop_main(loopmgr), recvresponse, message, &request); CHECK("dns_request_create", result); diff --git a/bin/tools/mdig.c b/bin/tools/mdig.c index 600ab78be6..fb8dcf4f66 100644 --- a/bin/tools/mdig.c +++ b/bin/tools/mdig.c @@ -751,9 +751,9 @@ sendquery(struct query *query) { result = dns_request_create( requestmgr, message, have_src ? &srcaddr : NULL, &dstaddr, NULL, - NULL, options, NULL, query->timeout, query->udptimeout, - query->udpretries, isc_loop_main(loopmgr), recvresponse, - message, &request); + NULL, options, NULL, query->timeout, query->timeout, + query->udptimeout, query->udpretries, isc_loop_main(loopmgr), + recvresponse, message, &request); CHECK("dns_request_create", result); return ISC_R_SUCCESS; diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 6c9227fd84..c3e42ceb13 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -86,6 +86,7 @@ struct dns_dispentry { dns_transport_t *transport; isc_tlsctx_cache_t *tlsctx_cache; unsigned int retries; + unsigned int connect_timeout; unsigned int timeout; isc_time_t start; isc_sockaddr_t local; @@ -1095,6 +1096,13 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats) { isc_stats_attach(stats, &mgr->stats); } +isc_nm_t * +dns_dispatchmgr_getnetmgr(dns_dispatchmgr_t *mgr) { + REQUIRE(VALID_DISPATCHMGR(mgr)); + + return mgr->nm; +} + /* * Allocate and set important limits. */ @@ -1414,11 +1422,12 @@ ISC_REFCOUNT_IMPL(dns_dispatch, dispatch_destroy); isc_result_t dns_dispatch_add(dns_dispatch_t *disp, isc_loop_t *loop, - dns_dispatchopt_t options, unsigned int timeout, - const isc_sockaddr_t *dest, dns_transport_t *transport, - isc_tlsctx_cache_t *tlsctx_cache, dispatch_cb_t connected, - dispatch_cb_t sent, dispatch_cb_t response, void *arg, - dns_messageid_t *idp, dns_dispentry_t **respp) { + dns_dispatchopt_t options, unsigned int connect_timeout, + unsigned int timeout, const isc_sockaddr_t *dest, + dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, + dispatch_cb_t connected, dispatch_cb_t sent, + dispatch_cb_t response, void *arg, dns_messageid_t *idp, + dns_dispentry_t **respp) { REQUIRE(VALID_DISPATCH(disp)); REQUIRE(dest != NULL); REQUIRE(respp != NULL && *respp == NULL); @@ -1439,6 +1448,7 @@ dns_dispatch_add(dns_dispatch_t *disp, isc_loop_t *loop, in_port_t localport = isc_sockaddr_getport(&disp->local); dns_dispentry_t *resp = isc_mem_get(disp->mctx, sizeof(*resp)); *resp = (dns_dispentry_t){ + .connect_timeout = connect_timeout, .timeout = timeout, .port = localport, .peer = *dest, @@ -1866,6 +1876,13 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { } else if (eresult == ISC_R_SUCCESS) { disp->state = DNS_DISPATCHSTATE_CONNECTED; isc_nmhandle_attach(handle, &disp->handle); + if (resp != NULL) { + isc_nmhandle_cleartimeout(disp->handle); + if (resp->timeout != 0) { + isc_nmhandle_settimeout(disp->handle, + resp->timeout); + } + } tcp_startrecv(disp, resp); } else { disp->state = DNS_DISPATCHSTATE_NONE; @@ -1994,7 +2011,7 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) { dns_dispatch_ref(disp); /* DISPATCH003 */ dispentry_log(resp, ISC_LOG_DEBUG(90), "connecting from %s to %s, timeout %u", localbuf, - peerbuf, resp->timeout); + peerbuf, resp->connect_timeout); char *hostname = NULL; if (resp->transport != NULL) { @@ -2004,7 +2021,7 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) { isc_nm_streamdnsconnect(disp->mgr->nm, &disp->local, &disp->peer, tcp_connected, disp, - resp->timeout, tlsctx, hostname, + resp->connect_timeout, tlsctx, hostname, sess_cache, ISC_NM_PROXY_NONE, NULL); break; @@ -2028,6 +2045,11 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) { if (!disp->reading) { /* Restart the reading */ + isc_nmhandle_cleartimeout(disp->handle); + if (resp->timeout != 0) { + isc_nmhandle_settimeout(disp->handle, + resp->timeout); + } tcp_startrecv(disp, resp); } diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index eced64f0af..be77b12980 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -162,6 +162,15 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats); * (see dns/stats.h). */ +isc_nm_t * +dns_dispatchmgr_getnetmgr(dns_dispatchmgr_t *mgr); +/*%< + * Get the network manager object associated with the dispatch manager. + * + * Requires: + *\li disp is valid + */ + isc_result_t dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, dns_dispatch_t **dispp); @@ -296,14 +305,20 @@ typedef void (*dispatch_cb_t)(isc_result_t eresult, isc_region_t *region, isc_result_t dns_dispatch_add(dns_dispatch_t *disp, isc_loop_t *loop, - dns_dispatchopt_t options, unsigned int timeout, - const isc_sockaddr_t *dest, dns_transport_t *transport, - isc_tlsctx_cache_t *tlsctx_cache, dispatch_cb_t connected, - dispatch_cb_t sent, dispatch_cb_t response, void *arg, - dns_messageid_t *idp, dns_dispentry_t **resp); + dns_dispatchopt_t options, unsigned int connect_timeout, + unsigned int timeout, const isc_sockaddr_t *dest, + dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, + dispatch_cb_t connected, dispatch_cb_t sent, + dispatch_cb_t response, void *arg, dns_messageid_t *idp, + dns_dispentry_t **respp); /*%< * Add a response entry for this dispatch. * + * The 'connect_timeout' and 'timeout' define the number of milliseconds for + * the connect and read timeouts respectively. When 0 is provided, the + * corresponding timeout timer is disabled. For UDP disptaches 'connect_timeout' + * is ignored. + * * "*idp" is filled in with the assigned message ID, and *resp is filled in * with the dispatch entry object. * diff --git a/lib/dns/include/dns/request.h b/lib/dns/include/dns/request.h index 07b2b17af9..ac892a69e1 100644 --- a/lib/dns/include/dns/request.h +++ b/lib/dns/include/dns/request.h @@ -111,21 +111,23 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, const isc_sockaddr_t *srcaddr, const isc_sockaddr_t *destaddr, dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, unsigned int options, - dns_tsigkey_t *key, unsigned int timeout, - unsigned int udptimeout, unsigned int udpretries, - isc_loop_t *loop, isc_job_cb cb, void *arg, - dns_request_t **requestp); + dns_tsigkey_t *key, unsigned int connect_timeout, + unsigned int timeout, unsigned int udptimeout, + unsigned int udpretries, isc_loop_t *loop, isc_job_cb cb, + void *arg, dns_request_t **requestp); /*%< * Create and send a request. * * Notes: * *\li 'message' will be rendered and sent to 'address'. If the - * #DNS_REQUESTOPT_TCP option is set, TCP will be used, - * #DNS_REQUESTOPT_SHARE option is set too, connecting TCP - * (vs. connected) will be shared too. The request - * will timeout after 'timeout' seconds. UDP requests will be resent - * at 'udptimeout' intervals if non-zero or 'udpretries' is non-zero. + * #DNS_REQUESTOPT_TCP option is set or the request message's size is + * larger than 512 bytes then TCP will be used, and #DNS_REQUESTOPT_SHARE + * option is set too, connecting TCP (vs. connected) will be shared too. + * With TCP a connection attempt will timeout after 'connect_timeout' + * seconds. The request will timeout after 'timeout' seconds for both TCP + * and UDP. UDP requests will be resent at 'udptimeout' intervals if + * non-zero or 'udpretries' is non-zero. * *\li If the #DNS_REQUESTOPT_CASE option is set, use case sensitive * compression. @@ -146,7 +148,7 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, * *\li 'srcaddr' and 'dstaddr' are the same protocol family. * - *\li 'timeout' > 0 + *\li 'connect_timeout' > 0 and 'timeout' > 0. * *\li 'loop' is a valid loop. * @@ -159,20 +161,23 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, const isc_sockaddr_t *destaddr, dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, unsigned int options, - unsigned int timeout, unsigned int udptimeout, - unsigned int udpretries, isc_loop_t *loop, isc_job_cb cb, - void *arg, dns_request_t **requestp); + unsigned int connect_timeout, unsigned int timeout, + unsigned int udptimeout, unsigned int udpretries, + isc_loop_t *loop, isc_job_cb cb, void *arg, + dns_request_t **requestp); /*!< * \brief Create and send a request. * * Notes: * *\li 'msgbuf' will be sent to 'destaddr' after setting the id. If the - * #DNS_REQUESTOPT_TCP option is set, TCP will be used, - * #DNS_REQUESTOPT_SHARE option is set too, connecting TCP - * (vs. connected) will be shared too. The request - * will timeout after 'timeout' seconds. UDP requests will be resent - * at 'udptimeout' intervals if non-zero or if 'udpretries' is not zero. + * #DNS_REQUESTOPT_TCP option is set or the request message's size is + * larger than 512 bytes then TCP will be used, and #DNS_REQUESTOPT_SHARE + * option is set too, connecting TCP (vs. connected) will be shared too. + * With TCP a connection attempt will timeout after 'connect_timeout' + * seconds. The request wll timeout after timeout' seconds for both TCP + * and UDP. UDP requests will be resent at 'udptimeout' intervals if + * non-zero or if 'udpretries' is not zero. * *\li When the request completes, successfully, due to a timeout, or * because it was canceled, a completion callback will run in 'loop'. @@ -187,7 +192,7 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, * *\li 'srcaddr' and 'dstaddr' are the same protocol family. * - *\li 'timeout' > 0 + *\li 'connect_timeout' > 0 and 'timeout' > 0. * *\li 'loop' is a valid loop. * diff --git a/lib/dns/request.c b/lib/dns/request.c index b87c52fb6a..3b30599a49 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -81,6 +81,7 @@ struct dns_request { isc_buffer_t *tsig; dns_tsigkey_t *tsigkey; isc_sockaddr_t destaddr; + unsigned int connect_timeout; unsigned int timeout; unsigned int udpcount; }; @@ -278,8 +279,8 @@ req_send(dns_request_t *request) { static dns_request_t * new_request(isc_mem_t *mctx, isc_loop_t *loop, isc_job_cb cb, void *arg, - bool tcp, unsigned int timeout, unsigned int udptimeout, - unsigned int udpretries) { + bool tcp, unsigned int connect_timeout, unsigned int timeout, + unsigned int udptimeout, unsigned int udpretries) { dns_request_t *request = isc_mem_get(mctx, sizeof(*request)); *request = (dns_request_t){ .magic = REQUEST_MAGIC, @@ -296,6 +297,7 @@ new_request(isc_mem_t *mctx, isc_loop_t *loop, isc_job_cb cb, void *arg, isc_mem_attach(mctx, &request->mctx); if (tcp) { + request->connect_timeout = connect_timeout * 1000; request->timeout = timeout * 1000; } else { if (udptimeout == 0) { @@ -409,9 +411,10 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, const isc_sockaddr_t *destaddr, dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, unsigned int options, - unsigned int timeout, unsigned int udptimeout, - unsigned int udpretries, isc_loop_t *loop, isc_job_cb cb, - void *arg, dns_request_t **requestp) { + unsigned int connect_timeout, unsigned int timeout, + unsigned int udptimeout, unsigned int udpretries, + isc_loop_t *loop, isc_job_cb cb, void *arg, + dns_request_t **requestp) { dns_request_t *request = NULL; isc_result_t result; isc_mem_t *mctx = NULL; @@ -427,7 +430,7 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, REQUIRE(loop != NULL); REQUIRE(cb != NULL); REQUIRE(requestp != NULL && *requestp == NULL); - REQUIRE(timeout > 0); + REQUIRE(connect_timeout > 0 && timeout > 0); REQUIRE(udpretries != UINT_MAX); if (srcaddr != NULL) { @@ -460,8 +463,8 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, tcp = true; } - request = new_request(mctx, loop, cb, arg, tcp, timeout, udptimeout, - udpretries); + request = new_request(mctx, loop, cb, arg, tcp, connect_timeout, + timeout, udptimeout, udpretries); isc_buffer_allocate(mctx, &request->query, r.length + (tcp ? 2 : 0)); result = isc_buffer_copyregion(request->query, &r); @@ -481,10 +484,11 @@ again: dispopt |= DNS_DISPATCHOPT_FIXEDID; } - result = dns_dispatch_add( - request->dispatch, loop, dispopt, request->timeout, destaddr, - transport, tlsctx_cache, req_connected, req_senddone, - req_response, request, &id, &request->dispentry); + result = dns_dispatch_add(request->dispatch, loop, dispopt, + request->connect_timeout, request->timeout, + destaddr, transport, tlsctx_cache, + req_connected, req_senddone, req_response, + request, &id, &request->dispentry); if (result != ISC_R_SUCCESS) { if ((options & DNS_REQUESTOPT_FIXEDID) != 0 && !newtcp) { dns_dispatch_detach(&request->dispatch); @@ -537,10 +541,10 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, const isc_sockaddr_t *srcaddr, const isc_sockaddr_t *destaddr, dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, unsigned int options, - dns_tsigkey_t *key, unsigned int timeout, - unsigned int udptimeout, unsigned int udpretries, - isc_loop_t *loop, isc_job_cb cb, void *arg, - dns_request_t **requestp) { + dns_tsigkey_t *key, unsigned int connect_timeout, + unsigned int timeout, unsigned int udptimeout, + unsigned int udpretries, isc_loop_t *loop, isc_job_cb cb, + void *arg, dns_request_t **requestp) { dns_request_t *request = NULL; isc_result_t result; isc_mem_t *mctx = NULL; @@ -553,7 +557,7 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, REQUIRE(loop != NULL); REQUIRE(cb != NULL); REQUIRE(requestp != NULL && *requestp == NULL); - REQUIRE(timeout > 0); + REQUIRE(connect_timeout > 0 && timeout > 0); REQUIRE(udpretries != UINT_MAX); if (srcaddr != NULL && @@ -582,8 +586,8 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, tcp = true; } - request = new_request(mctx, loop, cb, arg, tcp, timeout, udptimeout, - udpretries); + request = new_request(mctx, loop, cb, arg, tcp, connect_timeout, + timeout, udptimeout, udpretries); if (key != NULL) { dns_tsigkey_attach(key, &request->tsigkey); @@ -601,7 +605,8 @@ again: goto cleanup; } - result = dns_dispatch_add(request->dispatch, loop, 0, request->timeout, + result = dns_dispatch_add(request->dispatch, loop, 0, + request->connect_timeout, request->timeout, destaddr, transport, tlsctx_cache, req_connected, req_senddone, req_response, request, &id, &request->dispentry); diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index b2c26bde61..ce878f15f8 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -2110,12 +2110,12 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, UNLOCK(&fctx->lock); /* Set up the dispatch and set the query ID */ - result = dns_dispatch_add(query->dispatch, fctx->loop, 0, - isc_interval_ms(&fctx->interval), &sockaddr, - addrinfo->transport, tlsctx_cache, - resquery_connected, resquery_senddone, - resquery_response, query, &query->id, - &query->dispentry); + const unsigned int timeout_ms = isc_interval_ms(&fctx->interval); + result = dns_dispatch_add(query->dispatch, fctx->loop, 0, timeout_ms, + timeout_ms, &sockaddr, addrinfo->transport, + tlsctx_cache, resquery_connected, + resquery_senddone, resquery_response, query, + &query->id, &query->dispentry); if (result != ISC_R_SUCCESS) { goto cleanup_udpfetch; } diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index b5c9b5941c..cefb35f634 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -1253,6 +1253,7 @@ static isc_result_t xfrin_start(dns_xfrin_t *xfr) { isc_result_t result = ISC_R_FAILURE; isc_interval_t interval; + uint32_t initial; dns_xfrin_ref(xfr); @@ -1263,14 +1264,16 @@ xfrin_start(dns_xfrin_t *xfr) { if (dispmgr == NULL) { result = ISC_R_SHUTTINGDOWN; goto failure; - } else { - result = dns_dispatch_createtcp( - dispmgr, &xfr->sourceaddr, &xfr->primaryaddr, - xfr->transport, DNS_DISPATCHOPT_UNSHARED, &xfr->disp); - dns_dispatchmgr_detach(&dispmgr); - if (result != ISC_R_SUCCESS) { - goto failure; - } + } + + isc_nm_gettimeouts(dns_dispatchmgr_getnetmgr(dispmgr), &initial, NULL, + NULL, NULL); + result = dns_dispatch_createtcp(dispmgr, &xfr->sourceaddr, + &xfr->primaryaddr, xfr->transport, + DNS_DISPATCHOPT_UNSHARED, &xfr->disp); + dns_dispatchmgr_detach(&dispmgr); + if (result != ISC_R_SUCCESS) { + goto failure; } LIBDNS_XFRIN_START(xfr, xfr->info); @@ -1293,10 +1296,19 @@ xfrin_start(dns_xfrin_t *xfr) { dns_xfrin_gettransporttype(xfr)); } - CHECK(dns_dispatch_add( - xfr->disp, xfr->loop, 0, 0, &xfr->primaryaddr, xfr->transport, - xfr->tlsctx_cache, xfrin_connect_done, xfrin_send_done, - xfrin_recv_done, xfr, &xfr->id, &xfr->dispentry)); + /* + * Before a configuration option for the primary servers' TCP timeout + * is implemented, use initial TCP timeout as the connect timeout. + * The receive timeout timer is disabled on the dispatch level because + * the xfr module has its own timeouts. + */ + const unsigned int connect_timeout = initial, timeout = 0; + + CHECK(dns_dispatch_add(xfr->disp, xfr->loop, 0, connect_timeout, + timeout, &xfr->primaryaddr, xfr->transport, + xfr->tlsctx_cache, xfrin_connect_done, + xfrin_send_done, xfrin_recv_done, xfr, &xfr->id, + &xfr->dispentry)); /* Set the maximum timer */ if (xfr->max_time_timer == NULL) { diff --git a/lib/dns/zone.c b/lib/dns/zone.c index c2b8186f4d..cb2798a3fc 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -12651,7 +12651,7 @@ notify_send_toaddr(void *arg) { dns_tsigkey_t *key = NULL; char addrbuf[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t src; - unsigned int options, timeout, udptimeout; + unsigned int options, connect_timeout, timeout, udptimeout; bool have_notifysource = false; isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL; @@ -12761,7 +12761,7 @@ notify_send_toaddr(void *arg) { goto cleanup_key; } udptimeout = 5; - timeout = 3 * udptimeout + 1; + connect_timeout = timeout = 3 * udptimeout + 1; again: if ((notify->flags & DNS_NOTIFY_TCP) != 0) { options |= DNS_REQUESTOPT_TCP; @@ -12771,11 +12771,11 @@ again: zmgr_tlsctx_attach(notify->zone->zmgr, &zmgr_tlsctx_cache); - result = dns_request_create(notify->zone->view->requestmgr, message, - &src, ¬ify->dst, notify->transport, - zmgr_tlsctx_cache, options, key, timeout, - udptimeout, 2, notify->zone->loop, - notify_done, notify, ¬ify->request); + result = dns_request_create( + notify->zone->view->requestmgr, message, &src, ¬ify->dst, + notify->transport, zmgr_tlsctx_cache, options, key, + connect_timeout, timeout, udptimeout, 2, notify->zone->loop, + notify_done, notify, ¬ify->request); isc_tlsctx_cache_detach(&zmgr_tlsctx_cache); @@ -13522,8 +13522,8 @@ stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4, result = dns_request_create( zone->view->requestmgr, message, &zone->sourceaddr, &curraddr, NULL, NULL, DNS_REQUESTOPT_TCP, args->tsig_key, - args->timeout * 3, args->timeout, 2, zone->loop, - stub_glue_response, sgr, &sgr->request); + args->timeout * 3 + 1, args->timeout * 3 + 1, args->timeout, 2, + zone->loop, stub_glue_response, sgr, &sgr->request); if (result != ISC_R_SUCCESS) { uint_fast32_t pr; @@ -14676,11 +14676,11 @@ again: zone_iattach(zone, &(dns_zone_t *){ NULL }); - int timeout = 5; + const unsigned int timeout = 5; result = dns_request_create( zone->view->requestmgr, message, &zone->sourceaddr, &curraddr, - NULL, NULL, options, key, timeout * 3 + 1, timeout, 2, - zone->loop, refresh_callback, zone, &zone->request); + NULL, NULL, options, key, timeout * 3 + 1, timeout * 3 + 1, + timeout, 2, zone->loop, refresh_callback, zone, &zone->request); if (result != ISC_R_SUCCESS) { zone_idetach(&(dns_zone_t *){ zone }); zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__, 1, @@ -14952,11 +14952,12 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { cb_args->timeout = 15; cb_args->reqnsid = reqnsid; - int timeout = 5; - result = dns_request_create( - zone->view->requestmgr, message, &zone->sourceaddr, &curraddr, - NULL, NULL, DNS_REQUESTOPT_TCP, key, timeout * 3 + 1, timeout, - 2, zone->loop, stub_callback, cb_args, &zone->request); + const unsigned int timeout = 5; + result = dns_request_create(zone->view->requestmgr, message, + &zone->sourceaddr, &curraddr, NULL, NULL, + DNS_REQUESTOPT_TCP, key, timeout * 3 + 1, + timeout * 3 + 1, timeout, 2, zone->loop, + stub_callback, cb_args, &zone->request); if (result != ISC_R_SUCCESS) { zone_debuglog(zone, __func__, 1, "dns_request_create() failed: %s", @@ -18817,7 +18818,7 @@ next: result = dns_request_createraw( forward->zone->view->requestmgr, forward->msgbuf, &src, &forward->addr, forward->transport, zmgr_tlsctx_cache, - forward->options, 15 /* XXX */, 0, 0, forward->zone->loop, + forward->options, 15, 15 /* XXX */, 0, 0, forward->zone->loop, forward_callback, forward, &forward->request); isc_tlsctx_cache_detach(&zmgr_tlsctx_cache); @@ -21416,7 +21417,7 @@ checkds_send_toaddr(void *arg) { dns_tsigkey_t *key = NULL; char addrbuf[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t src; - unsigned int options, timeout; + unsigned int options; bool have_checkdssource = false; bool canceled = checkds->rlevent->canceled; @@ -21529,12 +21530,13 @@ checkds_send_toaddr(void *arg) { dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3), "checkds: create request for DS query to %s", addrbuf); - timeout = 5; + const unsigned int timeout = 5; options |= DNS_REQUESTOPT_TCP; - result = dns_request_create( - checkds->zone->view->requestmgr, message, &src, &checkds->dst, - NULL, NULL, options, key, timeout * 3 + 1, timeout, 2, - checkds->zone->loop, checkds_done, checkds, &checkds->request); + result = dns_request_create(checkds->zone->view->requestmgr, message, + &src, &checkds->dst, NULL, NULL, options, + key, timeout * 3 + 1, timeout * 3 + 1, + timeout, 2, checkds->zone->loop, + checkds_done, checkds, &checkds->request); if (result != ISC_R_SUCCESS) { dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3), "checkds: dns_request_create() to %s failed: %s", diff --git a/tests/dns/dispatch_test.c b/tests/dns/dispatch_test.c index bc0924023f..20530e9e91 100644 --- a/tests/dns/dispatch_test.c +++ b/tests/dns/dispatch_test.c @@ -51,7 +51,7 @@ #define T_CLIENT_CONNECT (30 * 1000) /* For checks which are expected to timeout */ -#define T_CLIENT_CONNECT_SHORT (10 * 1000) +#define T_CLIENT_SHORT (10 * 1000) /* dns_dispatchset_t *dset = NULL; */ static isc_sockaddr_t udp_server_addr; @@ -513,11 +513,11 @@ connected_gettcp(isc_result_t eresult ISC_ATTR_UNUSED, assert_ptr_equal(test1->dispatch, test2->dispatch); - result = dns_dispatch_add(test2->dispatch, isc_loop_main(loopmgr), 0, - T_CLIENT_CONNECT, &tcp_server_addr, NULL, - NULL, connected_shutdown, client_senddone, - response_noop, test2, &test2->id, - &test2->dispentry); + result = dns_dispatch_add( + test2->dispatch, isc_loop_main(loopmgr), 0, T_CLIENT_CONNECT, + T_CLIENT_INIT, &tcp_server_addr, NULL, NULL, connected_shutdown, + client_senddone, response_noop, test2, &test2->id, + &test2->dispentry); assert_int_equal(result, ISC_R_SUCCESS); dns_dispatch_connect(test2->dispentry); @@ -547,11 +547,11 @@ connected_newtcp(isc_result_t eresult ISC_ATTR_UNUSED, assert_ptr_not_equal(test3->dispatch, test4->dispatch); - result = dns_dispatch_add(test4->dispatch, isc_loop_main(loopmgr), 0, - T_CLIENT_CONNECT, &tcp_server_addr, NULL, - NULL, connected_shutdown, client_senddone, - response_noop, test4, &test4->id, - &test4->dispentry); + result = dns_dispatch_add( + test4->dispatch, isc_loop_main(loopmgr), 0, T_CLIENT_CONNECT, + T_CLIENT_INIT, &tcp_server_addr, NULL, NULL, connected_shutdown, + client_senddone, response_noop, test4, &test4->id, + &test4->dispentry); assert_int_equal(result, ISC_R_SUCCESS); dns_dispatch_connect(test4->dispentry); @@ -597,11 +597,11 @@ ISC_LOOP_TEST_IMPL(dispatch_timeout_tcp_connect) { &test->dispatch); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_dispatch_add(test->dispatch, isc_loop_main(loopmgr), 0, - T_CLIENT_CONNECT_SHORT, &tcp_server_addr, - NULL, NULL, timeout_connected, - client_senddone, response_timeout, test, - &test->id, &test->dispentry); + result = dns_dispatch_add( + test->dispatch, isc_loop_main(loopmgr), 0, T_CLIENT_SHORT, + T_CLIENT_INIT, &tcp_server_addr, NULL, NULL, timeout_connected, + client_senddone, response_timeout, test, &test->id, + &test->dispentry); assert_int_equal(result, ISC_R_SUCCESS); testdata.message[0] = (test->id >> 8) & 0xff; @@ -644,10 +644,10 @@ ISC_LOOP_TEST_IMPL(dispatch_timeout_tcp_response) { assert_int_equal(result, ISC_R_SUCCESS); result = dns_dispatch_add(test->dispatch, isc_loop_main(loopmgr), 0, - T_CLIENT_CONNECT_SHORT, &tcp_server_addr, - NULL, NULL, connected, client_senddone, - response_timeout, test, &test->id, - &test->dispentry); + T_CLIENT_CONNECT, T_CLIENT_SHORT, + &tcp_server_addr, NULL, NULL, connected, + client_senddone, response_timeout, test, + &test->id, &test->dispentry); assert_int_equal(result, ISC_R_SUCCESS); dns_dispatch_connect(test->dispentry); @@ -679,10 +679,11 @@ ISC_LOOP_TEST_IMPL(dispatch_tcp_response) { &test->dispatch); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_dispatch_add( - test->dispatch, isc_loop_main(loopmgr), 0, T_CLIENT_CONNECT, - &tcp_server_addr, NULL, NULL, connected, client_senddone, - response_shutdown, test, &test->id, &test->dispentry); + result = dns_dispatch_add(test->dispatch, isc_loop_main(loopmgr), 0, + T_CLIENT_CONNECT, T_CLIENT_INIT, + &tcp_server_addr, NULL, NULL, connected, + client_senddone, response_shutdown, test, + &test->id, &test->dispentry); assert_int_equal(result, ISC_R_SUCCESS); testdata.message[0] = (test->id >> 8) & 0xff; @@ -718,11 +719,11 @@ ISC_LOOP_TEST_IMPL(dispatch_tls_response) { &test->dispatch); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_dispatch_add(test->dispatch, isc_loop_main(loopmgr), 0, - T_CLIENT_CONNECT, &tls_server_addr, - tls_transport, tls_tlsctx_client_cache, - connected, client_senddone, response_shutdown, - test, &test->id, &test->dispentry); + result = dns_dispatch_add( + test->dispatch, isc_loop_main(loopmgr), 0, T_CLIENT_CONNECT, + T_CLIENT_INIT, &tls_server_addr, tls_transport, + tls_tlsctx_client_cache, connected, client_senddone, + response_shutdown, test, &test->id, &test->dispentry); assert_int_equal(result, ISC_R_SUCCESS); testdata.message[0] = (test->id >> 8) & 0xff; @@ -754,10 +755,10 @@ ISC_LOOP_TEST_IMPL(dispatch_timeout_udp_response) { assert_int_equal(result, ISC_R_SUCCESS); result = dns_dispatch_add(test->dispatch, isc_loop_main(loopmgr), 0, - T_CLIENT_CONNECT_SHORT, &udp_server_addr, - NULL, NULL, connected, client_senddone, - response_timeout, test, &test->id, - &test->dispentry); + T_CLIENT_CONNECT, T_CLIENT_SHORT, + &udp_server_addr, NULL, NULL, connected, + client_senddone, response_timeout, test, + &test->id, &test->dispentry); assert_int_equal(result, ISC_R_SUCCESS); dns_dispatch_connect(test->dispentry); @@ -788,10 +789,11 @@ ISC_LOOP_TEST_IMPL(dispatch_getnext) { &test->dispatch); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_dispatch_add( - test->dispatch, isc_loop_main(loopmgr), 0, T_CLIENT_CONNECT, - &udp_server_addr, NULL, NULL, connected, client_senddone, - response_getnext, test, &test->id, &test->dispentry); + result = dns_dispatch_add(test->dispatch, isc_loop_main(loopmgr), 0, + T_CLIENT_CONNECT, T_CLIENT_INIT, + &udp_server_addr, NULL, NULL, connected, + client_senddone, response_getnext, test, + &test->id, &test->dispentry); assert_int_equal(result, ISC_R_SUCCESS); testdata.message[0] = (test->id >> 8) & 0xff; @@ -826,8 +828,9 @@ ISC_LOOP_TEST_IMPL(dispatch_gettcp) { result = dns_dispatch_add( test->dispatch, isc_loop_main(loopmgr), 0, T_CLIENT_CONNECT, - &tcp_server_addr, NULL, NULL, connected_gettcp, client_senddone, - response_noop, test, &test->id, &test->dispentry); + T_CLIENT_INIT, &tcp_server_addr, NULL, NULL, connected_gettcp, + client_senddone, response_noop, test, &test->id, + &test->dispentry); assert_int_equal(result, ISC_R_SUCCESS); dns_dispatch_connect(test->dispentry); @@ -859,8 +862,9 @@ ISC_LOOP_TEST_IMPL(dispatch_newtcp) { result = dns_dispatch_add( test->dispatch, isc_loop_main(loopmgr), 0, T_CLIENT_CONNECT, - &tcp_server_addr, NULL, NULL, connected_newtcp, client_senddone, - response_noop, test, &test->id, &test->dispentry); + T_CLIENT_INIT, &tcp_server_addr, NULL, NULL, connected_newtcp, + client_senddone, response_noop, test, &test->id, + &test->dispentry); assert_int_equal(result, ISC_R_SUCCESS); dns_dispatch_connect(test->dispentry);