mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
Start moving the dispatcher code to allow it to be used for wire format as well as for lightweight resolver daemon stuff.
This commit is contained in:
@@ -150,7 +150,8 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
*/
|
||||
ifp->udpdispatch = NULL;
|
||||
result = dns_dispatch_create(mgr->mctx, ifp->udpsocket, ifp->task,
|
||||
4096, 50, 50, 17, 19, &ifp->udpdispatch);
|
||||
4096, 50, 50, 17, 19, NULL,
|
||||
&ifp->udpdispatch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"UDP dns_dispatch_create(): %s",
|
||||
|
@@ -107,7 +107,7 @@ my_accept(isc_task_t *task, isc_event_t *ev_in)
|
||||
*/
|
||||
disp = NULL;
|
||||
RUNTIME_CHECK(dns_dispatch_create(mctx, ev->newsocket, task,
|
||||
512, 6, 1024, 17, 19, &disp)
|
||||
512, 6, 1024, 17, 19, NULL, &disp)
|
||||
== ISC_R_SUCCESS);
|
||||
|
||||
resp = NULL;
|
||||
|
@@ -405,7 +405,8 @@ main(int argc, char *argv[])
|
||||
*/
|
||||
disp = NULL;
|
||||
RUNTIME_CHECK(dns_dispatch_create(mctx, s0, t0, 512, 6, 1024,
|
||||
17, 19, &disp) == ISC_R_SUCCESS);
|
||||
17, 19, NULL, &disp)
|
||||
== ISC_R_SUCCESS);
|
||||
|
||||
RUNTIME_CHECK(isc_mutex_init(&client_lock) == ISC_R_SUCCESS);
|
||||
RUNTIME_CHECK(isc_mutex_lock(&client_lock) == ISC_R_SUCCESS);
|
||||
|
@@ -45,7 +45,7 @@
|
||||
|
||||
struct dns_dispentry {
|
||||
unsigned int magic;
|
||||
dns_messageid_t id;
|
||||
isc_uint32_t id;
|
||||
unsigned int bucket;
|
||||
isc_sockaddr_t host;
|
||||
isc_task_t *task;
|
||||
@@ -87,6 +87,7 @@ 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 */
|
||||
dns_dispatchmethods_t methods; /* methods to use */
|
||||
isc_lfsr_t qid_lfsr1; /* state generator info */
|
||||
isc_lfsr_t qid_lfsr2; /* state generator info */
|
||||
unsigned int qid_nbuckets; /* hash table size */
|
||||
@@ -112,8 +113,8 @@ static void destroy(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 dns_messageid_t randomid(dns_dispatch_t *);
|
||||
static unsigned int hash(dns_dispatch_t *, isc_sockaddr_t *, dns_messageid_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 void free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len);
|
||||
static void *allocate_buffer(dns_dispatch_t *disp, unsigned int len);
|
||||
static inline void free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev);
|
||||
@@ -138,16 +139,38 @@ reseed_lfsr(isc_lfsr_t *lfsr, void *arg)
|
||||
/*
|
||||
* Return an unpredictable message ID.
|
||||
*/
|
||||
static inline dns_messageid_t
|
||||
randomid(dns_dispatch_t *disp)
|
||||
static isc_uint32_t
|
||||
dns_randomid(dns_dispatch_t *disp)
|
||||
{
|
||||
isc_uint32_t id;
|
||||
|
||||
id = isc_lfsr_generate32(&disp->qid_lfsr1, &disp->qid_lfsr2);
|
||||
|
||||
return ((dns_messageid_t)(id & 0x0000ffff));
|
||||
return (id & 0x0000ffffU);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
unsigned int ret;
|
||||
|
||||
ret = isc_sockaddr_hash(dest, ISC_TRUE);
|
||||
ret ^= (id & 0x0000ffff); /* important to mask off garbage bits */
|
||||
ret %= disp->qid_nbuckets;
|
||||
|
||||
INSIST(ret < disp->qid_nbuckets);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static dns_dispatchmethods_t dns_wire_methods = {
|
||||
dns_randomid,
|
||||
dns_hash
|
||||
};
|
||||
|
||||
static dns_dispentry_t *
|
||||
linear_first(dns_dispatch_t *disp)
|
||||
{
|
||||
@@ -187,23 +210,6 @@ linear_next(dns_dispatch_t *disp, dns_dispentry_t *resp)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a hash of the destination and message id.
|
||||
*/
|
||||
static unsigned int
|
||||
hash(dns_dispatch_t *disp, isc_sockaddr_t *dest, dns_messageid_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;
|
||||
|
||||
INSIST(ret < disp->qid_nbuckets);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when refcount reaches 0 (and safe to destroy)
|
||||
*/
|
||||
@@ -476,7 +482,7 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in)
|
||||
/* query */
|
||||
} else {
|
||||
/* response */
|
||||
bucket = hash(disp, &ev->address, id);
|
||||
bucket = disp->methods.hash(disp, &ev->address, id);
|
||||
resp = bucket_search(disp, &ev->address, id, bucket);
|
||||
XDEBUG(("Search for response in bucket %d: %s\n",
|
||||
bucket, (resp == NULL ? "NOT FOUND" : "FOUND")));
|
||||
@@ -662,7 +668,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in)
|
||||
/* query */
|
||||
} else {
|
||||
/* response */
|
||||
bucket = hash(disp, &tcpmsg->address, id);
|
||||
bucket = disp->methods.hash(disp, &tcpmsg->address, id);
|
||||
resp = bucket_search(disp, &tcpmsg->address, id, bucket);
|
||||
XDEBUG(("Search for response in bucket %d: %s\n",
|
||||
bucket, (resp == NULL ? "NOT FOUND" : "FOUND")));
|
||||
@@ -785,6 +791,7 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
|
||||
unsigned int maxbuffersize,
|
||||
unsigned int maxbuffers, unsigned int maxrequests,
|
||||
unsigned int buckets, unsigned int increment,
|
||||
dns_dispatchmethods_t *methods,
|
||||
dns_dispatch_t **dispp)
|
||||
{
|
||||
dns_dispatch_t *disp;
|
||||
@@ -831,6 +838,11 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
|
||||
ISC_LIST_INIT(disp->rq_handlers);
|
||||
ISC_LIST_INIT(disp->rq_events);
|
||||
|
||||
if (methods == NULL)
|
||||
disp->methods = dns_wire_methods;
|
||||
else
|
||||
disp->methods = *methods;
|
||||
|
||||
disp->qid_table = isc_mem_get(disp->mctx,
|
||||
buckets * sizeof(dns_displist_t));
|
||||
if (disp->qid_table == NULL) {
|
||||
@@ -1023,8 +1035,8 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
|
||||
/*
|
||||
* Try somewhat hard to find an unique ID.
|
||||
*/
|
||||
id = randomid(disp);
|
||||
bucket = hash(disp, dest, id);
|
||||
id = disp->methods.randomid(disp);
|
||||
bucket = disp->methods.hash(disp, dest, id);
|
||||
ok = ISC_FALSE;
|
||||
for (i = 0 ; i < 64 ; i++) {
|
||||
if (bucket_search(disp, dest, id, bucket) == NULL) {
|
||||
@@ -1033,7 +1045,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
|
||||
}
|
||||
id += disp->qid_increment;
|
||||
id &= 0x0000ffff;
|
||||
bucket = hash(disp, dest, id);
|
||||
bucket = disp->methods.hash(disp, dest, id);
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
|
@@ -82,16 +82,32 @@ ISC_LANG_BEGINDECLS
|
||||
struct dns_dispatchevent {
|
||||
ISC_EVENT_COMMON(dns_dispatchevent_t); /* standard event common */
|
||||
isc_result_t result; /* result code */
|
||||
isc_int16_t id; /* message id */
|
||||
isc_int32_t id; /* message id */
|
||||
isc_sockaddr_t addr; /* address recv'd from */
|
||||
isc_buffer_t buffer; /* data buffer */
|
||||
};
|
||||
|
||||
/*
|
||||
* Functions to:
|
||||
*
|
||||
* Return if a packet is a query or a response,
|
||||
* Hash IDs,
|
||||
* Generate a new random ID,
|
||||
* Compare entries (IDs) for equality,
|
||||
*/
|
||||
struct dns_dispatchmethods {
|
||||
isc_uint32_t (*randomid)(dns_dispatch_t *);
|
||||
isc_uint32_t (*hash)(dns_dispatch_t *, isc_sockaddr_t *,
|
||||
isc_uint32_t);
|
||||
};
|
||||
typedef struct dns_dispatchmethods dns_dispatchmethods_t;
|
||||
|
||||
isc_result_t
|
||||
dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
|
||||
unsigned int maxbuffersize,
|
||||
unsigned int maxbuffers, unsigned int maxrequests,
|
||||
unsigned int buckets, unsigned int increment,
|
||||
dns_dispatchmethods_t *methods,
|
||||
dns_dispatch_t **dispp);
|
||||
/*
|
||||
* Create a new dns_dispatch and attach it to the provided isc_socket_t.
|
||||
@@ -108,6 +124,10 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
|
||||
* "increment" is used in a collision avoidance function, and needs to be
|
||||
* a prime > buckets, and not 2.
|
||||
*
|
||||
* "methods" be NULL for normal DNS wire format, or all elements in that
|
||||
* structure be filled in with function pointers to control dispatch
|
||||
* behavior.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* mctx is a valid memory context.
|
||||
|
@@ -593,7 +593,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_query;
|
||||
result = dns_dispatch_create(res->mctx, socket, task,
|
||||
4096, 2, 1, 1, 3,
|
||||
4096, 2, 1, 1, 3, NULL,
|
||||
&query->dispatch);
|
||||
/*
|
||||
* Regardless of whether dns_dispatch_create() succeeded or
|
||||
@@ -3296,7 +3296,7 @@ dns_resolver_create(dns_view_t *view,
|
||||
}
|
||||
result = dns_dispatch_create(res->mctx, res->udpsocket4,
|
||||
res->buckets[0].task, 4096,
|
||||
1000, 32768, 16411, 16433,
|
||||
1000, 32768, 16411, 16433, NULL,
|
||||
&res->dispatch4);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_udpsocket4;
|
||||
@@ -3318,7 +3318,7 @@ dns_resolver_create(dns_view_t *view,
|
||||
goto cleanup_dispatch4;
|
||||
result = dns_dispatch_create(res->mctx, res->udpsocket6,
|
||||
res->buckets[0].task, 4096,
|
||||
1000, 32768, 16411, 16433,
|
||||
1000, 32768, 16411, 16433, NULL,
|
||||
&res->dispatch6);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_udpsocket6;
|
||||
|
Reference in New Issue
Block a user