mirror of
https://github.com/isc-projects/bind9.git
synced 2026-07-16 00:32:50 -04:00
Rewrite dns_resolver and dns_request to use netmgr timeouts
- The `timeout_action` parameter to dns_dispatch_addresponse() been replaced with a netmgr callback that is called when a dispatch read times out. this callback may optionally reset the read timer and resume reading. - Added a function to convert isc_interval to milliseconds; this is used to translate fctx->interval into a value that can be passed to dns_dispatch_addresponse() as the timeout. - Note that netmgr timeouts are accurate to the millisecond, so code to check whether a timeout has been reached cannot rely on microsecond accuracy. - If serve-stale is configured, then a timeout received by the resolver may trigger it to return stale data, and then resume waiting for the read timeout. this is no longer based on a separate stale timer. - The code for canceling requests in request.c has been altered so that it can run asynchronously. - TCP timeout events apply to the dispatch, which may be shared by multiple queries. since in the event of a timeout we have no query ID to use to identify the resp we wanted, we now just send the timeout to the oldest query that was pending. - There was some additional refactoring in the resolver: combining fctx_join() and fctx_try_events() into one function to reduce code duplication, and using fixednames in fetchctx and fetchevent. - Incidental fix: new_adbaddrinfo() can't return NULL anymore, so the code can be simplified.
This commit is contained in:
parent
308bc46a59
commit
08ce69a0ea
14 changed files with 601 additions and 827 deletions
|
|
@ -2237,11 +2237,9 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find,
|
|||
find->options |= DNS_ADBFIND_LAMEPRUNED;
|
||||
goto nextv4;
|
||||
}
|
||||
|
||||
addrinfo = new_adbaddrinfo(adb, entry, find->port);
|
||||
if (addrinfo == NULL) {
|
||||
find->partial_result |= DNS_ADBFIND_INET;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found a valid entry. Add it to the find's list.
|
||||
*/
|
||||
|
|
@ -2275,10 +2273,7 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find,
|
|||
goto nextv6;
|
||||
}
|
||||
addrinfo = new_adbaddrinfo(adb, entry, find->port);
|
||||
if (addrinfo == NULL) {
|
||||
find->partial_result |= DNS_ADBFIND_INET6;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found a valid entry. Add it to the find's list.
|
||||
*/
|
||||
|
|
@ -2292,7 +2287,6 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find,
|
|||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (bucket != DNS_ADB_INVALIDBUCKET) {
|
||||
UNLOCK(&adb->entrylocks[bucket]);
|
||||
}
|
||||
|
|
@ -3962,8 +3956,7 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
|
|||
dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
|
||||
clean_target(adb, &name->target);
|
||||
name->expire_target = INT_MAX;
|
||||
result = set_target(adb, &name->name,
|
||||
dns_fixedname_name(&dev->foundname),
|
||||
result = set_target(adb, &name->name, dev->foundname,
|
||||
dev->rdataset, &name->target);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
DP(NCACHE_LEVEL,
|
||||
|
|
@ -4533,12 +4526,8 @@ dns_adb_findaddrinfo(dns_adb_t *adb, const isc_sockaddr_t *sa,
|
|||
|
||||
port = isc_sockaddr_getport(sa);
|
||||
addr = new_adbaddrinfo(adb, entry, port);
|
||||
if (addr == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
} else {
|
||||
inc_entry_refcnt(adb, entry, false);
|
||||
*addrp = addr;
|
||||
}
|
||||
inc_entry_refcnt(adb, entry, false);
|
||||
*addrp = addr;
|
||||
|
||||
unlock:
|
||||
UNLOCK(&adb->entrylocks[bucket]);
|
||||
|
|
|
|||
|
|
@ -579,9 +579,9 @@ client_resfind(resctx_t *rctx, dns_fetchevent_t *event) {
|
|||
isc_result_t vresult = ISC_R_SUCCESS;
|
||||
bool want_restart;
|
||||
bool send_event = false;
|
||||
dns_name_t *name, *prefix;
|
||||
dns_name_t *name = NULL, *prefix = NULL;
|
||||
dns_fixedname_t foundname, fixed;
|
||||
dns_rdataset_t *trdataset;
|
||||
dns_rdataset_t *trdataset = NULL;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
unsigned int nlabels;
|
||||
int order;
|
||||
|
|
@ -643,7 +643,7 @@ client_resfind(resctx_t *rctx, dns_fetchevent_t *event) {
|
|||
node = event->node;
|
||||
result = event->result;
|
||||
vresult = event->vresult;
|
||||
fname = dns_fixedname_name(&event->foundname);
|
||||
fname = event->foundname;
|
||||
INSIST(event->rdataset == rctx->rdataset);
|
||||
INSIST(event->sigrdataset == rctx->sigrdataset);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
#include <dns/stats.h>
|
||||
#include <dns/types.h>
|
||||
|
||||
#define DISPATCH_TRACE
|
||||
|
||||
typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
|
||||
|
||||
typedef struct dispsocket dispsocket_t;
|
||||
|
|
@ -89,8 +91,8 @@ struct dns_dispentry {
|
|||
isc_task_t *task;
|
||||
isc_nm_cb_t connected;
|
||||
isc_nm_cb_t sent;
|
||||
isc_nm_cb_t timedout;
|
||||
isc_taskaction_t action;
|
||||
isc_taskaction_t timeout_action;
|
||||
void *arg;
|
||||
bool item_out;
|
||||
dispsocket_t *dispsocket;
|
||||
|
|
@ -729,7 +731,6 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|||
dns_dispatchmgr_t *mgr = NULL;
|
||||
isc_sockaddr_t peer;
|
||||
isc_netaddr_t netaddr;
|
||||
isc_taskaction_t action;
|
||||
int match;
|
||||
|
||||
REQUIRE(VALID_DISPSOCK(dispsock));
|
||||
|
|
@ -767,8 +768,7 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|||
}
|
||||
|
||||
if (dispsock == NULL) {
|
||||
UNLOCK(&disp->lock);
|
||||
return;
|
||||
goto next;
|
||||
}
|
||||
|
||||
resp = dispsock->resp;
|
||||
|
|
@ -777,12 +777,20 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|||
peer = isc_nmhandle_peeraddr(handle);
|
||||
isc_netaddr_fromsockaddr(&netaddr, &peer);
|
||||
|
||||
if (eresult == ISC_R_TIMEDOUT && resp->timedout != NULL) {
|
||||
resp->timedout(handle, ISC_R_TIMEDOUT, resp->arg);
|
||||
if (isc_nmhandle_timer_running(handle)) {
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
if (eresult != ISC_R_SUCCESS) {
|
||||
/*
|
||||
* 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.
|
||||
* This is most likely a network error on a connected
|
||||
* socket, or a timeout on a timer that has not been
|
||||
* reset. It makes no sense to check the address or
|
||||
* parse the packet, but it will help to return the
|
||||
* error to the caller.
|
||||
*/
|
||||
goto sendevent;
|
||||
}
|
||||
|
|
@ -858,12 +866,11 @@ sendevent:
|
|||
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,
|
||||
action, resp->arg, resp, NULL, NULL);
|
||||
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,
|
||||
|
|
@ -900,6 +907,7 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|||
dns_messageid_t id;
|
||||
isc_result_t dres;
|
||||
unsigned int flags;
|
||||
dispsocket_t *dispsock = NULL;
|
||||
dns_dispentry_t *resp = NULL;
|
||||
dns_dispatchevent_t *rev = NULL;
|
||||
unsigned int bucket;
|
||||
|
|
@ -910,7 +918,6 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|||
char buf[ISC_SOCKADDR_FORMATSIZE];
|
||||
isc_buffer_t source;
|
||||
isc_sockaddr_t peer;
|
||||
isc_taskaction_t action;
|
||||
|
||||
REQUIRE(VALID_DISPATCH(disp));
|
||||
|
||||
|
|
@ -940,6 +947,8 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|||
|
||||
switch (eresult) {
|
||||
case ISC_R_CANCELED:
|
||||
dispatch_log(disp, LVL(90), "shutting down on cancel");
|
||||
do_cancel(disp);
|
||||
break;
|
||||
|
||||
case ISC_R_EOF:
|
||||
|
|
@ -952,8 +961,26 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|||
goto logit;
|
||||
|
||||
case ISC_R_TIMEDOUT:
|
||||
id = 0; /* XXX this is broken */
|
||||
goto sendevent;
|
||||
/*
|
||||
* Time out the first active response for which
|
||||
* no event has already been sent.
|
||||
*/
|
||||
for (dispsock = ISC_LIST_HEAD(disp->activesockets);
|
||||
dispsock != NULL;
|
||||
dispsock = ISC_LIST_NEXT(dispsock, link))
|
||||
{
|
||||
resp = dispsock->resp;
|
||||
if (resp->item_out) {
|
||||
continue;
|
||||
}
|
||||
ISC_LIST_UNLINK(disp->activesockets, dispsock,
|
||||
link);
|
||||
ISC_LIST_APPEND(disp->activesockets, dispsock,
|
||||
link);
|
||||
goto sendevent;
|
||||
}
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
|
||||
default:
|
||||
level = ISC_LOG_ERROR;
|
||||
|
|
@ -1014,20 +1041,20 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|||
goto next;
|
||||
}
|
||||
|
||||
sendevent:
|
||||
/*
|
||||
* Response.
|
||||
* We have a response; find the associated dispentry.
|
||||
*/
|
||||
bucket = dns_hash(qid, &peer, id, disp->localport);
|
||||
LOCK(&qid->lock);
|
||||
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"));
|
||||
UNLOCK(&qid->lock);
|
||||
if (resp == NULL) {
|
||||
UNLOCK(&qid->lock);
|
||||
goto next;
|
||||
}
|
||||
|
||||
sendevent:
|
||||
queue_response = resp->item_out;
|
||||
rev = allocate_devent(disp);
|
||||
|
||||
|
|
@ -1052,14 +1079,13 @@ sendevent:
|
|||
ISC_LIST_APPEND(resp->items, rev, ev_link);
|
||||
} else {
|
||||
ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, DNS_EVENT_DISPATCH,
|
||||
action, resp->arg, resp, NULL, NULL);
|
||||
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);
|
||||
isc_task_send(resp->task, ISC_EVENT_PTR(&rev));
|
||||
}
|
||||
UNLOCK(&qid->lock);
|
||||
|
||||
next:
|
||||
startrecv(disp, NULL);
|
||||
|
|
@ -1710,8 +1736,8 @@ 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_taskaction_t timeout_action, void *arg,
|
||||
dns_messageid_t *idp, dns_dispentry_t **resp) {
|
||||
isc_nm_cb_t timedout, void *arg, dns_messageid_t *idp,
|
||||
dns_dispentry_t **resp) {
|
||||
isc_result_t result;
|
||||
dns_dispentry_t *res = NULL;
|
||||
dispsocket_t *dispsocket = NULL;
|
||||
|
|
@ -1829,8 +1855,8 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
|
|||
.peer = *dest,
|
||||
.connected = connected,
|
||||
.sent = sent,
|
||||
.timedout = timedout,
|
||||
.action = action,
|
||||
.timeout_action = timeout_action,
|
||||
.arg = arg,
|
||||
.dispsocket = dispsocket };
|
||||
|
||||
|
|
|
|||
|
|
@ -312,8 +312,8 @@ 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_taskaction_t timeout_action, void *arg,
|
||||
dns_messageid_t *idp, dns_dispentry_t **resp);
|
||||
isc_nm_cb_t timedout, void *arg, dns_messageid_t *idp,
|
||||
dns_dispentry_t **resp);
|
||||
/*%<
|
||||
* Add a response entry for this dispatch.
|
||||
*
|
||||
|
|
@ -321,7 +321,9 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
|
|||
* to contain the magic token used to request event flow stop.
|
||||
*
|
||||
* The 'connected' and 'sent' callbacks are run to inform the caller when
|
||||
* the connection and send functions are complete.
|
||||
* 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,
|
||||
|
|
@ -329,8 +331,6 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
|
|||
* 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:
|
||||
|
|
|
|||
|
|
@ -74,7 +74,8 @@ typedef struct dns_fetchevent {
|
|||
dns_dbnode_t * node;
|
||||
dns_rdataset_t * rdataset;
|
||||
dns_rdataset_t * sigrdataset;
|
||||
dns_fixedname_t foundname;
|
||||
dns_fixedname_t fname;
|
||||
dns_name_t * foundname;
|
||||
const isc_sockaddr_t *client;
|
||||
dns_messageid_t id;
|
||||
isc_result_t vresult;
|
||||
|
|
|
|||
|
|
@ -140,10 +140,10 @@ view_find(dns_lookup_t *lookup, dns_name_t *foundname) {
|
|||
|
||||
static void
|
||||
lookup_find(dns_lookup_t *lookup, dns_fetchevent_t *event) {
|
||||
isc_result_t result;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
bool want_restart;
|
||||
bool send_event;
|
||||
dns_name_t *name, *fname, *prefix;
|
||||
dns_name_t *name = NULL, *fname = NULL, *prefix = NULL;
|
||||
dns_fixedname_t foundname, fixed;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
unsigned int nlabels;
|
||||
|
|
@ -156,7 +156,6 @@ lookup_find(dns_lookup_t *lookup, dns_fetchevent_t *event) {
|
|||
|
||||
LOCK(&lookup->lock);
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
name = dns_fixedname_name(&lookup->name);
|
||||
|
||||
do {
|
||||
|
|
@ -202,12 +201,10 @@ lookup_find(dns_lookup_t *lookup, dns_fetchevent_t *event) {
|
|||
}
|
||||
} else if (event != NULL) {
|
||||
result = event->result;
|
||||
fname = dns_fixedname_name(&event->foundname);
|
||||
fname = event->foundname;
|
||||
dns_resolver_destroyfetch(&lookup->fetch);
|
||||
INSIST(event->rdataset == &lookup->rdataset);
|
||||
INSIST(event->sigrdataset == &lookup->sigrdataset);
|
||||
} else {
|
||||
fname = NULL; /* Silence compiler warning. */
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <isc/magic.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/netmgr.h>
|
||||
#include <isc/task.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
|
|
@ -75,24 +76,20 @@ struct dns_request {
|
|||
isc_buffer_t *tsig;
|
||||
dns_tsigkey_t *tsigkey;
|
||||
isc_socketevent_t sendevent;
|
||||
isc_event_t ctlevent;
|
||||
bool canceling; /* ctlevent outstanding */
|
||||
isc_sockaddr_t destaddr;
|
||||
unsigned int timeout;
|
||||
unsigned int udpcount;
|
||||
isc_dscp_t dscp;
|
||||
};
|
||||
|
||||
#define DNS_REQUEST_F_CONNECTING 0x0001
|
||||
#define DNS_REQUEST_F_SENDING 0x0002
|
||||
#define DNS_REQUEST_F_CANCELED \
|
||||
0x0004 /*%< ctlevent received, or otherwise \
|
||||
* synchronously canceled */
|
||||
#define DNS_REQUEST_F_TIMEDOUT 0x0008 /*%< canceled due to a timeout */
|
||||
#define DNS_REQUEST_F_TCP 0x0010 /*%< This request used TCP */
|
||||
#define DNS_REQUEST_F_CANCELED 0x0004
|
||||
#define DNS_REQUEST_F_TCP 0x0010
|
||||
|
||||
#define DNS_REQUEST_CANCELED(r) (((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
|
||||
#define DNS_REQUEST_CONNECTING(r) (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)
|
||||
#define DNS_REQUEST_SENDING(r) (((r)->flags & DNS_REQUEST_F_SENDING) != 0)
|
||||
#define DNS_REQUEST_TIMEDOUT(r) (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0)
|
||||
|
||||
/***
|
||||
*** Forward
|
||||
|
|
@ -113,21 +110,19 @@ req_render(dns_message_t *message, isc_buffer_t **buffer, unsigned int options,
|
|||
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_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);
|
||||
req_timeout(isc_nmhandle_t *handle, isc_result_t eresult, void *arg);
|
||||
static void
|
||||
req_destroy(dns_request_t *request);
|
||||
static void
|
||||
req_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
|
||||
static void
|
||||
do_cancel(isc_task_t *task, isc_event_t *event);
|
||||
void
|
||||
request_cancel(dns_request_t *request);
|
||||
|
||||
/***
|
||||
*** Public
|
||||
|
|
@ -236,9 +231,6 @@ static void
|
|||
mgr_shutdown(dns_requestmgr_t *requestmgr) {
|
||||
dns_request_t *request;
|
||||
|
||||
/*
|
||||
* Caller holds lock.
|
||||
*/
|
||||
if (!requestmgr->exiting) {
|
||||
requestmgr->exiting = true;
|
||||
for (request = ISC_LIST_HEAD(requestmgr->requests);
|
||||
|
|
@ -422,9 +414,6 @@ new_request(isc_mem_t *mctx, dns_request_t **requestp) {
|
|||
request = isc_mem_get(mctx, sizeof(*request));
|
||||
*request = (dns_request_t){ .dscp = -1 };
|
||||
ISC_LINK_INIT(request, link);
|
||||
ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL,
|
||||
DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL, NULL,
|
||||
NULL);
|
||||
|
||||
isc_mem_attach(mctx, &request->mctx);
|
||||
|
||||
|
|
@ -574,16 +563,6 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
|
|||
return (result);
|
||||
}
|
||||
|
||||
if (udptimeout == 0 && udpretries != 0) {
|
||||
udptimeout = timeout / (udpretries + 1);
|
||||
if (udptimeout == 0) {
|
||||
udptimeout = 1;
|
||||
}
|
||||
}
|
||||
|
||||
timeout *= 1000;
|
||||
udptimeout *= 1000;
|
||||
|
||||
request->udpcount = udpretries;
|
||||
request->dscp = dscp;
|
||||
|
||||
|
|
@ -603,6 +582,15 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
|
|||
|
||||
if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512) {
|
||||
tcp = true;
|
||||
request->timeout = timeout * 1000;
|
||||
} else {
|
||||
if (udptimeout == 0 && udpretries != 0) {
|
||||
udptimeout = timeout / (udpretries + 1);
|
||||
}
|
||||
if (udptimeout == 0) {
|
||||
udptimeout = 1;
|
||||
}
|
||||
request->timeout = udptimeout * 1000;
|
||||
}
|
||||
|
||||
again:
|
||||
|
|
@ -618,9 +606,9 @@ again:
|
|||
}
|
||||
|
||||
result = dns_dispatch_addresponse(
|
||||
request->dispatch, dispopt, tcp ? timeout : udptimeout,
|
||||
destaddr, task, req_connected, req_senddone, req_response,
|
||||
req_timeout, request, &id, &request->dispentry);
|
||||
request->dispatch, dispopt, request->timeout, 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;
|
||||
|
|
@ -708,7 +696,7 @@ dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
|
|||
isc_result_t result;
|
||||
isc_mem_t *mctx;
|
||||
dns_messageid_t id;
|
||||
bool tcp;
|
||||
bool tcp = false;
|
||||
bool settsigkey = true;
|
||||
bool connected = false;
|
||||
|
||||
|
|
@ -738,16 +726,6 @@ dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
|
|||
return (result);
|
||||
}
|
||||
|
||||
if (udptimeout == 0 && udpretries != 0) {
|
||||
udptimeout = timeout / (udpretries + 1);
|
||||
if (udptimeout == 0) {
|
||||
udptimeout = 1;
|
||||
}
|
||||
}
|
||||
|
||||
timeout *= 1000;
|
||||
udptimeout *= 1000;
|
||||
|
||||
request->udpcount = udpretries;
|
||||
request->dscp = dscp;
|
||||
|
||||
|
|
@ -763,7 +741,19 @@ dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
|
|||
}
|
||||
|
||||
use_tcp:
|
||||
tcp = ((options & DNS_REQUESTOPT_TCP) != 0);
|
||||
if ((options & DNS_REQUESTOPT_TCP) != 0) {
|
||||
tcp = true;
|
||||
request->timeout = timeout * 1000;
|
||||
} else {
|
||||
if (udptimeout == 0 && udpretries != 0) {
|
||||
udptimeout = timeout / (udpretries + 1);
|
||||
}
|
||||
if (udptimeout == 0) {
|
||||
udptimeout = 1;
|
||||
}
|
||||
request->timeout = udptimeout * 1000;
|
||||
}
|
||||
|
||||
result = get_dispatch(tcp, false, requestmgr, srcaddr, destaddr, dscp,
|
||||
&connected, &request->dispatch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -771,9 +761,9 @@ use_tcp:
|
|||
}
|
||||
|
||||
result = dns_dispatch_addresponse(
|
||||
request->dispatch, 0, tcp ? timeout : udptimeout, destaddr,
|
||||
task, req_connected, req_senddone, req_response, req_timeout,
|
||||
request, &id, &request->dispentry);
|
||||
request->dispatch, 0, request->timeout, destaddr, task,
|
||||
req_connected, req_senddone, req_response, req_timeout, request,
|
||||
&id, &request->dispentry);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
@ -952,26 +942,28 @@ cleanup:
|
|||
*/
|
||||
static void
|
||||
send_if_done(dns_request_t *request, isc_result_t result) {
|
||||
if (request->event != NULL && !request->canceling) {
|
||||
if (request->event != NULL) {
|
||||
req_sendevent(request, result);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the control event.
|
||||
*/
|
||||
static void
|
||||
do_cancel(isc_task_t *task, isc_event_t *event) {
|
||||
dns_request_t *request = event->ev_arg;
|
||||
UNUSED(task);
|
||||
INSIST(event->ev_type == DNS_EVENT_REQUESTCONTROL);
|
||||
LOCK(&request->requestmgr->locks[request->hash]);
|
||||
request->canceling = false;
|
||||
void
|
||||
request_cancel(dns_request_t *request) {
|
||||
if (!DNS_REQUEST_CANCELED(request)) {
|
||||
req_cancel(request);
|
||||
req_log(ISC_LOG_DEBUG(3), "do_cancel: request %p", request);
|
||||
|
||||
request->flags |= DNS_REQUEST_F_CANCELED;
|
||||
request->flags &= ~DNS_REQUEST_F_CONNECTING;
|
||||
|
||||
if (request->dispentry != NULL) {
|
||||
dns_dispatch_cancel(NULL, request->dispentry,
|
||||
DNS_REQUEST_SENDING(request),
|
||||
DNS_REQUEST_CONNECTING(request));
|
||||
dns_dispatch_removeresponse(&request->dispentry, NULL);
|
||||
}
|
||||
|
||||
dns_dispatch_detach(&request->dispatch);
|
||||
}
|
||||
send_if_done(request, ISC_R_CANCELED);
|
||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -979,15 +971,9 @@ dns_request_cancel(dns_request_t *request) {
|
|||
REQUIRE(VALID_REQUEST(request));
|
||||
|
||||
req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request);
|
||||
|
||||
REQUIRE(VALID_REQUEST(request));
|
||||
|
||||
LOCK(&request->requestmgr->locks[request->hash]);
|
||||
if (!request->canceling && !DNS_REQUEST_CANCELED(request)) {
|
||||
isc_event_t *ev = &request->ctlevent;
|
||||
isc_task_send(request->event->ev_sender, &ev);
|
||||
request->canceling = true;
|
||||
}
|
||||
request_cancel(request);
|
||||
send_if_done(request, ISC_R_CANCELED);
|
||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||
}
|
||||
|
||||
|
|
@ -1054,8 +1040,8 @@ dns_request_destroy(dns_request_t **requestp) {
|
|||
UNLOCK(&request->requestmgr->lock);
|
||||
|
||||
/*
|
||||
* These should have been cleaned up by req_cancel() before
|
||||
* the completion event was sent.
|
||||
* These should have been cleaned up before the completion
|
||||
* event was sent.
|
||||
*/
|
||||
INSIST(!ISC_LINK_LINKED(request, link));
|
||||
INSIST(request->dispentry == NULL);
|
||||
|
|
@ -1073,6 +1059,10 @@ req_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
|
|||
|
||||
UNUSED(handle);
|
||||
|
||||
if (eresult == ISC_R_CANCELED) {
|
||||
return;
|
||||
}
|
||||
|
||||
REQUIRE(VALID_REQUEST(request));
|
||||
REQUIRE(DNS_REQUEST_CONNECTING(request));
|
||||
|
||||
|
|
@ -1081,22 +1071,17 @@ req_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
|
|||
LOCK(&request->requestmgr->locks[request->hash]);
|
||||
request->flags &= ~DNS_REQUEST_F_CONNECTING;
|
||||
|
||||
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);
|
||||
}
|
||||
if (eresult == ISC_R_TIMEDOUT) {
|
||||
dns_dispatch_removeresponse(&request->dispentry, NULL);
|
||||
dns_dispatch_detach(&request->dispatch);
|
||||
send_if_done(request, eresult);
|
||||
} else if (DNS_REQUEST_CANCELED(request)) {
|
||||
send_if_done(request, ISC_R_CANCELED);
|
||||
} else if (eresult == ISC_R_SUCCESS) {
|
||||
req_send(request);
|
||||
} else {
|
||||
if (eresult == ISC_R_SUCCESS) {
|
||||
req_send(request);
|
||||
} else {
|
||||
req_cancel(request);
|
||||
send_if_done(request, ISC_R_CANCELED);
|
||||
}
|
||||
request_cancel(request);
|
||||
send_if_done(request, ISC_R_CANCELED);
|
||||
}
|
||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||
}
|
||||
|
|
@ -1116,19 +1101,39 @@ req_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
|
|||
request->flags &= ~DNS_REQUEST_F_SENDING;
|
||||
|
||||
if (DNS_REQUEST_CANCELED(request)) {
|
||||
if (DNS_REQUEST_TIMEDOUT(request)) {
|
||||
send_if_done(request, ISC_R_TIMEDOUT);
|
||||
if (eresult == ISC_R_TIMEDOUT) {
|
||||
send_if_done(request, eresult);
|
||||
} else {
|
||||
send_if_done(request, ISC_R_CANCELED);
|
||||
}
|
||||
} else if (eresult != ISC_R_SUCCESS) {
|
||||
req_cancel(request);
|
||||
request_cancel(request);
|
||||
send_if_done(request, ISC_R_CANCELED);
|
||||
}
|
||||
|
||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||
}
|
||||
|
||||
static void
|
||||
req_timeout(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
|
||||
dns_request_t *request = (dns_request_t *)arg;
|
||||
|
||||
REQUIRE(VALID_REQUEST(request));
|
||||
|
||||
UNUSED(eresult);
|
||||
|
||||
req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request);
|
||||
|
||||
LOCK(&request->requestmgr->locks[request->hash]);
|
||||
if (--request->udpcount != 0) {
|
||||
isc_nmhandle_settimeout(handle, request->timeout);
|
||||
if (!DNS_REQUEST_SENDING(request)) {
|
||||
req_send(request);
|
||||
}
|
||||
}
|
||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||
}
|
||||
|
||||
static void
|
||||
req_response(isc_task_t *task, isc_event_t *event) {
|
||||
isc_result_t result;
|
||||
|
|
@ -1164,7 +1169,8 @@ done:
|
|||
* Cleanup.
|
||||
*/
|
||||
dns_dispatch_removeresponse(&request->dispentry, &devent);
|
||||
req_cancel(request);
|
||||
request_cancel(request);
|
||||
|
||||
/*
|
||||
* Send completion event.
|
||||
*/
|
||||
|
|
@ -1172,29 +1178,6 @@ done:
|
|||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||
}
|
||||
|
||||
static void
|
||||
req_timeout(isc_task_t *task, isc_event_t *event) {
|
||||
dns_request_t *request = event->ev_arg;
|
||||
|
||||
REQUIRE(VALID_REQUEST(request));
|
||||
|
||||
req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request);
|
||||
|
||||
UNUSED(task);
|
||||
LOCK(&request->requestmgr->locks[request->hash]);
|
||||
if (request->udpcount-- != 0) {
|
||||
if (!DNS_REQUEST_SENDING(request)) {
|
||||
req_send(request);
|
||||
}
|
||||
} else {
|
||||
request->flags |= DNS_REQUEST_F_TIMEDOUT;
|
||||
req_cancel(request);
|
||||
send_if_done(request, ISC_R_TIMEDOUT);
|
||||
}
|
||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
req_sendevent(dns_request_t *request, isc_result_t result) {
|
||||
isc_task_t *task;
|
||||
|
|
@ -1246,29 +1229,6 @@ req_destroy(dns_request_t *request) {
|
|||
isc_mem_putanddetach(&request->mctx, request, sizeof(*request));
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the current request. Must be called from the request's task.
|
||||
*/
|
||||
static void
|
||||
req_cancel(dns_request_t *request) {
|
||||
REQUIRE(VALID_REQUEST(request));
|
||||
|
||||
req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request);
|
||||
|
||||
/*
|
||||
* Lock held by caller.
|
||||
*/
|
||||
request->flags |= DNS_REQUEST_F_CANCELED;
|
||||
|
||||
if (request->dispentry != NULL) {
|
||||
dns_dispatch_cancel(NULL, request->dispentry,
|
||||
DNS_REQUEST_SENDING(request),
|
||||
DNS_REQUEST_CONNECTING(request));
|
||||
dns_dispatch_removeresponse(&request->dispentry, NULL);
|
||||
}
|
||||
dns_dispatch_detach(&request->dispatch);
|
||||
}
|
||||
|
||||
static void
|
||||
req_log(int level, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
|
|
|||
1038
lib/dns/resolver.c
1038
lib/dns/resolver.c
File diff suppressed because it is too large
Load diff
|
|
@ -576,8 +576,8 @@ fetch_callback_ds(isc_task_t *task, isc_event_t *event) {
|
|||
} else if (eresult == DNS_R_SERVFAIL) {
|
||||
goto unexpected;
|
||||
} else if (eresult != DNS_R_CNAME &&
|
||||
isdelegation(dns_fixedname_name(&devent->foundname),
|
||||
&val->frdataset, eresult))
|
||||
isdelegation(devent->foundname, &val->frdataset,
|
||||
eresult))
|
||||
{
|
||||
/*
|
||||
* Failed to find a DS while trying to prove
|
||||
|
|
|
|||
|
|
@ -160,6 +160,12 @@ isc_nmhandle_cleartimeout(isc_nmhandle_t *handle);
|
|||
* a TCPDNS socket wrapping a TCP connection), the timer is set for
|
||||
* both socket layers.
|
||||
*/
|
||||
bool
|
||||
isc_nmhandle_timer_running(isc_nmhandle_t *handle);
|
||||
/*%<
|
||||
* Return true if the timer for the socket connected to 'handle'
|
||||
* is running.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_nmhandle_keepalive(isc_nmhandle_t *handle, bool value);
|
||||
|
|
|
|||
|
|
@ -71,6 +71,16 @@ isc_interval_iszero(const isc_interval_t *i);
|
|||
*\li 'i' is a valid pointer.
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
isc_interval_ms(const isc_interval_t *i);
|
||||
/*%<
|
||||
* Returns interval 'i' expressed as a number of milliseconds.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'i' is a valid pointer.
|
||||
*/
|
||||
|
||||
/***
|
||||
*** Absolute Times
|
||||
***/
|
||||
|
|
|
|||
|
|
@ -2404,6 +2404,14 @@ isc_nmhandle_keepalive(isc_nmhandle_t *handle, bool value) {
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
isc_nmhandle_timer_running(isc_nmhandle_t *handle) {
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
|
||||
return (isc__nmsocket_timer_running(handle->sock));
|
||||
}
|
||||
|
||||
void *
|
||||
isc_nmhandle_getextra(isc_nmhandle_t *handle) {
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#define NS_PER_S 1000000000 /*%< Nanoseconds per second. */
|
||||
#define NS_PER_US 1000 /*%< Nanoseconds per microsecond. */
|
||||
#define NS_PER_MS 1000000 /*%< Nanoseconds per millisecond. */
|
||||
#define MS_PER_S 1000 /*%< Milliseonds per second. */
|
||||
|
||||
#if defined(CLOCK_REALTIME)
|
||||
#define CLOCKSOURCE_HIRES CLOCK_REALTIME
|
||||
|
|
@ -77,6 +78,14 @@ isc_interval_iszero(const isc_interval_t *i) {
|
|||
return (false);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
isc_interval_ms(const isc_interval_t *i) {
|
||||
REQUIRE(i != NULL);
|
||||
INSIST(i->nanoseconds < NS_PER_S);
|
||||
|
||||
return ((i->seconds * MS_PER_S) + (i->nanoseconds / NS_PER_MS));
|
||||
}
|
||||
|
||||
/***
|
||||
*** Absolute Times
|
||||
***/
|
||||
|
|
|
|||
|
|
@ -6652,7 +6652,7 @@ query_resume(query_ctx_t *qctx) {
|
|||
} else if (REDIRECT(qctx->client)) {
|
||||
tname = qctx->client->query.redirect.fname;
|
||||
} else {
|
||||
tname = dns_fixedname_name(&qctx->event->foundname);
|
||||
tname = qctx->event->foundname;
|
||||
}
|
||||
|
||||
dns_name_copy(tname, qctx->fname);
|
||||
|
|
|
|||
Loading…
Reference in a new issue