2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 01:59:26 +00:00

Add a quota for SIG(0) signature checks

In order to protect from a malicious DNS client that sends many
queries with a SIG(0)-signed message, add a quota of simultaneously
running SIG(0) checks.

This protection can only help when named is using more than one worker
threads. For example, if named is running with the '-n 4' option, and
'sig0checks-quota 2;' is used, then named will make sure to not use
more than 2 workers for the SIG(0) signature checks in parallel, thus
leaving the other workers to serve the remaining clients which do not
use SIG(0)-signed messages.

That limitation is going to change when SIG(0) signature checks are
offloaded to "slow" threads in a future commit.

The 'sig0checks-quota-exempt' ACL option can be used to exempt certain
clients from the quota requirements using their IP or network addresses.

The 'sig0checks-quota-maxwait-ms' option is used to define a maximum
amount of time for named to wait for a quota to appear. If during that
time no new quota becomes available, named will answer to the client
with DNS_R_REFUSED.
This commit is contained in:
Aram Sargsyan 2024-03-25 11:07:47 +00:00 committed by Nicki Křížek
parent 24e8cc7b38
commit c7f79a0353
No known key found for this signature in database
GPG Key ID: 01623B9B652A20A7
13 changed files with 339 additions and 83 deletions

View File

@ -2117,12 +2117,13 @@ cleanup:
static isc_result_t
matchview(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr,
dns_message_t *message, dns_aclenv_t *env, isc_result_t *sigresultp,
dns_view_t **viewp) {
dns_message_t *message, dns_aclenv_t *env, ns_server_t *lsctx,
isc_result_t *sigresultp, dns_view_t **viewp) {
UNUSED(srcaddr);
UNUSED(destaddr);
UNUSED(message);
UNUSED(env);
UNUSED(lsctx);
UNUSED(sigresultp);
*viewp = view;

View File

@ -109,6 +109,8 @@ options {\n\
# session-keyfile \"" NAMED_LOCALSTATEDIR "/run/named/session.key\";\n\
session-keyname local-ddns;\n\
startup-notify-rate 20;\n\
sig0checks-quota 1;\n\
sig0checks-quota-maxwait-ms 1500;\n\
statistics-file \"named.stats\";\n\
tcp-advertised-timeout 300;\n\
tcp-clients 150;\n\

View File

@ -8412,6 +8412,8 @@ load_configuration(const char *filename, named_server_t *server,
configure_server_quota(maps, "recursive-clients",
&server->sctx->recursionquota);
configure_server_quota(maps, "update-quota", &server->sctx->updquota);
configure_server_quota(maps, "sig0checks-quota",
&server->sctx->sig0checksquota);
max = isc_quota_getmax(&server->sctx->recursionquota);
if (max > 1000) {
@ -8430,9 +8432,23 @@ load_configuration(const char *filename, named_server_t *server,
} else {
softquota = (max * 90) / 100;
}
isc_quota_soft(&server->sctx->recursionquota, softquota);
obj = NULL;
result = named_config_get(maps, "sig0checks-quota-exempt", &obj);
if (result == ISC_R_SUCCESS) {
result = cfg_acl_fromconfig(
obj, config, named_g_lctx, named_g_aclconfctx,
named_g_mctx, 0, &server->sctx->sig0checksquota_exempt);
INSIST(result == ISC_R_SUCCESS);
}
obj = NULL;
result = named_config_get(maps, "sig0checks-quota-maxwait-ms", &obj);
if (result == ISC_R_SUCCESS) {
server->sctx->sig0checksquota_maxwaitms = cfg_obj_asuint32(obj);
}
/*
* Set "blackhole". Only legal at options level; there is
* no default.
@ -10048,11 +10064,12 @@ shutdown_server(void *arg) {
*/
static isc_result_t
get_matching_view(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr,
dns_message_t *message, dns_aclenv_t *env,
dns_message_t *message, dns_aclenv_t *env, ns_server_t *sctx,
isc_result_t *sigresult, dns_view_t **viewp) {
dns_view_t *view;
REQUIRE(message != NULL);
REQUIRE(sctx != NULL);
REQUIRE(sigresult != NULL);
REQUIRE(viewp != NULL && *viewp == NULL);
@ -10063,13 +10080,49 @@ get_matching_view(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr,
message->rdclass == dns_rdataclass_any)
{
const dns_name_t *tsig = NULL;
int exempt_match;
isc_result_t sig0_qresult = ISC_R_UNSET;
if (message->sig0 != NULL) {
/*
* If the message has a SIG0 signature and the
* client is not exempt from the quota, then
* acquire a quota. If quota is reached, then
* return early.
*/
if (sctx->sig0checksquota_exempt != NULL) {
isc_result_t result = dns_acl_match(
srcaddr, NULL,
sctx->sig0checksquota_exempt,
env, &exempt_match, NULL);
if (result == ISC_R_SUCCESS &&
exempt_match > 0)
{
sig0_qresult = ISC_R_EXISTS;
}
}
if (sig0_qresult == ISC_R_UNSET) {
sig0_qresult = isc_quota_acquire(
&sctx->sig0checksquota);
}
if (sig0_qresult == ISC_R_SOFTQUOTA) {
isc_quota_release(
&sctx->sig0checksquota);
}
if (sig0_qresult != ISC_R_SUCCESS &&
sig0_qresult != ISC_R_EXISTS)
{
return (ISC_R_QUOTA);
}
}
/* Check the signature, then release the quota */
*sigresult = dns_message_rechecksig(message, view);
if (sig0_qresult == ISC_R_SUCCESS) {
isc_quota_release(&sctx->sig0checksquota);
}
if (*sigresult == ISC_R_SUCCESS) {
dns_tsigkey_t *tsigkey;
tsigkey = message->tsigkey;
tsig = dns_tsigkey_identity(tsigkey);
tsig = dns_tsigkey_identity(message->tsigkey);
}
if (dns_acl_allowed(srcaddr, tsig, view->matchclients,

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
options {
sig0checks-quota-exempt { unknownacl; };
};

View File

@ -0,0 +1,20 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
acl goodacl {
192.168.0.1;
};
options {
sig0checks-quota-exempt { 10.0.0.0/8; 2001:db8::100; goodacl; };
};

View File

@ -277,6 +277,9 @@ options {
sig-signing-signatures <integer>;
sig-signing-type <integer>;
sig-validity-interval <integer> [ <integer> ]; // obsolete
sig0checks-quota <integer>;
sig0checks-quota-exempt { <address_match_element>; ... };
sig0checks-quota-maxwait-ms <integer>;
sortlist { <address_match_element>; ... }; // deprecated
stale-answer-client-timeout ( disabled | off | <integer> );
stale-answer-enable <boolean>;

View File

@ -2073,6 +2073,21 @@ check_options(const cfg_obj_t *options, const cfg_obj_t *config,
cfg_aclconfctx_create(mctx, &actx);
obj = NULL;
(void)cfg_map_get(options, "sig0checks-quota-exempt", &obj);
if (obj != NULL) {
dns_acl_t *acl = NULL;
tresult = cfg_acl_fromconfig(obj, config, logctx, actx, mctx, 0,
&acl);
if (acl != NULL) {
dns_acl_detach(&acl);
}
if (result == ISC_R_SUCCESS) {
result = tresult;
}
}
obj = NULL;
(void)cfg_map_get(options, "listen-on", &obj);
if (obj != NULL) {

View File

@ -1361,6 +1361,9 @@ static cfg_clausedef_t options_clauses[] = {
{ "session-keyalg", &cfg_type_astring, 0 },
{ "session-keyfile", &cfg_type_qstringornone, 0 },
{ "session-keyname", &cfg_type_astring, 0 },
{ "sig0checks-quota", &cfg_type_uint32, 0 },
{ "sig0checks-quota-maxwait-ms", &cfg_type_uint32, 0 },
{ "sig0checks-quota-exempt", &cfg_type_bracketed_aml, 0 },
{ "sit-secret", NULL, CFG_CLAUSEFLAG_ANCIENT },
{ "stacksize", &cfg_type_size, CFG_CLAUSEFLAG_ANCIENT },
{ "startup-notify-rate", &cfg_type_uint32, 0 },

View File

@ -118,11 +118,27 @@
atomic_uint_fast64_t ns_client_requests = 0;
static atomic_uint_fast32_t last_sigchecks_quota_log = 0;
static bool
can_log_sigchecks_quota(void) {
isc_stdtime_t last;
isc_stdtime_t now = isc_stdtime_now();
last = atomic_exchange_relaxed(&last_sigchecks_quota_log, now);
if (now != last) {
return (true);
}
return (false);
}
static void
clientmgr_destroy_cb(void *arg);
static void
ns_client_dumpmessage(ns_client_t *client, const char *reason);
static void
ns_client_request_continue(void *arg);
static void
compute_cookie(ns_client_t *client, uint32_t when, const unsigned char *secret,
isc_buffer_t *buf);
@ -1739,6 +1755,53 @@ ns__client_put_cb(void *client0) {
ns_clientmgr_detach(&manager);
}
static isc_result_t
ns_client_setup_view(ns_client_t *client, isc_netaddr_t *netaddr) {
isc_result_t result;
result = client->manager->sctx->matchingview(
netaddr, &client->destaddr, client->message,
client->manager->aclenv, client->manager->sctx,
&client->sigresult, &client->view);
if (result != ISC_R_SUCCESS) {
if (result == ISC_R_QUOTA) {
if (can_log_sigchecks_quota()) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_CLIENT, ISC_LOG_INFO,
"SIG(0) checks quota reached");
ns_client_dumpmessage(
client, "SIG(0) checks quota reached");
}
} else {
char classname[DNS_RDATACLASS_FORMATSIZE];
isc_buffer_t b;
isc_region_t *r;
/*
* Do a dummy TSIG verification attempt so that the
* response will have a TSIG if the query did, as
* required by RFC2845.
*/
dns_message_resetsig(client->message);
r = dns_message_getrawmessage(client->message);
isc_buffer_init(&b, r->base, r->length);
isc_buffer_add(&b, r->length);
(void)dns_tsig_verify(&b, client->message, NULL, NULL);
dns_rdataclass_format(client->message->rdclass,
classname, sizeof(classname));
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
"no matching view in class '%s'",
classname);
ns_client_dumpmessage(client,
"no matching view in class");
}
}
return (result);
}
/*
* Handle an incoming request event from the socket (UDP case)
* or tcpmsg (TCP case).
@ -1748,12 +1811,7 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *region, void *arg) {
ns_client_t *client = NULL;
isc_result_t result;
isc_result_t sigresult = ISC_R_SUCCESS;
isc_buffer_t *buffer = NULL;
isc_buffer_t tbuffer;
dns_rdataset_t *opt = NULL;
const dns_name_t *signame = NULL;
bool ra; /* Recursion available. */
isc_netaddr_t netaddr;
int match;
dns_messageid_t id;
@ -1761,28 +1819,6 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
bool notimp;
size_t reqsize;
dns_aclenv_t *env = NULL;
#ifdef HAVE_DNSTAP
dns_transport_type_t transport_type;
dns_dtmsgtype_t dtmsgtype;
#endif /* ifdef HAVE_DNSTAP */
static const char *ra_reasons[] = {
"ACLs not processed yet",
"no resolver in view",
"recursion not enabled for view",
"allow-recursion did not match",
"allow-query-cache did not match",
"allow-recursion-on did not match",
"allow-query-cache-on did not match",
};
enum refusal_reasons {
INVALID,
NO_RESOLVER,
RECURSION_DISABLED,
ALLOW_RECURSION,
ALLOW_QUERY_CACHE,
ALLOW_RECURSION_ON,
ALLOW_QUERY_CACHE_ON
} ra_refusal_reason = INVALID;
if (eresult != ISC_R_SUCCESS) {
return;
@ -1830,14 +1866,14 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
(void)atomic_fetch_add_relaxed(&ns_client_requests, 1);
isc_buffer_init(&tbuffer, region->base, region->length);
isc_buffer_add(&tbuffer, region->length);
buffer = &tbuffer;
isc_buffer_init(&client->tbuffer, region->base, region->length);
isc_buffer_add(&client->tbuffer, region->length);
client->buffer = &client->tbuffer;
client->peeraddr = isc_nmhandle_peeraddr(handle);
client->peeraddr_valid = true;
reqsize = isc_buffer_usedlength(buffer);
reqsize = isc_buffer_usedlength(client->buffer);
client->state = NS_CLIENTSTATE_WORKING;
@ -1876,7 +1912,7 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
ISC_LOG_DEBUG(3), "%s request",
TCP_CLIENT(client) ? "TCP" : "UDP");
result = dns_message_peekheader(buffer, &id, &flags);
result = dns_message_peekheader(client->buffer, &id, &flags);
if (result != ISC_R_SUCCESS) {
/*
* There isn't enough header to determine whether
@ -1951,7 +1987,7 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
/*
* It's a request. Parse it.
*/
result = dns_message_parse(client->message, buffer, 0);
result = dns_message_parse(client->message, client->buffer, 0);
if (result != ISC_R_SUCCESS) {
/*
* Parsing the request failed. Send a response
@ -2080,38 +2116,119 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
client->destsockaddr = isc_nmhandle_localaddr(handle);
isc_netaddr_fromsockaddr(&client->destaddr, &client->destsockaddr);
result = client->manager->sctx->matchingview(
&netaddr, &client->destaddr, client->message, env, &sigresult,
&client->view);
if (result != ISC_R_SUCCESS) {
char classname[DNS_RDATACLASS_FORMATSIZE];
/*
* Do a dummy TSIG verification attempt so that the
* response will have a TSIG if the query did, as
* required by RFC2845.
*/
isc_buffer_t b;
isc_region_t *r;
dns_message_resetsig(client->message);
r = dns_message_getrawmessage(client->message);
isc_buffer_init(&b, r->base, r->length);
isc_buffer_add(&b, r->length);
(void)dns_tsig_verify(&b, client->message, NULL, NULL);
dns_rdataclass_format(client->message->rdclass, classname,
sizeof(classname));
result = ns_client_setup_view(client, &netaddr);
if (result == ISC_R_QUOTA) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
"no matching view in class '%s'", classname);
ns_client_dumpmessage(client, "no matching view in class");
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
"client is starting to wait for quota");
client->async = true;
isc_nmhandle_ref(client->handle);
isc_async_run(client->manager->loop, ns_client_request_continue,
client);
return;
} else if (result != ISC_R_SUCCESS) {
ns_client_extendederror(client, DNS_EDE_PROHIBITED, NULL);
ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
return;
}
ns_client_request_continue(client);
}
static void
ns_client_request_continue(void *arg) {
ns_client_t *client = arg;
isc_netaddr_t netaddr;
const dns_name_t *signame = NULL;
bool ra; /* Recursion available. */
isc_result_t result;
static const char *ra_reasons[] = {
"ACLs not processed yet",
"no resolver in view",
"recursion not enabled for view",
"allow-recursion did not match",
"allow-query-cache did not match",
"allow-recursion-on did not match",
"allow-query-cache-on did not match",
};
enum refusal_reasons {
INVALID,
NO_RESOLVER,
RECURSION_DISABLED,
ALLOW_RECURSION,
ALLOW_QUERY_CACHE,
ALLOW_RECURSION_ON,
ALLOW_QUERY_CACHE_ON
} ra_refusal_reason = INVALID;
#ifdef HAVE_DNSTAP
dns_transport_type_t transport_type;
dns_dtmsgtype_t dtmsgtype;
#endif /* ifdef HAVE_DNSTAP */
/*
* This function could be running asynchronously if a quota was reached
* before, and named was waiting for available quota. In that case we
* need to update the current 'now', and check that named doesn't wait
* for too long.
*/
if (client->async) {
uint64_t wait_us;
uint64_t maxwait_us;
client->tnow = isc_time_now();
client->now = isc_time_seconds(&client->tnow);
wait_us = isc_time_microdiff(&client->tnow,
&client->requesttime);
maxwait_us = US_PER_MS *
client->manager->sctx->sig0checksquota_maxwaitms;
if (wait_us > maxwait_us) {
isc_buffer_t b;
isc_region_t *r;
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
"client reached max wait time for quota");
/*
* Do a dummy TSIG verification attempt so that the
* response will have a TSIG if the query did, as
* required by RFC2845.
*/
dns_message_resetsig(client->message);
r = dns_message_getrawmessage(client->message);
isc_buffer_init(&b, r->base, r->length);
isc_buffer_add(&b, r->length);
(void)dns_tsig_verify(&b, client->message, NULL, NULL);
ns_client_extendederror(client, DNS_EDE_PROHIBITED,
NULL);
ns_client_error(client, DNS_R_REFUSED);
goto cleanup;
}
}
isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
if (client->view == NULL) {
result = ns_client_setup_view(client, &netaddr);
if (result == ISC_R_QUOTA) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
"client continues waiting for quota");
client->async = true;
isc_nmhandle_ref(client->handle);
isc_async_run(client->manager->loop,
ns_client_request_continue, client);
goto cleanup;
} else if (result != ISC_R_SUCCESS) {
ns_client_extendederror(client, DNS_EDE_PROHIBITED,
NULL);
ns_client_error(client, DNS_R_REFUSED);
goto cleanup;
}
}
if (isc_nm_is_proxy_handle(client->handle)) {
char fmtbuf[ISC_SOCKADDR_FORMATSIZE] = { 0 };
isc_netaddr_t real_local_addr, real_peer_addr;
@ -2140,8 +2257,8 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
"ACL",
fmtbuf);
}
isc_nm_bad_request(handle);
return;
isc_nm_bad_request(client->handle);
goto cleanup;
}
/* allow by default */
@ -2161,8 +2278,8 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
"'allow-proxy-on' ACL",
fmtbuf);
}
isc_nm_bad_request(handle);
return;
isc_nm_bad_request(client->handle);
goto cleanup;
}
}
@ -2255,8 +2372,8 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
client->message->opcode == dns_opcode_update))
{
ns_client_error(client, sigresult);
return;
ns_client_error(client, client->sigresult);
goto cleanup;
}
}
@ -2340,25 +2457,25 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
dns_dt_send(client->view, dtmsgtype, &client->peeraddr,
&client->destsockaddr, transport_type, NULL,
&client->requesttime, NULL, buffer);
&client->requesttime, NULL, client->buffer);
#endif /* HAVE_DNSTAP */
ns_query_start(client, handle);
ns_query_start(client, client->handle);
break;
case dns_opcode_update:
CTRACE("update");
#ifdef HAVE_DNSTAP
dns_dt_send(client->view, DNS_DTTYPE_UQ, &client->peeraddr,
&client->destsockaddr, transport_type, NULL,
&client->requesttime, NULL, buffer);
&client->requesttime, NULL, client->buffer);
#endif /* HAVE_DNSTAP */
ns_client_settimeout(client, 60);
ns_update_start(client, handle, sigresult);
ns_update_start(client, client->handle, client->sigresult);
break;
case dns_opcode_notify:
CTRACE("notify");
ns_client_settimeout(client, 60);
ns_notify_start(client, handle);
ns_notify_start(client, client->handle);
break;
case dns_opcode_iquery:
CTRACE("iquery");
@ -2368,6 +2485,15 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
CTRACE("unknown opcode");
ns_client_error(client, DNS_R_NOTIMP);
}
cleanup:
if (client->async) {
/*
* Do not detach, only 'unref' the corresponding 'ref' when
* async was used, because the client can still be reused.
*/
isc_nmhandle_unref(client->handle);
}
}
isc_result_t

