From ca9739800f045cd4d39014f98b920d4354b5bd14 Mon Sep 17 00:00:00 2001 From: Michael Graff Date: Wed, 10 May 2000 21:34:50 +0000 Subject: [PATCH] implement dns_dispatchmgr_t, replacing dns_dispatchlist_t. Use it throughout the library/server. --- bin/lwresd/main.c | 11 +- bin/named/include/named/globals.h | 1 + bin/named/include/named/interfacemgr.h | 5 +- bin/named/interfacemgr.c | 22 +- bin/named/main.c | 11 + bin/named/server.c | 19 +- lib/dns/Makefile.in | 2 - lib/dns/dispatch.c | 329 ++++++++++++++++++++----- lib/dns/dispatchlist.c | 263 -------------------- lib/dns/include/dns/confctx.h | 2 +- lib/dns/include/dns/dispatch.h | 145 ++++++++++- lib/dns/include/dns/dispatchlist.h | 178 ------------- lib/dns/include/dns/request.h | 1 + lib/dns/include/dns/resolver.h | 4 + lib/dns/include/dns/types.h | 1 + lib/dns/include/dns/view.h | 1 + lib/dns/request.c | 70 +++--- lib/dns/resolver.c | 59 ++++- lib/dns/view.c | 5 +- 19 files changed, 575 insertions(+), 554 deletions(-) delete mode 100644 lib/dns/dispatchlist.c delete mode 100644 lib/dns/include/dns/dispatchlist.h diff --git a/bin/lwresd/main.c b/bin/lwresd/main.c index 5e1a94e9f9..281aca579c 100644 --- a/bin/lwresd/main.c +++ b/bin/lwresd/main.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -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. */ diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index cf2875c06a..1e442b8f25 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -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 diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h index 78c5307089..d0535217d5 100644 --- a/bin/named/include/named/interfacemgr.h +++ b/bin/named/include/named/interfacemgr.h @@ -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); diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c index d4f95ff2e3..b7f20904cd 100644 --- a/bin/named/interfacemgr.c +++ b/bin/named/interfacemgr.c @@ -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", diff --git a/bin/named/main.c b/bin/named/main.c index 594071ceed..5785e205cd 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -25,6 +25,8 @@ #include #include +#include + #include /* @@ -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 diff --git a/bin/named/server.c b/bin/named/server.c index 011cce2fa9..08a9f08edc 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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"); diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index df3dc0bfaa..9a997bb244 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -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 \ diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 3068212f3c..a29aa4c912 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -20,7 +20,9 @@ #include #include +#include #include +#include #include #include #include @@ -30,6 +32,23 @@ #include #include #include +#include + +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); +} diff --git a/lib/dns/dispatchlist.c b/lib/dns/dispatchlist.c deleted file mode 100644 index c23647659a..0000000000 --- a/lib/dns/dispatchlist.c +++ /dev/null @@ -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 - -#include - -#include -#include - -#include -#include -#include - -/* - * 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); -} diff --git a/lib/dns/include/dns/confctx.h b/lib/dns/include/dns/confctx.h index b747e8ec22..eafc086686 100644 --- a/lib/dns/include/dns/confctx.h +++ b/lib/dns/include/dns/confctx.h @@ -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; diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index a60f321063..0a6faf7cc5 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -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 diff --git a/lib/dns/include/dns/dispatchlist.h b/lib/dns/include/dns/dispatchlist.h deleted file mode 100644 index 857900c7fb..0000000000 --- a/lib/dns/include/dns/dispatchlist.h +++ /dev/null @@ -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 - -#include - -/* - * 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 */ diff --git a/lib/dns/include/dns/request.h b/lib/dns/include/dns/request.h index 51b103b97d..fd099e0ac0 100644 --- a/lib/dns/include/dns/request.h +++ b/lib/dns/include/dns/request.h @@ -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); /* diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index 804578d4c0..84302d9049 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -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); diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 3a8d002cf9..07b3358107 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -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; diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index 5b969b56b1..588536c2fc 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -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); /* diff --git a/lib/dns/request.c b/lib/dns/request.c index 7a7059bb3e..b882dd087a 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -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) diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 062761f064..acc73ab936 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -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)); diff --git a/lib/dns/view.c b/lib/dns/view.c index caf4b95aca..8b25d31d51 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -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);