mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-04 19:52:03 -04:00
Clients now listen on sockets instead of accepting queries from dispatchers.
When a socket is shared by clients and query-source, the client hands off responses to the dispatcher.
This commit is contained in:
parent
562f162981
commit
35f06ab0e6
6 changed files with 222 additions and 126 deletions
|
|
@ -15,7 +15,7 @@
|
|||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: client.c,v 1.141 2001/01/23 18:47:33 gson Exp $ */
|
||||
/* $Id: client.c,v 1.142 2001/01/27 02:07:59 bwelling Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
|
@ -134,10 +134,10 @@ struct ns_clientmgr {
|
|||
* client manager's list of active clients.
|
||||
*
|
||||
* If it is a TCP client object, it has a TCP listener socket
|
||||
* and an outstading TCP listen request.
|
||||
* and an outstanding TCP listen request.
|
||||
*
|
||||
* If it is a UDP client object, it is associated with a
|
||||
* dispatch and has an outstanding dispatch request.
|
||||
* If it is a UDP client object, it has a UDP listener socket
|
||||
* and an outstanding UDP receive request.
|
||||
*/
|
||||
|
||||
#define NS_CLIENTSTATE_READING 3
|
||||
|
|
@ -152,8 +152,7 @@ struct ns_clientmgr {
|
|||
/*
|
||||
* The client object has received a request and is working
|
||||
* on it. It has a view, and it may have any of a non-reset OPT,
|
||||
* recursion quota, and an outstanding write request. If it
|
||||
* is a UDP client object, it has a dispatch event.
|
||||
* recursion quota, and an outstanding write request.
|
||||
*/
|
||||
|
||||
#define NS_CLIENTSTATE_MAX 9
|
||||
|
|
@ -166,6 +165,7 @@ struct ns_clientmgr {
|
|||
|
||||
static void client_read(ns_client_t *client);
|
||||
static void client_accept(ns_client_t *client);
|
||||
static void client_udprecv(ns_client_t *client);
|
||||
static void clientmgr_destroy(ns_clientmgr_t *manager);
|
||||
static isc_boolean_t exit_check(ns_client_t *client);
|
||||
static void ns_client_endrequest(ns_client_t *client);
|
||||
|
|
@ -191,14 +191,9 @@ client_deactivate(ns_client_t *client) {
|
|||
if (client->tcplistener != NULL)
|
||||
isc_socket_detach(&client->tcplistener);
|
||||
|
||||
if (client->dispentry != NULL) {
|
||||
dns_dispatchevent_t **deventp;
|
||||
if (client->dispevent != NULL)
|
||||
deventp = &client->dispevent;
|
||||
else
|
||||
deventp = NULL;
|
||||
dns_dispatch_removerequest(&client->dispentry, deventp);
|
||||
}
|
||||
if (client->udpsocket != NULL)
|
||||
isc_socket_detach(&client->udpsocket);
|
||||
|
||||
if (client->dispatch != NULL)
|
||||
dns_dispatch_detach(&client->dispatch);
|
||||
|
||||
|
|
@ -237,6 +232,7 @@ client_free(ns_client_t *client) {
|
|||
|
||||
ns_query_free(client);
|
||||
isc_mem_put(client->mctx, client->sendbuf, SEND_BUFFER_SIZE);
|
||||
isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
|
||||
isc_timer_detach(&client->timer);
|
||||
|
||||
if (client->tcpbuf != NULL)
|
||||
|
|
@ -338,13 +334,14 @@ exit_check(ns_client_t *client) {
|
|||
if (TCP_CLIENT(client))
|
||||
socket = client->tcpsocket;
|
||||
else
|
||||
socket =
|
||||
dns_dispatch_getsocket(client->dispatch);
|
||||
socket = client->udpsocket;
|
||||
isc_socket_cancel(socket, client->task,
|
||||
ISC_SOCKCANCEL_SEND);
|
||||
}
|
||||
|
||||
if (! (client->nsends == 0 && client->references == 0)) {
|
||||
if (! (client->nsends == 0 && client->nrecvs == 0 &&
|
||||
client->references == 0))
|
||||
{
|
||||
/*
|
||||
* Still waiting for I/O cancel completion.
|
||||
* or lingering references.
|
||||
|
|
@ -411,16 +408,8 @@ exit_check(ns_client_t *client) {
|
|||
if (NS_CLIENTSTATE_READY == client->newstate) {
|
||||
if (TCP_CLIENT(client)) {
|
||||
client_accept(client);
|
||||
} else {
|
||||
/*
|
||||
* Give the processed dispatch event back to
|
||||
* the dispatch. This tells the dispatch
|
||||
* that we are ready to receive the next event.
|
||||
*/
|
||||
dns_dispatch_freeevent(client->dispatch,
|
||||
client->dispentry,
|
||||
&client->dispevent);
|
||||
}
|
||||
} else
|
||||
client_udprecv(client);
|
||||
client->newstate = NS_CLIENTSTATE_MAX;
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
|
@ -440,6 +429,16 @@ exit_check(ns_client_t *client) {
|
|||
return (ISC_TRUE);
|
||||
}
|
||||
/* Accept cancel is complete. */
|
||||
|
||||
if (client->nrecvs > 0)
|
||||
isc_socket_cancel(client->udpsocket, client->task,
|
||||
ISC_SOCKCANCEL_RECV);
|
||||
if (! (client->nrecvs == 0)) {
|
||||
/* Still waiting for recv cancel completion. */
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
/* Recv cancel is complete. */
|
||||
|
||||
client_deactivate(client);
|
||||
client->state = NS_CLIENTSTATE_INACTIVE;
|
||||
INSIST(client->recursionquota == NULL);
|
||||
|
|
@ -468,7 +467,6 @@ exit_check(ns_client_t *client) {
|
|||
static void
|
||||
client_start(isc_task_t *task, isc_event_t *event) {
|
||||
ns_client_t *client = (ns_client_t *) event->ev_arg;
|
||||
isc_result_t result;
|
||||
|
||||
INSIST(task == client->task);
|
||||
|
||||
|
|
@ -477,25 +475,7 @@ client_start(isc_task_t *task, isc_event_t *event) {
|
|||
if (TCP_CLIENT(client)) {
|
||||
client_accept(client);
|
||||
} else {
|
||||
result = dns_dispatch_addrequest(client->dispatch,
|
||||
client->task,
|
||||
client_request,
|
||||
client,
|
||||
&client->dispentry);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_client_log(client,
|
||||
DNS_LOGCATEGORY_SECURITY,
|
||||
NS_LOGMODULE_CLIENT,
|
||||
ISC_LOG_DEBUG(3),
|
||||
"dns_dispatch_addrequest() "
|
||||
"failed: %s",
|
||||
isc_result_totext(result));
|
||||
/*
|
||||
* Not much we can do here but log the failure;
|
||||
* the client will effectively go idle.
|
||||
*/
|
||||
}
|
||||
client_udprecv(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -535,6 +515,7 @@ ns_client_endrequest(ns_client_t *client) {
|
|||
INSIST(client->naccepts == 0);
|
||||
INSIST(client->nreads == 0);
|
||||
INSIST(client->nsends == 0);
|
||||
INSIST(client->nrecvs == 0);
|
||||
INSIST(client->state == NS_CLIENTSTATE_WORKING);
|
||||
|
||||
CTRACE("endrequest");
|
||||
|
|
@ -731,8 +712,8 @@ client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
|
|||
socket = client->tcpsocket;
|
||||
address = NULL;
|
||||
} else {
|
||||
socket = dns_dispatch_getsocket(client->dispatch);
|
||||
address = &client->dispevent->addr;
|
||||
socket = client->udpsocket;
|
||||
address = &client->peeraddr;
|
||||
|
||||
isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
|
||||
if (ns_g_server->blackholeacl != NULL &&
|
||||
|
|
@ -1135,16 +1116,17 @@ client_getoptattrs(ns_client_t *client, dns_rdataset_t *opt) {
|
|||
|
||||
|
||||
/*
|
||||
* Handle an incoming request event from the dispatch (UDP case)
|
||||
* Handle an incoming request event from the socket (UDP case)
|
||||
* or tcpmsg (TCP case).
|
||||
*/
|
||||
static void
|
||||
client_request(isc_task_t *task, isc_event_t *event) {
|
||||
ns_client_t *client;
|
||||
dns_dispatchevent_t *devent;
|
||||
isc_socketevent_t *sevent;
|
||||
isc_result_t result;
|
||||
isc_result_t sigresult;
|
||||
isc_buffer_t *buffer;
|
||||
isc_buffer_t tbuffer;
|
||||
dns_view_t *view;
|
||||
dns_rdataset_t *opt;
|
||||
isc_boolean_t ra; /* Recursion available. */
|
||||
|
|
@ -1166,21 +1148,22 @@ client_request(isc_task_t *task, isc_event_t *event) {
|
|||
RWLOCK(&ns_g_server->conflock, isc_rwlocktype_read);
|
||||
dns_zonemgr_lockconf(ns_g_server->zonemgr, isc_rwlocktype_read);
|
||||
|
||||
if (event->ev_type == DNS_EVENT_DISPATCH) {
|
||||
if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
|
||||
INSIST(!TCP_CLIENT(client));
|
||||
devent = (dns_dispatchevent_t *)event;
|
||||
REQUIRE(client->dispentry != NULL);
|
||||
client->dispevent = devent;
|
||||
buffer = &devent->buffer;
|
||||
result = devent->result;
|
||||
client->peeraddr = devent->addr;
|
||||
sevent = (isc_socketevent_t *)event;
|
||||
isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
|
||||
isc_buffer_add(&tbuffer, sevent->n);
|
||||
buffer = &tbuffer;
|
||||
result = sevent->result;
|
||||
client->peeraddr = sevent->address;
|
||||
client->peeraddr_valid = ISC_TRUE;
|
||||
if ((devent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
|
||||
if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
|
||||
client->attributes |= NS_CLIENTATTR_PKTINFO;
|
||||
client->pktinfo = devent->pktinfo;
|
||||
client->pktinfo = sevent->pktinfo;
|
||||
}
|
||||
if ((devent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
|
||||
if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
|
||||
client->attributes |= NS_CLIENTATTR_MULTICAST;
|
||||
client->nrecvs--;
|
||||
} else {
|
||||
INSIST(TCP_CLIENT(client));
|
||||
REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
|
||||
|
|
@ -1232,14 +1215,20 @@ client_request(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
|
||||
/*
|
||||
* We expect a query, not a response. Unexpected UDP responses
|
||||
* are discarded early by the dispatcher, but TCP responses
|
||||
* bypass the dispatcher and must be discarded here.
|
||||
* We expect a query, not a response. If this is a UDP response,
|
||||
* forward it to the dispatcher. If it's a TCP response,
|
||||
* discarded it here.
|
||||
*/
|
||||
if ((client->message->flags & DNS_MESSAGEFLAG_QR) != 0) {
|
||||
CTRACE("unexpected response");
|
||||
ns_client_next(client, DNS_R_FORMERR);
|
||||
goto cleanup_serverlock;
|
||||
if (TCP_CLIENT(client)) {
|
||||
CTRACE("unexpected response");
|
||||
ns_client_next(client, DNS_R_FORMERR);
|
||||
goto cleanup_serverlock;
|
||||
} else {
|
||||
dns_dispatch_importrecv(client->dispatch, &event);
|
||||
ns_client_next(client, ISC_R_SUCCESS);
|
||||
goto cleanup_serverlock;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1546,6 +1535,10 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp)
|
|||
if (client->sendbuf == NULL)
|
||||
goto cleanup_message;
|
||||
|
||||
client->recvbuf = isc_mem_get(manager->mctx, RECV_BUFFER_SIZE);
|
||||
if (client->recvbuf == NULL)
|
||||
goto cleanup_sendbuf;
|
||||
|
||||
client->magic = NS_CLIENT_MAGIC;
|
||||
client->mctx = manager->mctx;
|
||||
client->manager = NULL;
|
||||
|
|
@ -1554,13 +1547,13 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp)
|
|||
client->naccepts = 0;
|
||||
client->nreads = 0;
|
||||
client->nsends = 0;
|
||||
client->nrecvs = 0;
|
||||
client->references = 0;
|
||||
client->attributes = 0;
|
||||
client->view = NULL;
|
||||
client->lockview = NULL;
|
||||
client->dispatch = NULL;
|
||||
client->dispentry = NULL;
|
||||
client->dispevent = NULL;
|
||||
client->udpsocket = NULL;
|
||||
client->tcplistener = NULL;
|
||||
client->tcpsocket = NULL;
|
||||
client->tcpmsg_valid = ISC_FALSE;
|
||||
|
|
@ -1594,7 +1587,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp)
|
|||
*/
|
||||
result = ns_query_init(client);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_sendbuf;
|
||||
goto cleanup_recvbuf;
|
||||
|
||||
CTRACE("create");
|
||||
|
||||
|
|
@ -1602,6 +1595,9 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp)
|
|||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup_recvbuf:
|
||||
isc_mem_put(manager->mctx, client->recvbuf, RECV_BUFFER_SIZE);
|
||||
|
||||
cleanup_sendbuf:
|
||||
isc_mem_put(manager->mctx, client->sendbuf, SEND_BUFFER_SIZE);
|
||||
|
||||
|
|
@ -1782,6 +1778,34 @@ client_accept(ns_client_t *client) {
|
|||
UNLOCK(&client->interface->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
client_udprecv(ns_client_t *client) {
|
||||
isc_result_t result;
|
||||
isc_region_t r;
|
||||
|
||||
CTRACE("udprecv");
|
||||
|
||||
r.base = client->recvbuf;
|
||||
r.length = RECV_BUFFER_SIZE;
|
||||
result = isc_socket_recv(client->udpsocket, &r, 1,
|
||||
client->task, client_request, client);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_socket_recv() failed: %s",
|
||||
isc_result_totext(result));
|
||||
/*
|
||||
* XXXBEW What should we do? We're trying to accept but
|
||||
* it didn't work. If we just give up, then UDP
|
||||
* service may eventually stop.
|
||||
*
|
||||
* For now, we just go idle.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
INSIST(client->nrecvs == 0);
|
||||
client->nrecvs++;
|
||||
}
|
||||
|
||||
void
|
||||
ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
|
||||
REQUIRE(NS_CLIENT_VALID(source));
|
||||
|
|
@ -1972,8 +1996,12 @@ ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
|
|||
isc_socket_attach(ifp->tcpsocket,
|
||||
&client->tcplistener);
|
||||
} else {
|
||||
isc_socket_t *sock;
|
||||
|
||||
dns_dispatch_attach(ifp->udpdispatch,
|
||||
&client->dispatch);
|
||||
sock = dns_dispatch_getsocket(client->dispatch);
|
||||
isc_socket_attach(sock, &client->udpsocket);
|
||||
}
|
||||
client->manager = manager;
|
||||
ISC_LIST_APPEND(manager->active, client, link);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: client.h,v 1.49 2001/01/09 21:40:12 bwelling Exp $ */
|
||||
/* $Id: client.h,v 1.50 2001/01/27 02:08:03 bwelling Exp $ */
|
||||
|
||||
#ifndef NAMED_CLIENT_H
|
||||
#define NAMED_CLIENT_H 1
|
||||
|
|
@ -93,14 +93,14 @@ struct ns_client {
|
|||
int naccepts;
|
||||
int nreads;
|
||||
int nsends;
|
||||
int nrecvs;
|
||||
int references;
|
||||
unsigned int attributes;
|
||||
isc_task_t * task;
|
||||
dns_view_t * view;
|
||||
dns_view_t * lockview;
|
||||
dns_dispatch_t * dispatch;
|
||||
dns_dispentry_t * dispentry;
|
||||
dns_dispatchevent_t * dispevent;
|
||||
isc_socket_t * udpsocket;
|
||||
isc_socket_t * tcplistener;
|
||||
isc_socket_t * tcpsocket;
|
||||
unsigned char * tcpbuf;
|
||||
|
|
@ -109,6 +109,7 @@ struct ns_client {
|
|||
isc_timer_t * timer;
|
||||
dns_message_t * message;
|
||||
unsigned char * sendbuf;
|
||||
unsigned char * recvbuf;
|
||||
dns_rdataset_t * opt;
|
||||
isc_uint16_t udpsize;
|
||||
isc_uint16_t extflags;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: interfacemgr.c,v 1.55 2001/01/09 21:39:42 bwelling Exp $ */
|
||||
/* $Id: interfacemgr.c,v 1.56 2001/01/27 02:08:01 bwelling Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
|
@ -244,6 +244,7 @@ ns_interface_listenudp(ns_interface_t *ifp) {
|
|||
attrs |= DNS_DISPATCHATTR_IPV4;
|
||||
else
|
||||
attrs |= DNS_DISPATCHATTR_IPV6;
|
||||
attrs |= DNS_DISPATCHATTR_NOLISTEN;
|
||||
attrmask = 0;
|
||||
attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
|
||||
attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
|
||||
|
|
@ -269,6 +270,8 @@ ns_interface_listenudp(ns_interface_t *ifp) {
|
|||
return (ISC_R_SUCCESS);
|
||||
|
||||
addtodispatch_failure:
|
||||
dns_dispatch_changeattributes(ifp->udpdispatch, 0,
|
||||
DNS_DISPATCHATTR_NOLISTEN);
|
||||
dns_dispatch_detach(&ifp->udpdispatch);
|
||||
udp_dispatch_failure:
|
||||
return (result);
|
||||
|
|
@ -373,8 +376,11 @@ ns_interface_destroy(ns_interface_t *ifp) {
|
|||
|
||||
ns_interface_shutdown(ifp);
|
||||
|
||||
if (ifp->udpdispatch != NULL)
|
||||
if (ifp->udpdispatch != NULL) {
|
||||
dns_dispatch_changeattributes(ifp->udpdispatch, 0,
|
||||
DNS_DISPATCHATTR_NOLISTEN);
|
||||
dns_dispatch_detach(&ifp->udpdispatch);
|
||||
}
|
||||
if (ifp->tcpsocket != NULL)
|
||||
isc_socket_detach(&ifp->tcpsocket);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: dispatch.c,v 1.85 2001/01/25 13:52:32 gson Exp $ */
|
||||
/* $Id: dispatch.c,v 1.86 2001/01/27 02:08:04 bwelling Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
|
@ -109,6 +109,7 @@ struct dns_dispatch {
|
|||
isc_sockaddr_t local; /* local address */
|
||||
unsigned int maxrequests; /* max requests */
|
||||
dns_acl_t *blackhole;
|
||||
isc_event_t *ctlevent;
|
||||
|
||||
/* Locked by mgr->lock. */
|
||||
ISC_LINK(dns_dispatch_t) link;
|
||||
|
|
@ -156,7 +157,7 @@ struct dns_dispatch {
|
|||
static dns_dispentry_t *bucket_search(dns_qid_t *, isc_sockaddr_t *,
|
||||
dns_messageid_t, unsigned int);
|
||||
static isc_boolean_t destroy_disp_ok(dns_dispatch_t *);
|
||||
static void destroy_disp(dns_dispatch_t **);
|
||||
static void destroy_disp(isc_task_t *task, isc_event_t *event);
|
||||
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 *);
|
||||
|
|
@ -376,14 +377,19 @@ destroy_disp_ok(dns_dispatch_t *disp)
|
|||
* The manager must be locked.
|
||||
*/
|
||||
static void
|
||||
destroy_disp(dns_dispatch_t **dispp) {
|
||||
dns_dispatchmgr_t *mgr;
|
||||
destroy_disp(isc_task_t *task, isc_event_t *event) {
|
||||
dns_dispatch_t *disp;
|
||||
dns_dispatchmgr_t *mgr;
|
||||
isc_boolean_t killmgr;
|
||||
|
||||
disp = *dispp;
|
||||
*dispp = NULL;
|
||||
INSIST(event->ev_type == DNS_EVENT_DISPATCHCONTROL);
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
disp = event->ev_arg;
|
||||
mgr = disp->mgr;
|
||||
|
||||
LOCK(&mgr->lock);
|
||||
ISC_LIST_UNLINK(mgr->list, disp, link);
|
||||
|
||||
dispatch_log(disp, LVL(90),
|
||||
|
|
@ -392,8 +398,14 @@ destroy_disp(dns_dispatch_t **dispp) {
|
|||
|
||||
isc_socket_detach(&disp->socket);
|
||||
isc_task_detach(&disp->task);
|
||||
isc_event_free(&event);
|
||||
|
||||
dispatch_free(&disp);
|
||||
|
||||
killmgr = destroy_mgr_ok(mgr);
|
||||
UNLOCK(&mgr->lock);
|
||||
if (killmgr)
|
||||
destroy_mgr(&mgr);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -537,8 +549,10 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
|
|||
"got packet: requests %d, buffers %d, recvs %d",
|
||||
disp->requests, disp->mgr->buffers, disp->recv_pending);
|
||||
|
||||
INSIST(disp->recv_pending != 0);
|
||||
disp->recv_pending = 0;
|
||||
if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0) {
|
||||
INSIST(disp->recv_pending != 0);
|
||||
disp->recv_pending = 0;
|
||||
}
|
||||
|
||||
if (disp->shutting_down) {
|
||||
/*
|
||||
|
|
@ -551,14 +565,8 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
|
|||
|
||||
killit = destroy_disp_ok(disp);
|
||||
UNLOCK(&disp->lock);
|
||||
if (killit) {
|
||||
LOCK(&mgr->lock);
|
||||
destroy_disp(&disp);
|
||||
killit = destroy_mgr_ok(mgr);
|
||||
UNLOCK(&mgr->lock);
|
||||
if (killit)
|
||||
destroy_mgr(&mgr);
|
||||
}
|
||||
if (killit)
|
||||
isc_task_send(disp->task, &disp->ctlevent);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -800,14 +808,8 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
|
|||
*/
|
||||
killit = destroy_disp_ok(disp);
|
||||
UNLOCK(&disp->lock);
|
||||
if (killit) {
|
||||
LOCK(&mgr->lock);
|
||||
destroy_disp(&disp);
|
||||
killit = destroy_mgr_ok(mgr);
|
||||
UNLOCK(&mgr->lock);
|
||||
if (killit)
|
||||
destroy_mgr(&mgr);
|
||||
}
|
||||
if (killit)
|
||||
isc_task_send(disp->task, &disp->ctlevent);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -921,6 +923,9 @@ startrecv(dns_dispatch_t *disp) {
|
|||
if (disp->shutting_down == 1)
|
||||
return;
|
||||
|
||||
if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)
|
||||
return;
|
||||
|
||||
if (disp->recv_pending != 0)
|
||||
return;
|
||||
|
||||
|
|
@ -1560,6 +1565,13 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
|
|||
if (result != ISC_R_SUCCESS)
|
||||
goto kill_socket;
|
||||
|
||||
disp->ctlevent = isc_event_allocate(mgr->mctx, disp,
|
||||
DNS_EVENT_DISPATCHCONTROL,
|
||||
destroy_disp, disp,
|
||||
sizeof(isc_event_t));
|
||||
if (disp->ctlevent == NULL)
|
||||
goto kill_task;
|
||||
|
||||
isc_task_setname(disp->task, "tcpdispatch", disp);
|
||||
|
||||
dns_tcpmsg_init(mgr->mctx, disp->socket, &disp->tcpmsg);
|
||||
|
|
@ -1583,6 +1595,8 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
|
|||
/*
|
||||
* Error returns.
|
||||
*/
|
||||
kill_task:
|
||||
isc_task_detach(&disp->task);
|
||||
kill_socket:
|
||||
isc_socket_detach(&disp->socket);
|
||||
deallocate_dispatch:
|
||||
|
|
@ -1634,6 +1648,13 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
|||
if (disp->maxrequests < maxrequests)
|
||||
disp->maxrequests = maxrequests;
|
||||
|
||||
if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0 &&
|
||||
(attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)
|
||||
disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;
|
||||
if (disp->recv_pending > 0)
|
||||
isc_socket_cancel(disp->socket, NULL,
|
||||
ISC_SOCKCANCEL_RECV);
|
||||
|
||||
UNLOCK(&disp->lock);
|
||||
UNLOCK(&mgr->lock);
|
||||
|
||||
|
|
@ -1693,6 +1714,13 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
|||
if (result != ISC_R_SUCCESS)
|
||||
goto kill_socket;
|
||||
|
||||
disp->ctlevent = isc_event_allocate(mgr->mctx, disp,
|
||||
DNS_EVENT_DISPATCHCONTROL,
|
||||
destroy_disp, disp,
|
||||
sizeof(isc_event_t));
|
||||
if (disp->ctlevent == NULL)
|
||||
goto kill_task;
|
||||
|
||||
isc_task_setname(disp->task, "udpdispatch", disp);
|
||||
|
||||
attributes &= ~DNS_DISPATCHATTR_TCP;
|
||||
|
|
@ -1715,6 +1743,8 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
|||
/*
|
||||
* Error returns.
|
||||
*/
|
||||
kill_task:
|
||||
isc_task_detach(&disp->task);
|
||||
kill_socket:
|
||||
isc_socket_detach(&disp->socket);
|
||||
deallocate_dispatch:
|
||||
|
|
@ -1771,14 +1801,8 @@ dns_dispatch_detach(dns_dispatch_t **dispp) {
|
|||
|
||||
killit = destroy_disp_ok(disp);
|
||||
UNLOCK(&disp->lock);
|
||||
if (killit) {
|
||||
LOCK(&mgr->lock);
|
||||
destroy_disp(&disp);
|
||||
killit = destroy_mgr_ok(mgr);
|
||||
UNLOCK(&mgr->lock);
|
||||
if (killit)
|
||||
destroy_mgr(&mgr);
|
||||
}
|
||||
if (killit)
|
||||
isc_task_send(disp->task, &disp->ctlevent);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
|
|
@ -1988,13 +2012,8 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
|
|||
|
||||
killit = destroy_disp_ok(disp);
|
||||
UNLOCK(&disp->lock);
|
||||
if (killit) {
|
||||
destroy_disp(&disp);
|
||||
killit = destroy_mgr_ok(mgr);
|
||||
UNLOCK(&mgr->lock);
|
||||
if (killit)
|
||||
destroy_mgr(&mgr);
|
||||
}
|
||||
if (killit)
|
||||
isc_task_send(disp->task, &disp->ctlevent);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
|
|
@ -2138,13 +2157,8 @@ dns_dispatch_removerequest(dns_dispentry_t **resp,
|
|||
|
||||
killit = destroy_disp_ok(disp);
|
||||
UNLOCK(&disp->lock);
|
||||
if (killit) {
|
||||
destroy_disp(&disp);
|
||||
killit = destroy_mgr_ok(mgr);
|
||||
UNLOCK(&mgr->lock);
|
||||
if (killit)
|
||||
destroy_mgr(&mgr);
|
||||
}
|
||||
if (killit)
|
||||
isc_task_send(disp->task, &disp->ctlevent);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2344,11 +2358,45 @@ dns_dispatch_changeattributes(dns_dispatch_t *disp,
|
|||
*/
|
||||
|
||||
LOCK(&disp->lock);
|
||||
|
||||
if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0 &&
|
||||
(attributes & DNS_DISPATCHATTR_NOLISTEN) == 0)
|
||||
{
|
||||
disp->attributes &= ~DNS_DISPATCHATTR_NOLISTEN;
|
||||
startrecv(disp);
|
||||
}
|
||||
|
||||
disp->attributes &= ~mask;
|
||||
disp->attributes |= (attributes & mask);
|
||||
UNLOCK(&disp->lock);
|
||||
}
|
||||
|
||||
void
|
||||
dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t **eventp) {
|
||||
void *buf;
|
||||
isc_socketevent_t *sevent;
|
||||
|
||||
REQUIRE(VALID_DISPATCH(disp));
|
||||
REQUIRE((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0);
|
||||
REQUIRE(eventp != NULL && *eventp != NULL);
|
||||
|
||||
sevent = (isc_socketevent_t *)*eventp;
|
||||
|
||||
INSIST(sevent->n <= disp->mgr->buffersize);
|
||||
buf = allocate_udp_buffer(disp);
|
||||
if (buf == NULL) {
|
||||
isc_event_free(eventp);
|
||||
return;
|
||||
}
|
||||
memcpy(buf, sevent->region.base, sevent->n);
|
||||
sevent->region.base = buf;
|
||||
sevent->region.length = disp->mgr->buffersize;
|
||||
sevent->ev_action = udp_recv;
|
||||
sevent->ev_arg = disp;
|
||||
sevent->ev_sender = NULL;
|
||||
isc_task_send(disp->task, eventp);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
dns_dispatchmgr_dump(dns_dispatchmgr_t *mgr) {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: dispatch.h,v 1.38 2001/01/09 21:52:47 bwelling Exp $ */
|
||||
/* $Id: dispatch.h,v 1.39 2001/01/27 02:08:06 bwelling Exp $ */
|
||||
|
||||
#ifndef DNS_DISPATCH_H
|
||||
#define DNS_DISPATCH_H 1
|
||||
|
|
@ -105,8 +105,8 @@ struct dns_dispatchevent {
|
|||
* _IPV4, _IPV6
|
||||
* The dispatcher uses an ipv4 or ipv6 socket.
|
||||
*
|
||||
* _ACCEPTREQUEST
|
||||
* The dispatcher can be used to accept requests.
|
||||
* _NOLISTEN
|
||||
* The dispatcher should not listen on the socket.
|
||||
*
|
||||
* _MAKEQUERY
|
||||
* The dispatcher can be used to issue queries to other servers, and
|
||||
|
|
@ -117,7 +117,7 @@ struct dns_dispatchevent {
|
|||
#define DNS_DISPATCHATTR_UDP 0x00000004U
|
||||
#define DNS_DISPATCHATTR_IPV4 0x00000008U
|
||||
#define DNS_DISPATCHATTR_IPV6 0x00000010U
|
||||
#define DNS_DISPATCHATTR_ACCEPTREQUEST 0x00000020U
|
||||
#define DNS_DISPATCHATTR_NOLISTEN 0x00000020U
|
||||
#define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U
|
||||
#define DNS_DISPATCHATTR_CONNECTED 0x00000080U
|
||||
|
||||
|
|
@ -462,6 +462,18 @@ dns_dispatch_changeattributes(dns_dispatch_t *disp,
|
|||
* attribute on a TCP socket isn't reasonable.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t **eventp);
|
||||
/*
|
||||
* Give a socket receive event to the dispatcher. This is used for sockets
|
||||
* shared between dispatchers and clients. If the dispatcher fails to send
|
||||
* the event, it frees it.
|
||||
*
|
||||
* Requires:
|
||||
* disp is valid, and the attribute DNS_DISPATCHATTR_NOLISTEN is set.
|
||||
* eventp != NULL && *eventp != NULL
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_DISPATCH_H */
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: events.h,v 1.35 2001/01/19 22:22:17 bwelling Exp $ */
|
||||
/* $Id: events.h,v 1.36 2001/01/27 02:08:07 bwelling Exp $ */
|
||||
|
||||
#ifndef DNS_EVENTS_H
|
||||
#define DNS_EVENTS_H 1
|
||||
|
|
@ -58,6 +58,7 @@
|
|||
#define DNS_EVENT_IOREADY (ISC_EVENTCLASS_DNS + 29)
|
||||
#define DNS_EVENT_LOOKUPDONE (ISC_EVENTCLASS_DNS + 30)
|
||||
#define DNS_EVENT_QUERYABORTED (ISC_EVENTCLASS_DNS + 31)
|
||||
#define DNS_EVENT_DISPATCHCONTROL (ISC_EVENTCLASS_DNS + 32)
|
||||
|
||||
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
|
||||
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
|
||||
|
|
|
|||
Loading…
Reference in a new issue