mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-12 22:19:59 -04:00
[9.20] new: usr: Add a new option to configure the maximum number of outgoing queries per client request
The configuration option 'max-query-count' sets how many outgoing queries per client request is allowed. The existing 'max-recursion-queries' is the number of permissible queries for a single name and is reset on every CNAME redirection. This new option is a global limit on the client request. The default is 200. This allows us to send a bit more queries while looking up a single name. The default for 'max-recursion-queries' is changed from 32 to 50. Closes #4980 Closes #4921 Backport of MR !9737 Merge branch 'backport-4980-global-limit-outgoing-queries-9.20' into 'bind-9.20' See merge request isc-projects/bind9!9832
This commit is contained in:
commit
844a531053
38 changed files with 763 additions and 69 deletions
|
|
@ -88,7 +88,8 @@
|
|||
|
||||
#define MAXNAME (DNS_NAME_MAXTEXT + 1)
|
||||
|
||||
#define MAX_QUERIES 32
|
||||
#define MAX_QUERIES 50
|
||||
#define MAX_TOTAL 200
|
||||
#define MAX_RESTARTS 11
|
||||
|
||||
/* Variables used internally by delv. */
|
||||
|
|
@ -134,6 +135,7 @@ static bool showcomments = true, showdnssec = true, showtrust = true,
|
|||
yaml = false, fulltrace = false;
|
||||
|
||||
static uint32_t maxqueries = MAX_QUERIES;
|
||||
static uint32_t maxtotal = MAX_TOTAL;
|
||||
static uint32_t restarts = MAX_RESTARTS;
|
||||
|
||||
static bool resolve_trace = false, validator_trace = false,
|
||||
|
|
@ -1197,22 +1199,46 @@ plus_option(char *option) {
|
|||
break;
|
||||
case 'm':
|
||||
switch (cmd[1]) {
|
||||
case 'a': /* maxqueries */
|
||||
FULLCHECK("maxqueries");
|
||||
if (value == NULL) {
|
||||
goto need_value;
|
||||
}
|
||||
if (!state) {
|
||||
case 'a':
|
||||
switch (cmd[3]) {
|
||||
case 'q': /* maxqueries */
|
||||
FULLCHECK("maxqueries");
|
||||
if (value == NULL) {
|
||||
goto need_value;
|
||||
}
|
||||
if (!state) {
|
||||
goto invalid_option;
|
||||
}
|
||||
result = parse_uint(&maxqueries, value,
|
||||
UINT_MAX, "maxqueries");
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("Couldn't parse maxqueries");
|
||||
}
|
||||
if (maxqueries == 0) {
|
||||
fatal("maxqueries must be nonzero");
|
||||
}
|
||||
break;
|
||||
case 't': /* maxtotalqueries */
|
||||
FULLCHECK("maxtotalqueries");
|
||||
if (value == NULL) {
|
||||
goto need_value;
|
||||
}
|
||||
if (!state) {
|
||||
goto invalid_option;
|
||||
}
|
||||
result = parse_uint(&maxtotal, value, UINT_MAX,
|
||||
"maxtotalqueries");
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("Couldn't parse maxtotalqueries");
|
||||
}
|
||||
if (maxtotal == 0) {
|
||||
fatal("maxtotalqueries must be "
|
||||
"nonzero");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
result = parse_uint(&maxqueries, value, UINT_MAX,
|
||||
"maxqueries");
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("Couldn't parse maxqueries");
|
||||
}
|
||||
if (maxqueries == 0) {
|
||||
fatal("maxqueries must be nonzero");
|
||||
}
|
||||
break;
|
||||
case 't': /* mtrace */
|
||||
FULLCHECK("mtrace");
|
||||
|
|
@ -1935,6 +1961,7 @@ run_resolve(void *arg) {
|
|||
CHECK(dns_client_create(mctx, loopmgr, netmgr, 0, tlsctx_client_cache,
|
||||
&client, srcaddr4, srcaddr6));
|
||||
dns_client_setmaxrestarts(client, restarts);
|
||||
dns_client_setmaxqueries(client, maxtotal);
|
||||
|
||||
/* Set the nameserver */
|
||||
if (server != NULL) {
|
||||
|
|
@ -2200,6 +2227,7 @@ run_server(void *arg) {
|
|||
dns_cache_detach(&cache);
|
||||
dns_view_setdstport(view, destport);
|
||||
dns_view_setmaxrestarts(view, restarts);
|
||||
dns_view_setmaxqueries(view, maxtotal);
|
||||
|
||||
CHECK(dns_rootns_create(mctx, dns_rdataclass_in, hintfile, &roothints));
|
||||
dns_view_sethints(view, roothints);
|
||||
|
|
|
|||
|
|
@ -347,7 +347,12 @@ assign values to options like the timeout interval. They have the form
|
|||
.. option:: +maxqueries
|
||||
|
||||
This option specifies the maximum number of queries to send to resolve
|
||||
a name before giving up. The default is 32.
|
||||
a name before giving up. The default is 50.
|
||||
|
||||
.. option:: +maxtotalqueries
|
||||
|
||||
This option specifies the maximum number of queries to send to resolve
|
||||
a client request before giving up. The default is 200.
|
||||
|
||||
.. option:: +trust, +notrust
|
||||
|
||||
|
|
|
|||
|
|
@ -172,7 +172,8 @@ options {\n\
|
|||
max-clients-per-query 100;\n\
|
||||
max-ncache-ttl 10800; /* 3 hours */\n\
|
||||
max-recursion-depth 7;\n\
|
||||
max-recursion-queries 32;\n\
|
||||
max-recursion-queries 50;\n\
|
||||
max-query-count 200;\n\
|
||||
max-query-restarts 11;\n\
|
||||
max-stale-ttl 86400; /* 1 day */\n\
|
||||
message-compression yes;\n\
|
||||
|
|
|
|||
|
|
@ -5600,6 +5600,11 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_view_setmaxrestarts(view, cfg_obj_asuint32(obj));
|
||||
|
||||
obj = NULL;
|
||||
result = named_config_get(maps, "max-query-count", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_view_setmaxqueries(view, cfg_obj_asuint32(obj));
|
||||
|
||||
obj = NULL;
|
||||
result = named_config_get(maps, "max-validations-per-fetch", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
|
|
@ -7361,7 +7366,7 @@ tat_send(void *arg) {
|
|||
if (result == ISC_R_SUCCESS) {
|
||||
result = dns_resolver_createfetch(
|
||||
tat->view->resolver, tatname, dns_rdatatype_null,
|
||||
domain, &nameservers, NULL, NULL, 0, 0, 0, NULL,
|
||||
domain, &nameservers, NULL, NULL, 0, 0, 0, NULL, NULL,
|
||||
tat->loop, tat_done, tat, &tat->rdataset,
|
||||
&tat->sigrdataset, &tat->fetch);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ TESTS = \
|
|||
autosign \
|
||||
builtin \
|
||||
cacheclean \
|
||||
camp \
|
||||
case \
|
||||
catz \
|
||||
cds \
|
||||
|
|
|
|||
31
bin/tests/system/camp/ns1/named.conf.in
Normal file
31
bin/tests/system/camp/ns1/named.conf.in
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// NS1
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.1;
|
||||
notify-source 10.53.0.1;
|
||||
transfer-source 10.53.0.1;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.1; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
notify yes;
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type primary;
|
||||
file "root.db";
|
||||
};
|
||||
51
bin/tests/system/camp/ns1/root.db
Normal file
51
bin/tests/system/camp/ns1/root.db
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
; 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.
|
||||
|
||||
$TTL 300
|
||||
. IN SOA gson.nominum.com. a.root.servers.nil. (
|
||||
2000042100 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
. NS a.root-servers.nil.
|
||||
a.root-servers.nil. A 10.53.0.1
|
||||
|
||||
tld0. NS ns.tld0.
|
||||
ns.tld0. A 10.53.0.2
|
||||
|
||||
tld1. NS ns.tld1.
|
||||
ns.tld1. A 10.53.0.2
|
||||
|
||||
tld2. NS ns.tld2.
|
||||
ns.tld2. A 10.53.0.2
|
||||
|
||||
tld3. NS ns.tld3.
|
||||
ns.tld3. A 10.53.0.2
|
||||
|
||||
tld4. NS ns.tld4.
|
||||
ns.tld4. A 10.53.0.2
|
||||
|
||||
tld5. NS ns.tld5.
|
||||
ns.tld5. A 10.53.0.2
|
||||
|
||||
tld6. NS ns.tld6.
|
||||
ns.tld6. A 10.53.0.2
|
||||
|
||||
tld7. NS ns.tld7.
|
||||
ns.tld7. A 10.53.0.2
|
||||
|
||||
tld8. NS ns.tld8.
|
||||
ns.tld8. A 10.53.0.2
|
||||
|
||||
tld9. NS ns.tld9.
|
||||
ns.tld9. A 10.53.0.2
|
||||
31
bin/tests/system/camp/ns2/named.conf.in
Normal file
31
bin/tests/system/camp/ns2/named.conf.in
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// NS2
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.2;
|
||||
notify-source 10.53.0.2;
|
||||
transfer-source 10.53.0.2;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.2; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
notify yes;
|
||||
};
|
||||
|
||||
zone "tld0" {
|
||||
type primary;
|
||||
file "tld0.db";
|
||||
};
|
||||
57
bin/tests/system/camp/ns2/setup.sh
Normal file
57
bin/tests/system/camp/ns2/setup.sh
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
# 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.
|
||||
|
||||
# shellcheck source=conf.sh
|
||||
. ../../conf.sh
|
||||
|
||||
echo_i "ns2/setup.sh"
|
||||
|
||||
cp template.db.in tld0.db
|
||||
echo "final.tld0. IN NS ns.final.tld0." >>tld0.db
|
||||
echo "ns.final.tld0. IN A 10.53.0.3" >>tld0.db
|
||||
|
||||
DEPTH=5
|
||||
|
||||
tld=1
|
||||
while [ $tld -le $DEPTH ]; do
|
||||
|
||||
cat >>"named.conf" <<EOF
|
||||
zone "tld${tld}" {
|
||||
type primary;
|
||||
file "tld${tld}.db";
|
||||
};
|
||||
EOF
|
||||
|
||||
cp template.db.in tld${tld}.db
|
||||
|
||||
label=0
|
||||
while [ $label -le $DEPTH ]; do
|
||||
echo "label${label}.tld${tld}. IN NS ns.label${label}.tld${tld}." >>tld${tld}.db
|
||||
echo "ns.label${label}.tld${tld}. IN A 10.53.0.3" >>tld${tld}.db
|
||||
echo "" >>tld${tld}.db
|
||||
|
||||
label=$((label + 1))
|
||||
done
|
||||
|
||||
tld=$((tld + 1))
|
||||
done
|
||||
|
||||
goto=1
|
||||
tld=1
|
||||
while [ $goto -le $DEPTH ]; do
|
||||
echo "goto${goto}.tld${tld}. IN NS ns.goto${goto}.tld${tld}." >>tld${tld}.db
|
||||
echo "ns.goto${goto}.tld${tld}. IN A 10.53.0.3" >>tld${tld}.db
|
||||
echo "" >>tld${tld}.db
|
||||
|
||||
goto=$((goto + 1))
|
||||
done
|
||||
26
bin/tests/system/camp/ns2/template.db.in
Normal file
26
bin/tests/system/camp/ns2/template.db.in
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
; 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.
|
||||
|
||||
$TTL 300
|
||||
@ IN SOA mname1. . (
|
||||
1 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
|
||||
NS ns2
|
||||
ns2 A 10.53.0.2
|
||||
NS ns
|
||||
ns A 10.53.0.2
|
||||
|
||||
; camp attack
|
||||
42
bin/tests/system/camp/ns3/named.conf.in
Normal file
42
bin/tests/system/camp/ns3/named.conf.in
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// NS3
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.3;
|
||||
notify-source 10.53.0.3;
|
||||
transfer-source 10.53.0.3;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.3; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
dnssec-validation no;
|
||||
|
||||
max-query-count 150;
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
zone "final.tld0" {
|
||||
type primary;
|
||||
file "final.tld0.db";
|
||||
};
|
||||
79
bin/tests/system/camp/ns3/setup.sh
Normal file
79
bin/tests/system/camp/ns3/setup.sh
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
# 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.
|
||||
|
||||
# shellcheck source=conf.sh
|
||||
. ../../conf.sh
|
||||
|
||||
echo_i "ns3/setup.sh"
|
||||
|
||||
cp template.db.in final.tld0.db
|
||||
echo "q.final.tld0. IN A 1.2.3.4" >>final.tld0.db
|
||||
|
||||
DEPTH=5
|
||||
|
||||
tld=1
|
||||
while [ $tld -le $DEPTH ]; do
|
||||
nexttld=$((tld + 1))
|
||||
|
||||
label=1
|
||||
while [ $label -le $DEPTH ]; do
|
||||
nextlabel=$((label + 1))
|
||||
|
||||
cat >>"named.conf" <<EOF
|
||||
zone "label${label}.tld${tld}" {
|
||||
type primary;
|
||||
file "label${label}.tld${tld}.db";
|
||||
};
|
||||
EOF
|
||||
|
||||
cp template.db.in label${label}.tld${tld}.db
|
||||
|
||||
if [ $label -eq $DEPTH ] && [ $tld -eq $DEPTH ]; then
|
||||
echo "q.label${label}.tld${tld}. IN CNAME q.goto1.tld1." >>label${label}.tld${tld}.db
|
||||
elif [ $tld -eq $DEPTH ]; then
|
||||
nextlabel=$((label + 1))
|
||||
echo "q.label${label}.tld${tld}. IN CNAME q.label${nextlabel}.tld1." >>label${label}.tld${tld}.db
|
||||
else
|
||||
echo "q.label${label}.tld${tld}. IN CNAME q.label${label}.tld${nexttld}." >>label${label}.tld${tld}.db
|
||||
fi
|
||||
|
||||
label=$nextlabel
|
||||
done
|
||||
|
||||
echo "" >>label${label}.tld${tld}.db
|
||||
tld=$nexttld
|
||||
done
|
||||
|
||||
goto=1
|
||||
tld=1
|
||||
while [ $goto -le $DEPTH ]; do
|
||||
nextgoto=$((goto + 1))
|
||||
|
||||
cat >>"named.conf" <<EOF
|
||||
zone "goto${goto}.tld${tld}" {
|
||||
type primary;
|
||||
file "goto${goto}.tld${tld}.db";
|
||||
};
|
||||
EOF
|
||||
|
||||
cp template.db.in goto${goto}.tld${tld}.db
|
||||
|
||||
if [ $goto -eq $DEPTH ]; then
|
||||
echo "q.goto${goto}.tld${tld}. IN CNAME q.final.tld0." >>goto${goto}.tld${tld}.db
|
||||
else
|
||||
echo "q.goto${goto}.tld${tld}. IN CNAME q.goto${nextgoto}.tld${tld}." >>goto${goto}.tld${tld}.db
|
||||
fi
|
||||
|
||||
echo "" >>label${label}.tld${tld}.db
|
||||
goto=$nextgoto
|
||||
done
|
||||
26
bin/tests/system/camp/ns3/template.db.in
Normal file
26
bin/tests/system/camp/ns3/template.db.in
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
; 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.
|
||||
|
||||
$TTL 300
|
||||
@ IN SOA mname1. . (
|
||||
1 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
|
||||
NS ns
|
||||
NS ns3
|
||||
ns A 10.53.0.3
|
||||
ns3 A 10.53.0.3
|
||||
|
||||
; camp attack
|
||||
13
bin/tests/system/camp/ns9/hints.db
Normal file
13
bin/tests/system/camp/ns9/hints.db
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
; 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.
|
||||
|
||||
. 60 IN NS a.root-servers.nil.
|
||||
a.root-servers.nil. A 10.53.0.1
|
||||
41
bin/tests/system/camp/ns9/named.conf.in
Normal file
41
bin/tests/system/camp/ns9/named.conf.in
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// NS9
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.9;
|
||||
notify-source 10.53.0.9;
|
||||
transfer-source 10.53.0.9;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.9; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
dnssec-validation no;
|
||||
|
||||
max-recursion-queries 50;
|
||||
max-query-restarts 50;
|
||||
max-query-count 100;
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
zone "." { type hint; file "hints.db"; };
|
||||
32
bin/tests/system/camp/setup.sh
Normal file
32
bin/tests/system/camp/setup.sh
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
# 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.
|
||||
|
||||
# shellcheck source=conf.sh
|
||||
. ../conf.sh
|
||||
|
||||
set -e
|
||||
|
||||
copy_setports ns1/named.conf.in ns1/named.conf
|
||||
copy_setports ns2/named.conf.in ns2/named.conf
|
||||
copy_setports ns3/named.conf.in ns3/named.conf
|
||||
copy_setports ns9/named.conf.in ns9/named.conf
|
||||
|
||||
(
|
||||
cd ns3
|
||||
$SHELL setup.sh
|
||||
)
|
||||
|
||||
(
|
||||
cd ns2
|
||||
$SHELL setup.sh
|
||||
)
|
||||
36
bin/tests/system/camp/tests.sh
Executable file
36
bin/tests/system/camp/tests.sh
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
#!/bin/sh
|
||||
|
||||
# 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.
|
||||
|
||||
set -e
|
||||
|
||||
# shellcheck source=../conf.sh
|
||||
. ../conf.sh
|
||||
|
||||
dig_with_opts() {
|
||||
"${DIG}" -p "${PORT}" "${@}"
|
||||
}
|
||||
|
||||
status=0
|
||||
n=0
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking max-query-count is in effect ($n)"
|
||||
ret=0
|
||||
dig_with_opts q.label1.tld1. @10.53.0.9 a >dig.out.ns9.test${n} || ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns9.test${n} >/dev/null || ret=1
|
||||
grep "exceeded global max queries resolving" ns9/named.run >/dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
||||
25
bin/tests/system/camp/tests_sh_camp.py
Normal file
25
bin/tests/system/camp/tests_sh_camp.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# 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.
|
||||
|
||||
import pytest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"dig.out*",
|
||||
"ans*/ans.run",
|
||||
"ns*/*.jnl",
|
||||
"ns*/*tld*.db",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_camp(run_tests_sh):
|
||||
run_tests_sh()
|
||||
|
|
@ -81,6 +81,7 @@ options {
|
|||
check-names primary warn;
|
||||
check-names secondary ignore;
|
||||
max-cache-size 20000000000000;
|
||||
max-query-count 100;
|
||||
max-query-restarts 10;
|
||||
nta-lifetime 604800;
|
||||
nta-recheck 604800;
|
||||
|
|
|
|||
|
|
@ -4600,6 +4600,15 @@ Tuning
|
|||
format is more human-readable, and is thus suitable when a zone is to
|
||||
be edited by hand. The default is ``relative``.
|
||||
|
||||
.. namedconf:statement:: max-query-count
|
||||
:tags: server, query
|
||||
:short: Sets the maximum number of iterative queries while servicing a recursive query.
|
||||
|
||||
This sets the maximum number of iterative queries that may be sent
|
||||
by a resolver while looking up a single name. If more queries than this
|
||||
need to be sent before an answer is reached, then recursion is terminated
|
||||
and a SERVFAIL response is returned to the client. The default is ``200``.
|
||||
|
||||
.. namedconf:statement:: max-recursion-depth
|
||||
:tags: server
|
||||
:short: Sets the maximum number of levels of recursion permitted at any one time while servicing a recursive query.
|
||||
|
|
@ -4620,7 +4629,7 @@ Tuning
|
|||
need to be sent before an answer is reached, then recursion is terminated
|
||||
and a SERVFAIL response is returned to the client. (Note: if the answer
|
||||
is a CNAME, then the subsequent lookup for the target of the CNAME is
|
||||
counted separately.) The default is 32.
|
||||
counted separately.) The default is 50.
|
||||
|
||||
.. namedconf:statement:: max-query-restarts
|
||||
:tags: server, query
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ options {
|
|||
max-ixfr-ratio ( unlimited | <percentage> );
|
||||
max-journal-size ( default | unlimited | <sizeval> );
|
||||
max-ncache-ttl <duration>;
|
||||
max-query-count <integer>;
|
||||
max-query-restarts <integer>;
|
||||
max-records <integer>;
|
||||
max-records-per-type <integer>;
|
||||
|
|
@ -474,6 +475,7 @@ view <string> [ <class> ] {
|
|||
max-ixfr-ratio ( unlimited | <percentage> );
|
||||
max-journal-size ( default | unlimited | <sizeval> );
|
||||
max-ncache-ttl <duration>;
|
||||
max-query-count <integer>;
|
||||
max-query-restarts <integer>;
|
||||
max-records <integer>;
|
||||
max-records-per-type <integer>;
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ static isc_result_t
|
|||
dbfind_name(dns_adbname_t *, isc_stdtime_t, dns_rdatatype_t);
|
||||
static isc_result_t
|
||||
fetch_name(dns_adbname_t *, bool, unsigned int, isc_counter_t *qc,
|
||||
dns_rdatatype_t);
|
||||
isc_counter_t *gqc, dns_rdatatype_t);
|
||||
static void
|
||||
destroy(dns_adb_t *);
|
||||
static void
|
||||
|
|
@ -1926,7 +1926,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
|
|||
const dns_name_t *name, const dns_name_t *qname,
|
||||
dns_rdatatype_t qtype ISC_ATTR_UNUSED, unsigned int options,
|
||||
isc_stdtime_t now, dns_name_t *target, in_port_t port,
|
||||
unsigned int depth, isc_counter_t *qc,
|
||||
unsigned int depth, isc_counter_t *qc, isc_counter_t *gqc,
|
||||
dns_adbfind_t **findp) {
|
||||
isc_result_t result = ISC_R_UNEXPECTED;
|
||||
dns_adbfind_t *find = NULL;
|
||||
|
|
@ -2136,7 +2136,7 @@ fetch:
|
|||
* Start V4.
|
||||
*/
|
||||
if (WANT_INET(wanted_fetches) &&
|
||||
fetch_name(adbname, start_at_zone, depth, qc,
|
||||
fetch_name(adbname, start_at_zone, depth, qc, gqc,
|
||||
dns_rdatatype_a) == ISC_R_SUCCESS)
|
||||
{
|
||||
DP(DEF_LEVEL,
|
||||
|
|
@ -2149,7 +2149,7 @@ fetch:
|
|||
* Start V6.
|
||||
*/
|
||||
if (WANT_INET6(wanted_fetches) &&
|
||||
fetch_name(adbname, start_at_zone, depth, qc,
|
||||
fetch_name(adbname, start_at_zone, depth, qc, gqc,
|
||||
dns_rdatatype_aaaa) == ISC_R_SUCCESS)
|
||||
{
|
||||
DP(DEF_LEVEL,
|
||||
|
|
@ -2955,7 +2955,7 @@ out:
|
|||
|
||||
static isc_result_t
|
||||
fetch_name(dns_adbname_t *adbname, bool start_at_zone, unsigned int depth,
|
||||
isc_counter_t *qc, dns_rdatatype_t type) {
|
||||
isc_counter_t *qc, isc_counter_t *gqc, dns_rdatatype_t type) {
|
||||
isc_result_t result;
|
||||
dns_adbfetch_t *fetch = NULL;
|
||||
dns_adb_t *adb = NULL;
|
||||
|
|
@ -3011,7 +3011,7 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone, unsigned int depth,
|
|||
*/
|
||||
result = dns_resolver_createfetch(
|
||||
adb->res, adbname->name, type, name, nameservers, NULL, NULL, 0,
|
||||
options, depth, qc, isc_loop(), fetch_callback, adbname,
|
||||
options, depth, qc, gqc, isc_loop(), fetch_callback, adbname,
|
||||
&fetch->rdataset, NULL, &fetch->fetch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
DP(ENTER_LEVEL, "fetch_name: createfetch failed with %s",
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <isc/async.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/counter.h>
|
||||
#include <isc/loop.h>
|
||||
#include <isc/md.h>
|
||||
#include <isc/mem.h>
|
||||
|
|
@ -81,6 +82,7 @@ struct dns_client {
|
|||
unsigned int find_timeout;
|
||||
unsigned int find_udpretries;
|
||||
uint8_t max_restarts;
|
||||
uint8_t max_queries;
|
||||
|
||||
isc_refcount_t references;
|
||||
|
||||
|
|
@ -91,6 +93,7 @@ struct dns_client {
|
|||
#define DEF_FIND_TIMEOUT 5
|
||||
#define DEF_FIND_UDPRETRIES 3
|
||||
#define DEF_MAX_RESTARTS 11
|
||||
#define DEF_MAX_QUERIES 200
|
||||
|
||||
/*%
|
||||
* Internal state for a single name resolution procedure
|
||||
|
|
@ -111,6 +114,7 @@ typedef struct resctx {
|
|||
dns_fetch_t *fetch;
|
||||
dns_namelist_t namelist;
|
||||
isc_result_t result;
|
||||
isc_counter_t *qc;
|
||||
dns_clientresume_t *rev;
|
||||
dns_rdataset_t *rdataset;
|
||||
dns_rdataset_t *sigrdataset;
|
||||
|
|
@ -252,6 +256,7 @@ dns_client_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr, isc_nm_t *nm,
|
|||
.loop = isc_loop_get(loopmgr, 0),
|
||||
.nm = nm,
|
||||
.max_restarts = DEF_MAX_RESTARTS,
|
||||
.max_queries = DEF_MAX_QUERIES,
|
||||
};
|
||||
|
||||
result = dns_dispatchmgr_create(mctx, loopmgr, nm,
|
||||
|
|
@ -395,6 +400,14 @@ dns_client_setmaxrestarts(dns_client_t *client, uint8_t max_restarts) {
|
|||
client->max_restarts = max_restarts;
|
||||
}
|
||||
|
||||
void
|
||||
dns_client_setmaxqueries(dns_client_t *client, uint8_t max_queries) {
|
||||
REQUIRE(DNS_CLIENT_VALID(client));
|
||||
REQUIRE(max_queries > 0);
|
||||
|
||||
client->max_queries = max_queries;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
getrdataset(isc_mem_t *mctx, dns_rdataset_t **rdatasetp) {
|
||||
dns_rdataset_t *rdataset;
|
||||
|
|
@ -456,7 +469,7 @@ start_fetch(resctx_t *rctx) {
|
|||
|
||||
result = dns_resolver_createfetch(
|
||||
rctx->view->resolver, dns_fixedname_name(&rctx->name),
|
||||
rctx->type, NULL, NULL, NULL, NULL, 0, fopts, 0, NULL,
|
||||
rctx->type, NULL, NULL, NULL, NULL, 0, fopts, 0, NULL, rctx->qc,
|
||||
rctx->client->loop, fetch_done, rctx, rctx->rdataset,
|
||||
rctx->sigrdataset, &rctx->fetch);
|
||||
|
||||
|
|
@ -935,6 +948,11 @@ startresolve(dns_client_t *client, const dns_name_t *name,
|
|||
rctx->magic = RCTX_MAGIC;
|
||||
isc_refcount_increment(&client->references);
|
||||
|
||||
result = isc_counter_create(mctx, client->max_queries, &rctx->qc);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ISC_LIST_APPEND(client->resctxs, rctx, link);
|
||||
|
||||
*transp = (dns_clientrestrans_t *)rctx;
|
||||
|
|
@ -949,6 +967,9 @@ cleanup:
|
|||
if (sigrdataset != NULL) {
|
||||
putrdataset(client->mctx, &sigrdataset);
|
||||
}
|
||||
if (rctx->qc != NULL) {
|
||||
isc_counter_detach(&rctx->qc);
|
||||
}
|
||||
isc_mem_put(mctx, rctx, sizeof(*rctx));
|
||||
isc_mem_put(mctx, rev, sizeof(*rev));
|
||||
|
||||
|
|
@ -1042,6 +1063,9 @@ destroyrestrans(dns_clientrestrans_t **transp) {
|
|||
|
||||
rctx->magic = 0;
|
||||
|
||||
if (rctx->qc != NULL) {
|
||||
isc_counter_detach(&rctx->qc);
|
||||
}
|
||||
isc_mem_put(mctx, rctx, sizeof(*rctx));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -281,7 +281,8 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
|
|||
const dns_name_t *name, const dns_name_t *qname,
|
||||
dns_rdatatype_t qtype, unsigned int options,
|
||||
isc_stdtime_t now, dns_name_t *target, in_port_t port,
|
||||
unsigned int depth, isc_counter_t *qc, dns_adbfind_t **find);
|
||||
unsigned int depth, isc_counter_t *qc, isc_counter_t *gqc,
|
||||
dns_adbfind_t **find);
|
||||
/*%<
|
||||
* Main interface for clients. The adb will look up the name given in
|
||||
* "name" and will build up a list of found addresses, and perhaps start
|
||||
|
|
|
|||
|
|
@ -187,6 +187,19 @@ dns_client_setmaxrestarts(dns_client_t *client, uint8_t max_restarts);
|
|||
*\li 'max_restarts' is greater than 0.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_client_setmaxqueries(dns_client_t *client, uint8_t max_queries);
|
||||
/*%<
|
||||
* Set the number of permissible outgoing queries before we give up,
|
||||
* This defaults to 200.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'client' is a valid client.
|
||||
|
||||
*\li 'max_queries' is greater than 0.
|
||||
*/
|
||||
|
||||
typedef void (*dns_client_resolve_cb)(dns_client_t *client,
|
||||
const dns_name_t *name,
|
||||
dns_namelist_t *namelist,
|
||||
|
|
|
|||
|
|
@ -272,9 +272,10 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
|
|||
dns_forwarders_t *forwarders,
|
||||
const isc_sockaddr_t *client, dns_messageid_t id,
|
||||
unsigned int options, unsigned int depth,
|
||||
isc_counter_t *qc, isc_loop_t *loop, isc_job_cb cb,
|
||||
void *arg, dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *sigrdataset, dns_fetch_t **fetchp);
|
||||
isc_counter_t *qc, isc_counter_t *gqc,
|
||||
isc_loop_t *loop, isc_job_cb cb, void *arg,
|
||||
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
|
||||
dns_fetch_t **fetchp);
|
||||
/*%<
|
||||
* Recurse to answer a question.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ struct dns_validator {
|
|||
uint32_t *nvalidations;
|
||||
uint32_t *nfails;
|
||||
isc_counter_t *qc;
|
||||
isc_counter_t *gqc;
|
||||
};
|
||||
|
||||
/*%
|
||||
|
|
@ -172,7 +173,8 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
|||
dns_message_t *message, unsigned int options,
|
||||
isc_loop_t *loop, isc_job_cb cb, void *arg,
|
||||
uint32_t *nvalidations, uint32_t *nfails,
|
||||
isc_counter_t *qc, dns_validator_t **validatorp);
|
||||
isc_counter_t *qc, isc_counter_t *gqc,
|
||||
dns_validator_t **validatorp);
|
||||
/*%<
|
||||
* Start a DNSSEC validation.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ struct dns_view {
|
|||
unsigned int udpsize;
|
||||
uint32_t maxrrperset;
|
||||
uint32_t maxtypepername;
|
||||
uint16_t max_queries;
|
||||
uint8_t max_restarts;
|
||||
|
||||
/*
|
||||
|
|
@ -1341,4 +1342,16 @@ dns_view_setmaxrestarts(dns_view_t *view, uint8_t max_restarts);
|
|||
*\li 'max_restarts' is greater than 0.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_view_setmaxqueries(dns_view_t *view, uint16_t max_queries);
|
||||
/*%
|
||||
* Set the number of permissible outgoing queries before we give up.
|
||||
* This defaults to 200.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'view' is valid;
|
||||
*\li 'max_queries' is greater than 0.
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
|
|
|||
|
|
@ -241,8 +241,9 @@ checkbogus(void *arg) {
|
|||
dns__nta_ref(nta); /* for dns_resolver_createfetch */
|
||||
result = dns_resolver_createfetch(
|
||||
resolver, &nta->name, dns_rdatatype_nsec, NULL, NULL, NULL,
|
||||
NULL, 0, DNS_FETCHOPT_NONTA, 0, NULL, nta->loop, fetch_done,
|
||||
nta, &nta->rdataset, &nta->sigrdataset, &nta->fetch);
|
||||
NULL, 0, DNS_FETCHOPT_NONTA, 0, NULL, NULL, nta->loop,
|
||||
fetch_done, nta, &nta->rdataset, &nta->sigrdataset,
|
||||
&nta->fetch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns__nta_detach(&nta); /* for dns_resolver_createfetch() */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -395,6 +395,7 @@ struct fetchctx {
|
|||
bool ns_ttl_ok;
|
||||
uint32_t ns_ttl;
|
||||
isc_counter_t *qc;
|
||||
isc_counter_t *gqc;
|
||||
bool minimized;
|
||||
unsigned int qmin_labels;
|
||||
isc_result_t qmin_warning;
|
||||
|
|
@ -573,6 +574,7 @@ struct dns_resolver {
|
|||
unsigned int query_timeout;
|
||||
unsigned int maxdepth;
|
||||
unsigned int maxqueries;
|
||||
unsigned int maxquerycount;
|
||||
isc_result_t quotaresp[2];
|
||||
isc_stats_t *stats;
|
||||
dns_stats_t *querystats;
|
||||
|
|
@ -713,7 +715,7 @@ get_attached_fctx(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
|
|||
dns_rdatatype_t type, const dns_name_t *domain,
|
||||
dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
|
||||
unsigned int options, unsigned int depth, isc_counter_t *qc,
|
||||
fetchctx_t **fctxp, bool *new_fctx);
|
||||
isc_counter_t *gqc, fetchctx_t **fctxp, bool *new_fctx);
|
||||
static void
|
||||
release_fctx(fetchctx_t *fctx);
|
||||
|
||||
|
|
@ -987,7 +989,7 @@ valcreate(fetchctx_t *fctx, dns_message_t *message, dns_adbaddrinfo_t *addrinfo,
|
|||
result = dns_validator_create(
|
||||
fctx->res->view, name, type, rdataset, sigrdataset, message,
|
||||
valoptions, fctx->loop, validated, valarg, &fctx->nvalidations,
|
||||
&fctx->nfails, fctx->qc, &validator);
|
||||
&fctx->nfails, fctx->qc, fctx->gqc, &validator);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
inc_stats(fctx->res, dns_resstatscounter_val);
|
||||
if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
|
||||
|
|
@ -3285,7 +3287,7 @@ findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
|
|||
result = dns_adb_createfind(fctx->adb, fctx->loop, fctx_finddone, fctx,
|
||||
name, fctx->name, fctx->type, options, now,
|
||||
NULL, res->view->dstport, fctx->depth + 1,
|
||||
fctx->qc, &find);
|
||||
fctx->qc, fctx->gqc, &find);
|
||||
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
|
||||
|
|
@ -3985,6 +3987,9 @@ fctx_try(fetchctx_t *fctx, bool retrying) {
|
|||
dns_resolver_t *res = NULL;
|
||||
|
||||
FCTXTRACE5("try", "fctx->qc=", isc_counter_used(fctx->qc));
|
||||
if (fctx->gqc != NULL) {
|
||||
FCTXTRACE5("try", "fctx->gqc=", isc_counter_used(fctx->gqc));
|
||||
}
|
||||
|
||||
REQUIRE(!ADDRWAIT(fctx));
|
||||
REQUIRE(fctx->tid == isc_tid());
|
||||
|
|
@ -3992,13 +3997,27 @@ fctx_try(fetchctx_t *fctx, bool retrying) {
|
|||
res = fctx->res;
|
||||
|
||||
/* We've already exceeded maximum query count */
|
||||
if (isc_counter_used(fctx->qc) > res->maxqueries) {
|
||||
if (isc_counter_used(fctx->qc) > isc_counter_getlimit(fctx->qc)) {
|
||||
isc_log_write(
|
||||
dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
|
||||
"exceeded max queries resolving '%s' "
|
||||
"(max-recursion-queries, querycount=%u, maxqueries=%u)",
|
||||
fctx->info, isc_counter_used(fctx->qc),
|
||||
isc_counter_getlimit(fctx->qc));
|
||||
result = DNS_R_SERVFAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (fctx->gqc != NULL &&
|
||||
isc_counter_used(fctx->gqc) > isc_counter_getlimit(fctx->gqc))
|
||||
{
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
|
||||
"exceeded max queries resolving '%s' "
|
||||
"(querycount=%u, maxqueries=%u)",
|
||||
fctx->info, isc_counter_used(fctx->qc),
|
||||
res->maxqueries);
|
||||
"exceeded global max queries resolving '%s' "
|
||||
"(max-query-count, querycount=%u, maxqueries=%u)",
|
||||
fctx->info, isc_counter_used(fctx->gqc),
|
||||
isc_counter_getlimit(fctx->gqc));
|
||||
result = DNS_R_SERVFAIL;
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -4096,8 +4115,8 @@ fctx_try(fetchctx_t *fctx, bool retrying) {
|
|||
result = dns_resolver_createfetch(
|
||||
fctx->res, fctx->qminname, fctx->qmintype, fctx->domain,
|
||||
&fctx->nameservers, NULL, NULL, 0, options, 0, fctx->qc,
|
||||
fctx->loop, resume_qmin, fctx, &fctx->qminrrset, NULL,
|
||||
&fctx->qminfetch);
|
||||
fctx->gqc, fctx->loop, resume_qmin, fctx,
|
||||
&fctx->qminrrset, NULL, &fctx->qminfetch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fetchctx_unref(fctx);
|
||||
goto done;
|
||||
|
|
@ -4109,11 +4128,24 @@ fctx_try(fetchctx_t *fctx, bool retrying) {
|
|||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
|
||||
"exceeded max queries resolving '%s'",
|
||||
fctx->info);
|
||||
"exceeded max queries resolving '%s' "
|
||||
"(max-recursion-queries, querycount=%u)",
|
||||
fctx->info, isc_counter_used(fctx->qc));
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (fctx->gqc != NULL) {
|
||||
result = isc_counter_increment(fctx->gqc);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
|
||||
"exceeded global max queries resolving "
|
||||
"'%s' (max-query-count, querycount=%u)",
|
||||
fctx->info, isc_counter_used(fctx->gqc));
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
result = fctx_query(fctx, addrinfo, fctx->options);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto done;
|
||||
|
|
@ -4345,6 +4377,9 @@ fctx_destroy(fetchctx_t *fctx) {
|
|||
}
|
||||
|
||||
isc_counter_detach(&fctx->qc);
|
||||
if (fctx->gqc != NULL) {
|
||||
isc_counter_detach(&fctx->gqc);
|
||||
}
|
||||
fcount_decr(fctx);
|
||||
dns_message_detach(&fctx->qmessage);
|
||||
if (dns_rdataset_isassociated(&fctx->nameservers)) {
|
||||
|
|
@ -4502,7 +4537,7 @@ fctx_create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
|
|||
dns_rdatatype_t type, const dns_name_t *domain,
|
||||
dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
|
||||
unsigned int options, unsigned int depth, isc_counter_t *qc,
|
||||
fetchctx_t **fctxp) {
|
||||
isc_counter_t *gqc, fetchctx_t **fctxp) {
|
||||
fetchctx_t *fctx = NULL;
|
||||
isc_result_t result;
|
||||
isc_result_t iresult;
|
||||
|
|
@ -4570,6 +4605,15 @@ fctx_create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
|
|||
fctx->info, fctx->qc);
|
||||
}
|
||||
|
||||
if (gqc != NULL) {
|
||||
isc_counter_attach(gqc, &fctx->gqc);
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(9),
|
||||
"fctx %p(%s): attached to counter %p (%d)", fctx,
|
||||
fctx->info, fctx->gqc,
|
||||
isc_counter_used(fctx->gqc));
|
||||
}
|
||||
|
||||
#if DNS_RESOLVER_TRACE
|
||||
fprintf(stderr, "fetchctx__init:%s:%s:%d:%p:%p->references = 1\n",
|
||||
__func__, __FILE__, __LINE__, fctx, fctx);
|
||||
|
|
@ -4779,6 +4823,9 @@ cleanup_nameservers:
|
|||
}
|
||||
isc_mem_free(fctx->mctx, fctx->info);
|
||||
isc_counter_detach(&fctx->qc);
|
||||
if (fctx->gqc != NULL) {
|
||||
isc_counter_detach(&fctx->gqc);
|
||||
}
|
||||
|
||||
cleanup_fetch:
|
||||
dns_resolver_detach(&fctx->res);
|
||||
|
|
@ -7146,8 +7193,8 @@ resume_dslookup(void *arg) {
|
|||
fetchctx_ref(fctx);
|
||||
result = dns_resolver_createfetch(
|
||||
res, fctx->nsname, dns_rdatatype_ns, domain, nsrdataset,
|
||||
NULL, NULL, 0, fctx->options, 0, fctx->qc, loop,
|
||||
resume_dslookup, fctx, &fctx->nsrrset, NULL,
|
||||
NULL, NULL, 0, fctx->options, 0, fctx->qc, fctx->gqc,
|
||||
loop, resume_dslookup, fctx, &fctx->nsrrset, NULL,
|
||||
&fctx->nsfetch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fetchctx_unref(fctx);
|
||||
|
|
@ -9574,7 +9621,7 @@ rctx_chaseds(respctx_t *rctx, dns_message_t *message,
|
|||
fetchctx_ref(fctx);
|
||||
result = dns_resolver_createfetch(
|
||||
fctx->res, fctx->nsname, dns_rdatatype_ns, NULL, NULL, NULL,
|
||||
NULL, 0, fctx->options, 0, fctx->qc, fctx->loop,
|
||||
NULL, 0, fctx->options, 0, fctx->qc, fctx->gqc, fctx->loop,
|
||||
resume_dslookup, fctx, &fctx->nsrrset, NULL, &fctx->nsfetch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (result == DNS_R_DUPLICATE) {
|
||||
|
|
@ -10149,8 +10196,9 @@ dns_resolver_prime(dns_resolver_t *res) {
|
|||
LOCK(&res->primelock);
|
||||
result = dns_resolver_createfetch(
|
||||
res, dns_rootname, dns_rdatatype_ns, NULL, NULL, NULL,
|
||||
NULL, 0, DNS_FETCHOPT_NOFORWARD, 0, NULL, isc_loop(),
|
||||
prime_done, res, rdataset, NULL, &res->primefetch);
|
||||
NULL, 0, DNS_FETCHOPT_NOFORWARD, 0, NULL, NULL,
|
||||
isc_loop(), prime_done, res, rdataset, NULL,
|
||||
&res->primefetch);
|
||||
UNLOCK(&res->primelock);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -10349,7 +10397,7 @@ get_attached_fctx(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
|
|||
dns_rdatatype_t type, const dns_name_t *domain,
|
||||
dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
|
||||
unsigned int options, unsigned int depth, isc_counter_t *qc,
|
||||
fetchctx_t **fctxp, bool *new_fctx) {
|
||||
isc_counter_t *gqc, fetchctx_t **fctxp, bool *new_fctx) {
|
||||
isc_result_t result;
|
||||
fetchctx_t key = {
|
||||
.name = UNCONST(name),
|
||||
|
|
@ -10369,7 +10417,7 @@ again:
|
|||
break;
|
||||
case ISC_R_NOTFOUND:
|
||||
result = fctx_create(res, loop, name, type, domain, nameservers,
|
||||
client, options, depth, qc, &fctx);
|
||||
client, options, depth, qc, gqc, &fctx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto unlock;
|
||||
}
|
||||
|
|
@ -10424,9 +10472,10 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
|
|||
dns_forwarders_t *forwarders,
|
||||
const isc_sockaddr_t *client, dns_messageid_t id,
|
||||
unsigned int options, unsigned int depth,
|
||||
isc_counter_t *qc, isc_loop_t *loop, isc_job_cb cb,
|
||||
void *arg, dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *sigrdataset, dns_fetch_t **fetchp) {
|
||||
isc_counter_t *qc, isc_counter_t *gqc,
|
||||
isc_loop_t *loop, isc_job_cb cb, void *arg,
|
||||
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
|
||||
dns_fetch_t **fetchp) {
|
||||
dns_fetch_t *fetch = NULL;
|
||||
fetchctx_t *fctx = NULL;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
|
@ -10477,7 +10526,7 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
|
|||
|
||||
result = get_attached_fctx(res, loop, name, type, domain,
|
||||
nameservers, client, options, depth,
|
||||
qc, &fctx, &new_fctx);
|
||||
qc, gqc, &fctx, &new_fctx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -10513,7 +10562,7 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
|
|||
}
|
||||
} else {
|
||||
result = fctx_create(res, loop, name, type, domain, nameservers,
|
||||
client, options, depth, qc, &fctx);
|
||||
client, options, depth, qc, gqc, &fctx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto unlock;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -938,7 +938,7 @@ create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
|
|||
dns_validator_ref(val);
|
||||
result = dns_resolver_createfetch(
|
||||
val->view->resolver, name, type, NULL, NULL, NULL, NULL, 0,
|
||||
fopts, 0, NULL, val->loop, callback, val, &val->frdataset,
|
||||
fopts, 0, NULL, NULL, val->loop, callback, val, &val->frdataset,
|
||||
&val->fsigrdataset, &val->fetch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_validator_detach(&val);
|
||||
|
|
@ -976,7 +976,7 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
|
|||
result = dns_validator_create(val->view, name, type, rdataset, sig,
|
||||
NULL, vopts, val->loop, cb, val,
|
||||
val->nvalidations, val->nfails, val->qc,
|
||||
&val->subvalidator);
|
||||
val->gqc, &val->subvalidator);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
dns_validator_attach(val, &val->subvalidator->parent);
|
||||
val->subvalidator->depth = val->depth + 1;
|
||||
|
|
@ -3392,7 +3392,8 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
|||
dns_message_t *message, unsigned int options,
|
||||
isc_loop_t *loop, isc_job_cb cb, void *arg,
|
||||
uint32_t *nvalidations, uint32_t *nfails,
|
||||
isc_counter_t *qc, dns_validator_t **validatorp) {
|
||||
isc_counter_t *qc, isc_counter_t *gqc,
|
||||
dns_validator_t **validatorp) {
|
||||
isc_result_t result = ISC_R_FAILURE;
|
||||
dns_validator_t *val = NULL;
|
||||
dns_keytable_t *kt = NULL;
|
||||
|
|
@ -3435,6 +3436,9 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
|||
if (qc != NULL) {
|
||||
isc_counter_attach(qc, &val->qc);
|
||||
}
|
||||
if (gqc != NULL) {
|
||||
isc_counter_attach(gqc, &val->gqc);
|
||||
}
|
||||
|
||||
val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
|
||||
dns_rdataset_init(&val->fdsset);
|
||||
|
|
@ -3525,6 +3529,9 @@ destroy_validator(dns_validator_t *val) {
|
|||
if (val->qc != NULL) {
|
||||
isc_counter_detach(&val->qc);
|
||||
}
|
||||
if (val->gqc != NULL) {
|
||||
isc_counter_detach(&val->gqc);
|
||||
}
|
||||
dns_view_detach(&val->view);
|
||||
isc_loop_detach(&val->loop);
|
||||
isc_mem_put(mctx, val, sizeof(*val));
|
||||
|
|
|
|||
|
|
@ -2471,3 +2471,11 @@ dns_view_setmaxrestarts(dns_view_t *view, uint8_t max_restarts) {
|
|||
|
||||
view->max_restarts = max_restarts;
|
||||
}
|
||||
|
||||
void
|
||||
dns_view_setmaxqueries(dns_view_t *view, uint16_t max_queries) {
|
||||
REQUIRE(DNS_VIEW_VALID(view));
|
||||
REQUIRE(max_queries > 0);
|
||||
|
||||
view->max_queries = max_queries;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10896,7 +10896,7 @@ do_keyfetch(void *arg) {
|
|||
*/
|
||||
result = dns_resolver_createfetch(
|
||||
resolver, kname, dns_rdatatype_dnskey, NULL, NULL, NULL, NULL,
|
||||
0, options, 0, NULL, zone->loop, keyfetch_done, kfetch,
|
||||
0, options, 0, NULL, NULL, zone->loop, keyfetch_done, kfetch,
|
||||
&kfetch->dnskeyset, &kfetch->dnskeysigset, &kfetch->fetch);
|
||||
|
||||
dns_resolver_detach(&resolver);
|
||||
|
|
@ -12416,7 +12416,7 @@ notify_find_address(dns_notify_t *notify) {
|
|||
result = dns_adb_createfind(
|
||||
adb, notify->zone->loop, process_notify_adb_event, notify,
|
||||
¬ify->ns, dns_rootname, 0, options, 0, NULL,
|
||||
notify->zone->view->dstport, 0, NULL, ¬ify->find);
|
||||
notify->zone->view->dstport, 0, NULL, NULL, ¬ify->find);
|
||||
dns_adb_detach(&adb);
|
||||
|
||||
/* Something failed? */
|
||||
|
|
@ -21276,7 +21276,7 @@ checkds_find_address(dns_checkds_t *checkds) {
|
|||
result = dns_adb_createfind(
|
||||
adb, checkds->zone->loop, process_checkds_adb_event, checkds,
|
||||
&checkds->ns, dns_rootname, 0, options, 0, NULL,
|
||||
checkds->zone->view->dstport, 0, NULL, &checkds->find);
|
||||
checkds->zone->view->dstport, 0, NULL, NULL, &checkds->find);
|
||||
dns_adb_detach(&adb);
|
||||
|
||||
/* Something failed? */
|
||||
|
|
@ -21861,8 +21861,9 @@ do_nsfetch(void *arg) {
|
|||
*/
|
||||
result = dns_resolver_createfetch(
|
||||
resolver, &nsfetch->pname, dns_rdatatype_ns, NULL, NULL, NULL,
|
||||
NULL, 0, options, 0, NULL, zone->loop, nsfetch_done, nsfetch,
|
||||
&nsfetch->nsrrset, &nsfetch->nssigset, &nsfetch->fetch);
|
||||
NULL, 0, options, 0, NULL, NULL, zone->loop, nsfetch_done,
|
||||
nsfetch, &nsfetch->nsrrset, &nsfetch->nssigset,
|
||||
&nsfetch->fetch);
|
||||
|
||||
dns_resolver_detach(&resolver);
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,13 @@ isc_counter_setlimit(isc_counter_t *counter, int limit) {
|
|||
atomic_store(&counter->limit, limit);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
isc_counter_getlimit(isc_counter_t *counter) {
|
||||
REQUIRE(VALID_COUNTER(counter));
|
||||
|
||||
return atomic_load_acquire(&counter->limit);
|
||||
}
|
||||
|
||||
void
|
||||
isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp) {
|
||||
REQUIRE(VALID_COUNTER(source));
|
||||
|
|
|
|||
|
|
@ -68,6 +68,12 @@ isc_counter_setlimit(isc_counter_t *counter, int limit);
|
|||
* Set the counter limit.
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
isc_counter_getlimit(isc_counter_t *counter);
|
||||
/*%<
|
||||
* Get the counter limit.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -2220,6 +2220,7 @@ static cfg_clausedef_t view_clauses[] = {
|
|||
{ "max-ncache-ttl", &cfg_type_duration, 0 },
|
||||
{ "max-recursion-depth", &cfg_type_uint32, 0 },
|
||||
{ "max-recursion-queries", &cfg_type_uint32, 0 },
|
||||
{ "max-query-count", &cfg_type_uint32, 0 },
|
||||
{ "max-query-restarts", &cfg_type_uint32, 0 },
|
||||
{ "max-stale-ttl", &cfg_type_duration, 0 },
|
||||
{ "max-udp-size", &cfg_type_uint32, 0 },
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ typedef struct ns_query_recparam {
|
|||
struct ns_query {
|
||||
unsigned int attributes;
|
||||
unsigned int restarts;
|
||||
isc_counter_t *qc;
|
||||
bool timerset;
|
||||
dns_name_t *qname;
|
||||
dns_name_t *origqname;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <isc/async.h>
|
||||
#include <isc/counter.h>
|
||||
#include <isc/hex.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/once.h>
|
||||
|
|
@ -865,6 +866,9 @@ query_reset(ns_client_t *client, bool everything) {
|
|||
client->query.rpz_st = NULL;
|
||||
}
|
||||
}
|
||||
if (client->query.qc != NULL) {
|
||||
isc_counter_detach(&client->query.qc);
|
||||
}
|
||||
client->query.origqname = NULL;
|
||||
client->query.dboptions = 0;
|
||||
client->query.fetchoptions = 0;
|
||||
|
|
@ -2804,7 +2808,8 @@ fetch_and_forget(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t qtype,
|
|||
result = dns_resolver_createfetch(
|
||||
client->view->resolver, qname, qtype, NULL, NULL, NULL,
|
||||
peeraddr, client->message->id, options, 0, NULL,
|
||||
client->manager->loop, cb, client, tmprdataset, NULL, fetchp);
|
||||
client->query.qc, client->manager->loop, cb, client,
|
||||
tmprdataset, NULL, fetchp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_client_putrdataset(client, &tmprdataset);
|
||||
isc_nmhandle_detach(handlep);
|
||||
|
|
@ -6590,8 +6595,9 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
|
|||
result = dns_resolver_createfetch(
|
||||
client->view->resolver, qname, qtype, qdomain, nameservers,
|
||||
NULL, peeraddr, client->message->id, client->query.fetchoptions,
|
||||
0, NULL, client->manager->loop, fetch_callback, client,
|
||||
rdataset, sigrdataset, &FETCH_RECTYPE_NORMAL(client));
|
||||
0, NULL, client->query.qc, client->manager->loop,
|
||||
fetch_callback, client, rdataset, sigrdataset,
|
||||
&FETCH_RECTYPE_NORMAL(client));
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
release_recursionquota(client);
|
||||
|
||||
|
|
@ -12251,5 +12257,16 @@ ns_query_start(ns_client_t *client, isc_nmhandle_t *handle) {
|
|||
message->flags |= DNS_MESSAGEFLAG_AD;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start global outgoing query count.
|
||||
*/
|
||||
result = isc_counter_create(client->manager->mctx,
|
||||
client->view->max_queries,
|
||||
&client->query.qc);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
query_next(client, result);
|
||||
return;
|
||||
}
|
||||
|
||||
query_setup(client, qtype);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue