isc_result_t
dns_acl_match(const isc_netaddr_t *reqaddr, const dns_name_t *reqsigner,
- const dns_acl_t *acl, const dns_aclenv_t *env, int *match,
+ const dns_acl_t *acl, dns_aclenv_t *env, int *match,
const dns_aclelement_t **matchelt) {
uint16_t bitlen;
isc_prefix_t pfx;
const in_port_t local_port,
const isc_nmsocket_type_t transport,
const bool encrypted, const dns_name_t *reqsigner,
- const dns_acl_t *acl, const dns_aclenv_t *env,
+ const dns_acl_t *acl, dns_aclenv_t *env,
int *match, const dns_aclelement_t **matchelt) {
isc_result_t result = ISC_R_SUCCESS;
dns_acl_port_transports_t *next;
bool
dns_aclelement_match(const isc_netaddr_t *reqaddr, const dns_name_t *reqsigner,
- const dns_aclelement_t *e, const dns_aclenv_t *env,
+ const dns_aclelement_t *e, dns_aclenv_t *env,
const dns_aclelement_t **matchelt) {
dns_acl_t *inner = NULL;
int indirectmatch;
}
case dns_aclelementtype_nestedacl:
- inner = e->nestedacl;
+ dns_acl_attach(e->nestedacl, &inner);
break;
case dns_aclelementtype_localhost:
- if (env == NULL || env->localhost == NULL) {
+ if (env == NULL) {
return (false);
}
- inner = env->localhost;
+ RWLOCK(&env->rwlock, isc_rwlocktype_read);
+ if (env->localhost == NULL) {
+ RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
+ return (false);
+ }
+ dns_acl_attach(env->localhost, &inner);
+ RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
break;
case dns_aclelementtype_localnets:
- if (env == NULL || env->localnets == NULL) {
+ if (env == NULL) {
+ return (false);
+ }
+ RWLOCK(&env->rwlock, isc_rwlocktype_read);
+ if (env->localnets == NULL) {
+ RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
return (false);
}
- inner = env->localnets;
+ dns_acl_attach(env->localnets, &inner);
+ RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
break;
#if defined(HAVE_GEOIP2)
matchelt);
INSIST(result == ISC_R_SUCCESS);
+ dns_acl_detach(&inner);
+
/*
* Treat negative matches in indirect ACLs as "no match".
* That way, a negated indirect ACL will never become a
isc_mem_attach(mctx, &env->mctx);
isc_refcount_init(&env->references, 1);
+ isc_rwlock_init(&env->rwlock, 0, 0);
result = dns_acl_create(mctx, 0, &env->localhost);
if (result != ISC_R_SUCCESS) {
- goto cleanup_nothing;
+ goto cleanup_rwlock;
}
result = dns_acl_create(mctx, 0, &env->localnets);
if (result != ISC_R_SUCCESS) {
cleanup_localhost:
dns_acl_detach(&env->localhost);
-cleanup_nothing:
+cleanup_rwlock:
+ isc_rwlock_destroy(&env->rwlock);
+ isc_mem_putanddetach(&env->mctx, env, sizeof(*env));
return (result);
}
+void
+dns_aclenv_set(dns_aclenv_t *env, dns_acl_t *localhost, dns_acl_t *localnets) {
+ REQUIRE(VALID_ACLENV(env));
+
+ RWLOCK(&env->rwlock, isc_rwlocktype_write);
+ dns_acl_detach(&env->localhost);
+ dns_acl_attach(localhost, &env->localhost);
+ dns_acl_detach(&env->localnets);
+ dns_acl_attach(localnets, &env->localnets);
+ RWUNLOCK(&env->rwlock, isc_rwlocktype_write);
+}
+
void
dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s) {
REQUIRE(VALID_ACLENV(s));
REQUIRE(VALID_ACLENV(t));
+ RWLOCK(&t->rwlock, isc_rwlocktype_write);
+ RWLOCK(&s->rwlock, isc_rwlocktype_read);
dns_acl_detach(&t->localhost);
dns_acl_attach(s->localhost, &t->localhost);
dns_acl_detach(&t->localnets);
#if defined(HAVE_GEOIP2)
t->geoip = s->geoip;
#endif /* if defined(HAVE_GEOIP2) */
+
+ RWUNLOCK(&s->rwlock, isc_rwlocktype_read);
+ RWUNLOCK(&t->rwlock, isc_rwlocktype_write);
}
static void
aclenv->magic = 0;
- if (aclenv->localhost != NULL) {
- dns_acl_detach(&aclenv->localhost);
- }
- if (aclenv->localnets != NULL) {
- dns_acl_detach(&aclenv->localnets);
- }
+ isc_refcount_destroy(&aclenv->references);
+ dns_acl_detach(&aclenv->localhost);
+ dns_acl_detach(&aclenv->localnets);
+ isc_rwlock_destroy(&aclenv->rwlock);
isc_mem_putanddetach(&aclenv->mctx, aclenv, sizeof(*aclenv));
}
isc_result_t
dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
- const dns_name_t *reqsigner, const dns_aclenv_t *env,
+ const dns_name_t *reqsigner, dns_aclenv_t *env,
unsigned int flags, unsigned char *a, unsigned char *aaaa) {
unsigned int nbytes, i;
isc_result_t result;
bool
dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
- const dns_name_t *reqsigner, const dns_aclenv_t *env,
+ const dns_name_t *reqsigner, dns_aclenv_t *env,
unsigned int flags, dns_rdataset_t *rdataset, bool *aaaaok,
size_t aaaaoklen) {
struct in6_addr in6;
#include <isc/magic.h>
#include <isc/netaddr.h>
#include <isc/refcount.h>
+#include <isc/rwlock.h>
#include <dns/geoip.h>
#include <dns/iptable.h>
unsigned int magic;
isc_mem_t *mctx;
isc_refcount_t references;
+
+ isc_rwlock_t rwlock; /*%< Locks localhost and localnets */
dns_acl_t *localhost;
dns_acl_t *localnets;
- bool match_mapped;
+
+ bool match_mapped;
#if defined(HAVE_GEOIP2)
dns_geoip_databases_t *geoip;
#endif /* HAVE_GEOIP2 */
*\li both 's' and 't' are valid ACL environments.
*/
+void
+dns_aclenv_set(dns_aclenv_t *env, dns_acl_t *localhost, dns_acl_t *localnets);
+/*%<
+ * Attach the 'localhost' and 'localnets' arguments to 'env' ACL environment
+ */
+
void
dns_aclenv_attach(dns_aclenv_t *source, dns_aclenv_t **targetp);
/*%<
isc_result_t
dns_acl_match(const isc_netaddr_t *reqaddr, const dns_name_t *reqsigner,
- const dns_acl_t *acl, const dns_aclenv_t *env, int *match,
+ const dns_acl_t *acl, dns_aclenv_t *env, int *match,
const dns_aclelement_t **matchelt);
/*%<
* General, low-level ACL matching. This is expected to
bool
dns_aclelement_match(const isc_netaddr_t *reqaddr, const dns_name_t *reqsigner,
- const dns_aclelement_t *e, const dns_aclenv_t *env,
+ const dns_aclelement_t *e, dns_aclenv_t *env,
const dns_aclelement_t **matchelt);
/*%<
* Like dns_acl_match, but matches against the single ACL element 'e'
const in_port_t local_port,
const isc_nmsocket_type_t transport,
const bool encrypted, const dns_name_t *reqsigner,
- const dns_acl_t *acl, const dns_aclenv_t *env,
+ const dns_acl_t *acl, dns_aclenv_t *env,
int *match, const dns_aclelement_t **matchelt);
/*%<
* Like dns_acl_match, but able to match the server port and
isc_result_t
dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
- const dns_name_t *reqsigner, const dns_aclenv_t *env,
+ const dns_name_t *reqsigner, dns_aclenv_t *env,
unsigned int flags, unsigned char *a, unsigned char *aaaa);
/*
* dns_dns64_aaaafroma() determines whether to perform a DNS64 address
bool
dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
- const dns_name_t *reqsigner, const dns_aclenv_t *env,
+ const dns_name_t *reqsigner, dns_aclenv_t *env,
unsigned int flags, dns_rdataset_t *rdataset, bool *aaaaok,
size_t aaaaoklen);
/*
struct dns_sortlist_arg {
dns_aclenv_t *env;
- const dns_acl_t *acl;
+ dns_acl_t *acl;
const dns_aclelement_t *element;
};
void
dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
- dns_aclenv_t *env, const dns_acl_t *acl,
+ dns_aclenv_t *env, dns_acl_t *acl,
const dns_aclelement_t *element);
/*%<
* Define the order in which RR sets get rendered by
bool
dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
const dns_name_t *name, const isc_netaddr_t *addr,
- bool tcp, const dns_aclenv_t *env, dns_rdatatype_t type,
+ bool tcp, dns_aclenv_t *env, dns_rdatatype_t type,
const dns_name_t *target, const dst_key_t *key,
const dns_ssurule_t **rulep);
/*%<
dynbuf = next_dynbuf;
}
+ if (msg->order_arg.env != NULL) {
+ dns_aclenv_detach(&msg->order_arg.env);
+ }
+ if (msg->order_arg.acl != NULL) {
+ dns_acl_detach(&msg->order_arg.acl);
+ }
+
/*
* Set other bits to normal default values.
*/
void
dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
- dns_aclenv_t *env, const dns_acl_t *acl,
+ dns_aclenv_t *env, dns_acl_t *acl,
const dns_aclelement_t *elem) {
REQUIRE(DNS_MESSAGE_VALID(msg));
REQUIRE((order == NULL) == (env == NULL));
REQUIRE(env == NULL || (acl != NULL || elem != NULL));
msg->order = order;
- msg->order_arg.env = env;
- msg->order_arg.acl = acl;
+ if (env != NULL) {
+ dns_aclenv_attach(env, &msg->order_arg.env);
+ }
+ if (acl != NULL) {
+ dns_acl_attach(acl, &msg->order_arg.acl);
+ }
msg->order_arg.element = elem;
}
bool
dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
const dns_name_t *name, const isc_netaddr_t *addr,
- bool tcp, const dns_aclenv_t *env, dns_rdatatype_t type,
+ bool tcp, dns_aclenv_t *env, dns_rdatatype_t type,
const dns_name_t *target, const dst_key_t *key,
const dns_ssurule_t **rulep) {
dns_fixedname_t fixed;
if (!dns_name_issubdomain(name, rule->name)) {
continue;
}
+ RWLOCK(&env->rwlock, isc_rwlocktype_read);
dns_acl_match(addr, NULL, env->localhost, NULL, &match,
NULL);
+ RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
if (match == 0) {
if (signer != NULL) {
isc_log_write(dns_lctx,
ns_sortlisttype_t
ns_sortlist_setup(dns_acl_t *acl, dns_aclenv_t *env, isc_netaddr_t *clientaddr,
- const void **argp);
+ void **argp);
/*%<
* Find the sortlist statement in 'acl' (for ACL environment 'env')
* that applies to 'clientaddr', if any.
void
ns_sortlist_byaddrsetup(dns_acl_t *sortlist_acl, dns_aclenv_t *env,
isc_netaddr_t *client_addr,
- dns_addressorderfunc_t *orderp, const void **argp);
+ dns_addressorderfunc_t *orderp, void **argp);
/*%<
* Find the sortlist statement in 'acl' that applies to 'clientaddr', if any.
* If a sortlist statement applies, return in '*orderp' a pointer to a function
isc_netaddr_t netaddr;
ns_client_t *client = qctx->client;
dns_aclenv_t *env = client->manager->aclenv;
- const void *order_arg = NULL;
+ dns_acl_t *acl = NULL;
+ dns_aclelement_t *elt = NULL;
+ void *order_arg = NULL;
isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
switch (ns_sortlist_setup(client->view->sortlist, env, &netaddr,
&order_arg)) {
case NS_SORTLISTTYPE_1ELEMENT:
+ elt = order_arg;
dns_message_setsortorder(client->message,
query_sortlist_order_1element, env,
- NULL, order_arg);
+ NULL, elt);
break;
case NS_SORTLISTTYPE_2ELEMENT:
+ acl = order_arg;
dns_message_setsortorder(client->message,
query_sortlist_order_2element, env,
- order_arg, NULL);
+ acl, NULL);
+ dns_acl_detach(&acl);
break;
case NS_SORTLISTTYPE_NONE:
break;
ns_sortlisttype_t
ns_sortlist_setup(dns_acl_t *acl, dns_aclenv_t *env, isc_netaddr_t *clientaddr,
- const void **argp) {
- unsigned int i;
-
+ void **argp) {
if (acl == NULL) {
goto dont_sort;
}
- for (i = 0; i < acl->length; i++) {
+ for (size_t i = 0; i < acl->length; i++) {
/*
* 'e' refers to the current 'top level statement'
* in the sortlist (see ARM).
dns_aclelement_t *e = &acl->elements[i];
dns_aclelement_t *try_elt;
dns_aclelement_t *order_elt = NULL;
- const dns_aclelement_t *matched_elt = NULL;
+ dns_aclelement_t *matched_elt = NULL;
if (e->type == dns_aclelementtype_nestedacl) {
dns_acl_t *inner = e->nestedacl;
try_elt = e;
}
- if (dns_aclelement_match(clientaddr, NULL, try_elt, env,
- &matched_elt)) {
- if (order_elt != NULL) {
- if (order_elt->type ==
- dns_aclelementtype_nestedacl) {
- *argp = order_elt->nestedacl;
- return (NS_SORTLISTTYPE_2ELEMENT);
- } else if (order_elt->type ==
- dns_aclelementtype_localhost &&
- env->localhost != NULL)
- {
- *argp = env->localhost;
- return (NS_SORTLISTTYPE_2ELEMENT);
- } else if (order_elt->type ==
- dns_aclelementtype_localnets &&
- env->localnets != NULL)
- {
- *argp = env->localnets;
- return (NS_SORTLISTTYPE_2ELEMENT);
- } else {
- /*
- * BIND 8 allows a bare IP prefix as
- * the 2nd element of a 2-element
- * sortlist statement.
- */
- *argp = order_elt;
- return (NS_SORTLISTTYPE_1ELEMENT);
- }
- } else {
- INSIST(matched_elt != NULL);
- *argp = matched_elt;
- return (NS_SORTLISTTYPE_1ELEMENT);
+ if (!dns_aclelement_match(
+ clientaddr, NULL, try_elt, env,
+ (const dns_aclelement_t **)&matched_elt))
+ {
+ continue;
+ }
+
+ if (order_elt == NULL) {
+ INSIST(matched_elt != NULL);
+ *argp = matched_elt;
+ return (NS_SORTLISTTYPE_1ELEMENT);
+ }
+
+ if (order_elt->type == dns_aclelementtype_nestedacl) {
+ dns_acl_t *inner = NULL;
+ dns_acl_attach(order_elt->nestedacl, &inner);
+ *argp = inner;
+ return (NS_SORTLISTTYPE_2ELEMENT);
+ }
+
+ if (order_elt->type == dns_aclelementtype_localhost) {
+ dns_acl_t *inner = NULL;
+ RWLOCK(&env->rwlock, isc_rwlocktype_read);
+ if (env->localhost != NULL) {
+ dns_acl_attach(env->localhost, &inner);
+ }
+ RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
+
+ if (inner != NULL) {
+ *argp = inner;
+ return (NS_SORTLISTTYPE_2ELEMENT);
}
}
+
+ if (order_elt->type == dns_aclelementtype_localnets) {
+ dns_acl_t *inner = NULL;
+ RWLOCK(&env->rwlock, isc_rwlocktype_read);
+ if (env->localnets != NULL) {
+ dns_acl_attach(env->localnets, &inner);
+ }
+ RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
+ if (inner != NULL) {
+ *argp = inner;
+ return (NS_SORTLISTTYPE_2ELEMENT);
+ }
+ }
+
+ /*
+ * BIND 8 allows a bare IP prefix as
+ * the 2nd element of a 2-element
+ * sortlist statement.
+ */
+ *argp = order_elt;
+ return (NS_SORTLISTTYPE_1ELEMENT);
}
- /* No match; don't sort. */
dont_sort:
*argp = NULL;
return (NS_SORTLISTTYPE_NONE);
int
ns_sortlist_addrorder2(const isc_netaddr_t *addr, const void *arg) {
const dns_sortlist_arg_t *sla = (const dns_sortlist_arg_t *)arg;
- const dns_aclenv_t *env = sla->env;
+ dns_aclenv_t *env = sla->env;
const dns_acl_t *sortacl = sla->acl;
int match;
int
ns_sortlist_addrorder1(const isc_netaddr_t *addr, const void *arg) {
const dns_sortlist_arg_t *sla = (const dns_sortlist_arg_t *)arg;
- const dns_aclenv_t *env = sla->env;
+ dns_aclenv_t *env = sla->env;
const dns_aclelement_t *element = sla->element;
if (dns_aclelement_match(addr, NULL, element, env, NULL)) {
void
ns_sortlist_byaddrsetup(dns_acl_t *sortlist_acl, dns_aclenv_t *env,
isc_netaddr_t *client_addr,
- dns_addressorderfunc_t *orderp, const void **argp) {
+ dns_addressorderfunc_t *orderp, void **argp) {
ns_sortlisttype_t sortlisttype;
sortlisttype = ns_sortlist_setup(sortlist_acl, env, client_addr, argp);