View File

@ -167,6 +167,7 @@ struct ns_client {
ns_clientmgr_t *manager;
ns_clientstate_t state;
bool nodetach;
bool async;
unsigned int attributes;
dns_view_t *view;
dns_dispatch_t *dispatch;
@ -192,6 +193,9 @@ struct ns_client {
isc_time_t tnow;
dns_name_t signername; /*%< [T]SIG key name */
dns_name_t *signer; /*%< NULL if not valid sig */
isc_result_t sigresult;
isc_buffer_t *buffer;
isc_buffer_t tbuffer;
isc_sockaddr_t peeraddr;
bool peeraddr_valid;

View File

@ -64,9 +64,12 @@ typedef void (*ns_fuzzcb_t)(void);
/*%
* Type for callback function to get the view that can answer a query.
*/
typedef isc_result_t (*ns_matchview_t)(
isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr, dns_message_t *message,
dns_aclenv_t *env, isc_result_t *sigresultp, dns_view_t **viewp);
typedef isc_result_t (*ns_matchview_t)(isc_netaddr_t *srcaddr,
isc_netaddr_t *destaddr,
dns_message_t *message,
dns_aclenv_t *env, ns_server_t *sctx,
isc_result_t *sigresultp,
dns_view_t **viewp);
/*%
* Server context.
@ -88,6 +91,9 @@ struct ns_server {
isc_quota_t tcpquota;
isc_quota_t xfroutquota;
isc_quota_t updquota;
isc_quota_t sig0checksquota;
uint32_t sig0checksquota_maxwaitms;
dns_acl_t *sig0checksquota_exempt;
ISC_LIST(isc_quota_t) http_quotas;
isc_mutex_t http_quotas_lock;

View File

@ -66,6 +66,7 @@ ns_server_create(isc_mem_t *mctx, ns_matchview_t matchingview,
isc_quota_init(&sctx->tcpquota, 10);
isc_quota_init(&sctx->recursionquota, 100);
isc_quota_init(&sctx->updquota, 100);
isc_quota_init(&sctx->sig0checksquota, 1);
ISC_LIST_INIT(sctx->http_quotas);
isc_mutex_init(&sctx->http_quotas_lock);
@ -134,6 +135,11 @@ ns_server_detach(ns_server_t **sctxp) {
isc_mem_put(sctx->mctx, altsecret, sizeof(*altsecret));
}
if (sctx->sig0checksquota_exempt != NULL) {
dns_acl_detach(&sctx->sig0checksquota_exempt);
}
isc_quota_destroy(&sctx->sig0checksquota);
isc_quota_destroy(&sctx->updquota);
isc_quota_destroy(&sctx->recursionquota);
isc_quota_destroy(&sctx->tcpquota);

View File

@ -57,12 +57,13 @@ ns_server_t *sctx = NULL;
static isc_result_t
matchview(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr,
dns_message_t *message, dns_aclenv_t *env, isc_result_t *sigresultp,
dns_view_t **viewp) {
dns_message_t *message, dns_aclenv_t *env, ns_server_t *lsctx,
isc_result_t *sigresultp, dns_view_t **viewp) {
UNUSED(srcaddr);
UNUSED(destaddr);
UNUSED(message);
UNUSED(env);
UNUSED(lsctx);
UNUSED(sigresultp);
UNUSED(viewp);