}
}
- result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_taskmgr,
- &sa, attrs, &disp);
+ result = dns_dispatch_createudp(named_g_dispatchmgr, &sa, attrs, &disp);
if (result != ISC_R_SUCCESS) {
isc_sockaddr_t any;
char buf[ISC_SOCKADDR_FORMATSIZE];
server->heartbeat_interval = 0;
CHECKFATAL(dns_zonemgr_create(named_g_mctx, named_g_taskmgr,
- named_g_timermgr, named_g_socketmgr,
- named_g_netmgr, &server->zonemgr),
+ named_g_timermgr, named_g_netmgr,
+ &server->zonemgr),
"dns_zonemgr_create");
CHECKFATAL(dns_zonemgr_setsize(server->zonemgr, 1000), "dns_zonemgr_"
"setsize");
dispatch->dispatchgen = server->dispatchgen;
dispatch->dispatch = NULL;
- result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_taskmgr,
- &dispatch->addr, attrs,
- &dispatch->dispatch);
+ result = dns_dispatch_createudp(named_g_dispatchmgr, &dispatch->addr,
+ attrs, &dispatch->dispatch);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
if (have_ipv6) {
isc_sockaddr_any6(&bind_any6);
- result = dns_dispatch_createudp(dispatchmgr, taskmgr,
- &bind_any6, 0, &dispatchv6);
+ result = dns_dispatch_createudp(dispatchmgr, &bind_any6, 0,
+ &dispatchv6);
check_result(result, "dns_dispatch_createudp (v6)");
}
if (have_ipv4) {
isc_sockaddr_any(&bind_any);
- result = dns_dispatch_createudp(dispatchmgr, taskmgr, &bind_any,
- 0, &dispatchv4);
+ result = dns_dispatch_createudp(dispatchmgr, &bind_any, 0,
+ &dispatchv4);
check_result(result, "dns_dispatch_createudp (v4)");
}
RUNCHECK(isc_task_create(taskmgr, 0, &task));
RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr));
- RUNCHECK(dns_dispatch_createudp(dispatchmgr, taskmgr,
- have_src ? &srcaddr : &bind_any, 0,
- &dispatchv4));
+ RUNCHECK(dns_dispatch_createudp(
+ dispatchmgr, have_src ? &srcaddr : &bind_any, 0, &dispatchv4));
RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4,
NULL, &requestmgr));
RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr));
isc_sockaddr_any(&bind_any);
- RUNCHECK(dns_dispatch_createudp(dispatchmgr, taskmgr, &bind_any, 0,
- &dispatchv4));
+ RUNCHECK(
+ dns_dispatch_createudp(dispatchmgr, &bind_any, 0, &dispatchv4));
RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4,
NULL, &requestmgr));
RUNCHECK(isc_task_create(taskmgr, 0, &task));
RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr));
isc_sockaddr_any(&bind_any);
- RUNCHECK(dns_dispatch_createudp(dispatchmgr, taskmgr, &bind_any, 0,
- &dispatchv4));
+ RUNCHECK(
+ dns_dispatch_createudp(dispatchmgr, &bind_any, 0, &dispatchv4));
RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4,
NULL, &requestmgr));
} else {
isc_sockaddr_any6(&bind_any);
}
- RUNCHECK(dns_dispatch_createudp(dispatchmgr, taskmgr,
- have_src ? &srcaddr : &bind_any, 0,
- &dispatchvx));
+ RUNCHECK(dns_dispatch_createudp(
+ dispatchmgr, have_src ? &srcaddr : &bind_any, 0, &dispatchvx));
RUNCHECK(dns_requestmgr_create(
mctx, taskmgr, dispatchmgr, have_ipv4 ? dispatchvx : NULL,
static isc_result_t
getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr,
- isc_taskmgr_t *taskmgr, dns_dispatch_t **dispp,
- const isc_sockaddr_t *localaddr) {
+ 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, taskmgr, localaddr, 0,
- &disp);
+ result = dns_dispatch_createudp(dispatchmgr, localaddr, 0, &disp);
if (result == ISC_R_SUCCESS) {
*dispp = disp;
}
*/
client->dispatchv4 = NULL;
if (localaddr4 != NULL || localaddr6 == NULL) {
- result = getudpdispatch(AF_INET, client->dispatchmgr, taskmgr,
+ result = getudpdispatch(AF_INET, client->dispatchmgr,
&dispatchv4, localaddr4);
if (result == ISC_R_SUCCESS) {
client->dispatchv4 = dispatchv4;
client->dispatchv6 = NULL;
if (localaddr6 != NULL || localaddr4 == NULL) {
- result = getudpdispatch(AF_INET6, client->dispatchmgr, taskmgr,
+ result = getudpdispatch(AF_INET6, client->dispatchmgr,
&dispatchv6, localaddr6);
if (result == ISC_R_SUCCESS) {
client->dispatchv6 = dispatchv6;
#include <isc/random.h>
#include <isc/stats.h>
#include <isc/string.h>
-#include <isc/task.h>
#include <isc/time.h>
#include <isc/util.h>
#include <dns/acl.h>
#include <dns/dispatch.h>
-#include <dns/events.h>
#include <dns/log.h>
#include <dns/message.h>
#include <dns/stats.h>
unsigned int magic;
isc_refcount_t references;
dns_dispatch_t *disp;
- isc_task_t *task;
isc_nmhandle_t *handle; /*%< netmgr handle for UDP connection */
unsigned int bucket;
unsigned int timeout;
dns_messageid_t id;
isc_nm_cb_t connected;
isc_nm_cb_t sent;
+ isc_nm_recv_cb_t response;
isc_nm_cb_t timedout;
- isc_taskaction_t action;
void *arg;
bool canceled;
- ISC_LIST(dns_dispatchevent_t) items;
ISC_LINK(dns_dispentry_t) link;
ISC_LINK(dns_dispentry_t) alink;
};
/* Unlocked. */
unsigned int magic; /*%< magic */
dns_dispatchmgr_t *mgr; /*%< dispatch manager */
- 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_socktype_t socktype;
unsigned int attributes;
isc_refcount_t references;
- dns_dispatchevent_t failsafe_ev; /*%< failsafe cancel event */
- unsigned int shutdown_out : 1, recv_pending : 1;
+ unsigned int shutdown_out : 1;
ISC_LIST(dns_dispentry_t) active;
unsigned int nsockets;
#define DNS_DISPATCH_SOCKSQUOTA 3072
#endif /* ifndef DNS_DISPATCH_SOCKSQUOTA */
-/*%
- * Number of buffers available for all dispatches in the buffer
- * memory pool.
- */
-#ifndef DNS_DISPATCH_MAXBUFFERS
-#define DNS_DISPATCH_MAXBUFFERS 37268
-#endif /* ifndef DNS_DISPATCH_MAXBUFFERS */
-
/*%
* Quota to control the number of concurrent requests that can be handled
* by each TCP dispatch. (UDP dispatches do not currently support socket
void *arg);
static uint32_t
dns_hash(dns_qid_t *, const isc_sockaddr_t *, dns_messageid_t, in_port_t);
-static inline void
-free_devent(dns_dispatch_t *disp, dns_dispatchevent_t *ev);
-static inline dns_dispatchevent_t *
-allocate_devent(dns_dispatch_t *disp);
static void
dispatch_free(dns_dispatch_t **dispp);
static isc_result_t
-dispatch_createudp(dns_dispatchmgr_t *mgr, isc_taskmgr_t *taskmgr,
- const isc_sockaddr_t *localaddr, unsigned int attributes,
- dns_dispatch_t **dispp);
+dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
+ unsigned int attributes, dns_dispatch_t **dispp);
static void
qid_allocate(dns_dispatchmgr_t *mgr, dns_qid_t **qidp);
static void
msgbuf);
}
-static void
-request_log(dns_dispatch_t *disp, dns_dispentry_t *resp, int level,
- const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
-
-static void
-request_log(dns_dispatch_t *disp, dns_dispentry_t *resp, int level,
- const char *fmt, ...) {
- char msgbuf[2048];
- va_list ap;
-
- if (!isc_log_wouldlog(dns_lctx, level)) {
- return;
- }
-
- va_start(ap, fmt);
- vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
- va_end(ap);
-
- if (VALID_RESPONSE(resp)) {
- char peerbuf[256];
- 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,
- peerbuf, msgbuf);
- } else {
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,
- DNS_LOGMODULE_DISPATCH, level,
- "dispatch %p req/resp %p: %s", disp, resp,
- msgbuf);
- }
-}
-
/*
* Return a hash of the destination and message id.
*/
if (ISC_LINK_LINKED(resp, alink)) {
ISC_LIST_UNLINK(disp->active, resp, alink);
}
+
if (resp->handle != NULL) {
isc_nm_cancelread(resp->handle);
isc_nmhandle_detach(&resp->handle);
}
+
disp->nsockets--;
}
return (NULL);
}
-static void
-free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {
- REQUIRE(buf != NULL && len != 0);
-
- switch (disp->socktype) {
- case isc_socktype_tcp:
- INSIST(disp->tcpbuffers > 0);
- disp->tcpbuffers--;
- isc_mem_put(disp->mgr->mctx, buf, len);
- break;
- case isc_socktype_udp:
- LOCK(&disp->mgr->buffer_lock);
- INSIST(disp->mgr->buffers > 0);
- INSIST(len == DNS_DISPATCH_UDPBUFSIZE);
- disp->mgr->buffers--;
- UNLOCK(&disp->mgr->buffer_lock);
- isc_mem_put(disp->mgr->mctx, buf, len);
- break;
- default:
- INSIST(0);
- ISC_UNREACHABLE();
- }
-}
-
-static void *
-allocate_udp_buffer(dns_dispatch_t *disp) {
- LOCK(&disp->mgr->buffer_lock);
- if (disp->mgr->buffers >= DNS_DISPATCH_MAXBUFFERS) {
- UNLOCK(&disp->mgr->buffer_lock);
- return (NULL);
- }
- disp->mgr->buffers++;
- UNLOCK(&disp->mgr->buffer_lock);
-
- return (isc_mem_get(disp->mgr->mctx, DNS_DISPATCH_UDPBUFSIZE));
-}
-
-static inline void
-free_devent(dns_dispatch_t *disp, dns_dispatchevent_t *ev) {
- /* failsafe_ev is not allocated */
- if (&(disp->failsafe_ev) == ev) {
- INSIST(disp->shutdown_out == 1);
- disp->shutdown_out = 0;
-
- return;
- }
-
- if (ev->region.base != NULL) {
- free_buffer(disp, ev->region.base, ev->region.length);
- ev->region.base = NULL;
- ev->region.length = 0;
- }
-
- isc_mem_put(disp->mgr->mctx, ev, sizeof(*ev));
-
- dns_dispatch_detach(&disp);
-}
-
-static inline dns_dispatchevent_t *
-allocate_devent(dns_dispatch_t *disp) {
- dns_dispatchevent_t *ev = NULL;
-
- ev = isc_mem_get(disp->mgr->mctx, sizeof(*ev));
-
- *ev = (dns_dispatchevent_t){ 0 };
-
- dns_dispatch_attach(disp, &ev->dispatch);
-
- ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, 0, NULL, NULL, NULL, NULL,
- NULL);
- return (ev);
-}
-
static void
dispentry_attach(dns_dispentry_t *resp, dns_dispentry_t **respp) {
REQUIRE(VALID_RESPONSE(resp));
isc_refcount_destroy(&resp->references);
- isc_task_detach(&resp->task);
isc_mem_put(disp->mgr->mctx, resp, sizeof(*resp));
dns_dispatch_detach(&disp);
isc_result_t dres;
isc_buffer_t source;
unsigned int flags;
- dns_dispatchevent_t *rev = NULL;
isc_sockaddr_t peer;
isc_netaddr_t netaddr;
int match;
- isc_taskaction_t action = NULL;
+ isc_nm_recv_cb_t response = NULL;
bool nomore = true;
REQUIRE(VALID_RESPONSE(resp));
+ REQUIRE(VALID_DISPATCH(resp->disp));
disp = resp->disp;
if (isc_log_wouldlog(dns_lctx, LVL(90))) {
LOCK(&disp->mgr->buffer_lock);
- dispatch_log(disp, LVL(90), "got packet: requests %d, recvs %d",
- disp->requests, disp->recv_pending);
+ dispatch_log(disp, LVL(90), "got packet: requests %d",
+ disp->requests);
UNLOCK(&disp->mgr->buffer_lock);
}
/*
* This dispatcher is shutting down.
*/
- goto unlock;
+ goto sendevent;
}
if (!ISC_LINK_LINKED(resp, alink)) {
}
sendevent:
- rev = allocate_devent(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.
*/
- rev->result = eresult;
- 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);
- }
-
- ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, DNS_EVENT_DISPATCH,
- resp->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);
-
- action = resp->action;
+ response = resp->response;
unlock:
UNLOCK(&disp->lock);
- if (action != NULL) {
- action(resp->task, (isc_event_t *)rev);
+ if (response != NULL) {
+ response(handle, eresult, region, resp->arg);
}
if (nomore) {
dispentry_detach(&resp);
}
- return;
}
/*
static void
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_dispentry_t *resp0 = (dns_dispentry_t *)arg;
+ dns_dispentry_t *resp = NULL;
+ dns_dispatch_t *disp = NULL;
dns_messageid_t id;
isc_result_t dres;
unsigned int flags;
- dns_dispentry_t *resp = NULL;
- dns_dispatchevent_t *rev = NULL;
unsigned int bucket;
dns_qid_t *qid = NULL;
int level;
char buf[ISC_SOCKADDR_FORMATSIZE];
isc_buffer_t source;
isc_sockaddr_t peer;
- isc_taskaction_t action = NULL;
- REQUIRE(VALID_DISPATCH(disp));
+ REQUIRE(VALID_RESPONSE(resp0));
+ REQUIRE(VALID_DISPATCH(resp0->disp));
+
+ disp = resp0->disp;
qid = disp->mgr->qid;
LOCK(&disp->lock);
- dispatch_log(disp, LVL(90),
- "got TCP packet: requests %d, buffers %d, recvs %d",
- disp->requests, disp->tcpbuffers, disp->recv_pending);
-
- INSIST(disp->recv_pending != 0);
- disp->recv_pending = 0;
+ dispatch_log(disp, LVL(90), "got TCP packet: requests %d, buffers %d",
+ disp->requests, disp->tcpbuffers);
peer = isc_nmhandle_peeraddr(handle);
/*
* Time out the first active response for which
* no event has already been sent.
+ * FIXME: The code doesn't match the description
*/
for (resp = ISC_LIST_HEAD(disp->active); resp != NULL;
resp = ISC_LIST_NEXT(resp, alink))
{
ISC_LIST_UNLINK(disp->active, resp, alink);
ISC_LIST_APPEND(disp->active, resp, alink);
- goto sendevent;
+ break;
}
break;
dispatch_log(disp, LVL(90), "search for response in bucket %d: %s",
bucket, (resp == NULL ? "not found" : "found"));
UNLOCK(&qid->lock);
- if (resp == NULL) {
- goto next;
- }
-
-sendevent:
- rev = allocate_devent(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.
- */
- rev->result = eresult;
- 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 (resp == NULL) {
+ goto unlock;
}
- ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, DNS_EVENT_DISPATCH,
- resp->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);
-
- action = resp->action;
-
next:
- startrecv(disp, NULL);
+ startrecv(disp, resp0);
unlock:
isc_nmhandle_detach(&handle);
UNLOCK(&disp->lock);
- dns_dispatch_detach(&disp);
+ dispentry_detach(&resp0);
- if (action != NULL) {
- action(resp->task, (isc_event_t *)rev);
+ if (resp != NULL) {
+ resp->response(handle, eresult, region, resp->arg);
}
}
isc_mutex_init(&disp->lock);
- /* failsafe_ev is not allocated */
- ISC_EVENT_INIT(&disp->failsafe_ev, sizeof(disp->failsafe_ev), 0, NULL,
- 0, NULL, NULL, NULL, NULL, NULL);
-
disp->magic = DISPATCH_MAGIC;
*dispp = disp;
REQUIRE(VALID_DISPATCHMGR(mgr));
INSIST(disp->requests == 0);
- INSIST(disp->recv_pending == 0);
INSIST(ISC_LIST_EMPTY(disp->active));
isc_mutex_destroy(&disp->lock);
}
isc_result_t
-dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_taskmgr_t *taskmgr,
- const isc_sockaddr_t *localaddr,
+dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
const isc_sockaddr_t *destaddr, unsigned int attributes,
isc_dscp_t dscp, dns_dispatch_t **dispp) {
- isc_result_t result;
dns_dispatch_t *disp = NULL;
int pf;
isc_sockaddr_setport(&disp->local, 0);
}
- result = isc_task_create(taskmgr, 50, &disp->task);
- if (result != ISC_R_SUCCESS) {
- goto cleanup;
- }
-
- 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);
}
*dispp = disp;
return (ISC_R_SUCCESS);
-
-cleanup:
- dispatch_free(&disp);
-
- UNLOCK(&mgr->lock);
-
- return (result);
}
#define ATTRMATCH(_a1, _a2, _mask) (((_a1) & (_mask)) == ((_a2) & (_mask)))
}
isc_result_t
-dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_taskmgr_t *taskmgr,
- const isc_sockaddr_t *localaddr, unsigned int attributes,
- dns_dispatch_t **dispp) {
+dns_dispatch_createudp(dns_dispatchmgr_t *mgr, 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(localaddr != NULL);
- REQUIRE(taskmgr != NULL);
REQUIRE(dispp != NULL && *dispp == NULL);
LOCK(&mgr->lock);
- result = dispatch_createudp(mgr, taskmgr, localaddr, attributes, &disp);
+ result = dispatch_createudp(mgr, localaddr, attributes, &disp);
if (result == ISC_R_SUCCESS) {
*dispp = disp;
}
}
static isc_result_t
-dispatch_createudp(dns_dispatchmgr_t *mgr, isc_taskmgr_t *taskmgr,
- const isc_sockaddr_t *localaddr, unsigned int attributes,
- dns_dispatch_t **dispp) {
+dispatch_createudp(dns_dispatchmgr_t *mgr, 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_sockaddr_t sa_any;
}
disp->local = *localaddr;
- result = isc_task_create(taskmgr, 0, &disp->task);
- if (result != ISC_R_SUCCESS) {
- goto cleanup;
- }
/*
* Append it to the dispatcher list.
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);
*dispp = disp;
isc_nmhandle_detach(&disp->handle);
}
- isc_task_detach(&disp->task);
-
dispatch_free(&disp);
/* Because dispatch uses mgr->mctx, we must detach after freeing
dispatch_log(disp, LVL(90), "detach: refcount %" PRIuFAST32, ref - 1);
if (ref == 1) {
LOCK(&disp->lock);
- REQUIRE(disp->recv_pending == 0);
REQUIRE(ISC_LIST_EMPTY(disp->active));
UNLOCK(&disp->lock);
isc_result_t
dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
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_nm_cb_t timedout, void *arg, dns_messageid_t *idp,
+ isc_nm_cb_t connected, isc_nm_cb_t sent,
+ isc_nm_recv_cb_t response, isc_nm_cb_t timedout,
+ void *arg, dns_messageid_t *idp,
dns_dispentry_t **resp) {
dns_dispentry_t *res = NULL;
dns_qid_t *qid = NULL;
unsigned int bucket;
bool ok = false;
int i = 0;
- isc_taskaction_t oldest_action = NULL;
- isc_task_t *oldest_task = NULL;
- isc_event_t *oldest_ev = NULL;
+ isc_nm_recv_cb_t oldest_response = NULL;
REQUIRE(VALID_DISPATCH(disp));
- REQUIRE(task != NULL);
REQUIRE(dest != NULL);
REQUIRE(resp != NULL && *resp == NULL);
REQUIRE(idp != NULL);
disp->nsockets > DNS_DISPATCH_SOCKSQUOTA)
{
dns_dispentry_t *oldest = NULL;
- dns_dispatchevent_t *rev = NULL;
/*
* Kill oldest outstanding query if the number of sockets
*/
oldest = ISC_LIST_HEAD(disp->active);
if (oldest != NULL) {
- rev = allocate_devent(oldest->disp);
- rev->buffer.base = NULL;
- rev->result = ISC_R_CANCELED;
- ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL,
- DNS_EVENT_DISPATCH, oldest->action,
- oldest->arg, oldest, NULL, NULL);
-
- oldest_action = oldest->action;
- oldest_task = oldest->task;
- oldest_ev = (isc_event_t *)rev;
-
+ oldest_response = oldest->response;
inc_stats(disp->mgr, dns_resstatscounter_dispabort);
}
}
.connected = connected,
.sent = sent,
.timedout = timedout,
- .action = action,
+ .response = response,
.arg = arg };
isc_refcount_init(&res->references, 1);
- ISC_LIST_INIT(res->items);
ISC_LINK_INIT(res, link);
ISC_LINK_INIT(res, alink);
dns_dispatch_attach(disp, &res->disp);
- isc_task_attach(task, &res->task);
-
res->id = id;
res->bucket = bucket;
res->magic = RESPONSE_MAGIC;
ISC_LIST_APPEND(qid->qid_table[bucket], res, link);
UNLOCK(&qid->lock);
- request_log(disp, res, LVL(90), "attached to task %p", res->task);
-
inc_stats(disp->mgr, (disp->socktype == isc_socktype_udp)
? dns_resstatscounter_disprequdp
: dns_resstatscounter_dispreqtcp);
UNLOCK(&disp->lock);
- if (oldest_action != NULL) {
- oldest_action(oldest_task, oldest_ev);
+ if (oldest_response != NULL) {
+ oldest_response(res->handle, ISC_R_CANCELED, NULL, res->arg);
}
*idp = id;
}
isc_result_t
-dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent) {
+dns_dispatch_getnext(dns_dispentry_t *resp) {
dns_dispatch_t *disp = NULL;
- dns_dispatchevent_t *ev = NULL;
- isc_taskaction_t action = NULL;
REQUIRE(VALID_RESPONSE(resp));
- REQUIRE(sockevent != NULL && *sockevent != NULL);
disp = resp->disp;
REQUIRE(VALID_DISPATCH(disp));
- ev = *sockevent;
- *sockevent = NULL;
-
LOCK(&disp->lock);
- free_devent(disp, ev);
-
- ev = ISC_LIST_HEAD(resp->items);
- if (ev != NULL) {
- ISC_LIST_UNLINK(resp->items, ev, ev_link);
- ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, DNS_EVENT_DISPATCH,
- resp->action, resp->arg, resp, NULL, NULL);
- request_log(disp, resp, LVL(90),
- "[c] Sent event %p buffer %p len %d to task %p", ev,
- ev->buffer.base, ev->buffer.length, resp->task);
-
- action = resp->action;
- }
-
startrecv(disp, resp);
UNLOCK(&disp->lock);
- if (action != NULL) {
- action(resp->task, (isc_event_t *)ev);
- }
-
return (ISC_R_SUCCESS);
}
void
-dns_dispatch_removeresponse(dns_dispentry_t **respp,
- dns_dispatchevent_t **sockevent) {
+dns_dispatch_removeresponse(dns_dispentry_t **respp) {
dns_dispatchmgr_t *mgr = NULL;
dns_dispatch_t *disp = NULL;
dns_dispentry_t *resp = NULL;
- dns_dispatchevent_t *ev = NULL;
dns_qid_t *qid = NULL;
REQUIRE(respp != NULL);
qid = mgr->qid;
- if (sockevent != NULL) {
- REQUIRE(*sockevent != NULL);
- ev = *sockevent;
- *sockevent = NULL;
- } else {
- ev = NULL;
- }
-
LOCK(&disp->lock);
INSIST(disp->requests > 0);
disp->requests--;
UNLOCK(&qid->lock);
UNLOCK(&disp->lock);
- if (ev != NULL) {
- free_devent(disp, ev);
- }
-
- /*
- * Free any buffered responses as well
- */
- ev = ISC_LIST_HEAD(resp->items);
- while (ev != NULL) {
- ISC_LIST_UNLINK(resp->items, ev, ev_link);
- free_devent(disp, ev);
- ev = ISC_LIST_HEAD(resp->items);
- }
-
dispentry_detach(respp);
}
*/
static void
startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp) {
- isc_nmhandle_t *handle = NULL;
- dns_dispentry_t *tmp_resp = NULL;
- dns_dispatch_t *tmp_disp = NULL;
-
switch (disp->socktype) {
case isc_socktype_udp:
- REQUIRE(resp != NULL);
- REQUIRE(resp->handle != NULL);
+ REQUIRE(resp != NULL && resp->handle != NULL);
- dispentry_attach(resp, &tmp_resp);
-
- /* resp->handle is detached in _removeresponse() */
+ dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
isc_nm_read(resp->handle, udp_recv, resp);
-
break;
+
case isc_socktype_tcp:
- if (resp != NULL) {
- REQUIRE(resp->handle == NULL);
+ REQUIRE(resp != NULL && resp->handle == NULL);
+ REQUIRE(disp->handle != NULL);
+
+ if (isc_nmhandle_timer_running(disp->handle)) {
+ isc_nmhandle_settimeout(disp->handle, resp->timeout);
+ break;
}
- isc_nmhandle_attach(disp->handle, &handle);
- dns_dispatch_attach(disp, &tmp_disp);
- isc_nm_read(handle, tcp_recv, disp);
- INSIST(disp->recv_pending == 0);
- disp->recv_pending = 1;
+ isc_nmhandle_attach(disp->handle, &(isc_nmhandle_t *){ NULL });
+ dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
+ isc_nm_read(disp->handle, tcp_recv, resp);
break;
+
default:
INSIST(0);
ISC_UNREACHABLE();
goto detach;
}
- if (MGR_IS_SHUTTINGDOWN(disp->mgr)) {
- eresult = ISC_R_SHUTTINGDOWN;
- }
-
- /*
- * Start listening on success
- */
if (eresult == ISC_R_SUCCESS) {
switch (disp->socktype) {
case isc_socktype_udp:
startrecv(disp, resp);
break;
case isc_socktype_tcp:
- if (disp->handle == NULL) {
- LOCK(&disp->lock);
- isc_nmhandle_attach(handle, &disp->handle);
- disp->attributes |= DNS_DISPATCHATTR_CONNECTED;
- UNLOCK(&disp->lock);
- startrecv(disp, resp);
- }
+ REQUIRE(disp->handle == NULL);
+ LOCK(&disp->lock);
+ isc_nmhandle_attach(handle, &disp->handle);
+ disp->attributes |= DNS_DISPATCHATTR_CONNECTED;
+ UNLOCK(&disp->lock);
+ startrecv(disp, resp);
break;
default:
INSIST(0);
}
}
+ if (MGR_IS_SHUTTINGDOWN(disp->mgr)) {
+ eresult = ISC_R_SHUTTINGDOWN;
+ }
+
if (resp->connected != NULL) {
resp->connected(handle, eresult, resp->arg);
}
switch (disp->socktype) {
case isc_socktype_tcp:
INSIST(disp->handle == NULL);
- if (disp->handle != NULL) {
- /* We are already connected */
- break;
- }
-
isc_nm_tcpdnsconnect(disp->mgr->nm, &disp->local, &disp->peer,
disp_connected, resp, resp->timeout, 0);
break;
void
dns_dispatch_send(dns_dispentry_t *resp, isc_region_t *r, isc_dscp_t dscp) {
isc_nmhandle_t *handle = NULL;
- dns_dispentry_t *tmp = NULL;
REQUIRE(VALID_RESPONSE(resp));
}
#endif
- dispentry_attach(resp, &tmp); /* detached in send_done() */
+ dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
isc_nm_send(handle, r, send_done, resp);
}
}
isc_result_t
-dns_dispatchset_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
- dns_dispatch_t *source, dns_dispatchset_t **dsetp,
- int n) {
+dns_dispatchset_create(isc_mem_t *mctx, 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, taskmgr, &source->local,
+ result = dispatch_createudp(mgr, &source->local,
source->attributes,
&dset->dispatches[i]);
if (result != ISC_R_SUCCESS) {
ISC_LANG_BEGINDECLS
-/*%
- * This event is sent to a task when a response comes in.
- * No part of this structure should ever be modified by the caller,
- * other than parts of the buffer. The holy parts of the buffer are
- * the base and size of the buffer. All other parts of the buffer may
- * be used. On event delivery the used region contains the packet.
- *
- * "id" is the received message id,
- *
- * "addr" is the host that sent it to us,
- *
- * "buffer" holds state on the received data.
- *
- * The "free" routine for this event will clean up itself as well as
- * any buffer space allocated from common pools.
- */
-
-struct dns_dispatchevent {
- ISC_EVENT_COMMON(dns_dispatchevent_t); /*%< standard event common */
- isc_result_t result; /*%< result code */
- isc_region_t region; /*%< data region */
- isc_buffer_t buffer; /*%< data buffer */
- dns_dispatch_t *dispatch;
-};
-
/*%
* This is a set of one or more dispatches which can be retrieved
* round-robin fashion.
*/
isc_result_t
-dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_taskmgr_t *taskmgr,
- const isc_sockaddr_t *localaddr, unsigned int attributes,
- dns_dispatch_t **dispp);
+dns_dispatch_createudp(dns_dispatchmgr_t *mgr, 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_taskmgr_t *taskmgr,
- const isc_sockaddr_t *localaddr,
+dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
const isc_sockaddr_t *destaddr, unsigned int attributes,
isc_dscp_t dscp, dns_dispatch_t **dispp);
/*%<
*
*\li sock is a valid.
*
- *\li task is a valid task that can be used internally to this dispatcher.
- *
* Returns:
*\li ISC_R_SUCCESS -- success.
*
isc_result_t
dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
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_nm_cb_t timedout, void *arg, dns_messageid_t *idp,
+ isc_nm_cb_t connected, isc_nm_cb_t sent,
+ isc_nm_recv_cb_t response, isc_nm_cb_t timedout,
+ 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.
+ * with the dispatch entry object.
*
* The 'connected' and 'sent' callbacks are run to inform the caller when
* the connect and send functions are complete. The 'timedout' callback
* is run to inform the caller that a read has timed out; it may optionally
- * reset the read timer.
- *
- * 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.
+ * reset the read timer. The 'response' callback is run for recv results
+ * (response packets, timeouts, or cancellations).
*
- * All three callback functions are sent 'arg' as a parameter.
+ * All the callback functions are sent 'arg' as a parameter.
*
* Requires:
*\li "idp" be non-NULL.
*
- *\li "task" "action" and "arg" be set as appropriate.
+ *\li "response" and "arg" be set as appropriate.
*
*\li "dest" be non-NULL and valid.
*
*/
void
-dns_dispatch_removeresponse(dns_dispentry_t ** resp,
- dns_dispatchevent_t **sockevent);
+dns_dispatch_removeresponse(dns_dispentry_t **resp);
/*%<
* Stops the flow of responses for the provided id and destination.
- * If "sockevent" is non-NULL, the dispatch event and associated buffer is
- * also returned to the system.
*
* Requires:
*\li "resp" != NULL and "*resp" contain a value previously allocated
* by dns_dispatch_addresponse();
- *
- *\li May only be called from within the task given as the 'task'
- * argument to dns_dispatch_addresponse() when allocating '*resp'.
*/
isc_result_t
*/
isc_result_t
-dns_dispatchset_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
- dns_dispatch_t *source, dns_dispatchset_t **dsetp,
- int n);
+dns_dispatchset_create(isc_mem_t *mctx, 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_result_t
-dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent);
+dns_dispatch_getnext(dns_dispentry_t *resp);
/*%<
- * Free the sockevent and trigger the sending of the next item off the
- * dispatch queue if present.
+ * Trigger the sending of the next item off the dispatch queue if present.
*
* Requires:
*\li resp is valid
- *\li *sockevent to be valid
*/
ISC_LANG_ENDDECLS
typedef struct dns_sdlzimplementation dns_sdlzimplementation_t;
typedef struct dns_decompress dns_decompress_t;
typedef struct dns_dispatch dns_dispatch_t;
-typedef struct dns_dispatchevent dns_dispatchevent_t;
typedef struct dns_dispatchlist dns_dispatchlist_t;
typedef struct dns_dispatchset dns_dispatchset_t;
typedef struct dns_dispatchmgr dns_dispatchmgr_t;
isc_result_t
dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
- isc_nm_t *netmgr, dns_zonemgr_t **zmgrp);
+ isc_timermgr_t *timermgr, isc_nm_t *netmgr,
+ dns_zonemgr_t **zmgrp);
/*%<
* Create a zone manager. Note: the zone manager will not be able to
* manage any zones until dns_zonemgr_setsize() has been run.
req_render(dns_message_t *message, isc_buffer_t **buffer, unsigned int options,
isc_mem_t *mctx);
static void
-req_response(isc_task_t *task, isc_event_t *event);
+req_response(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
+ void *arg);
static void
req_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *arg);
static void
}
}
- result = dns_dispatch_createtcp(requestmgr->dispatchmgr,
- requestmgr->taskmgr, srcaddr, destaddr,
- 0, dscp, dispatchp);
+ result = dns_dispatch_createtcp(requestmgr->dispatchmgr, srcaddr,
+ destaddr, 0, dscp, dispatchp);
return (result);
}
return (ISC_R_SUCCESS);
}
- return (dns_dispatch_createudp(requestmgr->dispatchmgr,
- requestmgr->taskmgr, srcaddr, 0,
+ return (dns_dispatch_createudp(requestmgr->dispatchmgr, srcaddr, 0,
dispatchp));
}
dns_request_t **requestp) {
dns_request_t *request = NULL;
isc_task_t *tclone = NULL;
+ dns_request_t *rclone = NULL;
isc_result_t result;
- isc_mem_t *mctx;
+ isc_mem_t *mctx = NULL;
dns_messageid_t id;
bool tcp = false;
bool newtcp = false;
return (DNS_R_BLACKHOLED);
}
- request = NULL;
result = new_request(mctx, &request);
if (result != ISC_R_SUCCESS) {
return (result);
dispopt |= DNS_DISPATCHOPT_FIXEDID;
}
- dns_request_t *tmp = NULL;
- req_attach(request, &tmp);
-
+ req_attach(request, &rclone);
result = dns_dispatch_addresponse(
- request->dispatch, dispopt, request->timeout, destaddr, task,
+ request->dispatch, dispopt, request->timeout, destaddr,
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;
connected = false;
+ req_detach(&rclone);
dns_dispatch_detach(&request->dispatch);
goto again;
}
request->flags |= DNS_REQUEST_F_CONNECTING | DNS_REQUEST_F_TCP;
} else {
req_send(request);
+ req_detach(&rclone);
}
req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p", request);
dns_request_t **requestp) {
dns_request_t *request = NULL;
isc_task_t *tclone = NULL;
+ dns_request_t *rclone = NULL;
isc_result_t result;
- isc_mem_t *mctx;
+ isc_mem_t *mctx = NULL;
dns_messageid_t id;
bool tcp = false;
bool connected = false;
goto cleanup;
}
- dns_request_t *tmp = NULL;
- req_attach(request, &tmp);
-
+ req_attach(request, &rclone);
result = dns_dispatch_addresponse(
- request->dispatch, 0, request->timeout, destaddr, task,
- req_connected, req_senddone, req_response, req_timeout, request,
- &id, &request->dispentry);
+ request->dispatch, 0, request->timeout, destaddr, req_connected,
+ req_senddone, req_response, req_timeout, request, &id,
+ &request->dispentry);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
/*
* Try again using TCP.
*/
+ req_detach(&rclone);
dns_message_renderreset(message);
- dns_dispatch_removeresponse(&request->dispentry, NULL);
+ dns_dispatch_removeresponse(&request->dispentry);
dns_dispatch_detach(&request->dispatch);
options |= DNS_REQUESTOPT_TCP;
tcp = true;
request->flags |= DNS_REQUEST_F_CONNECTING | DNS_REQUEST_F_TCP;
} else {
req_send(request);
+ req_detach(&rclone);
}
req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p", request);
if (tclone != NULL) {
isc_task_detach(&tclone);
}
+ if (rclone != NULL) {
+ req_detach(&rclone);
+ }
req_detach(&request);
req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s",
dns_result_totext(result));
if (request->dispentry != NULL) {
dns_dispatch_cancel(request->dispentry);
- dns_dispatch_removeresponse(&request->dispentry, NULL);
+ dns_dispatch_removeresponse(&request->dispentry);
}
dns_dispatch_detach(&request->dispatch);
request->flags &= ~DNS_REQUEST_F_CONNECTING;
if (eresult == ISC_R_TIMEDOUT) {
- dns_dispatch_removeresponse(&request->dispentry, NULL);
+ dns_dispatch_removeresponse(&request->dispentry);
dns_dispatch_detach(&request->dispatch);
send_if_done(request, eresult);
} else if (DNS_REQUEST_CANCELED(request)) {
}
static void
-req_response(isc_task_t *task, isc_event_t *event) {
- isc_result_t result;
- dns_request_t *request = event->ev_arg;
- dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
- isc_region_t r;
+req_response(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
+ void *arg) {
+ dns_request_t *request = (dns_request_t *)arg;
- REQUIRE(VALID_REQUEST(request));
- REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
+ UNUSED(handle);
+
+ if (result == ISC_R_CANCELED) {
+ return;
+ }
- UNUSED(task);
+ REQUIRE(VALID_REQUEST(request));
req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request,
- dns_result_totext(devent->result));
+ dns_result_totext(result));
LOCK(&request->requestmgr->locks[request->hash]);
- result = devent->result;
if (result != ISC_R_SUCCESS) {
goto done;
}
/*
- * Copy buffer to request.
+ * Copy region to request.
*/
- isc_buffer_usedregion(&devent->buffer, &r);
- isc_buffer_allocate(request->mctx, &request->answer, r.length);
- result = isc_buffer_copyregion(request->answer, &r);
+ isc_buffer_allocate(request->mctx, &request->answer, region->length);
+ result = isc_buffer_copyregion(request->answer, region);
if (result != ISC_R_SUCCESS) {
isc_buffer_free(&request->answer);
}
/*
* Cleanup.
*/
- dns_dispatch_removeresponse(&request->dispentry, &devent);
+ dns_dispatch_removeresponse(&request->dispentry);
request_cancel(request);
/*
isc_event_free((isc_event_t **)&request->event);
}
if (request->dispentry != NULL) {
- dns_dispatch_removeresponse(&request->dispentry, NULL);
+ dns_dispatch_removeresponse(&request->dispentry);
}
if (request->dispatch != NULL) {
dns_dispatch_detach(&request->dispatch);
char *info;
isc_mem_t *mctx;
isc_stdtime_t now;
+ isc_task_t *task;
/* Atomic */
isc_refcount_t references;
static isc_result_t
resquery_send(resquery_t *query);
static void
-resquery_response(isc_task_t *task, isc_event_t *event);
+resquery_response(isc_nmhandle_t *handle, isc_result_t eresult,
+ isc_region_t *region, void *arg);
static void
resquery_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg);
static void
*/
typedef struct respctx {
- isc_task_t *task;
- dns_dispatchevent_t *devent;
resquery_t *query;
fetchctx_t *fctx;
isc_result_t result;
+ isc_buffer_t buffer;
unsigned int retryopts; /* updated options to pass to
* fctx_query() when resending */
} respctx_t;
static void
-rctx_respinit(isc_task_t *task, dns_dispatchevent_t *devent, resquery_t *query,
- fetchctx_t *fctx, respctx_t *rctx);
+rctx_respinit(resquery_t *query, fetchctx_t *fctx, isc_result_t result,
+ isc_region_t *region, respctx_t *rctx);
static void
rctx_answer_init(respctx_t *rctx);
dns_tsigkey_detach(&query->tsigkey);
}
+ if (query->dispentry != NULL) {
+ dns_dispatch_removeresponse(&query->dispentry);
+ }
+
if (query->dispatch != NULL) {
dns_dispatch_detach(&query->dispatch);
}
}
static void
-fctx_cancelquery(resquery_t *query, dns_dispatchevent_t **deventp,
- isc_time_t *finish, bool no_response, bool age_untried) {
+fctx_cancelquery(resquery_t *query, isc_time_t *finish, bool no_response,
+ bool age_untried) {
fetchctx_t *fctx = NULL;
unsigned int rtt, rttms;
unsigned int factor;
*/
if (query->dispentry != NULL) {
dns_dispatch_cancel(query->dispentry);
- dns_dispatch_removeresponse(&query->dispentry, deventp);
+ dns_dispatch_removeresponse(&query->dispentry);
}
if (ISC_LINK_LINKED(query, link)) {
static void
fctx_cancelqueries(fetchctx_t *fctx, bool no_response, bool age_untried) {
- resquery_t *query, *next_query;
+ resquery_t *query = NULL, *next_query = NULL;
FCTXTRACE("cancelqueries");
for (query = ISC_LIST_HEAD(fctx->queries); query != NULL;
query = next_query) {
next_query = ISC_LIST_NEXT(query, link);
- fctx_cancelquery(query, NULL, NULL, no_response, age_untried);
+ fctx_cancelquery(query, NULL, no_response, age_untried);
}
}
switch (eresult) {
case ISC_R_SUCCESS:
- /* Don't detach from resquery */
- return;
+ goto detach;
case ISC_R_HOSTUNREACH:
case ISC_R_NETUNREACH:
*/
add_bad(fctx, query->rmessage, query->addrinfo, eresult,
badns_unreachable);
- fctx_cancelquery(query, NULL, NULL, true, false);
+ fctx_cancelquery(query, NULL, true, false);
FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
fctx_try(fctx, true, false);
break;
+ case ISC_R_CANCELED:
+ break;
default:
FCTXTRACE3("query canceled in resquery_senddone() "
"due to unexpected result; responding",
eresult);
- fctx_cancelquery(query, NULL, NULL, false, false);
+ fctx_cancelquery(query, NULL, false, false);
fctx_done(fctx, eresult, __LINE__);
break;
}
detach:
- resquery_detach(&query);
+ resquery_detach(&query); /* Detach dispatch query */
}
static inline isc_result_t
unsigned int options) {
isc_result_t result;
dns_resolver_t *res = NULL;
- isc_task_t *task = NULL;
resquery_t *query = NULL;
isc_sockaddr_t addr;
bool have_addr = false;
FCTXTRACE("query");
res = fctx->res;
- task = res->buckets[fctx->bucketnum].task;
srtt = addrinfo->srtt;
query->dscp = dscp;
}
- result = dns_dispatch_createtcp(res->dispatchmgr, res->taskmgr,
- &addr, &addrinfo->sockaddr, 0,
+ result = dns_dispatch_createtcp(res->dispatchmgr, &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->taskmgr, &addr, 0,
- &query->dispatch);
+ result = dns_dispatch_createudp(res->dispatchmgr, &addr,
+ 0, &query->dispatch);
if (result != ISC_R_SUCCESS) {
goto cleanup_query;
}
fctx->nqueries++;
UNLOCK(&res->buckets[fctx->bucketnum].lock);
- resquery_t *tmp = NULL;
- resquery_attach(query, &tmp);
-
/* Set up the dispatch and set the query ID */
result = dns_dispatch_addresponse(
query->dispatch, 0, isc_interval_ms(&fctx->interval),
- &query->addrinfo->sockaddr, task, resquery_connected,
+ &query->addrinfo->sockaddr, resquery_connected,
resquery_senddone, resquery_response, resquery_timeout, query,
&query->id, &query->dispentry);
if (result != ISC_R_SUCCESS) {
}
/* Connect the socket */
- fctx_increference(fctx);
-
+ resquery_attach(query, &(resquery_t *){ NULL }); /* dispatch query */
result = dns_dispatch_connect(query->dispentry);
+
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
return (result);
cleanup_dispatch:
isc_buffer_usedregion(&buffer, &r);
+ resquery_attach(query, &(resquery_t *){ NULL });
dns_dispatch_send(query->dispentry, &r, query->dscp);
QTRACE("sent");
/*
* Stop the dispatcher from listening.
*/
- dns_dispatch_removeresponse(&query->dispentry, NULL);
+ dns_dispatch_removeresponse(&query->dispentry);
cleanup_temps:
if (qname != NULL) {
static void
resquery_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
resquery_t *query = (resquery_t *)arg;
- resquery_t *connquery = query;
isc_result_t result;
fetchctx_t *fctx = NULL;
dns_resolver_t *res = NULL;
- unsigned int bucketnum;
- bool bucket_empty;
int pf;
REQUIRE(VALID_QUERY(query));
fctx = query->fctx;
res = fctx->res;
- bucketnum = fctx->bucketnum;
-
- if (atomic_load_acquire(&res->exiting)) {
- eresult = ISC_R_SHUTTINGDOWN;
- }
-
if (RESQUERY_CANCELED(query)) {
goto detach;
}
+ if (atomic_load_acquire(&fctx->res->exiting)) {
+ if (eresult == ISC_R_SUCCESS) {
+ /*
+ * The reading from the socket has already started at
+ * this point, so we need to properly cancel the reading
+ * and then detach the final resquery_t
+ */
+ resquery_attach(query, &(resquery_t *){ NULL });
+ dns_dispatch_cancel(query->dispentry);
+ }
+ eresult = ISC_R_SHUTTINGDOWN;
+ }
+
switch (eresult) {
case ISC_R_SUCCESS:
/*
"resquery_send() failed; "
"responding");
- fctx_cancelquery(query, NULL, NULL, false, false);
+ fctx_cancelquery(query, NULL, false, false);
fctx_done(fctx, result, __LINE__);
+ break;
}
fctx->querysent++;
dns_rdatatypestats_increment(res->view->resquerystats,
fctx->type);
}
- break;
+ goto detach;
case ISC_R_NETUNREACH:
case ISC_R_HOSTUNREACH:
*/
add_bad(fctx, query->rmessage, query->addrinfo, eresult,
badns_unreachable);
- fctx_cancelquery(query, NULL, NULL, true, false);
+ fctx_cancelquery(query, NULL, true, false);
FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
fctx_try(fctx, true, false);
break;
+ case ISC_R_CANCELED:
+ break;
+
default:
FCTXTRACE3("query canceled in "
"resquery_connected() "
"due to unexpected result; responding",
eresult);
- fctx_cancelquery(query, NULL, NULL, false, false);
+ fctx_cancelquery(query, NULL, false, false);
fctx_done(fctx, eresult, __LINE__);
- }
-
- LOCK(&res->buckets[bucketnum].lock);
- bucket_empty = fctx_decreference(fctx);
- UNLOCK(&res->buckets[bucketnum].lock);
- if (bucket_empty) {
- empty_bucket(res);
+ break;
}
detach:
- resquery_detach(&connquery);
+ resquery_detach(&query); /* Detach dispatch query */
}
static void
dns_messageid_t id, isc_taskaction_t action, void *arg,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
dns_fetch_t *fetch, isc_eventtype_t event_type) {
- isc_task_t *tclone = NULL;
dns_fetchevent_t *event = NULL;
/*
* sender field. We'll make the fetch the sender when we
* actually send the event.
*/
- isc_task_attach(task, &tclone);
- event = (dns_fetchevent_t *)isc_event_allocate(fctx->res->mctx, tclone,
- event_type, action, arg,
- sizeof(*event));
+ isc_task_attach(task, &(isc_task_t *){ NULL });
+ event = (dns_fetchevent_t *)isc_event_allocate(
+ fctx->res->mctx, task, event_type, action, arg, sizeof(*event));
event->result = DNS_R_SERVFAIL;
event->qtype = fctx->type;
event->db = NULL;
}
static isc_result_t
-fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
- const dns_name_t *domain, dns_rdataset_t *nameservers,
- const isc_sockaddr_t *client, unsigned int options,
- unsigned int bucketnum, unsigned int depth, isc_counter_t *qc,
- fetchctx_t **fctxp) {
+fctx_create(dns_resolver_t *res, isc_task_t *task, const dns_name_t *name,
+ dns_rdatatype_t type, const dns_name_t *domain,
+ dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
+ unsigned int options, unsigned int bucketnum, unsigned int depth,
+ isc_counter_t *qc, fetchctx_t **fctxp) {
fetchctx_t *fctx = NULL;
isc_result_t result;
isc_result_t iresult;
.qmintype = type,
.options = options,
.res = res,
+ .task = task,
.bucketnum = bucketnum,
.dbucketnum = RES_NOBUCKET,
.state = fetchstate_init,
* resquery_send(). Sets up a response context (respctx_t).
*/
static void
-resquery_response(isc_task_t *task, isc_event_t *event) {
- isc_result_t result = ISC_R_SUCCESS;
- resquery_t *query = event->ev_arg;
- dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
- fetchctx_t *fctx;
+resquery_response(isc_nmhandle_t *handle, isc_result_t eresult,
+ isc_region_t *region, void *arg) {
+ isc_result_t result;
+ resquery_t *query = (resquery_t *)arg;
+ fetchctx_t *fctx = NULL;
respctx_t rctx;
+ UNUSED(handle);
+
+ if (eresult == ISC_R_CANCELED) {
+ return;
+ }
+
REQUIRE(VALID_QUERY(query));
fctx = query->fctx;
REQUIRE(VALID_FCTX(fctx));
- REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
QTRACE("response");
inc_stats(fctx->res, dns_resstatscounter_responsev6);
}
- rctx_respinit(task, devent, query, fctx, &rctx);
+ rctx_respinit(query, fctx, eresult, region, &rctx);
if (atomic_load_acquire(&fctx->res->exiting)) {
result = ISC_R_SHUTTINGDOWN;
if ((rctx.retryopts & DNS_FETCHOPT_TCP) == 0) {
if ((rctx.retryopts & DNS_FETCHOPT_NOEDNS0) == 0) {
- dns_adb_setudpsize(
- fctx->adb, query->addrinfo,
- isc_buffer_usedlength(&devent->buffer));
+ dns_adb_setudpsize(fctx->adb, query->addrinfo,
+ isc_buffer_usedlength(&rctx.buffer));
} else {
dns_adb_plainresponse(fctx->adb, query->addrinfo);
}
* resquery_response().
*/
static void
-rctx_respinit(isc_task_t *task, dns_dispatchevent_t *devent, resquery_t *query,
- fetchctx_t *fctx, respctx_t *rctx) {
- *rctx = (respctx_t){ .task = task,
- .devent = devent,
- .result = devent->result,
+rctx_respinit(resquery_t *query, fetchctx_t *fctx, isc_result_t result,
+ isc_region_t *region, respctx_t *rctx) {
+ *rctx = (respctx_t){ .result = result,
.query = query,
.fctx = fctx,
.broken_type = badns_response,
.retryopts = query->options };
-
+ isc_buffer_init(&rctx->buffer, region->base, region->length);
+ isc_buffer_add(&rctx->buffer, region->length);
TIME_NOW(&rctx->tnow);
rctx->finish = &rctx->tnow;
rctx->now = (isc_stdtime_t)isc_time_seconds(&rctx->tnow);
*/
static isc_result_t
rctx_dispfail(respctx_t *rctx) {
- dns_dispatchevent_t *devent = rctx->devent;
fetchctx_t *fctx = rctx->fctx;
resquery_t *query = rctx->query;
- if (devent->result == ISC_R_SUCCESS) {
+ if (rctx->result == ISC_R_SUCCESS) {
return (ISC_R_SUCCESS);
}
- if (devent->result == ISC_R_EOF &&
- (rctx->retryopts & DNS_FETCHOPT_NOEDNS0) == 0)
- {
+ if (rctx->result == ISC_R_EOF &&
+ (rctx->retryopts & DNS_FETCHOPT_NOEDNS0) == 0) {
/*
* The problem might be that they don't understand
* EDNS0. Turn it off and try again.
* adjust finish and no_response so that we penalize
* this address in SRTT adjustment later.
*/
- if (devent->result == ISC_R_HOSTUNREACH ||
- devent->result == ISC_R_NETUNREACH ||
- devent->result == ISC_R_CONNREFUSED ||
- devent->result == ISC_R_CANCELED)
+ if (rctx->result == ISC_R_HOSTUNREACH ||
+ rctx->result == ISC_R_NETUNREACH ||
+ rctx->result == ISC_R_CONNREFUSED ||
+ rctx->result == ISC_R_CANCELED)
{
- rctx->broken_server = devent->result;
+ rctx->broken_server = rctx->result;
rctx->broken_type = badns_unreachable;
rctx->finish = NULL;
rctx->no_response = true;
}
}
- FCTXTRACE3("dispatcher failure", devent->result);
+ FCTXTRACE3("dispatcher failure", rctx->result);
rctx_done(rctx, ISC_R_SUCCESS);
return (ISC_R_COMPLETE);
}
fetchctx_t *fctx = rctx->fctx;
resquery_t *query = rctx->query;
- result = dns_message_parse(query->rmessage, &rctx->devent->buffer, 0);
+ result = dns_message_parse(query->rmessage, &rctx->buffer, 0);
if (result == ISC_R_SUCCESS) {
return (ISC_R_SUCCESS);
}
inc_stats(fctx->res, dns_resstatscounter_retry);
fctx_increference(fctx);
result = fctx_query(fctx, addrinfo, rctx->retryopts);
- if (result == ISC_R_SUCCESS) {
- return;
- }
-
- bucketnum = fctx->bucketnum;
- fctx_done(fctx, result, __LINE__);
- LOCK(&res->buckets[bucketnum].lock);
- bucket_empty = fctx_decreference(fctx);
- UNLOCK(&res->buckets[bucketnum].lock);
- if (bucket_empty) {
- empty_bucket(res);
+ if (result != ISC_R_SUCCESS) {
+ bucketnum = fctx->bucketnum;
+ fctx_done(fctx, result, __LINE__);
+ LOCK(&res->buckets[bucketnum].lock);
+ bucket_empty = fctx_decreference(fctx);
+ UNLOCK(&res->buckets[bucketnum].lock);
+ if (bucket_empty) {
+ empty_bucket(res);
+ }
}
}
inc_stats(rctx->fctx->res, dns_resstatscounter_nextitem);
INSIST(rctx->query->dispentry != NULL);
dns_message_reset(rctx->query->rmessage, DNS_MESSAGE_INTENTPARSE);
- result = dns_dispatch_getnext(rctx->query->dispentry, &rctx->devent);
+ result = dns_dispatch_getnext(rctx->query->dispentry);
if (result != ISC_R_SUCCESS) {
fctx_done(rctx->fctx, result, __LINE__);
}
result = dns_resolver_createfetch(
fctx->res, fctx->nsname, dns_rdatatype_ns, NULL, NULL, NULL,
- NULL, 0, fctx->options, 0, NULL, rctx->task, resume_dslookup,
+ NULL, 0, fctx->options, 0, NULL, fctx->task, resume_dslookup,
fctx, &fctx->nsrrset, NULL, &fctx->nsfetch);
if (result != ISC_R_SUCCESS) {
if (result == DNS_R_DUPLICATE) {
FCTXTRACE4("query canceled in rctx_done();",
rctx->no_response ? "no response" : "responding", result);
- /*
- * Cancel the query.
- */
- if (!rctx->nextitem) {
- fctx_cancelquery(query, &rctx->devent, rctx->finish,
- rctx->no_response, false);
- }
-
#ifdef ENABLE_AFL
if (dns_fuzzing_resolver &&
(rctx->next_server || rctx->resend || rctx->nextitem))
{
- if (rctx->nextitem) {
- fctx_cancelquery(query, &rctx->devent, rctx->finish,
- rctx->no_response, false);
- }
+ fctx_cancelquery(query, rctx->finish, rctx->no_response, false);
fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
- return;
- } else
+ goto detach;
+ }
#endif /* ifdef ENABLE_AFL */
- if (rctx->next_server)
- {
+
+ if (rctx->nextitem) {
+ REQUIRE(!rctx->next_server);
+ REQUIRE(!rctx->resend);
+
+ result = rctx_next(rctx);
+ if (result == ISC_R_SUCCESS) {
+ goto detach;
+ }
+ }
+
+ /* Cancel the query */
+ fctx_cancelquery(query, rctx->finish, rctx->no_response, false);
+
+ if (rctx->next_server) {
rctx_nextserver(rctx, message, addrinfo, result);
} else if (rctx->resend) {
rctx_resend(rctx, addrinfo);
- } else if (rctx->nextitem) {
- if (rctx_next(rctx) != ISC_R_SUCCESS) {
- resquery_detach(&query);
- }
} else if (result == DNS_R_CHASEDSSERVERS) {
rctx_chaseds(rctx, message, addrinfo, result);
} else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
/*
- * All has gone well so far, but we are waiting for the
- * DNSSEC validator to validate the answer.
+ * All has gone well so far, but we are waiting for the DNSSEC
+ * validator to validate the answer.
*/
FCTXTRACE("wait for validator");
fctx_cancelqueries(fctx, true, false);
fctx_done(fctx, result, __LINE__);
}
+detach:
dns_message_detach(&message);
}
dns_dt_send(fctx->res->view, dtmsgtype, la,
&rctx->query->addrinfo->sockaddr,
((rctx->query->options & DNS_FETCHOPT_TCP) != 0), &zr,
- &rctx->query->start, NULL, &rctx->devent->buffer);
+ &rctx->query->start, NULL, &rctx->buffer);
#endif /* HAVE_DNSTAP */
}
}
if (dispatchv4 != NULL) {
- dns_dispatchset_create(view->mctx, taskmgr, dispatchv4,
+ dns_dispatchset_create(view->mctx, dispatchv4,
&res->dispatches4, ndisp);
}
if (dispatchv6 != NULL) {
- dns_dispatchset_create(view->mctx, taskmgr, dispatchv6,
+ dns_dispatchset_create(view->mctx, dispatchv6,
&res->dispatches6, ndisp);
}
void
dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
isc_event_t **eventp) {
- isc_task_t *tclone;
- isc_event_t *event;
+ isc_event_t *event = NULL;
REQUIRE(VALID_RESOLVER(res));
REQUIRE(eventp != NULL);
event->ev_sender = res;
isc_task_send(task, &event);
} else {
- tclone = NULL;
- isc_task_attach(task, &tclone);
- event->ev_sender = tclone;
+ isc_task_attach(task, &(isc_task_t *){ NULL });
+ event->ev_sender = task;
ISC_LIST_APPEND(res->whenshutdown, event, ev_link);
}
}
if (fctx == NULL) {
- result = fctx_create(res, name, type, domain, nameservers,
+ result = fctx_create(res, task, name, type, domain, nameservers,
client, options, bucketnum, depth, qc,
&fctx);
if (result != ISC_R_SUCCESS) {
isc_refcount_t refs;
isc_taskmgr_t *taskmgr;
isc_timermgr_t *timermgr;
- isc_socketmgr_t *socketmgr;
isc_nm_t *netmgr;
isc_taskpool_t *zonetasks;
isc_taskpool_t *loadtasks;
isc_result_t
dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
- isc_nm_t *netmgr, dns_zonemgr_t **zmgrp) {
+ isc_timermgr_t *timermgr, isc_nm_t *netmgr,
+ dns_zonemgr_t **zmgrp) {
dns_zonemgr_t *zmgr;
isc_result_t result;
isc_mem_attach(mctx, &zmgr->mctx);
zmgr->taskmgr = taskmgr;
zmgr->timermgr = timermgr;
- zmgr->socketmgr = socketmgr;
zmgr->netmgr = netmgr;
zmgr->zonetasks = NULL;
zmgr->loadtasks = NULL;
#endif /* HAVE_LIBNGHTTP2 */
typedef void (*isc_taskaction_t)(isc_task_t *, isc_event_t *);
-typedef int (*isc_sockfdwatch_t)(isc_task_t *, isc_socket_t *, void *, int);
/* The following cannot be listed alphabetically due to forward reference */
typedef isc_result_t(isc_httpdaction_t)(
result = isc_task_create_bound(manager->taskmgr, 20, &manager->task,
manager->tid);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ isc_task_setname(manager->task, "clientmgr", NULL);
isc_refcount_init(&manager->references, 1);
manager->sctx = NULL;
#include <isc/mem.h>
#include <isc/netmgr.h>
#include <isc/refcount.h>
-#include <isc/socket.h>
#include <dns/geoip.h>
#include <dns/result.h>
isc_sockaddr_t addr; /*%< Address and port. */
unsigned int flags; /*%< Interface flags */
char name[32]; /*%< Null terminated. */
- isc_socket_t * tcpsocket; /*%< TCP socket. */
isc_nmsocket_t * udplistensocket;
isc_nmsocket_t * tcplistensocket;
isc_nmsocket_t * http_listensocket;
ns_interface_shutdown(ifp);
- if (ifp->tcpsocket != NULL) {
- isc_socket_detach(&ifp->tcpsocket);
- }
-
isc_mutex_destroy(&ifp->lock);
ns_interfacemgr_detach(&ifp->mgr);