mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
convert ns_client and related objects to use netmgr
- ns__client_request() is now called by netmgr with an isc_nmhandle_t parameter. The handle can then be permanently associated with an ns_client object. - The task manager is paused so that isc_task events that may be triggred during client processing will not fire until after the netmgr is finished with it. Before any asynchronous event, the client MUST call isc_nmhandle_ref(client->handle), to prevent the client from being reset and reused while waiting for an event to process. When the asynchronous event is complete, isc_nmhandle_unref(client->handle) must be called to ensure the handle can be reused later. - reference counting of client objects is now handled in the nmhandle object. when the handle references drop to zero, the client's "reset" callback is used to free temporary resources and reiniialize it, whereupon the handle (and associated client) is placed in the "inactive handles" queue. when the sysstem is shutdown and the handles are cleaned up, the client's "put" callback is called to free all remaining resources. - because client allocation is no longer handled in the same way, the '-T clienttest' option has now been removed and is no longer used by any system tests. - the unit tests require wrapping the isc_nmhandle_unref() function; when LD_WRAP is supported, that is used. otherwise we link a libwrap.so interposer library and use that.
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <isc/interfaceiter.h>
|
||||
#include <isc/netmgr.h>
|
||||
#include <isc/os.h>
|
||||
#include <isc/random.h>
|
||||
#include <isc/string.h>
|
||||
@@ -72,6 +73,7 @@ struct ns_interfacemgr {
|
||||
isc_task_t * excl; /*%< Exclusive task. */
|
||||
isc_timermgr_t * timermgr; /*%< Timer manager. */
|
||||
isc_socketmgr_t * socketmgr; /*%< Socket manager. */
|
||||
isc_nm_t * nm; /*%< Net manager. */
|
||||
dns_dispatchmgr_t * dispatchmgr;
|
||||
unsigned int generation; /*%< Current generation no. */
|
||||
ns_listenlist_t * listenon4;
|
||||
@@ -172,6 +174,7 @@ ns_interfacemgr_create(isc_mem_t *mctx,
|
||||
isc_taskmgr_t *taskmgr,
|
||||
isc_timermgr_t *timermgr,
|
||||
isc_socketmgr_t *socketmgr,
|
||||
isc_nm_t *nm,
|
||||
dns_dispatchmgr_t *dispatchmgr,
|
||||
isc_task_t *task,
|
||||
unsigned int udpdisp,
|
||||
@@ -208,6 +211,7 @@ ns_interfacemgr_create(isc_mem_t *mctx,
|
||||
mgr->taskmgr = taskmgr;
|
||||
mgr->timermgr = timermgr;
|
||||
mgr->socketmgr = socketmgr;
|
||||
mgr->nm = nm;
|
||||
mgr->dispatchmgr = dispatchmgr;
|
||||
mgr->generation = 1;
|
||||
mgr->listenon4 = NULL;
|
||||
@@ -249,8 +253,9 @@ ns_interfacemgr_create(isc_mem_t *mctx,
|
||||
}
|
||||
|
||||
mgr->task = NULL;
|
||||
if (mgr->route != NULL)
|
||||
if (mgr->route != NULL) {
|
||||
isc_task_attach(task, &mgr->task);
|
||||
}
|
||||
isc_refcount_init(&mgr->references, (mgr->route != NULL) ? 2 : 1);
|
||||
#else
|
||||
isc_refcount_init(&mgr->references, 1);
|
||||
@@ -379,30 +384,19 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
||||
|
||||
ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
|
||||
*ifp = (ns_interface_t){
|
||||
.generation = mgr->generation,
|
||||
.addr = *addr,
|
||||
.dscp = -1
|
||||
};
|
||||
|
||||
ifp->mgr = NULL;
|
||||
ifp->generation = mgr->generation;
|
||||
ifp->addr = *addr;
|
||||
ifp->flags = 0;
|
||||
strlcpy(ifp->name, name, sizeof(ifp->name));
|
||||
ifp->clientmgr = NULL;
|
||||
|
||||
isc_mutex_init(&ifp->lock);
|
||||
|
||||
result = ns_clientmgr_create(mgr->mctx, mgr->sctx,
|
||||
mgr->taskmgr, mgr->timermgr,
|
||||
&ifp->clientmgr);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||
"ns_clientmgr_create() failed: %s",
|
||||
isc_result_totext(result));
|
||||
goto clientmgr_create_failure;
|
||||
}
|
||||
|
||||
for (disp = 0; disp < MAX_UDP_DISPATCH; disp++)
|
||||
for (disp = 0; disp < MAX_UDP_DISPATCH; disp++) {
|
||||
ifp->udpdispatch[disp] = NULL;
|
||||
|
||||
ifp->tcpsocket = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a single TCP client object. It will replace itself
|
||||
@@ -413,10 +407,6 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
isc_refcount_init(&ifp->ntcpaccepting, 0);
|
||||
isc_refcount_init(&ifp->ntcpactive, 0);
|
||||
|
||||
ifp->nudpdispatch = 0;
|
||||
|
||||
ifp->dscp = -1;
|
||||
|
||||
ISC_LINK_INIT(ifp, link);
|
||||
|
||||
ns_interfacemgr_attach(mgr, &ifp->mgr);
|
||||
@@ -424,11 +414,22 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
|
||||
isc_refcount_init(&ifp->references, 1);
|
||||
ifp->magic = IFACE_MAGIC;
|
||||
|
||||
result = ns_clientmgr_create(mgr->mctx, mgr->sctx,
|
||||
mgr->taskmgr, mgr->timermgr, ifp,
|
||||
&ifp->clientmgr);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||
"ns_clientmgr_create() failed: %s",
|
||||
isc_result_totext(result));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
*ifpret = ifp;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
clientmgr_create_failure:
|
||||
failure:
|
||||
isc_mutex_destroy(&ifp->lock);
|
||||
|
||||
ifp->magic = 0;
|
||||
@@ -440,127 +441,43 @@ 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;
|
||||
unsigned int attrmask;
|
||||
int disp, i;
|
||||
|
||||
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_NOLISTEN;
|
||||
attrs |= DNS_DISPATCHATTR_CANREUSE;
|
||||
attrmask = 0;
|
||||
attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
|
||||
attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
|
||||
|
||||
ifp->nudpdispatch = ISC_MIN(ifp->mgr->udpdisp, MAX_UDP_DISPATCH);
|
||||
for (disp = 0; disp < ifp->nudpdispatch; disp++) {
|
||||
result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr,
|
||||
ifp->mgr->socketmgr,
|
||||
ifp->mgr->taskmgr, &ifp->addr,
|
||||
4096, UDPBUFFERS,
|
||||
32768, 8219, 8237,
|
||||
attrs, attrmask,
|
||||
&ifp->udpdispatch[disp],
|
||||
disp == 0
|
||||
? NULL
|
||||
: ifp->udpdispatch[0]);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||
"could not listen on UDP socket: %s",
|
||||
isc_result_totext(result));
|
||||
goto udp_dispatch_failure;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
result = ns_clientmgr_createclients(ifp->clientmgr, ifp->nudpdispatch,
|
||||
ifp, false);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"UDP ns_clientmgr_createclients(): %s",
|
||||
isc_result_totext(result));
|
||||
goto addtodispatch_failure;
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
addtodispatch_failure:
|
||||
for (i = disp - 1; i >= 0; i--) {
|
||||
dns_dispatch_changeattributes(ifp->udpdispatch[i], 0,
|
||||
DNS_DISPATCHATTR_NOLISTEN);
|
||||
dns_dispatch_detach(&(ifp->udpdispatch[i]));
|
||||
}
|
||||
ifp->nudpdispatch = 0;
|
||||
|
||||
udp_dispatch_failure:
|
||||
/* Reserve space for an ns_client_t with the netmgr handle */
|
||||
result = isc_nm_listenudp(ifp->mgr->nm,
|
||||
(isc_nmiface_t *) &ifp->addr,
|
||||
ns__client_request, ifp,
|
||||
sizeof(ns_client_t),
|
||||
&ifp->udplistensocket);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
ns_interface_accepttcp(ns_interface_t *ifp) {
|
||||
ns_interface_listentcp(ns_interface_t *ifp) {
|
||||
isc_result_t result;
|
||||
|
||||
/*
|
||||
* Open a TCP socket.
|
||||
*/
|
||||
result = isc_socket_create(ifp->mgr->socketmgr,
|
||||
isc_sockaddr_pf(&ifp->addr),
|
||||
isc_sockettype_tcp,
|
||||
&ifp->tcpsocket);
|
||||
/* Reserve space for an ns_client_t with the netmgr handle */
|
||||
result = isc_nm_listentcpdns(ifp->mgr->nm,
|
||||
(isc_nmiface_t *) &ifp->addr,
|
||||
ns__client_request, ifp,
|
||||
sizeof(ns_client_t),
|
||||
&ifp->mgr->sctx->tcpquota,
|
||||
&ifp->tcplistensocket);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||
"creating TCP socket: %s",
|
||||
isc_result_totext(result));
|
||||
goto tcp_socket_failure;
|
||||
}
|
||||
isc_socket_setname(ifp->tcpsocket, "dispatcher", NULL);
|
||||
|
||||
#if 0
|
||||
#ifndef ISC_ALLOW_MAPPED
|
||||
isc_socket_ipv6only(ifp->tcpsocket, true);
|
||||
#endif
|
||||
result = isc_socket_bind(ifp->tcpsocket, &ifp->addr,
|
||||
ISC_SOCKET_REUSEADDRESS);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||
"binding TCP socket: %s",
|
||||
isc_result_totext(result));
|
||||
goto tcp_bind_failure;
|
||||
}
|
||||
|
||||
if (ifp->dscp != -1)
|
||||
isc_socket_dscp(ifp->tcpsocket, ifp->dscp);
|
||||
|
||||
result = isc_socket_listen(ifp->tcpsocket, ifp->mgr->backlog);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||
"listening on TCP socket: %s",
|
||||
isc_result_totext(result));
|
||||
goto tcp_listen_failure;
|
||||
}
|
||||
|
||||
/*
|
||||
* If/when there a multiple filters listen to the
|
||||
* result.
|
||||
*/
|
||||
(void)isc_socket_filter(ifp->tcpsocket, "dataready");
|
||||
|
||||
result = ns_clientmgr_createclients(ifp->clientmgr, 1, ifp, true);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"TCP ns_clientmgr_createclients(): %s",
|
||||
isc_result_totext(result));
|
||||
goto accepttcp_failure;
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
accepttcp_failure:
|
||||
tcp_listen_failure:
|
||||
tcp_bind_failure:
|
||||
isc_socket_detach(&ifp->tcpsocket);
|
||||
tcp_socket_failure:
|
||||
#endif
|
||||
return (result);
|
||||
}
|
||||
|
||||
@@ -591,7 +508,7 @@ ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
if (((mgr->sctx->options & NS_SERVER_NOTCP) == 0) &&
|
||||
accept_tcp == true)
|
||||
{
|
||||
result = ns_interface_accepttcp(ifp);
|
||||
result = ns_interface_listentcp(ifp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if ((result == ISC_R_ADDRINUSE) &&
|
||||
(addr_in_use != NULL))
|
||||
@@ -617,8 +534,17 @@ ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
|
||||
void
|
||||
ns_interface_shutdown(ns_interface_t *ifp) {
|
||||
if (ifp->clientmgr != NULL)
|
||||
if (ifp->udplistensocket != NULL) {
|
||||
isc_nm_udp_stoplistening(ifp->udplistensocket);
|
||||
isc_nmsocket_detach(&ifp->udplistensocket);
|
||||
}
|
||||
if (ifp->tcplistensocket != NULL) {
|
||||
isc_nm_tcpdns_stoplistening(ifp->tcplistensocket);
|
||||
isc_nmsocket_detach(&ifp->tcplistensocket);
|
||||
}
|
||||
if (ifp->clientmgr != NULL) {
|
||||
ns_clientmgr_destroy(&ifp->clientmgr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
Reference in New Issue
Block a user