implement dns_dispatchmgr_t, replacing dns_dispatchlist_t. Use it throughout the library/server.

This commit is contained in:
Michael Graff
2000-05-10 21:34:50 +00:00
parent f019e00452
commit ca9739800f
19 changed files with 575 additions and 554 deletions

View File

@@ -26,6 +26,7 @@
#include <dns/cache.h>
#include <dns/db.h>
#include <dns/dispatch.h>
#include <dns/log.h>
#include <dns/resolver.h>
#include <dns/result.h>
@@ -53,6 +54,7 @@ dns_view_t *view;
isc_taskmgr_t *taskmgr;
isc_socketmgr_t *sockmgr;
isc_timermgr_t *timermgr;
dns_dispatchmgr_t *dispatchmgr;
isc_sockaddrlist_t forwarders;
@@ -88,7 +90,7 @@ create_view(isc_mem_t *mctx) {
* XXXMLG hardwired number of tasks.
*/
result = dns_view_createresolver(view, taskmgr, 16, sockmgr,
timermgr, 0, NULL, NULL);
timermgr, dispatchmgr, 0, NULL, NULL);
if (result != ISC_R_SUCCESS)
goto out;
@@ -271,6 +273,13 @@ main(int argc, char **argv) {
result = isc_timermgr_create(mem, &timermgr);
INSIST(result == ISC_R_SUCCESS);
/*
* Create a dispatch manager.
*/
dispatchmgr = NULL;
result = dns_dispatchmgr_create(mem, &dispatchmgr);
INSIST(result == ISC_R_SUCCESS);
/*
* Read resolv.conf to get our forwarders.
*/

View File

@@ -39,6 +39,7 @@
EXTERN isc_mem_t * ns_g_mctx INIT(NULL);
EXTERN unsigned int ns_g_cpus INIT(1);
EXTERN isc_taskmgr_t * ns_g_taskmgr INIT(NULL);
EXTERN dns_dispatchmgr_t * ns_g_dispatchmgr INIT(NULL);
/*
* XXXRTH We're going to want multiple timer managers eventually. One
* for really short timers, another for client timers, and one

View File

@@ -87,8 +87,9 @@ struct ns_interface {
isc_result_t
ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_socketmgr_t *socketmgr, ns_clientmgr_t *clientmgr,
ns_interfacemgr_t **mgrp);
isc_socketmgr_t *socketmgr,
dns_dispatchmgr_t *dispatchmgr,
ns_clientmgr_t *clientmgr, ns_interfacemgr_t **mgrp);
void
ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target);

View File

@@ -42,6 +42,7 @@ struct ns_interfacemgr {
isc_mem_t * mctx; /* Memory context. */
isc_taskmgr_t * taskmgr; /* Task manager. */
isc_socketmgr_t * socketmgr; /* Socket manager. */
dns_dispatchmgr_t * dispatchmgr;
ns_clientmgr_t * clientmgr; /* Client manager. */
unsigned int generation; /* Current generation no. */
ns_listenlist_t * listenon;
@@ -71,8 +72,9 @@ sockaddr_format(isc_sockaddr_t *sa, char *array, unsigned int size) {
isc_result_t
ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_socketmgr_t *socketmgr, ns_clientmgr_t *clientmgr,
ns_interfacemgr_t **mgrp)
isc_socketmgr_t *socketmgr,
dns_dispatchmgr_t *dispatchmgr,
ns_clientmgr_t *clientmgr, ns_interfacemgr_t **mgrp)
{
isc_result_t result;
ns_interfacemgr_t *mgr;
@@ -92,6 +94,7 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
mgr->mctx = mctx;
mgr->taskmgr = taskmgr;
mgr->socketmgr = socketmgr;
mgr->dispatchmgr = dispatchmgr;
mgr->clientmgr = clientmgr;
mgr->generation = 1;
mgr->listenon = NULL;
@@ -245,6 +248,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
static isc_result_t
ns_interface_listenudp(ns_interface_t *ifp) {
isc_result_t result;
unsigned int attrs;
/*
* Open a UDP socket.
@@ -266,9 +270,17 @@ ns_interface_listenudp(ns_interface_t *ifp) {
isc_result_totext(result));
goto udp_bind_failure;
}
result = dns_dispatch_create(ifp->mgr->mctx, ifp->udpsocket, ifp->task,
4096, 1000, 32768, 8219, 8237, NULL,
&ifp->udpdispatch);
attrs = 0;
attrs |= DNS_DISPATCHATTR_UDP;
if (isc_sockaddr_pf(&ifp->addr) == AF_INET)
attrs |= DNS_DISPATCHATTR_IPV4;
else
attrs |= DNS_DISPATCHATTR_IPV6;
attrs |= DNS_DISPATCHATTR_MAKEQUERY;
attrs |= DNS_DISPATCHATTR_ACCEPTREQUEST;
result = dns_dispatch_create(ifp->mgr->dispatchmgr, ifp->udpsocket,
ifp->task, 4096, 1000, 32768, 8219,
8237, NULL, attrs, &ifp->udpdispatch);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"UDP dns_dispatch_create(): %s",

View File

@@ -25,6 +25,8 @@
#include <isc/timer.h>
#include <isc/util.h>
#include <dns/dispatch.h>
#include <dst/result.h>
/*
@@ -258,6 +260,14 @@ create_managers() {
return (ISC_R_UNEXPECTED);
}
result = dns_dispatchmgr_create(ns_g_mctx, &ns_g_dispatchmgr);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"dns_dispatchmgr_create() failed: %s",
isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
return (ISC_R_SUCCESS);
}
@@ -274,6 +284,7 @@ destroy_managers(void) {
isc_taskmgr_destroy(&ns_g_taskmgr);
isc_timermgr_destroy(&ns_g_timermgr);
isc_socketmgr_destroy(&ns_g_socketmgr);
dns_dispatchmgr_destroy(&ns_g_dispatchmgr);
}
static void

View File

@@ -356,7 +356,8 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview,
*/
CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31,
ns_g_socketmgr, ns_g_timermgr,
0, dispatchv4, dispatchv6));
0, ns_g_dispatchmgr,
dispatchv4, dispatchv6));
/*
* Set resolver forwarding policy.
@@ -866,6 +867,7 @@ static isc_result_t
configure_server_querysource(dns_c_ctx_t *cctx, ns_server_t *server, int af,
dns_dispatch_t **dispatchp) {
isc_result_t result;
unsigned int attrs;
struct in_addr ina;
isc_sockaddr_t sa, any4, any6, *any;
isc_socket_t *socket;
@@ -982,10 +984,18 @@ configure_server_querysource(dns_c_ctx_t *cctx, ns_server_t *server, int af,
isc_socket_detach(&socket);
return (result);
}
result = dns_dispatch_create(ns_g_mctx, socket,
attrs = 0;
attrs = DNS_DISPATCHATTR_UDP;
attrs |= DNS_DISPATCHATTR_PRIVATE;
if (af == AF_INET)
attrs |= DNS_DISPATCHATTR_IPV4;
else
attrs |= DNS_DISPATCHATTR_IPV6;
attrs |= DNS_DISPATCHATTR_MAKEQUERY;
result = dns_dispatch_create(ns_g_dispatchmgr, socket,
server->task, 4096,
1000, 32768, 16411, 16433, NULL,
server_dispatchp);
attrs, server_dispatchp);
/*
* Regardless of whether dns_dispatch_create() succeeded or
* failed, we don't need to keep the reference to the socket.
@@ -1390,7 +1400,8 @@ run_server(isc_task_t *task, isc_event_t *event) {
"creating client manager");
CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr,
ns_g_socketmgr, server->clientmgr,
ns_g_socketmgr, ns_g_dispatchmgr,
server->clientmgr,
&server->interfacemgr),
"creating interface manager");

View File

@@ -119,7 +119,6 @@ DNSSAFEOBJS = sec/dnssafe/ahchdig.@O@ sec/dnssafe/ahchencr.@O@ \
OBJS = a6.@O@ acl.@O@ aclconf.@O@ adb.@O@ byaddr.@O@ \
cache.@O@ callbacks.@O@ compress.@O@ \
db.@O@ dbiterator.@O@ dbtable.@O@ dispatch.@O@ dnssec.@O@ \
dispatchlist.@O@ \
journal.@O@ keytable.@O@ lib.@O@ log.@O@ \
master.@O@ masterdump.@O@ message.@O@ \
name.@O@ ncache.@O@ nxt.@O@ peer.@O@ \
@@ -135,7 +134,6 @@ OBJS = a6.@O@ acl.@O@ aclconf.@O@ adb.@O@ byaddr.@O@ \
SRCS = a6.c acl.c aclconf.c adb.c byaddr.c \
cache.c callbacks.c compress.c \
db.c dbiterator.c dbtable.c dispatch.c dnssec.c \
dispatchlist.c \
journal.c keytable.c lib.c log.c \
master.c masterdump.c message.c \
name.c ncache.c nxt.c peer.c \

View File

@@ -20,7 +20,9 @@
#include <stdlib.h>
#include <isc/lfsr.h>
#include <isc/list.h>
#include <isc/mem.h>
#include <isc/mutex.h>
#include <isc/print.h>
#include <isc/task.h>
#include <isc/util.h>
@@ -30,6 +32,23 @@
#include <dns/log.h>
#include <dns/message.h>
#include <dns/tcpmsg.h>
#include <dns/types.h>
struct dns_dispatchmgr {
/* Unlocked. */
unsigned int magic;
isc_mem_t *mctx;
/* Locked by "lock". */
isc_mutex_t lock;
unsigned int state;
ISC_LIST(dns_dispatch_t) list;
};
#define MGR_SHUTTINGDOWN 0x00000001U
#define MGR_IS_SHUTTINGDOWN(l) (((l)->state & MGR_SHUTTINGDOWN) != 0)
#define IS_PRIVATE(d) (((d)->attributes & DNS_DISPATCHATTR_PRIVATE) != 0)
struct dns_dispentry {
unsigned int magic;
@@ -51,14 +70,18 @@ typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
struct dns_dispatch {
/* Unlocked. */
unsigned int magic; /* magic */
isc_mem_t *mctx; /* memory context */
dns_dispatchmgr_t *mgr; /* dispatch manager */
isc_task_t *task; /* internal task */
isc_socket_t *socket; /* isc socket attached to */
unsigned int buffersize; /* size of each buffer */
unsigned int maxrequests; /* max requests */
unsigned int maxbuffers; /* max buffers */
/* Locked. */
/* Locked by mgr->lock. */
unsigned int attributes;
ISC_LINK(dns_dispatch_t) link;
/* Locked by "lock". */
isc_mutex_t lock; /* locks all below */
unsigned int refcount; /* number of users */
isc_mempool_t *epool; /* memory pool for events */
@@ -83,21 +106,24 @@ struct dns_dispatch {
dns_displist_t *qid_table; /* the table itself */
};
#define REQUEST_MAGIC 0x53912051 /* "random" value */
#define VALID_REQUEST(e) ((e) != NULL && (e)->magic == REQUEST_MAGIC)
#define REQUEST_MAGIC ISC_MAGIC('D', 'r', 'q', 's')
#define VALID_REQUEST(e) ISC_MAGIC_VALID((e), REQUEST_MAGIC)
#define RESPONSE_MAGIC 0x15021935 /* "random" value */
#define VALID_RESPONSE(e) ((e) != NULL && (e)->magic == RESPONSE_MAGIC)
#define RESPONSE_MAGIC ISC_MAGIC('D', 'r', 's', 'p')
#define VALID_RESPONSE(e) ISC_MAGIC_VALID((e), RESPONSE_MAGIC)
#define DISPATCH_MAGIC 0x69385829 /* "random" value */
#define VALID_DISPATCH(e) ((e) != NULL && (e)->magic == DISPATCH_MAGIC)
#define DISPATCH_MAGIC ISC_MAGIC('D', 'i', 's', 'p')
#define VALID_DISPATCH(e) ISC_MAGIC_VALID((e), DISPATCH_MAGIC)
#define DNS_DISPATCHMGR_MAGIC ISC_MAGIC('D', 'M', 'g', 'r')
#define VALID_DISPATCHMGR(e) ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC)
/*
* statics.
*/
static dns_dispentry_t *bucket_search(dns_dispatch_t *, isc_sockaddr_t *,
dns_messageid_t, unsigned int);
static void destroy(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 *);
@@ -124,7 +150,8 @@ static dns_dispentry_t *linear_next(dns_dispatch_t *disp,
* The resulting string is guaranteed to be null-terminated.
*/
static void
sockaddr_format(isc_sockaddr_t *sa, char *array, unsigned int size) {
sockaddr_format(isc_sockaddr_t *sa, char *array, unsigned int size)
{
isc_result_t result;
isc_buffer_t buf;
@@ -182,7 +209,8 @@ request_log(dns_dispatch_t *disp, dns_dispentry_t *resp,
}
static void
reseed_lfsr(isc_lfsr_t *lfsr, void *arg) {
reseed_lfsr(isc_lfsr_t *lfsr, void *arg)
{
UNUSED(arg);
lfsr->count = (random() & 0x1f) + 32; /* From 32 to 63 states */
@@ -194,7 +222,8 @@ 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_dispatch_t *disp)
{
isc_uint32_t id;
id = isc_lfsr_generate32(&disp->qid_lfsr1, &disp->qid_lfsr2);
@@ -206,7 +235,8 @@ 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_dispatch_t *disp, isc_sockaddr_t *dest, isc_uint32_t id)
{
unsigned int ret;
ret = isc_sockaddr_hash(dest, ISC_TRUE);
@@ -224,7 +254,8 @@ static dns_dispatchmethods_t dns_wire_methods = {
};
static dns_dispentry_t *
linear_first(dns_dispatch_t *disp) {
linear_first(dns_dispatch_t *disp)
{
dns_dispentry_t *ret;
unsigned int bucket;
@@ -241,7 +272,8 @@ linear_first(dns_dispatch_t *disp) {
}
static dns_dispentry_t *
linear_next(dns_dispatch_t *disp, dns_dispentry_t *resp) {
linear_next(dns_dispatch_t *disp, dns_dispentry_t *resp)
{
dns_dispentry_t *ret;
unsigned int bucket;
@@ -261,11 +293,21 @@ linear_next(dns_dispatch_t *disp, dns_dispentry_t *resp) {
}
/*
* Called when refcount reaches 0 (and safe to destroy)
* Called when refcount reaches 0 (and safe to destroy).
*
* The dispatch lock must NOT be locked, and the manager lock MUST be
* locked.
*/
static void
destroy(dns_dispatch_t *disp) {
destroy_disp(dns_dispatch_t *disp)
{
dns_dispatchevent_t *ev;
dns_dispatchmgr_t *mgr;
mgr = disp->mgr;
disp->mgr = NULL;
ISC_LIST_UNLINK(mgr->list, disp, link);
disp->magic = 0;
@@ -299,10 +341,10 @@ destroy(dns_dispatch_t *disp) {
isc_mempool_destroy(&disp->rpool);
isc_mempool_destroy(&disp->bpool);
isc_mempool_destroy(&disp->epool);
isc_mem_put(disp->mctx, disp->qid_table,
isc_mem_put(mgr->mctx, disp->qid_table,
disp->qid_nbuckets * sizeof(dns_displist_t));
isc_mem_put(disp->mctx, disp, sizeof(dns_dispatch_t));
isc_mem_put(mgr->mctx, disp, sizeof(dns_dispatch_t));
}
@@ -326,7 +368,8 @@ bucket_search(dns_dispatch_t *disp, isc_sockaddr_t *dest, dns_messageid_t id,
}
static void
free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {
free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len)
{
isc_sockettype_t socktype;
INSIST(buf != NULL && len != 0);
@@ -337,13 +380,13 @@ free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {
switch (socktype) {
case isc_sockettype_tcp:
isc_mem_put(disp->mctx, buf, len);
isc_mem_put(disp->mgr->mctx, buf, len);
break;
case isc_sockettype_udp:
if (len == disp->buffersize)
isc_mempool_put(disp->bpool, buf);
else
isc_mem_put(disp->mctx, buf, len);
isc_mem_put(disp->mgr->mctx, buf, len);
break;
default:
INSIST(0);
@@ -352,7 +395,8 @@ free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {
}
static void *
allocate_buffer(dns_dispatch_t *disp, unsigned int len) {
allocate_buffer(dns_dispatch_t *disp, unsigned int len)
{
void *temp;
INSIST(len > 0);
@@ -360,7 +404,7 @@ allocate_buffer(dns_dispatch_t *disp, unsigned int len) {
if (len == disp->buffersize)
temp = isc_mempool_get(disp->bpool);
else
temp = isc_mem_get(disp->mctx, len);
temp = isc_mem_get(disp->mgr->mctx, len);
if (temp != NULL)
disp->buffers++;
@@ -369,7 +413,8 @@ allocate_buffer(dns_dispatch_t *disp, unsigned int len) {
}
static inline void
free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev) {
free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev)
{
if (disp->failsafe_ev == ev) {
INSIST(disp->shutdown_out == 1);
disp->shutdown_out = 0;
@@ -381,7 +426,8 @@ free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev) {
}
static inline dns_dispatchevent_t *
allocate_event(dns_dispatch_t *disp) {
allocate_event(dns_dispatch_t *disp)
{
dns_dispatchevent_t *ev;
ev = isc_mempool_get(disp->epool);
@@ -413,7 +459,8 @@ allocate_event(dns_dispatch_t *disp) {
* restart.
*/
static void
udp_recv(isc_task_t *task, isc_event_t *ev_in) {
udp_recv(isc_task_t *task, isc_event_t *ev_in)
{
isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
dns_dispatch_t *disp = ev_in->ev_arg;
dns_messageid_t id;
@@ -451,7 +498,7 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
UNLOCK(&disp->lock);
if (killit)
destroy(disp);
destroy_disp(disp);
isc_event_free(&ev_in);
return;
@@ -596,7 +643,8 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
* restart.
*/
static void
tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
tcp_recv(isc_task_t *task, isc_event_t *ev_in)
{
dns_dispatch_t *disp = ev_in->ev_arg;
dns_tcpmsg_t *tcpmsg = &disp->tcpmsg;
dns_messageid_t id;
@@ -652,13 +700,13 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
/*
* The event is statically allocated in the tcpmsg
* structure, and destroy() frees the tcpmsg, so we must
* free the event *before* calling destroy().
* structure, and destroy_disp() frees the tcpmsg, so we must
* free the event *before* calling destroy_disp().
*/
isc_event_free(&ev_in);
if (killit)
destroy(disp);
destroy_disp(disp);
return;
@@ -767,7 +815,8 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
* disp must be locked.
*/
static void
startrecv(dns_dispatch_t *disp) {
startrecv(dns_dispatch_t *disp)
{
isc_sockettype_t socktype;
isc_result_t res;
isc_region_t region;
@@ -825,16 +874,142 @@ startrecv(dns_dispatch_t *disp) {
}
}
/*
* Mgr must be locked when calling this function.
*/
static isc_boolean_t
destroy_mgr_ok(dns_dispatchmgr_t *mgr)
{
if (!MGR_IS_SHUTTINGDOWN(mgr))
return (ISC_FALSE);
if (!ISC_LIST_EMPTY(mgr->list))
return (ISC_FALSE);
return (ISC_TRUE);
}
/*
* Mgr must be unlocked when calling this function.
*/
static void
destroy_mgr(dns_dispatchmgr_t **mgrp)
{
isc_mem_t *mctx;
dns_dispatchmgr_t *mgr;
mgr = *mgrp;
*mgrp = NULL;
mctx = mgr->mctx;
mgr->magic = 0;
mgr->mctx = 0;
isc_mutex_destroy(&mgr->lock);
mgr->state = 0;
isc_mem_put(mctx, mgr, sizeof(dns_dispatchmgr_t));
isc_mem_detach(&mctx);
}
/*
* Publics.
*/
isc_result_t
dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
unsigned int maxbuffersize,
dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp)
{
dns_dispatchmgr_t *mgr;
isc_result_t result;
REQUIRE(mctx != NULL);
REQUIRE(mgrp != NULL && *mgrp == NULL);
mgr = isc_mem_get(mctx, sizeof(dns_dispatchmgr_t));
if (mgr == NULL)
return (ISC_R_NOMEMORY);
result = isc_mutex_init(&mgr->lock);
if (result != ISC_R_SUCCESS) {
isc_mem_put(mctx, mgr, sizeof(dns_dispatchmgr_t));
return (result);
}
mgr->magic = DNS_DISPATCHMGR_MAGIC;
mgr->state = 0;
mgr->mctx = NULL;
isc_mem_attach(mctx, &mgr->mctx);
ISC_LIST_INIT(mgr->list);
*mgrp = mgr;
return (ISC_R_SUCCESS);
}
void
dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp)
{
dns_dispatchmgr_t *mgr;
isc_boolean_t killit;
REQUIRE(mgrp != NULL);
REQUIRE(VALID_DISPATCHMGR(*mgrp));
mgr = *mgrp;
*mgrp = NULL;
LOCK(&mgr->lock);
mgr->state |= MGR_SHUTTINGDOWN;
killit = destroy_mgr_ok(mgr);
UNLOCK(&mgr->lock);
if (killit)
destroy_mgr(&mgr);
}
#define ATTRMATCH(_a1, _a2, _mask) (((_a1) & (_mask)) == ((_a2) & (_mask)))
isc_result_t
dns_dispatchmgr_find(dns_dispatchmgr_t *mgr, unsigned int attributes,
unsigned int mask, dns_dispatch_t **dispp)
{
dns_dispatch_t *disp;
isc_result_t result;
REQUIRE(VALID_DISPATCHMGR(mgr));
REQUIRE(dispp != NULL && *dispp == NULL);
LOCK(&mgr->lock);
disp = ISC_LIST_HEAD(mgr->list);
while (disp != NULL) {
if (!IS_PRIVATE(disp)
&& ATTRMATCH(disp->attributes, attributes, mask))
break;
disp = ISC_LIST_NEXT(disp, link);
}
if (disp == NULL) {
result = ISC_R_NOTFOUND;
goto out;
}
dns_dispatch_attach(disp, dispp);
result = ISC_R_SUCCESS;
out:
UNLOCK(&mgr->lock);
return (result);
}
isc_result_t
dns_dispatch_create(dns_dispatchmgr_t *mgr, 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_dispatchmethods_t *methods, unsigned int attributes,
dns_dispatch_t **dispp)
{
dns_dispatch_t *disp;
@@ -842,7 +1017,7 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
isc_sockettype_t socktype;
unsigned int i;
REQUIRE(mctx != NULL);
REQUIRE(VALID_DISPATCHMGR(mgr));
REQUIRE(sock != NULL);
REQUIRE(task != NULL);
REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
@@ -857,15 +1032,16 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
res = ISC_R_SUCCESS;
disp = isc_mem_get(mctx, sizeof(dns_dispatch_t));
disp = isc_mem_get(mgr->mctx, sizeof(dns_dispatch_t));
if (disp == NULL)
return (ISC_R_NOMEMORY);
disp->magic = 0;
disp->mctx = mctx;
disp->buffersize = maxbuffersize;
disp->maxrequests = maxrequests;
disp->maxbuffers = maxbuffers;
disp->attributes = attributes;
ISC_LINK_INIT(disp, link);
disp->refcount = 1;
disp->recvs = 0;
if (socktype == isc_sockettype_udp) {
@@ -886,7 +1062,7 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
else
disp->methods = *methods;
disp->qid_table = isc_mem_get(disp->mctx,
disp->qid_table = isc_mem_get(mgr->mctx,
buckets * sizeof(dns_displist_t));
if (disp->qid_table == NULL) {
res = ISC_R_NOMEMORY;
@@ -906,7 +1082,7 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
}
disp->epool = NULL;
if (isc_mempool_create(mctx, sizeof(dns_dispatchevent_t),
if (isc_mempool_create(mgr->mctx, sizeof(dns_dispatchevent_t),
&disp->epool) != ISC_R_SUCCESS) {
res = ISC_R_NOMEMORY;
goto out3;
@@ -914,7 +1090,7 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
isc_mempool_setname(disp->epool, "disp_epool");
disp->bpool = NULL;
if (isc_mempool_create(mctx, maxbuffersize,
if (isc_mempool_create(mgr->mctx, maxbuffersize,
&disp->bpool) != ISC_R_SUCCESS) {
res = ISC_R_NOMEMORY;
goto out4;
@@ -923,7 +1099,7 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
isc_mempool_setname(disp->bpool, "disp_bpool");
disp->rpool = NULL;
if (isc_mempool_create(mctx, sizeof(dns_dispentry_t),
if (isc_mempool_create(mgr->mctx, sizeof(dns_dispentry_t),
&disp->rpool) != ISC_R_SUCCESS) {
res = ISC_R_NOMEMORY;
goto out5;
@@ -968,6 +1144,7 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
0, reseed_lfsr, disp);
disp->magic = DISPATCH_MAGIC;
disp->mgr = mgr;
disp->task = NULL;
isc_task_attach(task, &disp->task);
@@ -976,7 +1153,14 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
isc_socket_attach(sock, &disp->socket);
dispatch_log(disp, LVL(90), "attaching to socket %p", disp->socket);
dns_tcpmsg_init(disp->mctx, disp->socket, &disp->tcpmsg);
dns_tcpmsg_init(mgr->mctx, disp->socket, &disp->tcpmsg);
/*
* Append it to the dispatcher list.
*/
LOCK(&mgr->lock);
ISC_LIST_APPEND(mgr->list, disp, link);
UNLOCK(&mgr->lock);
*dispp = disp;
@@ -994,34 +1178,43 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
out3:
isc_mutex_destroy(&disp->lock);
out2:
isc_mem_put(mctx, disp->mctx, disp->qid_nbuckets * sizeof(void *));
isc_mem_put(mgr->mctx, disp->mgr->mctx,
disp->qid_nbuckets * sizeof(void *));
out1:
isc_mem_put(mctx, disp, sizeof(dns_dispatch_t));
isc_mem_put(mgr->mctx, disp, sizeof(dns_dispatch_t));
return (res);
}
void
dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp) {
dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp)
{
REQUIRE(VALID_DISPATCH(disp));
REQUIRE(dispp != NULL && *dispp == NULL);
LOCK(&disp->lock);
disp->refcount++;
UNLOCK(&disp->lock);
*dispp = disp;
}
void
dns_dispatch_detach(dns_dispatch_t **dispp) {
dns_dispatch_detach(dns_dispatch_t **dispp)
{
dns_dispatch_t *disp;
isc_boolean_t killit;
dns_dispatchmgr_t *mgr;
REQUIRE(dispp != NULL && VALID_DISPATCH(*dispp));
disp = *dispp;
*dispp = NULL;
mgr = disp->mgr;
LOCK(&mgr->lock);
LOCK(&disp->lock);
INSIST(disp->refcount > 0);
@@ -1040,7 +1233,14 @@ dns_dispatch_detach(dns_dispatch_t **dispp) {
UNLOCK(&disp->lock);
if (killit)
destroy(disp);
destroy_disp(disp);
killit = destroy_mgr_ok(mgr);
UNLOCK(&mgr->lock);
if (killit)
destroy_mgr(&mgr);
}
isc_result_t
@@ -1219,7 +1419,7 @@ dns_dispatch_removeresponse(dns_dispatch_t *disp, dns_dispentry_t **resp,
UNLOCK(&disp->lock);
if (killit)
destroy(disp);
destroy_disp(disp);
}
isc_result_t
@@ -1360,7 +1560,7 @@ dns_dispatch_removerequest(dns_dispatch_t *disp, dns_dispentry_t **resp,
UNLOCK(&disp->lock);
if (killit)
destroy(disp);
destroy_disp(disp);
}
void
@@ -1405,7 +1605,8 @@ dns_dispatch_freeevent(dns_dispatch_t *disp, dns_dispentry_t *resp,
}
static void
do_next_response(dns_dispatch_t *disp, dns_dispentry_t *resp) {
do_next_response(dns_dispatch_t *disp, dns_dispentry_t *resp)
{
dns_dispatchevent_t *ev;
INSIST(resp->item_out == ISC_FALSE);
@@ -1430,7 +1631,8 @@ do_next_response(dns_dispatch_t *disp, dns_dispentry_t *resp) {
}
static void
do_next_request(dns_dispatch_t *disp, dns_dispentry_t *resp) {
do_next_request(dns_dispatch_t *disp, dns_dispentry_t *resp)
{
dns_dispatchevent_t *ev;
INSIST(resp->item_out == ISC_FALSE);
@@ -1454,7 +1656,8 @@ do_next_request(dns_dispatch_t *disp, dns_dispentry_t *resp) {
}
static void
do_cancel(dns_dispatch_t *disp, dns_dispentry_t *resp) {
do_cancel(dns_dispatch_t *disp, dns_dispentry_t *resp)
{
dns_dispatchevent_t *ev;
if (disp->shutdown_out == 1)
@@ -1516,14 +1719,16 @@ do_cancel(dns_dispatch_t *disp, dns_dispentry_t *resp) {
}
isc_socket_t *
dns_dispatch_getsocket(dns_dispatch_t *disp) {
dns_dispatch_getsocket(dns_dispatch_t *disp)
{
REQUIRE(VALID_DISPATCH(disp));
return (disp->socket);
}
void
dns_dispatch_cancel(dns_dispatch_t *disp) {
dns_dispatch_cancel(dns_dispatch_t *disp)
{
REQUIRE(VALID_DISPATCH(disp));
LOCK(&disp->lock);
@@ -1541,3 +1746,15 @@ dns_dispatch_cancel(dns_dispatch_t *disp) {
return;
}
void
dns_dispatch_changeattributes(dns_dispatch_t *disp,
unsigned int attributes, unsigned int mask)
{
LOCK(&disp->mgr->lock);
LOCK(&disp->lock);
disp->attributes &= ~mask;
disp->attributes |= (attributes & mask);
UNLOCK(&disp->lock);
UNLOCK(&disp->mgr->lock);
}

View File

@@ -1,263 +0,0 @@
/*
* Copyright (C) 2000 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include <config.h>
#include <stdlib.h>
#include <isc/mem.h>
#include <isc/util.h>
#include <dns/dispatch.h>
#include <dns/dispatchlist.h>
#include <dns/types.h>
/*
* This module implements a dispatch list. The items on the list are
* dispatch objects. These dispatchers have attributes such as shared,
* TCP, UDP, IPv4, IPv6, etc. When searching for a usable shared
* dispatcher these flags are respected.
*/
typedef struct dns__dle dns__dle_t;
struct dns__dle {
dns_dispatch_t *disp;
unsigned int attributes;
ISC_LINK(dns__dle_t) link;
};
struct dns_dispatchlist {
/* Unlocked. */
unsigned int magic;
isc_mem_t *mctx;
/* Locked. */
isc_mutex_t lock;
unsigned int state;
ISC_LIST(dns__dle_t) list;
};
#define SHUTTINGDOWN 0x00000001U
#define IS_SHUTTINGDOWN(l) (((l)->state & SHUTTINGDOWN) != 0)
#define IS_PRIVATE(dle) (((dle)->attributes & DNS_DISPATCHLISTATTR_PRIVATE) \
!= 0)
#define DNS_DISPATCHLIST_MAGIC ISC_MAGIC('D', 'l', 's', 't')
#define DNS_DISPATCHLIST_VALID(a) \
ISC_MAGIC_VALID(a, DNS_DISPATCHLIST_MAGIC)
isc_result_t
dns_dispatchlist_create(isc_mem_t *mctx, dns_dispatchlist_t **listp)
{
dns_dispatchlist_t *list;
isc_result_t result;
REQUIRE(mctx != NULL);
REQUIRE(listp != NULL && *listp == NULL);
list = isc_mem_get(mctx, sizeof(dns_dispatchlist_t));
if (list == NULL)
return (ISC_R_NOMEMORY);
result = isc_mutex_init(&list->lock);
if (result != ISC_R_SUCCESS) {
isc_mem_put(mctx, list, sizeof(dns_dispatchlist_t));
return (result);
}
list->magic = DNS_DISPATCHLIST_MAGIC;
list->state = 0;
list->mctx = NULL;
isc_mem_attach(mctx, &list->mctx);
ISC_LIST_INIT(list->list);
*listp = list;
return (ISC_R_SUCCESS);
}
/*
* List must be locked when calling this function.
*/
static isc_boolean_t
destroy_ok(dns_dispatchlist_t *list)
{
if ((list->state & SHUTTINGDOWN) == 0)
return (ISC_FALSE);
if (!ISC_LIST_EMPTY(list->list))
return (ISC_FALSE);
return (ISC_TRUE);
}
/*
* List must be unlocked when calling this function.
*/
static void
destroy(dns_dispatchlist_t **listp)
{
isc_mem_t *mctx;
dns_dispatchlist_t *list;
list = *listp;
*listp = NULL;
mctx = list->mctx;
list->magic = 0;
list->mctx = 0;
isc_mutex_destroy(&list->lock);
list->state = 0;
isc_mem_put(mctx, list, sizeof(dns_dispatchlist_t));
isc_mem_detach(&mctx);
}
void
dns_dispatchlist_destroy(dns_dispatchlist_t **listp)
{
dns_dispatchlist_t *list;
isc_boolean_t killit;
REQUIRE(listp != NULL);
REQUIRE(DNS_DISPATCHLIST_VALID(*listp));
RUNTIME_CHECK(destroy_ok(*listp));
list = *listp;
*listp = NULL;
LOCK(&list->lock);
list->state |= SHUTTINGDOWN;
killit = destroy_ok(list);
UNLOCK(&list->lock);
if (killit)
destroy(&list);
}
isc_result_t
dns_dispatchlist_add(dns_dispatchlist_t *list, dns_dispatch_t *disp,
unsigned int attributes)
{
dns__dle_t *dle;
isc_result_t result;
REQUIRE(DNS_DISPATCHLIST_VALID(list));
REQUIRE(disp != NULL);
LOCK(&list->lock);
if (IS_SHUTTINGDOWN(list)) {
result = ISC_R_SHUTTINGDOWN;
goto out;
}
dle = isc_mem_get(list->mctx, sizeof(dns__dle_t));
if (dle == NULL) {
result = ISC_R_NOMEMORY;
goto out;
}
dle->disp = NULL;
dns_dispatch_attach(disp, &dle->disp);
dle->attributes = attributes;
ISC_LINK_INIT(dle, link);
ISC_LIST_APPEND(list->list, dle, link);
result = ISC_R_SUCCESS;
out:
UNLOCK(&list->lock);
return (result);
}
isc_result_t
dns_dispatchlist_delete(dns_dispatchlist_t *list, dns_dispatch_t *disp)
{
dns__dle_t *dle;
isc_result_t result;
isc_boolean_t killit;
REQUIRE(DNS_DISPATCHLIST_VALID(list));
REQUIRE(disp != NULL);
LOCK(&list->lock);
dle = ISC_LIST_HEAD(list->list);
while (dle != NULL) {
if (dle->disp == disp)
break;
dle = ISC_LIST_NEXT(dle, link);
}
if (dle == NULL) {
result = ISC_R_NOTFOUND;
goto out;
}
ISC_LIST_UNLINK(list->list, dle, link);
dns_dispatch_detach(&dle->disp);
isc_mem_put(list->mctx, dle, sizeof(dns__dle_t));
result = ISC_R_SUCCESS;
out:
killit = destroy_ok(list);
UNLOCK(&list->lock);
if (killit)
destroy(&list);
return (result);
}
#define ATTRMATCH(_a1, _a2, _mask) (((_a1) & (_mask)) == ((_a2) & (_mask)))
isc_result_t
dns_dispatchlist_find(dns_dispatchlist_t *list, unsigned int attributes,
unsigned int mask, dns_dispatch_t **dispp)
{
dns__dle_t *dle;
isc_result_t result;
REQUIRE(DNS_DISPATCHLIST_VALID(list));
REQUIRE(dispp != NULL && *dispp == NULL);
LOCK(&list->lock);
dle = ISC_LIST_HEAD(list->list);
while (dle != NULL) {
if (!IS_PRIVATE(dle)
&& ATTRMATCH(dle->attributes, attributes, mask))
break;
dle = ISC_LIST_NEXT(dle, link);
}
if (dle == NULL) {
result = ISC_R_NOTFOUND;
goto out;
}
dns_dispatch_attach(dle->disp, dispp);
result = ISC_R_SUCCESS;
out:
UNLOCK(&list->lock);
return (result);
}

View File

@@ -105,8 +105,8 @@ struct dns_c_ctx {
* statement. If a field is NULL then it has never been set.
*/
struct dns_c_options {
isc_mem_t *mem;
isc_uint32_t magic;
isc_mem_t *mem;
char *directory;
char *version;

View File

@@ -58,8 +58,6 @@
ISC_LANG_BEGINDECLS
#define DNS_DISPATCHEVENT_RECV (ISC_EVENTCLASS_DNS + 1) /* XXXMLG */
/*
* This event is sent to a task when a response (or request) comes in.
* No part of this structure should ever be modified by the caller,
@@ -102,12 +100,101 @@ struct dns_dispatchmethods {
};
typedef struct dns_dispatchmethods dns_dispatchmethods_t;
/*
* Attributes for added dispatchers.
*
* Values with the mask 0xffff0000 are application defined.
* Values with the mask 0x0000ffff are library defined.
*
* Insane values (like setting both TCP and UDP) are not caught. Don't
* do that.
*
* _PRIVATE
* The dispatcher cannot be shared.
*
* _TCP, _UDP
* The dispatcher is a TCP or UDP socket.
*
* _IPV4, _IPV6
* The dispatcher uses an ipv4 or ipv6 socket.
*
* _REQUEST
* The dispatcher can be used to accept requests.
*
* _RESPONSE
* The dispatcher can be used to issue queries to other servers, and
* accept replies from them.
*/
#define DNS_DISPATCHATTR_PRIVATE 0x00000001U
#define DNS_DISPATCHATTR_TCP 0x00000002U
#define DNS_DISPATCHATTR_UDP 0x00000004U
#define DNS_DISPATCHATTR_IPV4 0x00000008U
#define DNS_DISPATCHATTR_IPV6 0x00000010U
#define DNS_DISPATCHATTR_ACCEPTREQUEST 0x00000020U
#define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U
ISC_LANG_BEGINDECLS
isc_result_t
dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
unsigned int maxbuffersize,
dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp);
/*
* Creates a new dispatchmgr object.
*
* Requires:
* "mctx" be a valid memory context.
*
* mgrp != NULL && *mgrp == NULL
*
* Returns:
* ISC_R_SUCCESS -- all ok
*
* anything else -- failure
*/
void
dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp);
/*
* Destroys the dispatchmgr when it becomes empty. This could be
* immediately.
*
* Requires:
* mgrp != NULL && *mgrp is a valid dispatchmgr.
*/
isc_result_t
dns_dispatchmgr_find(dns_dispatchmgr_t *mgr, unsigned int attributes,
unsigned int mask, dns_dispatch_t **dispp);
/*
* Search for a dispatcher that has the attributes specified by
* (attributes & mask)
*
* Requires:
* "mgr" be a valid dispatchmgr.
*
* dispp != NULL && *dispp == NULL.
*
* Ensures:
* The dispatcher returned into *dispp is attached on behalf of the
* caller. It is required that the caller detach from it when it is
* no longer needed.
*
* Returns:
* ISC_R_SUCCESS -- found.
*
* ISC_R_NOTFOUND -- no dispatcher matching the requirements found.
*
* anything else -- failure.
*/
isc_result_t
dns_dispatch_create(dns_dispatchmgr_t *mgr, 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_dispatchmethods_t *methods, unsigned int attributes,
dns_dispatch_t **dispp);
/*
* Create a new dns_dispatch and attach it to the provided isc_socket_t.
@@ -130,7 +217,7 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
*
* Requires:
*
* mctx is a valid memory context.
* mgr is a valid dispatch manager.
*
* sock is a valid.
*
@@ -148,6 +235,7 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
* increment > buckets (and prime)
*/
void
dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp);
/*
@@ -163,6 +251,7 @@ dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp);
* < mumble >
*/
void
dns_dispatch_detach(dns_dispatch_t **dispp);
/*
@@ -178,6 +267,7 @@ dns_dispatch_detach(dns_dispatch_t **dispp);
* < mumble >
*/
isc_result_t
dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
isc_task_t *task, isc_taskaction_t action, void *arg,
@@ -214,6 +304,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
* for this destination.
*/
void
dns_dispatch_removeresponse(dns_dispatch_t *disp, dns_dispentry_t **resp,
dns_dispatchevent_t **sockevent);
@@ -233,6 +324,7 @@ dns_dispatch_removeresponse(dns_dispatch_t *disp, dns_dispentry_t **resp,
* < mumble >
*/
isc_result_t
dns_dispatch_addrequest(dns_dispatch_t *disp,
isc_task_t *task, isc_taskaction_t action, void *arg,
@@ -252,6 +344,7 @@ dns_dispatch_addrequest(dns_dispatch_t *disp,
* < mumble >
*/
void
dns_dispatch_removerequest(dns_dispatch_t *disp, dns_dispentry_t **resp,
dns_dispatchevent_t **sockevent);
@@ -270,6 +363,7 @@ dns_dispatch_removerequest(dns_dispatch_t *disp, dns_dispentry_t **resp,
* < mumble >
*/
void
dns_dispatch_freeevent(dns_dispatch_t *disp, dns_dispentry_t *resp,
dns_dispatchevent_t **sockevent);
@@ -288,16 +382,53 @@ dns_dispatch_freeevent(dns_dispatch_t *disp, dns_dispentry_t *resp,
* < mumble >
*/
isc_socket_t *
dns_dispatch_getsocket(dns_dispatch_t *disp);
/*
* Return the socket associated with this dispatcher
* Return the socket associated with this dispatcher.
*
* Requires:
* < mumble >
*
* Ensures:
* < mumble >
*
* Returns:
* < mumble >
*/
void
dns_dispatch_cancel(dns_dispatch_t *disp);
/*
* cancel outstanding clients
*
* Requires:
* < mumble >
*
* Ensures:
* < mumble >
*
* Returns:
* < mumble >
*/
void
dns_dispatch_changeattributes(dns_dispatch_t *disp,
unsigned int attributes, unsigned int mask);
/*
* Set the bits described by "mask" to the corresponding values in
* "attributes".
*
* Requires:
* < mumble >
*
* Ensures:
* < mumble >
*
* Returns:
* < mumble >
*/
ISC_LANG_ENDDECLS

View File

@@ -1,178 +0,0 @@
/*
* Copyright (C) 2000 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifndef DNS_DISPATCHLIST_H
#define DNS_DISPATCHLIST_H 1
/*****
***** Module Info
*****/
/*
* DNS Dispatch List Management
*
* Maintains a list of dispatchers to help various parts of the DNS
* library and applications keep track and share dispatchers.
*
* MP:
*
* All locking is performed internally to each list.
*
* dns_dispatchlist_find() will return dispatches which are
* attached.
*
* Reliability:
*
* Resources:
*
* Security:
*
* None.
*
* Standards:
*
* None.
*/
/***
*** Imports
***/
#include <isc/lang.h>
#include <dns/types.h>
/*
* Attributes for added dispatchers.
*
* Values with the mask 0xffff0000 are application defined.
* Values with the mask 0x0000ffff are library defined.
*
* Insane values (like setting both TCP and UDP) are not caught. Don't
* do that.
*/
#define DNS_DISPATCHLISTATTR_PRIVATE 0x00000001U
#define DNS_DISPATCHLISTATTR_TCP 0x00000002U
#define DNS_DISPATCHLISTATTR_UDP 0x00000004U
#define DNS_DISPATCHLISTATTR_IPV4 0x00000008U
#define DNS_DISPATCHLISTATTR_IPV6 0x00000010U
ISC_LANG_BEGINDECLS
isc_result_t
dns_dispatchlist_create(isc_mem_t *mctx, dns_dispatchlist_t **listp);
/*
* Creates a new dispatchlist object.
*
* Requires:
* "mctx" be a valid memory context.
*
* listp != NULL && *listp == NULL
*
* Returns:
* ISC_R_SUCCESS -- all ok
*
* anything else -- failure
*/
void
dns_dispatchlist_destroy(dns_dispatchlist_t **listp);
/*
* Destroys the dispatchlist when it becomes empty. This could be
* immediately.
*
* Requires:
* listp != NULL && *listp is a valid dispatchlist.
*/
isc_result_t
dns_dispatchlist_add(dns_dispatchlist_t *list, dns_dispatch_t *disp,
unsigned int attributes);
/*
* Add a new dispatch object to the dispatch list with the attributes
* supplied.
*
* Requires:
* "list" be a valid dispatchlist.
*
* "disp" be a valid dispatcher that is not already present on "list"
*
* Ensures:
* On successful return, the dispatcher is attached, preventing it
* from being deleted while on the dispatchlist.
*
* Returns:
* ISC_R_SUCCESS -- added.
*
* anything else -- failure.
*/
isc_result_t
dns_dispatchlist_delete(dns_dispatchlist_t *list, dns_dispatch_t *disp);
/*
* Deletes the dispatcher from the list.
*
* Requires:
* "list" be a valid dispatchlist.
*
* "disp" be a valid dispatcher.
*
* Ensures:
* On successful return, the dispatcher is detached once, allowing it
* to be deleted.
*
* Returns:
* ISC_R_SUCCESS -- deleted.
*
* ISC_R_NOTFOUND -- dispatcher is not on the list.
*
* anything else -- failure.
*/
isc_result_t
dns_dispatchlist_find(dns_dispatchlist_t *list, unsigned int attributes,
unsigned int mask, dns_dispatch_t **dispp);
/*
* Search for a dispatcher that has the attributes specified by
* (attributes & mask)
*
* Requires:
* "list" be a valid dispatchlist.
*
* dispp != NULL && *dispp == NULL.
*
* Ensures:
* The dispatcher returned into *dispp is attached on behalf of the
* caller. It is required that the caller detach from it when it is
* no longer needed.
*
* Returns:
* ISC_R_SUCCESS -- found.
*
* ISC_R_NOTFOUND -- no dispatcher matching the requirements found.
*
* anything else -- failure.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_DISPATCHLIST_H */

View File

@@ -57,6 +57,7 @@ ISC_LANG_BEGINDECLS
isc_result_t
dns_requestmgr_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
isc_socketmgr_t *socketmgr,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
dns_requestmgr_t **requestmgrp);
/*

View File

@@ -94,6 +94,7 @@ dns_resolver_create(dns_view_t *view,
isc_socketmgr_t *socketmgr,
isc_timermgr_t *timermgr,
unsigned int options,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4,
dns_dispatch_t *dispatchv6,
dns_resolver_t **resp);
@@ -338,6 +339,9 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp);
* *fetchp == NULL.
*/
dns_dispatchmgr_t *
dns_resolver_dispatchmgr(dns_resolver_t *resolver);
dns_dispatch_t *
dns_resolver_dispatchv4(dns_resolver_t *resolver);

View File

@@ -52,6 +52,7 @@ typedef struct dns_decompress dns_decompress_t;
typedef struct dns_dispatch dns_dispatch_t;
typedef struct dns_dispatchevent dns_dispatchevent_t;
typedef struct dns_dispatchlist dns_dispatchlist_t;
typedef struct dns_dispatchmgr dns_dispatchmgr_t;
typedef struct dns_dispentry dns_dispentry_t;
typedef struct dns_fetch dns_fetch_t;
typedef struct dns_fixedname dns_fixedname_t;

View File

@@ -191,6 +191,7 @@ dns_view_createresolver(dns_view_t *view,
isc_socketmgr_t *socketmgr,
isc_timermgr_t *timermgr,
unsigned int options,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4,
dns_dispatch_t *dispatchv6);
/*

View File

@@ -42,37 +42,38 @@ typedef ISC_LIST(dns_request_t) dns_requestlist_t;
#define DNS_REQUEST_NLOCKS 7
struct dns_requestmgr {
isc_int32_t magic;
isc_mutex_t lock;
isc_mem_t *mctx;
isc_int32_t magic;
isc_mutex_t lock;
isc_mem_t *mctx;
/* locked */
isc_int32_t eref;
isc_int32_t iref;
isc_timermgr_t *timermgr;
isc_socketmgr_t *socketmgr;
dns_dispatch_t *dispatchv4;
dns_dispatch_t *dispatchv6;
isc_boolean_t exiting;
isc_eventlist_t whenshutdown;
unsigned int hash;
isc_mutex_t locks[DNS_REQUEST_NLOCKS];
dns_requestlist_t requests;
isc_int32_t eref;
isc_int32_t iref;
isc_timermgr_t *timermgr;
isc_socketmgr_t *socketmgr;
dns_dispatchmgr_t *dispatchmgr;
dns_dispatch_t *dispatchv4;
dns_dispatch_t *dispatchv6;
isc_boolean_t exiting;
isc_eventlist_t whenshutdown;
unsigned int hash;
isc_mutex_t locks[DNS_REQUEST_NLOCKS];
dns_requestlist_t requests;
};
struct dns_request {
isc_int32_t magic;
unsigned int hash;
isc_mem_t *mctx;
isc_int32_t flags;
ISC_LINK(dns_request_t) link;
isc_buffer_t *query;
isc_buffer_t *answer;
dns_requestevent_t *event;
dns_dispatch_t *dispatch;
dns_dispentry_t *dispentry;
isc_timer_t *timer;
dns_requestmgr_t *requestmgr;
isc_int32_t magic;
unsigned int hash;
isc_mem_t *mctx;
isc_int32_t flags;
ISC_LINK(dns_request_t) link;
isc_buffer_t *query;
isc_buffer_t *answer;
dns_requestevent_t *event;
dns_dispatch_t *dispatch;
dns_dispentry_t *dispentry;
isc_timer_t *timer;
dns_requestmgr_t *requestmgr;
};
#define DNS_REQUEST_F_CONNECTING 0x0001
@@ -110,6 +111,7 @@ isc_result_t
dns_requestmgr_create(isc_mem_t *mctx,
isc_timermgr_t *timermgr,
isc_socketmgr_t *socketmgr,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4,
dns_dispatch_t *dispatchv6,
dns_requestmgr_t **requestmgrp)
@@ -124,6 +126,7 @@ dns_requestmgr_create(isc_mem_t *mctx,
REQUIRE(requestmgrp != NULL && *requestmgrp == NULL);
REQUIRE(timermgr != NULL);
REQUIRE(socketmgr != NULL);
REQUIRE(dispatchmgr != NULL);
if (dispatchv4 != NULL) {
socket = dns_dispatch_getsocket(dispatchv4);
REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
@@ -154,6 +157,7 @@ dns_requestmgr_create(isc_mem_t *mctx,
}
requestmgr->timermgr = timermgr;
requestmgr->socketmgr = socketmgr;
requestmgr->dispatchmgr = dispatchmgr;
requestmgr->dispatchv4 = NULL;
if (dispatchv4 != NULL)
dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4);
@@ -419,6 +423,7 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
isc_interval_t interval;
dns_messageid_t id;
isc_time_t expires;
unsigned int attrs;
REQUIRE(VALID_REQUESTMGR(requestmgr));
REQUIRE(message != NULL);
@@ -479,8 +484,17 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
isc_sockettype_tcp, &socket);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_dispatch_create(mctx, socket, task,
4096, 2, 1, 1, 3, NULL,
attrs = 0;
attrs |= DNS_DISPATCHATTR_TCP;
attrs |= DNS_DISPATCHATTR_PRIVATE;
if (isc_sockaddr_pf(address) == AF_INET)
attrs |= DNS_DISPATCHATTR_IPV4;
else
attrs |= DNS_DISPATCHATTR_IPV6;
attrs |= DNS_DISPATCHATTR_MAKEQUERY;
result = dns_dispatch_create(requestmgr->dispatchmgr,
socket, task,
4096, 2, 1, 1, 3, NULL, attrs,
&request->dispatch);
isc_socket_detach(&socket);
if (result != ISC_R_SUCCESS)

View File

@@ -214,6 +214,7 @@ struct dns_resolver {
unsigned int options;
isc_socket_t * udpsocketv4;
isc_socket_t * udpsocketv6;
dns_dispatchmgr_t * dispatchmgr;
dns_dispatch_t * dispatchv4;
dns_dispatch_t * dispatchv6;
unsigned int nbuckets;
@@ -615,6 +616,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
isc_result_t result;
resquery_t *query;
isc_socket_t *socket;
unsigned int attrs;
FCTXTRACE("query");
@@ -659,8 +661,16 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
&socket);
if (result != ISC_R_SUCCESS)
goto cleanup_query;
result = dns_dispatch_create(res->mctx, socket, task,
4096, 2, 1, 1, 3, NULL,
attrs = 0;
attrs |= DNS_DISPATCHATTR_TCP;
attrs |= DNS_DISPATCHATTR_PRIVATE;
if (isc_sockaddr_pf(addrinfo->sockaddr) == AF_INET)
attrs |= DNS_DISPATCHATTR_IPV4;
else
attrs |= DNS_DISPATCHATTR_IPV6;
attrs |= DNS_DISPATCHATTR_MAKEQUERY;
result = dns_dispatch_create(res->dispatchmgr, socket, task,
4096, 2, 1, 1, 3, NULL, attrs,
&query->dispatch);
/*
* Regardless of whether dns_dispatch_create() succeeded or
@@ -3911,6 +3921,7 @@ dns_resolver_create(dns_view_t *view,
isc_socketmgr_t *socketmgr,
isc_timermgr_t *timermgr,
unsigned int options,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4,
dns_dispatch_t *dispatchv6,
dns_resolver_t **resp)
@@ -3919,6 +3930,7 @@ dns_resolver_create(dns_view_t *view,
isc_result_t result = ISC_R_SUCCESS;
unsigned int i, buckets_created = 0;
char name[16];
unsigned int attrs;
/*
* Create a resolver.
@@ -3927,6 +3939,7 @@ dns_resolver_create(dns_view_t *view,
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(ntasks > 0);
REQUIRE(resp != NULL && *resp == NULL);
REQUIRE(dispatchmgr != NULL);
res = isc_mem_get(view->mctx, sizeof *res);
if (res == NULL)
@@ -3936,6 +3949,7 @@ dns_resolver_create(dns_view_t *view,
res->rdclass = view->rdclass;
res->socketmgr = socketmgr;
res->timermgr = timermgr;
res->dispatchmgr = dispatchmgr;
res->view = view;
res->options = options;
@@ -3972,6 +3986,8 @@ dns_resolver_create(dns_view_t *view,
if (dispatchv4 != NULL) {
dns_dispatch_attach(dispatchv4, &res->dispatchv4);
} else if (isc_net_probeipv4() == ISC_R_SUCCESS) {
isc_sockaddr_t saddr;
/*
* Create an IPv4 UDP socket and a dispatcher for it.
*/
@@ -3980,10 +3996,22 @@ dns_resolver_create(dns_view_t *view,
&res->udpsocketv4);
if (result != ISC_R_SUCCESS)
goto cleanup_buckets;
result = dns_dispatch_create(res->mctx, res->udpsocketv4,
isc_sockaddr_any(&saddr);
#if 0 /* XXXMLG */
result = isc_socket_bind(res->udpsocketv4, &saddr);
if (result != ISC_R_SUCCESS)
goto cleanup_udpsocketv4;
#endif
attrs = 0;
attrs |= DNS_DISPATCHATTR_UDP;
attrs |= DNS_DISPATCHATTR_PRIVATE;
attrs |= DNS_DISPATCHATTR_IPV4;
attrs |= DNS_DISPATCHATTR_MAKEQUERY;
result = dns_dispatch_create(res->dispatchmgr,
res->udpsocketv4,
res->buckets[0].task, 4096,
1000, 32768, 16411, 16433, NULL,
&res->dispatchv4);
attrs, &res->dispatchv4);
if (result != ISC_R_SUCCESS)
goto cleanup_udpsocketv4;
}
@@ -3996,6 +4024,7 @@ dns_resolver_create(dns_view_t *view,
if (dispatchv6 != NULL) {
dns_dispatch_attach(dispatchv6, &res->dispatchv6);
} else if (isc_net_probeipv6() == ISC_R_SUCCESS) {
isc_sockaddr_t saddr;
/*
* Create an IPv6 UDP socket and a dispatcher for it.
*/
@@ -4004,10 +4033,22 @@ dns_resolver_create(dns_view_t *view,
&res->udpsocketv6);
if (result != ISC_R_SUCCESS)
goto cleanup_dispatchv4;
result = dns_dispatch_create(res->mctx, res->udpsocketv6,
isc_sockaddr_any6(&saddr);
#if 0 /* XXXMLG */
result = isc_socket_bind(res->udpsocketv6, &saddr);
if (result != ISC_R_SUCCESS)
goto cleanup_udpsocketv6;
#endif
attrs = 0;
attrs |= DNS_DISPATCHATTR_UDP;
attrs |= DNS_DISPATCHATTR_PRIVATE;
attrs |= DNS_DISPATCHATTR_IPV6;
attrs |= DNS_DISPATCHATTR_MAKEQUERY;
result = dns_dispatch_create(res->dispatchmgr,
res->udpsocketv6,
res->buckets[0].task, 4096,
1000, 32768, 16411, 16433, NULL,
&res->dispatchv6);
attrs, &res->dispatchv6);
if (result != ISC_R_SUCCESS)
goto cleanup_udpsocketv6;
}
@@ -4593,6 +4634,12 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
empty_bucket(res);
}
dns_dispatchmgr_t *
dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));
return (resolver->dispatchmgr);
}
dns_dispatch_t *
dns_resolver_dispatchv4(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));

View File

@@ -376,6 +376,7 @@ dns_view_createresolver(dns_view_t *view,
isc_socketmgr_t *socketmgr,
isc_timermgr_t *timermgr,
unsigned int options,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4,
dns_dispatch_t *dispatchv6)
{
@@ -396,7 +397,8 @@ dns_view_createresolver(dns_view_t *view,
isc_task_setname(view->task, "view", view);
result = dns_resolver_create(view, taskmgr, ntasks, socketmgr,
timermgr, options, dispatchv4, dispatchv6,
timermgr, options, dispatchmgr,
dispatchv4, dispatchv6,
&view->resolver);
if (result != ISC_R_SUCCESS) {
isc_task_detach(&view->task);
@@ -417,6 +419,7 @@ dns_view_createresolver(dns_view_t *view,
view->attributes &= ~DNS_VIEWATTR_ADBSHUTDOWN;
result = dns_requestmgr_create(view->mctx, timermgr, socketmgr,
dns_resolver_dispatchmgr(view->resolver),
dns_resolver_dispatchv4(view->resolver),
dns_resolver_dispatchv6(view->resolver),
&view->requestmgr);