2
0
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:
Michael Graff
2000-01-07 01:17:47 +00:00
parent 8a9b755d32
commit 0941f35ad9
6 changed files with 69 additions and 35 deletions

View File

@@ -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",

View File

@@ -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;

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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;