2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 21:47:59 +00:00

469. [bug] "query-source address * port 53;" now works.

This commit is contained in:
Mark Andrews 2000-09-18 04:50:05 +00:00
parent 79907dfac9
commit a7c76f1924
2 changed files with 226 additions and 86 deletions

View File

@ -1,3 +1,5 @@
469. [bug] "query-source address * port 53;" now works.
468. [bug] dns_master_load*() failed to report file and line
number in certain error conditions.

View File

@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: dispatch.c,v 1.68 2000/09/08 22:02:21 gson Exp $ */
/* $Id: dispatch.c,v 1.69 2000/09/18 04:50:05 marka Exp $ */
#include <config.h>
@ -37,6 +37,20 @@
#include <dns/tcpmsg.h>
#include <dns/types.h>
typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
typedef struct dns_qid {
unsigned int magic;
isc_mem_t *mctx;
isc_entropy_t *entropy;
unsigned int qid_nbuckets; /* hash table size */
unsigned int qid_increment; /* id increment on collision */
isc_mutex_t lock;
isc_lfsr_t qid_lfsr1; /* state generator info */
isc_lfsr_t qid_lfsr2; /* state generator info */
dns_displist_t *qid_table; /* the table itself */
} dns_qid_t;
struct dns_dispatchmgr {
/* Unlocked. */
unsigned int magic;
@ -46,6 +60,7 @@ struct dns_dispatchmgr {
isc_mutex_t lock;
unsigned int state;
ISC_LIST(dns_dispatch_t) list;
dns_qid_t *qid;
/* Locked internally. */
isc_mutex_t pool_lock;
@ -77,8 +92,6 @@ struct dns_dispentry {
#define INVALID_BUCKET (0xffffdead)
typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
struct dns_dispatch {
/* Unlocked. */
unsigned int magic; /* magic */
@ -112,13 +125,12 @@ struct dns_dispatch {
ISC_LIST(dns_dispentry_t) rq_handlers; /* request handler list */
ISC_LIST(dns_dispatchevent_t) rq_events; /* holder for rq events */
dns_tcpmsg_t tcpmsg; /* for tcp streams */
isc_lfsr_t qid_lfsr1; /* state generator info */
isc_lfsr_t qid_lfsr2; /* state generator info */
unsigned int qid_nbuckets; /* hash table size */
unsigned int qid_increment; /* id increment on collision */
dns_displist_t *qid_table; /* the table itself */
dns_qid_t *qid;
};
#define QID_MAGIC ISC_MAGIC('Q', 'i', 'd', ' ')
#define VALID_QID(e) ISC_MAGIC_VALID((e), QID_MAGIC)
#define REQUEST_MAGIC ISC_MAGIC('D', 'r', 'q', 's')
#define VALID_REQUEST(e) ISC_MAGIC_VALID((e), REQUEST_MAGIC)
@ -131,18 +143,20 @@ struct dns_dispatch {
#define DNS_DISPATCHMGR_MAGIC ISC_MAGIC('D', 'M', 'g', 'r')
#define VALID_DISPATCHMGR(e) ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC)
#define DNS_QID(disp) ((disp)->socktype == isc_sockettype_tcp) ? \
(disp)->qid : (disp)->mgr->qid
/*
* Statics.
*/
static dns_dispentry_t *bucket_search(dns_dispatch_t *, isc_sockaddr_t *,
static dns_dispentry_t *bucket_search(dns_qid_t *, isc_sockaddr_t *,
dns_messageid_t, unsigned int);
static isc_boolean_t destroy_disp_ok(dns_dispatch_t *);
static void destroy_disp(dns_dispatch_t **);
static void udp_recv(isc_task_t *, isc_event_t *);
static void tcp_recv(isc_task_t *, isc_event_t *);
static inline void startrecv(dns_dispatch_t *);
static isc_uint32_t dns_randomid(dns_dispatch_t *);
static isc_uint32_t dns_hash(dns_dispatch_t *, isc_sockaddr_t *, isc_uint32_t);
static isc_uint32_t dns_randomid(dns_qid_t *);
static isc_uint32_t dns_hash(dns_qid_t *, isc_sockaddr_t *, isc_uint32_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_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev);
@ -150,8 +164,8 @@ static inline dns_dispatchevent_t *allocate_event(dns_dispatch_t *disp);
static void do_next_request(dns_dispatch_t *disp, dns_dispentry_t *resp);
static void do_next_response(dns_dispatch_t *disp, dns_dispentry_t *resp);
static void do_cancel(dns_dispatch_t *disp, dns_dispentry_t *resp);
static dns_dispentry_t *linear_first(dns_dispatch_t *disp);
static dns_dispentry_t *linear_next(dns_dispatch_t *disp,
static dns_dispentry_t *linear_first(dns_qid_t *disp);
static dns_dispentry_t *linear_next(dns_qid_t *disp,
dns_dispentry_t *resp);
static void dispatch_free(dns_dispatch_t **dispp);
static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr,
@ -167,6 +181,10 @@ static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr,
dns_dispatch_t **dispp);
static isc_boolean_t destroy_mgr_ok(dns_dispatchmgr_t *mgr);
static void destroy_mgr(dns_dispatchmgr_t **mgrp);
static isc_result_t qid_allocate(isc_mem_t *mctx, unsigned int buckets,
unsigned int increment,
isc_entropy_t *entropy, dns_qid_t **qidp);
static void qid_destroy(dns_qid_t **qidp);
#define LVL(x) ISC_LOG_DEBUG(x)
@ -241,13 +259,14 @@ request_log(dns_dispatch_t *disp, dns_dispentry_t *resp,
static void
reseed_lfsr(isc_lfsr_t *lfsr, void *arg)
{
dns_dispatch_t *disp = (dns_dispatch_t *)arg;
dns_dispatchmgr_t *mgr = disp->mgr;
dns_qid_t *qid = arg;
isc_result_t result;
isc_uint32_t val;
if (mgr->entropy != NULL) {
result = isc_entropy_getdata(mgr->entropy, &val, sizeof val,
REQUIRE(VALID_QID(qid));
if (qid->entropy != NULL) {
result = isc_entropy_getdata(qid->entropy, &val, sizeof val,
NULL, 0);
INSIST(result == ISC_R_SUCCESS);
lfsr->count = (val & 0x1f) + 32;
@ -263,10 +282,10 @@ reseed_lfsr(isc_lfsr_t *lfsr, void *arg)
* Return an unpredictable message ID.
*/
static isc_uint32_t
dns_randomid(dns_dispatch_t *disp) {
dns_randomid(dns_qid_t *qid) {
isc_uint32_t id;
id = isc_lfsr_generate32(&disp->qid_lfsr1, &disp->qid_lfsr2);
id = isc_lfsr_generate32(&qid->qid_lfsr1, &qid->qid_lfsr2);
return (id & 0x0000ffffU);
}
@ -275,27 +294,27 @@ dns_randomid(dns_dispatch_t *disp) {
* Return a hash of the destination and message id.
*/
static isc_uint32_t
dns_hash(dns_dispatch_t *disp, isc_sockaddr_t *dest, isc_uint32_t id) {
dns_hash(dns_qid_t *qid, isc_sockaddr_t *dest, isc_uint32_t id) {
unsigned int ret;
ret = isc_sockaddr_hash(dest, ISC_TRUE);
ret ^= (id & 0x0000ffff); /* important to mask off garbage bits */
ret %= disp->qid_nbuckets;
ret %= qid->qid_nbuckets;
INSIST(ret < disp->qid_nbuckets);
INSIST(ret < qid->qid_nbuckets);
return (ret);
}
static dns_dispentry_t *
linear_first(dns_dispatch_t *disp) {
linear_first(dns_qid_t *qid) {
dns_dispentry_t *ret;
unsigned int bucket;
bucket = 0;
while (bucket < disp->qid_nbuckets) {
ret = ISC_LIST_HEAD(disp->qid_table[bucket]);
while (bucket < qid->qid_nbuckets) {
ret = ISC_LIST_HEAD(qid->qid_table[bucket]);
if (ret != NULL)
return (ret);
bucket++;
@ -305,7 +324,7 @@ linear_first(dns_dispatch_t *disp) {
}
static dns_dispentry_t *
linear_next(dns_dispatch_t *disp, dns_dispentry_t *resp) {
linear_next(dns_qid_t *qid, dns_dispentry_t *resp) {
dns_dispentry_t *ret;
unsigned int bucket;
@ -314,8 +333,8 @@ linear_next(dns_dispatch_t *disp, dns_dispentry_t *resp) {
return (ret);
bucket = resp->bucket;
while (bucket < disp->qid_nbuckets) {
ret = ISC_LIST_HEAD(disp->qid_table[bucket]);
while (bucket < qid->qid_nbuckets) {
ret = ISC_LIST_HEAD(qid->qid_table[bucket]);
if (ret != NULL)
return (ret);
bucket++;
@ -372,14 +391,14 @@ destroy_disp(dns_dispatch_t **dispp) {
static dns_dispentry_t *
bucket_search(dns_dispatch_t *disp, isc_sockaddr_t *dest, dns_messageid_t id,
bucket_search(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id,
unsigned int bucket)
{
dns_dispentry_t *res;
REQUIRE(bucket < disp->qid_nbuckets);
REQUIRE(bucket < qid->qid_nbuckets);
res = ISC_LIST_HEAD(disp->qid_table[bucket]);
res = ISC_LIST_HEAD(qid->qid_table[bucket]);
while (res != NULL) {
if ((res->id == id) && isc_sockaddr_equal(dest, &res->host))
@ -481,12 +500,15 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
isc_boolean_t queue_request;
isc_boolean_t queue_response;
dns_dispatchmgr_t *mgr;
dns_qid_t *qid;
unsigned char *buf;
UNUSED(task);
LOCK(&disp->lock);
mgr = disp->mgr;
qid = mgr->qid;
dispatch_log(disp, LVL(90),
"got packet: requests %d, buffers %d, recvs %d",
@ -577,11 +599,16 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
free_buffer(disp, ev->region.base, ev->region.length);
goto restart;
}
isc_buffer_init(&rev->buffer, ev->region.base,
ev->region.length);
isc_buffer_add(&rev->buffer, ev->n);
/* query */
} else {
/* response */
bucket = dns_hash(disp, &ev->address, id);
resp = bucket_search(disp, &ev->address, id, bucket);
bucket = dns_hash(qid, &ev->address, id);
LOCK(&qid->lock);
resp = bucket_search(qid, &ev->address, id, bucket);
UNLOCK(&qid->lock);
dispatch_log(disp, LVL(90),
"search for response in bucket %d: %s",
bucket, (resp == NULL ? "NOT FOUND" : "FOUND"));
@ -589,13 +616,43 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
if (resp == NULL) {
free_buffer(disp, ev->region.base, ev->region.length);
goto restart;
}
}
queue_response = resp->item_out;
rev = allocate_event(disp);
rev = allocate_event(resp->disp);
if (rev == NULL) {
free_buffer(disp, ev->region.base, ev->region.length);
goto restart;
}
/*
* The kernel may deliver answers to the "wrong" socket
* if we are using "query-source address * port 53;".
* Fix up resource allocation if this happens.
*/
if (resp->disp != disp) {
if (ev->n > resp->disp->buffersize) {
free_event(resp->disp, rev);
free_buffer(disp, ev->region.base,
ev->region.length);
goto restart;
}
LOCK(&resp->disp->lock);
buf = allocate_udp_buffer(resp->disp);
UNLOCK(&resp->disp->lock);
if (buf == NULL) {
free_event(resp->disp, rev);
free_buffer(disp, ev->region.base,
ev->region.length);
goto restart;
}
isc_buffer_init(&rev->buffer, buf,
resp->disp->buffersize);
isc_buffer_putmem(&rev->buffer, ev->region.base, ev->n);
free_buffer(disp, ev->region.base, ev->region.length);
} else {
isc_buffer_init(&rev->buffer, ev->region.base,
ev->region.length);
isc_buffer_add(&rev->buffer, ev->n);
}
}
/*
@ -603,8 +660,6 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
* resp contains the information on the place to send it to.
* Send the event off.
*/
isc_buffer_init(&rev->buffer, ev->region.base, ev->region.length);
isc_buffer_add(&rev->buffer, ev->n);
rev->result = ISC_R_SUCCESS;
rev->id = id;
rev->addr = ev->address;
@ -671,12 +726,14 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
isc_boolean_t killit;
isc_boolean_t queue_request;
isc_boolean_t queue_response;
dns_qid_t *qid;
UNUSED(task);
REQUIRE(VALID_DISPATCH(disp));
mgr = disp->mgr;
qid = disp->qid;
dispatch_log(disp, LVL(90),
"got TCP packet: requests %d, buffers %d, recvs %d",
@ -788,8 +845,10 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
/*
* Response.
*/
bucket = dns_hash(disp, &tcpmsg->address, id);
resp = bucket_search(disp, &tcpmsg->address, id, bucket);
bucket = dns_hash(qid, &tcpmsg->address, id);
LOCK(&qid->lock);
resp = bucket_search(qid, &tcpmsg->address, id, bucket);
UNLOCK(&qid->lock);
dispatch_log(disp, LVL(90),
"search for response in bucket %d: %s",
bucket, (resp == NULL ? "NOT FOUND" : "FOUND"));
@ -949,6 +1008,8 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
if (mgr->entropy != NULL)
isc_entropy_detach(&mgr->entropy);
if (mgr->qid != NULL)
qid_destroy(&mgr->qid);
isc_mem_put(mctx, mgr, sizeof(dns_dispatchmgr_t));
isc_mem_detach(&mctx);
@ -1047,13 +1108,16 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
if (entropy != NULL)
isc_entropy_attach(entropy, &mgr->entropy);
mgr->qid = NULL;
result = qid_allocate(mgr->mctx, 16411, 16433, entropy, &mgr->qid);
if (result != ISC_R_SUCCESS)
goto kill_dpool;
*mgrp = mgr;
return (ISC_R_SUCCESS);
#if 0
kill_dpool:
isc_mempool_destroy(&mgr->dpool);
#endif
kill_rpool:
isc_mempool_destroy(&mgr->rpool);
kill_epool:
@ -1157,6 +1221,83 @@ dispatch_find(dns_dispatchmgr_t *mgr, isc_sockaddr_t *local,
return (result);
}
static isc_result_t
qid_allocate(isc_mem_t *mctx, unsigned int buckets, unsigned int increment,
isc_entropy_t *entropy, dns_qid_t **qidp)
{
dns_qid_t *qid;
unsigned int i;
REQUIRE(qidp != NULL && *qidp == NULL);
qid = isc_mem_get(mctx, sizeof(*qid));
if (qid == NULL)
return (ISC_R_NOMEMORY);
qid->qid_table = isc_mem_get(mctx, buckets * sizeof(dns_displist_t));
if (qid->qid_table == NULL) {
isc_mem_put(mctx, qid, sizeof(*qid));
return (ISC_R_NOMEMORY);
}
if (isc_mutex_init(&qid->lock) != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_mutex_init failed");
isc_mem_put(mctx, qid->qid_table,
buckets * sizeof(dns_displist_t));
isc_mem_put(mctx, qid, sizeof(*qid));
return (ISC_R_UNEXPECTED);
}
for (i = 0 ; i < buckets ; i++)
ISC_LIST_INIT(qid->qid_table[i]);
qid->qid_nbuckets = buckets;
qid->qid_increment = increment;
qid->entropy = NULL;
if (entropy != NULL)
isc_entropy_attach(entropy, &qid->entropy);
qid->mctx = NULL;
isc_mem_attach(mctx, &qid->mctx);
qid->magic = QID_MAGIC;
/*
* Initialize to a 32-bit LFSR. Both of these are from Applied
* Cryptography.
*
* lfsr1:
* x^32 + x^7 + x^5 + x^3 + x^2 + x + 1
*
* lfsr2:
* x^32 + x^7 + x^6 + x^2 + 1
*/
isc_lfsr_init(&qid->qid_lfsr1, 0, 32, 0x80000057U,
0, reseed_lfsr, qid);
isc_lfsr_init(&qid->qid_lfsr2, 0, 32, 0x800000c2U,
0, reseed_lfsr, qid);
*qidp = qid;
return (ISC_R_SUCCESS);
}
static void
qid_destroy(dns_qid_t **qidp) {
dns_qid_t *qid;
REQUIRE(qidp != NULL);
qid = *qidp;
REQUIRE(VALID_QID(qid));
*qidp = NULL;
qid->magic = 0;
isc_mem_put(qid->mctx, qid->qid_table,
qid->qid_nbuckets * sizeof(dns_displist_t));
if (qid->entropy != NULL)
isc_entropy_detach(&qid->entropy);
DESTROYLOCK(&qid->lock);
isc_mem_putanddetach(&qid->mctx, qid, sizeof(*qid));
}
/*
* Allocate and set important limits.
*/
@ -1164,9 +1305,8 @@ static isc_result_t
dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int buffersize,
unsigned int maxbuffers, unsigned int maxrequests,
unsigned int buckets, unsigned int increment,
dns_dispatch_t **dispp)
isc_boolean_t need_qid, dns_dispatch_t **dispp)
{
unsigned int i;
dns_dispatch_t *disp;
isc_result_t res;
@ -1203,22 +1343,17 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int buffersize,
disp->shutdown_why = ISC_R_UNEXPECTED;
disp->requests = 0;
disp->buffers = 0;
disp->qid = NULL;
ISC_LIST_INIT(disp->rq_handlers);
ISC_LIST_INIT(disp->rq_events);
disp->qid_table = isc_mem_get(mgr->mctx,
buckets * sizeof(dns_displist_t));
if (disp->qid_table == NULL) {
res = ISC_R_NOMEMORY;
goto deallocate;
if (need_qid) {
res = qid_allocate(mgr->mctx, buckets, increment, mgr->entropy,
&disp->qid);
if (res != ISC_R_SUCCESS)
goto deallocate;
}
for (i = 0 ; i < buckets ; i++)
ISC_LIST_INIT(disp->qid_table[i]);
disp->qid_nbuckets = buckets;
disp->qid_increment = increment;
if (isc_mutex_init(&disp->lock) != ISC_R_SUCCESS) {
res = ISC_R_UNEXPECTED;
UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_mutex_init failed");
@ -1254,21 +1389,6 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int buffersize,
goto kill_bpool;
}
/*
* Initialize to a 32-bit LFSR. Both of these are from Applied
* Cryptography.
*
* lfsr1:
* x^32 + x^7 + x^5 + x^3 + x^2 + x + 1
*
* lfsr2:
* x^32 + x^7 + x^6 + x^2 + 1
*/
isc_lfsr_init(&disp->qid_lfsr1, 0, 32, 0x80000057U,
0, reseed_lfsr, disp);
isc_lfsr_init(&disp->qid_lfsr2, 0, 32, 0x800000c2U,
0, reseed_lfsr, disp);
disp->magic = DISPATCH_MAGIC;
*dispp = disp;
@ -1282,8 +1402,8 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int buffersize,
kill_lock:
DESTROYLOCK(&disp->lock);
deallocate_qidtable:
isc_mem_put(mgr->mctx, disp->qid_table,
disp->qid_nbuckets * sizeof(dns_displist_t));
if (disp->qid != NULL)
qid_destroy(&disp->qid);
deallocate:
isc_mempool_put(mgr->dpool, disp);
@ -1333,14 +1453,13 @@ dispatch_free(dns_dispatch_t **dispp)
isc_mempool_destroy(&disp->bpool);
DESTROYLOCK(&disp->lock);
isc_mem_put(mgr->mctx, disp->qid_table,
disp->qid_nbuckets * sizeof(dns_displist_t));
if (disp->qid != NULL)
qid_destroy(&disp->qid);
disp->mgr = NULL;
disp->magic = 0;
isc_mempool_put(mgr->dpool, disp);
}
isc_result_t
dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
isc_taskmgr_t *taskmgr, unsigned int buffersize,
@ -1366,7 +1485,7 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
*/
disp = NULL;
result = dispatch_allocate(mgr, buffersize, maxbuffers, maxrequests,
buckets, increment, &disp);
buckets, increment, ISC_TRUE, &disp);
if (result != ISC_R_SUCCESS) {
UNLOCK(&mgr->lock);
return (result);
@ -1502,7 +1621,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
*/
disp = NULL;
result = dispatch_allocate(mgr, buffersize, maxbuffers, maxrequests,
buckets, increment, &disp);
buckets, increment, ISC_FALSE, &disp);
if (result != ISC_R_SUCCESS)
return (result);
@ -1620,6 +1739,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
dns_messageid_t id;
int i;
isc_boolean_t ok;
dns_qid_t *qid;
REQUIRE(VALID_DISPATCH(disp));
REQUIRE(task != NULL);
@ -1642,18 +1762,21 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
/*
* Try somewhat hard to find an unique ID.
*/
id = dns_randomid(disp);
bucket = dns_hash(disp, dest, id);
qid = DNS_QID(disp);
LOCK(&qid->lock);
id = dns_randomid(qid);
bucket = dns_hash(qid, dest, id);
ok = ISC_FALSE;
for (i = 0 ; i < 64 ; i++) {
if (bucket_search(disp, dest, id, bucket) == NULL) {
if (bucket_search(qid, dest, id, bucket) == NULL) {
ok = ISC_TRUE;
break;
}
id += disp->qid_increment;
id += qid->qid_increment;
id &= 0x0000ffff;
bucket = dns_hash(disp, dest, id);
bucket = dns_hash(qid, dest, id);
}
UNLOCK(&qid->lock);
if (!ok) {
UNLOCK(&disp->lock);
@ -1680,7 +1803,9 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
ISC_LIST_INIT(res->items);
ISC_LINK_INIT(res, link);
res->magic = RESPONSE_MAGIC;
ISC_LIST_APPEND(disp->qid_table[bucket], res, link);
LOCK(&qid->lock);
ISC_LIST_APPEND(qid->qid_table[bucket], res, link);
UNLOCK(&qid->lock);
request_log(disp, res, LVL(90),
"attached to task %p", res->task);
@ -1722,6 +1847,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
isc_boolean_t killit;
unsigned int n;
isc_eventlist_t events;
dns_qid_t *qid;
REQUIRE(resp != NULL);
REQUIRE(VALID_RESPONSE(*resp));
@ -1734,6 +1860,8 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
mgr = disp->mgr;
REQUIRE(VALID_DISPATCHMGR(mgr));
qid = DNS_QID(disp);
if (sockevent != NULL) {
REQUIRE(*sockevent != NULL);
ev = *sockevent;
@ -1758,7 +1886,9 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
bucket = res->bucket;
ISC_LIST_UNLINK(disp->qid_table[bucket], res, link);
LOCK(&qid->lock);
ISC_LIST_UNLINK(qid->qid_table[bucket], res, link);
UNLOCK(&qid->lock);
if (ev == NULL && res->item_out) {
/*
@ -2059,10 +2189,13 @@ do_next_request(dns_dispatch_t *disp, dns_dispentry_t *resp) {
static void
do_cancel(dns_dispatch_t *disp, dns_dispentry_t *resp) {
dns_dispatchevent_t *ev;
dns_qid_t *qid;
if (disp->shutdown_out == 1)
return;
qid = DNS_QID(disp);
/*
* If no target given, find the first request handler. If
* there are packets waiting for any handler, however, don't
@ -2083,15 +2216,20 @@ do_cancel(dns_dispatch_t *disp, dns_dispentry_t *resp) {
* Search for the first response handler without packets outstanding.
*/
if (resp == NULL) {
resp = linear_first(disp);
if (resp == NULL) /* no first item? */
LOCK(&qid->lock);
resp = linear_first(qid);
if (resp == NULL) {
/* no first item? */
UNLOCK(&qid->lock);
return;
}
do {
if (resp->item_out == ISC_FALSE)
break;
resp = linear_next(disp, resp);
resp = linear_next(qid, resp);
} while (resp != NULL);
UNLOCK(&qid->lock);
}
/*