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;
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);
}
/* 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",
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);
}
}
}
- 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];
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) {
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);
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;
#include <isc/log.h>
#include <isc/managers.h>
#include <isc/mem.h>
+#include <isc/netmgr.h>
#include <isc/nonce.h>
#include <isc/parseint.h>
#include <isc/portset.h>
#include <isc/random.h>
#include <isc/region.h>
#include <isc/sockaddr.h>
-#include <isc/socket.h>
#include <isc/stdio.h>
#include <isc/string.h>
#include <isc/task.h>
-#include <isc/timer.h>
#include <isc/types.h>
#include <isc/util.h>
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;
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");
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) {
}
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);
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/net.h>
+#include <isc/netmgr.h>
#include <isc/parseint.h>
#include <isc/print.h>
#include <isc/sockaddr.h>
-#include <isc/socket.h>
#include <isc/task.h>
-#include <isc/timer.h>
#include <isc/util.h>
#include <dns/dispatch.h>
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];
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;
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));
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();
#include <isc/commandline.h>
#include <isc/managers.h>
#include <isc/mem.h>
+#include <isc/netmgr.h>
#include <isc/print.h>
#include <isc/sockaddr.h>
-#include <isc/socket.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/util.h>
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);
}
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) {
return (result);
}
-static char *algname;
+static char *algname = NULL;
static isc_result_t
printdata(dns_rdataset_t *rdataset, dns_name_t *owner) {
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;
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,
#include <isc/log.h>
#include <isc/managers.h>
#include <isc/mem.h>
+#include <isc/netmgr.h>
#include <isc/nonce.h>
#include <isc/print.h>
#include <isc/random.h>
#include <isc/sockaddr.h>
-#include <isc/socket.h>
#include <isc/task.h>
-#include <isc/timer.h>
#include <isc/util.h>
#include <dns/dispatch.h>
query = reqev->ev_arg;
- response = NULL;
dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
result = dns_request_getresponse(reqev->request, response,
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;
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));
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;
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);
#include <isc/print.h>
#include <isc/random.h>
#include <isc/sockaddr.h>
-#include <isc/socket.h>
#include <isc/task.h>
-#include <isc/timer.h>
#include <isc/util.h>
#include <dns/dispatch.h>
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;
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));
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;
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);
#include <isc/managers.h>
#include <isc/mem.h>
#include <isc/net.h>
+#include <isc/netmgr.h>
#include <isc/nonce.h>
#include <isc/parseint.h>
#include <isc/print.h>
#include <isc/random.h>
#include <isc/sockaddr.h>
-#include <isc/socket.h>
#include <isc/string.h>
#include <isc/task.h>
-#include <isc/timer.h>
#include <isc/util.h>
#include <dns/byaddr.h>
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;
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));
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();
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;
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;
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;
}
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;
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);
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;
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;
}
*/
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;
}
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;
}
/* 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;
}
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;
#include <isc/mem.h>
#include <isc/mutex.h>
+#include <isc/netmgr.h>
#include <isc/portset.h>
#include <isc/print.h>
#include <isc/random.h>
-#include <isc/socket.h>
#include <isc/stats.h>
#include <isc/string.h>
#include <isc/task.h>
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 {
isc_mem_t *mctx;
dns_acl_t *blackhole;
isc_stats_t *stats;
+ isc_nm_t *nm;
/* Locked by "lock". */
isc_mutex_t lock;
/* 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;
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;
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 */
/* 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', ' ')
#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 */
/*%
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 *
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
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)
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,
dns_dispatchmgr_t *mgr = NULL;
bool killmgr;
dispsocket_t *dispsocket = NULL;
- int i;
INSIST(event->ev_type == DNS_EVENT_DISPATCHCONTROL);
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);
}
}
-/*%
- * 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;
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;
-
- 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->local = disp->local;
+ dispsock->peer = *dest;
- 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;
/*%
* 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);
}
}
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);
}
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);
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) {
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));
}
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);
* 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;
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));
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;
}
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 &&
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),
*/
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);
}
* 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;
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));
/*
* 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;
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.
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),
/*
* 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;
* 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;
-
- disp->tcpbuffers++;
- rev->result = ISC_R_SUCCESS;
- rev->id = id;
- rev->addr = tcpmsg->address;
+ 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);
+ }
+
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.
*/
isc_mem_put(mgr->mctx, mgr->v6ports,
mgr->nv6ports * sizeof(in_port_t));
}
- 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);
- }
+ isc_nm_detach(&mgr->nm);
- *sockp = sock;
- return (ISC_R_SUCCESS);
+ isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(dns_dispatchmgr_t));
}
/*%
*/
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;
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);
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;
}
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));
}
* 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;
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:
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);
}
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;
- }
- }
-
- disp->ntasks = 1;
- disp->task[0] = NULL;
- result = isc_task_create(taskmgr, 50, &disp->task[0]);
- 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;
+ isc_sockaddr_anyofpf(&disp->local, pf);
+ isc_sockaddr_setport(&disp->local, 0);
}
- if (localaddr == NULL) {
- isc_sockaddr_anyofpf(&src, pf);
- } else {
- src = *localaddr;
- isc_sockaddr_setport(&src, 0);
- }
-
- result = isc_socket_bind(disp->socket, &src, 0);
+ result = isc_task_create(taskmgr, 50, &disp->task);
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.
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);
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;
(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)))
{
}
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;
}
}
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;
}
}
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 =
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;
/*
* Error returns.
*/
-kill_socket:
- if (disp->socket != NULL) {
- isc_socket_detach(&disp->socket);
- }
-deallocate_dispatch:
+cleanup:
dispatch_free(&disp);
return (result);
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);
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;
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);
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);
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) {
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);
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;
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;
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);
resp->item_out = true;
isc_task_send(resp->task, ISC_EVENT_PTR(&ev));
}
+
+ startrecv(disp, resp->dispsocket);
+
UNLOCK(&disp->lock);
+
return (ISC_R_SUCCESS);
}
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;
*resp = NULL;
disp = res->disp;
+ res->disp = NULL;
REQUIRE(VALID_DISPATCH(disp));
+
mgr = disp->mgr;
REQUIRE(VALID_DISPATCHMGR(mgr));
qid = mgr->qid;
}
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;
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.
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));
+
+ dns_dispatch_detach(&disp);
+}
+
+/*
+ * disp must be locked.
+ */
+static void
+startrecv(dns_dispatch_t *disp, dispsocket_t *dispsocket) {
+ isc_nmhandle_t *handle = NULL;
+
if (disp->shutting_down == 1) {
- do_cancel(disp);
- } else {
- (void)startrecv(disp, NULL);
+ return;
}
- killit = destroy_disp_ok(disp);
- UNLOCK(&disp->lock);
- if (killit) {
- isc_task_send(disp->task[0], &disp->ctlevent);
+ if (dispsocket == NULL) {
+ if (disp->socktype == isc_socktype_udp ||
+ disp->recv_pending != 0) {
+ return;
+ }
+ isc_nmhandle_attach(disp->handle, &handle);
+ } else {
+ handle = dispsocket->handle;
}
-}
-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;
+ switch (disp->socktype) {
+ case isc_socktype_udp:
+ isc_nm_read(handle, udp_recv, dispsocket);
+ break;
- 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;
- } else {
+ 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();
}
+}
+
+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);
+ }
- return (isc_socket_connect(sock, address, task, action, arg));
+ 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;
+
+ switch (disp->socktype) {
+ case isc_socktype_tcp:
+ if (disp->handle != NULL) {
+ break;
+ }
- sock = getentrysocket(resp);
+ 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;
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);
}
}
* 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;
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);
}
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);
}
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);
}
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;
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;
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
*
*\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.
*
* information regarding copyright ownership.
*/
+#include <isc/netmgr.h>
+
#ifndef DNS_DISPATCH_H
#define DNS_DISPATCH_H 1
#include <isc/buffer.h>
#include <isc/lang.h>
#include <isc/mutex.h>
+#include <isc/netmgr.h>
#include <isc/socket.h>
#include <isc/types.h>
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 */
};
/*%
#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:
*/
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.
*
*/
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
-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
*\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,
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.
*
*\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
*/
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
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);
*
*\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.
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.
*
*\li 'ntasks' > 0.
*
- *\li 'socketmgr' is a valid socket manager.
+ *\li 'nm' is a valid network manager.
*
*\li 'timermgr' is a valid timer manager.
*
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);
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.
*\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:
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/task.h>
-#include <isc/timer.h>
#include <isc/util.h>
#include <dns/acl.h>
/* 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;
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;
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);
***/
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) {
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);
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;
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);
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
}
}
- 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);
}
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
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,
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));
}
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;
}
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;
/* 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;
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);
return (DNS_R_BLACKHOLED);
}
- request = NULL;
result = new_request(mctx, &request);
if (result != ISC_R_SUCCESS) {
return (result);
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));
}
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;
}
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);
isc_buffer_t *buf2 = NULL;
isc_result_t result;
isc_region_t r;
- bool tcp = false;
dns_compress_t cctx;
bool cleanup_cctx = false;
* 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;
INSIST(!ISC_LINK_LINKED(request, link));
INSIST(request->dispentry == NULL);
INSIST(request->dispatch == NULL);
- INSIST(request->timer == NULL);
req_destroy(request);
}
*** 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));
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
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));
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;
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);
}
*/
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),
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;
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
}
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);
+ }
}
/*
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);
}
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)) {
destroy_query = true;
}
} else {
- switch (sevent->result) {
+ switch (eresult) {
case ISC_R_SUCCESS:
break;
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) {
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");
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;
}
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;
}
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) {
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];
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);
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;
/*
}
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;
}
goto cleanup_message;
}
- peer = NULL;
isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
(void)dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
}
}
- /*
- * 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.
*/
*/
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");
}
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);
}
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:
/*
* 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; "
}
/*
- * We are connected. Update the dispatcher and
+ * We are connected. Update the dispatcher and
* send the query.
*/
dns_dispatch_changeattributes(
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:
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);
}
}
}
fctx_increference(fctx);
-
result = fctx_query(fctx, addrinfo, fctx->options);
if (result != ISC_R_SUCCESS) {
fctx_done(fctx, result, __LINE__);
(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,
if (atomic_load_acquire(&fctx->res->exiting)) {
result = ISC_R_SHUTTINGDOWN;
FCTXTRACE("resolver shutting down");
+ rctx.finish = NULL;
rctx_done(&rctx, result);
return;
}
/*
* 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);
/*
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;
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,
}
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);
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));
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <uv.h>
#define UNIT_TESTING
#include <cmocka.h>
#include <isc/app.h>
#include <isc/buffer.h>
+#include <isc/managers.h>
#include <isc/refcount.h>
#include <isc/socket.h>
#include <isc/task.h>
-#include <isc/timer.h>
#include <isc/util.h>
#include <dns/dispatch.h>
#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);
}
_teardown(void **state) {
UNUSED(state);
+ isc_managers_destroy(&connect_nm, NULL, NULL, NULL);
+ assert_null(connect_nm);
+
dns_test_end();
return (0);
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);
reset();
}
-static void
-senddone(isc_task_t *task, isc_event_t *event) {
- isc_socket_t *sock = event->ev_arg;
+struct {
+ isc_nmhandle_t *handle;
+ atomic_uint_fast32_t responses;
+} testdata;
- UNUSED(task);
+static dns_dispatch_t *dispatch = NULL;
+static dns_dispentry_t *dispentry = NULL;
+static atomic_bool first = ATOMIC_VAR_INIT(true);
- isc_socket_detach(&sock);
- isc_event_free(&event);
+static void
+server_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
+ UNUSED(handle);
+ UNUSED(eresult);
+ UNUSED(cbarg);
+
+ 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;
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));
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);
/*
#include <isc/lex.h>
#include <isc/managers.h>
#include <isc/mem.h>
+#include <isc/netmgr.h>
#include <isc/os.h>
#include <isc/print.h>
#include <isc/socket.h>
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();
}
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;
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);
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);
}
dns_zone_t *mkzone = NULL, *rdzone = NULL;
isc_refcount_destroy(&view->references);
+
if (!RESSHUTDOWN(view)) {
dns_resolver_shutdown(view->resolver);
}
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;
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;
}
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);
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);
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);
REQUIRE(VALID_ZT(zt));
+ RWLOCK(&zt->rwlock, isc_rwlocktype_read);
dns_rbtnodechain_init(&chain);
result = dns_rbtnodechain_first(&chain, zt->table, NULL, NULL);
}
dns_rbtnodechain_invalidate(&chain);
+ RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
}
void
* 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,
/*
* 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:
int fd;
isc_socketmgr_t *manager;
isc__socketthread_t *thread;
- fflush(stdout);
+
REQUIRE(VALID_SOCKET(sock));
LOCK(&sock->lock);
#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) {
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,