/*
* Copy the aclenv object.
*/
- dns_aclenv_copy(&view->aclenv, ns_interfacemgr_getaclenv(
- named_g_server->interfacemgr));
+ dns_aclenv_copy(view->aclenv, ns_interfacemgr_getaclenv(
+ named_g_server->interfacemgr));
/*
* Configure the "match-clients" and "match-destinations" ACL.
#include <dns/acl.h>
#include <dns/iptable.h>
+#define DNS_ACLENV_MAGIC ISC_MAGIC('a', 'c', 'n', 'v')
+#define VALID_ACLENV(a) ISC_MAGIC_VALID(a, DNS_ACLENV_MAGIC)
+
/*
* Create a new ACL, including an IP table and an array with room
* for 'n' ACL elements. The elements are uninitialized and the
* Initialize ACL environment, setting up localhost and localnets ACLs
*/
isc_result_t
-dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) {
+dns_aclenv_create(isc_mem_t *mctx, dns_aclenv_t **envp) {
isc_result_t result;
+ dns_aclenv_t *env = isc_mem_get(mctx, sizeof(*env));
+ *env = (dns_aclenv_t){ 0 };
+
+ isc_mem_attach(mctx, &env->mctx);
+ isc_refcount_init(&env->references, 1);
- env->localhost = NULL;
- env->localnets = NULL;
result = dns_acl_create(mctx, 0, &env->localhost);
if (result != ISC_R_SUCCESS) {
goto cleanup_nothing;
#if defined(HAVE_GEOIP2)
env->geoip = NULL;
#endif /* if defined(HAVE_GEOIP2) */
+
+ env->magic = DNS_ACLENV_MAGIC;
+
+ *envp = env;
+
return (ISC_R_SUCCESS);
cleanup_localhost:
void
dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s) {
+ REQUIRE(VALID_ACLENV(s));
+ REQUIRE(VALID_ACLENV(t));
+
dns_acl_detach(&t->localhost);
dns_acl_attach(s->localhost, &t->localhost);
dns_acl_detach(&t->localnets);
dns_acl_attach(s->localnets, &t->localnets);
+
t->match_mapped = s->match_mapped;
#if defined(HAVE_GEOIP2)
t->geoip = s->geoip;
#endif /* if defined(HAVE_GEOIP2) */
}
-void
-dns_aclenv_destroy(dns_aclenv_t *env) {
- if (env->localhost != NULL) {
- dns_acl_detach(&env->localhost);
+static void
+dns__aclenv_destroy(dns_aclenv_t *aclenv) {
+ REQUIRE(VALID_ACLENV(aclenv));
+
+ aclenv->magic = 0;
+
+ if (aclenv->localhost != NULL) {
+ dns_acl_detach(&aclenv->localhost);
+ }
+ if (aclenv->localnets != NULL) {
+ dns_acl_detach(&aclenv->localnets);
}
- if (env->localnets != NULL) {
- dns_acl_detach(&env->localnets);
+
+ isc_mem_putanddetach(&aclenv->mctx, aclenv, sizeof(*aclenv));
+}
+
+void
+dns_aclenv_attach(dns_aclenv_t *source, dns_aclenv_t **targetp) {
+ REQUIRE(VALID_ACLENV(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ isc_refcount_increment(&source->references);
+ *targetp = source;
+}
+
+void
+dns_aclenv_detach(dns_aclenv_t **aclenvp) {
+ dns_aclenv_t *aclenv = NULL;
+
+ REQUIRE(aclenvp != NULL && VALID_ACLENV(*aclenvp));
+
+ aclenv = *aclenvp;
+ *aclenvp = NULL;
+
+ if (isc_refcount_decrement(&aclenv->references) == 1) {
+ dns__aclenv_destroy(aclenv);
}
}
};
struct dns_aclenv {
- dns_acl_t *localhost;
- dns_acl_t *localnets;
- bool match_mapped;
+ unsigned int magic;
+ isc_mem_t * mctx;
+ isc_refcount_t references;
+ dns_acl_t * localhost;
+ dns_acl_t * localnets;
+ bool match_mapped;
#if defined(HAVE_GEOIP2)
dns_geoip_databases_t *geoip;
#endif /* HAVE_GEOIP2 */
*/
isc_result_t
-dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env);
+dns_aclenv_create(isc_mem_t *mctx, dns_aclenv_t **envp);
/*%<
- * Initialize ACL environment, setting up localhost and localnets ACLs
+ * Create ACL environment, setting up localhost and localnets ACLs
*/
void
dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s);
+/*%<
+ * Copy the ACLs from one ACL environment object to another.
+ *
+ * Requires:
+ *\li both 's' and 't' are valid ACL environments.
+ */
+
+void
+dns_aclenv_attach(dns_aclenv_t *source, dns_aclenv_t **targetp);
+/*%<
+ * Attach '*targetp' to ACL environment 'source'.
+ *
+ * Requires:
+ *\li 'source' is a valid ACL environment.
+ *\li 'targetp' is not NULL and '*targetp' is NULL.
+ */
void
-dns_aclenv_destroy(dns_aclenv_t *env);
+dns_aclenv_detach(dns_aclenv_t **aclenvp);
+/*%<
+ * Detach an ACL environment; on final detach, destroy it.
+ *
+ * Requires:
+ *\li '*aclenvp' to be a valid ACL environment
+ */
isc_result_t
dns_acl_match(const isc_netaddr_t *reqaddr, const dns_name_t *reqsigner,
dns_ttl_t prefetch_trigger;
dns_ttl_t prefetch_eligible;
in_port_t dstport;
- dns_aclenv_t aclenv;
+ dns_aclenv_t * aclenv;
dns_rdatatype_t preferred_glue;
bool flush;
dns_namelist_t * delonly;
if (blackhole != NULL) {
int match;
- if ((dns_acl_match(&ipaddr, NULL, blackhole, &res->view->aclenv,
+ if ((dns_acl_match(&ipaddr, NULL, blackhole, res->view->aclenv,
&match, NULL) == ISC_R_SUCCESS) &&
match > 0)
{
}
result = dns_acl_match(&netaddr, NULL, view->denyansweracl,
- &view->aclenv, &match, NULL);
+ view->aclenv, &match, NULL);
if (result == ISC_R_SUCCESS && match > 0) {
isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
dns_name_format(name, namebuf, sizeof(namebuf));
if (rrl->exempt != NULL) {
isc_netaddr_fromsockaddr(&netclient, client_addr);
result = dns_acl_match(&netclient, NULL, rrl->exempt,
- &view->aclenv, &exempt_match, NULL);
+ view->aclenv, &exempt_match, NULL);
if (result == ISC_R_SUCCESS && exempt_match > 0) {
return (DNS_RRL_RESULT_OK);
}
goto cleanup_order;
}
- result = dns_aclenv_init(view->mctx, &view->aclenv);
+ result = dns_aclenv_create(view->mctx, &view->aclenv);
if (result != ISC_R_SUCCESS) {
goto cleanup_peerlist;
}
}
#endif /* HAVE_LMDB */
dns_fwdtable_destroy(&view->fwdtable);
- dns_aclenv_destroy(&view->aclenv);
+ dns_aclenv_detach(&view->aclenv);
if (view->failcache != NULL) {
dns_badcache_destroy(&view->failcache);
}
dns_acl_merge
dns_acl_none
dns_aclelement_match
+dns_aclenv_attach
dns_aclenv_copy
-dns_aclenv_destroy
-dns_aclenv_init
+dns_aclenv_create
+dns_aclenv_detach
dns_adb_adjustsrtt
dns_adb_agesrtt
dns_adb_attach
if (isc_sockaddr_eqaddr(from, &zone->masters[i])) {
break;
}
- if (zone->view->aclenv.match_mapped &&
+ if (zone->view->aclenv->match_mapped &&
IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
isc_sockaddr_pf(&zone->masters[i]) == AF_INET)
{
tsigkey = dns_message_gettsigkey(msg);
tsig = dns_tsigkey_identity(tsigkey);
if (i >= zone->masterscnt && zone->notify_acl != NULL &&
- (dns_acl_match(&netaddr, tsig, zone->notify_acl,
- &zone->view->aclenv, &match,
- NULL) == ISC_R_SUCCESS) &&
+ (dns_acl_match(&netaddr, tsig, zone->notify_acl, zone->view->aclenv,
+ &match, NULL) == ISC_R_SUCCESS) &&
match > 0)
{
/* Accept notify. */
* tid will be picked randomly. The threadid is capped (by modulo) to
* maximum number of 'workers' as specifed in isc_nm_start()
*/
+
+void
+isc__nm_force_tid(int tid);
+/*%<
+ * Force the thread ID to 'tid'. This is STRICTLY for use in unit
+ * tests and should not be used in any production code.
+ */
bool
isc__nm_in_netthread(void);
-/*%
+/*%<
* Returns 'true' if we're in the network thread.
*/
return (isc__nm_tid_v >= 0);
}
+void
+isc__nm_force_tid(int tid) {
+ isc__nm_tid_v = tid;
+}
+
#ifdef WIN32
static void
isc__nm_winsock_initialize(void) {
isc_netaddr_totext
isc_netaddr_unspec
isc_netscope_pton
+isc__nm_force_tid
isc__nmhandle_attach
isc__nmhandle_detach
isc_nmhandle_cleartimeout
static void
compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
const unsigned char *secret, isc_buffer_t *buf);
-static void
-get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp);
void
ns_client_recursing(ns_client_t *client) {
void
ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
isc_result_t result;
- unsigned char *data;
+ unsigned char *data = NULL;
isc_buffer_t buffer;
isc_region_t r;
- isc_region_t *mr;
+ isc_region_t *mr = NULL;
REQUIRE(NS_CLIENT_VALID(client));
void
ns_client_send(ns_client_t *client) {
isc_result_t result;
- unsigned char *data;
+ unsigned char *data = NULL;
isc_buffer_t buffer = { .magic = 0 };
isc_region_t r;
dns_compress_t cctx;
unsigned int preferred_glue;
bool opt_included = false;
size_t respsize;
- dns_aclenv_t *env;
+ dns_aclenv_t *env = NULL;
#ifdef HAVE_DNSTAP
unsigned char zone[DNS_NAME_MAXWIRE];
dns_dtmsgtype_t dtmsgtype;
* Delay the response according to the -T delay option
*/
- env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
+ env = client->manager->aclenv;
CTRACE("send");
ns_client_addopt(ns_client_t *client, dns_message_t *message,
dns_rdataset_t **opt) {
unsigned char ecs[ECS_SIZE];
- char nsid[BUFSIZ], *nsidp;
+ char nsid[BUFSIZ], *nsidp = NULL;
unsigned char cookie[COOKIE_SIZE];
isc_result_t result;
- dns_view_t *view;
- dns_resolver_t *resolver;
+ dns_view_t *view = NULL;
+ dns_resolver_t *resolver = NULL;
uint16_t udpsize;
dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
int count = 0;
unsigned int flags;
unsigned char expire[4];
unsigned char advtimo[2];
- dns_aclenv_t *env;
+ dns_aclenv_t *env = NULL;
REQUIRE(NS_CLIENT_VALID(client));
REQUIRE(opt != NULL && *opt == NULL);
REQUIRE(message != NULL);
- env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
+ env = client->manager->aclenv;
view = client->view;
resolver = (view != NULL) ? view->resolver : NULL;
if (resolver != NULL) {
client->magic = 0;
client->shuttingdown = true;
- if (client->manager != NULL) {
- clientmgr_detach(&client->manager);
- }
-
isc_mem_put(client->mctx, client->sendbuf, NS_CLIENT_SEND_BUFFER_SIZE);
if (client->opt != NULL) {
INSIST(dns_rdataset_isassociated(client->opt));
dns_message_detach(&client->message);
+ if (client->manager != NULL) {
+ clientmgr_detach(&client->manager);
+ }
+
/*
* Detaching the task must be done after unlinking from
* the manager's lists because the manager accesses
ns_server_detach(&client->sctx);
}
- if (client->mctx != NULL) {
- isc_mem_detach(&client->mctx);
- }
+ isc_mem_detach(&client->mctx);
}
/*
bool notimp;
size_t reqsize;
dns_aclenv_t *env = NULL;
+ isc_sockaddr_t sockaddr;
#ifdef HAVE_DNSTAP
dns_dtmsgtype_t dtmsgtype;
#endif /* ifdef HAVE_DNSTAP */
client = isc_nmhandle_getdata(handle);
if (client == NULL) {
ns_interface_t *ifp = (ns_interface_t *)arg;
+ ns_clientmgr_t *clientmgr =
+ ns_interfacemgr_getclientmgr(ifp->mgr);
- INSIST(VALID_MANAGER(ifp->clientmgr));
+ INSIST(VALID_MANAGER(clientmgr));
client = isc_nmhandle_getextra(handle);
- result = ns__client_setup(client, ifp->clientmgr, true);
+ result = ns__client_setup(client, clientmgr, true);
if (result != ISC_R_SUCCESS) {
return;
}
}
#endif /* if NS_CLIENT_DROPPORT */
- env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
+ env = client->manager->aclenv;
if (client->sctx->blackholeacl != NULL &&
(dns_acl_match(&netaddr, NULL, client->sctx->blackholeacl, env,
&match, NULL) == ISC_R_SUCCESS) &&
return;
}
- /*
- * Determine the destination address. If the receiving interface is
- * bound to a specific address, we simply use it regardless of the
- * address family. All IPv4 queries should fall into this case.
- * Otherwise, if this is a TCP query, get the address from the
- * receiving socket (this needs a system call and can be heavy).
- * For IPv6 UDP queries, we get this from the pktinfo structure (if
- * supported).
- *
- * If all the attempts fail (this can happen due to memory shortage,
- * etc), we regard this as an error for safety.
- */
- if ((client->manager->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
- {
- isc_netaddr_fromsockaddr(&client->destaddr,
- &client->manager->interface->addr);
- } else {
- isc_sockaddr_t sockaddr = isc_nmhandle_localaddr(handle);
- isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
- }
+ sockaddr = isc_nmhandle_localaddr(handle);
+ isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
isc_sockaddr_fromnetaddr(&client->destsockaddr, &client->destaddr, 0);
return (ISC_R_SUCCESS);
}
-static void
-get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp) {
- MTRACE("clienttask");
-
- int tid = isc_nm_tid();
- REQUIRE(tid >= 0);
- REQUIRE(tid < manager->ncpus);
-
- isc_task_attach(manager->taskpool[tid], taskp);
-}
-
isc_result_t
ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
isc_result_t result;
* The caller is responsible for that.
*/
- REQUIRE(NS_CLIENT_VALID(client) || (new &&client != NULL));
- REQUIRE(VALID_MANAGER(mgr) || !new);
-
if (new) {
- *client = (ns_client_t){ .magic = 0 };
+ REQUIRE(VALID_MANAGER(mgr));
+ REQUIRE(client != NULL);
+ REQUIRE(mgr->tid == isc_nm_tid());
+
+ *client = (ns_client_t){ .magic = 0, .tid = mgr->tid };
isc_mem_attach(mgr->mctx, &client->mctx);
clientmgr_attach(mgr, &client->manager);
ns_server_attach(mgr->sctx, &client->sctx);
- get_clienttask(mgr, &client->task);
+ isc_task_attach(mgr->task, &client->task);
dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
&client->message);
goto cleanup;
}
} else {
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(client->tid == isc_nm_tid());
+
ns_clientmgr_t *oldmgr = client->manager;
ns_server_t *sctx = client->sctx;
isc_task_t *task = client->task;
dns_message_t *message = client->message;
isc_mem_t *oldmctx = client->mctx;
ns_query_t query = client->query;
+ int tid = client->tid;
/*
* Retain these values from the existing client, but
.task = task,
.sendbuf = sendbuf,
.message = message,
- .query = query };
+ .query = query,
+ .tid = tid };
}
client->query.attributes &= ~NS_QUERYATTR_ANSWERED;
if (client->manager != NULL) {
clientmgr_detach(&client->manager);
}
- if (client->mctx != NULL) {
- isc_mem_detach(&client->mctx);
- }
+ isc_mem_detach(&client->mctx);
if (client->sctx != NULL) {
ns_server_detach(&client->sctx);
}
static void
clientmgr_destroy(ns_clientmgr_t *manager) {
- int i;
-
MTRACE("clientmgr_destroy");
isc_refcount_destroy(&manager->references);
manager->magic = 0;
- if (manager->interface != NULL) {
- ns_interface_detach(&manager->interface);
- }
+ dns_aclenv_detach(&manager->aclenv);
isc_mutex_destroy(&manager->lock);
isc_mutex_destroy(&manager->reclock);
isc_task_detach(&manager->excl);
}
- for (i = 0; i < manager->ncpus; i++) {
- if (manager->taskpool[i] != NULL) {
- isc_task_detach(&manager->taskpool[i]);
- }
- }
- isc_mem_put(manager->mctx, manager->taskpool,
- manager->ncpus * sizeof(manager->taskpool[0]));
+ isc_task_detach(&manager->task);
ns_server_detach(&manager->sctx);
- isc_mem_put(manager->mctx, manager, sizeof(*manager));
+ isc_mem_putanddetach(&manager->mctx, manager, sizeof(*manager));
}
isc_result_t
-ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, ns_interface_t *interface,
- int ncpus, ns_clientmgr_t **managerp) {
- ns_clientmgr_t *manager;
+ns_clientmgr_create(ns_server_t *sctx, isc_taskmgr_t *taskmgr,
+ isc_timermgr_t *timermgr, dns_aclenv_t *aclenv, int tid,
+ ns_clientmgr_t **managerp) {
+ ns_clientmgr_t *manager = NULL;
+ isc_mem_t *mctx = NULL;
isc_result_t result;
- int i;
- manager = isc_mem_get(mctx, sizeof(*manager));
- *manager = (ns_clientmgr_t){ .magic = 0 };
+ isc_mem_create(&mctx);
- isc_mutex_init(&manager->lock);
- isc_mutex_init(&manager->reclock);
+ manager = isc_mem_get(mctx, sizeof(*manager));
+ *manager = (ns_clientmgr_t){ .magic = 0, .mctx = mctx };
- manager->excl = NULL;
result = isc_taskmgr_excltask(taskmgr, &manager->excl);
if (result != ISC_R_SUCCESS) {
- goto cleanup_reclock;
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ return (result);
}
- manager->mctx = mctx;
+ isc_mutex_init(&manager->lock);
+ isc_mutex_init(&manager->reclock);
+
manager->taskmgr = taskmgr;
manager->timermgr = timermgr;
- manager->ncpus = ncpus;
+ manager->tid = tid;
- ns_interface_attach(interface, &manager->interface);
+ dns_aclenv_attach(aclenv, &manager->aclenv);
manager->exiting = false;
- manager->taskpool = isc_mem_get(
- mctx, manager->ncpus * sizeof(manager->taskpool[0]));
- for (i = 0; i < manager->ncpus; i++) {
- manager->taskpool[i] = NULL;
- result = isc_task_create_bound(manager->taskmgr, 20,
- &manager->taskpool[i], i);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- }
+ result = isc_task_create_bound(manager->taskmgr, 20, &manager->task,
+ manager->tid);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
isc_refcount_init(&manager->references, 1);
manager->sctx = NULL;
ns_server_attach(sctx, &manager->sctx);
*managerp = manager;
return (ISC_R_SUCCESS);
-
-cleanup_reclock:
- isc_mutex_destroy(&manager->reclock);
- isc_mutex_destroy(&manager->lock);
-
- isc_mem_put(mctx, manager, sizeof(*manager));
-
- return (result);
}
void
ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
dns_acl_t *acl, bool default_allow) {
isc_result_t result;
- dns_aclenv_t *env =
- ns_interfacemgr_getaclenv(client->manager->interface->mgr);
+ dns_aclenv_t *env = client->manager->aclenv;
isc_netaddr_t tmpnetaddr;
int match;
isc_timermgr_t *timermgr;
isc_task_t * excl;
isc_refcount_t references;
- int ncpus;
+ int tid;
/* Attached by clients, needed for e.g. recursion */
- isc_task_t **taskpool;
+ isc_task_t *task;
- ns_interface_t *interface;
+ dns_aclenv_t *aclenv;
/* Lock covers manager state. */
isc_mutex_t lock;
struct ns_client {
unsigned int magic;
isc_mem_t * mctx;
+ int tid;
bool allocated; /* Do we need to free it? */
ns_server_t * sctx;
ns_clientmgr_t * manager;
*/
isc_result_t
-ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr,
- isc_timermgr_t *timermgr, ns_interface_t *ifp, int ncpus,
+ns_clientmgr_create(ns_server_t *sctx, isc_taskmgr_t *taskmgr,
+ isc_timermgr_t *timermgr, dns_aclenv_t *aclenv, int tid,
ns_clientmgr_t **managerp);
/*%<
* Create a client manager.
* information regarding copyright ownership.
*/
-#ifndef NS_INTERFACEMGR_H
-#define NS_INTERFACEMGR_H 1
+#pragma once
/*****
***** Module Info
* servicing TCP queries
* (whether accepting or
* connected) */
- int nudpdispatch; /*%< Number of UDP dispatches */
- ns_clientmgr_t *clientmgr; /*%< Client manager. */
+ int nudpdispatch; /*%< Number of UDP dispatches */
ISC_LINK(ns_interface_t) link;
};
* Returns the ns_server object associated with the interface manager.
*/
+ns_clientmgr_t *
+ns_interfacemgr_getclientmgr(ns_interfacemgr_t *mgr);
+/*%<
+ *
+ * Returns the client manager for the current worker thread.
+ * (This cannot be run from outside a network manager thread.)
+ */
+
ns_interface_t *
ns__interfacemgr_getif(ns_interfacemgr_t *mgr);
ns_interface_t *
ns__interfacemgr_nextif(ns_interface_t *ifp);
-/*
+/*%<
* Functions to allow external callers to walk the interfaces list.
* (Not intended for use outside this module and associated tests.)
*/
-#endif /* NS_INTERFACEMGR_H */
/*% nameserver interface manager structure */
struct ns_interfacemgr {
- unsigned int magic; /*%< Magic number. */
+ unsigned int magic; /*%< Magic number */
isc_refcount_t references;
isc_mutex_t lock;
- isc_mem_t *mctx; /*%< Memory context. */
- ns_server_t *sctx; /*%< Server context. */
- isc_taskmgr_t *taskmgr; /*%< Task manager. */
- isc_task_t *excl; /*%< Exclusive task. */
- isc_timermgr_t *timermgr; /*%< Timer manager. */
- isc_socketmgr_t *socketmgr; /*%< Socket manager. */
- isc_nm_t *nm; /*%< Net manager. */
- int ncpus; /*%< Number of workers . */
+ isc_mem_t *mctx; /*%< Memory context */
+ ns_server_t *sctx; /*%< Server context */
+ isc_taskmgr_t *taskmgr; /*%< Task manager */
+ isc_task_t *excl; /*%< Exclusive task */
+ isc_timermgr_t *timermgr; /*%< Timer manager */
+ isc_socketmgr_t *socketmgr; /*%< Socket manager */
+ isc_nm_t *nm; /*%< Net manager */
+ int ncpus; /*%< Number of workers */
dns_dispatchmgr_t *dispatchmgr;
- unsigned int generation; /*%< Current generation no. */
+ unsigned int generation; /*%< Current generation no */
ns_listenlist_t *listenon4;
ns_listenlist_t *listenon6;
- dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */
- ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */
+ dns_aclenv_t *aclenv; /*%< Localhost/localnets ACLs */
+ ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces */
ISC_LIST(isc_sockaddr_t) listenon;
- int backlog; /*%< Listen queue size */
- unsigned int udpdisp; /*%< UDP dispatch count */
- atomic_bool shuttingdown; /*%< Interfacemgr is shutting
- * down */
+ int backlog; /*%< Listen queue size */
+ unsigned int udpdisp; /*%< UDP dispatch count */
+ atomic_bool shuttingdown; /*%< Interfacemgr shutting down */
+ ns_clientmgr_t **clientmgrs; /*%< Client managers */
#ifdef USE_ROUTE_SOCKET
isc_task_t *task;
isc_socket_t *route;
*/
result = ns_listenlist_create(mctx, &mgr->listenon4);
if (result != ISC_R_SUCCESS) {
- goto cleanup_ctx;
+ goto cleanup_sctx;
}
ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);
- result = dns_aclenv_init(mctx, &mgr->aclenv);
+ result = dns_aclenv_create(mctx, &mgr->aclenv);
if (result != ISC_R_SUCCESS) {
goto cleanup_listenon;
}
#if defined(HAVE_GEOIP2)
- mgr->aclenv.geoip = geoip;
+ mgr->aclenv->geoip = geoip;
#else /* if defined(HAVE_GEOIP2) */
UNUSED(geoip);
#endif /* if defined(HAVE_GEOIP2) */
mgr->magic = IFMGR_MAGIC;
*mgrp = mgr;
+ mgr->clientmgrs = isc_mem_get(mgr->mctx,
+ mgr->ncpus * sizeof(*mgr->clientmgrs[0]));
+ for (size_t i = 0; i < (size_t)mgr->ncpus; i++) {
+ result = ns_clientmgr_create(mgr->sctx, mgr->taskmgr,
+ mgr->timermgr, mgr->aclenv, (int)i,
+ &mgr->clientmgrs[i]);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ }
+
#ifdef USE_ROUTE_SOCKET
if (mgr->route != NULL) {
isc_region_t r = { mgr->buf, sizeof(mgr->buf) };
#ifdef USE_ROUTE_SOCKET
cleanup_aclenv:
- dns_aclenv_destroy(&mgr->aclenv);
+ dns_aclenv_detach(&mgr->aclenv);
#endif /* ifdef USE_ROUTE_SOCKET */
cleanup_listenon:
ns_listenlist_detach(&mgr->listenon4);
ns_listenlist_detach(&mgr->listenon6);
cleanup_lock:
isc_mutex_destroy(&mgr->lock);
-cleanup_ctx:
+cleanup_sctx:
ns_server_detach(&mgr->sctx);
isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
return (result);
isc_task_detach(&mgr->task);
}
#endif /* ifdef USE_ROUTE_SOCKET */
- dns_aclenv_destroy(&mgr->aclenv);
+ dns_aclenv_detach(&mgr->aclenv);
ns_listenlist_detach(&mgr->listenon4);
ns_listenlist_detach(&mgr->listenon6);
clearlistenon(mgr);
isc_mutex_destroy(&mgr->lock);
+ for (size_t i = 0; i < (size_t)mgr->ncpus; i++) {
+ ns_clientmgr_destroy(&mgr->clientmgrs[i]);
+ }
+ isc_mem_put(mgr->mctx, mgr->clientmgrs,
+ mgr->ncpus * sizeof(*mgr->clientmgrs[0]));
+
if (mgr->sctx != NULL) {
ns_server_detach(&mgr->sctx);
}
ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
- return (&mgr->aclenv);
+ return (mgr->aclenv);
}
void
ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
const char *name, ns_interface_t **ifpret) {
ns_interface_t *ifp;
- isc_result_t result;
int disp;
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
isc_refcount_init(&ifp->references, 1);
ifp->magic = IFACE_MAGIC;
- result = ns_clientmgr_create(mgr->mctx, mgr->sctx, mgr->taskmgr,
- mgr->timermgr, ifp, mgr->ncpus,
- &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;
- }
-
ifp->tcplistensocket = NULL;
ifp->http_listensocket = NULL;
ifp->http_secure_listensocket = NULL;
*ifpret = ifp;
return (ISC_R_SUCCESS);
-
-failure:
- isc_mutex_destroy(&ifp->lock);
-
- ifp->magic = 0;
- isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
-
- return (ISC_R_UNEXPECTED);
}
static isc_result_t
isc_nm_stoplistening(ifp->http_secure_listensocket);
isc_nmsocket_close(&ifp->http_secure_listensocket);
}
- if (ifp->clientmgr != NULL) {
- ns_clientmgr_destroy(&ifp->clientmgr);
- }
}
static void
/* First add localhost address */
prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
- result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable, netaddr,
+ result = dns_iptable_addprefix(mgr->aclenv->localhost->iptable, netaddr,
prefixlen, true);
if (result != ISC_R_SUCCESS) {
return (result);
return (ISC_R_SUCCESS);
}
- result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable, netaddr,
+ result = dns_iptable_addprefix(mgr->aclenv->localnets->iptable, netaddr,
prefixlen, true);
if (result != ISC_R_SUCCESS) {
return (result);
}
if (!adjusting) {
- result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
+ result = clearacl(mgr->mctx, &mgr->aclenv->localhost);
if (result != ISC_R_SUCCESS) {
goto cleanup_iter;
}
- result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
+ result = clearacl(mgr->mctx, &mgr->aclenv->localnets);
if (result != ISC_R_SUCCESS) {
goto cleanup_iter;
}
* if not, ignore the interface.
*/
(void)dns_acl_match(&listen_netaddr, NULL, le->acl,
- &mgr->aclenv, &match, NULL);
+ mgr->aclenv, &match, NULL);
if (match <= 0) {
continue;
}
void
ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
- ns_interface_t *interface;
-
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
LOCK(&mgr->lock);
- interface = ISC_LIST_HEAD(mgr->interfaces);
- while (interface != NULL) {
- if (interface->clientmgr != NULL) {
- ns_client_dumprecursing(f, interface->clientmgr);
- }
- interface = ISC_LIST_NEXT(interface, link);
+ for (size_t i = 0; i < (size_t)mgr->ncpus; i++) {
+ ns_client_dumprecursing(f, mgr->clientmgrs[i]);
}
UNLOCK(&mgr->lock);
}
UNLOCK(&ifp->lock);
return (next);
}
+
+ns_clientmgr_t *
+ns_interfacemgr_getclientmgr(ns_interfacemgr_t *mgr) {
+ int tid = isc_nm_tid();
+
+ REQUIRE(NS_INTERFACEMGR_VALID(mgr));
+ REQUIRE(tid >= 0);
+ REQUIRE(tid < mgr->ncpus);
+
+ return (mgr->clientmgrs[tid]);
+}
dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset) {
isc_netaddr_t netaddr;
- dns_aclenv_t *env =
- ns_interfacemgr_getaclenv(client->manager->interface->mgr);
+ dns_aclenv_t *env = client->manager->aclenv;
dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64);
unsigned int flags = 0;
unsigned int i, count;
static isc_result_t
query_dns64(query_ctx_t *qctx) {
ns_client_t *client = qctx->client;
- dns_aclenv_t *env =
- ns_interfacemgr_getaclenv(client->manager->interface->mgr);
+ dns_aclenv_t *env = client->manager->aclenv;
dns_name_t *name, *mname;
dns_rdata_t *dns64_rdata;
dns_rdata_t rdata = DNS_RDATA_INIT;
query_setup_sortlist(query_ctx_t *qctx) {
isc_netaddr_t netaddr;
ns_client_t *client = qctx->client;
- dns_aclenv_t *env =
- ns_interfacemgr_getaclenv(client->manager->interface->mgr);
+ dns_aclenv_t *env = client->manager->aclenv;
const void *order_arg = NULL;
isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
UNUSED(state);
+ isc__nm_force_tid(0);
+
result = ns_test_begin(NULL, true);
assert_int_equal(result, ISC_R_SUCCESS);
_teardown(void **state) {
UNUSED(state);
+ isc__nm_force_tid(-1);
+
ns_test_end();
return (0);
#include <isc/event.h>
#include <isc/print.h>
#include <isc/task.h>
+#include <isc/thread.h>
#include <dns/acl.h>
#include <dns/rcode.h>
UNUSED(state);
+ isc__nm_force_tid(0);
+
result = ns_test_begin(NULL, true);
assert_int_equal(result, ISC_R_SUCCESS);
_teardown(void **state) {
UNUSED(state);
+ isc__nm_force_tid(-1);
+
ns_test_end();
return (0);
* we'll just sleep for a bit and hope.
*/
ns_test_nap(500000);
- ns_interface_t *ifp = ns__interfacemgr_getif(interfacemgr);
- clientmgr = ifp->clientmgr;
+ clientmgr = ns_interfacemgr_getclientmgr(interfacemgr);
atomic_store(&run_managers, true);
UNUSED(state);
+ isc__nm_force_tid(0);
+
result = ns_test_begin(NULL, true);
assert_int_equal(result, ISC_R_SUCCESS);
_teardown(void **state) {
UNUSED(state);
+ isc__nm_force_tid(-1);
+
ns_test_end();
return (0);
dns_ttl_t maxttl = 0;
uint32_t maxrecords;
uint64_t records;
- dns_aclenv_t *env =
- ns_interfacemgr_getaclenv(client->manager->interface->mgr);
+ dns_aclenv_t *env = client->manager->aclenv;
size_t ruleslen = 0;
size_t rule;
const dns_ssurule_t **rules = NULL;
ns_interfacemgr_detach
ns_interfacemgr_dumprecursing
ns_interfacemgr_getaclenv
+ns_interfacemgr_getclientmgr
ns_interfacemgr_getserver
ns_interfacemgr_islistening
ns_interfacemgr_listeningon