mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-02 15:45:25 +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;
|
ifp->udpdispatch = NULL;
|
||||||
result = dns_dispatch_create(mgr->mctx, ifp->udpsocket, ifp->task,
|
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) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||||
"UDP dns_dispatch_create(): %s",
|
"UDP dns_dispatch_create(): %s",
|
||||||
|
@@ -107,7 +107,7 @@ my_accept(isc_task_t *task, isc_event_t *ev_in)
|
|||||||
*/
|
*/
|
||||||
disp = NULL;
|
disp = NULL;
|
||||||
RUNTIME_CHECK(dns_dispatch_create(mctx, ev->newsocket, task,
|
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);
|
== ISC_R_SUCCESS);
|
||||||
|
|
||||||
resp = NULL;
|
resp = NULL;
|
||||||
|
@@ -405,7 +405,8 @@ main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
disp = NULL;
|
disp = NULL;
|
||||||
RUNTIME_CHECK(dns_dispatch_create(mctx, s0, t0, 512, 6, 1024,
|
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_init(&client_lock) == ISC_R_SUCCESS);
|
||||||
RUNTIME_CHECK(isc_mutex_lock(&client_lock) == ISC_R_SUCCESS);
|
RUNTIME_CHECK(isc_mutex_lock(&client_lock) == ISC_R_SUCCESS);
|
||||||
|
@@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
struct dns_dispentry {
|
struct dns_dispentry {
|
||||||
unsigned int magic;
|
unsigned int magic;
|
||||||
dns_messageid_t id;
|
isc_uint32_t id;
|
||||||
unsigned int bucket;
|
unsigned int bucket;
|
||||||
isc_sockaddr_t host;
|
isc_sockaddr_t host;
|
||||||
isc_task_t *task;
|
isc_task_t *task;
|
||||||
@@ -87,6 +87,7 @@ struct dns_dispatch {
|
|||||||
ISC_LIST(dns_dispentry_t) rq_handlers; /* request handler list */
|
ISC_LIST(dns_dispentry_t) rq_handlers; /* request handler list */
|
||||||
ISC_LIST(dns_dispatchevent_t) rq_events; /* holder for rq events */
|
ISC_LIST(dns_dispatchevent_t) rq_events; /* holder for rq events */
|
||||||
dns_tcpmsg_t tcpmsg; /* for tcp streams */
|
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_lfsr1; /* state generator info */
|
||||||
isc_lfsr_t qid_lfsr2; /* state generator info */
|
isc_lfsr_t qid_lfsr2; /* state generator info */
|
||||||
unsigned int qid_nbuckets; /* hash table size */
|
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 udp_recv(isc_task_t *, isc_event_t *);
|
||||||
static void tcp_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 inline void startrecv(dns_dispatch_t *);
|
||||||
static dns_messageid_t randomid(dns_dispatch_t *);
|
static isc_uint32_t dns_randomid(dns_dispatch_t *);
|
||||||
static unsigned int hash(dns_dispatch_t *, isc_sockaddr_t *, dns_messageid_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 free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len);
|
||||||
static void *allocate_buffer(dns_dispatch_t *disp, 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);
|
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.
|
* Return an unpredictable message ID.
|
||||||
*/
|
*/
|
||||||
static inline dns_messageid_t
|
static isc_uint32_t
|
||||||
randomid(dns_dispatch_t *disp)
|
dns_randomid(dns_dispatch_t *disp)
|
||||||
{
|
{
|
||||||
isc_uint32_t id;
|
isc_uint32_t id;
|
||||||
|
|
||||||
id = isc_lfsr_generate32(&disp->qid_lfsr1, &disp->qid_lfsr2);
|
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 *
|
static dns_dispentry_t *
|
||||||
linear_first(dns_dispatch_t *disp)
|
linear_first(dns_dispatch_t *disp)
|
||||||
{
|
{
|
||||||
@@ -187,23 +210,6 @@ linear_next(dns_dispatch_t *disp, dns_dispentry_t *resp)
|
|||||||
return (NULL);
|
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)
|
* 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 */
|
/* query */
|
||||||
} else {
|
} else {
|
||||||
/* response */
|
/* response */
|
||||||
bucket = hash(disp, &ev->address, id);
|
bucket = disp->methods.hash(disp, &ev->address, id);
|
||||||
resp = bucket_search(disp, &ev->address, id, bucket);
|
resp = bucket_search(disp, &ev->address, id, bucket);
|
||||||
XDEBUG(("Search for response in bucket %d: %s\n",
|
XDEBUG(("Search for response in bucket %d: %s\n",
|
||||||
bucket, (resp == NULL ? "NOT FOUND" : "FOUND")));
|
bucket, (resp == NULL ? "NOT FOUND" : "FOUND")));
|
||||||
@@ -662,7 +668,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in)
|
|||||||
/* query */
|
/* query */
|
||||||
} else {
|
} else {
|
||||||
/* response */
|
/* response */
|
||||||
bucket = hash(disp, &tcpmsg->address, id);
|
bucket = disp->methods.hash(disp, &tcpmsg->address, id);
|
||||||
resp = bucket_search(disp, &tcpmsg->address, id, bucket);
|
resp = bucket_search(disp, &tcpmsg->address, id, bucket);
|
||||||
XDEBUG(("Search for response in bucket %d: %s\n",
|
XDEBUG(("Search for response in bucket %d: %s\n",
|
||||||
bucket, (resp == NULL ? "NOT FOUND" : "FOUND")));
|
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 maxbuffersize,
|
||||||
unsigned int maxbuffers, unsigned int maxrequests,
|
unsigned int maxbuffers, unsigned int maxrequests,
|
||||||
unsigned int buckets, unsigned int increment,
|
unsigned int buckets, unsigned int increment,
|
||||||
|
dns_dispatchmethods_t *methods,
|
||||||
dns_dispatch_t **dispp)
|
dns_dispatch_t **dispp)
|
||||||
{
|
{
|
||||||
dns_dispatch_t *disp;
|
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_handlers);
|
||||||
ISC_LIST_INIT(disp->rq_events);
|
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,
|
disp->qid_table = isc_mem_get(disp->mctx,
|
||||||
buckets * sizeof(dns_displist_t));
|
buckets * sizeof(dns_displist_t));
|
||||||
if (disp->qid_table == NULL) {
|
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.
|
* Try somewhat hard to find an unique ID.
|
||||||
*/
|
*/
|
||||||
id = randomid(disp);
|
id = disp->methods.randomid(disp);
|
||||||
bucket = hash(disp, dest, id);
|
bucket = disp->methods.hash(disp, dest, id);
|
||||||
ok = ISC_FALSE;
|
ok = ISC_FALSE;
|
||||||
for (i = 0 ; i < 64 ; i++) {
|
for (i = 0 ; i < 64 ; i++) {
|
||||||
if (bucket_search(disp, dest, id, bucket) == NULL) {
|
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 += disp->qid_increment;
|
||||||
id &= 0x0000ffff;
|
id &= 0x0000ffff;
|
||||||
bucket = hash(disp, dest, id);
|
bucket = disp->methods.hash(disp, dest, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
|
@@ -82,16 +82,32 @@ ISC_LANG_BEGINDECLS
|
|||||||
struct dns_dispatchevent {
|
struct dns_dispatchevent {
|
||||||
ISC_EVENT_COMMON(dns_dispatchevent_t); /* standard event common */
|
ISC_EVENT_COMMON(dns_dispatchevent_t); /* standard event common */
|
||||||
isc_result_t result; /* result code */
|
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_sockaddr_t addr; /* address recv'd from */
|
||||||
isc_buffer_t buffer; /* data buffer */
|
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
|
isc_result_t
|
||||||
dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
|
dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
|
||||||
unsigned int maxbuffersize,
|
unsigned int maxbuffersize,
|
||||||
unsigned int maxbuffers, unsigned int maxrequests,
|
unsigned int maxbuffers, unsigned int maxrequests,
|
||||||
unsigned int buckets, unsigned int increment,
|
unsigned int buckets, unsigned int increment,
|
||||||
|
dns_dispatchmethods_t *methods,
|
||||||
dns_dispatch_t **dispp);
|
dns_dispatch_t **dispp);
|
||||||
/*
|
/*
|
||||||
* Create a new dns_dispatch and attach it to the provided isc_socket_t.
|
* 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
|
* "increment" is used in a collision avoidance function, and needs to be
|
||||||
* a prime > buckets, and not 2.
|
* 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:
|
* Requires:
|
||||||
*
|
*
|
||||||
* mctx is a valid memory context.
|
* mctx is a valid memory context.
|
||||||
|
@@ -593,7 +593,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
|||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto cleanup_query;
|
goto cleanup_query;
|
||||||
result = dns_dispatch_create(res->mctx, socket, task,
|
result = dns_dispatch_create(res->mctx, socket, task,
|
||||||
4096, 2, 1, 1, 3,
|
4096, 2, 1, 1, 3, NULL,
|
||||||
&query->dispatch);
|
&query->dispatch);
|
||||||
/*
|
/*
|
||||||
* Regardless of whether dns_dispatch_create() succeeded or
|
* 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,
|
result = dns_dispatch_create(res->mctx, res->udpsocket4,
|
||||||
res->buckets[0].task, 4096,
|
res->buckets[0].task, 4096,
|
||||||
1000, 32768, 16411, 16433,
|
1000, 32768, 16411, 16433, NULL,
|
||||||
&res->dispatch4);
|
&res->dispatch4);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto cleanup_udpsocket4;
|
goto cleanup_udpsocket4;
|
||||||
@@ -3318,7 +3318,7 @@ dns_resolver_create(dns_view_t *view,
|
|||||||
goto cleanup_dispatch4;
|
goto cleanup_dispatch4;
|
||||||
result = dns_dispatch_create(res->mctx, res->udpsocket6,
|
result = dns_dispatch_create(res->mctx, res->udpsocket6,
|
||||||
res->buckets[0].task, 4096,
|
res->buckets[0].task, 4096,
|
||||||
1000, 32768, 16411, 16433,
|
1000, 32768, 16411, 16433, NULL,
|
||||||
&res->dispatch6);
|
&res->dispatch6);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto cleanup_udpsocket6;
|
goto cleanup_udpsocket6;
|
||||||
|
Reference in New Issue
Block a user