diff --git a/bin/delv/delv.c b/bin/delv/delv.c index dd1181076b..3559f1bf63 100644 --- a/bin/delv/delv.c +++ b/bin/delv/delv.c @@ -1725,7 +1725,6 @@ main(int argc, char *argv[]) { isc_appctx_t *actx = NULL; isc_nm_t *netmgr = NULL; isc_taskmgr_t *taskmgr = NULL; - isc_socketmgr_t *socketmgr = NULL; isc_timermgr_t *timermgr = NULL; dns_master_style_t *style = NULL; struct sigaction sa; @@ -1744,8 +1743,8 @@ main(int argc, char *argv[]) { isc_mem_create(&mctx); CHECK(isc_appctx_create(mctx, &actx)); - isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr, - &socketmgr); + + isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr, NULL); parse_args(argc, argv); @@ -1763,7 +1762,7 @@ main(int argc, char *argv[]) { } /* Create client */ - result = dns_client_create(mctx, actx, taskmgr, socketmgr, timermgr, 0, + result = dns_client_create(mctx, actx, taskmgr, netmgr, timermgr, 0, &client, srcaddr4, srcaddr6); if (result != ISC_R_SUCCESS) { delv_log(ISC_LOG_ERROR, "dns_client_create: %s", @@ -1846,7 +1845,9 @@ cleanup: if (client != NULL) { dns_client_detach(&client); } - isc_managers_destroy(&netmgr, &taskmgr, &timermgr, &socketmgr); + + isc_managers_destroy(&netmgr, &taskmgr, &timermgr, NULL); + if (actx != NULL) { isc_appctx_destroy(&actx); } diff --git a/bin/named/server.c b/bin/named/server.c index e70cba3662..0abefe8407 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -1315,8 +1315,8 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af, } } - result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_socketmgr, - named_g_taskmgr, &sa, attrs, &disp); + result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_taskmgr, + &sa, attrs, &disp); if (result != ISC_R_SUCCESS) { isc_sockaddr_t any; char buf[ISC_SOCKADDR_FORMATSIZE]; @@ -4716,7 +4716,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, ndisp = 4 * ISC_MIN(named_g_udpdisp, MAX_UDP_DISPATCH); CHECK(dns_view_createresolver( view, named_g_taskmgr, RESOLVER_NTASKS_PERCPU * named_g_cpus, - ndisp, named_g_socketmgr, named_g_timermgr, resopts, + ndisp, named_g_netmgr, named_g_timermgr, resopts, named_g_dispatchmgr, dispatch4, dispatch6)); if (dscp4 == -1) { @@ -9862,7 +9862,8 @@ run_server(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); - CHECKFATAL(dns_dispatchmgr_create(named_g_mctx, &named_g_dispatchmgr), + CHECKFATAL(dns_dispatchmgr_create(named_g_mctx, named_g_netmgr, + &named_g_dispatchmgr), "creating dispatch manager"); dns_dispatchmgr_setstats(named_g_dispatchmgr, server->resolverstats); @@ -10357,8 +10358,8 @@ named_add_reserved_dispatch(named_server_t *server, dispatch->dispatchgen = server->dispatchgen; dispatch->dispatch = NULL; - result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_socketmgr, - named_g_taskmgr, &dispatch->addr, attrs, + result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_taskmgr, + &dispatch->addr, attrs, &dispatch->dispatch); if (result != ISC_R_SUCCESS) { goto cleanup; diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index be39164216..a3bb130a7e 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -38,11 +39,9 @@ #include #include #include -#include #include #include #include -#include #include #include @@ -131,8 +130,6 @@ static isc_log_t *glctx = NULL; static isc_mem_t *gmctx = NULL; static dns_dispatchmgr_t *dispatchmgr = NULL; static dns_requestmgr_t *requestmgr = NULL; -static isc_socketmgr_t *socketmgr = NULL; -static isc_timermgr_t *timermgr = NULL; static dns_dispatch_t *dispatchv4 = NULL; static dns_dispatch_t *dispatchv6 = NULL; static dns_message_t *updatemsg = NULL; @@ -917,11 +914,12 @@ setup_system(void) { irs_resconf_destroy(&resconf); - result = dns_dispatchmgr_create(gmctx, &dispatchmgr); - check_result(result, "dns_dispatchmgr_create"); + result = isc_managers_create(gmctx, 1, 0, 0, &netmgr, &taskmgr, NULL, + NULL); + check_result(result, "isc_managers_create"); - isc_managers_create(gmctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr, - &socketmgr); + result = dns_dispatchmgr_create(gmctx, netmgr, &dispatchmgr); + check_result(result, "dns_dispatchmgr_create"); result = isc_task_create(taskmgr, 0, &global_task); check_result(result, "isc_task_create"); @@ -937,21 +935,20 @@ setup_system(void) { if (have_ipv6) { isc_sockaddr_any6(&bind_any6); - result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, + result = dns_dispatch_createudp(dispatchmgr, taskmgr, &bind_any6, 0, &dispatchv6); check_result(result, "dns_dispatch_createudp (v6)"); } if (have_ipv4) { isc_sockaddr_any(&bind_any); - result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, - &bind_any, 0, &dispatchv4); + result = dns_dispatch_createudp(dispatchmgr, taskmgr, &bind_any, + 0, &dispatchv4); check_result(result, "dns_dispatch_createudp (v4)"); } - result = dns_requestmgr_create(gmctx, timermgr, socketmgr, taskmgr, - dispatchmgr, dispatchv4, dispatchv6, - &requestmgr); + result = dns_requestmgr_create(gmctx, taskmgr, dispatchmgr, dispatchv4, + dispatchv6, &requestmgr); check_result(result, "dns_requestmgr_create"); if (keystr != NULL) { @@ -3322,7 +3319,7 @@ cleanup(void) { } ddebug("Shutting down managers"); - isc_managers_destroy(&netmgr, &taskmgr, &timermgr, &socketmgr); + isc_managers_destroy(&netmgr, &taskmgr, NULL, NULL); ddebug("Destroying event"); isc_event_free(&global_event); diff --git a/bin/tests/system/pipelined/pipequeries.c b/bin/tests/system/pipelined/pipequeries.c index 6466771ff2..6b34dd808c 100644 --- a/bin/tests/system/pipelined/pipequeries.c +++ b/bin/tests/system/pipelined/pipequeries.c @@ -23,12 +23,11 @@ #include #include #include +#include #include #include #include -#include #include -#include #include #include @@ -70,7 +69,8 @@ static void recvresponse(isc_task_t *task, isc_event_t *event) { dns_requestevent_t *reqev = (dns_requestevent_t *)event; isc_result_t result; - dns_message_t *query = NULL, *response = NULL; + dns_message_t *query = NULL; + dns_message_t *response = NULL; isc_buffer_t outbuf; char output[1024]; @@ -203,8 +203,6 @@ main(int argc, char *argv[]) { isc_nm_t *netmgr = NULL; isc_taskmgr_t *taskmgr = NULL; isc_task_t *task = NULL; - isc_timermgr_t *timermgr = NULL; - isc_socketmgr_t *socketmgr = NULL; dns_dispatchmgr_t *dispatchmgr = NULL; dns_dispatch_t *dispatchv4 = NULL; dns_view_t *view = NULL; @@ -267,18 +265,15 @@ main(int argc, char *argv[]) { RUNCHECK(dst_lib_init(mctx, NULL)); - isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr, - &socketmgr); - + isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, NULL, NULL); RUNCHECK(isc_task_create(taskmgr, 0, &task)); - RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); + RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr)); - RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, + RUNCHECK(dns_dispatch_createudp(dispatchmgr, taskmgr, have_src ? &srcaddr : &bind_any, 0, &dispatchv4)); - RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, - dispatchmgr, dispatchv4, NULL, - &requestmgr)); + RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4, + NULL, &requestmgr)); RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); RUNCHECK(isc_app_onrun(mctx, task, sendqueries, NULL)); @@ -296,7 +291,7 @@ main(int argc, char *argv[]) { isc_task_shutdown(task); isc_task_detach(&task); - isc_managers_destroy(&netmgr, &taskmgr, &timermgr, &socketmgr); + isc_managers_destroy(&netmgr, &taskmgr, NULL, NULL); dst_lib_destroy(); diff --git a/bin/tests/system/resolve.c b/bin/tests/system/resolve.c index c13cb5bee4..6508b6e9ff 100644 --- a/bin/tests/system/resolve.c +++ b/bin/tests/system/resolve.c @@ -27,9 +27,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -58,13 +58,11 @@ isc_mem_t *ctxs_mctx = NULL; isc_appctx_t *ctxs_actx = NULL; isc_nm_t *ctxs_netmgr = NULL; isc_taskmgr_t *ctxs_taskmgr = NULL; -isc_socketmgr_t *ctxs_socketmgr = NULL; isc_timermgr_t *ctxs_timermgr = NULL; static void ctxs_destroy(void) { - isc_managers_destroy(&ctxs_netmgr, &ctxs_taskmgr, &ctxs_timermgr, - &ctxs_socketmgr); + isc_managers_destroy(&ctxs_netmgr, &ctxs_taskmgr, &ctxs_timermgr, NULL); if (ctxs_actx != NULL) { isc_appctx_destroy(&ctxs_actx); @@ -87,7 +85,7 @@ ctxs_init(void) { } isc_managers_create(ctxs_mctx, 1, 0, 0, &ctxs_netmgr, &ctxs_taskmgr, - &ctxs_timermgr, &ctxs_socketmgr); + &ctxs_timermgr, NULL); result = isc_app_ctxstart(ctxs_actx); if (result != ISC_R_SUCCESS) { @@ -102,7 +100,7 @@ fail: return (result); } -static char *algname; +static char *algname = NULL; static isc_result_t printdata(dns_rdataset_t *rdataset, dns_name_t *owner) { @@ -281,9 +279,9 @@ main(int argc, char *argv[]) { isc_buffer_t b; dns_fixedname_t qname0; unsigned int namelen; - dns_name_t *qname, *name; + dns_name_t *qname = NULL, *name = NULL; dns_rdatatype_t type = dns_rdatatype_a; - dns_rdataset_t *rdataset; + dns_rdataset_t *rdataset = NULL; dns_namelist_t namelist; unsigned int clientopt, resopt = 0; bool is_sep = false; @@ -406,7 +404,7 @@ main(int argc, char *argv[]) { clientopt = 0; result = dns_client_create(ctxs_mctx, ctxs_actx, ctxs_taskmgr, - ctxs_socketmgr, ctxs_timermgr, clientopt, + ctxs_netmgr, ctxs_timermgr, clientopt, &client, addr4, addr6); if (result != ISC_R_SUCCESS) { fprintf(stderr, "dns_client_create failed: %u, %s\n", result, diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c index 6904c1998a..9ede9a65b5 100644 --- a/bin/tests/system/tkey/keycreate.c +++ b/bin/tests/system/tkey/keycreate.c @@ -18,13 +18,12 @@ #include #include #include +#include #include #include #include #include -#include #include -#include #include #include @@ -86,7 +85,6 @@ recvquery(isc_task_t *task, isc_event_t *event) { query = reqev->ev_arg; - response = NULL; dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); result = dns_request_getresponse(reqev->request, response, @@ -190,9 +188,6 @@ main(int argc, char *argv[]) { char *ourkeyname = NULL; isc_nm_t *netmgr = NULL; isc_taskmgr_t *taskmgr = NULL; - isc_timermgr_t *timermgr = NULL; - isc_socketmgr_t *socketmgr = NULL; - isc_socket_t *sock = NULL; isc_sockaddr_t bind_any; dns_dispatchmgr_t *dispatchmgr = NULL; dns_dispatch_t *dispatchv4 = NULL; @@ -227,18 +222,16 @@ main(int argc, char *argv[]) { RUNCHECK(dst_lib_init(mctx, NULL)); - isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr, - &socketmgr); + isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, NULL, NULL); RUNCHECK(isc_task_create(taskmgr, 0, &task)); - RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); + RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr)); isc_sockaddr_any(&bind_any); - RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, - &bind_any, 0, &dispatchv4)); - RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, - dispatchmgr, dispatchv4, NULL, - &requestmgr)); + RUNCHECK(dns_dispatch_createudp(dispatchmgr, taskmgr, &bind_any, 0, + &dispatchv4)); + RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4, + NULL, &requestmgr)); RUNCHECK(dns_tsigkeyring_create(mctx, &ring)); RUNCHECK(dns_tkeyctx_create(mctx, &tctx)); @@ -247,9 +240,6 @@ main(int argc, char *argv[]) { dns_view_setkeyring(view, ring); dns_tsigkeyring_detach(&ring); - RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, - &sock)); - RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL)); type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY; @@ -268,8 +258,7 @@ main(int argc, char *argv[]) { dns_dispatchmgr_destroy(&dispatchmgr); isc_task_shutdown(task); isc_task_detach(&task); - isc_socket_detach(&sock); - isc_managers_destroy(&netmgr, &taskmgr, &timermgr, &socketmgr); + isc_managers_destroy(&netmgr, &taskmgr, NULL, NULL); dst_key_free(&ourkey); dns_tsigkey_detach(&initialkey); diff --git a/bin/tests/system/tkey/keydelete.c b/bin/tests/system/tkey/keydelete.c index 1b8d3dc336..c76d816132 100644 --- a/bin/tests/system/tkey/keydelete.c +++ b/bin/tests/system/tkey/keydelete.c @@ -22,9 +22,7 @@ #include #include #include -#include #include -#include #include #include @@ -134,9 +132,6 @@ main(int argc, char **argv) { char *keyname = NULL; isc_nm_t *netmgr = NULL; isc_taskmgr_t *taskmgr = NULL; - isc_timermgr_t *timermgr = NULL; - isc_socketmgr_t *socketmgr = NULL; - isc_socket_t *sock = NULL; isc_sockaddr_t bind_any; dns_dispatchmgr_t *dispatchmgr = NULL; dns_dispatch_t *dispatchv4 = NULL; @@ -171,17 +166,15 @@ main(int argc, char **argv) { RUNCHECK(dst_lib_init(mctx, NULL)); - isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr, - &socketmgr); + isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, NULL, NULL); RUNCHECK(isc_task_create(taskmgr, 0, &task)); - RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); + RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr)); isc_sockaddr_any(&bind_any); - RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, - &bind_any, 0, &dispatchv4)); - RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, - dispatchmgr, dispatchv4, NULL, - &requestmgr)); + RUNCHECK(dns_dispatch_createudp(dispatchmgr, taskmgr, &bind_any, 0, + &dispatchv4)); + RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4, + NULL, &requestmgr)); RUNCHECK(dns_tsigkeyring_create(mctx, &ring)); RUNCHECK(dns_tkeyctx_create(mctx, &tctx)); @@ -189,9 +182,6 @@ main(int argc, char **argv) { RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); dns_view_setkeyring(view, ring); - RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, - &sock)); - RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL)); type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY; @@ -211,8 +201,7 @@ main(int argc, char **argv) { dns_dispatchmgr_destroy(&dispatchmgr); isc_task_shutdown(task); isc_task_detach(&task); - isc_socket_detach(&sock); - isc_managers_destroy(&netmgr, &taskmgr, &timermgr, &socketmgr); + isc_managers_destroy(&netmgr, &taskmgr, NULL, NULL); dns_tsigkeyring_detach(&ring); diff --git a/bin/tools/mdig.c b/bin/tools/mdig.c index 9c58a337cd..f3d37da52c 100644 --- a/bin/tools/mdig.c +++ b/bin/tools/mdig.c @@ -24,15 +24,14 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include -#include #include #include @@ -2068,8 +2067,6 @@ main(int argc, char *argv[]) { isc_nm_t *netmgr = NULL; isc_taskmgr_t *taskmgr = NULL; isc_task_t *task = NULL; - isc_timermgr_t *timermgr = NULL; - isc_socketmgr_t *socketmgr = NULL; dns_dispatchmgr_t *dispatchmgr = NULL; dns_dispatch_t *dispatchvx = NULL; dns_view_t *view = NULL; @@ -2122,25 +2119,22 @@ main(int argc, char *argv[]) { fatal("can't choose between IPv4 and IPv6"); } - isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, &timermgr, - &socketmgr); - + isc_managers_create(mctx, 1, 0, 0, &netmgr, &taskmgr, NULL, NULL); RUNCHECK(isc_task_create(taskmgr, 0, &task)); - RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); + RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr)); if (have_ipv4) { isc_sockaddr_any(&bind_any); } else { isc_sockaddr_any6(&bind_any); } - RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, + RUNCHECK(dns_dispatch_createudp(dispatchmgr, taskmgr, have_src ? &srcaddr : &bind_any, 0, &dispatchvx)); RUNCHECK(dns_requestmgr_create( - mctx, timermgr, socketmgr, taskmgr, dispatchmgr, - have_ipv4 ? dispatchvx : NULL, have_ipv6 ? dispatchvx : NULL, - &requestmgr)); + mctx, taskmgr, dispatchmgr, have_ipv4 ? dispatchvx : NULL, + have_ipv6 ? dispatchvx : NULL, &requestmgr)); RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); @@ -2186,7 +2180,7 @@ main(int argc, char *argv[]) { isc_task_shutdown(task); isc_task_detach(&task); - isc_managers_destroy(&netmgr, &taskmgr, &timermgr, &socketmgr); + isc_managers_destroy(&netmgr, &taskmgr, NULL, NULL); dst_lib_destroy(); diff --git a/lib/dns/client.c b/lib/dns/client.c index 1d113972b8..70a1adb859 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -86,7 +86,7 @@ struct dns_client { isc_appctx_t *actx; isc_taskmgr_t *taskmgr; isc_task_t *task; - isc_socketmgr_t *socketmgr; + isc_nm_t *nm; isc_timermgr_t *timermgr; dns_dispatchmgr_t *dispatchmgr; dns_dispatch_t *dispatchv4; @@ -202,8 +202,8 @@ cleanup: static isc_result_t getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, - isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr, - dns_dispatch_t **dispp, const isc_sockaddr_t *localaddr) { + isc_taskmgr_t *taskmgr, dns_dispatch_t **dispp, + const isc_sockaddr_t *localaddr) { dns_dispatch_t *disp = NULL; isc_result_t result; isc_sockaddr_t anyaddr; @@ -213,8 +213,8 @@ getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, localaddr = &anyaddr; } - result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, - localaddr, 0, &disp); + result = dns_dispatch_createudp(dispatchmgr, taskmgr, localaddr, 0, + &disp); if (result == ISC_R_SUCCESS) { *dispp = disp; } @@ -224,10 +224,9 @@ getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, static isc_result_t createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, isc_taskmgr_t *taskmgr, - unsigned int ntasks, isc_socketmgr_t *socketmgr, - isc_timermgr_t *timermgr, dns_dispatchmgr_t *dispatchmgr, - dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, - dns_view_t **viewp) { + unsigned int ntasks, isc_nm_t *nm, isc_timermgr_t *timermgr, + dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4, + dns_dispatch_t *dispatchv6, dns_view_t **viewp) { isc_result_t result; dns_view_t *view = NULL; @@ -243,8 +242,8 @@ createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, isc_taskmgr_t *taskmgr, return (result); } - result = dns_view_createresolver(view, taskmgr, ntasks, 1, socketmgr, - timermgr, 0, dispatchmgr, dispatchv4, + result = dns_view_createresolver(view, taskmgr, ntasks, 1, nm, timermgr, + 0, dispatchmgr, dispatchv4, dispatchv6); if (result != ISC_R_SUCCESS) { dns_view_detach(&view); @@ -264,9 +263,8 @@ createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, isc_taskmgr_t *taskmgr, isc_result_t dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, - isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, - unsigned int options, dns_client_t **clientp, - const isc_sockaddr_t *localaddr4, + isc_nm_t *nm, isc_timermgr_t *timermgr, unsigned int options, + dns_client_t **clientp, const isc_sockaddr_t *localaddr4, const isc_sockaddr_t *localaddr6) { isc_result_t result; dns_client_t *client = NULL; @@ -278,27 +276,24 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, REQUIRE(mctx != NULL); REQUIRE(taskmgr != NULL); REQUIRE(timermgr != NULL); - REQUIRE(socketmgr != NULL); + REQUIRE(nm != NULL); REQUIRE(clientp != NULL && *clientp == NULL); UNUSED(options); client = isc_mem_get(mctx, sizeof(*client)); + *client = (dns_client_t){ + .actx = actx, .taskmgr = taskmgr, .timermgr = timermgr, .nm = nm + }; isc_mutex_init(&client->lock); - client->actx = actx; - client->taskmgr = taskmgr; - client->socketmgr = socketmgr; - client->timermgr = timermgr; - - client->task = NULL; result = isc_task_create(client->taskmgr, 0, &client->task); if (result != ISC_R_SUCCESS) { goto cleanup_lock; } - result = dns_dispatchmgr_create(mctx, &dispatchmgr); + result = dns_dispatchmgr_create(mctx, nm, &dispatchmgr); if (result != ISC_R_SUCCESS) { goto cleanup_task; } @@ -311,8 +306,8 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, */ client->dispatchv4 = NULL; if (localaddr4 != NULL || localaddr6 == NULL) { - result = getudpdispatch(AF_INET, dispatchmgr, socketmgr, - taskmgr, &dispatchv4, localaddr4); + result = getudpdispatch(AF_INET, dispatchmgr, taskmgr, + &dispatchv4, localaddr4); if (result == ISC_R_SUCCESS) { client->dispatchv4 = dispatchv4; } @@ -320,8 +315,8 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, client->dispatchv6 = NULL; if (localaddr6 != NULL || localaddr4 == NULL) { - result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr, - taskmgr, &dispatchv6, localaddr6); + result = getudpdispatch(AF_INET6, dispatchmgr, taskmgr, + &dispatchv6, localaddr6); if (result == ISC_R_SUCCESS) { client->dispatchv6 = dispatchv6; } @@ -337,8 +332,8 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, /* Create the default view for class IN */ result = createview(mctx, dns_rdataclass_in, taskmgr, RESOLVER_NTASKS, - socketmgr, timermgr, dispatchmgr, dispatchv4, - dispatchv6, &view); + nm, timermgr, dispatchmgr, dispatchv4, dispatchv6, + &view); if (result != ISC_R_SUCCESS) { goto cleanup_references; } @@ -350,12 +345,10 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, ISC_LIST_INIT(client->resctxs); - client->mctx = NULL; isc_mem_attach(mctx, &client->mctx); client->find_timeout = DEF_FIND_TIMEOUT; client->find_udpretries = DEF_FIND_UDPRETRIES; - client->attributes = 0; client->magic = DNS_CLIENT_MAGIC; diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index e8f78d5550..a159e79c55 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -19,10 +19,10 @@ #include #include +#include #include #include #include -#include #include #include #include @@ -40,15 +40,13 @@ typedef ISC_LIST(dns_dispentry_t) dns_displist_t; typedef struct dispsocket dispsocket_t; -typedef ISC_LIST(dispsocket_t) dispsocketlist_t; typedef struct dns_qid { unsigned int magic; + isc_mutex_t lock; unsigned int qid_nbuckets; /*%< hash table size */ unsigned int qid_increment; /*%< id increment on collision */ - isc_mutex_t lock; - dns_displist_t *qid_table; /*%< the table itself */ - dispsocketlist_t *sock_table; /*%< socket table */ + dns_displist_t *qid_table; /*%< the table itself */ } dns_qid_t; struct dns_dispatchmgr { @@ -57,6 +55,7 @@ struct dns_dispatchmgr { isc_mem_t *mctx; dns_acl_t *blackhole; isc_stats_t *stats; + isc_nm_t *nm; /* Locked by "lock". */ isc_mutex_t lock; @@ -66,8 +65,7 @@ struct dns_dispatchmgr { /* locked by buffer_lock */ dns_qid_t *qid; isc_mutex_t buffer_lock; - unsigned int buffers; /*%< allocated buffers */ - unsigned int buffersize; /*%< size of each buffer */ + unsigned int buffers; isc_refcount_t irefs; @@ -86,9 +84,13 @@ struct dns_dispentry { dns_messageid_t id; in_port_t port; unsigned int bucket; - isc_sockaddr_t host; + unsigned int timeout; + isc_sockaddr_t peer; isc_task_t *task; + isc_nm_cb_t connected; + isc_nm_cb_t sent; isc_taskaction_t action; + isc_taskaction_t timeout_action; void *arg; bool item_out; dispsocket_t *dispsocket; @@ -105,51 +107,24 @@ struct dns_dispentry { struct dispsocket { unsigned int magic; - isc_socket_t *socket; + isc_nmhandle_t *handle; dns_dispatch_t *disp; - isc_sockaddr_t host; + isc_sockaddr_t local; + isc_sockaddr_t peer; dns_dispentry_t *resp; - isc_task_t *task; in_port_t port; ISC_LINK(dispsocket_t) link; - unsigned int bucket; - ISC_LINK(dispsocket_t) blink; }; -typedef struct tcpmsg { - uint16_t size; - dns_dispatch_t *disp; - isc_buffer_t buffer; - isc_task_t *task; - isc_taskaction_t action; - void *arg; - isc_event_t event; - isc_result_t result; - isc_sockaddr_t address; -} tcpmsg_t; - -/*% - * Number of tasks for each dispatch that use separate sockets for different - * transactions. This must be a power of 2 as it will divide 32 bit numbers - * to get an uniformly random tasks selection. See get_dispsocket(). - */ -#define MAX_INTERNAL_TASKS 64 - struct dns_dispatch { /* Unlocked. */ unsigned int magic; /*%< magic */ dns_dispatchmgr_t *mgr; /*%< dispatch manager */ - int ntasks; - /*% - * internal task buckets. We use multiple tasks to distribute various - * socket events well when using separate dispatch sockets. We use the - * 1st task (task[0]) for internal control events. - */ - isc_task_t *task[MAX_INTERNAL_TASKS]; - isc_socket_t *socket; /*%< isc socket attached to */ - isc_sockaddr_t local; /*%< local address */ - in_port_t localport; /*%< local UDP port */ - isc_sockaddr_t peer; /*%< peer address (TCP) */ + isc_task_t *task; + isc_nmhandle_t *handle; /*%< netmgr handle for TCP connection */ + isc_sockaddr_t local; /*%< local address */ + in_port_t localport; /*%< local UDP port */ + isc_sockaddr_t peer; /*%< peer address (TCP) */ isc_event_t *ctlevent; isc_mem_t *sepool; /*%< pool for socket events */ @@ -159,19 +134,17 @@ struct dns_dispatch { /* Locked by "lock". */ isc_mutex_t lock; /*%< locks all below */ - isc_sockettype_t socktype; + isc_socktype_t socktype; unsigned int attributes; isc_refcount_t refcount; dns_dispatchevent_t *failsafe_ev; /*%< failsafe cancel event */ - unsigned int shutting_down : 1, shutdown_out : 1, recv_pending : 1, - tcpmsg_valid : 1; + unsigned int shutting_down : 1, shutdown_out : 1, recv_pending : 1; isc_result_t shutdown_why; ISC_LIST(dispsocket_t) activesockets; ISC_LIST(dispsocket_t) inactivesockets; unsigned int nsockets; unsigned int requests; /*%< how many requests we have */ unsigned int tcpbuffers; /*%< allocated buffers */ - tcpmsg_t tcpmsg; }; #define QID_MAGIC ISC_MAGIC('Q', 'i', 'd', ' ') @@ -212,11 +185,11 @@ struct dns_dispatch { #endif /* ifndef DNS_DISPATCH_SOCKSQUOTA */ /*% - * Number of buffers available for all dispatches in the buffery memory - * pool. + * Number of buffers available for all dispatches in the buffer + * memory pool. */ #ifndef DNS_DISPATCH_MAXBUFFERS -#define DNS_DISPATCH_MAXBUFFERS 32768 +#define DNS_DISPATCH_MAXBUFFERS 37268 #endif /* ifndef DNS_DISPATCH_MAXBUFFERS */ /*% @@ -264,17 +237,13 @@ destroy_dispsocket(dns_dispatch_t *, dispsocket_t **); static void deactivate_dispsocket(dns_dispatch_t *, dispsocket_t *); static void -udp_recv(isc_task_t *, isc_event_t *); +udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, + void *arg); static void -tcp_recv(isc_task_t *, isc_event_t *); -static isc_result_t -startrecv(dns_dispatch_t *, dispsocket_t *); +tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, + void *arg); static uint32_t dns_hash(dns_qid_t *, const isc_sockaddr_t *, dns_messageid_t, in_port_t); -static void -free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len); -static void * -allocate_udp_buffer(dns_dispatch_t *disp); static inline void free_devent(dns_dispatch_t *disp, dns_dispatchevent_t *ev); static inline dns_dispatchevent_t * @@ -288,9 +257,9 @@ linear_next(dns_qid_t *disp, dns_dispentry_t *resp); static void dispatch_free(dns_dispatch_t **dispp); static isc_result_t -dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, - isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, - unsigned int attributes, dns_dispatch_t **dispp); +dispatch_createudp(dns_dispatchmgr_t *mgr, isc_taskmgr_t *taskmgr, + const isc_sockaddr_t *localaddr, unsigned int attributes, + dns_dispatch_t **dispp); static bool destroy_mgr_ok(dns_dispatchmgr_t *mgr); static void @@ -299,13 +268,12 @@ static void qid_allocate(dns_dispatchmgr_t *mgr, dns_qid_t **qidp); static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp); -static isc_result_t -open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local, - unsigned int options, isc_socket_t **sockp); -static isc_socket_t * -getentrysocket(dns_dispentry_t *resp); -static isc_socket_t * -getsocket(dns_dispatch_t *disp); +static isc_nmhandle_t * +gethandle(dns_dispatch_t *disp); +static isc_nmhandle_t * +getentryhandle(dns_dispentry_t *resp); +static void +startrecv(dns_dispatch_t *disp, dispsocket_t *dispsocket); #define LVL(x) ISC_LOG_DEBUG(x) @@ -387,7 +355,7 @@ request_log(dns_dispatch_t *disp, dns_dispentry_t *resp, int level, va_end(ap); if (VALID_RESPONSE(resp)) { - isc_sockaddr_format(&resp->host, peerbuf, sizeof(peerbuf)); + isc_sockaddr_format(&resp->peer, peerbuf, sizeof(peerbuf)); isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH, DNS_LOGMODULE_DISPATCH, level, "dispatch %p response %p %s: %s", disp, resp, @@ -498,7 +466,6 @@ destroy_disp(isc_task_t *task, isc_event_t *event) { dns_dispatchmgr_t *mgr = NULL; bool killmgr; dispsocket_t *dispsocket = NULL; - int i; INSIST(event->ev_type == DNS_EVENT_DISPATCHCONTROL); @@ -510,23 +477,21 @@ destroy_disp(isc_task_t *task, isc_event_t *event) { LOCK(&mgr->lock); ISC_LIST_UNLINK(mgr->list, disp, link); - dispatch_log(disp, LVL(90), "shutting down; detaching from sock %p", - disp->socket); + dispatch_log(disp, LVL(90), "shutting down; detaching from handle %p", + disp->handle); if (disp->sepool != NULL) { isc_mem_destroy(&disp->sepool); } - if (disp->socket != NULL) { - isc_socket_detach(&disp->socket); + if (disp->handle != NULL) { + isc_nmhandle_detach(&disp->handle); } while ((dispsocket = ISC_LIST_HEAD(disp->inactivesockets)) != NULL) { ISC_LIST_UNLINK(disp->inactivesockets, dispsocket, link); destroy_dispsocket(disp, &dispsocket); } - for (i = 0; i < disp->ntasks; i++) { - isc_task_detach(&disp->task[i]); - } + isc_task_detach(&disp->task); isc_event_free(&event); dispatch_free(&disp); @@ -538,47 +503,15 @@ destroy_disp(isc_task_t *task, isc_event_t *event) { } } -/*% - * Find a dispsocket for socket address 'dest', and port number 'port'. - * Return NULL if no such entry exists. Requires qid->lock to be held. - */ -static dispsocket_t * -socket_search(dns_qid_t *qid, const isc_sockaddr_t *dest, in_port_t port, - unsigned int bucket) { - dispsocket_t *dispsock = NULL; - - REQUIRE(VALID_QID(qid)); - REQUIRE(bucket < qid->qid_nbuckets); - - dispsock = ISC_LIST_HEAD(qid->sock_table[bucket]); - - while (dispsock != NULL) { - if (dispsock->port == port && - isc_sockaddr_equal(dest, &dispsock->host)) { - return (dispsock); - } - dispsock = ISC_LIST_NEXT(dispsock, blink); - } - - return (NULL); -} - /*% * Make a new socket for a single dispatch with a random port number. * The caller must hold the disp->lock */ static isc_result_t get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, - isc_socketmgr_t *sockmgr, dispsocket_t **dispsockp, - in_port_t *portp) { - int i; + dispsocket_t **dispsockp, in_port_t *portp) { dns_dispatchmgr_t *mgr = disp->mgr; - dns_qid_t *qid = mgr->qid; - isc_socket_t *sock = NULL; - isc_result_t result = ISC_R_FAILURE; in_port_t port; - isc_sockaddr_t localaddr; - unsigned int bucket = 0; dispsocket_t *dispsock = NULL; unsigned int nports; in_port_t *ports = NULL; @@ -597,71 +530,23 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, dispsock = ISC_LIST_HEAD(disp->inactivesockets); if (dispsock != NULL) { ISC_LIST_UNLINK(disp->inactivesockets, dispsock, link); - sock = dispsock->socket; - dispsock->socket = NULL; } else { dispsock = isc_mem_get(mgr->mctx, sizeof(*dispsock)); - disp->nsockets++; *dispsock = (dispsocket_t){ .disp = disp }; - isc_task_attach(disp->task[isc_random_uniform(disp->ntasks)], - &dispsock->task); ISC_LINK_INIT(dispsock, link); - ISC_LINK_INIT(dispsock, blink); dispsock->magic = DISPSOCK_MAGIC; } - /* - * Pick up a random UDP port and open a new socket with it. Avoid - * choosing ports that share the same destination because it will be - * very likely to fail in bind(2) or connect(2). - */ - localaddr = disp->local; + dispsock->local = disp->local; + dispsock->peer = *dest; - for (i = 0; i < 64; i++) { - port = ports[isc_random_uniform(nports)]; - isc_sockaddr_setport(&localaddr, port); - - LOCK(&qid->lock); - bucket = dns_hash(qid, dest, 0, port); - if (socket_search(qid, dest, port, bucket) != NULL) { - UNLOCK(&qid->lock); - continue; - } - UNLOCK(&qid->lock); - - result = open_socket(sockmgr, &localaddr, - ISC_SOCKET_REUSEADDRESS, &sock); - if (result == ISC_R_SUCCESS) { - break; - } else if (result == ISC_R_NOPERM) { - char buf[ISC_SOCKADDR_FORMATSIZE]; - isc_sockaddr_format(&localaddr, buf, sizeof(buf)); - dispatch_log(disp, ISC_LOG_WARNING, - "open_socket(%s) -> %s: continuing", buf, - isc_result_totext(result)); - } else if (result != ISC_R_ADDRINUSE) { - break; - } - } - - if (result != ISC_R_SUCCESS) { - if (sock != NULL) { - isc_socket_detach(&sock); - } - destroy_dispsocket(disp, &dispsock); - return (result); - } - - dispsock->socket = sock; - dispsock->host = *dest; - dispsock->bucket = bucket; + /* Pick a random UDP port */ + port = ports[isc_random_uniform(nports)]; + isc_sockaddr_setport(&dispsock->local, port); dispsock->port = port; - LOCK(&qid->lock); - ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink); - UNLOCK(&qid->lock); *dispsockp = dispsock; *portp = port; @@ -670,77 +555,52 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, /*% * Destroy a dedicated dispatch socket. + * The dispatch must be locked. */ static void destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) { dispsocket_t *dispsock = NULL; - dns_qid_t *qid = disp->mgr->qid; - - /* - * The dispatch must be locked. - */ REQUIRE(dispsockp != NULL && *dispsockp != NULL); + dispsock = *dispsockp; *dispsockp = NULL; + REQUIRE(!ISC_LINK_LINKED(dispsock, link)); disp->nsockets--; dispsock->magic = 0; - if (dispsock->socket != NULL) { - isc_socket_detach(&dispsock->socket); - } - if (ISC_LINK_LINKED(dispsock, blink)) { - LOCK(&qid->lock); - ISC_LIST_UNLINK(qid->sock_table[dispsock->bucket], dispsock, - blink); - UNLOCK(&qid->lock); - } - if (dispsock->task != NULL) { - isc_task_detach(&dispsock->task); + if (dispsock->handle != NULL) { + isc_nm_cancelread(dispsock->handle); + isc_nmhandle_detach(&dispsock->handle); } + isc_mem_put(disp->mgr->mctx, dispsock, sizeof(*dispsock)); } /*% * Deactivate a dedicated dispatch socket. Move it to the inactive list for * future reuse unless the total number of sockets are exceeding the maximum. + * The dispatch must be locked. */ static void deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { - isc_result_t result; - dns_qid_t *qid = disp->mgr->qid; - - /* - * The dispatch must be locked. - */ ISC_LIST_UNLINK(disp->activesockets, dispsock, link); if (dispsock->resp != NULL) { INSIST(dispsock->resp->dispsocket == dispsock); dispsock->resp->dispsocket = NULL; + dispsock->resp = NULL; } if (disp->nsockets > DNS_DISPATCH_POOLSOCKS) { destroy_dispsocket(disp, &dispsock); } else { - result = isc_socket_close(dispsock->socket); - - LOCK(&qid->lock); - ISC_LIST_UNLINK(qid->sock_table[dispsock->bucket], dispsock, - blink); - UNLOCK(&qid->lock); - - if (result == ISC_R_SUCCESS) { - ISC_LIST_APPEND(disp->inactivesockets, dispsock, link); - } else { - /* - * If the underlying system does not allow this - * optimization, destroy this temporary structure (and - * create a new one for a new transaction). - */ - INSIST(result == ISC_R_NOTIMPLEMENTED); - destroy_dispsocket(disp, &dispsock); + if (dispsock->handle != NULL) { + isc_nm_cancelread(dispsock->handle); + isc_nmhandle_detach(&dispsock->handle); } + + ISC_LIST_APPEND(disp->inactivesockets, dispsock, link); } } @@ -760,7 +620,7 @@ entry_search(dns_qid_t *qid, const isc_sockaddr_t *dest, dns_messageid_t id, res = ISC_LIST_HEAD(qid->qid_table[bucket]); while (res != NULL) { - if (res->id == id && isc_sockaddr_equal(dest, &res->host) && + if (res->id == id && isc_sockaddr_equal(dest, &res->peer) && res->port == port) { return (res); } @@ -775,12 +635,12 @@ free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) { REQUIRE(buf != NULL && len != 0); switch (disp->socktype) { - case isc_sockettype_tcp: + case isc_socktype_tcp: INSIST(disp->tcpbuffers > 0); disp->tcpbuffers--; isc_mem_put(disp->mgr->mctx, buf, len); break; - case isc_sockettype_udp: + case isc_socktype_udp: LOCK(&disp->mgr->buffer_lock); INSIST(disp->mgr->buffers > 0); INSIST(len == DNS_DISPATCH_UDPBUFSIZE); @@ -807,33 +667,6 @@ allocate_udp_buffer(dns_dispatch_t *disp) { return (isc_mem_get(disp->mgr->mctx, DNS_DISPATCH_UDPBUFSIZE)); } -static inline void -free_sevent(isc_event_t *ev) { - isc_mem_t *pool = ev->ev_destroy_arg; - isc_socketevent_t *sev = (isc_socketevent_t *)ev; - isc_mem_put(pool, sev, sizeof(*sev)); -} - -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 = NULL; - void *deconst_arg; - - ev = isc_mem_get(disp->sepool, sizeof(*ev)); - DE_CONST(arg, deconst_arg); - ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, type, action, deconst_arg, - sock, free_sevent, disp->sepool); - ev->result = ISC_R_UNSET; - ISC_LINK_INIT(ev, ev_link); - ev->region.base = NULL; - ev->n = 0; - ev->offset = 0; - ev->attributes = 0; - - return (ev); -} - static inline void free_devent(dns_dispatch_t *disp, dns_dispatchevent_t *ev) { if (disp->failsafe_ev == ev) { @@ -843,6 +676,12 @@ free_devent(dns_dispatch_t *disp, dns_dispatchevent_t *ev) { return; } + if (ev->region.base != NULL) { + free_buffer(disp, ev->region.base, ev->region.length); + ev->region.base = NULL; + ev->region.length = 0; + } + isc_refcount_decrement(&disp->mgr->irefs); isc_mem_put(disp->mgr->mctx, ev, sizeof(*ev)); } @@ -853,6 +692,8 @@ allocate_devent(dns_dispatch_t *disp) { ev = isc_mem_get(disp->mgr->mctx, sizeof(*ev)); isc_refcount_increment0(&disp->mgr->irefs); + + *ev = (dns_dispatchevent_t){ 0 }; ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, 0, NULL, NULL, NULL, NULL, NULL); return (ev); @@ -873,9 +714,9 @@ allocate_devent(dns_dispatch_t *disp) { * restart. */ static void -udp_recv(isc_task_t *task, isc_event_t *ev_in) { - isc_socketevent_t *ev = (isc_socketevent_t *)ev_in; - dispsocket_t *dispsock = NULL; +udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, + void *arg) { + dispsocket_t *dispsock = (dispsocket_t *)arg; dns_dispatch_t *disp = NULL; dns_messageid_t id; isc_result_t dres; @@ -886,15 +727,10 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) { bool killit; bool queue_response; dns_dispatchmgr_t *mgr = NULL; + isc_sockaddr_t peer; isc_netaddr_t netaddr; + isc_taskaction_t action; int match; - int result; - - UNUSED(task); - - REQUIRE(ev->ev_type == ISC_SOCKEVENT_RECVDONE); - - dispsock = ev_in->ev_arg; REQUIRE(VALID_DISPSOCK(dispsock)); @@ -905,44 +741,32 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) { mgr = disp->mgr; LOCK(&disp->mgr->buffer_lock); - dispatch_log(disp, LVL(90), - "got packet: requests %d, buffers %d, recvs %d", - disp->requests, disp->mgr->buffers, disp->recv_pending); + dispatch_log(disp, LVL(90), "got packet: requests %d, recvs %d", + disp->requests, disp->recv_pending); UNLOCK(&disp->mgr->buffer_lock); - if (ev->result == ISC_R_CANCELED || dispsock->resp == NULL) { + if (eresult == ISC_R_CANCELED || dispsock->resp == NULL) { /* * dispsock->resp can be NULL if this transaction was canceled - * just after receiving a response. Since this socket is - * exclusively used and there should be at most one receive - * event the canceled event should have no effect. So - * we can (and should) deactivate the socket right now. + * just after receiving a response. So we can just move on. */ - deactivate_dispsocket(disp, dispsock); dispsock = NULL; } - if (disp->shutting_down) { + if (disp->shutting_down == 1) { /* * This dispatcher is shutting down. */ - free_buffer(disp, ev->region.base, ev->region.length); - - isc_event_free(&ev_in); - ev = NULL; - killit = destroy_disp_ok(disp); UNLOCK(&disp->lock); if (killit) { - isc_task_send(disp->task[0], &disp->ctlevent); + isc_task_send(disp->task, &disp->ctlevent); } return; } if (dispsock == NULL) { - free_buffer(disp, ev->region.base, ev->region.length); - isc_event_free(&ev_in); UNLOCK(&disp->lock); return; } @@ -950,20 +774,22 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) { resp = dispsock->resp; id = resp->id; - if (ev->result != ISC_R_SUCCESS) { + peer = isc_nmhandle_peeraddr(handle); + isc_netaddr_fromsockaddr(&netaddr, &peer); + + if (eresult != ISC_R_SUCCESS) { /* - * This is most likely a network error on a - * connected socket. It makes no sense to + * This is most likely either a timeout or 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; + goto sendevent; } /* * If this is from a blackholed address, drop it. */ - isc_netaddr_fromsockaddr(&netaddr, &ev->address); if (disp->mgr->blackhole != NULL && dns_acl_match(&netaddr, NULL, disp->mgr->blackhole, NULL, &match, NULL) == ISC_R_SUCCESS && @@ -976,20 +802,18 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) { dispatch_log(disp, LVL(10), "blackholed packet from %s", netaddrstr); } - free_buffer(disp, ev->region.base, ev->region.length); - goto restart; + goto next; } /* * Peek into the buffer to see what we can see. */ - isc_buffer_init(&source, ev->region.base, ev->region.length); - isc_buffer_add(&source, ev->n); + isc_buffer_init(&source, region->base, region->length); + isc_buffer_add(&source, region->length); dres = dns_message_peekheader(&source, &id, &flags); if (dres != ISC_R_SUCCESS) { - free_buffer(disp, ev->region.base, ev->region.length); dispatch_log(disp, LVL(10), "got garbage packet"); - goto restart; + goto next; } dispatch_log(disp, LVL(92), @@ -1002,105 +826,55 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) { */ if ((flags & DNS_MESSAGEFLAG_QR) == 0) { /* query */ - free_buffer(disp, ev->region.base, ev->region.length); - goto restart; + goto next; } /* * The QID and the address must match the expected ones. */ - if (resp->id != id || !isc_sockaddr_equal(&ev->address, &resp->host)) { + if (resp->id != id || !isc_sockaddr_equal(&peer, &resp->peer)) { dispatch_log(disp, LVL(90), "response doesn't match"); inc_stats(mgr, dns_resstatscounter_mismatch); - free_buffer(disp, ev->region.base, ev->region.length); - goto restart; + goto next; } - /* - * Now that we have the original dispatch the query was sent - * from check that the address and port the response was - * sent to make sense. - */ - if (disp != resp->disp) { - isc_sockaddr_t a1; - isc_sockaddr_t a2; - - /* - * Check that the socket types and ports match. - */ - if (disp->socktype != resp->disp->socktype || - isc_sockaddr_getport(&disp->local) != - isc_sockaddr_getport(&resp->disp->local)) - { - free_buffer(disp, ev->region.base, ev->region.length); - goto restart; - } - - /* - * If each dispatch is bound to a different address - * then fail. - * - * Note under Linux a packet can be sent out via IPv4 socket - * and the response be received via a IPv6 socket. - * - * Requests sent out via IPv6 should always come back in - * via IPv6. - */ - if (isc_sockaddr_pf(&resp->disp->local) == PF_INET6 && - isc_sockaddr_pf(&disp->local) != PF_INET6) - { - free_buffer(disp, ev->region.base, ev->region.length); - goto restart; - } - isc_sockaddr_anyofpf(&a1, isc_sockaddr_pf(&resp->disp->local)); - isc_sockaddr_anyofpf(&a2, isc_sockaddr_pf(&disp->local)); - if (!isc_sockaddr_eqaddr(&disp->local, &resp->disp->local) && - !isc_sockaddr_eqaddr(&a1, &resp->disp->local) && - !isc_sockaddr_eqaddr(&a2, &disp->local)) - { - free_buffer(disp, ev->region.base, ev->region.length); - goto restart; - } - } - -sendresponse: +sendevent: + rev = allocate_devent(disp); queue_response = resp->item_out; - rev = allocate_devent(resp->disp); /* * At this point, rev contains the event we want to fill in, and * resp contains the information on the place to send it to. * Send the event off. */ - isc_buffer_init(&rev->buffer, ev->region.base, ev->region.length); - isc_buffer_add(&rev->buffer, ev->n); - rev->result = ev->result; - rev->id = id; - rev->addr = ev->address; - rev->pktinfo = ev->pktinfo; - rev->attributes = ev->attributes; + rev->result = eresult; + resp->item_out = true; + if (region != NULL) { + rev->region.base = allocate_udp_buffer(disp); + rev->region.length = DNS_DISPATCH_UDPBUFSIZE; + memmove(rev->region.base, region->base, region->length); + isc_buffer_init(&rev->buffer, rev->region.base, + rev->region.length); + isc_buffer_add(&rev->buffer, rev->region.length); + } + + rev->result = eresult; if (queue_response) { ISC_LIST_APPEND(resp->items, rev, ev_link); } else { ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, DNS_EVENT_DISPATCH, - resp->action, resp->arg, resp, NULL, NULL); + action, resp->arg, resp, NULL, NULL); request_log(disp, resp, LVL(90), "[a] Sent event %p buffer %p len %d to task %p", rev, rev->buffer.base, rev->buffer.length, resp->task); - resp->item_out = true; isc_task_send(resp->task, ISC_EVENT_PTR(&rev)); } - /* - * Restart recv() to get the next packet. - */ -restart: - result = startrecv(disp, dispsock); - if (result != ISC_R_SUCCESS) { - deactivate_dispsocket(disp, dispsock); - } - isc_event_free(&ev_in); + UNLOCK(&disp->lock); + return; + +next: UNLOCK(&disp->lock); } @@ -1120,9 +894,9 @@ restart: * restart. */ static void -tcp_recv(isc_task_t *task, isc_event_t *ev_in) { - dns_dispatch_t *disp = ev_in->ev_arg; - tcpmsg_t *tcpmsg = &disp->tcpmsg; +tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, + void *arg) { + dns_dispatch_t *disp = (dns_dispatch_t *)arg; dns_messageid_t id; isc_result_t dres; unsigned int flags; @@ -1134,8 +908,9 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { dns_qid_t *qid = NULL; int level; char buf[ISC_SOCKADDR_FORMATSIZE]; - - UNUSED(task); + isc_buffer_t source; + isc_sockaddr_t peer; + isc_taskaction_t action; REQUIRE(VALID_DISPATCH(disp)); @@ -1154,11 +929,16 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { /* * This dispatcher is shutting down. Force cancellation. */ - tcpmsg->result = ISC_R_CANCELED; + eresult = ISC_R_CANCELED; } - if (tcpmsg->result != ISC_R_SUCCESS) { - switch (tcpmsg->result) { + peer = isc_nmhandle_peeraddr(handle); + isc_nmhandle_detach(&handle); + + if (eresult != ISC_R_SUCCESS) { + disp->shutdown_why = eresult; + + switch (eresult) { case ISC_R_CANCELED: break; @@ -1171,27 +951,23 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { level = ISC_LOG_INFO; goto logit; + case ISC_R_TIMEDOUT: + id = 0; /* XXX this is broken */ + goto sendevent; + default: level = ISC_LOG_ERROR; logit: - isc_sockaddr_format(&tcpmsg->address, buf, sizeof(buf)); + isc_sockaddr_format(&peer, buf, sizeof(buf)); dispatch_log(disp, level, "shutting down due to TCP " "receive error: %s: %s", - buf, isc_result_totext(tcpmsg->result)); + buf, isc_result_totext(eresult)); do_cancel(disp); break; } - /* - * The event is statically allocated in the tcpmsg - * structure, and destroy_disp() frees the tcpmsg, so we must - * free the event *before* calling destroy_disp(). - */ - isc_event_free(&ev_in); - disp->shutting_down = 1; - disp->shutdown_why = tcpmsg->result; /* * If the recv() was canceled pass the word on. @@ -1199,22 +975,23 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { killit = destroy_disp_ok(disp); UNLOCK(&disp->lock); if (killit) { - isc_task_send(disp->task[0], &disp->ctlevent); + isc_task_send(disp->task, &disp->ctlevent); } return; } dispatch_log(disp, LVL(90), "result %d, length == %d, addr = %p", - tcpmsg->result, disp->tcpmsg.buffer.length, - disp->tcpmsg.buffer.base); + eresult, region->length, region->base); /* * Peek into the buffer to see what we can see. */ - dres = dns_message_peekheader(&disp->tcpmsg.buffer, &id, &flags); + isc_buffer_init(&source, region->base, region->length); + isc_buffer_add(&source, region->length); + dres = dns_message_peekheader(&source, &id, &flags); if (dres != ISC_R_SUCCESS) { dispatch_log(disp, LVL(10), "got garbage packet"); - goto restart; + goto next; } dispatch_log(disp, LVL(92), @@ -1234,19 +1011,21 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { /* * Query. */ - goto restart; + goto next; } +sendevent: /* * Response. */ - bucket = dns_hash(qid, &tcpmsg->address, id, disp->localport); + bucket = dns_hash(qid, &peer, id, disp->localport); LOCK(&qid->lock); - resp = entry_search(qid, &tcpmsg->address, id, disp->localport, bucket); + resp = entry_search(qid, &peer, 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; + UNLOCK(&qid->lock); + goto next; } queue_response = resp->item_out; @@ -1257,212 +1036,36 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { * resp contains the information on the place to send it to. * Send the event off. */ - rev->buffer = disp->tcpmsg.buffer; - disp->tcpmsg.buffer.base = NULL; - disp->tcpmsg.buffer.length = 0; + rev->result = eresult; + resp->item_out = true; + if (region != NULL) { + disp->tcpbuffers++; + rev->region.base = isc_mem_get(disp->mgr->mctx, region->length); + rev->region.length = region->length; + memmove(rev->region.base, region->base, region->length); + isc_buffer_init(&rev->buffer, rev->region.base, + rev->region.length); + isc_buffer_add(&rev->buffer, rev->region.length); + } - disp->tcpbuffers++; - rev->result = ISC_R_SUCCESS; - rev->id = id; - rev->addr = tcpmsg->address; if (queue_response) { ISC_LIST_APPEND(resp->items, rev, ev_link); } else { ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, DNS_EVENT_DISPATCH, - resp->action, resp->arg, resp, NULL, NULL); + action, resp->arg, resp, NULL, NULL); request_log(disp, resp, LVL(90), "[b] Sent event %p buffer %p len %d to task %p", rev, rev->buffer.base, rev->buffer.length, resp->task); - resp->item_out = true; isc_task_send(resp->task, ISC_EVENT_PTR(&rev)); } -unlock: UNLOCK(&qid->lock); - /* - * Restart recv() to get the next packet. - */ -restart: - (void)startrecv(disp, NULL); - - isc_event_free(&ev_in); +next: + startrecv(disp, NULL); UNLOCK(&disp->lock); } -static void -recv_tcpmsg(isc_task_t *task, isc_event_t *ev_in) { - isc_socketevent_t *ev = (isc_socketevent_t *)ev_in; - tcpmsg_t *tcpmsg = ev_in->ev_arg; - isc_event_t *dev = &tcpmsg->event; - - UNUSED(task); - - tcpmsg->address = ev->address; - - if (ev->result != ISC_R_SUCCESS) { - tcpmsg->result = ev->result; - goto send_and_free; - } - - tcpmsg->result = ISC_R_SUCCESS; - isc_buffer_add(&tcpmsg->buffer, ev->n); - -send_and_free: - isc_task_send(tcpmsg->task, &dev); - tcpmsg->task = NULL; - isc_event_free(&ev_in); -} - -static void -recv_tcplen(isc_task_t *task, isc_event_t *ev_in) { - isc_socketevent_t *ev = (isc_socketevent_t *)ev_in; - tcpmsg_t *tcpmsg = ev_in->ev_arg; - isc_event_t *dev = &tcpmsg->event; - isc_region_t region; - isc_result_t result; - - tcpmsg->address = ev->address; - - if (ev->result != ISC_R_SUCCESS) { - tcpmsg->result = ev->result; - goto send_and_free; - } - - /* - * Success. - */ - tcpmsg->size = ntohs(tcpmsg->size); - if (tcpmsg->size == 0) { - tcpmsg->result = ISC_R_UNEXPECTEDEND; - goto send_and_free; - } - - region.base = isc_mem_get(tcpmsg->disp->mgr->mctx, tcpmsg->size); - region.length = tcpmsg->size; - if (region.base == NULL) { - tcpmsg->result = ISC_R_NOMEMORY; - goto send_and_free; - } - - isc_buffer_init(&tcpmsg->buffer, region.base, region.length); - result = isc_socket_recv(tcpmsg->disp->socket, ®ion, 0, task, - recv_tcpmsg, tcpmsg); - if (result != ISC_R_SUCCESS) { - tcpmsg->result = result; - goto send_and_free; - } - - isc_event_free(&ev_in); - return; - -send_and_free: - isc_task_send(tcpmsg->task, &dev); - tcpmsg->task = NULL; - isc_event_free(&ev_in); - return; -} - -static isc_result_t -tcp_readmessage(tcpmsg_t *tcpmsg, isc_task_t *task, isc_taskaction_t action, - void *arg) { - isc_result_t result; - isc_region_t region; - - REQUIRE(task != NULL); - REQUIRE(tcpmsg->task == NULL); /* not currently in use */ - - if (tcpmsg->buffer.base != NULL) { - isc_mem_put(tcpmsg->disp->mgr->mctx, tcpmsg->buffer.base, - tcpmsg->buffer.length); - tcpmsg->buffer.base = NULL; - tcpmsg->buffer.length = 0; - } - - tcpmsg->task = task; - tcpmsg->action = action; - tcpmsg->arg = arg; - tcpmsg->result = ISC_R_UNEXPECTED; /* unknown right now */ - - ISC_EVENT_INIT(&tcpmsg->event, sizeof(isc_event_t), 0, 0, - DNS_EVENT_TCPMSG, action, arg, tcpmsg, NULL, NULL); - - region.base = (unsigned char *)&tcpmsg->size; - region.length = 2; /* uint16_t */ - result = isc_socket_recv(tcpmsg->disp->socket, ®ion, 0, tcpmsg->task, - recv_tcplen, tcpmsg); - - if (result != ISC_R_SUCCESS) { - tcpmsg->task = NULL; - } - - return (result); -} - -/* - * disp must be locked. - */ -static isc_result_t -startrecv(dns_dispatch_t *disp, dispsocket_t *dispsock) { - isc_result_t res; - isc_region_t region; - isc_socket_t *sock = NULL; - isc_socketevent_t *sev = NULL; - - if (disp->shutting_down == 1) { - return (ISC_R_SUCCESS); - } - - if (dispsock == NULL) { - if (disp->socktype == isc_sockettype_udp || - disp->recv_pending != 0) { - return (ISC_R_SUCCESS); - } - sock = disp->socket; - } else { - sock = dispsock->socket; - } - - switch (disp->socktype) { - /* - * UDP reads are always maximal. - */ - case isc_sockettype_udp: - region.length = DNS_DISPATCH_UDPBUFSIZE; - region.base = allocate_udp_buffer(disp); - if (region.base == NULL) { - return (ISC_R_NOMEMORY); - } - sev = allocate_sevent(disp, sock, ISC_SOCKEVENT_RECVDONE, - udp_recv, dispsock); - res = isc_socket_recv2(sock, ®ion, 1, dispsock->task, sev, - 0); - if (res != ISC_R_SUCCESS) { - free_buffer(disp, region.base, region.length); - return (res); - } - break; - - case isc_sockettype_tcp: - res = tcp_readmessage(&disp->tcpmsg, disp->task[0], tcp_recv, - disp); - if (res != ISC_R_SUCCESS) { - disp->shutdown_why = res; - disp->shutting_down = 1; - do_cancel(disp); - return (ISC_R_SUCCESS); /* recover by cancel */ - } - INSIST(disp->recv_pending == 0); - disp->recv_pending = 1; - break; - default: - INSIST(0); - ISC_UNREACHABLE(); - } - - return (ISC_R_SUCCESS); -} - /* * Mgr must be locked when calling this function. */ @@ -1520,48 +1123,12 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) { isc_mem_put(mgr->mctx, mgr->v6ports, mgr->nv6ports * sizeof(in_port_t)); } + + isc_nm_detach(&mgr->nm); + isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(dns_dispatchmgr_t)); } -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 *sock = NULL; - isc_result_t result; - - sock = *sockp; - if (sock != NULL) { - result = isc_socket_open(sock); - if (result != ISC_R_SUCCESS) { - return (result); - } - } else { - result = isc_socket_create(mgr, isc_sockaddr_pf(local), - isc_sockettype_udp, &sock); - if (result != ISC_R_SUCCESS) { - return (result); - } - } - - isc_socket_setname(sock, "dispatcher", NULL); - -#ifndef ISC_ALLOW_MAPPED - isc_socket_ipv6only(sock, true); -#endif /* ifndef ISC_ALLOW_MAPPED */ - result = isc_socket_bind(sock, local, options); - if (result != ISC_R_SUCCESS) { - if (*sockp == NULL) { - isc_socket_detach(&sock); - } else { - isc_socket_close(sock); - } - return (result); - } - - *sockp = sock; - return (ISC_R_SUCCESS); -} - /*% * Create a temporary port list to set the initial default set of dispatch * ports: [1024, 65535]. This is almost meaningless as the application will @@ -1626,7 +1193,8 @@ setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset, */ isc_result_t -dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp) { +dns_dispatchmgr_create(isc_mem_t *mctx, isc_nm_t *nm, + dns_dispatchmgr_t **mgrp) { dns_dispatchmgr_t *mgr = NULL; isc_portset_t *v4portset = NULL; isc_portset_t *v6portset = NULL; @@ -1635,15 +1203,16 @@ dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp) { REQUIRE(mgrp != NULL && *mgrp == NULL); mgr = isc_mem_get(mctx, sizeof(dns_dispatchmgr_t)); - *mgr = (dns_dispatchmgr_t){ 0 }; + *mgr = (dns_dispatchmgr_t){ .magic = 0 }; + + isc_refcount_init(&mgr->irefs, 0); isc_mem_attach(mctx, &mgr->mctx); + isc_nm_attach(nm, &mgr->nm); isc_mutex_init(&mgr->lock); isc_mutex_init(&mgr->buffer_lock); - isc_refcount_init(&mgr->irefs, 0); - ISC_LIST_INIT(mgr->list); create_default_portset(mctx, &v4portset); @@ -1728,16 +1297,11 @@ qid_allocate(dns_dispatchmgr_t *mgr, dns_qid_t **qidp) { qid->qid_table = isc_mem_get(mgr->mctx, DNS_QID_BUCKETS * sizeof(dns_displist_t)); - qid->sock_table = isc_mem_get( - mgr->mctx, DNS_QID_BUCKETS * sizeof(dispsocketlist_t)); - - isc_mutex_init(&qid->lock); - for (i = 0; i < qid->qid_nbuckets; i++) { ISC_LIST_INIT(qid->qid_table[i]); - ISC_LIST_INIT(qid->sock_table[i]); } + isc_mutex_init(&qid->lock); qid->magic = QID_MAGIC; *qidp = qid; } @@ -1755,8 +1319,6 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) { qid->magic = 0; isc_mem_put(mctx, qid->qid_table, qid->qid_nbuckets * sizeof(dns_displist_t)); - isc_mem_put(mctx, qid->sock_table, - qid->qid_nbuckets * sizeof(dispsocketlist_t)); isc_mutex_destroy(&qid->lock); isc_mem_put(mctx, qid, sizeof(*qid)); } @@ -1765,7 +1327,7 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) { * Allocate and set important limits. */ static void -dispatch_allocate(dns_dispatchmgr_t *mgr, isc_sockettype_t type, int pf, +dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type, int pf, unsigned int attributes, dns_dispatch_t **dispp) { dns_dispatch_t *disp = NULL; @@ -1789,10 +1351,10 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, isc_sockettype_t type, int pf, ISC_LIST_INIT(disp->inactivesockets); switch (type) { - case isc_sockettype_tcp: + case isc_socktype_tcp: disp->attributes |= DNS_DISPATCHATTR_TCP; break; - case isc_sockettype_udp: + case isc_socktype_udp: disp->attributes |= DNS_DISPATCHATTR_UDP; break; default: @@ -1842,25 +1404,18 @@ dispatch_free(dns_dispatch_t **dispp) { mgr = disp->mgr; REQUIRE(VALID_DISPATCHMGR(mgr)); - if (disp->tcpmsg_valid) { - if (disp->tcpmsg.buffer.base != NULL) { - isc_mem_put(disp->mgr->mctx, disp->tcpmsg.buffer.base, - disp->tcpmsg.buffer.length); - disp->tcpmsg.buffer.base = NULL; - disp->tcpmsg.buffer.length = 0; - } - disp->tcpmsg_valid = 0; - } - - INSIST(disp->tcpbuffers == 0); INSIST(disp->requests == 0); INSIST(disp->recv_pending == 0); INSIST(ISC_LIST_EMPTY(disp->activesockets)); INSIST(ISC_LIST_EMPTY(disp->inactivesockets)); isc_refcount_decrement(&mgr->irefs); - isc_mem_put(mgr->mctx, disp->failsafe_ev, sizeof(*disp->failsafe_ev)); - disp->failsafe_ev = NULL; + + if (disp->failsafe_ev != NULL) { + isc_mem_put(mgr->mctx, disp->failsafe_ev, + sizeof(*disp->failsafe_ev)); + disp->failsafe_ev = NULL; + } disp->mgr = NULL; isc_mutex_destroy(&disp->lock); @@ -1870,74 +1425,43 @@ dispatch_free(dns_dispatch_t **dispp) { } isc_result_t -dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, - isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, +dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_taskmgr_t *taskmgr, + const isc_sockaddr_t *localaddr, const isc_sockaddr_t *destaddr, unsigned int attributes, isc_dscp_t dscp, dns_dispatch_t **dispp) { isc_result_t result; dns_dispatch_t *disp = NULL; - isc_sockaddr_t src; int pf; REQUIRE(VALID_DISPATCHMGR(mgr)); - REQUIRE(sockmgr != NULL); REQUIRE(destaddr != NULL); + UNUSED(dscp); + LOCK(&mgr->lock); pf = isc_sockaddr_pf(destaddr); - dispatch_allocate(mgr, isc_sockettype_tcp, pf, attributes, &disp); + dispatch_allocate(mgr, isc_socktype_tcp, pf, attributes, &disp); disp->peer = *destaddr; if (localaddr != NULL) { disp->local = *localaddr; } else { - switch (pf) { - case AF_INET: - isc_sockaddr_any(&disp->local); - break; - case AF_INET6: - isc_sockaddr_any6(&disp->local); - break; - } + isc_sockaddr_anyofpf(&disp->local, pf); + isc_sockaddr_setport(&disp->local, 0); } - disp->ntasks = 1; - disp->task[0] = NULL; - result = isc_task_create(taskmgr, 50, &disp->task[0]); + result = isc_task_create(taskmgr, 50, &disp->task); if (result != ISC_R_SUCCESS) { goto cleanup; } - result = isc_socket_create(sockmgr, isc_sockaddr_pf(destaddr), - isc_sockettype_tcp, &disp->socket); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - - if (localaddr == NULL) { - isc_sockaddr_anyofpf(&src, pf); - } else { - src = *localaddr; - isc_sockaddr_setport(&src, 0); - } - - result = isc_socket_bind(disp->socket, &src, 0); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - - isc_socket_dscp(disp->socket, dscp); - disp->ctlevent = isc_event_allocate(mgr->mctx, disp, DNS_EVENT_DISPATCHCONTROL, destroy_disp, disp, sizeof(isc_event_t)); - isc_task_setname(disp->task[0], "tcpdispatch", disp); - - disp->tcpmsg = (tcpmsg_t){ .disp = disp, .result = ISC_R_UNEXPECTED }; - disp->tcpmsg_valid = 1; + isc_task_setname(disp->task, "tcpdispatch", disp); /* * Append it to the dispatcher list. @@ -1949,14 +1473,13 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, mgr_log(mgr, LVL(90), "dns_dispatch_createtcp: created TCP dispatch %p", disp); - dispatch_log(disp, LVL(90), "created task %p", disp->task[0]); + dispatch_log(disp, LVL(90), "created task %p", disp->task); } *dispp = disp; return (ISC_R_SUCCESS); cleanup: - isc_socket_detach(&disp->socket); dispatch_free(&disp); UNLOCK(&mgr->lock); @@ -1971,7 +1494,6 @@ 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; - isc_result_t result; isc_sockaddr_t peeraddr; isc_sockaddr_t sockname; unsigned int attributes, mask; @@ -1995,14 +1517,9 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, (localaddr == NULL || isc_sockaddr_eqaddr(localaddr, &disp->local))) { - result = isc_socket_getsockname(disp->socket, - &sockname); - if (result == ISC_R_SUCCESS) { - result = isc_socket_getpeername(disp->socket, - &peeraddr); - } - if (result == ISC_R_SUCCESS && - isc_sockaddr_equal(destaddr, &peeraddr) && + sockname = isc_nmhandle_localaddr(disp->handle); + peeraddr = isc_nmhandle_peeraddr(disp->handle); + if (isc_sockaddr_equal(destaddr, &peeraddr) && (localaddr == NULL || isc_sockaddr_eqaddr(localaddr, &sockname))) { @@ -2049,21 +1566,19 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, } isc_result_t -dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, - isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, - unsigned int attributes, dns_dispatch_t **dispp) { +dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_taskmgr_t *taskmgr, + const isc_sockaddr_t *localaddr, unsigned int attributes, + dns_dispatch_t **dispp) { isc_result_t result; dns_dispatch_t *disp = NULL; REQUIRE(VALID_DISPATCHMGR(mgr)); - REQUIRE(sockmgr != NULL); REQUIRE(localaddr != NULL); REQUIRE(taskmgr != NULL); REQUIRE(dispp != NULL && *dispp == NULL); LOCK(&mgr->lock); - result = dispatch_createudp(mgr, sockmgr, taskmgr, localaddr, - attributes, &disp); + result = dispatch_createudp(mgr, taskmgr, localaddr, attributes, &disp); if (result == ISC_R_SUCCESS) { *dispp = disp; } @@ -2073,32 +1588,25 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, } static isc_result_t -dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, - isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, - unsigned int attributes, dns_dispatch_t **dispp) { +dispatch_createudp(dns_dispatchmgr_t *mgr, isc_taskmgr_t *taskmgr, + const isc_sockaddr_t *localaddr, unsigned int attributes, + dns_dispatch_t **dispp) { isc_result_t result = ISC_R_SUCCESS; dns_dispatch_t *disp = NULL; - isc_socket_t *sock = NULL; isc_sockaddr_t sa_any; - int pf, i = 0; + int pf; pf = isc_sockaddr_pf(localaddr); - dispatch_allocate(mgr, isc_sockettype_udp, pf, attributes, &disp); + dispatch_allocate(mgr, isc_socktype_udp, pf, attributes, &disp); /* - * For dispatches with a specified source address, we open a - * socket to make sure that address is available on the system, - * but we don't keep it open; sockets used for sending requests - * will be created later on demand. + * Check whether this address/port is available locally. */ isc_sockaddr_anyofpf(&sa_any, pf); if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) { - result = open_socket(sockmgr, localaddr, 0, &sock); - if (sock != NULL) { - isc_socket_detach(&sock); - } + result = isc_nm_checkaddr(localaddr, isc_socktype_udp); if (result != ISC_R_SUCCESS) { - goto deallocate_dispatch; + goto cleanup; } } @@ -2112,21 +1620,10 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, addrbuf); } - disp->socket = sock; disp->local = *localaddr; - disp->ntasks = MAX_INTERNAL_TASKS; - - for (i = 0; i < disp->ntasks; i++) { - disp->task[i] = NULL; - result = isc_task_create(taskmgr, 0, &disp->task[i]); - if (result != ISC_R_SUCCESS) { - while (--i >= 0) { - isc_task_shutdown(disp->task[i]); - isc_task_detach(&disp->task[i]); - } - goto kill_socket; - } - isc_task_setname(disp->task[i], "udpdispatch", disp); + result = isc_task_create(taskmgr, 0, &disp->task); + if (result != ISC_R_SUCCESS) { + goto cleanup; } disp->ctlevent = @@ -2143,10 +1640,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, ISC_LIST_APPEND(mgr->list, disp, link); mgr_log(mgr, LVL(90), "created UDP dispatcher %p", disp); - dispatch_log(disp, LVL(90), "created task %p", disp->task[0]); /* XXX */ - if (disp->socket != NULL) { - dispatch_log(disp, LVL(90), "created socket %p", disp->socket); - } + dispatch_log(disp, LVL(90), "created task %p", disp->task); *dispp = disp; @@ -2155,11 +1649,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, /* * Error returns. */ -kill_socket: - if (disp->socket != NULL) { - isc_socket_detach(&disp->socket); - } -deallocate_dispatch: +cleanup: dispatch_free(&disp); return (result); @@ -2178,60 +1668,67 @@ void dns_dispatch_detach(dns_dispatch_t **dispp) { dns_dispatch_t *disp = NULL; dispsocket_t *dispsock = NULL; - bool killit; + bool killit = false; REQUIRE(dispp != NULL && VALID_DISPATCH(*dispp)); disp = *dispp; *dispp = NULL; - LOCK(&disp->lock); if (isc_refcount_decrement(&disp->refcount) == 1) { - if (disp->recv_pending > 0) { - isc_socket_cancel(disp->socket, disp->task[0], - ISC_SOCKCANCEL_RECV); + LOCK(&disp->lock); + if (disp->recv_pending != 0 && disp->handle != NULL) { + isc_nm_cancelread(disp->handle); + } + if (disp->handle != NULL) { + isc_nmhandle_detach(&disp->handle); } for (dispsock = ISC_LIST_HEAD(disp->activesockets); dispsock != NULL; dispsock = ISC_LIST_NEXT(dispsock, link)) { - isc_socket_cancel(dispsock->socket, dispsock->task, - ISC_SOCKCANCEL_RECV); + if (dispsock->handle != NULL) { + isc_nmhandle_detach(&dispsock->handle); + } } disp->shutting_down = 1; + do_cancel(disp); + + killit = destroy_disp_ok(disp); + UNLOCK(&disp->lock); } dispatch_log(disp, LVL(90), "detach: refcount %" PRIuFAST32, isc_refcount_current(&disp->refcount)); - killit = destroy_disp_ok(disp); - UNLOCK(&disp->lock); if (killit) { - isc_task_send(disp->task[0], &disp->ctlevent); + isc_task_send(disp->task, &disp->ctlevent); } } isc_result_t dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, - const isc_sockaddr_t *dest, isc_task_t *task, - isc_taskaction_t action, void *arg, - dns_messageid_t *idp, dns_dispentry_t **resp, - isc_socketmgr_t *sockmgr) { + unsigned int timeout, const isc_sockaddr_t *dest, + isc_task_t *task, isc_nm_cb_t connected, + isc_nm_cb_t sent, isc_taskaction_t action, + isc_taskaction_t timeout_action, void *arg, + dns_messageid_t *idp, dns_dispentry_t **resp) { + isc_result_t result; dns_dispentry_t *res = NULL; - unsigned int bucket; + dispsocket_t *dispsocket = NULL; + dns_qid_t *qid = NULL; in_port_t localport = 0; dns_messageid_t id; - int i = 0; + unsigned int bucket; bool ok = false; - dns_qid_t *qid = NULL; - dispsocket_t *dispsocket = NULL; - isc_result_t result; + int i = 0; REQUIRE(VALID_DISPATCH(disp)); REQUIRE(task != NULL); REQUIRE(dest != NULL); REQUIRE(resp != NULL && *resp == NULL); REQUIRE(idp != NULL); - REQUIRE(disp->socktype == isc_sockettype_tcp || sockmgr != NULL); + REQUIRE(disp->socktype == isc_socktype_tcp || + disp->socktype == isc_socktype_udp); LOCK(&disp->lock); @@ -2247,7 +1744,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, qid = disp->mgr->qid; - if (disp->socktype == isc_sockettype_udp && + if (disp->socktype == isc_socktype_udp && disp->nsockets > DNS_DISPATCH_SOCKSQUOTA) { dispsocket_t *oldestsocket = NULL; @@ -2264,7 +1761,6 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, rev = allocate_devent(oldestresp->disp); 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); @@ -2281,12 +1777,11 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, ISC_LIST_APPEND(disp->activesockets, oldestsocket, link); } - if (disp->socktype == isc_sockettype_udp) { + if (disp->socktype == isc_socktype_udp) { /* * Get a separate UDP socket with a random port number. */ - result = get_dispsocket(disp, dest, sockmgr, &dispsocket, - &localport); + result = get_dispsocket(disp, dest, &dispsocket, &localport); if (result != ISC_R_SUCCESS) { UNLOCK(&disp->lock); inc_stats(disp->mgr, dns_resstatscounter_dispsockfail); @@ -2326,20 +1821,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); - *res = (dns_dispentry_t){ .disp = disp, - .id = id, + + *res = (dns_dispentry_t){ .id = id, .port = localport, .bucket = bucket, - .host = *dest, + .timeout = timeout, + .peer = *dest, + .connected = connected, + .sent = sent, .action = action, + .timeout_action = timeout_action, .arg = arg, .dispsocket = dispsocket }; + + dns_dispatch_attach(disp, &res->disp); isc_task_attach(task, &res->task); + ISC_LIST_INIT(res->items); ISC_LINK_INIT(res, link); res->magic = RESPONSE_MAGIC; - isc_refcount_increment(&disp->refcount); disp->requests++; if (dispsocket != NULL) { @@ -2350,40 +1851,11 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, ISC_LIST_APPEND(qid->qid_table[bucket], res, link); UNLOCK(&qid->lock); - inc_stats(disp->mgr, (disp->socktype == isc_sockettype_udp) - ? dns_resstatscounter_disprequdp - : dns_resstatscounter_dispreqtcp); - request_log(disp, res, LVL(90), "attached to task %p", res->task); - if (((disp->attributes & DNS_DISPATCHATTR_UDP) != 0) || - ((disp->attributes & DNS_DISPATCHATTR_CONNECTED) != 0)) - { - result = startrecv(disp, dispsocket); - if (result != ISC_R_SUCCESS) { - LOCK(&qid->lock); - ISC_LIST_UNLINK(qid->qid_table[bucket], res, link); - UNLOCK(&qid->lock); - - if (dispsocket != NULL) { - destroy_dispsocket(disp, &dispsocket); - } - - isc_refcount_decrement(&disp->refcount); - disp->requests--; - - dec_stats(disp->mgr, - (disp->socktype == isc_sockettype_udp) - ? dns_resstatscounter_disprequdp - : dns_resstatscounter_dispreqtcp); - - UNLOCK(&disp->lock); - isc_task_detach(&res->task); - isc_refcount_decrement(&disp->mgr->irefs); - isc_mem_put(disp->mgr->mctx, res, sizeof(*res)); - return (result); - } - } + inc_stats(disp->mgr, (disp->socktype == isc_socktype_udp) + ? dns_resstatscounter_disprequdp + : dns_resstatscounter_dispreqtcp); if (dispsocket != NULL) { ISC_LIST_APPEND(disp->activesockets, dispsocket, link); @@ -2391,7 +1863,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, UNLOCK(&disp->lock); - INSIST(disp->socktype == isc_sockettype_tcp || res->dispsocket != NULL); + INSIST(disp->socktype == isc_socktype_tcp || res->dispsocket != NULL); *idp = id; *resp = res; @@ -2399,20 +1871,6 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, return (ISC_R_SUCCESS); } -void -dns_dispatch_starttcp(dns_dispatch_t *disp) { - REQUIRE(VALID_DISPATCH(disp)); - - dispatch_log(disp, LVL(90), "starttcp %p", disp->task[0]); - - LOCK(&disp->lock); - if ((disp->attributes & DNS_DISPATCHATTR_CONNECTED) == 0) { - disp->attributes |= DNS_DISPATCHATTR_CONNECTED; - (void)startrecv(disp, NULL); - } - UNLOCK(&disp->lock); -} - isc_result_t dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent) { dns_dispatch_t *disp = NULL; @@ -2432,15 +1890,13 @@ dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent) { REQUIRE(resp->item_out); resp->item_out = false; - if (ev->buffer.base != NULL) { - free_buffer(disp, ev->buffer.base, ev->buffer.length); - } free_devent(disp, ev); if (disp->shutting_down == 1) { UNLOCK(&disp->lock); return (ISC_R_SHUTTINGDOWN); } + ev = ISC_LIST_HEAD(resp->items); if (ev != NULL) { ISC_LIST_UNLINK(resp->items, ev, ev_link); @@ -2452,7 +1908,11 @@ dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent) { resp->item_out = true; isc_task_send(resp->task, ISC_EVENT_PTR(&ev)); } + + startrecv(disp, resp->dispsocket); + UNLOCK(&disp->lock); + return (ISC_R_SUCCESS); } @@ -2462,11 +1922,8 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, 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 = NULL; @@ -2477,7 +1934,9 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, *resp = NULL; disp = res->disp; + res->disp = NULL; REQUIRE(VALID_DISPATCH(disp)); + mgr = disp->mgr; REQUIRE(VALID_DISPATCHMGR(mgr)); qid = mgr->qid; @@ -2491,26 +1950,16 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, } LOCK(&disp->lock); - INSIST(disp->requests > 0); disp->requests--; - dec_stats(disp->mgr, (disp->socktype == isc_sockettype_udp) + dec_stats(disp->mgr, (disp->socktype == isc_socktype_udp) ? dns_resstatscounter_disprequdp : dns_resstatscounter_dispreqtcp); - if (isc_refcount_decrement(&disp->refcount) == 1) { - if (disp->recv_pending > 0) { - isc_socket_cancel(disp->socket, disp->task[0], - ISC_SOCKCANCEL_RECV); - } - for (dispsock = ISC_LIST_HEAD(disp->activesockets); - dispsock != NULL; dispsock = ISC_LIST_NEXT(dispsock, link)) - { - isc_socket_cancel(dispsock->socket, dispsock->task, - ISC_SOCKCANCEL_RECV); - } - disp->shutting_down = 1; + if (res->dispsocket != NULL) { + deactivate_dispsocket(disp, res->dispsocket); } + UNLOCK(&disp->lock); bucket = res->bucket; @@ -2519,6 +1968,8 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, UNLOCK(&qid->lock); if (ev == NULL && res->item_out) { + unsigned int n; + /* * We've posted our event, but the caller hasn't gotten it * yet. Take it back. @@ -2536,88 +1987,130 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, if (ev != NULL) { REQUIRE(res->item_out); res->item_out = false; - if (ev->buffer.base != NULL) { - free_buffer(disp, ev->buffer.base, ev->buffer.length); - } free_devent(disp, ev); } request_log(disp, res, LVL(90), "detaching from task %p", res->task); isc_task_detach(&res->task); - if (res->dispsocket != NULL) { - isc_socket_cancel(res->dispsocket->socket, - res->dispsocket->task, ISC_SOCKCANCEL_RECV); - res->dispsocket->resp = NULL; - } - /* * Free any buffered responses as well */ ev = ISC_LIST_HEAD(res->items); while (ev != NULL) { ISC_LIST_UNLINK(res->items, ev, ev_link); - if (ev->buffer.base != NULL) { - free_buffer(disp, ev->buffer.base, ev->buffer.length); - } free_devent(disp, ev); ev = ISC_LIST_HEAD(res->items); } res->magic = 0; isc_refcount_decrement(&disp->mgr->irefs); isc_mem_put(disp->mgr->mctx, res, sizeof(*res)); - if (disp->shutting_down == 1) { - do_cancel(disp); - } else { - (void)startrecv(disp, NULL); - } - killit = destroy_disp_ok(disp); - UNLOCK(&disp->lock); - if (killit) { - isc_task_send(disp->task[0], &disp->ctlevent); - } + dns_dispatch_detach(&disp); } -isc_result_t -dns_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp, - isc_task_t *task, isc_taskaction_t action, void *arg) { - isc_socket_t *sock = NULL; - isc_sockaddr_t *address = NULL; +/* + * disp must be locked. + */ +static void +startrecv(dns_dispatch_t *disp, dispsocket_t *dispsocket) { + isc_nmhandle_t *handle = NULL; - if (resp != NULL) { - REQUIRE(VALID_RESPONSE(resp)); - sock = resp->dispsocket->socket; - address = &resp->host; - } else if (disp != NULL) { - REQUIRE(VALID_DISPATCH(disp)); - sock = disp->socket; - address = &disp->peer; + if (disp->shutting_down == 1) { + return; + } + + if (dispsocket == NULL) { + if (disp->socktype == isc_socktype_udp || + disp->recv_pending != 0) { + return; + } + isc_nmhandle_attach(disp->handle, &handle); } else { + handle = dispsocket->handle; + } + + switch (disp->socktype) { + case isc_socktype_udp: + isc_nm_read(handle, udp_recv, dispsocket); + break; + + case isc_socktype_tcp: + isc_nm_read(handle, tcp_recv, disp); + INSIST(disp->recv_pending == 0); + disp->recv_pending = 1; + break; + + default: INSIST(0); ISC_UNREACHABLE(); } +} - return (isc_socket_connect(sock, address, task, action, arg)); +static void +disp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { + dns_dispentry_t *resp = (dns_dispentry_t *)arg; + dns_dispatch_t *disp = resp->disp; + dispsocket_t *dispsocket = NULL; + + if (eresult == ISC_R_SUCCESS) { + if (disp->socktype == isc_socktype_udp) { + dispsocket = resp->dispsocket; + isc_nmhandle_attach(handle, &dispsocket->handle); + } else if (disp->handle == NULL) { + disp->attributes |= DNS_DISPATCHATTR_CONNECTED; + isc_nmhandle_attach(handle, &disp->handle); + } + + startrecv(disp, dispsocket); + } + + if (resp->connected != NULL) { + resp->connected(handle, eresult, resp->arg); + } } isc_result_t -dns_dispatch_send(dns_dispentry_t *resp, bool tcp, isc_task_t *task, - isc_socketevent_t *sendevent, isc_region_t *r, - const isc_sockaddr_t *address, isc_dscp_t dscp, - isc_taskaction_t action, void *arg) { - isc_result_t result; - isc_socket_t *sock = NULL; +dns_dispatch_connect(dns_dispentry_t *resp) { + dns_dispatch_t *disp = NULL; REQUIRE(VALID_RESPONSE(resp)); - REQUIRE(sendevent != NULL); - memset(sendevent, 0, sizeof(isc_socketevent_t)); - ISC_EVENT_INIT(sendevent, sizeof(isc_socketevent_t), 0, NULL, - ISC_SOCKEVENT_SENDDONE, action, arg, NULL, NULL, NULL); + disp = resp->disp; - sock = getentrysocket(resp); + switch (disp->socktype) { + case isc_socktype_tcp: + if (disp->handle != NULL) { + break; + } + isc_nm_tcpdnsconnect(disp->mgr->nm, &disp->local, &disp->peer, + disp_connected, resp, resp->timeout, 0); + break; + case isc_socktype_udp: + isc_nm_udpconnect(disp->mgr->nm, &resp->dispsocket->local, + &resp->dispsocket->peer, disp_connected, resp, + resp->timeout, 0); + break; + default: + return (ISC_R_NOTIMPLEMENTED); + } + + return (ISC_R_SUCCESS); +} + +void +dns_dispatch_send(dns_dispentry_t *resp, isc_region_t *r, isc_dscp_t dscp) { + isc_nmhandle_t *handle = NULL; + + REQUIRE(VALID_RESPONSE(resp)); + + UNUSED(dscp); + + handle = getentryhandle(resp); + +#if 0 + /* XXX: no DSCP support */ if (dscp == -1) { sendevent->attributes &= ~ISC_SOCKEVENTATTR_DSCP; sendevent->dscp = 0; @@ -2628,43 +2121,39 @@ dns_dispatch_send(dns_dispentry_t *resp, bool tcp, isc_task_t *task, isc_socket_dscp(sock, dscp); } } +#endif - if (tcp) { - address = NULL; - } - - result = isc_socket_sendto2(sock, r, task, address, NULL, sendevent, 0); - return (result); + isc_nm_send(handle, r, resp->sent, resp->arg); } void dns_dispatch_cancel(dns_dispatch_t *disp, dns_dispentry_t *resp, bool sending, bool connecting) { - isc_socket_t *sock = NULL; + isc_nmhandle_t *handle = NULL; REQUIRE(disp != NULL || resp != NULL); if (resp != NULL) { REQUIRE(VALID_RESPONSE(resp)); - sock = getentrysocket(resp); + handle = getentryhandle(resp); } else if (disp != NULL) { REQUIRE(VALID_DISPATCH(disp)); - sock = getsocket(disp); + handle = gethandle(disp); } else { INSIST(0); ISC_UNREACHABLE(); } - if (sock == NULL) { + if (handle == NULL) { return; } if (connecting) { - isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_CONNECT); + // isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_CONNECT); } if (sending) { - isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_SEND); + // isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_SEND); } } @@ -2703,6 +2192,7 @@ do_cancel(dns_dispatch_t *disp) { * Send the shutdown failsafe event to this resp. */ ev = disp->failsafe_ev; + disp->failsafe_ev = NULL; ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, DNS_EVENT_DISPATCH, resp->action, resp->arg, resp, NULL, NULL); ev->result = disp->shutdown_why; @@ -2717,21 +2207,21 @@ unlock: UNLOCK(&qid->lock); } -static isc_socket_t * -getsocket(dns_dispatch_t *disp) { +static isc_nmhandle_t * +gethandle(dns_dispatch_t *disp) { REQUIRE(VALID_DISPATCH(disp)); - return (disp->socket); + return (disp->handle); } -static isc_socket_t * -getentrysocket(dns_dispentry_t *resp) { +static isc_nmhandle_t * +getentryhandle(dns_dispentry_t *resp) { REQUIRE(VALID_RESPONSE(resp)); - if (resp->disp->socktype == isc_sockettype_tcp) { - return (resp->disp->socket); + if (resp->disp->socktype == isc_socktype_tcp) { + return (resp->disp->handle); } else if (resp->dispsocket != NULL) { - return (resp->dispsocket->socket); + return (resp->dispsocket->handle); } else { return (NULL); } @@ -2742,7 +2232,7 @@ dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp) { REQUIRE(VALID_DISPATCH(disp)); REQUIRE(addrp != NULL); - if (disp->socktype == isc_sockettype_udp) { + if (disp->socktype == isc_socktype_udp) { *addrp = disp->local; return (ISC_R_SUCCESS); } @@ -2754,13 +2244,14 @@ dns_dispentry_getlocaladdress(dns_dispentry_t *resp, isc_sockaddr_t *addrp) { REQUIRE(VALID_RESPONSE(resp)); REQUIRE(addrp != NULL); - if (resp->disp->socktype == isc_sockettype_tcp) { - return (isc_socket_getsockname(resp->disp->socket, addrp)); + if (resp->disp->socktype == isc_socktype_tcp) { + *addrp = resp->disp->local; + return (ISC_R_SUCCESS); } - if (resp->dispsocket != NULL) { - return (isc_socket_getsockname(resp->dispsocket->socket, - addrp)); + if (resp->dispsocket != NULL && resp->dispsocket->handle != NULL) { + *addrp = isc_nmhandle_localaddr(resp->dispsocket->handle); + return (ISC_R_SUCCESS); } return (ISC_R_NOTIMPLEMENTED); @@ -2810,9 +2301,9 @@ dns_dispatchset_get(dns_dispatchset_t *dset) { } isc_result_t -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) { +dns_dispatchset_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, + dns_dispatch_t *source, dns_dispatchset_t **dsetp, + int n) { isc_result_t result; dns_dispatchset_t *dset = NULL; dns_dispatchmgr_t *mgr = NULL; @@ -2839,8 +2330,8 @@ dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr, LOCK(&mgr->lock); for (i = 1; i < n; i++) { dset->dispatches[i] = NULL; - result = dispatch_createudp(mgr, sockmgr, taskmgr, - &source->local, source->attributes, + result = dispatch_createudp(mgr, taskmgr, &source->local, + source->attributes, &dset->dispatches[i]); if (result != ISC_R_SUCCESS) { goto fail; diff --git a/lib/dns/include/dns/client.h b/lib/dns/include/dns/client.h index d8fcfd3c9e..9c3114dbd0 100644 --- a/lib/dns/include/dns/client.h +++ b/lib/dns/include/dns/client.h @@ -89,9 +89,8 @@ typedef struct dns_clientresevent { isc_result_t dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, - isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, - unsigned int options, dns_client_t **clientp, - const isc_sockaddr_t *localaddr4, + isc_nm_t *nm, isc_timermgr_t *timermgr, unsigned int options, + dns_client_t **clientp, const isc_sockaddr_t *localaddr4, const isc_sockaddr_t *localaddr6); /*%< * Create a DNS client object with minimal internal resources, such as @@ -113,7 +112,7 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, * *\li 'taskmgr' is a valid task manager. * - *\li 'socketmgr' is a valid socket manager. + *\li 'nm' is a valid network manager. * *\li 'timermgr' is a valid timer manager. * diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index 0ff11844ff..aea71f9bd5 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -9,6 +9,8 @@ * information regarding copyright ownership. */ +#include + #ifndef DNS_DISPATCH_H #define DNS_DISPATCH_H 1 @@ -50,6 +52,7 @@ #include #include #include +#include #include #include @@ -76,12 +79,9 @@ ISC_LANG_BEGINDECLS struct dns_dispatchevent { ISC_EVENT_COMMON(dns_dispatchevent_t); /*%< standard event common */ - isc_result_t result; /*%< result code */ - int32_t id; /*%< message id */ - isc_sockaddr_t addr; /*%< address recv'd from */ - struct in6_pktinfo pktinfo; /*%< reply info for v6 */ - isc_buffer_t buffer; /*%< data buffer */ - uint32_t attributes; /*%< mirrored from socket.h */ + isc_result_t result; /*%< result code */ + isc_region_t region; /*%< data region */ + isc_buffer_t buffer; /*%< data buffer */ }; /*% @@ -128,14 +128,16 @@ struct dns_dispatchset { #define DNS_DISPATCHOPT_FIXEDID 0x00000001U isc_result_t -dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp); +dns_dispatchmgr_create(isc_mem_t *mctx, isc_nm_t *nm, dns_dispatchmgr_t **mgrp); /*%< * Creates a new dispatchmgr object, and sets the available ports * to the default range (1024-65535). * * Requires: - *\li "mctx" be a valid memory context. + *\li 'mctx' be a valid memory context. * + *\li 'nm' is a valid network manager. + *\li mgrp != NULL && *mgrp == NULL * * Returns: @@ -205,9 +207,9 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats); */ isc_result_t -dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, - isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, - unsigned int attributes, dns_dispatch_t **dispp); +dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_taskmgr_t *taskmgr, + const isc_sockaddr_t *localaddr, unsigned int attributes, + dns_dispatch_t **dispp); /*%< * Create a new UDP dispatch. * @@ -223,8 +225,8 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, */ isc_result_t -dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, - isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, +dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_taskmgr_t *taskmgr, + const isc_sockaddr_t *localaddr, const isc_sockaddr_t *destaddr, unsigned int attributes, isc_dscp_t dscp, dns_dispatch_t **dispp); /*%< @@ -265,15 +267,13 @@ dns_dispatch_detach(dns_dispatch_t **dispp); */ isc_result_t -dns_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp, - isc_task_t *task, isc_taskaction_t action, void *arg); +dns_dispatch_connect(dns_dispentry_t *resp); /*%< - * Connect the UDP socket in 'resp' or the TCP socket in 'disp' to the - * remote server, and run the specified callback. + * Connect to the remote server configured in 'resp' and run the + * connect callback that was set up via dns_dispatch_addresponse(). * * Requires: - *\li 'resp' is NULL and 'disp' is valid, or - *\li 'disp' is NULL and 'resp' is valid. + *\li 'resp' is valid. */ void @@ -288,29 +288,16 @@ dns_dispatch_cancel(dns_dispatch_t *disp, dns_dispentry_t *resp, bool sending, *\li 'disp' is NULL and 'resp' is valid. */ -isc_result_t -dns_dispatch_send(dns_dispentry_t *resp, bool tcp, isc_task_t *task, - isc_socketevent_t *sendevent, isc_region_t *r, - const isc_sockaddr_t *address, isc_dscp_t dscp, - isc_taskaction_t action, void *arg); +void +dns_dispatch_send(dns_dispentry_t *resp, isc_region_t *r, isc_dscp_t dscp); /*%< * Send region 'r' using the socket in 'resp', then run the specified - * callback. 'sendevent' must point to enough memory to hold an - * isc_socketevent; it will be overwritten. + * callback. * * Requires: *\li 'resp' is valid. */ -void -dns_dispatch_starttcp(dns_dispatch_t *disp); -/*%< - * Start processing of a TCP dispatch once the socket connects. - * - * Requires: - *\li 'disp' is valid. - */ - isc_result_t dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, const isc_sockaddr_t *localaddr, bool *connected, @@ -322,18 +309,29 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, isc_result_t dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, - const isc_sockaddr_t *dest, isc_task_t *task, - isc_taskaction_t action, void *arg, uint16_t *idp, - dns_dispentry_t **resp, isc_socketmgr_t *sockmgr); + unsigned int timeout, const isc_sockaddr_t *dest, + isc_task_t *task, isc_nm_cb_t connected, + isc_nm_cb_t sent, isc_taskaction_t action, + isc_taskaction_t timeout_action, void *arg, + dns_messageid_t *idp, dns_dispentry_t **resp); /*%< * Add a response entry for this dispatch. * * "*idp" is filled in with the assigned message ID, and *resp is filled in * to contain the magic token used to request event flow stop. * - * Arranges for the given task to get a callback for response packets. When - * the event is delivered, it must be returned using dns_dispatch_freeevent() - * or through dns_dispatch_removeresponse() for another to be delivered. + * The 'connected' and 'sent' callbacks are run to inform the caller when + * the connection and send functions are complete. + * + * The specified 'task' is sent the 'action' callback for response packets. + * (Later, this should be updated to a network manager callback function, + * but for now we still use isc_task for this.) When the event is delivered, + * it must be returned using dns_dispatch_freeevent() or through + * dns_dispatch_removeresponse() for another to be delivered. + * + * On timeout, 'timeout_action' will be sent to the task. + * + * All three callback functions are sent 'arg' as a parameter. * * Requires: *\li "idp" be non-NULL. @@ -344,10 +342,6 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, * *\li "resp" be non-NULL and *resp be NULL * - *\li "sockmgr" be NULL or a valid socket manager. If 'disp' has - * the DNS_DISPATCHATTR_EXCLUSIVE attribute, this must not be NULL, - * which also means dns_dispatch_addresponse() cannot be used. - * * Ensures: * *\li <id, dest> is a unique tuple. That means incoming messages @@ -452,9 +446,9 @@ dns_dispatchset_get(dns_dispatchset_t *dset); */ isc_result_t -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); +dns_dispatchset_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, + dns_dispatch_t *source, dns_dispatchset_t **dsetp, + int n); /*%< * Given a valid dispatch 'source', create a dispatch set containing * 'n' UDP dispatches, with the remainder filled out by clones of the diff --git a/lib/dns/include/dns/request.h b/lib/dns/include/dns/request.h index 98afe5a4ae..9554603b50 100644 --- a/lib/dns/include/dns/request.h +++ b/lib/dns/include/dns/request.h @@ -53,8 +53,7 @@ typedef struct dns_requestevent { ISC_LANG_BEGINDECLS isc_result_t -dns_requestmgr_create(isc_mem_t *mctx, isc_timermgr_t *timermgr, - isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr, +dns_requestmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, dns_requestmgr_t **requestmgrp); @@ -65,8 +64,6 @@ dns_requestmgr_create(isc_mem_t *mctx, isc_timermgr_t *timermgr, * *\li 'mctx' is a valid memory context. * - *\li 'timermgr' is a valid timer manager. - * *\li 'socketmgr' is a valid socket manager. * *\li 'taskmgr' is a valid task manager. diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index 07b94fdcd1..aeda97dd38 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -163,11 +163,10 @@ typedef enum { dns_quotatype_zone = 0, dns_quotatype_server } dns_quotatype_t; isc_result_t dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, - unsigned int ntasks, unsigned int ndisp, - isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, - unsigned int options, dns_dispatchmgr_t *dispatchmgr, - dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, - dns_resolver_t **resp); + unsigned int ntasks, unsigned int ndisp, isc_nm_t *nm, + isc_timermgr_t *timermgr, unsigned int options, + dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4, + dns_dispatch_t *dispatchv6, dns_resolver_t **resp); /*%< * Create a resolver. @@ -185,7 +184,7 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, * *\li 'ntasks' > 0. * - *\li 'socketmgr' is a valid socket manager. + *\li 'nm' is a valid network manager. * *\li 'timermgr' is a valid timer manager. * @@ -413,9 +412,6 @@ dns_resolver_dispatchv4(dns_resolver_t *resolver); dns_dispatch_t * dns_resolver_dispatchv6(dns_resolver_t *resolver); -isc_socketmgr_t * -dns_resolver_socketmgr(dns_resolver_t *resolver); - isc_taskmgr_t * dns_resolver_taskmgr(dns_resolver_t *resolver); diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index bfe9abd763..5e777229e8 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -393,9 +393,9 @@ dns_view_createzonetable(dns_view_t *view); isc_result_t dns_view_createresolver(dns_view_t *view, isc_taskmgr_t *taskmgr, - unsigned int ntasks, unsigned int ndisp, - isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, - unsigned int options, dns_dispatchmgr_t *dispatchmgr, + unsigned int ntasks, unsigned int ndisp, isc_nm_t *nm, + isc_timermgr_t *timermgr, unsigned int options, + dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6); /*%< * Create a resolver and address database for the view. @@ -407,7 +407,7 @@ dns_view_createresolver(dns_view_t *view, isc_taskmgr_t *taskmgr, *\li 'view' does not have a resolver already. * *\li The requirements of dns_resolver_create() apply to 'taskmgr', - * 'ntasks', 'socketmgr', 'timermgr', 'options', 'dispatchv4', and + * 'ntasks', 'nm', 'timermgr', 'options', 'dispatchv4', and * 'dispatchv6'. * * Returns: diff --git a/lib/dns/request.c b/lib/dns/request.c index 367a716d20..c629997c02 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -50,8 +49,6 @@ struct dns_requestmgr { /* locked */ int32_t eref; int32_t iref; - isc_timermgr_t *timermgr; - isc_socketmgr_t *socketmgr; isc_taskmgr_t *taskmgr; dns_dispatchmgr_t *dispatchmgr; dns_dispatch_t *dispatchv4; @@ -74,7 +71,6 @@ struct dns_request { dns_requestevent_t *event; dns_dispatch_t *dispatch; dns_dispentry_t *dispentry; - isc_timer_t *timer; dns_requestmgr_t *requestmgr; isc_buffer_t *tsig; dns_tsigkey_t *tsigkey; @@ -115,16 +111,16 @@ static isc_result_t req_render(dns_message_t *message, isc_buffer_t **buffer, unsigned int options, isc_mem_t *mctx); static void -req_senddone(isc_task_t *task, isc_event_t *event); -static void req_response(isc_task_t *task, isc_event_t *event); static void req_timeout(isc_task_t *task, isc_event_t *event); static void -req_connected(isc_task_t *task, isc_event_t *event); +req_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *arg); static void req_sendevent(dns_request_t *request, isc_result_t result); static void +req_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg); +static void req_cancel(dns_request_t *request); static void req_destroy(dns_request_t *request); @@ -138,8 +134,7 @@ do_cancel(isc_task_t *task, isc_event_t *event); ***/ isc_result_t -dns_requestmgr_create(isc_mem_t *mctx, isc_timermgr_t *timermgr, - isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr, +dns_requestmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, dns_requestmgr_t **requestmgrp) { @@ -150,8 +145,6 @@ dns_requestmgr_create(isc_mem_t *mctx, isc_timermgr_t *timermgr, req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create"); REQUIRE(requestmgrp != NULL && *requestmgrp == NULL); - REQUIRE(timermgr != NULL); - REQUIRE(socketmgr != NULL); REQUIRE(taskmgr != NULL); REQUIRE(dispatchmgr != NULL); @@ -171,8 +164,6 @@ dns_requestmgr_create(isc_mem_t *mctx, isc_timermgr_t *timermgr, for (i = 0; i < DNS_REQUEST_NLOCKS; i++) { isc_mutex_init(&requestmgr->locks[i]); } - requestmgr->timermgr = timermgr; - requestmgr->socketmgr = socketmgr; requestmgr->taskmgr = taskmgr; requestmgr->dispatchmgr = dispatchmgr; requestmgr->dispatchv4 = NULL; @@ -410,12 +401,9 @@ mgr_gethash(dns_requestmgr_t *requestmgr) { return (requestmgr->hash % DNS_REQUEST_NLOCKS); } -static inline isc_result_t -req_send(dns_request_t *request, isc_task_t *task, - const isc_sockaddr_t *address) { - isc_result_t result; +static inline void +req_send(dns_request_t *request) { isc_region_t r; - bool tcp; req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request); @@ -423,14 +411,8 @@ req_send(dns_request_t *request, isc_task_t *task, isc_buffer_usedregion(request->query, &r); - tcp = dns_request_usedtcp(request); - request->flags |= DNS_REQUEST_F_SENDING; - result = dns_dispatch_send(request->dispentry, tcp, task, - &request->sendevent, &r, address, - request->dscp, req_senddone, request); - INSIST(result == ISC_R_SUCCESS); - return (result); + dns_dispatch_send(request->dispentry, &r, request->dscp); } static isc_result_t @@ -497,9 +479,9 @@ tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr, } } - result = dns_dispatch_createtcp( - requestmgr->dispatchmgr, requestmgr->socketmgr, - requestmgr->taskmgr, srcaddr, destaddr, 0, dscp, dispatchp); + result = dns_dispatch_createtcp(requestmgr->dispatchmgr, + requestmgr->taskmgr, srcaddr, destaddr, + 0, dscp, dispatchp); return (result); } @@ -528,9 +510,9 @@ udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, return (ISC_R_SUCCESS); } - return (dns_dispatch_createudp( - requestmgr->dispatchmgr, requestmgr->socketmgr, - requestmgr->taskmgr, srcaddr, 0, dispatchp)); + return (dns_dispatch_createudp(requestmgr->dispatchmgr, + requestmgr->taskmgr, srcaddr, 0, + dispatchp)); } static isc_result_t @@ -548,25 +530,6 @@ get_dispatch(bool tcp, bool newtcp, dns_requestmgr_t *requestmgr, return (result); } -static isc_result_t -set_timer(isc_timer_t *timer, unsigned int timeout, unsigned int udpresend) { - isc_time_t expires; - isc_interval_t interval; - isc_result_t result; - isc_timertype_t timertype; - - isc_interval_set(&interval, timeout, 0); - result = isc_time_nowplusinterval(&expires, &interval); - isc_interval_set(&interval, udpresend, 0); - - timertype = udpresend != 0 ? isc_timertype_limited : isc_timertype_once; - if (result == ISC_R_SUCCESS) { - result = isc_timer_reset(timer, timertype, &expires, &interval, - false); - } - return (result); -} - isc_result_t dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, const isc_sockaddr_t *srcaddr, @@ -617,19 +580,13 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, udptimeout = 1; } } + + timeout *= 1000; + udptimeout *= 1000; + request->udpcount = udpretries; request->dscp = dscp; - /* - * Create timer now. We will set it below once. - */ - result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive, - NULL, NULL, task, req_timeout, request, - &request->timer); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - request->event = (dns_requestevent_t *)isc_event_allocate( mctx, task, DNS_EVENT_REQUESTDONE, action, arg, sizeof(dns_requestevent_t)); @@ -661,8 +618,9 @@ again: } result = dns_dispatch_addresponse( - request->dispatch, dispopt, destaddr, task, req_response, - request, &id, &request->dispentry, requestmgr->socketmgr); + request->dispatch, dispopt, tcp ? timeout : udptimeout, + destaddr, task, req_connected, req_senddone, req_response, + req_timeout, request, &id, &request->dispentry); if (result != ISC_R_SUCCESS) { if ((options & DNS_REQUESTOPT_FIXEDID) != 0 && !newtcp) { newtcp = true; @@ -674,9 +632,6 @@ again: } isc_buffer_allocate(mctx, &request->query, r.length + (tcp ? 2 : 0)); - if (tcp) { - isc_buffer_putuint16(request->query, (uint16_t)r.length); - } result = isc_buffer_copyregion(request->query, &r); if (result != ISC_R_SUCCESS) { goto cleanup; @@ -684,9 +639,6 @@ again: /* Add message ID. */ isc_buffer_usedregion(request->query, &r); - if (tcp) { - isc_region_consume(&r, 2); - } r.base[0] = (id >> 8) & 0xff; r.base[1] = id & 0xff; @@ -701,24 +653,15 @@ again: ISC_LIST_APPEND(requestmgr->requests, request, link); UNLOCK(&requestmgr->lock); - result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout); - if (result != ISC_R_SUCCESS) { - goto unlink; - } - request->destaddr = *destaddr; - if (tcp && !connected) { - result = dns_dispatch_connect(request->dispatch, NULL, task, - req_connected, request); + if (!tcp || !connected) { + result = dns_dispatch_connect(request->dispentry); if (result != ISC_R_SUCCESS) { goto unlink; } request->flags |= DNS_REQUEST_F_CONNECTING | DNS_REQUEST_F_TCP; } else { - result = req_send(request, task, connected ? NULL : destaddr); - if (result != ISC_R_SUCCESS) { - goto unlink; - } + req_send(request); } req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p", request); @@ -790,7 +733,6 @@ dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message, return (DNS_R_BLACKHOLED); } - request = NULL; result = new_request(mctx, &request); if (result != ISC_R_SUCCESS) { return (result); @@ -802,19 +744,13 @@ dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message, udptimeout = 1; } } + + timeout *= 1000; + udptimeout *= 1000; + request->udpcount = udpretries; request->dscp = dscp; - /* - * Create timer now. We will set it below once. - */ - result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive, - NULL, NULL, task, req_timeout, request, - &request->timer); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - request->event = (dns_requestevent_t *)isc_event_allocate( mctx, task, DNS_EVENT_REQUESTDONE, action, arg, sizeof(dns_requestevent_t)); @@ -835,8 +771,9 @@ use_tcp: } result = dns_dispatch_addresponse( - request->dispatch, 0, destaddr, task, req_response, request, - &id, &request->dispentry, requestmgr->socketmgr); + request->dispatch, 0, tcp ? timeout : udptimeout, destaddr, + task, req_connected, req_senddone, req_response, req_timeout, + request, &id, &request->dispentry); if (result != ISC_R_SUCCESS) { goto cleanup; } @@ -880,24 +817,15 @@ use_tcp: ISC_LIST_APPEND(requestmgr->requests, request, link); UNLOCK(&requestmgr->lock); - result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout); - if (result != ISC_R_SUCCESS) { - goto unlink; - } - request->destaddr = *destaddr; - if (tcp && !connected) { - result = dns_dispatch_connect(request->dispatch, NULL, task, - req_connected, request); + if (!tcp || !connected) { + result = dns_dispatch_connect(request->dispentry); if (result != ISC_R_SUCCESS) { goto unlink; } request->flags |= DNS_REQUEST_F_CONNECTING | DNS_REQUEST_F_TCP; } else { - result = req_send(request, task, connected ? NULL : destaddr); - if (result != ISC_R_SUCCESS) { - goto unlink; - } + req_send(request); } req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p", request); @@ -926,7 +854,6 @@ req_render(dns_message_t *message, isc_buffer_t **bufferp, unsigned int options, isc_buffer_t *buf2 = NULL; isc_result_t result; isc_region_t r; - bool tcp = false; dns_compress_t cctx; bool cleanup_cctx = false; @@ -984,16 +911,11 @@ req_render(dns_message_t *message, isc_buffer_t **bufferp, unsigned int options, * Copy rendered message to exact sized buffer. */ isc_buffer_usedregion(buf1, &r); - if ((options & DNS_REQUESTOPT_TCP) != 0) { - tcp = true; - } else if (r.length > 512) { + if ((options & DNS_REQUESTOPT_TCP) == 0 && r.length > 512) { result = DNS_R_USETCP; goto cleanup; } - isc_buffer_allocate(mctx, &buf2, r.length + (tcp ? 2 : 0)); - if (tcp) { - isc_buffer_putuint16(buf2, (uint16_t)r.length); - } + isc_buffer_allocate(mctx, &buf2, r.length); result = isc_buffer_copyregion(buf2, &r); if (result != ISC_R_SUCCESS) { goto cleanup; @@ -1138,7 +1060,6 @@ dns_request_destroy(dns_request_t **requestp) { INSIST(!ISC_LINK_LINKED(request, link)); INSIST(request->dispentry == NULL); INSIST(request->dispatch == NULL); - INSIST(request->timer == NULL); req_destroy(request); } @@ -1147,12 +1068,11 @@ dns_request_destroy(dns_request_t **requestp) { *** Private: request. ***/ static void -req_connected(isc_task_t *task, isc_event_t *event) { - isc_socketevent_t *sevent = (isc_socketevent_t *)event; - isc_result_t result; - dns_request_t *request = event->ev_arg; +req_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { + dns_request_t *request = (dns_request_t *)arg; + + UNUSED(handle); - REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); REQUIRE(VALID_REQUEST(request)); REQUIRE(DNS_REQUEST_CONNECTING(request)); @@ -1171,53 +1091,42 @@ req_connected(isc_task_t *task, isc_event_t *event) { send_if_done(request, ISC_R_CANCELED); } } else { - dns_dispatch_starttcp(request->dispatch); - result = sevent->result; - if (result == ISC_R_SUCCESS) { - result = req_send(request, task, NULL); - } - - if (result != ISC_R_SUCCESS) { + if (eresult == ISC_R_SUCCESS) { + req_send(request); + } else { req_cancel(request); send_if_done(request, ISC_R_CANCELED); } } UNLOCK(&request->requestmgr->locks[request->hash]); - isc_event_free(&event); } static void -req_senddone(isc_task_t *task, isc_event_t *event) { - isc_socketevent_t *sevent = (isc_socketevent_t *)event; - dns_request_t *request = event->ev_arg; +req_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { + dns_request_t *request = (dns_request_t *)arg; - REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE); REQUIRE(VALID_REQUEST(request)); REQUIRE(DNS_REQUEST_SENDING(request)); - req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request); + UNUSED(handle); - UNUSED(task); + req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request); LOCK(&request->requestmgr->locks[request->hash]); request->flags &= ~DNS_REQUEST_F_SENDING; if (DNS_REQUEST_CANCELED(request)) { - /* - * Send delayed event. - */ if (DNS_REQUEST_TIMEDOUT(request)) { send_if_done(request, ISC_R_TIMEDOUT); } else { send_if_done(request, ISC_R_CANCELED); } - } else if (sevent->result != ISC_R_SUCCESS) { + } else if (eresult != ISC_R_SUCCESS) { req_cancel(request); send_if_done(request, ISC_R_CANCELED); } - UNLOCK(&request->requestmgr->locks[request->hash]); - isc_event_free(&event); + UNLOCK(&request->requestmgr->locks[request->hash]); } static void @@ -1266,7 +1175,6 @@ done: static void req_timeout(isc_task_t *task, isc_event_t *event) { dns_request_t *request = event->ev_arg; - isc_result_t result; REQUIRE(VALID_REQUEST(request)); @@ -1274,13 +1182,9 @@ req_timeout(isc_task_t *task, isc_event_t *event) { UNUSED(task); LOCK(&request->requestmgr->locks[request->hash]); - if (event->ev_type == ISC_TIMEREVENT_TICK && request->udpcount-- != 0) { + if (request->udpcount-- != 0) { if (!DNS_REQUEST_SENDING(request)) { - result = req_send(request, task, &request->destaddr); - if (result != ISC_R_SUCCESS) { - req_cancel(request); - send_if_done(request, result); - } + req_send(request); } } else { request->flags |= DNS_REQUEST_F_TIMEDOUT; @@ -1330,9 +1234,6 @@ req_destroy(dns_request_t *request) { if (request->dispatch != NULL) { dns_dispatch_detach(&request->dispatch); } - if (request->timer != NULL) { - isc_timer_detach(&request->timer); - } if (request->tsig != NULL) { isc_buffer_free(&request->tsig); } @@ -1359,10 +1260,6 @@ req_cancel(dns_request_t *request) { */ request->flags |= DNS_REQUEST_F_CANCELED; - if (request->timer != NULL) { - isc_timer_detach(&request->timer); - } - if (request->dispentry != NULL) { dns_dispatch_cancel(NULL, request->dispentry, DNS_REQUEST_SENDING(request), diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index febec16482..b987b888cb 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -496,7 +496,7 @@ struct dns_resolver { isc_mutex_t lock; isc_mutex_t primelock; dns_rdataclass_t rdclass; - isc_socketmgr_t *socketmgr; + isc_nm_t *nm; isc_timermgr_t *timermgr; isc_taskmgr_t *taskmgr; dns_view_t *view; @@ -604,7 +604,7 @@ resquery_send(resquery_t *query); static void resquery_response(isc_task_t *task, isc_event_t *event); static void -resquery_connected(isc_task_t *task, isc_event_t *event); +resquery_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg); static void fctx_try(fetchctx_t *fctx, bool retrying, bool badcache); static isc_result_t @@ -1354,10 +1354,11 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, } dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor); - } - if ((query->options & DNS_FETCHOPT_TCP) == 0) { - /* Inform the ADB that we're ending a UDP fetch */ - dns_adb_endudpfetch(fctx->adb, query->addrinfo); + + if ((query->options & DNS_FETCHOPT_TCP) == 0) { + /* Inform the ADB that we're ending a UDP fetch */ + dns_adb_endudpfetch(fctx->adb, query->addrinfo); + } } /* @@ -1428,7 +1429,9 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, dns_dispatch_removeresponse(&query->dispentry, deventp); } - ISC_LIST_UNLINK(fctx->queries, query, link); + if (ISC_LINK_LINKED(query, link)) { + ISC_LIST_UNLINK(fctx->queries, query, link); + } if (query->tsig != NULL) { isc_buffer_free(&query->tsig); @@ -1796,13 +1799,20 @@ fctx_done(fetchctx_t *fctx, isc_result_t result, int line) { } static void -process_sendevent(resquery_t *query, isc_event_t *event) { - isc_socketevent_t *sevent = (isc_socketevent_t *)event; +resquery_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { + resquery_t *query = (resquery_t *)arg; bool destroy_query = false; - bool retry = false; isc_result_t result; fetchctx_t *fctx = NULL; + QTRACE("senddone"); + + UNUSED(handle); + + INSIST(RESQUERY_SENDING(query)); + + query->sends--; + fctx = query->fctx; if (RESQUERY_CANCELED(query)) { @@ -1810,7 +1820,7 @@ process_sendevent(resquery_t *query, isc_event_t *event) { destroy_query = true; } } else { - switch (sevent->result) { + switch (eresult) { case ISC_R_SUCCESS: break; @@ -1819,94 +1829,44 @@ process_sendevent(resquery_t *query, isc_event_t *event) { case ISC_R_NOPERM: case ISC_R_ADDRNOTAVAIL: case ISC_R_CONNREFUSED: - FCTXTRACE3("query canceled in sendevent(): " + FCTXTRACE3("query canceled in resquery_senddone(): " "no route to host; no response", - sevent->result); + eresult); /* * No route to remote. */ - add_bad(fctx, query->rmessage, query->addrinfo, - sevent->result, badns_unreachable); + add_bad(fctx, query->rmessage, query->addrinfo, eresult, + badns_unreachable); fctx_cancelquery(&query, NULL, NULL, true, false); - retry = true; + + /* + * Behave as if the idle timer has expired. For TCP + * this may not actually reflect the latest timer. + */ + FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT); + result = fctx_stopidletimer(fctx); + if (result != ISC_R_SUCCESS) { + fctx_done(fctx, result, __LINE__); + } else { + fctx_try(fctx, true, false); + } break; default: - FCTXTRACE3("query canceled in sendevent() due to " - "unexpected event result; responding", - sevent->result); - + FCTXTRACE3("query canceled in resquery_senddone() " + "due to unexpected result; responding", + eresult); fctx_cancelquery(&query, NULL, NULL, false, false); break; } } - if (event->ev_type == ISC_SOCKEVENT_CONNECT) { - isc_event_free(&event); - } - - if (retry) { - /* - * Behave as if the idle timer has expired. For TCP - * this may not actually reflect the latest timer. - */ - FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT); - result = fctx_stopidletimer(fctx); - if (result != ISC_R_SUCCESS) { - fctx_done(fctx, result, __LINE__); - } else { - fctx_try(fctx, true, false); - } - } - if (destroy_query) { resquery_destroy(&query); } } -static void -resquery_udpconnected(isc_task_t *task, isc_event_t *event) { - resquery_t *query = event->ev_arg; - - REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); - - QTRACE("udpconnected"); - - UNUSED(task); - - INSIST(RESQUERY_CONNECTING(query)); - - query->connects--; - - process_sendevent(query, event); -} - -static void -resquery_senddone(isc_task_t *task, isc_event_t *event) { - resquery_t *query = event->ev_arg; - - REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE); - - QTRACE("senddone"); - - /* - * XXXRTH - * - * Currently we don't wait for the senddone event before retrying - * a query. This means that if we get really behind, we may end - * up doing extra work! - */ - - UNUSED(task); - - INSIST(RESQUERY_SENDING(query)); - - query->sends--; - - process_sendevent(query, event); -} - static inline isc_result_t fctx_addopt(dns_message_t *message, unsigned int version, uint16_t udpsize, dns_ednsopt_t *ednsopts, size_t count) { @@ -1972,15 +1932,14 @@ fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) { static isc_result_t fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, unsigned int options) { + isc_result_t result; dns_resolver_t *res = NULL; isc_task_t *task = NULL; - isc_result_t result; resquery_t *query = NULL; isc_sockaddr_t addr; bool have_addr = false; unsigned int srtt; isc_dscp_t dscp = -1; - unsigned int bucketnum; FCTXTRACE("query"); @@ -2088,9 +2047,9 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, query->dscp = dscp; } - result = dns_dispatch_createtcp( - res->dispatchmgr, res->socketmgr, res->taskmgr, &addr, - &addrinfo->sockaddr, 0, query->dscp, &query->dispatch); + result = dns_dispatch_createtcp(res->dispatchmgr, res->taskmgr, + &addr, &addrinfo->sockaddr, 0, + query->dscp, &query->dispatch); if (result != ISC_R_SUCCESS) { goto cleanup_query; } @@ -2107,9 +2066,9 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, result = ISC_R_NOTIMPLEMENTED; goto cleanup_query; } - result = dns_dispatch_createudp( - res->dispatchmgr, res->socketmgr, res->taskmgr, - &addr, 0, &query->dispatch); + result = dns_dispatch_createudp(res->dispatchmgr, + res->taskmgr, &addr, 0, + &query->dispatch); if (result != ISC_R_SUCCESS) { goto cleanup_query; } @@ -2150,49 +2109,34 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, ISC_LINK_INIT(query, link); query->magic = QUERY_MAGIC; - if ((query->options & DNS_FETCHOPT_TCP) != 0) { - /* - * Connect to the remote server. - */ - result = dns_dispatch_connect(query->dispatch, NULL, task, - resquery_connected, query); - if (result != ISC_R_SUCCESS) { - goto cleanup_dispatch; - } - query->connects++; - QTRACE("connecting via TCP"); - } else { + if ((query->options & DNS_FETCHOPT_TCP) == 0) { if (dns_adbentry_overquota(addrinfo->entry)) { goto cleanup_dispatch; } /* Inform the ADB that we're starting a UDP fetch */ dns_adb_beginudpfetch(fctx->adb, addrinfo); - - result = resquery_send(query); - if (result != ISC_R_SUCCESS) { - goto cleanup_dispatch; - } } - fctx->querysent++; - - ISC_LIST_APPEND(fctx->queries, query, link); - bucketnum = fctx->bucketnum; - LOCK(&res->buckets[bucketnum].lock); + LOCK(&res->buckets[fctx->bucketnum].lock); fctx->nqueries++; - UNLOCK(&res->buckets[bucketnum].lock); - if (isc_sockaddr_pf(&addrinfo->sockaddr) == PF_INET) { - inc_stats(res, dns_resstatscounter_queryv4); - } else { - inc_stats(res, dns_resstatscounter_queryv6); - } - if (res->view->resquerystats != NULL) { - dns_rdatatypestats_increment(res->view->resquerystats, - fctx->type); + UNLOCK(&res->buckets[fctx->bucketnum].lock); + + /* Set up the dispatch and set the query ID */ + /* XXX: timeout hard-coded to 10 seconds */ + result = dns_dispatch_addresponse( + query->dispatch, 0, 10000, &query->addrinfo->sockaddr, task, + resquery_connected, resquery_senddone, resquery_response, NULL, + query, &query->id, &query->dispentry); + if (result != ISC_R_SUCCESS) { + goto cleanup_dispatch; } - return (ISC_R_SUCCESS); + /* Connect the socket */ + query->connects++; + fctx_increference(fctx); + result = dns_dispatch_connect(query->dispentry); + return (result); cleanup_dispatch: if (query->dispatch != NULL) { @@ -2349,21 +2293,19 @@ issecuredomain(dns_view_t *view, const dns_name_t *name, dns_rdatatype_t type, static isc_result_t resquery_send(resquery_t *query) { - fetchctx_t *fctx = NULL; isc_result_t result; + fetchctx_t *fctx = query->fctx; + dns_resolver_t *res = fctx->res; + isc_buffer_t buffer; dns_name_t *qname = NULL; dns_rdataset_t *qrdataset = NULL; isc_region_t r; - dns_resolver_t *res = NULL; - isc_task_t *task = NULL; - isc_buffer_t tcpbuffer; - isc_buffer_t *buffer = NULL; isc_netaddr_t ipaddr; dns_tsigkey_t *tsigkey = NULL; dns_peer_t *peer = NULL; - bool useedns; dns_compress_t cctx; bool cleanup_cctx = false; + bool useedns; bool secure_domain; bool tcp = ((query->options & DNS_FETCHOPT_TCP) != 0); dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS]; @@ -2377,24 +2319,11 @@ resquery_send(resquery_t *query) { isc_buffer_t zb; #endif /* HAVE_DNSTAP */ - fctx = query->fctx; QTRACE("send"); - res = fctx->res; - task = res->buckets[fctx->bucketnum].task; - - if (tcp) { - /* - * Reserve space for the TCP message length. - */ - isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data)); - isc_buffer_init(&query->buffer, query->data + 2, - sizeof(query->data) - 2); - buffer = &tcpbuffer; - } else { - isc_buffer_init(&query->buffer, query->data, - sizeof(query->data)); - buffer = &query->buffer; + if (atomic_load_acquire(&res->exiting)) { + FCTXTRACE("resquery_send: resolver shutting down"); + return (ISC_R_SHUTTINGDOWN); } result = dns_message_gettempname(fctx->qmessage, &qname); @@ -2406,17 +2335,6 @@ resquery_send(resquery_t *query) { goto cleanup_temps; } - /* - * Get a query id from the dispatch. - */ - result = dns_dispatch_addresponse(query->dispatch, 0, - &query->addrinfo->sockaddr, task, - resquery_response, query, &query->id, - &query->dispentry, res->socketmgr); - if (result != ISC_R_SUCCESS) { - goto cleanup_temps; - } - fctx->qmessage->opcode = dns_opcode_query; /* @@ -2479,7 +2397,8 @@ resquery_send(resquery_t *query) { } cleanup_cctx = true; - result = dns_message_renderbegin(fctx->qmessage, &cctx, &query->buffer); + isc_buffer_init(&buffer, query->data, sizeof(query->data)); + result = dns_message_renderbegin(fctx->qmessage, &cctx, &buffer); if (result != ISC_R_SUCCESS) { goto cleanup_message; } @@ -2490,7 +2409,6 @@ resquery_send(resquery_t *query) { goto cleanup_message; } - peer = NULL; isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr); (void)dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer); @@ -2757,16 +2675,6 @@ resquery_send(resquery_t *query) { } } - /* - * If using TCP, write the length of the message at the beginning - * of the buffer. - */ - if (tcp) { - isc_buffer_usedregion(&query->buffer, &r); - isc_buffer_putuint16(&tcpbuffer, (uint16_t)r.length); - isc_buffer_add(&tcpbuffer, r.length); - } - /* * Log the outgoing packet. */ @@ -2780,23 +2688,9 @@ resquery_send(resquery_t *query) { */ dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER); - if (!tcp) { - /* Connect the UDP socket */ - result = dns_dispatch_connect(NULL, query->dispentry, task, - resquery_udpconnected, query); - if (result != ISC_R_SUCCESS) { - goto cleanup_message; - } - query->connects++; - } + isc_buffer_usedregion(&buffer, &r); - isc_buffer_usedregion(buffer, &r); - - result = dns_dispatch_send(query->dispentry, tcp, task, - &query->sendevent, &r, - &query->addrinfo->sockaddr, query->dscp, - resquery_senddone, query); - INSIST(result == ISC_R_SUCCESS); + dns_dispatch_send(query->dispentry, &r, query->dscp); query->sends++; QTRACE("sent"); @@ -2817,7 +2711,7 @@ resquery_send(resquery_t *query) { } dns_dt_send(fctx->res->view, dtmsgtype, la, &query->addrinfo->sockaddr, - tcp, &zr, &query->start, NULL, &query->buffer); + tcp, &zr, &query->start, NULL, &buffer); #endif /* HAVE_DNSTAP */ return (ISC_R_SUCCESS); @@ -2846,40 +2740,40 @@ cleanup_temps: } static void -resquery_connected(isc_task_t *task, isc_event_t *event) { - isc_socketevent_t *sevent = (isc_socketevent_t *)event; - resquery_t *query = event->ev_arg; - bool retry = false; +resquery_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { + resquery_t *query = (resquery_t *)arg; isc_interval_t interval; isc_result_t result; - fetchctx_t *fctx; + fetchctx_t *fctx = NULL; + dns_resolver_t *res = NULL; + unsigned int bucketnum; + bool bucket_empty; + int pf; - REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); REQUIRE(VALID_QUERY(query)); QTRACE("connected"); - UNUSED(task); - - /* - * XXXRTH - * - * Currently we don't wait for the connect event before retrying - * a query. This means that if we get really behind, we may end - * up doing extra work! - */ + UNUSED(handle); query->connects--; fctx = query->fctx; + res = fctx->res; + + bucketnum = fctx->bucketnum; + + if (atomic_load_acquire(&res->exiting)) { + eresult = ISC_R_SHUTTINGDOWN; + } if (RESQUERY_CANCELED(query)) { /* - * This query was canceled while the connect() was in - * progress. + * This query was canceled while the connect() was + * in progress. */ resquery_destroy(&query); } else { - switch (sevent->result) { + switch (eresult) { case ISC_R_SUCCESS: /* @@ -2890,8 +2784,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { * received. */ isc_interval_set(&interval, - fctx->res->query_timeout / 1000 / 2, - 0); + res->query_timeout / 1000 / 2, 0); result = fctx_startidletimer(query->fctx, &interval); if (result != ISC_R_SUCCESS) { FCTXTRACE("query canceled: idle timer failed; " @@ -2904,7 +2797,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { } /* - * We are connected. Update the dispatcher and + * We are connected. Update the dispatcher and * send the query. */ dns_dispatch_changeattributes( @@ -2920,6 +2813,20 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { false); fctx_done(fctx, result, __LINE__); } + + fctx->querysent++; + + ISC_LIST_APPEND(fctx->queries, query, link); + pf = isc_sockaddr_pf(&query->addrinfo->sockaddr); + if (pf == PF_INET) { + inc_stats(res, dns_resstatscounter_queryv4); + } else { + inc_stats(res, dns_resstatscounter_queryv6); + } + if (res->view->resquerystats != NULL) { + dns_rdatatypestats_increment( + res->view->resquerystats, fctx->type); + } break; case ISC_R_NETUNREACH: @@ -2928,45 +2835,46 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { case ISC_R_NOPERM: case ISC_R_ADDRNOTAVAIL: case ISC_R_CONNECTIONRESET: - FCTXTRACE3("query canceled in connected(): " + FCTXTRACE3("query canceled in resquery_connected(): " "no route to host; no response", - sevent->result); + eresult); /* * Do not query this server again in this fetch context * if the server is unavailable over TCP. */ - add_bad(fctx, query->rmessage, query->addrinfo, - sevent->result, badns_unreachable); + add_bad(fctx, query->rmessage, query->addrinfo, eresult, + badns_unreachable); fctx_cancelquery(&query, NULL, NULL, true, false); - retry = true; + + /* + * Behave as if the idle timer has expired. For + * TCP connections this may not actually reflect + * the latest timer. + */ + FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT); + result = fctx_stopidletimer(fctx); + if (result != ISC_R_SUCCESS) { + fctx_done(fctx, result, __LINE__); + } else { + fctx_try(fctx, true, false); + } break; default: - FCTXTRACE3("query canceled in connected() due to " - "unexpected event result; responding", - sevent->result); + FCTXTRACE3("query canceled in resquery_connected() " + "due to unexpected result; responding", + eresult); - dns_dispatch_detach(&query->dispatch); fctx_cancelquery(&query, NULL, NULL, false, false); - break; } } - isc_event_free(&event); - - if (retry) { - /* - * Behave as if the idle timer has expired. For TCP - * connections this may not actually reflect the latest timer. - */ - FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT); - result = fctx_stopidletimer(fctx); - if (result != ISC_R_SUCCESS) { - fctx_done(fctx, result, __LINE__); - } else { - fctx_try(fctx, true, false); - } + LOCK(&res->buckets[bucketnum].lock); + bucket_empty = fctx_decreference(fctx); + UNLOCK(&res->buckets[bucketnum].lock); + if (bucket_empty) { + empty_bucket(res); } } @@ -4140,7 +4048,6 @@ fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) { } fctx_increference(fctx); - result = fctx_query(fctx, addrinfo, fctx->options); if (result != ISC_R_SUCCESS) { fctx_done(fctx, result, __LINE__); @@ -5033,8 +4940,8 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type, (res->query_timeout - 1000)); /* * Compute an expiration time after which stale data will - * attempted to be served, if stale answers are enabled and - * target RRset is available in cache. + * be served, if stale answers are enabled and target RRset is + * available in cache. */ isc_interval_set( &interval, res->view->staleanswerclienttimeout / 1000, @@ -7521,6 +7428,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { if (atomic_load_acquire(&fctx->res->exiting)) { result = ISC_R_SHUTTINGDOWN; FCTXTRACE("resolver shutting down"); + rctx.finish = NULL; rctx_done(&rctx, result); return; } @@ -9689,13 +9597,13 @@ rctx_done(respctx_t *rctx, isc_result_t result) { /* * Need to attach to the message until the scope * of this function ends, since there are many places - * where te message is used and/or may be destroyed + * where the message is used and/or may be destroyed * before this function ends. */ dns_message_t *message = NULL; dns_message_attach(query->rmessage, &message); - FCTXTRACE4("query canceled in response(); ", + FCTXTRACE4("query canceled in rctx_done(); ", rctx->no_response ? "no response" : "responding", result); /* @@ -10128,11 +10036,10 @@ spillattimer_countdown(isc_task_t *task, isc_event_t *event) { isc_result_t dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, - unsigned int ntasks, unsigned int ndisp, - isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, - unsigned int options, dns_dispatchmgr_t *dispatchmgr, - dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, - dns_resolver_t **resp) { + unsigned int ntasks, unsigned int ndisp, isc_nm_t *nm, + isc_timermgr_t *timermgr, unsigned int options, + dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4, + dns_dispatch_t *dispatchv6, dns_resolver_t **resp) { dns_resolver_t *res = NULL; isc_result_t result = ISC_R_SUCCESS; unsigned int i, buckets_created = 0, dbuckets_created = 0; @@ -10154,7 +10061,7 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, res = isc_mem_get(view->mctx, sizeof(*res)); *res = (dns_resolver_t){ .mctx = view->mctx, .rdclass = view->rdclass, - .socketmgr = socketmgr, + .nm = nm, .timermgr = timermgr, .taskmgr = taskmgr, .dispatchmgr = dispatchmgr, @@ -10230,13 +10137,13 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, } if (dispatchv4 != NULL) { - dns_dispatchset_create(view->mctx, socketmgr, taskmgr, - dispatchv4, &res->dispatches4, ndisp); + dns_dispatchset_create(view->mctx, taskmgr, dispatchv4, + &res->dispatches4, ndisp); } if (dispatchv6 != NULL) { - dns_dispatchset_create(view->mctx, socketmgr, taskmgr, - dispatchv6, &res->dispatches6, ndisp); + dns_dispatchset_create(view->mctx, taskmgr, dispatchv6, + &res->dispatches6, ndisp); } isc_mutex_init(&res->lock); @@ -10951,12 +10858,6 @@ dns_resolver_dispatchv6(dns_resolver_t *resolver) { return (dns_dispatchset_get(resolver->dispatches6)); } -isc_socketmgr_t * -dns_resolver_socketmgr(dns_resolver_t *resolver) { - REQUIRE(VALID_RESOLVER(resolver)); - return (resolver->socketmgr); -} - isc_taskmgr_t * dns_resolver_taskmgr(dns_resolver_t *resolver) { REQUIRE(VALID_RESOLVER(resolver)); diff --git a/lib/dns/tests/dispatch_test.c b/lib/dns/tests/dispatch_test.c index aa92f4ed87..65a2f3d441 100644 --- a/lib/dns/tests/dispatch_test.c +++ b/lib/dns/tests/dispatch_test.c @@ -20,16 +20,17 @@ #include #include #include +#include #define UNIT_TESTING #include #include #include +#include #include #include #include -#include #include #include @@ -38,18 +39,91 @@ #include "dnstest.h" +/* Timeouts in miliseconds */ +#define T_INIT 120 * 1000 +#define T_IDLE 120 * 1000 +#define T_KEEPALIVE 120 * 1000 +#define T_ADVERTISED 120 * 1000 +#define T_CONNECT 30 * 1000 + dns_dispatchmgr_t *dispatchmgr = NULL; dns_dispatchset_t *dset = NULL; +isc_nm_t *connect_nm = NULL; +static isc_sockaddr_t server_addr; +static isc_sockaddr_t connect_addr; + +static int +setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) { + socklen_t addrlen = sizeof(*addr); + uv_os_sock_t fd; + int r; + + isc_sockaddr_fromin6(addr, &in6addr_loopback, 0); + + fd = socket(AF_INET6, family, 0); + if (fd < 0) { + perror("setup_ephemeral_port: socket()"); + return (-1); + } + + r = bind(fd, (const struct sockaddr *)&addr->type.sa, + sizeof(addr->type.sin6)); + if (r != 0) { + perror("setup_ephemeral_port: bind()"); + close(fd); + return (r); + } + + r = getsockname(fd, (struct sockaddr *)&addr->type.sa, &addrlen); + if (r != 0) { + perror("setup_ephemeral_port: getsockname()"); + close(fd); + return (r); + } + +#if IPV6_RECVERR +#define setsockopt_on(socket, level, name) \ + setsockopt(socket, level, name, &(int){ 1 }, sizeof(int)) + + r = setsockopt_on(fd, IPPROTO_IPV6, IPV6_RECVERR); + if (r != 0) { + perror("setup_ephemeral_port"); + close(fd); + return (r); + } +#endif + + return (fd); +} static int _setup(void **state) { isc_result_t result; + uv_os_sock_t sock = -1; UNUSED(state); result = dns_test_begin(NULL, true); assert_int_equal(result, ISC_R_SUCCESS); + connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0); + + server_addr = (isc_sockaddr_t){ .length = 0 }; + sock = setup_ephemeral_port(&server_addr, SOCK_DGRAM); + if (sock < 0) { + return (-1); + } + close(sock); + + /* Create a secondary network manager */ + isc_managers_create(dt_mctx, ncpus, 0, 0, &connect_nm, NULL, NULL, + NULL); + + isc_nm_settimeouts(netmgr, T_INIT, T_IDLE, T_KEEPALIVE, T_ADVERTISED); + isc_nm_settimeouts(connect_nm, T_INIT, T_IDLE, T_KEEPALIVE, + T_ADVERTISED); + return (0); } @@ -57,6 +131,9 @@ static int _teardown(void **state) { UNUSED(state); + isc_managers_destroy(&connect_nm, NULL, NULL, NULL); + assert_null(connect_nm); + dns_test_end(); return (0); @@ -68,20 +145,18 @@ make_dispatchset(unsigned int ndisps) { isc_sockaddr_t any; dns_dispatch_t *disp = NULL; - result = dns_dispatchmgr_create(dt_mctx, &dispatchmgr); + result = dns_dispatchmgr_create(dt_mctx, netmgr, &dispatchmgr); if (result != ISC_R_SUCCESS) { return (result); } isc_sockaddr_any(&any); - result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &any, - 0, &disp); + result = dns_dispatch_createudp(dispatchmgr, taskmgr, &any, 0, &disp); if (result != ISC_R_SUCCESS) { return (result); } - result = dns_dispatchset_create(dt_mctx, socketmgr, taskmgr, disp, - &dset, ndisps); + result = dns_dispatchset_create(dt_mctx, taskmgr, disp, &dset, ndisps); dns_dispatch_detach(&disp); return (result); @@ -155,68 +230,57 @@ dispatchset_get(void **state) { reset(); } +struct { + isc_nmhandle_t *handle; + atomic_uint_fast32_t responses; +} testdata; + +static dns_dispatch_t *dispatch = NULL; +static dns_dispentry_t *dispentry = NULL; +static atomic_bool first = ATOMIC_VAR_INIT(true); + static void -senddone(isc_task_t *task, isc_event_t *event) { - isc_socket_t *sock = event->ev_arg; +server_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + UNUSED(handle); + UNUSED(eresult); + UNUSED(cbarg); - UNUSED(task); - - isc_socket_detach(&sock); - isc_event_free(&event); + return; } static void -nameserver(isc_task_t *task, isc_event_t *event) { - isc_result_t result; - isc_region_t region; - isc_socket_t *dummy; - isc_socket_t *sock = event->ev_arg; - isc_socketevent_t *ev = (isc_socketevent_t *)event; +nameserver(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, + void *cbarg) { + isc_region_t response; static unsigned char buf1[16]; static unsigned char buf2[16]; - memmove(buf1, ev->region.base, 12); + UNUSED(eresult); + UNUSED(cbarg); + + memmove(buf1, region->base, 12); memset(buf1 + 12, 0, 4); buf1[2] |= 0x80; /* qr=1 */ - memmove(buf2, ev->region.base, 12); + memmove(buf2, region->base, 12); memset(buf2 + 12, 1, 4); buf2[2] |= 0x80; /* qr=1 */ /* * send message to be discarded. */ - region.base = buf1; - region.length = sizeof(buf1); - dummy = NULL; - isc_socket_attach(sock, &dummy); - result = isc_socket_sendto(sock, ®ion, task, senddone, sock, - &ev->address, NULL); - if (result != ISC_R_SUCCESS) { - isc_socket_detach(&dummy); - } + response.base = buf1; + response.length = sizeof(buf1); + isc_nm_send(handle, &response, server_senddone, NULL); /* * send nextitem message. */ - region.base = buf2; - region.length = sizeof(buf2); - dummy = NULL; - isc_socket_attach(sock, &dummy); - result = isc_socket_sendto(sock, ®ion, task, senddone, sock, - &ev->address, NULL); - if (result != ISC_R_SUCCESS) { - isc_socket_detach(&dummy); - } - isc_event_free(&event); + response.base = buf2; + response.length = sizeof(buf2); + isc_nm_send(handle, &response, server_senddone, NULL); } -static dns_dispatch_t *dispatch = NULL; -static dns_dispentry_t *dispentry = NULL; -static atomic_bool first = ATOMIC_VAR_INIT(true); -static isc_sockaddr_t local; -static atomic_uint_fast32_t responses; - static void response(isc_task_t *task, isc_event_t *event) { dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event; @@ -224,78 +288,81 @@ response(isc_task_t *task, isc_event_t *event) { UNUSED(task); - atomic_fetch_add_relaxed(&responses, 1); + atomic_fetch_add_relaxed(&testdata.responses, 1); if (atomic_compare_exchange_strong(&first, &exp_true, false)) { isc_result_t result = dns_dispatch_getnext(dispentry, &devent); assert_int_equal(result, ISC_R_SUCCESS); } else { dns_dispatch_removeresponse(&dispentry, &devent); + isc_nmhandle_detach(&testdata.handle); isc_app_shutdown(); } } static void -startit(isc_task_t *task, isc_event_t *event) { - isc_result_t result; - isc_socket_t *sock = NULL; +connected(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + isc_region_t *r = (isc_region_t *)cbarg; - isc_socket_attach(dns_dispatch_getentrysocket(dispentry), &sock); - result = isc_socket_sendto(sock, event->ev_arg, task, senddone, sock, - &local, NULL); - assert_int_equal(result, ISC_R_SUCCESS); + UNUSED(eresult); + + isc_nmhandle_attach(handle, &testdata.handle); + dns_dispatch_send(dispentry, r, -1); +} + +static void +client_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + UNUSED(handle); + UNUSED(eresult); + UNUSED(cbarg); + + return; +} + +static void +startit(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + dns_dispatch_connect(dispentry); isc_event_free(&event); } /* test dispatch getnext */ static void dispatch_getnext(void **state) { - isc_region_t region; isc_result_t result; - isc_socket_t *sock = NULL; + isc_region_t region; + isc_nmsocket_t *sock = NULL; isc_task_t *task = NULL; - uint16_t id; - struct in_addr ina; unsigned char message[12]; unsigned char rbuf[12]; + uint16_t id; UNUSED(state); - atomic_init(&responses, 0); + testdata.handle = NULL; + atomic_init(&testdata.responses, 0); result = isc_task_create(taskmgr, 0, &task); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_dispatchmgr_create(dt_mctx, &dispatchmgr); + result = dns_dispatchmgr_create(dt_mctx, connect_nm, &dispatchmgr); assert_int_equal(result, ISC_R_SUCCESS); - ina.s_addr = htonl(INADDR_LOOPBACK); - isc_sockaddr_fromin(&local, &ina, 0); - result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &local, - 0, &dispatch); + result = dns_dispatch_createudp(dispatchmgr, taskmgr, &connect_addr, 0, + &dispatch); assert_int_equal(result, ISC_R_SUCCESS); /* * Create a local udp nameserver on the loopback. */ - result = isc_socket_create(socketmgr, AF_INET, isc_sockettype_udp, - &sock); - assert_int_equal(result, ISC_R_SUCCESS); - - ina.s_addr = htonl(INADDR_LOOPBACK); - isc_sockaddr_fromin(&local, &ina, 0); - result = isc_socket_bind(sock, &local, 0); - assert_int_equal(result, ISC_R_SUCCESS); - - result = isc_socket_getsockname(sock, &local); + result = isc_nm_listenudp(netmgr, &server_addr, nameserver, NULL, 0, + &sock); assert_int_equal(result, ISC_R_SUCCESS); region.base = rbuf; region.length = sizeof(rbuf); - result = isc_socket_recv(sock, ®ion, 1, task, nameserver, sock); - assert_int_equal(result, ISC_R_SUCCESS); - - result = dns_dispatch_addresponse(dispatch, 0, &local, task, response, - NULL, &id, &dispentry, socketmgr); + result = dns_dispatch_addresponse( + dispatch, 0, 10000, &server_addr, task, connected, + client_senddone, response, NULL, ®ion, &id, &dispentry); assert_int_equal(result, ISC_R_SUCCESS); memset(message, 0, sizeof(message)); @@ -304,19 +371,22 @@ dispatch_getnext(void **state) { region.base = message; region.length = sizeof(message); - result = isc_app_onrun(dt_mctx, task, startit, ®ion); + + result = isc_app_onrun(dt_mctx, task, startit, NULL); assert_int_equal(result, ISC_R_SUCCESS); result = isc_app_run(); assert_int_equal(result, ISC_R_SUCCESS); - assert_int_equal(atomic_load_acquire(&responses), 2); + assert_int_equal(atomic_load_acquire(&testdata.responses), 2); + + isc_nm_stoplistening(sock); + isc_nmsocket_close(&sock); + assert_null(sock); /* * Shutdown nameserver. */ - isc_socket_cancel(sock, task, ISC_SOCKCANCEL_RECV); - isc_socket_detach(&sock); isc_task_detach(&task); /* diff --git a/lib/dns/tests/dnstest.c b/lib/dns/tests/dnstest.c index 5a16027e48..fac3f25725 100644 --- a/lib/dns/tests/dnstest.c +++ b/lib/dns/tests/dnstest.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -96,10 +97,12 @@ cleanup_managers(void) { isc_task_shutdown(maintask); isc_task_destroy(&maintask); } + isc_managers_destroy(netmgr == NULL ? NULL : &netmgr, taskmgr == NULL ? NULL : &taskmgr, timermgr == NULL ? NULL : &timermgr, socketmgr == NULL ? NULL : &socketmgr); + if (app_running) { isc_app_finish(); } diff --git a/lib/dns/tests/dnstest.h b/lib/dns/tests/dnstest.h index 53c7c6529f..a2c32cc146 100644 --- a/lib/dns/tests/dnstest.h +++ b/lib/dns/tests/dnstest.h @@ -46,6 +46,7 @@ extern isc_taskmgr_t *taskmgr; extern isc_task_t *maintask; extern isc_timermgr_t *timermgr; extern isc_socketmgr_t *socketmgr; +extern isc_nm_t *netmgr; extern dns_zonemgr_t *zonemgr; extern bool app_running; extern int ncpus; diff --git a/lib/dns/tests/resolver_test.c b/lib/dns/tests/resolver_test.c index 1a6e0f6143..2989af3041 100644 --- a/lib/dns/tests/resolver_test.c +++ b/lib/dns/tests/resolver_test.c @@ -50,15 +50,15 @@ _setup(void **state) { result = dns_test_begin(NULL, true); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_dispatchmgr_create(dt_mctx, &dispatchmgr); + result = dns_dispatchmgr_create(dt_mctx, netmgr, &dispatchmgr); assert_int_equal(result, ISC_R_SUCCESS); result = dns_test_makeview("view", &view); assert_int_equal(result, ISC_R_SUCCESS); isc_sockaddr_any(&local); - result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &local, - 0, &dispatch); + result = dns_dispatch_createudp(dispatchmgr, taskmgr, &local, 0, + &dispatch); assert_int_equal(result, ISC_R_SUCCESS); return (0); @@ -80,8 +80,8 @@ static void mkres(dns_resolver_t **resolverp) { isc_result_t result; - result = dns_resolver_create(view, taskmgr, 1, 1, socketmgr, timermgr, - 0, dispatchmgr, dispatch, NULL, resolverp); + result = dns_resolver_create(view, taskmgr, 1, 1, netmgr, timermgr, 0, + dispatchmgr, dispatch, NULL, resolverp); assert_int_equal(result, ISC_R_SUCCESS); } diff --git a/lib/dns/view.c b/lib/dns/view.c index 27df703811..ed2045f131 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -634,6 +634,7 @@ view_flushanddetach(dns_view_t **viewp, bool flush) { dns_zone_t *mkzone = NULL, *rdzone = NULL; isc_refcount_destroy(&view->references); + if (!RESSHUTDOWN(view)) { dns_resolver_shutdown(view->resolver); } @@ -643,14 +644,14 @@ view_flushanddetach(dns_view_t **viewp, bool flush) { if (!REQSHUTDOWN(view)) { dns_requestmgr_shutdown(view->requestmgr); } - LOCK(&view->lock); - if (view->zonetable != NULL) { - if (view->flush) { - dns_zt_flushanddetach(&view->zonetable); - } else { - dns_zt_detach(&view->zonetable); - } + + if (view->zonetable != NULL && view->flush) { + dns_zt_flushanddetach(&view->zonetable); + } else if (view->zonetable != NULL) { + dns_zt_detach(&view->zonetable); } + + LOCK(&view->lock); if (view->managed_keys != NULL) { mkzone = view->managed_keys; view->managed_keys = NULL; @@ -796,9 +797,9 @@ dns_view_createzonetable(dns_view_t *view) { isc_result_t dns_view_createresolver(dns_view_t *view, isc_taskmgr_t *taskmgr, - unsigned int ntasks, unsigned int ndisp, - isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, - unsigned int options, dns_dispatchmgr_t *dispatchmgr, + unsigned int ntasks, unsigned int ndisp, isc_nm_t *nm, + isc_timermgr_t *timermgr, unsigned int options, + dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6) { isc_result_t result; @@ -815,8 +816,8 @@ dns_view_createresolver(dns_view_t *view, isc_taskmgr_t *taskmgr, } isc_task_setname(view->task, "view", view); - result = dns_resolver_create(view, taskmgr, ntasks, ndisp, socketmgr, - timermgr, options, dispatchmgr, dispatchv4, + result = dns_resolver_create(view, taskmgr, ntasks, ndisp, nm, timermgr, + options, dispatchmgr, dispatchv4, dispatchv6, &view->resolver); if (result != ISC_R_SUCCESS) { isc_task_detach(&view->task); @@ -841,11 +842,10 @@ dns_view_createresolver(dns_view_t *view, isc_taskmgr_t *taskmgr, atomic_fetch_and(&view->attributes, ~DNS_VIEWATTR_ADBSHUTDOWN); isc_refcount_increment(&view->weakrefs); - result = dns_requestmgr_create(view->mctx, timermgr, socketmgr, - dns_resolver_taskmgr(view->resolver), - dns_resolver_dispatchmgr(view->resolver), - dispatchv4, dispatchv6, - &view->requestmgr); + result = dns_requestmgr_create( + view->mctx, dns_resolver_taskmgr(view->resolver), + dns_resolver_dispatchmgr(view->resolver), dispatchv4, + dispatchv6, &view->requestmgr); if (result != ISC_R_SUCCESS) { dns_adb_shutdown(view->adb); dns_resolver_shutdown(view->resolver); @@ -2502,12 +2502,12 @@ dns_view_setviewcommit(dns_view_t *view) { if (view->managed_keys != NULL) { dns_zone_attach(view->managed_keys, &managed_keys); } - if (view->zonetable != NULL) { - dns_zt_setviewcommit(view->zonetable); - } UNLOCK(&view->lock); + if (view->zonetable != NULL) { + dns_zt_setviewcommit(view->zonetable); + } if (redirect != NULL) { dns_zone_setviewcommit(redirect); dns_zone_detach(&redirect); diff --git a/lib/dns/zt.c b/lib/dns/zt.c index 8ca9cd65aa..da4f222ab6 100644 --- a/lib/dns/zt.c +++ b/lib/dns/zt.c @@ -483,6 +483,7 @@ dns_zt_setviewcommit(dns_zt_t *zt) { REQUIRE(VALID_ZT(zt)); + RWLOCK(&zt->rwlock, isc_rwlocktype_read); dns_rbtnodechain_init(&chain); result = dns_rbtnodechain_first(&chain, zt->table, NULL, NULL); @@ -496,6 +497,7 @@ dns_zt_setviewcommit(dns_zt_t *zt) { } dns_rbtnodechain_invalidate(&chain); + RWUNLOCK(&zt->rwlock, isc_rwlocktype_read); } void diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index 19cc946bc3..c14607f81d 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -450,6 +450,16 @@ isc_nm_setstats(isc_nm_t *mgr, isc_stats_t *stats); * full range of socket-related stats counter numbers. */ +isc_result_t +isc_nm_checkaddr(const isc_sockaddr_t *addr, isc_socktype_t type); +/*%< + * Check whether the specified address is available on the local system + * by opening a socket and immediately closing it. + * + * Requires: + *\li 'addr' is not NULL. + */ + void isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, isc_nm_cb_t cb, void *cbarg, unsigned int timeout, diff --git a/lib/isc/managers.c b/lib/isc/managers.c index f86d4c8485..628dd33fa9 100644 --- a/lib/isc/managers.c +++ b/lib/isc/managers.c @@ -91,7 +91,7 @@ isc_managers_destroy(isc_nm_t **netmgrp, isc_taskmgr_t **taskmgrp, /* * If we have a taskmgr to clean up, then we must also have a netmgr. */ - REQUIRE(taskmgrp != NULL || netmgrp == NULL); + REQUIRE(taskmgrp == NULL || netmgrp != NULL); /* * The sequence of operations here is important: diff --git a/lib/isc/socket.c b/lib/isc/socket.c index c28b32165c..1f3b107bf9 100644 --- a/lib/isc/socket.c +++ b/lib/isc/socket.c @@ -2593,7 +2593,7 @@ isc_socket_close(isc_socket_t *sock) { int fd; isc_socketmgr_t *manager; isc__socketthread_t *thread; - fflush(stdout); + REQUIRE(VALID_SOCKET(sock)); LOCK(&sock->lock); diff --git a/lib/ns/interfacemgr.c b/lib/ns/interfacemgr.c index 045c74f9cc..2590794285 100644 --- a/lib/ns/interfacemgr.c +++ b/lib/ns/interfacemgr.c @@ -482,7 +482,7 @@ ns_interface_listentcp(ns_interface_t *ifp) { #if 0 #ifndef ISC_ALLOW_MAPPED - isc_socket_ipv6only(ifp->tcpsocket,true); + isc_socket_ipv6only(ifp->tcpsocket, true); #endif /* ifndef ISC_ALLOW_MAPPED */ if (ifp->dscp != -1) { diff --git a/lib/ns/tests/nstest.c b/lib/ns/tests/nstest.c index ffcf23adfa..8ece586163 100644 --- a/lib/ns/tests/nstest.c +++ b/lib/ns/tests/nstest.c @@ -233,7 +233,7 @@ create_managers(void) { CHECK(ns_server_create(mctx, matchview, &sctx)); - CHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); + CHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr)); CHECK(ns_interfacemgr_create(mctx, sctx, taskmgr, timermgr, socketmgr, netmgr, dispatchmgr, maintask, NULL, ncpus,