mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-21 17:41:35 -04:00
Merge tag 'v9.21.22'
This commit is contained in:
commit
6cae1d10ca
92 changed files with 4453 additions and 478 deletions
|
|
@ -1715,6 +1715,7 @@ dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) {
|
|||
dns_name_t *origin = dns_zone_getorigin(zone);
|
||||
dns_rdataclass_t zclass = view->rdclass;
|
||||
|
||||
dns_zone_setclass(zone, zclass);
|
||||
RETERR(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
|
||||
|
||||
dns_zone_setstats(zone, named_g_server->zonestats);
|
||||
|
|
@ -3926,7 +3927,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
obj = NULL;
|
||||
result = named_config_get(maps, "recursion", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
view->recursion = cfg_obj_asboolean(obj);
|
||||
view->recursion = (view->rdclass == dns_rdataclass_in &&
|
||||
cfg_obj_asboolean(obj));
|
||||
|
||||
max_cache_size = configure_max_cache_size(view, maps);
|
||||
|
||||
|
|
@ -4543,35 +4545,13 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
/*
|
||||
* We have default root hints for class IN if we need them.
|
||||
* Each view gets its own rootdb so a priming response only
|
||||
* writes into that view's copy.
|
||||
* writes into that view's copy. Other classes don't support
|
||||
* recursion and don't need hints.
|
||||
*/
|
||||
if (view->rdclass == dns_rdataclass_in && view->rootdb == NULL) {
|
||||
CHECK(configure_rootdb(view, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
* If we still have no root hints, this is a non-IN view with no
|
||||
* "hints zone" configured. Issue a warning, except if this
|
||||
* is a root server. Root servers never need to consult
|
||||
* their hints, so it's no point requiring users to configure
|
||||
* them.
|
||||
*/
|
||||
if (view->rootdb == NULL) {
|
||||
dns_zone_t *rootzone = NULL;
|
||||
(void)dns_view_findzone(view, dns_rootname, DNS_ZTFIND_EXACT,
|
||||
&rootzone);
|
||||
if (rootzone != NULL) {
|
||||
dns_zone_detach(&rootzone);
|
||||
} else if (strcmp(view->name, "_bind") != 0 ||
|
||||
view->rdclass != dns_rdataclass_chaos)
|
||||
{
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
|
||||
"no root hints for view '%s'",
|
||||
view->name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure the view's transports (DoT/DoH)
|
||||
*/
|
||||
|
|
@ -4794,9 +4774,10 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
CHECK(configure_view_acl(vconfig, config, "allow-proxy-on", NULL,
|
||||
aclctx, isc_g_mctx, &view->proxyonacl));
|
||||
|
||||
if (strcmp(view->name, "_bind") != 0 &&
|
||||
view->rdclass != dns_rdataclass_chaos)
|
||||
{
|
||||
if (view->rdclass != dns_rdataclass_in) {
|
||||
dns_acl_none(isc_g_mctx, &view->recursionacl);
|
||||
dns_acl_none(isc_g_mctx, &view->recursiononacl);
|
||||
} else {
|
||||
CHECK(configure_view_acl(vconfig, config, "allow-recursion",
|
||||
NULL, aclctx, isc_g_mctx,
|
||||
&view->recursionacl));
|
||||
|
|
|
|||
|
|
@ -515,6 +515,7 @@ $CHECKCONF -l good.conf \
|
|||
| grep -v "is not implemented" \
|
||||
| grep -v "is not recommended" \
|
||||
| grep -v "no longer exists" \
|
||||
| grep -v "recursion will be disabled" \
|
||||
| grep -v "is obsolete" >checkconf.out$n || ret=1
|
||||
diff good.zonelist checkconf.out$n >diff.out$n || ret=1
|
||||
if [ $ret -ne 0 ]; then
|
||||
|
|
@ -738,5 +739,16 @@ if [ $ret != 0 ]; then
|
|||
fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "check 'recursion yes;' is warned and disabled in a non-IN view ($n)"
|
||||
ret=0
|
||||
$CHECKCONF warn-chaos-recursion.conf >checkconf.out$n 2>&1 || ret=1
|
||||
grep -F "recursion will be disabled" checkconf.out$n >/dev/null || ret=1
|
||||
if [ $ret != 0 ]; then
|
||||
echo_i "failed"
|
||||
ret=1
|
||||
fi
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
||||
|
|
|
|||
12
bin/tests/system/checkconf/warn-chaos-recursion.conf
Normal file
12
bin/tests/system/checkconf/warn-chaos-recursion.conf
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
options {
|
||||
directory ".";
|
||||
};
|
||||
|
||||
view chaos ch {
|
||||
match-clients { any; };
|
||||
recursion yes;
|
||||
zone "." {
|
||||
type hint;
|
||||
file "chaos.hints";
|
||||
};
|
||||
};
|
||||
4
bin/tests/system/class/ns1/chaos.db.in
Normal file
4
bin/tests/system/class/ns1/chaos.db.in
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
. CH NS ns.root.
|
||||
ns.root. CH A ns.root. 1
|
||||
ns.root. CH AAAA \# 1 00
|
||||
|
||||
31
bin/tests/system/class/ns1/named.conf.j2
Normal file
31
bin/tests/system/class/ns1/named.conf.j2
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
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; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
view chaos ch {
|
||||
match-clients { any; };
|
||||
recursion yes;
|
||||
zone "." {
|
||||
type hint;
|
||||
file "chaos.db";
|
||||
};
|
||||
zone "version.bind" {
|
||||
type primary;
|
||||
database "_builtin version";
|
||||
};
|
||||
};
|
||||
6
bin/tests/system/class/ns2/example.db.in
Normal file
6
bin/tests/system/class/ns2/example.db.in
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
$TTL 300
|
||||
@ CH SOA ns.example. hostmaster.example. 1 3600 1200 604800 300
|
||||
@ CH NS ns.example.
|
||||
ns CH TXT "ns"
|
||||
a CH A target.example. 1
|
||||
target CH TXT "target"
|
||||
11
bin/tests/system/class/ns2/localhost.db.in
Normal file
11
bin/tests/system/class/ns2/localhost.db.in
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
$ORIGIN 1.0.0.127.in-addr.arpa.
|
||||
$TTL 300
|
||||
@ IN SOA ns hostmaster 1 3600 900 604800 300
|
||||
@ IN NS ns
|
||||
ns IN A 127.0.0.1
|
||||
|
||||
@ IN KX 10 target.example.
|
||||
@ IN PX 10 map822.example. mapx400.example.
|
||||
@ IN NSAP 0x47000580ffff0000000001e133ffffff00016200
|
||||
@ IN NSAP-PTR target.example.
|
||||
@ in EID \# 01 aa
|
||||
42
bin/tests/system/class/ns2/named.conf.j2
Normal file
42
bin/tests/system/class/ns2/named.conf.j2
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
options {
|
||||
directory ".";
|
||||
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; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
view default {
|
||||
match-clients { any; };
|
||||
recursion no;
|
||||
dnssec-validation no;
|
||||
zone "1.0.0.127.in-addr.arpa." {
|
||||
type primary;
|
||||
file "localhost.db";
|
||||
update-policy {
|
||||
grant * tcp-self . ANY;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
view chaos ch {
|
||||
match-clients { any; };
|
||||
recursion no;
|
||||
zone example {
|
||||
type primary;
|
||||
file "example.db";
|
||||
allow-update { any; };
|
||||
};
|
||||
};
|
||||
28
bin/tests/system/class/ns3/named.conf.j2
Normal file
28
bin/tests/system/class/ns3/named.conf.j2
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
options {
|
||||
directory ".";
|
||||
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; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
view chaos ch {
|
||||
match-clients { any; };
|
||||
recursion yes;
|
||||
dnssec-validation no;
|
||||
forward only;
|
||||
forwarders port @PORT@ { 10.53.0.2; };
|
||||
deny-answer-addresses { 0.0.0.0/0; ::/0; };
|
||||
};
|
||||
19
bin/tests/system/class/setup.sh
Normal file
19
bin/tests/system/class/setup.sh
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#!/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
|
||||
|
||||
cp ns1/chaos.db.in ns1/chaos.db
|
||||
cp ns2/example.db.in ns2/example.db
|
||||
cp ns2/localhost.db.in ns2/localhost.db
|
||||
54
bin/tests/system/class/tests_class_chaos.py
Normal file
54
bin/tests/system/class/tests_class_chaos.py
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# 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 dns.opcode
|
||||
import pytest
|
||||
|
||||
import isctest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"*/*.db",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_chaos_recursion():
|
||||
msg = isctest.query.create("foo.example.", "TXT", qclass="CH")
|
||||
res = isctest.query.udp(msg, "10.53.0.1")
|
||||
isctest.check.refused(res)
|
||||
|
||||
|
||||
def test_chaos_auth():
|
||||
msg = isctest.query.create("a.example.", "A", qclass="CH")
|
||||
res = isctest.query.udp(msg, "10.53.0.2")
|
||||
isctest.check.noerror(res)
|
||||
|
||||
|
||||
def test_chaos_forward():
|
||||
msg = isctest.query.create("a.example.", "A", qclass="CH")
|
||||
res = isctest.query.udp(msg, "10.53.0.3")
|
||||
isctest.check.refused(res)
|
||||
|
||||
|
||||
def test_chaos_notify():
|
||||
msg = isctest.query.create("example.", "SOA", qclass="CH", rd=False, dnssec=False)
|
||||
msg.set_opcode(dns.opcode.NOTIFY)
|
||||
msg.flags = dns.opcode.to_flags(dns.opcode.NOTIFY)
|
||||
res = isctest.query.udp(msg, "10.53.0.2")
|
||||
isctest.check.notimp(res)
|
||||
|
||||
|
||||
def test_query_class_none():
|
||||
msg = isctest.query.create("example.", "A", qclass="NONE")
|
||||
res = isctest.query.udp(msg, "10.53.0.2")
|
||||
isctest.check.formerr(res)
|
||||
137
bin/tests/system/class/tests_class_update.py
Normal file
137
bin/tests/system/class/tests_class_update.py
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
# 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 socket
|
||||
import struct
|
||||
|
||||
from dns import message, rdataclass, rdatatype, update
|
||||
|
||||
import pytest
|
||||
|
||||
import isctest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"*/*.db",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def encode_name(name: str) -> bytes:
|
||||
out = b""
|
||||
for label in name.rstrip(".").split("."):
|
||||
out += bytes([len(label)]) + label.encode("ascii")
|
||||
return out + b"\x00"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"rdtype,rdclass,ttl,rdata",
|
||||
[
|
||||
(rdatatype.SRV, rdataclass.NONE, 0, b"\x00\x00\x00\x00\x00\x00\x01"),
|
||||
(rdatatype.SRV, rdataclass.NONE, 0, b"\x00"),
|
||||
(rdatatype.KX, rdataclass.NONE, 0, b""),
|
||||
(rdatatype.PX, rdataclass.NONE, 0, b""),
|
||||
(rdatatype.NSAP, rdataclass.NONE, 0, b""),
|
||||
(rdatatype.NSAP_PTR, rdataclass.NONE, 0, b""),
|
||||
(31, rdataclass.NONE, 0, b""), # dnspython doesn't define type EID
|
||||
],
|
||||
)
|
||||
def test_class_invalid(rdtype, rdclass, ttl, rdata, named_port):
|
||||
# these update messages are badly formatted, so we construct
|
||||
# them manually instead of using dnspython.
|
||||
|
||||
# opcode=UPDATE, 1 RRset in ZONE, 1 RRset in UPDATE
|
||||
header = struct.pack("!HHHHHH", 0, 0x2800, 1, 0, 1, 0)
|
||||
|
||||
# ZONE section: QNAME=<zone>, QTYPE=SOA, QCLASS=ANY
|
||||
zone_q = encode_name("1.0.0.127.in-addr.arpa") + struct.pack("!HH", 6, 255)
|
||||
|
||||
# UPDATE section RR:
|
||||
update_rr = (
|
||||
encode_name("1.0.0.127.in-addr.arpa")
|
||||
+ struct.pack("!HHIH", rdtype, rdclass, ttl, len(rdata))
|
||||
+ rdata
|
||||
)
|
||||
|
||||
m = header + zone_q + update_rr
|
||||
packet = struct.pack("!H", len(m)) + m
|
||||
|
||||
with socket.create_connection(
|
||||
("10.53.0.2", named_port), source_address=("127.0.0.1", 0), timeout=2.0
|
||||
) as s:
|
||||
s.sendall(packet)
|
||||
try:
|
||||
rwire = s.recv(4096)
|
||||
res = message.from_wire(rwire)
|
||||
isctest.check.formerr(res)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
pass
|
||||
|
||||
# check the server is answering
|
||||
msg = isctest.query.create("1.0.0.127.in-addr.arpa", "SRV")
|
||||
res = isctest.query.udp(msg, "10.53.0.2")
|
||||
isctest.check.noerror(res)
|
||||
isctest.check.rr_count_eq(res.answer, 0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"rdtype,rdata",
|
||||
[
|
||||
(rdatatype.SVCB, "\\# 02 0000"),
|
||||
(rdatatype.WKS, "\\# 02 4142"),
|
||||
(rdatatype.WKS, "\\# 02 4344"),
|
||||
],
|
||||
)
|
||||
def test_class_chaosupdate(rdtype, rdata):
|
||||
up = update.UpdateMessage("example.", rdclass=rdataclass.CHAOS)
|
||||
up.add("foo.example.", 300, rdtype, rdata)
|
||||
res = isctest.query.tcp(up, "10.53.0.2")
|
||||
isctest.check.notimp(res)
|
||||
|
||||
|
||||
def test_class_undefined(ns2):
|
||||
up = update.UpdateMessage(".", rdclass=257)
|
||||
up.present(".", 0)
|
||||
up.answer[0].rdclass = rdataclass.NONE
|
||||
with ns2.watch_log_from_here() as watcher:
|
||||
res = isctest.query.tcp(up, "10.53.0.2")
|
||||
isctest.check.notimp(res)
|
||||
watcher.wait_for_line("invalid message class: CLASS257")
|
||||
|
||||
|
||||
def test_class_zero(ns2):
|
||||
up = update.UpdateMessage(".", rdclass=0)
|
||||
up.present(".", 0)
|
||||
up.answer[0].rdclass = rdataclass.NONE
|
||||
with ns2.watch_log_from_here() as watcher:
|
||||
res = isctest.query.tcp(up, "10.53.0.2")
|
||||
isctest.check.formerr(res)
|
||||
watcher.wait_for_line("message class could not be determined")
|
||||
|
||||
|
||||
def test_class_any(ns2):
|
||||
up = update.UpdateMessage(".", rdclass=rdataclass.ANY)
|
||||
up.present(".", 0)
|
||||
up.answer[0].rdclass = rdataclass.NONE
|
||||
with ns2.watch_log_from_here() as watcher:
|
||||
res = isctest.query.tcp(up, "10.53.0.2")
|
||||
isctest.check.formerr(res)
|
||||
watcher.wait_for_line("message parsing failed: FORMERR")
|
||||
|
||||
|
||||
def test_class_none(ns2):
|
||||
up = update.UpdateMessage(".", rdclass=rdataclass.NONE)
|
||||
up.present(".", 0)
|
||||
up.answer[0].rdclass = rdataclass.NONE
|
||||
with ns2.watch_log_from_here() as watcher:
|
||||
res = isctest.query.tcp(up, "10.53.0.2")
|
||||
isctest.check.formerr(res)
|
||||
watcher.wait_for_line("message parsing failed: FORMERR")
|
||||
73
bin/tests/system/doth/tests_malicious.py
Normal file
73
bin/tests/system/doth/tests_malicious.py
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# 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 socket
|
||||
import ssl
|
||||
|
||||
from h2.config import H2Configuration
|
||||
from h2.connection import H2Connection
|
||||
from h2.settings import SettingCodes
|
||||
|
||||
import dns.message
|
||||
|
||||
|
||||
def test_settings_frame_flood(ns1, named_httpsport):
|
||||
msg = dns.message.make_query(".", "SOA")
|
||||
wire = msg.to_wire()
|
||||
|
||||
with socket.create_connection((ns1.ip, named_httpsport), timeout=10) as sock:
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
ctx.set_alpn_protocols(["h2"])
|
||||
|
||||
with ctx.wrap_socket(sock, server_hostname=ns1.ip) as tls:
|
||||
config = H2Configuration(client_side=True, header_encoding="utf-8")
|
||||
conn = H2Connection(config=config)
|
||||
conn.initiate_connection()
|
||||
tls.sendall(conn.data_to_send())
|
||||
|
||||
stream_id = conn.get_next_available_stream_id()
|
||||
conn.send_headers(
|
||||
stream_id,
|
||||
[
|
||||
(":method", "POST"),
|
||||
(":path", "/dns-query"),
|
||||
(":scheme", "https"),
|
||||
(":authority", f"{ns1.ip}:{named_httpsport}"),
|
||||
("content-type", "application/dns-message"),
|
||||
("accept", "application/dns-message"),
|
||||
("content-length", str(len(wire))),
|
||||
],
|
||||
)
|
||||
conn.send_data(stream_id, wire, end_stream=True)
|
||||
tls.sendall(conn.data_to_send())
|
||||
|
||||
for i in range(4096):
|
||||
try:
|
||||
conn.update_settings(
|
||||
{
|
||||
SettingCodes.MAX_CONCURRENT_STREAMS: (i % 100) + 1,
|
||||
SettingCodes.INITIAL_WINDOW_SIZE: i + 1,
|
||||
}
|
||||
)
|
||||
tls.sendall(conn.data_to_send())
|
||||
except Exception: # pylint: disable=broad-except
|
||||
break
|
||||
|
||||
if i % 500 == 0:
|
||||
tls.settimeout(0.05)
|
||||
try:
|
||||
while (data := tls.recv(65535)) != b"":
|
||||
conn.receive_data(data)
|
||||
tls.sendall(conn.data_to_send())
|
||||
except Exception: # pylint: disable=broad-except
|
||||
pass
|
||||
|
|
@ -47,6 +47,10 @@ def servfail(message: dns.message.Message) -> None:
|
|||
rcode(message, dns.rcode.SERVFAIL)
|
||||
|
||||
|
||||
def formerr(message: dns.message.Message) -> None:
|
||||
rcode(message, dns.rcode.FORMERR)
|
||||
|
||||
|
||||
def adflag(message: dns.message.Message) -> None:
|
||||
assert (message.flags & dns.flags.AD) != 0, str(message)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
options {
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.1; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
view _bind {
|
||||
};
|
||||
|
||||
view foo {
|
||||
};
|
||||
|
||||
view bar ch {
|
||||
};
|
||||
28
bin/tests/system/nslimit_outdomain/ns1/named.conf.j2
Normal file
28
bin/tests/system/nslimit_outdomain/ns1/named.conf.j2
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 {
|
||||
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; };
|
||||
recursion no;
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type primary;
|
||||
file "root.db";
|
||||
};
|
||||
24
bin/tests/system/nslimit_outdomain/ns1/root.db
Normal file
24
bin/tests/system/nslimit_outdomain/ns1/root.db
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
; 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 owner.root-servers.nil. a.root.servers.nil. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
. NS a.root-servers.nil.
|
||||
a.root-servers.nil. A 10.53.0.1
|
||||
|
||||
tld. NS ns.tld.
|
||||
ns.tld. A 10.53.0.2
|
||||
33
bin/tests/system/nslimit_outdomain/ns2/dnshoster.tld.db
Normal file
33
bin/tests/system/nslimit_outdomain/ns2/dnshoster.tld.db
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
; 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
|
||||
dnshoster.tld. IN SOA owner.tld. ns.tld. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
|
||||
dnshoster.tld. NS ns1.dnshoster.tld.
|
||||
ns1.dnshoster.tld. A 10.53.0.5
|
||||
ns1.dnshoster.tld. A 10.53.0.6
|
||||
|
||||
dnshoster.tld. NS ns2.dnshoster.tld.
|
||||
ns2.dnshoster.tld. A 10.53.1.1
|
||||
ns2.dnshoster.tld. A 10.53.1.2
|
||||
|
||||
dnshoster.tld. NS ns3.dnshoster.tld.
|
||||
ns3.dnshoster.tld. A 10.53.2.1
|
||||
ns3.dnshoster.tld. A 10.53.2.2
|
||||
|
||||
|
||||
41
bin/tests/system/nslimit_outdomain/ns2/named.conf.j2
Normal file
41
bin/tests/system/nslimit_outdomain/ns2/named.conf.j2
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.
|
||||
*/
|
||||
|
||||
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;
|
||||
10.53.0.5;
|
||||
10.53.0.6;
|
||||
10.53.0.7;
|
||||
10.53.1.1;
|
||||
10.53.1.2;
|
||||
10.53.2.2;
|
||||
};
|
||||
recursion no;
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
zone "tld." {
|
||||
type primary;
|
||||
file "tld.db";
|
||||
};
|
||||
|
||||
zone "dnshoster.tld." {
|
||||
type primary;
|
||||
file "dnshoster.tld.db";
|
||||
};
|
||||
36
bin/tests/system/nslimit_outdomain/ns2/tld.db
Normal file
36
bin/tests/system/nslimit_outdomain/ns2/tld.db
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
; 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
|
||||
tld. IN SOA owner.tld. ns.tld. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
tld. NS ns.tld.
|
||||
ns.tld. A 10.53.0.2
|
||||
|
||||
example4.tld. NS ns.example4.tld.
|
||||
ns.example4.tld. A 10.53.0.3
|
||||
|
||||
dnshoster.tld. NS ns1.dnshoster.tld.
|
||||
ns1.dnshoster.tld. A 10.53.0.5
|
||||
ns1.dnshoster.tld. A 10.53.0.6
|
||||
|
||||
dnshoster.tld. NS ns2.dnshoster.tld.
|
||||
ns2.dnshoster.tld. A 10.53.1.1
|
||||
ns2.dnshoster.tld. A 10.53.1.2
|
||||
|
||||
dnshoster.tld. NS ns3.dnshoster.tld.
|
||||
ns3.dnshoster.tld. A 10.53.2.1
|
||||
ns3.dnshoster.tld. A 10.53.2.2
|
||||
184
bin/tests/system/nslimit_outdomain/ns3/example.tld.db
Normal file
184
bin/tests/system/nslimit_outdomain/ns3/example.tld.db
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
; 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
|
||||
example.tld. IN SOA owner.dnshoster.tld. ns.dnshoster.tld. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
|
||||
example.tld. NS ns.example.tld.
|
||||
ns.example.tld. A 10.53.0.3
|
||||
|
||||
sub.example.tld. NS ns01.sub.example.tld.
|
||||
sub.example.tld. NS ns02.sub.example.tld.
|
||||
sub.example.tld. NS ns03.sub.example.tld.
|
||||
sub.example.tld. NS ns04.sub.example.tld.
|
||||
sub.example.tld. NS ns05.sub.example.tld.
|
||||
sub.example.tld. NS ns06.sub.example.tld.
|
||||
sub.example.tld. NS ns07.sub.example.tld.
|
||||
sub.example.tld. NS ns08.sub.example.tld.
|
||||
sub.example.tld. NS ns09.sub.example.tld.
|
||||
sub.example.tld. NS ns10.sub.example.tld.
|
||||
|
||||
ns01.sub.example.tld. A 10.53.0.5
|
||||
ns01.sub.example.tld. A 10.53.0.6
|
||||
ns01.sub.example.tld. A 10.53.0.7
|
||||
ns01.sub.example.tld. A 10.53.0.8
|
||||
ns01.sub.example.tld. A 10.53.0.9
|
||||
ns01.sub.example.tld. A 10.53.0.10
|
||||
ns01.sub.example.tld. A 10.53.1.1
|
||||
ns01.sub.example.tld. A 10.53.1.2
|
||||
ns01.sub.example.tld. A 10.53.2.1
|
||||
ns01.sub.example.tld. A 10.53.0.3
|
||||
ns01.sub.example.tld. A 127.0.0.1
|
||||
ns01.sub.example.tld. A 127.0.0.2
|
||||
; Those addresses won't be used (exceed the max-delegation-servers).
|
||||
ns01.sub.example.tld. A 127.0.0.3
|
||||
ns01.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns02.sub.example.tld. A 10.53.0.5
|
||||
ns02.sub.example.tld. A 10.53.0.6
|
||||
ns02.sub.example.tld. A 10.53.0.7
|
||||
ns02.sub.example.tld. A 10.53.0.8
|
||||
ns02.sub.example.tld. A 10.53.0.9
|
||||
ns02.sub.example.tld. A 10.53.0.10
|
||||
ns02.sub.example.tld. A 10.53.1.1
|
||||
ns02.sub.example.tld. A 10.53.1.2
|
||||
ns02.sub.example.tld. A 10.53.2.1
|
||||
ns02.sub.example.tld. A 10.53.0.3
|
||||
ns02.sub.example.tld. A 127.0.0.1
|
||||
ns02.sub.example.tld. A 127.0.0.2
|
||||
ns02.sub.example.tld. A 127.0.0.3
|
||||
ns02.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns03.sub.example.tld. A 10.53.0.5
|
||||
ns03.sub.example.tld. A 10.53.0.6
|
||||
ns03.sub.example.tld. A 10.53.0.7
|
||||
ns03.sub.example.tld. A 10.53.0.8
|
||||
ns03.sub.example.tld. A 10.53.0.9
|
||||
ns03.sub.example.tld. A 10.53.0.10
|
||||
ns03.sub.example.tld. A 10.53.1.1
|
||||
ns03.sub.example.tld. A 10.53.1.2
|
||||
ns03.sub.example.tld. A 10.53.2.1
|
||||
ns03.sub.example.tld. A 10.53.0.3
|
||||
ns03.sub.example.tld. A 127.0.0.1
|
||||
ns03.sub.example.tld. A 127.0.0.2
|
||||
ns03.sub.example.tld. A 127.0.0.3
|
||||
ns03.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns04.sub.example.tld. A 10.53.0.5
|
||||
ns04.sub.example.tld. A 10.53.0.6
|
||||
ns04.sub.example.tld. A 10.53.0.7
|
||||
ns04.sub.example.tld. A 10.53.0.8
|
||||
ns04.sub.example.tld. A 10.53.0.9
|
||||
ns04.sub.example.tld. A 10.53.0.10
|
||||
ns04.sub.example.tld. A 10.53.1.1
|
||||
ns04.sub.example.tld. A 10.53.1.2
|
||||
ns04.sub.example.tld. A 10.53.2.1
|
||||
ns04.sub.example.tld. A 10.53.0.3
|
||||
ns04.sub.example.tld. A 127.0.0.1
|
||||
ns04.sub.example.tld. A 127.0.0.2
|
||||
ns04.sub.example.tld. A 127.0.0.3
|
||||
ns04.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns05.sub.example.tld. A 10.53.0.5
|
||||
ns05.sub.example.tld. A 10.53.0.6
|
||||
ns05.sub.example.tld. A 10.53.0.7
|
||||
ns05.sub.example.tld. A 10.53.0.8
|
||||
ns05.sub.example.tld. A 10.53.0.9
|
||||
ns05.sub.example.tld. A 10.53.0.10
|
||||
ns05.sub.example.tld. A 10.53.1.1
|
||||
ns05.sub.example.tld. A 10.53.1.2
|
||||
ns05.sub.example.tld. A 10.53.2.1
|
||||
ns05.sub.example.tld. A 10.53.0.3
|
||||
ns05.sub.example.tld. A 127.0.0.1
|
||||
ns05.sub.example.tld. A 127.0.0.2
|
||||
ns05.sub.example.tld. A 127.0.0.3
|
||||
ns05.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns06.sub.example.tld. A 10.53.0.5
|
||||
ns06.sub.example.tld. A 10.53.0.6
|
||||
ns06.sub.example.tld. A 10.53.0.7
|
||||
ns06.sub.example.tld. A 10.53.0.8
|
||||
ns06.sub.example.tld. A 10.53.0.9
|
||||
ns06.sub.example.tld. A 10.53.0.10
|
||||
ns06.sub.example.tld. A 10.53.1.1
|
||||
ns06.sub.example.tld. A 10.53.1.2
|
||||
ns06.sub.example.tld. A 10.53.2.1
|
||||
ns06.sub.example.tld. A 10.53.0.3
|
||||
ns06.sub.example.tld. A 127.0.0.1
|
||||
ns06.sub.example.tld. A 127.0.0.2
|
||||
ns06.sub.example.tld. A 127.0.0.3
|
||||
ns06.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns07.sub.example.tld. A 10.53.0.5
|
||||
ns07.sub.example.tld. A 10.53.0.6
|
||||
ns07.sub.example.tld. A 10.53.0.7
|
||||
ns07.sub.example.tld. A 10.53.0.8
|
||||
ns07.sub.example.tld. A 10.53.0.9
|
||||
ns07.sub.example.tld. A 10.53.0.10
|
||||
ns07.sub.example.tld. A 10.53.1.1
|
||||
ns07.sub.example.tld. A 10.53.1.2
|
||||
ns07.sub.example.tld. A 10.53.2.1
|
||||
ns07.sub.example.tld. A 10.53.0.3
|
||||
ns07.sub.example.tld. A 127.0.0.1
|
||||
ns07.sub.example.tld. A 127.0.0.2
|
||||
ns07.sub.example.tld. A 127.0.0.3
|
||||
ns07.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns08.sub.example.tld. A 10.53.0.5
|
||||
ns08.sub.example.tld. A 10.53.0.6
|
||||
ns08.sub.example.tld. A 10.53.0.7
|
||||
ns08.sub.example.tld. A 10.53.0.8
|
||||
ns08.sub.example.tld. A 10.53.0.9
|
||||
ns08.sub.example.tld. A 10.53.0.10
|
||||
ns08.sub.example.tld. A 10.53.1.1
|
||||
ns08.sub.example.tld. A 10.53.1.2
|
||||
ns08.sub.example.tld. A 10.53.2.1
|
||||
ns08.sub.example.tld. A 10.53.0.3
|
||||
ns08.sub.example.tld. A 127.0.0.1
|
||||
ns08.sub.example.tld. A 127.0.0.2
|
||||
ns08.sub.example.tld. A 127.0.0.3
|
||||
ns08.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns09.sub.example.tld. A 10.53.0.5
|
||||
ns09.sub.example.tld. A 10.53.0.6
|
||||
ns09.sub.example.tld. A 10.53.0.7
|
||||
ns09.sub.example.tld. A 10.53.0.8
|
||||
ns09.sub.example.tld. A 10.53.0.9
|
||||
ns09.sub.example.tld. A 10.53.0.10
|
||||
ns09.sub.example.tld. A 10.53.1.1
|
||||
ns09.sub.example.tld. A 10.53.1.2
|
||||
ns09.sub.example.tld. A 10.53.2.1
|
||||
ns09.sub.example.tld. A 10.53.0.3
|
||||
ns09.sub.example.tld. A 127.0.0.1
|
||||
ns09.sub.example.tld. A 127.0.0.2
|
||||
ns09.sub.example.tld. A 127.0.0.3
|
||||
ns09.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns10.sub.example.tld. A 10.53.0.5
|
||||
ns10.sub.example.tld. A 10.53.0.6
|
||||
ns10.sub.example.tld. A 10.53.0.7
|
||||
ns10.sub.example.tld. A 10.53.0.8
|
||||
ns10.sub.example.tld. A 10.53.0.9
|
||||
ns10.sub.example.tld. A 10.53.0.10
|
||||
ns10.sub.example.tld. A 10.53.1.1
|
||||
ns10.sub.example.tld. A 10.53.1.2
|
||||
ns10.sub.example.tld. A 10.53.2.1
|
||||
ns10.sub.example.tld. A 10.53.0.3
|
||||
ns10.sub.example.tld. A 127.0.0.1
|
||||
ns10.sub.example.tld. A 127.0.0.2
|
||||
ns10.sub.example.tld. A 127.0.0.3
|
||||
ns10.sub.example.tld. A 127.0.0.4
|
||||
24
bin/tests/system/nslimit_outdomain/ns3/example4.tld.db
Normal file
24
bin/tests/system/nslimit_outdomain/ns3/example4.tld.db
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
; 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
|
||||
example4.tld. IN SOA owner.dnshoster.tld. ns.dnshoster.tld. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
|
||||
example4.tld. NS ns.example4.tld.
|
||||
ns.example4.tld. A 10.53.0.3
|
||||
sub.example4.tld. NS ns1.dnshoster.tld.
|
||||
sub.example4.tld. NS ns2.dnshoster.tld.
|
||||
30
bin/tests/system/nslimit_outdomain/ns3/named.conf.j2
Normal file
30
bin/tests/system/nslimit_outdomain/ns3/named.conf.j2
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 {
|
||||
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;
|
||||
};
|
||||
recursion no;
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
zone "example4.tld." {
|
||||
type primary;
|
||||
file "example4.tld.db";
|
||||
};
|
||||
1
bin/tests/system/nslimit_outdomain/ns4/named.args.j2
Normal file
1
bin/tests/system/nslimit_outdomain/ns4/named.args.j2
Normal file
|
|
@ -0,0 +1 @@
|
|||
-D selfpointedglue-ns4 -m record -c named.conf -d 99 -g -T maxcachesize=2097152 -4
|
||||
59
bin/tests/system/nslimit_outdomain/ns4/named.conf.j2
Normal file
59
bin/tests/system/nslimit_outdomain/ns4/named.conf.j2
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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 maxdelegationservers = maxdelegationservers | default(None) %}
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.4;
|
||||
notify-source 10.53.0.4;
|
||||
transfer-source 10.53.0.4;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.4; };
|
||||
recursion yes;
|
||||
dnssec-validation no;
|
||||
dnstap { resolver query; };
|
||||
dnstap-output file "dnstap.out";
|
||||
{% if maxdelegationservers %}
|
||||
@maxdelegationservers@
|
||||
{% endif %}
|
||||
};
|
||||
|
||||
/*
|
||||
* Forcing TCP ensures that ADDITIONAL won't be truncated (responses won't have
|
||||
* the TC flag, hence the resolver won't retry using TCP by itself, see
|
||||
* https://datatracker.ietf.org/doc/html/rfc2181#section-9)
|
||||
*/
|
||||
server 10.53.0.3 { tcp-only true; };
|
||||
server 10.53.0.5 { tcp-only true; };
|
||||
server 10.53.0.6 { tcp-only true; };
|
||||
server 10.53.0.7 { tcp-only true; };
|
||||
server 10.53.0.8 { tcp-only true; };
|
||||
server 10.53.0.9 { tcp-only true; };
|
||||
server 10.53.0.10 { tcp-only true; };
|
||||
server 10.53.1.1 { tcp-only true; };
|
||||
server 10.53.1.2 { tcp-only true; };
|
||||
server 10.53.2.1 { tcp-only true; };
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "root.hint";
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
14
bin/tests/system/nslimit_outdomain/ns4/root.hint
Normal file
14
bin/tests/system/nslimit_outdomain/ns4/root.hint
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
; 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 999999
|
||||
. IN NS a.root-servers.nil.
|
||||
a.root-servers.nil. IN A 10.53.0.1
|
||||
120
bin/tests/system/nslimit_outdomain/tests_nslimit_outdomain.py
Normal file
120
bin/tests/system/nslimit_outdomain/tests_nslimit_outdomain.py
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
# 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 os
|
||||
|
||||
import isctest
|
||||
import isctest.mark
|
||||
|
||||
pytestmark = [isctest.mark.with_dnstap]
|
||||
|
||||
|
||||
def line_to_ips_and_queries(line):
|
||||
# dnstap-read output line example
|
||||
# 05-Feb-2026 11:00:57.853 RQ 10.53.0.4:38507 -> 10.53.0.3:22047 TCP 56b sub.example.tld/IN/NS
|
||||
_, _, _, _, _, dst, _, _, query = line.split(" ", 9)
|
||||
ip, _ = dst.split(":", 1)
|
||||
return (ip, query)
|
||||
|
||||
|
||||
def extract_dnstap(ns, expectedlen):
|
||||
ns.rndc("dnstap -roll 1")
|
||||
path = os.path.join(ns.identifier, "dnstap.out.0")
|
||||
dnstapread = isctest.run.cmd(
|
||||
[isctest.vars.ALL["DNSTAPREAD"], path],
|
||||
)
|
||||
|
||||
lines = dnstapread.out.splitlines()
|
||||
assert expectedlen == len(lines)
|
||||
return list(map(line_to_ips_and_queries, lines))
|
||||
|
||||
|
||||
# Because DNSTAP doesn't have ordering guarantee, the order doesn't matter here.
|
||||
def has_ip_and_query(expected_ips_and_queries, ips_and_queries):
|
||||
found_count = 0
|
||||
for expected_ip, expected_query in expected_ips_and_queries:
|
||||
for ip, query in ips_and_queries:
|
||||
if ip == expected_ip and query == expected_query:
|
||||
found_count += 1
|
||||
break
|
||||
return found_count == len(expected_ips_and_queries)
|
||||
|
||||
|
||||
# Test the max-delegation-servers limit on flow where ADB attempt
|
||||
# a lookup from an NS name rather than directly with the NS addresses.
|
||||
def test_nslimit_outdomain(ns4, templates):
|
||||
templates.render(
|
||||
"ns4/named.conf", {"maxdelegationservers": "max-delegation-servers 2;"}
|
||||
)
|
||||
with ns4.watch_log_from_here() as watcher:
|
||||
ns4.rndc("flush")
|
||||
ns4.rndc("reload")
|
||||
watcher.wait_for_line("running")
|
||||
|
||||
msg = isctest.query.create("sub.example4.tld.", "A")
|
||||
res = isctest.query.tcp(msg, ns4.ip)
|
||||
isctest.check.servfail(res)
|
||||
|
||||
ips_and_queries = extract_dnstap(ns4, 9)
|
||||
|
||||
# The resolver first resolve example4.tld. and gets the NS for sub.example.tld.
|
||||
# which is out-domain. So it resolves it.
|
||||
assert has_ip_and_query(
|
||||
[
|
||||
("10.53.0.1", "./IN/NS"),
|
||||
("10.53.0.1", "tld/IN/NS"),
|
||||
("10.53.0.2", "example4.tld/IN/NS"),
|
||||
("10.53.0.3", "sub.example4.tld/IN/A"),
|
||||
("10.53.0.2", "dnshoster.tld/IN/NS"),
|
||||
],
|
||||
ips_and_queries,
|
||||
)
|
||||
|
||||
# Then, because max-delegation-servers is 2, the resolver will try to use either
|
||||
# the NS ns1.dnshoster.tld or the NS ns2.dnshoster.tld. or the NS ns3.dnshoster.tld.
|
||||
#
|
||||
# What is important here, is that the NS of sub.example4.tld are _names_, so
|
||||
# this is going through the dns_adb_createfind() flow, and it does stop after 2
|
||||
# queries (on the two IPs of one of the NS server above) and _won't_ try another
|
||||
# NS name (becuse max-delegation-servers will be reached).
|
||||
#
|
||||
# Note that the sum of all the queries checked here is 8 and not 9. This is because
|
||||
# when dnshoster.tld has been resolved, the resolver resolved 2 names. But the IPs
|
||||
# of only one of the two names has been used. (This is checked below).
|
||||
|
||||
used_ns1 = has_ip_and_query(
|
||||
[
|
||||
("10.53.0.2", "ns1.dnshoster.tld/IN/A"),
|
||||
("10.53.0.5", "sub.example4.tld/IN/A"),
|
||||
("10.53.0.6", "sub.example4.tld/IN/A"),
|
||||
],
|
||||
ips_and_queries,
|
||||
)
|
||||
|
||||
used_ns2 = has_ip_and_query(
|
||||
[
|
||||
("10.53.0.2", "ns2.dnshoster.tld/IN/A"),
|
||||
("10.53.1.1", "sub.example4.tld/IN/A"),
|
||||
("10.53.1.2", "sub.example4.tld/IN/A"),
|
||||
],
|
||||
ips_and_queries,
|
||||
)
|
||||
|
||||
used_ns3 = has_ip_and_query(
|
||||
[
|
||||
("10.53.0.2", "ns3.dnshoster.tld/IN/A"),
|
||||
("10.53.2.1", "sub.example4.tld/IN/A"),
|
||||
("10.53.2.2", "sub.example4.tld/IN/A"),
|
||||
],
|
||||
ips_and_queries,
|
||||
)
|
||||
|
||||
assert used_ns1 or used_ns2 or used_ns3
|
||||
|
|
@ -35,6 +35,7 @@ update.nil IN SOA ns1.example.nil. hostmaster.example.nil. (
|
|||
3600 ; minimum (1 hour)
|
||||
)
|
||||
update.nil. NS ns1.update.nil.
|
||||
update.nil. KX 0 .
|
||||
ns1.update.nil. A 10.53.0.2
|
||||
ns2.update.nil. AAAA ::1
|
||||
EOF
|
||||
|
|
|
|||
|
|
@ -485,8 +485,10 @@ grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1
|
|||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "check that TYPE=0 update is handled ($n)"
|
||||
nextpart ns1/named.run >/dev/null
|
||||
echo "a0e4280000010000000100000000060001c00c000000fe000000000000" \
|
||||
| $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp >/dev/null || ret=1
|
||||
| $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp -b >/dev/null || ret=1
|
||||
wait_for_log 2 "message parsing failed: FORMERR" ns1/named.run || ret=1
|
||||
$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1
|
||||
grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1
|
||||
[ $ret = 0 ] || {
|
||||
|
|
@ -497,20 +499,10 @@ grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1
|
|||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "check that TYPE=0 additional data is handled ($n)"
|
||||
nextpart ns1/named.run >/dev/null
|
||||
echo "a0e4280000010000000000010000060001c00c000000fe000000000000" \
|
||||
| $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp >/dev/null || ret=1
|
||||
$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1
|
||||
grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1
|
||||
[ $ret = 0 ] || {
|
||||
echo_i "failed"
|
||||
status=1
|
||||
}
|
||||
|
||||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "check that update to undefined class is handled ($n)"
|
||||
echo "a0e4280000010001000000000000060101c00c000000fe000000000000" \
|
||||
| $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp >/dev/null || ret=1
|
||||
| $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp -b >/dev/null || ret=1
|
||||
wait_for_log 2 "message parsing failed: FORMERR" ns1/named.run || ret=1
|
||||
$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1
|
||||
grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1
|
||||
[ $ret = 0 ] || {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
# -p <port>: specify port
|
||||
# -t <protocol>: specify UDP or TCP
|
||||
# -r <num>: send packet <num> times
|
||||
# -b: blocking io
|
||||
# -d: dump response packets
|
||||
#
|
||||
# If not specified, address defaults to 127.0.0.1, port to 53, protocol
|
||||
|
|
@ -51,6 +52,8 @@ use strict;
|
|||
use Getopt::Std;
|
||||
use IO::File;
|
||||
use IO::Socket;
|
||||
use Net::DNS;
|
||||
use Net::DNS::Packet;
|
||||
|
||||
sub usage {
|
||||
print ("Usage: packet.pl [-a address] [-d] [-p port] [-t (tcp|udp)] [-r <repeats>] [file]\n");
|
||||
|
|
@ -61,8 +64,6 @@ my $sock;
|
|||
my $proto;
|
||||
|
||||
sub dumppacket {
|
||||
use Net::DNS;
|
||||
use Net::DNS::Packet;
|
||||
|
||||
my $rin;
|
||||
my $rout;
|
||||
|
|
@ -96,7 +97,7 @@ sub dumppacket {
|
|||
}
|
||||
|
||||
my %options={};
|
||||
getopts("a:dp:t:r:", \%options);
|
||||
getopts("a:bdp:t:r:", \%options);
|
||||
|
||||
my $addr = "127.0.0.1";
|
||||
$addr = $options{a} if defined $options{a};
|
||||
|
|
@ -111,6 +112,8 @@ usage if ($proto !~ /^(udp|tcp)$/);
|
|||
my $repeats = 1;
|
||||
$repeats = $options{r} if defined $options{r};
|
||||
|
||||
my $blocking = defined $options{b} ? 1 : 0;
|
||||
|
||||
my $file = "STDIN";
|
||||
if (@ARGV >= 1) {
|
||||
my $filename = shift @ARGV;
|
||||
|
|
@ -132,8 +135,22 @@ my $len = length $data;
|
|||
my $output = unpack("H*", $data);
|
||||
print ("sending $repeats time(s): $output\n");
|
||||
|
||||
|
||||
if (defined $options{d}) {
|
||||
my $request;
|
||||
if ($Net::DNS::VERSION > 0.68) {
|
||||
$request = new Net::DNS::Packet(\$data, 0);
|
||||
$@ and die $@;
|
||||
} else {
|
||||
my $err;
|
||||
($request, $err) = new Net::DNS::Packet(\$data, 0);
|
||||
$err and die $err;
|
||||
}
|
||||
$request->print;
|
||||
}
|
||||
|
||||
$sock = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port,
|
||||
Blocking => 0,
|
||||
Blocking => $blocking,
|
||||
Proto => $proto,) or die "$!";
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
|
|
|
|||
132
bin/tests/system/resend_loop/ans3/ans.py
Normal file
132
bin/tests/system/resend_loop/ans3/ans.py
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
# 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.
|
||||
|
||||
from collections.abc import AsyncGenerator
|
||||
|
||||
import dns.edns
|
||||
import dns.name
|
||||
import dns.rcode
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
import dns.rrset
|
||||
|
||||
from isctest.asyncserver import (
|
||||
AsyncDnsServer,
|
||||
DnsResponseSend,
|
||||
QnameHandler,
|
||||
QueryContext,
|
||||
ResponseHandler,
|
||||
StaticResponseHandler,
|
||||
)
|
||||
|
||||
|
||||
def _get_cookie(qctx: QueryContext):
|
||||
for o in qctx.query.options:
|
||||
if o.otype == dns.edns.OptionType.COOKIE:
|
||||
cookie = o
|
||||
try:
|
||||
if len(cookie.server) == 0:
|
||||
cookie.server = b"\x11\x22\x33\x44\x55\x66\x77\x88"
|
||||
except AttributeError: # dnspython<2.7.0 compat
|
||||
if len(o.data) == 8:
|
||||
cookie.data *= 2
|
||||
|
||||
return cookie
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def rrset(
|
||||
qname: dns.name.Name | str,
|
||||
rtype: dns.rdatatype.RdataType,
|
||||
rdata: str,
|
||||
ttl: int = 300,
|
||||
) -> dns.rrset.RRset:
|
||||
return dns.rrset.from_text(qname, ttl, dns.rdataclass.IN, rtype, rdata)
|
||||
|
||||
|
||||
class RootNSHandler(QnameHandler, StaticResponseHandler):
|
||||
qnames = ["."]
|
||||
answer = [
|
||||
rrset(".", dns.rdatatype.NS, "a.root-servers.nil."),
|
||||
]
|
||||
additional = [
|
||||
rrset("a.root-servers.nil.", dns.rdatatype.A, "10.53.0.3"),
|
||||
]
|
||||
|
||||
|
||||
class ExampleNSHandler(QnameHandler, StaticResponseHandler):
|
||||
qnames = ["example."]
|
||||
answer = [
|
||||
rrset("example.", dns.rdatatype.NS, "ns.example."),
|
||||
]
|
||||
additional = [
|
||||
rrset("ns.example.", dns.rdatatype.A, "10.53.0.3"),
|
||||
]
|
||||
|
||||
|
||||
class CookieHandler(ResponseHandler):
|
||||
def match(self, qctx: QueryContext) -> bool:
|
||||
example = dns.name.from_text("example")
|
||||
return qctx.qname.is_subdomain(example)
|
||||
|
||||
async def get_responses(
|
||||
self, qctx: QueryContext
|
||||
) -> AsyncGenerator[DnsResponseSend, None]:
|
||||
|
||||
qctx.prepare_new_response()
|
||||
|
||||
# Check for client cookie
|
||||
cookie = _get_cookie(qctx)
|
||||
|
||||
# If missing cookie entirely, just return SERVFAIL
|
||||
if cookie is None:
|
||||
qctx.response.set_rcode(dns.rcode.SERVFAIL)
|
||||
yield DnsResponseSend(qctx.response, authoritative=True)
|
||||
|
||||
# If there is a client cookie, mock BADCOOKIE to trigger
|
||||
# the resend loop logic.
|
||||
qctx.response.use_edns(options=[cookie])
|
||||
qctx.response.set_rcode(dns.rcode.BADCOOKIE)
|
||||
yield DnsResponseSend(qctx.response, authoritative=True)
|
||||
|
||||
|
||||
class NoErrorHandler(ResponseHandler):
|
||||
"""
|
||||
If the query is NOT a subdomain of example, respond with standard NOERROR empty answer
|
||||
"""
|
||||
|
||||
async def get_responses(
|
||||
self, qctx: QueryContext
|
||||
) -> AsyncGenerator[DnsResponseSend, None]:
|
||||
|
||||
qctx.prepare_new_response()
|
||||
qctx.response.set_rcode(dns.rcode.NOERROR)
|
||||
yield DnsResponseSend(qctx.response, authoritative=True)
|
||||
|
||||
|
||||
def resend_server() -> AsyncDnsServer:
|
||||
server = AsyncDnsServer(default_aa=True, default_rcode=dns.rcode.NOERROR)
|
||||
server.install_response_handlers(
|
||||
RootNSHandler(),
|
||||
ExampleNSHandler(),
|
||||
CookieHandler(),
|
||||
NoErrorHandler(),
|
||||
)
|
||||
return server
|
||||
|
||||
|
||||
def main() -> None:
|
||||
resend_server().run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
17
bin/tests/system/resend_loop/ns4/named.conf.j2
Normal file
17
bin/tests/system/resend_loop/ns4/named.conf.j2
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
options {
|
||||
query-source address 10.53.0.4;
|
||||
notify-source 10.53.0.4;
|
||||
transfer-source 10.53.0.4;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.4; };
|
||||
listen-on-v6 { none; };
|
||||
query-source-v6 none;
|
||||
recursion yes;
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
zone "." IN {
|
||||
type hint;
|
||||
file "root.hint";
|
||||
};
|
||||
14
bin/tests/system/resend_loop/ns4/root.hint
Normal file
14
bin/tests/system/resend_loop/ns4/root.hint
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
; 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 999999
|
||||
. IN NS a.root-servers.nil.
|
||||
a.root-servers.nil. IN A 10.53.0.3
|
||||
85
bin/tests/system/resend_loop/tests_resend_loop.py
Normal file
85
bin/tests/system/resend_loop/tests_resend_loop.py
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# 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.
|
||||
|
||||
from re import compile as Re
|
||||
|
||||
import dns.message
|
||||
|
||||
import isctest
|
||||
|
||||
|
||||
# This test verifies the query pattern when the upstream behaves badly.
|
||||
# In this scenario, the upstream server (ans3) always responds with a
|
||||
# BADCOOKIE error for queries within the "example" zone, even on TCP.
|
||||
# The resolver (ns4), should not resend the same queries over and over
|
||||
# again, up to the max-query-count threshold. Instead, the expected
|
||||
# pattern is:
|
||||
# 1. Priming query, getting the NS for .
|
||||
# 2. Getting the NS for example.
|
||||
# 3. Trying to resolve test.example.
|
||||
# 4. Trying again, but now with the server cookie.
|
||||
# 5. Trying again, now over TCP.
|
||||
#
|
||||
# This means we expect 5 recursion queries trying to resolve test.example.
|
||||
def test_resend_loop_badcookie(ns4):
|
||||
sending_packet = Re("sending packet from 10.53.0.4#[0-9]+ to 10.53.0.3#[0-9]+")
|
||||
received_packet = Re("received packet from 10.53.0.3#[0-9]+ to 10.53.0.4#[0-9]+")
|
||||
|
||||
log_sequence = [
|
||||
# 1. Priming query, getting the NS for .
|
||||
sending_packet,
|
||||
Re("COOKIE: [0-9a-z]{16}$"),
|
||||
Re(".\\s+IN\\s+NS"),
|
||||
# 2. Getting the NS for example.
|
||||
sending_packet,
|
||||
Re("COOKIE: [0-9a-z]{16}$"),
|
||||
Re("example.\\s+IN\\s+NS"),
|
||||
# 3. Trying to resolve test.example.
|
||||
sending_packet,
|
||||
Re("COOKIE: [0-9a-z]{16}$"),
|
||||
Re("test.example.\\s+IN\\s+A"),
|
||||
# Get the first BADCOOKIE error.
|
||||
"UDP response",
|
||||
received_packet,
|
||||
"BADCOOKIE",
|
||||
Re("COOKIE: [0-9a-z]{16}1122334455667788"),
|
||||
Re("test.example.\\s+IN\\s+A"),
|
||||
# 4. Trying again, but now with the server cookie.
|
||||
sending_packet,
|
||||
Re("test.example.\\s+IN\\s+A"),
|
||||
# Get BADCOOKIE error again.
|
||||
"UDP response",
|
||||
received_packet,
|
||||
"BADCOOKIE",
|
||||
Re("COOKIE: [0-9a-z]{16}1122334455667788"),
|
||||
Re("test.example.\\s+IN\\s+A"),
|
||||
# 5. Trying again, now over TCP.
|
||||
sending_packet,
|
||||
Re("test.example.\\s+IN\\s+A"),
|
||||
# Fails and give up.
|
||||
"TCP response",
|
||||
received_packet,
|
||||
"BADCOOKIE",
|
||||
Re("COOKIE: [0-9a-z]{16}1122334455667788"),
|
||||
Re("test.example.\\s+IN\\s+A"),
|
||||
]
|
||||
|
||||
msg = dns.message.make_query("test.example", "A")
|
||||
with ns4.watch_log_from_here() as watcher:
|
||||
res = isctest.query.udp(msg, ns4.ip)
|
||||
watcher.wait_for_sequence(log_sequence)
|
||||
|
||||
assert len(ns4.log.grep(sending_packet)) == 5
|
||||
|
||||
isctest.check.servfail(res)
|
||||
|
||||
prohibited_log = "query failed (timed out) for test.example/IN/A"
|
||||
assert prohibited_log not in ns4.log
|
||||
|
|
@ -783,10 +783,12 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
|
|||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking NXDOMAIN is returned when querying non existing domain in CH class ($n)"
|
||||
echo_i "checking REFUSED is returned when querying non existing domain in CH class ($n)"
|
||||
ret=0
|
||||
dig_with_opts @10.53.0.1 id.hostname txt ch >dig.ns1.out.${n} || ret=1
|
||||
grep "status: NXDOMAIN" dig.ns1.out.${n} >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.1 hostname.chaostest txt ch >dig.ns1.out.1.${n} || ret=1
|
||||
grep "status: NOERROR" dig.ns1.out.1.${n} >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.1 id.hostname txt ch >dig.ns1.out.2.${n} || ret=1
|
||||
grep "status: REFUSED" dig.ns1.out.2.${n} >/dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
|
|
|
|||
28
bin/tests/system/selfpointedglue/ns1/named.conf.j2
Normal file
28
bin/tests/system/selfpointedglue/ns1/named.conf.j2
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 {
|
||||
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; };
|
||||
recursion no;
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type primary;
|
||||
file "root.db";
|
||||
};
|
||||
24
bin/tests/system/selfpointedglue/ns1/root.db
Normal file
24
bin/tests/system/selfpointedglue/ns1/root.db
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
; 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 owner.root-servers.nil. a.root.servers.nil. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
. NS a.root-servers.nil.
|
||||
a.root-servers.nil. A 10.53.0.1
|
||||
|
||||
tld. NS ns.tld.
|
||||
ns.tld. A 10.53.0.2
|
||||
28
bin/tests/system/selfpointedglue/ns2/named.conf.j2
Normal file
28
bin/tests/system/selfpointedglue/ns2/named.conf.j2
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 {
|
||||
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; };
|
||||
recursion no;
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
zone "tld." {
|
||||
type primary;
|
||||
file "tld.db";
|
||||
};
|
||||
30
bin/tests/system/selfpointedglue/ns2/tld.db
Normal file
30
bin/tests/system/selfpointedglue/ns2/tld.db
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
; 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
|
||||
tld. IN SOA owner.tld. ns.tld. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
tld. NS ns.tld.
|
||||
ns.tld. A 10.53.0.2
|
||||
|
||||
example.tld. NS ns.example.tld.
|
||||
ns.example.tld. A 10.53.0.3
|
||||
|
||||
example2.tld. NS ns.example2.tld.
|
||||
ns.example2.tld. A 10.53.0.3
|
||||
|
||||
example3.tld. NS ns.example3.tld.
|
||||
ns.example3.tld. A 10.53.0.3
|
||||
184
bin/tests/system/selfpointedglue/ns3/example.tld.db
Normal file
184
bin/tests/system/selfpointedglue/ns3/example.tld.db
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
; 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
|
||||
example.tld. IN SOA owner.dnshoster.tld. ns.dnshoster.tld. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
|
||||
example.tld. NS ns.example.tld.
|
||||
ns.example.tld. A 10.53.0.3
|
||||
|
||||
sub.example.tld. NS ns01.sub.example.tld.
|
||||
sub.example.tld. NS ns02.sub.example.tld.
|
||||
sub.example.tld. NS ns03.sub.example.tld.
|
||||
sub.example.tld. NS ns04.sub.example.tld.
|
||||
sub.example.tld. NS ns05.sub.example.tld.
|
||||
sub.example.tld. NS ns06.sub.example.tld.
|
||||
sub.example.tld. NS ns07.sub.example.tld.
|
||||
sub.example.tld. NS ns08.sub.example.tld.
|
||||
sub.example.tld. NS ns09.sub.example.tld.
|
||||
sub.example.tld. NS ns10.sub.example.tld.
|
||||
|
||||
ns01.sub.example.tld. A 10.53.0.5
|
||||
ns01.sub.example.tld. A 10.53.0.6
|
||||
ns01.sub.example.tld. A 10.53.0.7
|
||||
ns01.sub.example.tld. A 10.53.0.8
|
||||
ns01.sub.example.tld. A 10.53.0.9
|
||||
ns01.sub.example.tld. A 10.53.0.10
|
||||
ns01.sub.example.tld. A 10.53.1.1
|
||||
ns01.sub.example.tld. A 10.53.1.2
|
||||
ns01.sub.example.tld. A 10.53.2.1
|
||||
ns01.sub.example.tld. A 10.53.0.3
|
||||
ns01.sub.example.tld. A 127.0.0.1
|
||||
ns01.sub.example.tld. A 127.0.0.2
|
||||
; Those addresses won't be used (exceed the max-delegation-servers).
|
||||
ns01.sub.example.tld. A 127.0.0.3
|
||||
ns01.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns02.sub.example.tld. A 10.53.0.5
|
||||
ns02.sub.example.tld. A 10.53.0.6
|
||||
ns02.sub.example.tld. A 10.53.0.7
|
||||
ns02.sub.example.tld. A 10.53.0.8
|
||||
ns02.sub.example.tld. A 10.53.0.9
|
||||
ns02.sub.example.tld. A 10.53.0.10
|
||||
ns02.sub.example.tld. A 10.53.1.1
|
||||
ns02.sub.example.tld. A 10.53.1.2
|
||||
ns02.sub.example.tld. A 10.53.2.1
|
||||
ns02.sub.example.tld. A 10.53.0.3
|
||||
ns02.sub.example.tld. A 127.0.0.1
|
||||
ns02.sub.example.tld. A 127.0.0.2
|
||||
ns02.sub.example.tld. A 127.0.0.3
|
||||
ns02.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns03.sub.example.tld. A 10.53.0.5
|
||||
ns03.sub.example.tld. A 10.53.0.6
|
||||
ns03.sub.example.tld. A 10.53.0.7
|
||||
ns03.sub.example.tld. A 10.53.0.8
|
||||
ns03.sub.example.tld. A 10.53.0.9
|
||||
ns03.sub.example.tld. A 10.53.0.10
|
||||
ns03.sub.example.tld. A 10.53.1.1
|
||||
ns03.sub.example.tld. A 10.53.1.2
|
||||
ns03.sub.example.tld. A 10.53.2.1
|
||||
ns03.sub.example.tld. A 10.53.0.3
|
||||
ns03.sub.example.tld. A 127.0.0.1
|
||||
ns03.sub.example.tld. A 127.0.0.2
|
||||
ns03.sub.example.tld. A 127.0.0.3
|
||||
ns03.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns04.sub.example.tld. A 10.53.0.5
|
||||
ns04.sub.example.tld. A 10.53.0.6
|
||||
ns04.sub.example.tld. A 10.53.0.7
|
||||
ns04.sub.example.tld. A 10.53.0.8
|
||||
ns04.sub.example.tld. A 10.53.0.9
|
||||
ns04.sub.example.tld. A 10.53.0.10
|
||||
ns04.sub.example.tld. A 10.53.1.1
|
||||
ns04.sub.example.tld. A 10.53.1.2
|
||||
ns04.sub.example.tld. A 10.53.2.1
|
||||
ns04.sub.example.tld. A 10.53.0.3
|
||||
ns04.sub.example.tld. A 127.0.0.1
|
||||
ns04.sub.example.tld. A 127.0.0.2
|
||||
ns04.sub.example.tld. A 127.0.0.3
|
||||
ns04.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns05.sub.example.tld. A 10.53.0.5
|
||||
ns05.sub.example.tld. A 10.53.0.6
|
||||
ns05.sub.example.tld. A 10.53.0.7
|
||||
ns05.sub.example.tld. A 10.53.0.8
|
||||
ns05.sub.example.tld. A 10.53.0.9
|
||||
ns05.sub.example.tld. A 10.53.0.10
|
||||
ns05.sub.example.tld. A 10.53.1.1
|
||||
ns05.sub.example.tld. A 10.53.1.2
|
||||
ns05.sub.example.tld. A 10.53.2.1
|
||||
ns05.sub.example.tld. A 10.53.0.3
|
||||
ns05.sub.example.tld. A 127.0.0.1
|
||||
ns05.sub.example.tld. A 127.0.0.2
|
||||
ns05.sub.example.tld. A 127.0.0.3
|
||||
ns05.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns06.sub.example.tld. A 10.53.0.5
|
||||
ns06.sub.example.tld. A 10.53.0.6
|
||||
ns06.sub.example.tld. A 10.53.0.7
|
||||
ns06.sub.example.tld. A 10.53.0.8
|
||||
ns06.sub.example.tld. A 10.53.0.9
|
||||
ns06.sub.example.tld. A 10.53.0.10
|
||||
ns06.sub.example.tld. A 10.53.1.1
|
||||
ns06.sub.example.tld. A 10.53.1.2
|
||||
ns06.sub.example.tld. A 10.53.2.1
|
||||
ns06.sub.example.tld. A 10.53.0.3
|
||||
ns06.sub.example.tld. A 127.0.0.1
|
||||
ns06.sub.example.tld. A 127.0.0.2
|
||||
ns06.sub.example.tld. A 127.0.0.3
|
||||
ns06.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns07.sub.example.tld. A 10.53.0.5
|
||||
ns07.sub.example.tld. A 10.53.0.6
|
||||
ns07.sub.example.tld. A 10.53.0.7
|
||||
ns07.sub.example.tld. A 10.53.0.8
|
||||
ns07.sub.example.tld. A 10.53.0.9
|
||||
ns07.sub.example.tld. A 10.53.0.10
|
||||
ns07.sub.example.tld. A 10.53.1.1
|
||||
ns07.sub.example.tld. A 10.53.1.2
|
||||
ns07.sub.example.tld. A 10.53.2.1
|
||||
ns07.sub.example.tld. A 10.53.0.3
|
||||
ns07.sub.example.tld. A 127.0.0.1
|
||||
ns07.sub.example.tld. A 127.0.0.2
|
||||
ns07.sub.example.tld. A 127.0.0.3
|
||||
ns07.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns08.sub.example.tld. A 10.53.0.5
|
||||
ns08.sub.example.tld. A 10.53.0.6
|
||||
ns08.sub.example.tld. A 10.53.0.7
|
||||
ns08.sub.example.tld. A 10.53.0.8
|
||||
ns08.sub.example.tld. A 10.53.0.9
|
||||
ns08.sub.example.tld. A 10.53.0.10
|
||||
ns08.sub.example.tld. A 10.53.1.1
|
||||
ns08.sub.example.tld. A 10.53.1.2
|
||||
ns08.sub.example.tld. A 10.53.2.1
|
||||
ns08.sub.example.tld. A 10.53.0.3
|
||||
ns08.sub.example.tld. A 127.0.0.1
|
||||
ns08.sub.example.tld. A 127.0.0.2
|
||||
ns08.sub.example.tld. A 127.0.0.3
|
||||
ns08.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns09.sub.example.tld. A 10.53.0.5
|
||||
ns09.sub.example.tld. A 10.53.0.6
|
||||
ns09.sub.example.tld. A 10.53.0.7
|
||||
ns09.sub.example.tld. A 10.53.0.8
|
||||
ns09.sub.example.tld. A 10.53.0.9
|
||||
ns09.sub.example.tld. A 10.53.0.10
|
||||
ns09.sub.example.tld. A 10.53.1.1
|
||||
ns09.sub.example.tld. A 10.53.1.2
|
||||
ns09.sub.example.tld. A 10.53.2.1
|
||||
ns09.sub.example.tld. A 10.53.0.3
|
||||
ns09.sub.example.tld. A 127.0.0.1
|
||||
ns09.sub.example.tld. A 127.0.0.2
|
||||
ns09.sub.example.tld. A 127.0.0.3
|
||||
ns09.sub.example.tld. A 127.0.0.4
|
||||
|
||||
ns10.sub.example.tld. A 10.53.0.5
|
||||
ns10.sub.example.tld. A 10.53.0.6
|
||||
ns10.sub.example.tld. A 10.53.0.7
|
||||
ns10.sub.example.tld. A 10.53.0.8
|
||||
ns10.sub.example.tld. A 10.53.0.9
|
||||
ns10.sub.example.tld. A 10.53.0.10
|
||||
ns10.sub.example.tld. A 10.53.1.1
|
||||
ns10.sub.example.tld. A 10.53.1.2
|
||||
ns10.sub.example.tld. A 10.53.2.1
|
||||
ns10.sub.example.tld. A 10.53.0.3
|
||||
ns10.sub.example.tld. A 127.0.0.1
|
||||
ns10.sub.example.tld. A 127.0.0.2
|
||||
ns10.sub.example.tld. A 127.0.0.3
|
||||
ns10.sub.example.tld. A 127.0.0.4
|
||||
33
bin/tests/system/selfpointedglue/ns3/example2.tld.db
Normal file
33
bin/tests/system/selfpointedglue/ns3/example2.tld.db
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
; 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
|
||||
example2.tld. IN SOA owner.dnshoster.tld. ns.dnshoster.tld. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
|
||||
example2.tld. NS ns.example2.tld.
|
||||
ns.example2.tld. A 10.53.0.3
|
||||
|
||||
sub.example2.tld. NS ns01.sub.example2.tld.
|
||||
sub.example2.tld. NS ns02.sub.example2.tld.
|
||||
sub.example2.tld. NS ns03.sub.example2.tld.
|
||||
|
||||
ns01.sub.example2.tld. A 10.53.1.1
|
||||
ns01.sub.example2.tld. A 10.53.0.5
|
||||
ns02.sub.example2.tld. A 10.53.1.2
|
||||
ns02.sub.example2.tld. A 10.53.0.6
|
||||
ns03.sub.example2.tld. A 10.53.2.1
|
||||
ns03.sub.example2.tld. A 10.53.0.7
|
||||
63
bin/tests/system/selfpointedglue/ns3/example3.tld.db
Normal file
63
bin/tests/system/selfpointedglue/ns3/example3.tld.db
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
; 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
|
||||
example3.tld. IN SOA owner.dnshoster.tld. ns.dnshoster.tld. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
|
||||
example3.tld. NS ns.example3.tld.
|
||||
ns.example3.tld. A 10.53.0.3
|
||||
|
||||
sub.example3.tld. NS ns01.sub.example3.tld.
|
||||
sub.example3.tld. NS ns02.sub.example3.tld.
|
||||
sub.example3.tld. NS ns03.sub.example3.tld.
|
||||
sub.example3.tld. NS ns04.sub.example3.tld.
|
||||
sub.example3.tld. NS ns05.sub.example3.tld.
|
||||
sub.example3.tld. NS ns06.sub.example3.tld.
|
||||
sub.example3.tld. NS ns07.sub.example3.tld.
|
||||
sub.example3.tld. NS ns08.sub.example3.tld.
|
||||
sub.example3.tld. NS ns09.sub.example3.tld.
|
||||
sub.example3.tld. NS ns10.sub.example3.tld.
|
||||
|
||||
ns01.sub.example3.tld. A 10.53.0.5
|
||||
ns01.sub.example3.tld. A 10.53.0.6
|
||||
|
||||
ns02.sub.example3.tld. A 10.53.0.5
|
||||
ns02.sub.example3.tld. A 10.53.0.6
|
||||
|
||||
ns03.sub.example3.tld. A 10.53.0.5
|
||||
ns03.sub.example3.tld. A 10.53.0.6
|
||||
|
||||
ns04.sub.example3.tld. A 10.53.0.5
|
||||
ns04.sub.example3.tld. A 10.53.0.6
|
||||
|
||||
ns05.sub.example3.tld. A 10.53.0.5
|
||||
ns05.sub.example3.tld. A 10.53.0.6
|
||||
|
||||
ns06.sub.example3.tld. A 10.53.0.5
|
||||
ns06.sub.example3.tld. A 10.53.0.6
|
||||
|
||||
ns07.sub.example3.tld. A 10.53.0.5
|
||||
ns07.sub.example3.tld. A 10.53.0.6
|
||||
|
||||
ns08.sub.example3.tld. A 10.53.0.5
|
||||
ns08.sub.example3.tld. A 10.53.0.6
|
||||
|
||||
ns09.sub.example3.tld. A 10.53.0.5
|
||||
ns09.sub.example3.tld. A 10.53.0.6
|
||||
|
||||
ns10.sub.example3.tld. A 10.53.0.5
|
||||
ns10.sub.example3.tld. A 10.53.0.6
|
||||
49
bin/tests/system/selfpointedglue/ns3/named.conf.j2
Normal file
49
bin/tests/system/selfpointedglue/ns3/named.conf.j2
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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 {
|
||||
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;
|
||||
10.53.0.5;
|
||||
10.53.0.6;
|
||||
10.53.0.7;
|
||||
10.53.0.8;
|
||||
10.53.0.9;
|
||||
10.53.0.10;
|
||||
10.53.1.1;
|
||||
10.53.1.2;
|
||||
10.53.2.1;
|
||||
};
|
||||
recursion no;
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
zone "example.tld." {
|
||||
type primary;
|
||||
file "example.tld.db";
|
||||
};
|
||||
|
||||
zone "example2.tld." {
|
||||
type primary;
|
||||
file "example2.tld.db";
|
||||
};
|
||||
|
||||
zone "example3.tld." {
|
||||
type primary;
|
||||
file "example3.tld.db";
|
||||
};
|
||||
1
bin/tests/system/selfpointedglue/ns4/named.args.j2
Normal file
1
bin/tests/system/selfpointedglue/ns4/named.args.j2
Normal file
|
|
@ -0,0 +1 @@
|
|||
-D selfpointedglue-ns4 -m record -c named.conf -d 99 -g -T maxcachesize=2097152 -4
|
||||
59
bin/tests/system/selfpointedglue/ns4/named.conf.j2
Normal file
59
bin/tests/system/selfpointedglue/ns4/named.conf.j2
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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 maxdelegationservers = maxdelegationservers | default(None) %}
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.4;
|
||||
notify-source 10.53.0.4;
|
||||
transfer-source 10.53.0.4;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.4; };
|
||||
recursion yes;
|
||||
dnssec-validation no;
|
||||
dnstap { resolver query; };
|
||||
dnstap-output file "dnstap.out";
|
||||
{% if maxdelegationservers %}
|
||||
@maxdelegationservers@
|
||||
{% endif %}
|
||||
};
|
||||
|
||||
/*
|
||||
* Forcing TCP ensures that ADDITIONAL won't be truncated (responses won't have
|
||||
* the TC flag, hence the resolver won't retry using TCP by itself, see
|
||||
* https://datatracker.ietf.org/doc/html/rfc2181#section-9)
|
||||
*/
|
||||
server 10.53.0.3 { tcp-only true; };
|
||||
server 10.53.0.5 { tcp-only true; };
|
||||
server 10.53.0.6 { tcp-only true; };
|
||||
server 10.53.0.7 { tcp-only true; };
|
||||
server 10.53.0.8 { tcp-only true; };
|
||||
server 10.53.0.9 { tcp-only true; };
|
||||
server 10.53.0.10 { tcp-only true; };
|
||||
server 10.53.1.1 { tcp-only true; };
|
||||
server 10.53.1.2 { tcp-only true; };
|
||||
server 10.53.2.1 { tcp-only true; };
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "root.hint";
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
14
bin/tests/system/selfpointedglue/ns4/root.hint
Normal file
14
bin/tests/system/selfpointedglue/ns4/root.hint
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
; 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 999999
|
||||
. IN NS a.root-servers.nil.
|
||||
a.root-servers.nil. IN A 10.53.0.1
|
||||
157
bin/tests/system/selfpointedglue/tests_selfpointedglue.py
Normal file
157
bin/tests/system/selfpointedglue/tests_selfpointedglue.py
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
# 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 os
|
||||
|
||||
import isctest
|
||||
import isctest.mark
|
||||
|
||||
pytestmark = [isctest.mark.with_dnstap]
|
||||
|
||||
|
||||
def line_to_ips_and_queries(line):
|
||||
# dnstap-read output line example
|
||||
# 05-Feb-2026 11:00:57.853 RQ 10.53.0.4:38507 -> 10.53.0.3:22047 TCP 56b sub.example.tld/IN/NS
|
||||
_, _, _, _, _, dst, _, _, query = line.split(" ", 9)
|
||||
ip, _ = dst.split(":", 1)
|
||||
return (ip, query)
|
||||
|
||||
|
||||
def extract_dnstap(ns, expectedlen):
|
||||
ns.rndc("dnstap -roll 1")
|
||||
path = os.path.join(ns.identifier, "dnstap.out.0")
|
||||
dnstapread = isctest.run.cmd(
|
||||
[isctest.vars.ALL["DNSTAPREAD"], path],
|
||||
)
|
||||
|
||||
lines = dnstapread.out.splitlines()
|
||||
assert expectedlen == len(lines)
|
||||
return list(map(line_to_ips_and_queries, lines))
|
||||
|
||||
|
||||
# Because DNSTAP doesn't have ordering guarantee, the order doesn't matter here.
|
||||
def expect_ip_and_query(expected_ips_and_queries, ips_and_queries):
|
||||
found_count = 0
|
||||
for expected_ip, expected_query in expected_ips_and_queries:
|
||||
found = False
|
||||
for ip, query in ips_and_queries:
|
||||
if ip == expected_ip and query == expected_query:
|
||||
found = True
|
||||
found_count += 1
|
||||
break
|
||||
assert found
|
||||
assert found_count == len(expected_ips_and_queries)
|
||||
|
||||
|
||||
def expect_query(expected_query, expected_query_count, ips_and_queries):
|
||||
count = 0
|
||||
for _, query in ips_and_queries:
|
||||
if query == expected_query:
|
||||
count += 1
|
||||
assert count == expected_query_count
|
||||
|
||||
|
||||
def test_selfpointedglue1(ns4):
|
||||
msg = isctest.query.create("a.sub.example.tld.", "A")
|
||||
res = isctest.query.tcp(msg, ns4.ip)
|
||||
isctest.check.servfail(res)
|
||||
|
||||
# 4 queries to get to the delegation.
|
||||
# 13 queries to delegation NS servers.
|
||||
ips_and_queries = extract_dnstap(ns4, 17)
|
||||
|
||||
# Thanks to the de-duplication, only the first 13 NS IPs are
|
||||
# queried (once sub.example.tld. NS is found) instead of 13*10
|
||||
# (13 per NS, with 10 NS).
|
||||
expect_ip_and_query(
|
||||
[
|
||||
("10.53.0.1", "./IN/NS"),
|
||||
("10.53.0.1", "tld/IN/NS"),
|
||||
("10.53.0.2", "example.tld/IN/NS"),
|
||||
("10.53.0.3", "sub.example.tld/IN/NS"),
|
||||
("10.53.0.3", "a.sub.example.tld/IN/A"),
|
||||
("10.53.0.5", "a.sub.example.tld/IN/A"),
|
||||
("10.53.0.6", "a.sub.example.tld/IN/A"),
|
||||
("10.53.0.7", "a.sub.example.tld/IN/A"),
|
||||
("10.53.0.8", "a.sub.example.tld/IN/A"),
|
||||
("10.53.0.9", "a.sub.example.tld/IN/A"),
|
||||
("10.53.0.10", "a.sub.example.tld/IN/A"),
|
||||
("10.53.1.1", "a.sub.example.tld/IN/A"),
|
||||
("10.53.1.2", "a.sub.example.tld/IN/A"),
|
||||
("10.53.2.1", "a.sub.example.tld/IN/A"),
|
||||
("10.53.0.3", "a.sub.example.tld/IN/A"),
|
||||
("127.0.0.1", "a.sub.example.tld/IN/A"),
|
||||
("127.0.0.2", "a.sub.example.tld/IN/A"),
|
||||
],
|
||||
ips_and_queries,
|
||||
)
|
||||
|
||||
|
||||
# This test is useful because the one above hits the max-delegation-servers
|
||||
# from the first NS name lookup. This one doesn't, because there is only 2
|
||||
# addresses per NS, but the deduplication avoid the explosion of duplicate
|
||||
# addresses.
|
||||
def test_selfpointedglue2(ns4):
|
||||
with ns4.watch_log_from_here() as watcher:
|
||||
ns4.rndc("flush")
|
||||
ns4.rndc("reload")
|
||||
watcher.wait_for_line("running")
|
||||
msg = isctest.query.create("a.sub.example3.tld.", "A")
|
||||
res = isctest.query.tcp(msg, ns4.ip)
|
||||
isctest.check.servfail(res)
|
||||
|
||||
# 4 queries to get to the delegation.
|
||||
# 2 queries to delegation NS servers.
|
||||
ips_and_queries = extract_dnstap(ns4, 6)
|
||||
|
||||
# Thanks to the de-duplication, only the first 2 NS IPs are
|
||||
# queried (once sub.example.tld. NS is found) instead of 2*10
|
||||
# (2 per NS with 10 NS).
|
||||
expect_ip_and_query(
|
||||
[
|
||||
("10.53.0.1", "./IN/NS"),
|
||||
("10.53.0.1", "tld/IN/NS"),
|
||||
("10.53.0.2", "example3.tld/IN/NS"),
|
||||
("10.53.0.3", "sub.example3.tld/IN/NS"),
|
||||
("10.53.0.5", "a.sub.example3.tld/IN/A"),
|
||||
("10.53.0.6", "a.sub.example3.tld/IN/A"),
|
||||
],
|
||||
ips_and_queries,
|
||||
)
|
||||
|
||||
|
||||
def test_selfpointedglue_nslimit(ns4, templates):
|
||||
templates.render(
|
||||
"ns4/named.conf", {"maxdelegationservers": "max-delegation-servers 2;"}
|
||||
)
|
||||
with ns4.watch_log_from_here() as watcher:
|
||||
ns4.rndc("flush")
|
||||
ns4.rndc("reload")
|
||||
watcher.wait_for_line("running")
|
||||
|
||||
msg = isctest.query.create("a.sub.example2.tld.", "A")
|
||||
res = isctest.query.tcp(msg, ns4.ip)
|
||||
isctest.check.servfail(res)
|
||||
|
||||
ips_and_queries = extract_dnstap(ns4, 6)
|
||||
|
||||
# Checking the beginning of the resolution
|
||||
expect_ip_and_query(
|
||||
[
|
||||
("10.53.0.1", "./IN/NS"),
|
||||
("10.53.0.1", "tld/IN/NS"),
|
||||
("10.53.0.2", "example2.tld/IN/NS"),
|
||||
("10.53.0.3", "sub.example2.tld/IN/NS"),
|
||||
],
|
||||
ips_and_queries,
|
||||
)
|
||||
|
||||
expect_query("a.sub.example2.tld/IN/A", 2, ips_and_queries)
|
||||
18
bin/tests/system/srtt/README
Normal file
18
bin/tests/system/srtt/README
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
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 is root
|
||||
|
||||
ans{2-5} simulates four NS servers making authority on the same domain
|
||||
`example.`. ans2 is the quickest to answer, followed by ans3, then ans4, with
|
||||
ans5 being the slowest.
|
||||
|
||||
ns6 is a resolver
|
||||
36
bin/tests/system/srtt/ans2/ans.py
Normal file
36
bin/tests/system/srtt/ans2/ans.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
"""
|
||||
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 dns.rcode
|
||||
|
||||
from isctest.asyncserver import AsyncDnsServer, IgnoreAllQueries
|
||||
|
||||
from ..srtt_ans import DelayedQnameRangeHandler
|
||||
|
||||
|
||||
class Foo1ToFoo99Handler(DelayedQnameRangeHandler):
|
||||
max_qname = 99
|
||||
delay = 0.0
|
||||
|
||||
|
||||
def main() -> None:
|
||||
server = AsyncDnsServer(default_aa=True, default_rcode=dns.rcode.NOERROR)
|
||||
server.install_response_handlers(
|
||||
Foo1ToFoo99Handler(),
|
||||
IgnoreAllQueries(),
|
||||
)
|
||||
server.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
36
bin/tests/system/srtt/ans3/ans.py
Normal file
36
bin/tests/system/srtt/ans3/ans.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
"""
|
||||
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 dns.rcode
|
||||
|
||||
from isctest.asyncserver import AsyncDnsServer, IgnoreAllQueries
|
||||
|
||||
from ..srtt_ans import DelayedQnameRangeHandler
|
||||
|
||||
|
||||
class Foo1ToFoo199Handler(DelayedQnameRangeHandler):
|
||||
max_qname = 199
|
||||
delay = 0.03
|
||||
|
||||
|
||||
def main() -> None:
|
||||
server = AsyncDnsServer(default_aa=True, default_rcode=dns.rcode.NOERROR)
|
||||
server.install_response_handlers(
|
||||
Foo1ToFoo199Handler(),
|
||||
IgnoreAllQueries(),
|
||||
)
|
||||
server.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
36
bin/tests/system/srtt/ans4/ans.py
Normal file
36
bin/tests/system/srtt/ans4/ans.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
"""
|
||||
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 dns.rcode
|
||||
|
||||
from isctest.asyncserver import AsyncDnsServer, IgnoreAllQueries
|
||||
|
||||
from ..srtt_ans import DelayedQnameRangeHandler
|
||||
|
||||
|
||||
class Foo1ToFoo299Handler(DelayedQnameRangeHandler):
|
||||
max_qname = 299
|
||||
delay = 0.08
|
||||
|
||||
|
||||
def main() -> None:
|
||||
server = AsyncDnsServer(default_aa=True, default_rcode=dns.rcode.NOERROR)
|
||||
server.install_response_handlers(
|
||||
Foo1ToFoo299Handler(),
|
||||
IgnoreAllQueries(),
|
||||
)
|
||||
server.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
36
bin/tests/system/srtt/ans5/ans.py
Normal file
36
bin/tests/system/srtt/ans5/ans.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
"""
|
||||
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 dns.rcode
|
||||
|
||||
from isctest.asyncserver import AsyncDnsServer, IgnoreAllQueries
|
||||
|
||||
from ..srtt_ans import DelayedQnameRangeHandler
|
||||
|
||||
|
||||
class Foo1ToFoo399Handler(DelayedQnameRangeHandler):
|
||||
max_qname = 399
|
||||
delay = 0.15
|
||||
|
||||
|
||||
def main() -> None:
|
||||
server = AsyncDnsServer(default_aa=True, default_rcode=dns.rcode.NOERROR)
|
||||
server.install_response_handlers(
|
||||
Foo1ToFoo399Handler(),
|
||||
IgnoreAllQueries(),
|
||||
)
|
||||
server.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
29
bin/tests/system/srtt/ns1/named.conf.j2
Normal file
29
bin/tests/system/srtt/ns1/named.conf.j2
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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 {
|
||||
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";
|
||||
};
|
||||
36
bin/tests/system/srtt/ns1/root.db
Normal file
36
bin/tests/system/srtt/ns1/root.db
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
; 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 owner.root-servers.nil. 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
|
||||
|
||||
; The idea is that the resolver would do 2 ADB lookups, so there would be 2
|
||||
; find list, both with 2 IPs in it. ns1 (which is actually ans2 and ans5) would
|
||||
; have both the slowest and fastest addresses. ns2 (which is actually ans3 and
|
||||
; ans4) would have two addresses in the middle.
|
||||
|
||||
example. NS ns1.example.
|
||||
example. NS ns1.example.
|
||||
example. NS ns2.example.
|
||||
example. NS ns2.example.
|
||||
|
||||
ns1.example. A 10.53.0.2 ; delay is 0
|
||||
ns1.example. A 10.53.0.5 ; delay is 0.15
|
||||
ns2.example. A 10.53.0.4 ; delay is 0.08
|
||||
ns2.example. A 10.53.0.3 ; delay is 0.03
|
||||
1
bin/tests/system/srtt/ns6/named.args
Normal file
1
bin/tests/system/srtt/ns6/named.args
Normal file
|
|
@ -0,0 +1 @@
|
|||
-D srtt-ns6 -m record -c named.conf -d 99 -g -T maxcachesize=2097152 -4
|
||||
41
bin/tests/system/srtt/ns6/named.conf.j2
Normal file
41
bin/tests/system/srtt/ns6/named.conf.j2
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.
|
||||
*/
|
||||
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.6;
|
||||
notify-source 10.53.0.6;
|
||||
transfer-source 10.53.0.6;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.6; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
dnssec-validation no;
|
||||
dnstap { resolver query; };
|
||||
dnstap-output file "dnstap.out";
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "../../_common/root.hint";
|
||||
};
|
||||
59
bin/tests/system/srtt/srtt_ans.py
Normal file
59
bin/tests/system/srtt/srtt_ans.py
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
"""
|
||||
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.
|
||||
"""
|
||||
|
||||
from collections.abc import AsyncGenerator
|
||||
|
||||
import abc
|
||||
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
import dns.rrset
|
||||
|
||||
from isctest.asyncserver import DnsResponseSend, QnameQtypeHandler, QueryContext
|
||||
|
||||
|
||||
class DelayedQnameRangeHandler(QnameQtypeHandler):
|
||||
"""
|
||||
Respond to queries for QNAMEs "foo1.example." through "foo<N>.example."
|
||||
with QTYPE=A, where <N> must be defined by the subclass. Every response is
|
||||
delayed by a fixed amount of time, which must also be defined (in seconds)
|
||||
by the subclass.
|
||||
"""
|
||||
|
||||
@property
|
||||
def qnames(self) -> list[str]:
|
||||
return [f"foo{x}.example." for x in range(1, self.max_qname + 1)]
|
||||
|
||||
qtypes = [dns.rdatatype.A]
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def max_qname(self) -> int:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def delay(self) -> float:
|
||||
raise NotImplementedError
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.__class__.__name__}(foo[1-{self.max_qname}].example/A)"
|
||||
|
||||
async def get_responses(
|
||||
self, qctx: QueryContext
|
||||
) -> AsyncGenerator[DnsResponseSend, None]:
|
||||
a_rrset = dns.rrset.from_text(
|
||||
qctx.qname, 300, dns.rdataclass.IN, dns.rdatatype.A, "10.53.9.9"
|
||||
)
|
||||
qctx.response.answer.append(a_rrset)
|
||||
yield DnsResponseSend(qctx.response, delay=self.delay)
|
||||
89
bin/tests/system/srtt/tests_srtt.py
Normal file
89
bin/tests/system/srtt/tests_srtt.py
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
# 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 os
|
||||
|
||||
import isctest
|
||||
import isctest.mark
|
||||
|
||||
pytestmark = [isctest.mark.with_dnstap]
|
||||
|
||||
|
||||
def line_to_dst_ips(line):
|
||||
# dnstap-read output line example
|
||||
# 05-Feb-2026 11:00:57.853 RQ 10.53.0.6:38507 -> 10.53.0.3:22047 TCP 56b fooXXX.example./IN/NS
|
||||
_, _, _, _, _, dst, _, _, _ = line.split(" ", 9)
|
||||
ip, _ = dst.split(":", 1)
|
||||
return ip
|
||||
|
||||
|
||||
def extract_dnstap(ns):
|
||||
ns.rndc("dnstap -roll 1")
|
||||
path = os.path.join(ns.identifier, "dnstap.out.0")
|
||||
dnstapread = isctest.run.cmd(
|
||||
[isctest.vars.ALL["DNSTAPREAD"], path],
|
||||
)
|
||||
|
||||
lines = dnstapread.out.splitlines()
|
||||
return map(line_to_dst_ips, lines)
|
||||
|
||||
|
||||
def assert_used_auth(ns, authip):
|
||||
ips = extract_dnstap(ns)
|
||||
queries = 0
|
||||
matches = 0
|
||||
for ip in ips:
|
||||
queries += 1
|
||||
if ip == authip:
|
||||
matches += 1
|
||||
assert matches > 85
|
||||
assert queries <= 115
|
||||
|
||||
|
||||
def test_srtt(ns6):
|
||||
for i in range(1, 100):
|
||||
msg = isctest.query.create(f"foo{i}.example.", "A")
|
||||
res = isctest.query.udp(msg, ns6.ip)
|
||||
isctest.check.noerror(res)
|
||||
assert len(res.answer[0]) == 1
|
||||
res.answer[0].ttl = 300
|
||||
assert str(res.answer[0]) == f"foo{i}.example. 300 IN A 10.53.9.9"
|
||||
|
||||
assert_used_auth(ns6, "10.53.0.2")
|
||||
|
||||
for i in range(100, 200):
|
||||
msg = isctest.query.create(f"foo{i}.example.", "A")
|
||||
res = isctest.query.udp(msg, ns6.ip)
|
||||
isctest.check.noerror(res)
|
||||
assert len(res.answer[0]) == 1
|
||||
res.answer[0].ttl = 300
|
||||
assert str(res.answer[0]) == f"foo{i}.example. 300 IN A 10.53.9.9"
|
||||
|
||||
assert_used_auth(ns6, "10.53.0.3")
|
||||
|
||||
for i in range(200, 300):
|
||||
msg = isctest.query.create(f"foo{i}.example.", "A")
|
||||
res = isctest.query.udp(msg, ns6.ip)
|
||||
isctest.check.noerror(res)
|
||||
assert len(res.answer[0]) == 1
|
||||
res.answer[0].ttl = 300
|
||||
assert str(res.answer[0]) == f"foo{i}.example. 300 IN A 10.53.9.9"
|
||||
|
||||
assert_used_auth(ns6, "10.53.0.4")
|
||||
|
||||
for i in range(300, 400):
|
||||
msg = isctest.query.create(f"foo{i}.example.", "A")
|
||||
res = isctest.query.udp(msg, ns6.ip)
|
||||
isctest.check.noerror(res)
|
||||
assert len(res.answer[0]) == 1
|
||||
res.answer[0].ttl = 300
|
||||
assert str(res.answer[0]) == f"foo{i}.example. 300 IN A 10.53.9.9"
|
||||
assert_used_auth(ns6, "10.53.0.5")
|
||||
BIN
bin/tests/system/tkeyleak/ns1/dns.keytab
Normal file
BIN
bin/tests/system/tkeyleak/ns1/dns.keytab
Normal file
Binary file not shown.
21
bin/tests/system/tkeyleak/ns1/example.db.in
Normal file
21
bin/tests/system/tkeyleak/ns1/example.db.in
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
; 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 ns.example. admin.example. (
|
||||
1 ; serial
|
||||
3600 ; refresh
|
||||
900 ; retry
|
||||
604800 ; expire
|
||||
300 ; minimum
|
||||
)
|
||||
@ IN NS ns.example.
|
||||
ns IN A 10.53.0.1
|
||||
39
bin/tests/system/tkeyleak/ns1/named.conf.j2
Normal file
39
bin/tests/system/tkeyleak/ns1/named.conf.j2
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 {
|
||||
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;
|
||||
dnssec-validation no;
|
||||
tkey-gssapi-keytab "dns.keytab";
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
zone "example" {
|
||||
type primary;
|
||||
file "example.db";
|
||||
};
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
|
@ -9,17 +11,11 @@
|
|||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
import isctest
|
||||
. ../conf.sh
|
||||
|
||||
$FEATURETEST --gssapi || {
|
||||
echo_i "gssapi not supported - skipping tkeyleak test"
|
||||
exit 255
|
||||
}
|
||||
|
||||
def test_nohintswarn_bindchaos(ns1):
|
||||
found = True
|
||||
try:
|
||||
with ns1.watch_log_from_start(timeout=1) as watcher:
|
||||
watcher.wait_for_line("no root hints for view '_bind'")
|
||||
except isctest.log.watchlog.WatchLogTimeout:
|
||||
found = False
|
||||
assert found is False
|
||||
|
||||
with ns1.watch_log_from_start() as watcher:
|
||||
watcher.wait_for_line("no root hints for view 'bar'")
|
||||
exit 0
|
||||
17
bin/tests/system/tkeyleak/setup.sh
Normal file
17
bin/tests/system/tkeyleak/setup.sh
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#!/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
|
||||
|
||||
cp ns1/example.db.in ns1/example.db
|
||||
145
bin/tests/system/tkeyleak/tests_tkeyleak.py
Normal file
145
bin/tests/system/tkeyleak/tests_tkeyleak.py
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
# 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.
|
||||
|
||||
"""
|
||||
Regression test for GSS-API context leak via repeated TKEY queries.
|
||||
|
||||
An unauthenticated attacker could exhaust server memory by sending
|
||||
repeated TKEY queries with crafted SPNEGO NegTokenInit tokens.
|
||||
Each query triggers gss_accept_sec_context() which returns
|
||||
GSS_S_CONTINUE_NEEDED and allocates a GSS context. On the unfixed
|
||||
code path, the context handle in process_gsstkey() is never stored
|
||||
or freed, leaking ~520 bytes per query.
|
||||
|
||||
The fix rejects GSS_S_CONTINUE_NEEDED in dst_gssapi_acceptctx() and
|
||||
deletes the context immediately.
|
||||
|
||||
The key distinguishing signal in the TKEY response:
|
||||
- CONTINUE (vulnerable): error=0, output token present, no TSIG
|
||||
- BADKEY (fixed): error=17, no output token
|
||||
"""
|
||||
|
||||
import struct
|
||||
import time
|
||||
|
||||
import dns.name
|
||||
import dns.query
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
import dns.rdtypes.ANY.TKEY
|
||||
import pytest
|
||||
|
||||
import isctest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"*/*.db",
|
||||
]
|
||||
)
|
||||
|
||||
TKEY_NAME = dns.name.from_text("test.key.")
|
||||
GSSAPI_ALGORITHM = dns.name.from_text("gss-tsig.")
|
||||
TKEY_MODE_GSSAPI = 3
|
||||
|
||||
# OID 1.2.840.113554.1.2.2 (Kerberos 5)
|
||||
KRB5_OID = b"\x06\x09\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
|
||||
|
||||
# OID 1.3.6.1.5.5.2 (SPNEGO)
|
||||
SPNEGO_OID = b"\x06\x06\x2b\x06\x01\x05\x05\x02"
|
||||
|
||||
|
||||
def der_encode(tag, data):
|
||||
"""Encode data in ASN.1 DER TLV format."""
|
||||
length = len(data)
|
||||
if length < 128:
|
||||
return tag + bytes([length]) + data
|
||||
if length < 256:
|
||||
return tag + b"\x81" + bytes([length]) + data
|
||||
return tag + b"\x82" + struct.pack(">H", length) + data
|
||||
|
||||
|
||||
def spnego_negtokeninit():
|
||||
"""Build a SPNEGO NegTokenInit proposing krb5 without a mechToken.
|
||||
|
||||
This forces gss_accept_sec_context() to return GSS_S_CONTINUE_NEEDED
|
||||
because the acceptor recognizes the krb5 mechanism but has not
|
||||
received an actual AP-REQ token yet.
|
||||
"""
|
||||
# MechTypeList ::= SEQUENCE OF MechType
|
||||
mechtype_list = der_encode(b"\x30", KRB5_OID)
|
||||
# [0] mechTypes
|
||||
mechtypes = der_encode(b"\xa0", mechtype_list)
|
||||
# NegTokenInit ::= SEQUENCE { mechTypes, ... }
|
||||
negtokeninit = der_encode(b"\x30", mechtypes)
|
||||
# [0] CONSTRUCTED (wrapping NegTokenInit)
|
||||
wrapped = der_encode(b"\xa0", negtokeninit)
|
||||
# APPLICATION 0 CONSTRUCTED (SPNEGO OID + body)
|
||||
return der_encode(b"\x60", SPNEGO_OID + wrapped)
|
||||
|
||||
|
||||
def make_tkey_query(token):
|
||||
"""Build a TKEY query with a GSS-API token in the additional section."""
|
||||
now = int(time.time())
|
||||
tkey_rdata = dns.rdtypes.ANY.TKEY.TKEY(
|
||||
rdclass=dns.rdataclass.ANY,
|
||||
rdtype=dns.rdatatype.TKEY,
|
||||
algorithm=GSSAPI_ALGORITHM,
|
||||
inception=now,
|
||||
expiration=now + 86400,
|
||||
mode=TKEY_MODE_GSSAPI,
|
||||
error=0,
|
||||
key=token,
|
||||
other=b"",
|
||||
)
|
||||
|
||||
msg = isctest.query.create(TKEY_NAME, dns.rdatatype.TKEY, dns.rdataclass.ANY)
|
||||
rrset = msg.find_rrset(
|
||||
msg.additional,
|
||||
TKEY_NAME,
|
||||
dns.rdataclass.ANY,
|
||||
dns.rdatatype.TKEY,
|
||||
create=True,
|
||||
)
|
||||
rrset.add(tkey_rdata)
|
||||
return msg
|
||||
|
||||
|
||||
def test_tkey_gssapi_no_continuation(ns1):
|
||||
"""TKEY with a SPNEGO NegTokenInit must be rejected, not continued.
|
||||
|
||||
On unfixed code, gss_accept_sec_context() returns CONTINUE_NEEDED
|
||||
and the response has error=0 with an output token (the leaked path).
|
||||
On fixed code, CONTINUE_NEEDED is rejected and the response has
|
||||
error=BADKEY(17) with no output token.
|
||||
"""
|
||||
port = ns1.ports.dns
|
||||
ip = ns1.ip
|
||||
|
||||
msg = make_tkey_query(spnego_negtokeninit())
|
||||
res = dns.query.tcp(msg, ip, port=port, timeout=5)
|
||||
|
||||
assert res is not None
|
||||
|
||||
tkey = get_tkey_answer(res)
|
||||
assert tkey is not None, "server did not return a TKEY answer"
|
||||
assert (
|
||||
tkey.error != 0
|
||||
), "server returned error=0 (GSS_S_CONTINUE_NEEDED not rejected)"
|
||||
assert len(tkey.key) == 0, "server returned a continuation token"
|
||||
|
||||
|
||||
def get_tkey_answer(response):
|
||||
"""Extract TKEY rdata from a DNS response, or None."""
|
||||
for rrset in response.answer:
|
||||
if rrset.rdtype == dns.rdatatype.TKEY:
|
||||
for rdata in rrset:
|
||||
return rdata
|
||||
return None
|
||||
|
|
@ -25,6 +25,11 @@ dig_cmd() {
|
|||
"$DIG" $DIGOPTS "$@" | grep -v '^;'
|
||||
}
|
||||
|
||||
dig_full() {
|
||||
# shellcheck disable=SC2086
|
||||
"$DIG" $DIGOPTS "$@"
|
||||
}
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "querying for various representations of an IN A record ($n)"
|
||||
for i in 1 2 3 4 5 6 7 8 9 10 11 12; do
|
||||
|
|
@ -81,8 +86,8 @@ n=$((n + 1))
|
|||
echo_i "querying for various representations of a CLASS10 TYPE1 record ($n)"
|
||||
for i in 1 2; do
|
||||
ret=0
|
||||
dig_cmd +short @10.53.0.1 a$i.example a class10 >dig.out.$i.test$n
|
||||
echo '\# 4 0A000001' | diff - dig.out.$i.test$n || ret=1
|
||||
dig_full @10.53.0.1 a$i.example a class10 >dig.out.$i.test$n
|
||||
grep -q "NOTIMP" dig.out.$i.test$n || ret=1
|
||||
if [ $ret != 0 ]; then
|
||||
echo_i "#$i failed"
|
||||
fi
|
||||
|
|
@ -93,8 +98,8 @@ n=$((n + 1))
|
|||
echo_i "querying for various representations of a CLASS10 TXT record ($n)"
|
||||
for i in 1 2 3 4; do
|
||||
ret=0
|
||||
dig_cmd +short @10.53.0.1 txt$i.example txt class10 >dig.out.$i.test$n
|
||||
echo '"hello"' | diff - dig.out.$i.test$n || ret=1
|
||||
dig_full @10.53.0.1 txt$i.example txt class10 >dig.out.$i.test$n
|
||||
grep -q "NOTIMP" dig.out.$i.test$n || ret=1
|
||||
if [ $ret != 0 ]; then
|
||||
echo_i "#$i failed"
|
||||
fi
|
||||
|
|
@ -105,8 +110,8 @@ n=$((n + 1))
|
|||
echo_i "querying for various representations of a CLASS10 TYPE123 record ($n)"
|
||||
for i in 1 2; do
|
||||
ret=0
|
||||
dig_cmd +short @10.53.0.1 unk$i.example type123 class10 >dig.out.$i.test$n
|
||||
echo '\# 1 00' | diff - dig.out.$i.test$n || ret=1
|
||||
dig_full @10.53.0.1 unk$i.example type123 class10 >dig.out.$i.test$n
|
||||
grep -q "NOTIMP" dig.out.$i.test$n || ret=1
|
||||
if [ $ret != 0 ]; then
|
||||
echo_i "#$i failed"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ options {
|
|||
recursion no;
|
||||
dnssec-validation no;
|
||||
notify yes;
|
||||
|
||||
transfers-out 3;
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
|
|
|
|||
46
bin/tests/system/xferquota/ns3/named.conf.j2
Normal file
46
bin/tests/system/xferquota/ns3/named.conf.j2
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 {
|
||||
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 no;
|
||||
dnssec-validation no;
|
||||
|
||||
transfers-out 1;
|
||||
allow-transfer { 10.53.0.2; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type primary;
|
||||
file "root.db";
|
||||
};
|
||||
|
||||
zone "quota." {
|
||||
type primary;
|
||||
file "quota.db";
|
||||
};
|
||||
22
bin/tests/system/xferquota/ns3/quota.db
Normal file
22
bin/tests/system/xferquota/ns3/quota.db
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
; 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 ns1.quota. hostmaster.quota. (
|
||||
1 ; serial
|
||||
3600 ; refresh
|
||||
1800 ; retry
|
||||
604800 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
IN NS ns1.quota.
|
||||
ns1 IN A 10.53.0.3
|
||||
www IN A 10.0.0.1
|
||||
21
bin/tests/system/xferquota/ns3/root.db
Normal file
21
bin/tests/system/xferquota/ns3/root.db
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
; 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 ns.root. hostmaster.root. (
|
||||
1 ; serial
|
||||
3600 ; refresh
|
||||
1800 ; retry
|
||||
604800 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
. NS a.root-servers.nil.
|
||||
a.root-servers.nil. A 10.53.0.3
|
||||
|
|
@ -12,12 +12,15 @@
|
|||
from re import compile as Re
|
||||
|
||||
import glob
|
||||
import multiprocessing
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import signal
|
||||
import time
|
||||
|
||||
import dns.message
|
||||
import dns.query
|
||||
import dns.zone
|
||||
import pytest
|
||||
|
||||
|
|
@ -60,6 +63,9 @@ def test_xferquota(named_port, ns1, ns2):
|
|||
matching_line_count += 1
|
||||
return matching_line_count == 300
|
||||
|
||||
# The primary has 'transfers-out 3;', while the secondary has
|
||||
# 'transfers-in 5; transfer-per-ns 5;'. This will allow all the zones
|
||||
# to be eventually transferred, hitting the quotas now and then.
|
||||
isctest.run.retry_with_timeout(check_line_count, timeout=360)
|
||||
|
||||
axfr_msg = isctest.query.create("zone000099.example.", "AXFR")
|
||||
|
|
@ -79,3 +85,39 @@ def test_xferquota(named_port, ns1, ns2):
|
|||
with ns2.watch_log_from_start(timeout=30) as watcher:
|
||||
watcher.wait_for_line(pattern)
|
||||
query_and_compare(a_msg)
|
||||
|
||||
|
||||
def _flood_unauthorized_axfrs(port, duration):
|
||||
"""Child process: send unauthorized AXFR requests for `duration` seconds."""
|
||||
deadline = time.monotonic() + duration
|
||||
while time.monotonic() < deadline:
|
||||
try:
|
||||
msg = dns.message.make_query("quota.", "AXFR")
|
||||
dns.query.tcp(msg, "10.53.0.3", port=port, timeout=2, source="10.53.0.1")
|
||||
except Exception: # pylint: disable=broad-exception-caught
|
||||
pass
|
||||
|
||||
|
||||
def test_xfrquota_unauthorized_no_starve(named_port):
|
||||
"""Unauthorized AXFR clients must not consume XFR-out quota (GL #3859).
|
||||
|
||||
ns3 is configured with transfers-out 1 and allow-transfer { 10.53.0.2; }.
|
||||
We flood AXFR requests from unauthorized source processes (10.53.0.1) and
|
||||
verify that an authorized client (10.53.0.2) can still transfer.
|
||||
"""
|
||||
with multiprocessing.Pool(10) as pool:
|
||||
pool.starmap_async(_flood_unauthorized_axfrs, [(named_port, 5)] * 10)
|
||||
|
||||
# Give the flood a moment to saturate
|
||||
time.sleep(1)
|
||||
|
||||
# Try an authorized AXFR from 10.53.0.2 multiple times to increase
|
||||
# the chance of hitting the race window where quota is consumed.
|
||||
zone = dns.zone.Zone("quota.")
|
||||
dns.query.inbound_xfr(
|
||||
"10.53.0.3",
|
||||
zone,
|
||||
port=named_port,
|
||||
timeout=10,
|
||||
source="10.53.0.2",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ Changelog
|
|||
development. Regular users should refer to :ref:`Release Notes <relnotes>`
|
||||
for changes relevant to them.
|
||||
|
||||
.. include:: ../changelog/changelog-9.21.22.rst
|
||||
.. include:: ../changelog/changelog-9.21.21.rst
|
||||
.. include:: ../changelog/changelog-9.21.20.rst
|
||||
.. include:: ../changelog/changelog-9.21.19.rst
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ The list of known issues affecting the latest version in the 9.21 branch can be
|
|||
found at
|
||||
https://gitlab.isc.org/isc-projects/bind9/-/wikis/Known-Issues-in-BIND-9.21
|
||||
|
||||
.. include:: ../notes/notes-9.21.22.rst
|
||||
.. include:: ../notes/notes-9.21.21.rst
|
||||
.. include:: ../notes/notes-9.21.20.rst
|
||||
.. include:: ../notes/notes-9.21.19.rst
|
||||
|
|
|
|||
|
|
@ -4187,14 +4187,11 @@ Tuning
|
|||
|
||||
.. namedconf:statement:: max-delegation-servers
|
||||
:tags: server
|
||||
:short: Configure the maximum number of nameserver names considered for a delegation
|
||||
:short: Configure the maximum number of nameservers considered for a delegation
|
||||
|
||||
When looking up remote nameservers for a delegation, the list of nameserver
|
||||
names is sorted according to Canonical RR Ordering within an RRset (see
|
||||
:rfc:`4034` Section 6.3), and the number of names for which :iscman:`named`
|
||||
looks up IP addresses is capped at :any:`max-delegation-servers`.
|
||||
|
||||
This capped list of nameserver names is then randomly shuffled every time
|
||||
:rfc:`4034` Section 6.3). This list is then randomly shuffled every time
|
||||
:iscman:`named` needs additional remote addresses for those nameservers.
|
||||
This randomized selection works around situations where the first few
|
||||
nameserver names in the zone are unresponsive.
|
||||
|
|
@ -4207,6 +4204,12 @@ Tuning
|
|||
outgoing DNS query is initiated only if the DNS resolver does not already have
|
||||
existing IP addresses for any of the nameserver names in the cache.
|
||||
|
||||
The known NS addresses for an NS name (cached from a previous resolution, or
|
||||
the NS name has glues, or it is defined from a local zone or hints) are
|
||||
counted as delegation servers. Thus, the maximum queries the resolver does
|
||||
to resolve a name at a delegation point is capped at
|
||||
:any:`max-delegation-servers`.
|
||||
|
||||
The default and recommended value is ``13``. This limit prevents excessive
|
||||
resource use while processing large or misconfigured delegations. The default
|
||||
value should only be increased in controlled environments where a remote
|
||||
|
|
|
|||
768
doc/changelog/changelog-9.21.22.rst
Normal file
768
doc/changelog/changelog-9.21.22.rst
Normal file
|
|
@ -0,0 +1,768 @@
|
|||
.. 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.
|
||||
|
||||
BIND 9.21.22
|
||||
------------
|
||||
|
||||
Security Fixes
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
- Fix outgoing zone transfers' quota issue. ``3ddd7b8695``
|
||||
|
||||
Unauthorized clients could consume outgoing zone transfers quota and
|
||||
block authorized zone transfer clients. This has been fixed.
|
||||
:gl:`#3589`
|
||||
|
||||
- [CVE-2026-3592] Limit resolver server list size. ``e249148d75``
|
||||
|
||||
When resolving a domain with many nameservers that share overlapping
|
||||
IP addresses (e.g., 10 NS records all pointing at the same set of
|
||||
addresses), BIND could previously waste time querying duplicate
|
||||
addresses and build up excessively large server lists. Deduplicate
|
||||
addresses in the resolver's server list so that each unique IP is only
|
||||
queried once per resolution attempt, regardless of how many NS records
|
||||
point to it and cap the number of addresses stored per nameserver name
|
||||
to 6 (combined A and AAAA), preventing memory and CPU overhead from
|
||||
domains with unusually large NS/glue sets. :gl:`#5641`
|
||||
|
||||
- [CVE-2026-3039] Fix GSS-API resource leak. ``01bdb7abeb``
|
||||
|
||||
Fixed a memory leak where each GSS-API TKEY negotiation leaked a
|
||||
security context inside the GSS library. An unauthenticated attacker
|
||||
could exhaust server memory by sending repeated TKEY queries to a
|
||||
server with tkey-gssapi-keytab configured. The leaked memory was
|
||||
allocated by the GSS library, bypassing BIND's memory accounting.
|
||||
|
||||
Multi-round GSS-API negotiation (GSS_S_CONTINUE_NEEDED) is now
|
||||
rejected, as BIND never supported it correctly and Kerberos/SPNEGO
|
||||
completes in a single round. :gl:`#5752`
|
||||
|
||||
- [CVE-2026-5946] Disable recursion, UPDATE, and NOTIFY for non-IN
|
||||
views. ``21c8ba4f0b``
|
||||
|
||||
Recursion, dynamic updates (UPDATE), and zone change notifications
|
||||
(NOTIFY) are now disabled for views with a class other than IN (such
|
||||
as CHAOS or HESIOD); authoritative service for non-IN zones (e.g.
|
||||
version.bind in class CHAOS) continues to work as before. Servers
|
||||
configured with recursion yes in a non-IN view will log a warning at
|
||||
startup, and named-checkconf flags the same condition. UPDATE and
|
||||
NOTIFY messages that specify the meta-classes ANY or NONE in the
|
||||
question section are now rejected with FORMERR.
|
||||
|
||||
This addresses a set of closely related security issues collectively
|
||||
identified as CVE-2026-5946. ISC would like to thank Mcsky23 for
|
||||
bringing these issues to our attention. :gl:`#5784`
|
||||
|
||||
- [CVE-2026-5950] Avoid unbounded recursion loop. ``5319c21761``
|
||||
|
||||
A bug during bad server handling could cause the resolver to enter an
|
||||
infinite loop, continuously sending queries to an upstream server with
|
||||
no exit condition, until the resolver query timeout was hit. This has
|
||||
been fixed.
|
||||
|
||||
ISC would like to thank Billy Baraja (BielraX) for bringing this issue
|
||||
to our attention. :gl:`#5804`
|
||||
|
||||
- [CVE-2026-5947] Fix crash in resolver when SIG(0)-signed responses are
|
||||
received under load. ``9831f41894``
|
||||
|
||||
A resolver could crash when handling a SIG(0)-signed response if the
|
||||
matching client query was cancelled while signature verification was
|
||||
still in progress — for example, when the recursive-clients quota was
|
||||
exhausted. This has been fixed. :gl:`#5819`
|
||||
|
||||
- Fix race condition in getsigningtime() ``d35a527ffb``
|
||||
|
||||
Compute qpzone_get_lock(elem->node) into a local variable while the
|
||||
heap lock is still held, rather than dereferencing the stale elem
|
||||
pointer after releasing the lock. A concurrent thread running
|
||||
setsigningtime() (e.g. via IXFR apply on a worker thread) could free
|
||||
the top-of-heap element between the heap lock release and the
|
||||
dereference, causing a use-after-free. :gl:`#5883` :gl:`!11875`
|
||||
|
||||
- [CVE-2026-3593] Fix use-after-free in DNS-over-HTTPS when processing
|
||||
HTTP/2 SETTINGS frames. ``e33ff6bb0a``
|
||||
|
||||
A use-after-free vulnerability in the DNS-over-HTTPS implementation
|
||||
could cause named to crash when a client sends a flood of HTTP/2
|
||||
SETTINGS frames while a DoH response is being written. This affects
|
||||
servers with DoH (DNS-over-HTTPS) enabled.
|
||||
|
||||
ISC would like to thank Naresh Kandula Parmar (Nottiboy) for reporting
|
||||
this.
|
||||
|
||||
For: #5755
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- Add DTRACE probes to the delegation cache. ``780ffe375f``
|
||||
|
||||
The new delegation cache, which stores NS-based and DELEG-based
|
||||
delegations per view, is now instrumented with static user-space
|
||||
tracing probes so that cache hit rate, insertion and lookup latency,
|
||||
eviction pressure under memory limits, and removals triggered by rndc
|
||||
flush-delegation can be observed on a running named. :gl:`!11855`
|
||||
|
||||
Removed Features
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
- Remove obsolete KEY record flags deprecated by RFC 3445.
|
||||
``1535b32dab``
|
||||
|
||||
KEY resource records originally defined NOAUTH, NOCONF, EXTENDED, and
|
||||
ENTITY flags that were removed by RFC 3445 back in 2002. BIND still
|
||||
carried code to parse and emit them, including the additional
|
||||
two-octet flags field that followed when the EXTENDED bit was set.
|
||||
That handling has been removed and the affected bit positions are now
|
||||
reserved.
|
||||
|
||||
Dropping the extended-flags handling also eliminates a possible crash
|
||||
that could be reached when signing a zone containing an invalid key.
|
||||
:gl:`#5900` :gl:`!11961`
|
||||
|
||||
Feature Changes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- Embed default sanitizer flags in executables. ``7c60b7da8a``
|
||||
|
||||
Replicating CI failures requires the developer to piece together the
|
||||
sanitizer flags by hand, reducing ergonomics.
|
||||
|
||||
Fix this problem by embedding the relevant settings to the
|
||||
executables. Symbol resolution still needs manual intervention by
|
||||
setting the env variable `*SAN_SYMBOLIZER_PATH`. However, this doesn't
|
||||
affect any behavior.
|
||||
|
||||
The flags are passed though a meson-configured `sanitize.c.in`
|
||||
template file to toggle which flags are included for the executable.
|
||||
Using the built-in `__SANITIZE_XXX__` or `__has_feature` for this task
|
||||
is more trouble than it's worth because only one of the two is
|
||||
available in most GCC/clang versions, alongside the lack of
|
||||
`__SANITIZE_UNDEFINED__` from GCC.
|
||||
|
||||
Meson's own unit test execution sets its own `ASAN_OPTIONS` etc. To
|
||||
prevent it from overriding the default options, we also pass the same
|
||||
options to unit tests environment variables.
|
||||
|
||||
A new script `ci/sanitizer-default-check.py` is used in CI to detect
|
||||
if a build directory with sanitizers enabled has a meson `executable`
|
||||
definition that doesn't include the sanitizer flag source file.
|
||||
:gl:`#5469` :gl:`!10919`
|
||||
|
||||
- Catch rare named crash in recursive resolution earlier for diagnosis.
|
||||
``3c9a848be7``
|
||||
|
||||
A rare crash has been observed in named while it is resolving upstream
|
||||
nameserver addresses for a recursive query, surfacing as a
|
||||
segmentation fault with no immediate clue as to the cause. This change
|
||||
adds internal consistency checks so that a future occurrence of the
|
||||
same condition aborts named with a diagnostic message at the point the
|
||||
inconsistency arises, rather than corrupting state and crashing later
|
||||
in an unrelated location. :gl:`#5602` :gl:`!11943`
|
||||
|
||||
- Revert isdelegation() to return boolean value again. ``69d439cd1b``
|
||||
|
||||
:gl:`#5838` :gl:`!11792`
|
||||
|
||||
- Fix CPU spikes and slow queries when cache approaches memory limit.
|
||||
``2e7e9f51db``
|
||||
|
||||
Spread cache cleanup probabilistically to avoid CPU usage spikes and a
|
||||
drop in query throughput. :gl:`#5891`
|
||||
|
||||
- Add a refcount to the vecheaders. ``a743ff1e44``
|
||||
|
||||
This MR changes the way the ownership of the vecheaders is tracked.
|
||||
Before this MR, the ownership of the vecheader was implicitely tracked
|
||||
through a mix of the refcount on the node owning the header, the
|
||||
external refcount of the same node and the version. This has some
|
||||
adverse consequences in terms of contention, such as that querying A
|
||||
and AAAA glue hits the same refcount.
|
||||
|
||||
This MR adds a refcount to the vecheader itself, allowing it to exist
|
||||
independently of the node it is contained in. On its own, this would
|
||||
create a cycle, where the node has a reference to the header, which
|
||||
has a reference to the heap, which in turn has a reference to the
|
||||
node.
|
||||
|
||||
To break this cycle, this MR also moves from an "intrusive" heap, to a
|
||||
more traditional one where pointers to the node and vecheader in the
|
||||
heap are stored in a hashmap. :gl:`!11397`
|
||||
|
||||
- Change NSEC3 and NSEC3PARAM rdata struct fields to use isc_region_t.
|
||||
``245c71dfac``
|
||||
|
||||
Replace the separate pointer+length field pairs in the NSEC3 and
|
||||
NSEC3PARAM rdata structures (salt/salt_length, next/next_length,
|
||||
typebits/len) with isc_region_t, making the fields self-describing and
|
||||
eliminating a class of length-mismatch bugs. :gl:`!11592`
|
||||
|
||||
- Document that named-checkzone must not run on untrusted input.
|
||||
``5b164b551f``
|
||||
|
||||
The zone-file parser implements $INCLUDE by opening whatever local
|
||||
path the zone text names, and fragments of the included file leak
|
||||
through parser error messages. There is no safe way to validate
|
||||
untrusted zone text with named-checkzone or named-compilezone, so the
|
||||
manual pages for both tools now warn against doing so. :gl:`!11901`
|
||||
|
||||
- Don't set named curves explicitly in pre-3.0 libcrypto. ``2e92389905``
|
||||
|
||||
The function EC_KEY_set_asn1_flag is deprecated in AWS-LC. Fortunately
|
||||
calling it to make sure we use named curve keys is entirely
|
||||
unnecessary.
|
||||
|
||||
More information for pre-3.0 libcrypto and significant forks are as
|
||||
following:
|
||||
|
||||
OpenSSL: Named curves were the default between 1.1.0 and 3.6.1 [1],[2]
|
||||
|
||||
AWS-LC: Library only supports named curves in the first place [3]
|
||||
|
||||
BoringSSL: Likewise with AWS-LC [4]
|
||||
|
||||
LibreSSL: EC_GROUPs are named by default [5]
|
||||
|
||||
[1]: https://github.com/openssl/openssl/commit/86f300d38540ead85543aee
|
||||
0cb30c32145931744 [2]: https://github.com/openssl/openssl/commit/9db6a
|
||||
f922c48c5cab5398ef9f37e425e382f9440 [3]: https://github.com/aws/aws-lc
|
||||
/blob/a605df416bc6ddd0a3b79d728770664ce2302e71/include/openssl/ec_key.
|
||||
h#L442-L445 [4]: https://github.com/google/boringssl/blob/514abb73bb80
|
||||
130000b46cf589190c967c6647cd/include/openssl/ec_key.h#L279-L280 [5]: h
|
||||
ttps://github.com/libressl/openbsd/blob/c9338745181f31ae01336081edfdb7
|
||||
38c0b76d5f/src/lib/libcrypto/ec/ec_lib.c#L94 :gl:`!11530`
|
||||
|
||||
- Fix off by one error in dnssec-ksr sign. ``ae739daec2``
|
||||
|
||||
If the inception time of the signature is exactly equal to the
|
||||
inactive time of the key, add the signature. :gl:`!11791`
|
||||
|
||||
- Harden GSS-API context establishment in TKEY negotiation.
|
||||
``9212e1ac50``
|
||||
|
||||
Implement RFC 3645 Section 3.1.1 client-side check for REPLAY, MUTUAL,
|
||||
and INTEG flags after gss_init_sec_context() completes. Add
|
||||
server-side INTEG flag check after gss_accept_sec_context(). Also
|
||||
fixes an uninitialized gss_name_t on the error path in
|
||||
dst_gssapi_initctx().
|
||||
|
||||
- Implement RFC 3645 Section 4.1.1 key expiry check in TKEY.
|
||||
``6b6913c83b``
|
||||
|
||||
Check for existing TSIG keys before accepting a new GSS-API
|
||||
negotiation and delete the key if it has expired. Previously, an
|
||||
expired GSS key would permanently block re-negotiation for that name
|
||||
until the server was restarted. :gl:`!11713`
|
||||
|
||||
- Reduce memory footprint by actively returning unused memory to the OS.
|
||||
``460bf794a5``
|
||||
|
||||
Previously, :iscman:`named` relied on the default allocator settings
|
||||
for releasing unused memory back to the operating system, which could
|
||||
result in unnecessarily high resident memory usage. :iscman:`named`
|
||||
now actively manages memory page purging. On systems using jemalloc,
|
||||
background cleanup threads are enabled and the dirty page decay time
|
||||
is reduced from 10 seconds to 5 seconds. Additionally, a volume-based
|
||||
decay pass is triggered after every 16 MiB of freed memory. On
|
||||
glibc-based systems, a similar volume-based mechanism using
|
||||
malloc_trim() is used instead. :gl:`!11761`
|
||||
|
||||
- Split up zone.c (zone manager) ``e99b5f80be``
|
||||
|
||||
In order to make `zone.c` more readable, split it up in separate
|
||||
source files. This moves zone manager related code to `zonemgr.c`.
|
||||
:gl:`!11726`
|
||||
|
||||
- Split up zone.c (zone properties) ``36acc92131``
|
||||
|
||||
In order to make `zone.c` more readable, split it up in separate
|
||||
source files. This moves most of the set and get functions to
|
||||
`zoneproperties.c`. :gl:`!11501`
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
- Check validator name when adding EDE text. ``a6b44a6007``
|
||||
|
||||
When a validator is being shut down, the associated name `val->name`
|
||||
is set to NULL. This could cause a crash if a worker thread
|
||||
subsequently added an EDE code with `val->name` in the extra text.
|
||||
|
||||
`validator_addede()` now checks whether the name is NULL before trying
|
||||
to add it to the extra text. :gl:`#5613` :gl:`!11945`
|
||||
|
||||
- Use the zone file's basename as origin in DNSSEC tools. ``08fa344014``
|
||||
|
||||
In `dnssec-signzone` and `dnssec-verify`, when the zone origin is not
|
||||
specified using the `-o` parameter, the default behavior is to try to
|
||||
sign using the zone's file name as the origin. So, for example,
|
||||
`dnssec-signzone -S example.com` will work, so long as the file name
|
||||
matches the zone name.
|
||||
|
||||
This now also works if the zone is in a different directory. For
|
||||
example, `dnssec-signzone -S zones/example.com` will set the origin
|
||||
value to `example.com`. :gl:`#5678` :gl:`!11360`
|
||||
|
||||
- Fix a possible race condition during zone transfers. ``175b121bc3``
|
||||
|
||||
The :iscman:`named` process could terminate unexpectedly when
|
||||
processing an IXFR message during a zone transfer. This has been
|
||||
fixed. :gl:`#5767` :gl:`!11781`
|
||||
|
||||
- Do not resend query after BADCOOKIE answer on TCP. ``53593e8e13``
|
||||
|
||||
When an upstream server answers BADCOOKIE, no matter which transport
|
||||
is used, the resolver resends the query using TCP. However, if the
|
||||
upstream server responded with BADCOOKIE again over TCP, the resolver
|
||||
would keep resending until the maximum query count was reached.
|
||||
|
||||
This is now fixed by no longer resending once the query has already
|
||||
been sent over TCP. :gl:`#5804`
|
||||
|
||||
- Make BIND9 compatible with OpenSSL 4. ``80794c5e87``
|
||||
|
||||
OPENSSL_cleanup() in OpenSSL 4 doesn't free the memory, and that is
|
||||
not compatible with BIND 9's memory leak detection code. Don't use
|
||||
custom allocation/deallocation functions for OpenSSL's internal memory
|
||||
management.
|
||||
|
||||
See https://github.com/openssl/openssl/pull/29721 :gl:`#5808`
|
||||
:gl:`!11865`
|
||||
|
||||
- Fix named crash when processing SIG records in dynamic updates.
|
||||
``5f0b2f255f``
|
||||
|
||||
Previously, :iscman:`named` could abort if a client sent a dynamic
|
||||
update containing a SIG record (the legacy signature type) to a zone
|
||||
configured with an update-policy. The function `dns_db_findrdataset`
|
||||
had an incorrect requirements prerequisite that prevented SIG records
|
||||
being looked up, which was triggered as part of processing an UPDATE
|
||||
request and could be triggered remotely by any client permitted to
|
||||
send updates. This has been fixed by ensuring that SIG records are
|
||||
handled consistently with RRSIG records during update processing.
|
||||
:gl:`#5818` :gl:`!11864`
|
||||
|
||||
- Fix wrong NSEC proof for empty non-terminals after IXFR.
|
||||
``15f058b5a2``
|
||||
|
||||
When a secondary received an IXFR that transitioned a zone from
|
||||
unsigned to NSEC-signed, queries for empty non-terminal names returned
|
||||
the zone apex NSEC record instead of the NSEC that actually covers the
|
||||
queried name. The issue only occurred with incremental transfers; a
|
||||
full AXFR or a server restart resolved it. :gl:`#5824` :gl:`!11786`
|
||||
|
||||
- Fix rndc modzone behavior for a zone in named.conf. ``c56d4c13f9``
|
||||
|
||||
If a zone was present in the configuration file and not originally
|
||||
added by `rndc addzone`, `rndc modzone` for that zone would succeed
|
||||
once but subsequent `modzone` attempts would fail. This has been
|
||||
fixed. :gl:`#5826` :gl:`!11744`
|
||||
|
||||
- Fix zone verification of NSEC3 signed zones. ``0633effb5b``
|
||||
|
||||
Previously, when computing the compressed bitmap during verification
|
||||
of an NSEC3-signed zone, an undersized buffer was used that resulted
|
||||
in an out-of-bounds write if there were too many active windows in the
|
||||
bitmap. This impacted mirror zones which are NSEC3-signed,
|
||||
`dnssec-signzone` and `dnssec-verifyzone`. This has been fixed.
|
||||
:gl:`#5834` :gl:`!11804`
|
||||
|
||||
- Fix 'rndc modzone' issue with non-existing zones. ``09a4b80301``
|
||||
|
||||
The :iscman:`named` process could terminate unexpectedly or become
|
||||
subject to undefined behavior when issued an :option:`rndc modzone`
|
||||
operation for a non-existing zone. This has been fixed. :gl:`#5848`
|
||||
:gl:`!11844`
|
||||
|
||||
- Fix zone filename token-parsing bug. ``ef29555ba4``
|
||||
|
||||
The :iscman:`named` process could terminate unexpectedly when
|
||||
processing a catalog member zone containing special characters like
|
||||
'%' or '$' which could be interpreted as zone filename tokens and
|
||||
trigger a case-sensitivity bug in the token-parsing code. This has
|
||||
been fixed. :gl:`#5849` :gl:`!11839`
|
||||
|
||||
- Prevent a crash when using both dns64 and filter-aaaa. ``3c60322fa3``
|
||||
|
||||
An assertion failure could be triggered if both `dns64` and the
|
||||
`filter-aaaa` plugin were in use simultaneously. This happened if the
|
||||
plugin triggered a second recursion process, which then attempted to
|
||||
store DNS64 state information in a pointer that had already been set
|
||||
by the original recursion process. This has been fixed. :gl:`#5854`
|
||||
:gl:`!11949`
|
||||
|
||||
- Remove unnecessary dns_name_free call. ``bbdca691c0``
|
||||
|
||||
When processing a catalog zone member's primaries definition and there
|
||||
is a TXT record containing an invalid name TSIG key name,
|
||||
dns_name_free was incorrectly called triggering an assertion. This has
|
||||
been fixed. :gl:`#5858` :gl:`!11832`
|
||||
|
||||
- Prevent malicious DNSSEC zones from exhausting validator CPU.
|
||||
``120eaf546f``
|
||||
|
||||
A DNSSEC-signed zone could publish a DNSKEY with an unusually large
|
||||
RSA public exponent and force any validator resolving names in that
|
||||
zone to spend disproportionate CPU verifying signatures. The
|
||||
validator now rejects such DNSKEYs, matching the limit already applied
|
||||
to keys read from files or HSMs. :gl:`#5881` :gl:`!11917`
|
||||
|
||||
- Add missing parenthesis to fxhash. ``a8d412ab21``
|
||||
|
||||
The fxhash implementation had a missing parenthesis that caused it to
|
||||
diverge from Rust's reference implementation. This commit fixes this.
|
||||
:gl:`#5882` :gl:`!11857`
|
||||
|
||||
- Fix strict weak ordering violation in resign_sooner() ``13a6867757``
|
||||
|
||||
resign_sooner_values() only checked whether rhs was SOA-typed when
|
||||
resign times were equal, but did not check lhs. When both entries were
|
||||
SOA-typed with equal resign times, the comparison returned true in
|
||||
both directions, violating irreflexivity and corrupting heap
|
||||
invariants.
|
||||
|
||||
Add lhs_typepair parameter and require lhs to be non-SOA for the
|
||||
tie-breaking logic to apply. :gl:`#5884` :gl:`!11874`
|
||||
|
||||
- Fix inverted gethostname() check in rndc status. ``4a8c6a0933``
|
||||
|
||||
The replacement of named_os_gethostname() with raw gethostname()
|
||||
inverted the success check: the "localhost" fallback runs on success,
|
||||
and on failure the uninitialized hostname buffer is read by
|
||||
snprintf(), leaking stack memory via the rndc status reply.
|
||||
:gl:`#5889` :gl:`!11879`
|
||||
|
||||
- Fix rndc-confgen aborting on HMAC-SHA-384/512 keys above 512 bits.
|
||||
``c137dcd1a4``
|
||||
|
||||
`rndc-confgen -A hmac-sha384` and `-A hmac-sha512` documented a `-b`
|
||||
range of 1..1024, but any value above 512 aborted on hardened builds
|
||||
instead of producing a key. The full advertised range now works.
|
||||
:gl:`#5903` :gl:`!11903`
|
||||
|
||||
- Validate key names in rndc-confgen, tsig-keygen, ddns-confgen.
|
||||
``b8e09a5b5f``
|
||||
|
||||
The three tools embedded the key-name argument verbatim into the
|
||||
generated `named.conf` block, so a name containing characters like
|
||||
`"`, `{`, or `;` produced output that did not match the intended `key`
|
||||
clause. Key names are now restricted to letters, digits, dots,
|
||||
hyphens, and underscores. :gl:`#5904` :gl:`!11904`
|
||||
|
||||
- Do not follow symlinks when chowning the NZD database. ``ce77138b5c``
|
||||
|
||||
When `named` runs as root, the per-view NZD database file is chowned
|
||||
to the user `named` drops to. The chown call followed symlinks, so a
|
||||
symlink at the database path could redirect the ownership change to an
|
||||
unrelated file. The chown now refuses non-regular files and never
|
||||
follows symlinks. :gl:`#5905` :gl:`!11907`
|
||||
|
||||
- Prevent crafted queries from degrading RRL performance. ``cf18479882``
|
||||
|
||||
With response rate limiting enabled, an attacker sending queries from
|
||||
many spoofed source addresses could steer entries into the same slot
|
||||
of the internal rate-limit table and slow down query processing on the
|
||||
affected server. The table now uses a per-process keyed hash so the
|
||||
placement of entries cannot be predicted or influenced from the
|
||||
network. :gl:`#5906` :gl:`!11950`
|
||||
|
||||
- Fix swapped arguments in redirect2() single-label branch.
|
||||
``f5853e765f``
|
||||
|
||||
On a recursive resolver with nxdomain-redirect configured, an NXDOMAIN
|
||||
result for a query whose qname is the root could corrupt the view's
|
||||
nxdomain-redirect target, after which the redirect feature stopped
|
||||
working for every subsequent query in that view until named was
|
||||
restarted. :gl:`#5908` :gl:`!11908`
|
||||
|
||||
- Avoid named assertion failure during parent-NS lookups when none
|
||||
exist. ``90c7385000``
|
||||
|
||||
Configuring the root zone as a signed primary with parental agents (or
|
||||
with notify-on-cds-changes) caused named to exit on an internal
|
||||
assertion as soon as the DS-publication machinery tried to look up the
|
||||
parent NS RRset — the root has no parent. The lookup is now
|
||||
short-circuited cleanly.
|
||||
|
||||
Similar, a zone with no NS records in the parent caused named to exit
|
||||
in the same way. :gl:`#5910` :gl:`!11909`
|
||||
|
||||
- Remove the rndc testgen command. ``28025ceff8``
|
||||
|
||||
testgen existed only to let the rndc system test generate large
|
||||
response payloads. It accepted an unbounded count and was reachable
|
||||
from read-only control channels, so any read-only rndc client could
|
||||
drive named into memory exhaustion. The command and its supporting
|
||||
test helper are gone; remaining rndc commands already produce
|
||||
non-trivial responses, so transport coverage is preserved. :gl:`#5911`
|
||||
:gl:`!11912`
|
||||
|
||||
- Free per-command rndc state when response serialisation fails.
|
||||
``bf7ee390ba``
|
||||
|
||||
When isccc_cc_towire failed while building an rndc reply,
|
||||
control_respond returned without releasing the per-command request,
|
||||
response, HMAC secret copy, and text buffer. They were eventually
|
||||
freed when the connection closed, but until then the HMAC key copy
|
||||
stayed in named's memory. The failure path now goes through the same
|
||||
cleanup label as every other error. :gl:`#5913` :gl:`!11915`
|
||||
|
||||
- Handle KSR files with DNSKEY records before any header. ``55213079c6``
|
||||
|
||||
A DNSKEY record appearing before the first ';; KeySigningRequest'
|
||||
header in a KSR file made dnssec-ksr abort on an internal assertion
|
||||
instead of producing a structured error, killing pipelines that fed it
|
||||
crafted or corrupted input. The tool now exits with a fatal error
|
||||
naming the file and line. :gl:`#5914` :gl:`!11916`
|
||||
|
||||
- Prevent rare named crash when notifies are cancelled. ``d079ca1b92``
|
||||
|
||||
Under heavy load, named could occasionally crash when a queued
|
||||
outbound notify or zone refresh was cancelled at the moment it was
|
||||
being sent — for example, while a zone was being reloaded or removed.
|
||||
The race that caused the crash is now prevented. :gl:`#5915`
|
||||
:gl:`!11918`
|
||||
|
||||
- Stop delv from aborting on a malformed query name. ``ddf6239534``
|
||||
|
||||
delv aborts with SIGABRT instead of exiting cleanly when given a query
|
||||
name that fails wire-format conversion (e.g. a label longer than 63
|
||||
octets). After this change delv prints the parse error and exits with
|
||||
a normal failure code. :gl:`#5916` :gl:`!11921`
|
||||
|
||||
- Fix dig -x crash on excessively long arguments. ``62ced63e22``
|
||||
|
||||
dig -x crashed with a segmentation fault rather than printing an error
|
||||
when given an argument with thousands of dot-separated components. dig
|
||||
-x now rejects such inputs cleanly with "Invalid IP address".
|
||||
:gl:`#5917` :gl:`!11928`
|
||||
|
||||
- Reject RSA DNSKEYs with degenerate modulus. ``d455794d0d``
|
||||
|
||||
A crafted DNSKEY rdata whose declared exponent length consumed the
|
||||
whole buffer produced an RSA key with no modulus, which
|
||||
dnssec-importkey accepted as valid and wrote to a .private file with
|
||||
no key material. The wire-format parser now rejects RSA public keys
|
||||
with a modulus smaller than 512 bits, the lowest legitimate size
|
||||
across the RSA DNSSEC algorithms. :gl:`#5920` :gl:`!11929`
|
||||
|
||||
- Reject negative and out-of-range TTLs in dnssec-* tools.
|
||||
``31818f6417``
|
||||
|
||||
The dnssec-* tools accepted negative and out-of-range values for TTL
|
||||
flags such as dnssec-keygen -L, dnssec-signzone -t and dnssec-settime
|
||||
-L, silently turning them into TTLs of around 136 years in the
|
||||
resulting key or zone files. The flag values are now validated and
|
||||
rejected with a clear "TTL must be non-negative" or "TTL out of range"
|
||||
error. :gl:`#5923` :gl:`!11933`
|
||||
|
||||
- Fix a crash when reconfiguring while an NTA is being rechecked.
|
||||
``386177ec67``
|
||||
|
||||
When named was reconfigured or shut down while a negative trust anchor
|
||||
was being rechecked against authoritative servers, the in-flight
|
||||
recheck could outlive the view that owned it and cause `named` to
|
||||
crash. This has been fixed. :gl:`#5938` :gl:`!11948`
|
||||
|
||||
- Fix a bug in allow-query/allow-transfer catalog zone custom
|
||||
properties. ``774e08dee3``
|
||||
|
||||
The :iscman:`named` process could terminate unexpectedly when
|
||||
processing a catalog zone with an invalid ``allow-query`` or
|
||||
``allow-transfer`` custom property (i.e. having a non-APL type)
|
||||
coexisting with the valid property. This has been fixed. :gl:`#5941`
|
||||
:gl:`!11954`
|
||||
|
||||
- Fix a stack use-after-free in qpzone. ``82f67fc633``
|
||||
|
||||
In previous_closest_nsec(), a new qpreader was opened to search the
|
||||
NSEC tree. It was possible for that to be used to update a QP iterator
|
||||
object owned by the caller, and then be destroyed when the function
|
||||
returned.
|
||||
|
||||
This qpreader object isn't necessary anymore; since namespaces were
|
||||
added to the QP trie in commit 15653c54a0, we can now just reuse the
|
||||
existing reader for the main tree. :gl:`#5942` :gl:`!11955`
|
||||
|
||||
- Fix a memory leak issue in the catalog zones. ``deb3694a63``
|
||||
|
||||
The :iscman:`named` process could leak small amounts of memory when
|
||||
processing a catalog zone entry which had defined custom primary
|
||||
servers with TSIG keys using both the regular ``primaries`` custom
|
||||
property syntax and the legacy alternative syntax (``masters``) at the
|
||||
same time. This has been fixed. :gl:`#5943` :gl:`!11951`
|
||||
|
||||
- Avoid extra round trips for DS lookups when the parent delegation is
|
||||
already cached. ``07c8cddb4c``
|
||||
|
||||
DS queries could take two unnecessary extra round trips when the
|
||||
resolver sent them to the child zone instead of the parent. The child
|
||||
responds with NODATA, forcing a recovery path to rediscover the parent
|
||||
delegation even though it was already cached. The resolver now
|
||||
consults its delegation cache before starting DS fetches, sending
|
||||
queries directly to the correct parent nameservers and eliminating the
|
||||
extra latency. :gl:`!11835`
|
||||
|
||||
- Enforce dns_adb_createaddrinfofind() invariant. ``bb330e533b``
|
||||
|
||||
ADB `dns_adb_createaddrinfofind()` expects `maxaddrs` paramaters is
|
||||
always strictly positive. Add an assertion to enforce it. :gl:`!11819`
|
||||
|
||||
- Fix a bug with template filename reuse. ``cf11b88e0e``
|
||||
|
||||
When a zone filename is defined in `named.conf` which will be written
|
||||
to by the server - i.e., for secondary or dynamically updated zones -
|
||||
there is a test at configuration time to ensure that the filename is
|
||||
non-unique.
|
||||
|
||||
This test is run before the zone is actually created, so a zone
|
||||
configured using a template may not have had its filename expanded
|
||||
yet. This can cause a configuration to fail because, for example,
|
||||
multiple zones appear to using the filename `$name.db`. This has
|
||||
been fixed by adding a new function `dns_zone_expandzonefile()` and
|
||||
calling it during the uniqueness check. :gl:`!11769`
|
||||
|
||||
- Fix suppressed missing-glue check in named-checkzone. ``e75f146485``
|
||||
|
||||
named-checkzone and named-checkconf -z silently skipped the
|
||||
missing-glue check for any NS name that had already triggered an
|
||||
extra-AAAA-glue warning, so zones missing required A glue could pass
|
||||
validation and be deployed with broken delegations. :gl:`!11899`
|
||||
|
||||
- Glues from different parent are rejected. ``48d098467f``
|
||||
|
||||
The changes making BIND 9 parent-centric !11621 introduced an issue
|
||||
where it could be possible, when processing a referral, to use the
|
||||
glue to a nameserver which has a different parent than the zonecut.
|
||||
For instance:
|
||||
|
||||
AUTHORITY test.example. NS ns.test.example.
|
||||
test.example. NS ns.foo.example. test.example.
|
||||
NS ns.bar. ADDITIONAL ns.bar.
|
||||
A 1.2.3.4 ns.foo.example. A 5.6.7.8
|
||||
ns.test.example. A 9.8.7.6
|
||||
|
||||
In such situation, only the glues for `ns.foo.example.` and
|
||||
`ns.test.example.` should be used, and the glue from `ns.bar.` must be
|
||||
ignored as this is not either a sub-domain or a sibling domain, the
|
||||
parent is different (`bar.` instead of `example.`). This is now fixed.
|
||||
|
||||
Sibling glue and cyclic sibling glues are defined in RFC 9471 section
|
||||
2.2 and section 2.3. :gl:`!11873`
|
||||
|
||||
- Harden dig's EDNS option parsing against malformed replies.
|
||||
``7b87ab0236``
|
||||
|
||||
dig's parser for EDNS options in a DNS reply now stops cleanly when an
|
||||
option declares a length that runs past the end of the option data,
|
||||
rather than trusting the upstream OPT-record validator to reject the
|
||||
reply first. This is a defensive change; behavior is unchanged in
|
||||
practice. :gl:`!11937`
|
||||
|
||||
- Implement seamless outgoing TCP connection reuse. ``a61427e8ee``
|
||||
|
||||
The resolver can and will reuse outgoing TCP connections to the same
|
||||
host, as recommended by RFC 7766. This prevents a whole class of
|
||||
attacks that abuse the fact that establishing a TCP connection is
|
||||
expensive and it is fairly easy to deplete the outgoing TCP ports by
|
||||
putting them into TIME_WAIT state.
|
||||
|
||||
The number of pipelined queries per connection is capped at 256 to
|
||||
limit the impact of a connection drop. :gl:`!11845`
|
||||
|
||||
- Include <sys/endian.h> according by checking in meson. ``f27aba4d7d``
|
||||
|
||||
The <sys/endian.h> header has existed in macOS since around ~26. This
|
||||
causes the `htobeNN`/`htoleNN` macros to be redefined in
|
||||
<isc/endian.h> in terms of <libkern/OSByteOrder.h> when other system
|
||||
headers include <sys/endian.h>.
|
||||
|
||||
Fix this issue by using checking for the existence of <sys/endian.h>
|
||||
in meson and including it according to the probe result. :gl:`!11751`
|
||||
|
||||
- Pass empty string instead of NULL to ns_client_dumpmessage()
|
||||
``a0084190b4``
|
||||
|
||||
Pass "" instead of NULL to ns_client_dumpmessage() to get the log
|
||||
message printed.
|
||||
|
||||
- Possible crash when a resolver validate a static-stub zone.
|
||||
``b8dcabbd72``
|
||||
|
||||
A NULL pointer dereference could be made in some circumstances when
|
||||
resolving and validating a name under a `static-stub` zone. This is
|
||||
now fixed. :gl:`!11788`
|
||||
|
||||
- Prevent excessive priming queries to the root servers. ``5f8624df76``
|
||||
|
||||
BIND was sending a priming query to the root servers on nearly every
|
||||
recursive lookup instead of only when the cached root information
|
||||
expired. Priming now rearms only after the TTL of the fetched records
|
||||
elapses, and the refreshed root NS set is used for query routing until
|
||||
the next cycle. :gl:`!11847`
|
||||
|
||||
- Reject record sets too large to serve in DNS. ``a925af7ce6``
|
||||
|
||||
When BIND was asked to store a record set whose total size exceeds
|
||||
what fits in a DNS message, it would allocate memory and build the
|
||||
structure, then fail later at response time. Such oversized record
|
||||
sets are now rejected at the time of storage with an error, avoiding
|
||||
wasted work on data that can never be served. :gl:`!11963`
|
||||
|
||||
- Remove deadcode in `query_addbestns()` ``43c58dafcc``
|
||||
|
||||
The local variable `zfname` was released in the cleanup part of the
|
||||
function if not NULL, but it turns out it is now always NULL at that
|
||||
point.
|
||||
|
||||
The flow can get to that part only in two cases: either `zfname` is
|
||||
not NULL, and then it's ownership is moved to a different variable
|
||||
(thus, it is now NULL), or `zfname` is already NULL.
|
||||
|
||||
Removing the bit of deadcode releasing it. :gl:`!11790`
|
||||
|
||||
- Remove unneeded options in dns_zonefetch. ``a43a6cfba4``
|
||||
|
||||
In the `dns_zonefetch` mechanism, some option flags for
|
||||
`dns_resolver_createfetch()` were used for all fetches, but were
|
||||
actually only needed by the `DNSKEY` refresh fetches.
|
||||
|
||||
(Specifially, these options were `DNS_FETCHOPT_UNSHARED` and
|
||||
`DNS_FETCHOPT_NOCACHED`, which were used along with
|
||||
`DNS_FETCHOPT_NOVALIDATE` to ensure we get a new copy of the DNSKEY as
|
||||
it is currently published by the authority, without prior validation.
|
||||
Those conditions are needed for RFC 5011 trust anchor maintenace, but
|
||||
not when looking up parent-`NS` or `DSYNC` RRsets.) :gl:`!11866`
|
||||
|
||||
- Stop rndc-confgen from following symlinks when writing the keyfile.
|
||||
``468b09feb2``
|
||||
|
||||
When rndc-confgen -a (re)created the rndc control key, it followed a
|
||||
symbolic link if one happened to exist at the keyfile path: the
|
||||
existence check looked through the link, then the file was truncated,
|
||||
its ownership changed, and the key contents written into whatever file
|
||||
the link pointed at. rndc-confgen now refuses to follow symbolic links
|
||||
at the keyfile path and fails with an error instead, so the wrong file
|
||||
can no longer be overwritten by accident. :gl:`!11902`
|
||||
|
||||
- Validate -l and -L numeric arguments in named-checkzone.
|
||||
``1064d11af2``
|
||||
|
||||
named-checkzone and named-compilezone parsed the -l (max TTL) and -L
|
||||
(source serial) arguments with strtol(), so a negative value such as
|
||||
-1 silently became UINT32_MAX and out-of-range values were truncated
|
||||
to 32 bits without warning; -l in particular appeared to cap TTLs but
|
||||
no longer enforced anything. Both flags now go through
|
||||
isc_parse_uint32() and reject any value that is not a valid 32-bit
|
||||
unsigned integer. :gl:`!11900`
|
||||
|
||||
|
||||
402
doc/notes/notes-9.21.22.rst
Normal file
402
doc/notes/notes-9.21.22.rst
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
.. 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.
|
||||
|
||||
Notes for BIND 9.21.22
|
||||
----------------------
|
||||
|
||||
Security Fixes
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
- Limit resolver server list size. :cve:`2026-3592`
|
||||
|
||||
When resolving a domain with many nameservers that shared overlapping
|
||||
IP addresses (e.g., 10 NS records all pointing at the same set of
|
||||
addresses), BIND could previously waste time querying duplicate
|
||||
addresses and build up excessively large server lists. Addresses in
|
||||
the resolver's server list are now deduplicated so that each unique IP is only
|
||||
queried once per resolution attempt, regardless of how many NS records
|
||||
point to it. The number of addresses stored per nameserver name
|
||||
is also now capped at six (combined A and AAAA), preventing memory and CPU overhead from
|
||||
domains with unusually large NS/glue sets.
|
||||
|
||||
ISC would like to thank Shuhan Zhang from Tsinghua University for
|
||||
reporting this issue. :gl:`#5641`
|
||||
|
||||
- Fix GSS-API resource leak. :cve:`2026-3039`
|
||||
|
||||
A memory leak was fixed where each GSS-API TKEY negotiation leaked a
|
||||
security context inside the GSS library. An unauthenticated attacker
|
||||
could exhaust server memory by sending repeated TKEY queries to a
|
||||
server with :any:`tkey-gssapi-keytab` configured. The leaked memory was
|
||||
allocated by the GSS library, bypassing BIND's memory accounting.
|
||||
|
||||
Multi-round GSS-API negotiation (GSS_S_CONTINUE_NEEDED) is now
|
||||
rejected, as BIND never supported it correctly and Kerberos/SPNEGO
|
||||
completes in a single round.
|
||||
|
||||
ISC would like to thank Vitaly Simonovich for bringing this
|
||||
vulnerability to our attention. :gl:`#5752`
|
||||
|
||||
- Disable recursion, UPDATE, and NOTIFY for non-IN views.
|
||||
:cve:`2026-5946`
|
||||
|
||||
Recursion, dynamic updates (UPDATE), and zone change notifications
|
||||
(NOTIFY) are now disabled for views with a class other than IN (such
|
||||
as CHAOS or HESIOD); authoritative service for non-IN zones (e.g.
|
||||
version.bind in class CHAOS) continues to work as before. Servers
|
||||
configured with :namedconf:ref:`recursion yes; <recursion>`
|
||||
in a non-IN view log a warning at
|
||||
startup, and :iscman:`named-checkconf` flags the same condition. UPDATE and
|
||||
NOTIFY messages that specify the meta-classes ANY or NONE in the
|
||||
question section are now rejected with FORMERR.
|
||||
|
||||
This addresses a set of closely related security issues collectively
|
||||
identified as CVE-2026-5946. ISC would like to thank Mcsky23 for
|
||||
bringing these issues to our attention. :gl:`#5784`
|
||||
|
||||
- Avoid unbounded recursion loop. :cve:`2026-5950`
|
||||
|
||||
A bug during bad server handling could cause the resolver to enter an
|
||||
infinite loop, continuously sending queries to an upstream server with
|
||||
no exit condition, until the resolver query timeout was hit. This has
|
||||
been fixed.
|
||||
|
||||
ISC would like to thank Billy Baraja (BielraX) for bringing this issue
|
||||
to our attention. :gl:`#5804`
|
||||
|
||||
- Fix crash in resolver when SIG(0)-signed responses are received under
|
||||
load. :cve:`2026-5947`
|
||||
|
||||
A resolver could crash when handling a SIG(0)-signed response if the
|
||||
matching client query was cancelled while signature verification was
|
||||
still in progress — for example, when the recursive-clients quota was
|
||||
exhausted. This has been fixed.
|
||||
|
||||
ISC would like to thank Naoki Wakamatsu for bringing this
|
||||
vulnerability to our attention. :gl:`#5819`
|
||||
|
||||
- Fix use-after-free error in DNS-over-HTTPS when processing HTTP/2
|
||||
SETTINGS frames. :cve:`2026-3593`
|
||||
|
||||
Previously, a use-after-free vulnerability in the DNS-over-HTTPS implementation
|
||||
could cause :iscman:`named` to crash when a client sent a flood of HTTP/2
|
||||
SETTINGS frames while a DoH response was being written. This affected
|
||||
servers with DoH (DNS-over-HTTPS) enabled and has been fixed.
|
||||
|
||||
ISC would like to thank Naresh Kandula Parmar (Nottiboy) for reporting
|
||||
this. :gl:`#5755`
|
||||
|
||||
- Fix outgoing zone transfers' quota issue.
|
||||
|
||||
Unauthorized clients could consume the entire outgoing zone-transfer quota and
|
||||
block authorized zone transfer clients. This has been fixed.
|
||||
:gl:`#3589`
|
||||
|
||||
|
||||
Feature Changes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- Fix CPU spikes and slow queries when cache approaches memory limit.
|
||||
|
||||
Cache cleanup is now spread probabilistically to avoid CPU usage spikes and a
|
||||
drop in query throughput. :gl:`#5891`
|
||||
|
||||
- Implement :rfc:`3645` Section 4.1.1 key expiry check in TKEY.
|
||||
|
||||
BIND now checks for existing TSIG keys before accepting a new GSS-API
|
||||
negotiation, and deletes the key if it has expired. Previously, an
|
||||
expired GSS key would permanently block re-negotiation for that name
|
||||
until the server was restarted. :gl:`!11713`
|
||||
|
||||
- Reduce memory footprint by actively returning unused memory to the OS.
|
||||
|
||||
Previously, :iscman:`named` relied on the default allocator settings
|
||||
for releasing unused memory back to the operating system, which could
|
||||
result in unnecessarily high resident memory usage. :iscman:`named`
|
||||
now actively manages memory page purging. On systems using jemalloc,
|
||||
background cleanup threads are enabled and the dirty page decay time
|
||||
is reduced from 10 seconds to 5 seconds. Additionally, a volume-based
|
||||
decay pass is triggered after every 16 MiB of freed memory. On
|
||||
glibc-based systems, a similar volume-based mechanism using
|
||||
``malloc_trim()`` is used instead. :gl:`!11761`
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
- Use the zone file's basename as origin in DNSSEC tools.
|
||||
|
||||
In :iscman:`dnssec-signzone` and :iscman:`dnssec-verify`, when the zone origin is not
|
||||
specified using the ``-o`` parameter, the default behavior is to try to
|
||||
sign using the zone's file name as the origin. So, for example,
|
||||
``dnssec-signzone -S example.com`` will work, so long as the file name
|
||||
matches the zone name.
|
||||
|
||||
This now also works if the zone is in a different directory. For
|
||||
example, ``dnssec-signzone -S zones/example.com`` will set the origin
|
||||
value to ``example.com``. :gl:`#5678`
|
||||
|
||||
- Fix a possible race condition during zone transfers.
|
||||
|
||||
The :iscman:`named` process could terminate unexpectedly when
|
||||
processing an IXFR message during a zone transfer. This has been
|
||||
fixed. :gl:`#5767`
|
||||
|
||||
- Do not resend query after ``BADCOOKIE`` answer on TCP.
|
||||
|
||||
When an upstream server answered ``BADCOOKIE``, no matter which transport
|
||||
was used, the resolver resent the query using TCP. However, if the
|
||||
upstream server responded with ``BADCOOKIE`` again over TCP, the resolver
|
||||
would keep resending until the maximum query count was reached.
|
||||
|
||||
This is now fixed by no longer resending once the query has already
|
||||
been sent over TCP. :gl:`#5804`
|
||||
|
||||
- Fix :iscman:`named` crash when processing SIG records in dynamic updates.
|
||||
|
||||
Previously, :iscman:`named` could abort if a client sent a dynamic
|
||||
update containing a SIG record (the legacy signature type) to a zone
|
||||
configured with an update-policy. The function `dns_db_findrdataset`
|
||||
had an incorrect requirements prerequisite that prevented SIG records
|
||||
from being looked up, which was triggered as part of processing an UPDATE
|
||||
request and could be triggered remotely by any client permitted to
|
||||
send updates. This has been fixed by ensuring that SIG records are
|
||||
handled consistently with RRSIG records during update processing.
|
||||
:gl:`#5818`
|
||||
|
||||
- Fix wrong NSEC proof for empty non-terminals after IXFR.
|
||||
|
||||
When a secondary received an IXFR that transitioned a zone from
|
||||
unsigned to NSEC-signed, queries for empty non-terminal names returned
|
||||
the zone apex NSEC record instead of the NSEC that actually covered the
|
||||
queried name. The issue only occurred with incremental transfers; a
|
||||
full AXFR or a server restart resolved it. :gl:`#5824`
|
||||
|
||||
- Fix :option:`rndc modzone` behavior for a zone in named.conf.
|
||||
|
||||
If a zone was present in the configuration file and not originally
|
||||
added by :option:`rndc addzone`, :option:`rndc modzone` for that zone would succeed
|
||||
once but subsequent :option:`rndc modzone` attempts would fail. This has been
|
||||
fixed. :gl:`#5826`
|
||||
|
||||
- Fix zone verification of NSEC3 signed zones.
|
||||
|
||||
Previously, when computing the compressed bitmap during verification
|
||||
of an NSEC3-signed zone, an undersized buffer was used that resulted
|
||||
in an out-of-bounds write if there were too many active windows in the
|
||||
bitmap. This impacted the mirror zones which are NSEC3-signed,
|
||||
:iscman:`dnssec-signzone` and :iscman:`dnssec-verify`. This has been fixed.
|
||||
:gl:`#5834`
|
||||
|
||||
- Fix :option:`rndc modzone` issue with non-existing zones.
|
||||
|
||||
The :iscman:`named` process could terminate unexpectedly or become
|
||||
subject to undefined behavior when issued an :option:`rndc modzone`
|
||||
operation for a non-existing zone. This has been fixed. :gl:`#5848`
|
||||
|
||||
- Fix zone filename token-parsing bug.
|
||||
|
||||
The :iscman:`named` process could terminate unexpectedly when
|
||||
processing a catalog member zone containing special characters like
|
||||
"%" or "$", which could be interpreted as zone filename tokens and
|
||||
trigger a case-sensitivity bug in the token-parsing code. This has
|
||||
been fixed. :gl:`#5849`
|
||||
|
||||
- Prevent a crash when using both :any:`dns64` and :any:`filter-aaaa`.
|
||||
|
||||
An assertion failure could be triggered if both :any:`dns64` and the
|
||||
:any:`filter-aaaa` plugin were in use simultaneously. This happened if the
|
||||
plugin triggered a second recursion process, which then attempted to
|
||||
store DNS64 state information in a pointer that had already been set
|
||||
by the original recursion process. This has been fixed. :gl:`#5854`
|
||||
|
||||
- Fixed an assertion failure when processing catalog zones.
|
||||
|
||||
If a TXT record containing an invalid name TSIG key name was found
|
||||
when processing a catalog zone member's primaries definition,
|
||||
``dns_name_free`` was incorrectly called, triggering an assertion. This has
|
||||
been fixed. :gl:`#5858`
|
||||
|
||||
- Prevent malicious DNSSEC zones from exhausting validator CPU.
|
||||
|
||||
A DNSSEC-signed zone could publish a DNSKEY with an unusually large
|
||||
RSA public exponent and force any validator resolving names in that
|
||||
zone to spend disproportionate CPU verifying signatures. The
|
||||
validator now rejects such DNSKEYs, matching the limit already applied
|
||||
to keys read from files or HSMs. :gl:`#5881`
|
||||
|
||||
- Fix :iscman:`rndc-confgen` aborting on HMAC-SHA-384/512 keys above 512 bits.
|
||||
|
||||
:iscman:`rndc-confgen` (with either ``-A hmac-sha384`` or
|
||||
``-A hmac-sha512``) previously documented a ``-b``
|
||||
range of 1..1024, but any value above 512 aborted on hardened builds
|
||||
instead of producing a key. The full advertised range now works.
|
||||
:gl:`#5903`
|
||||
|
||||
- Validate key names in :iscman:`rndc-confgen`, :iscman:`tsig-keygen`, and :iscman:`ddns-confgen`.
|
||||
|
||||
The three tools embedded the key-name argument verbatim into the
|
||||
generated `named.conf` block, so a name containing characters like
|
||||
`"`, `{`, or `;` produced output that did not match the intended `key`
|
||||
clause. Key names are now restricted to letters, digits, dots,
|
||||
hyphens, and underscores. :gl:`#5904`
|
||||
|
||||
- Prevent crafted queries from degrading RRL performance.
|
||||
|
||||
With response rate limiting enabled, an attacker sending queries from
|
||||
many spoofed source addresses could steer entries into the same slot
|
||||
of the internal rate-limit table and slow down query processing on the
|
||||
affected server. The table now uses a per-process keyed hash so the
|
||||
placement of entries cannot be predicted or influenced from the
|
||||
network. :gl:`#5906`
|
||||
|
||||
- Prevent rare :iscman:`named` crash when notifies are cancelled.
|
||||
|
||||
Under heavy load, :iscman:`named` could occasionally crash when a queued
|
||||
outbound notify or zone refresh was cancelled at the moment it was
|
||||
being sent — for example, while a zone was being reloaded or removed.
|
||||
The race that caused the crash is now prevented. :gl:`#5915`
|
||||
|
||||
- Stop :iscman:`delv` from aborting on a malformed query name.
|
||||
|
||||
:iscman:`delv` previously aborted with SIGABRT instead of exiting cleanly when given a query
|
||||
name that failed wire-format conversion (e.g. a label longer than 63
|
||||
octets). After this change :iscman:`delv` prints the parse error and exits with
|
||||
a normal failure code. :gl:`#5916`
|
||||
|
||||
- Fix :option:`dig -x` crash on excessively long arguments.
|
||||
|
||||
Previously, :option:`dig -x` crashed with a segmentation fault rather than printing
|
||||
an error when given an argument with thousands of dot-separated components.
|
||||
:option:`dig -x` now rejects such inputs cleanly with "Invalid IP address".
|
||||
:gl:`#5917`
|
||||
|
||||
- Reject negative and out-of-range TTLs in ``dnssec-*`` tools.
|
||||
|
||||
The ``dnssec-*`` tools previously accepted negative and out-of-range values for TTL
|
||||
flags such as :option:`dnssec-keygen -L`, :option:`dnssec-signzone -t`
|
||||
and :option:`dnssec-settime -L`,
|
||||
silently turning them into TTLs of around 136 years in the
|
||||
resulting key or zone files. The flag values are now validated and
|
||||
rejected with a clear "TTL must be non-negative" or "TTL out of range"
|
||||
error. :gl:`#5923`
|
||||
|
||||
- Fix a crash when reconfiguring while an NTA is being rechecked.
|
||||
|
||||
Previously, if :iscman:`named` was reconfigured or shut down while a negative trust anchor
|
||||
was being rechecked against authoritative servers, the in-flight
|
||||
recheck could outlive the view that owned it and cause :iscman:`named` to
|
||||
crash. This has been fixed. :gl:`#5938`
|
||||
|
||||
- Fix a bug in :any:`allow-query`/:any:`allow-transfer` catalog zone custom
|
||||
properties.
|
||||
|
||||
The :iscman:`named` process could terminate unexpectedly when
|
||||
processing a catalog zone with an invalid :any:`allow-query` or
|
||||
:any:`allow-transfer` custom property (i.e. having a non-APL type)
|
||||
coexisting with the valid property. This has been fixed. :gl:`#5941`
|
||||
|
||||
- Fix a memory leak issue in catalog zones.
|
||||
|
||||
The :iscman:`named` process could leak small amounts of memory when
|
||||
processing a catalog zone entry which had defined custom primary
|
||||
servers with TSIG keys, if both the regular ``primaries`` custom
|
||||
property syntax and the legacy alternative syntax (``masters``) were used at the
|
||||
same time. This has been fixed. :gl:`#5943`
|
||||
|
||||
- Avoid extra round trips for DS lookups when the parent delegation is
|
||||
already cached.
|
||||
|
||||
Previously, DS queries could take two unnecessary extra round trips when the
|
||||
resolver sent them to the child zone instead of the parent. The child
|
||||
would respond with NODATA, forcing a recovery path to rediscover the parent
|
||||
delegation even though it was already cached. The resolver now
|
||||
consults its delegation cache before starting DS fetches, sending
|
||||
queries directly to the correct parent nameservers and eliminating the
|
||||
extra latency. :gl:`!11835`
|
||||
|
||||
- Fix suppressed missing-glue check in :iscman:`named-checkzone`.
|
||||
|
||||
:iscman:`named-checkzone` and :option:`named-checkconf -z` silently
|
||||
skipped the missing-glue check for any NS name that had already
|
||||
triggered an extra-AAAA-glue warning, so zones missing required A glue
|
||||
could pass validation and be deployed with broken delegations.
|
||||
:gl:`!11899`
|
||||
|
||||
- Reject glues from different parents.
|
||||
|
||||
The changes that made BIND 9 parent-centric (!11621) introduced an issue
|
||||
where it could be possible, when processing a referral, to use the
|
||||
glue to direct queries to a nameserver which had a different parent than the zonecut.
|
||||
For instance:::
|
||||
|
||||
AUTHORITY
|
||||
test.example. NS ns.test.example.
|
||||
test.example. NS ns.foo.example.
|
||||
test.example. NS ns.bar.
|
||||
|
||||
ADDITIONAL
|
||||
ns.bar. A 1.2.3.4
|
||||
ns.foo.example. A 5.6.7.8
|
||||
ns.test.example. A 9.8.7.6
|
||||
|
||||
In such a situation, only the glues for ``ns.foo.example.`` and
|
||||
``ns.test.example.`` should have been used; the glue from ``ns.bar.`` must be
|
||||
ignored as this is neither a sub-domain nor a sibling domain, and the
|
||||
parent is different (``bar.`` instead of ``example.``). This is now fixed.
|
||||
|
||||
Sibling glue and cyclic sibling glues are defined in :rfc:`9471` section
|
||||
2.2 and section 2.3. :gl:`!11873`
|
||||
|
||||
- Implement seamless outgoing TCP connection reuse.
|
||||
|
||||
The resolver can and will reuse outgoing TCP connections to the same
|
||||
host, as recommended by :rfc:`7766`. This prevents a whole class of
|
||||
attacks that abuse the fact that establishing a TCP connection is
|
||||
expensive and it is fairly easy to deplete the outgoing TCP ports by
|
||||
putting them into ``TIME_WAIT`` state.
|
||||
|
||||
The number of pipelined queries per connection is capped at 256 to
|
||||
limit the impact of a connection drop. :gl:`!11845`
|
||||
|
||||
- Prevent possible crash when a resolver validates a static-stub zone.
|
||||
|
||||
A NULL pointer dereference could be made in some circumstances when
|
||||
resolving and validating a name under a `static-stub` zone. This is
|
||||
now fixed. :gl:`!11788`
|
||||
|
||||
- Prevent excessive priming queries to the root servers.
|
||||
|
||||
BIND was sending a priming query to the root servers on nearly every
|
||||
recursive lookup instead of only when the cached root information
|
||||
expired. Priming now rearms only after the TTL of the fetched records
|
||||
elapses, and the refreshed root NS set is used for query routing until
|
||||
the next cycle. :gl:`!11847`
|
||||
|
||||
- Reject record sets too large to serve in DNS.
|
||||
|
||||
When BIND was asked to store a record set whose total size exceeded
|
||||
what fit in a DNS message, it would allocate memory and build the
|
||||
structure, then fail later at response time. Such oversized record
|
||||
sets are now rejected at the time of storage with an error, avoiding
|
||||
wasted work on data that can never be served. :gl:`!11963`
|
||||
|
||||
- Stop :iscman:`rndc-confgen` from following symlinks when writing the
|
||||
keyfile.
|
||||
|
||||
When :option:`rndc-confgen -a` (re)created the rndc control key, it
|
||||
followed a symbolic link if one happened to exist at the keyfile path;
|
||||
the existence check looked through the link, then the file was truncated,
|
||||
its ownership changed, and the key contents written into whatever file
|
||||
the link pointed at. :iscman:`rndc-confgen` now refuses to follow symbolic
|
||||
links at the keyfile path and fails with an error instead, so the wrong
|
||||
file can no longer be overwritten by accident. :gl:`!11902`
|
||||
|
||||
|
||||
|
|
@ -566,6 +566,9 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
|
|||
|
||||
rdtype = rdataset->type;
|
||||
|
||||
REQUIRE(rdataset->rdclass == dns_rdataclass_in);
|
||||
REQUIRE(dns_rdatatype_isaddr(rdtype));
|
||||
|
||||
switch (rdataset->trust) {
|
||||
case dns_trust_glue:
|
||||
case dns_trust_additional:
|
||||
|
|
@ -584,8 +587,6 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
|
|||
rdataset->ttl = ttlclamp(rdataset->ttl);
|
||||
}
|
||||
|
||||
REQUIRE(dns_rdatatype_isaddr(rdtype));
|
||||
|
||||
DNS_RDATASET_FOREACH(rdataset) {
|
||||
/* FIXME: Move to a separate function */
|
||||
dns_adbnamehooklist_t *hookhead = NULL;
|
||||
|
|
@ -1370,8 +1371,10 @@ log_quota(dns_adbentry_t *entry, const char *fmt, ...) {
|
|||
}
|
||||
|
||||
static void
|
||||
copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_adbname_t *name) {
|
||||
copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_adbname_t *name,
|
||||
size_t maxfindlen, size_t *findlen) {
|
||||
dns_adbentry_t *entry = NULL;
|
||||
size_t count = 0;
|
||||
|
||||
if ((find->options & DNS_ADBFIND_INET) != 0) {
|
||||
ISC_LIST_FOREACH(name->v4, namehook, name_link) {
|
||||
|
|
@ -1391,6 +1394,12 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_adbname_t *name) {
|
|||
* Found a valid entry. Add it to the find's list.
|
||||
*/
|
||||
ISC_LIST_APPEND(find->list, addrinfo, publink);
|
||||
|
||||
count++;
|
||||
if (maxfindlen - count == 0) {
|
||||
SET_IF_NOT_NULL(findlen, count);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1412,8 +1421,16 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_adbname_t *name) {
|
|||
* Found a valid entry. Add it to the find's list.
|
||||
*/
|
||||
ISC_LIST_APPEND(find->list, addrinfo, publink);
|
||||
|
||||
count++;
|
||||
if (maxfindlen - count == 0) {
|
||||
SET_IF_NOT_NULL(findlen, count);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SET_IF_NOT_NULL(findlen, count);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -1735,7 +1752,7 @@ out:
|
|||
void
|
||||
dns_adb_createaddrinfosfind(dns_adb_t *adb, isc_netaddrlist_t *addrs,
|
||||
in_port_t port, unsigned int options,
|
||||
isc_stdtime_t now, size_t maxaddrs,
|
||||
isc_stdtime_t now, size_t maxfindlen,
|
||||
dns_adbfind_t **findp, size_t *findlen) {
|
||||
dns_adbfind_t *find = NULL;
|
||||
isc_sockaddr_t sockaddr = {};
|
||||
|
|
@ -1743,7 +1760,7 @@ dns_adb_createaddrinfosfind(dns_adb_t *adb, isc_netaddrlist_t *addrs,
|
|||
REQUIRE(DNS_ADB_VALID(adb));
|
||||
REQUIRE(addrs != NULL);
|
||||
REQUIRE(findp != NULL && *findp == NULL);
|
||||
REQUIRE(maxaddrs > 0);
|
||||
REQUIRE(maxfindlen > 0);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
|
|
@ -1794,7 +1811,7 @@ dns_adb_createaddrinfosfind(dns_adb_t *adb, isc_netaddrlist_t *addrs,
|
|||
ISC_LIST_APPEND(find->list, addrinfo, publink);
|
||||
(*findlen)++;
|
||||
|
||||
if (maxaddrs - *findlen == 0) {
|
||||
if (maxfindlen - *findlen == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1825,7 +1842,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
|
|||
const dns_name_t *name, unsigned int options,
|
||||
isc_stdtime_t now, in_port_t port, unsigned int depth,
|
||||
isc_counter_t *qc, isc_counter_t *gqc, fetchctx_t *parent,
|
||||
dns_adbfind_t **findp) {
|
||||
size_t maxfindlen, dns_adbfind_t **findp, size_t *findlen) {
|
||||
isc_result_t result = ISC_R_UNEXPECTED;
|
||||
dns_adbfind_t *find = NULL;
|
||||
dns_adbname_t *adbname = NULL;
|
||||
|
|
@ -1844,6 +1861,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
|
|||
}
|
||||
REQUIRE(name != NULL);
|
||||
REQUIRE(findp != NULL && *findp == NULL);
|
||||
REQUIRE(maxfindlen > 0);
|
||||
|
||||
REQUIRE((options & DNS_ADBFIND_ADDRESSMASK) != 0);
|
||||
|
||||
|
|
@ -2056,7 +2074,7 @@ fetch:
|
|||
* Run through the name and copy out the bits we are
|
||||
* interested in.
|
||||
*/
|
||||
copy_namehook_lists(adb, find, adbname);
|
||||
copy_namehook_lists(adb, find, adbname, maxfindlen, findlen);
|
||||
|
||||
post_copy:
|
||||
if (NAME_FETCH_A(adbname)) {
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ dst_gssapi_initctx(const dns_name_t *name, isc_buffer_t *intoken,
|
|||
isc_mem_t *mctx, char **err_message) {
|
||||
isc_region_t r;
|
||||
isc_buffer_t namebuf;
|
||||
gss_name_t gname;
|
||||
gss_name_t gname = NULL;
|
||||
OM_uint32 gret, minor, ret_flags, flags;
|
||||
gss_buffer_desc gintoken, *gintokenp, gouttoken = GSS_C_EMPTY_BUFFER;
|
||||
isc_result_t result;
|
||||
|
|
@ -336,7 +336,14 @@ dst_gssapi_initctx(const dns_name_t *name, isc_buffer_t *intoken,
|
|||
GSS_SPNEGO_MECHANISM, flags, 0, NULL, gintokenp, NULL,
|
||||
&gouttoken, &ret_flags, NULL);
|
||||
|
||||
if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED) {
|
||||
switch (gret) {
|
||||
case GSS_S_COMPLETE:
|
||||
result = ISC_R_SUCCESS;
|
||||
break;
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
result = DNS_R_CONTINUE;
|
||||
break;
|
||||
default:
|
||||
gss_err_message(mctx, gret, minor, err_message);
|
||||
if (err_message != NULL && *err_message != NULL) {
|
||||
gss_log(3, "Failure initiating security context: %s",
|
||||
|
|
@ -349,9 +356,22 @@ dst_gssapi_initctx(const dns_name_t *name, isc_buffer_t *intoken,
|
|||
}
|
||||
|
||||
/*
|
||||
* XXXSRA Not handled yet: RFC 3645 3.1.1: check ret_flags
|
||||
* MUTUAL and INTEG flags, fail if either not set.
|
||||
* RFC 3645 Section 3.1.1: verify that replay detection, mutual
|
||||
* authentication and integrity are supported. The RFC mandates
|
||||
* checking replay_det_state and mutual_state; integ_avail is
|
||||
* also verified because GSS-TSIG cannot function without it.
|
||||
*/
|
||||
if (gret == GSS_S_COMPLETE &&
|
||||
(ret_flags &
|
||||
(GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG)) !=
|
||||
(GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG))
|
||||
{
|
||||
gss_log(3,
|
||||
"GSS-API context lacks required REPLAY, MUTUAL, "
|
||||
"or INTEG flags (ret_flags=0x%x)",
|
||||
(unsigned int)ret_flags);
|
||||
CLEANUP(ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 2744 states the a valid output token has a non-zero length.
|
||||
|
|
@ -361,23 +381,19 @@ dst_gssapi_initctx(const dns_name_t *name, isc_buffer_t *intoken,
|
|||
CHECK(isc_buffer_copyregion(outtoken, &r));
|
||||
}
|
||||
|
||||
if (gret == GSS_S_COMPLETE) {
|
||||
result = ISC_R_SUCCESS;
|
||||
} else {
|
||||
result = DNS_R_CONTINUE;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (gouttoken.length != 0U) {
|
||||
(void)gss_release_buffer(&minor, &gouttoken);
|
||||
}
|
||||
(void)gss_release_name(&minor, &gname);
|
||||
if (gname != NULL) {
|
||||
(void)gss_release_name(&minor, &gname);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken,
|
||||
isc_buffer_t **outtoken, dns_gss_ctx_id_t *ctxout,
|
||||
isc_buffer_t **outtokenp, dns_gss_ctx_id_t *ctxout,
|
||||
dns_name_t *principal, isc_mem_t *mctx) {
|
||||
isc_region_t r;
|
||||
isc_buffer_t namebuf;
|
||||
|
|
@ -389,16 +405,11 @@ dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken,
|
|||
isc_result_t result;
|
||||
char buf[1024];
|
||||
|
||||
REQUIRE(outtoken != NULL && *outtoken == NULL);
|
||||
REQUIRE(outtokenp != NULL && *outtokenp == NULL);
|
||||
REQUIRE(*ctxout == NULL);
|
||||
|
||||
REGION_TO_GBUFFER(*intoken, gintoken);
|
||||
|
||||
if (*ctxout == NULL) {
|
||||
context = GSS_C_NO_CONTEXT;
|
||||
} else {
|
||||
context = *ctxout;
|
||||
}
|
||||
|
||||
if (gssapi_keytab != NULL) {
|
||||
#if HAVE_GSSAPI_GSSAPI_KRB5_H || HAVE_GSSAPI_KRB5_H
|
||||
gret = gsskrb5_register_acceptor_identity(gssapi_keytab);
|
||||
|
|
@ -433,17 +444,39 @@ dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken,
|
|||
#endif
|
||||
}
|
||||
|
||||
OM_uint32 ret_flags = 0;
|
||||
|
||||
gret = gss_accept_sec_context(&minor, &context, GSS_C_NO_CREDENTIAL,
|
||||
&gintoken, GSS_C_NO_CHANNEL_BINDINGS,
|
||||
&gname, NULL, &gouttoken, NULL, NULL,
|
||||
NULL);
|
||||
&gname, NULL, &gouttoken, &ret_flags,
|
||||
NULL, NULL);
|
||||
|
||||
result = ISC_R_FAILURE;
|
||||
|
||||
switch (gret) {
|
||||
case GSS_S_COMPLETE:
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
/*
|
||||
* RFC 2743 Section 1.2.2: verify that the negotiated
|
||||
* context provides integrity protection.
|
||||
*/
|
||||
if ((ret_flags & GSS_C_INTEG_FLAG) == 0) {
|
||||
gss_log(3,
|
||||
"GSS-API context lacks required INTEG "
|
||||
"flag (ret_flags=0x%x)",
|
||||
(unsigned int)ret_flags);
|
||||
(void)gss_delete_sec_context(&minor, &context, NULL);
|
||||
result = DNS_R_INVALIDTKEY;
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
/*
|
||||
* RFC 3645 4.1.3: we don't handle GSS_S_CONTINUE_NEEDED
|
||||
* Multi-round GSS-API negotiation is not supported.
|
||||
*/
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
gss_log(3, "multi-round GSS-API negotiation not supported");
|
||||
(void)gss_delete_sec_context(&minor, &context, NULL);
|
||||
FALLTHROUGH;
|
||||
case GSS_S_DEFECTIVE_TOKEN:
|
||||
case GSS_S_DEFECTIVE_CREDENTIAL:
|
||||
case GSS_S_BAD_SIG:
|
||||
|
|
@ -456,7 +489,7 @@ dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken,
|
|||
case GSS_S_BAD_MECH:
|
||||
case GSS_S_FAILURE:
|
||||
result = DNS_R_INVALIDTKEY;
|
||||
/* fall through */
|
||||
FALLTHROUGH;
|
||||
default:
|
||||
gss_log(3, "failed gss_accept_sec_context: %s",
|
||||
gss_error_tostring(gret, minor, buf, sizeof(buf)));
|
||||
|
|
@ -467,49 +500,54 @@ dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken,
|
|||
}
|
||||
|
||||
if (gouttoken.length > 0U) {
|
||||
isc_buffer_allocate(mctx, outtoken,
|
||||
isc_buffer_allocate(mctx, outtokenp,
|
||||
(unsigned int)gouttoken.length);
|
||||
GBUFFER_TO_REGION(gouttoken, r);
|
||||
CHECK(isc_buffer_copyregion(*outtoken, &r));
|
||||
CHECK(isc_buffer_copyregion(*outtokenp, &r));
|
||||
(void)gss_release_buffer(&minor, &gouttoken);
|
||||
}
|
||||
|
||||
if (gret == GSS_S_COMPLETE) {
|
||||
gret = gss_display_name(&minor, gname, &gnamebuf, NULL);
|
||||
if (gret != GSS_S_COMPLETE) {
|
||||
gss_log(3, "failed gss_display_name: %s",
|
||||
gss_error_tostring(gret, minor, buf,
|
||||
sizeof(buf)));
|
||||
CLEANUP(ISC_R_FAILURE);
|
||||
}
|
||||
INSIST(gret == GSS_S_COMPLETE);
|
||||
|
||||
/*
|
||||
* Compensate for a bug in Solaris8's implementation
|
||||
* of gss_display_name(). Should be harmless in any
|
||||
* case, since principal names really should not
|
||||
* contain null characters.
|
||||
*/
|
||||
if (gnamebuf.length > 0U &&
|
||||
((char *)gnamebuf.value)[gnamebuf.length - 1] == '\0')
|
||||
{
|
||||
gnamebuf.length--;
|
||||
}
|
||||
|
||||
gss_log(3, "gss-api source name (accept) is %.*s",
|
||||
(int)gnamebuf.length, (char *)gnamebuf.value);
|
||||
|
||||
GBUFFER_TO_REGION(gnamebuf, r);
|
||||
isc_buffer_init(&namebuf, r.base, r.length);
|
||||
isc_buffer_add(&namebuf, r.length);
|
||||
|
||||
CHECK(dns_name_fromtext(principal, &namebuf, dns_rootname, 0));
|
||||
} else {
|
||||
result = DNS_R_CONTINUE;
|
||||
gret = gss_display_name(&minor, gname, &gnamebuf, NULL);
|
||||
if (gret != GSS_S_COMPLETE) {
|
||||
gss_log(3, "failed gss_display_name: %s",
|
||||
gss_error_tostring(gret, minor, buf, sizeof(buf)));
|
||||
CLEANUP(ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compensate for a bug in Solaris8's implementation
|
||||
* of gss_display_name(). Should be harmless in any
|
||||
* case, since principal names really should not
|
||||
* contain null characters.
|
||||
*/
|
||||
if (gnamebuf.length > 0U &&
|
||||
((char *)gnamebuf.value)[gnamebuf.length - 1] == '\0')
|
||||
{
|
||||
gnamebuf.length--;
|
||||
}
|
||||
|
||||
gss_log(3, "gss-api source name (accept) is %.*s", (int)gnamebuf.length,
|
||||
(char *)gnamebuf.value);
|
||||
|
||||
GBUFFER_TO_REGION(gnamebuf, r);
|
||||
isc_buffer_init(&namebuf, r.base, r.length);
|
||||
isc_buffer_add(&namebuf, r.length);
|
||||
|
||||
CHECK(dns_name_fromtext(principal, &namebuf, dns_rootname, 0));
|
||||
|
||||
*ctxout = context;
|
||||
|
||||
cleanup:
|
||||
if (result != ISC_R_SUCCESS && *outtokenp != NULL) {
|
||||
isc_buffer_free(outtokenp);
|
||||
}
|
||||
|
||||
if (result != ISC_R_SUCCESS && context != GSS_C_NO_CONTEXT) {
|
||||
(void)gss_delete_sec_context(&minor, &context, NULL);
|
||||
}
|
||||
|
||||
if (gnamebuf.length != 0U) {
|
||||
gret = gss_release_buffer(&minor, &gnamebuf);
|
||||
if (gret != GSS_S_COMPLETE) {
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
|
|||
const dns_name_t *name, unsigned int options,
|
||||
isc_stdtime_t now, in_port_t port, unsigned int depth,
|
||||
isc_counter_t *qc, isc_counter_t *gqc, fetchctx_t *parent,
|
||||
dns_adbfind_t **find);
|
||||
size_t maxfindlen, dns_adbfind_t **find, size_t *findlen);
|
||||
/*%<
|
||||
* 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
|
||||
|
|
@ -333,6 +333,8 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
|
|||
*
|
||||
*\li find != NULL && *find == NULL.
|
||||
*
|
||||
*\li findlen is optional, if not NULL, it will be set to the length of find.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
*\li #ISC_R_SUCCESS Addresses might have been returned, and events will be
|
||||
|
|
|
|||
|
|
@ -71,18 +71,17 @@ dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken,
|
|||
* generated by gss_accept_sec_context() to be sent to the
|
||||
* initiator
|
||||
* 'context' is a valid pointer to receive the generated context handle.
|
||||
* On the initial call, it should be a pointer to NULL, which
|
||||
* will be allocated as a dns_gss_ctx_id_t. Subsequent calls
|
||||
* should pass in the handle generated on the first call.
|
||||
*
|
||||
* Requires:
|
||||
* 'outtoken' to != NULL && *outtoken == NULL.
|
||||
* 'outtoken' != NULL && *outtoken == NULL.
|
||||
* 'context' != NULL && *context == NULL.
|
||||
*
|
||||
* Returns:
|
||||
* ISC_R_SUCCESS msg was successfully updated to include the
|
||||
* query to be sent
|
||||
* DNS_R_CONTINUE transaction still in progress
|
||||
* other an error occurred while building the message
|
||||
* ISC_R_SUCCESS msg was successfully updated to include
|
||||
* the query to be sent
|
||||
* DNS_R_INVALIDTKEY an error occurred while accepting the
|
||||
* context
|
||||
* ISC_R_FAILURE other error occurred
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
|
|
|
|||
|
|
@ -972,6 +972,17 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
|
|||
rdtype = isc_buffer_getuint16(source);
|
||||
rdclass = isc_buffer_getuint16(source);
|
||||
|
||||
/*
|
||||
* Notify and update messages need to specify the data class.
|
||||
*/
|
||||
if ((msg->opcode == dns_opcode_update ||
|
||||
msg->opcode == dns_opcode_notify) &&
|
||||
(rdclass == dns_rdataclass_none ||
|
||||
rdclass == dns_rdataclass_any))
|
||||
{
|
||||
DO_ERROR(DNS_R_FORMERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* If this class is different than the one we already read,
|
||||
* this is an error.
|
||||
|
|
|
|||
|
|
@ -761,9 +761,10 @@ dns_notify_find_address(dns_notify_t *notify) {
|
|||
goto destroy;
|
||||
}
|
||||
|
||||
result = dns_adb_createfind(adb, loop, process_notify_adb_event, notify,
|
||||
¬ify->ns, options, 0, notify->port, 0,
|
||||
NULL, NULL, NULL, ¬ify->find);
|
||||
result = dns_adb_createfind(
|
||||
adb, loop, process_notify_adb_event, notify, ¬ify->ns,
|
||||
options, 0, notify->port, 0, NULL, NULL, NULL,
|
||||
view->max_delegation_servers, ¬ify->find, NULL);
|
||||
dns_adb_detach(&adb);
|
||||
|
||||
/* Something failed? */
|
||||
|
|
|
|||
|
|
@ -376,7 +376,16 @@ struct fetchctx {
|
|||
dns_message_t *qmessage;
|
||||
ISC_LIST(resquery_t) queries;
|
||||
dns_adbfindlist_t finds;
|
||||
dns_adbfind_t *find;
|
||||
/*
|
||||
* This is a state to keep track of the latest upstream server which is
|
||||
* being queried. See `nextaddress()`.
|
||||
*
|
||||
* `addrinfo` is basically a copy of `foundaddrinfo` but came from the
|
||||
* response of the query, so fields like the SRTT/timing might have been
|
||||
* altered. So it might be possible (?) to wrap those two in an union
|
||||
* for clarity (and memory saving).
|
||||
*/
|
||||
dns_adbaddrinfo_t *foundaddrinfo;
|
||||
/*
|
||||
* altfinds are names and/or addresses of dual stack servers that
|
||||
* should be used when iterative resolution to a server is not
|
||||
|
|
@ -1417,7 +1426,7 @@ fctx_cleanup(fetchctx_t *fctx) {
|
|||
dns_adb_destroyfind(&find);
|
||||
fetchctx_unref(fctx);
|
||||
}
|
||||
fctx->find = NULL;
|
||||
fctx->foundaddrinfo = NULL;
|
||||
|
||||
ISC_LIST_FOREACH(fctx->altfinds, find, publink) {
|
||||
ISC_LIST_UNLINK(fctx->altfinds, find, publink);
|
||||
|
|
@ -3264,89 +3273,6 @@ add_bad(fetchctx_t *fctx, dns_message_t *rmessage, dns_adbaddrinfo_t *addrinfo,
|
|||
classbuf, addrbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort addrinfo list by RTT.
|
||||
*/
|
||||
static void
|
||||
sort_adbfind(dns_adbfind_t *find, unsigned int bias) {
|
||||
dns_adbaddrinfo_t *best, *curr;
|
||||
dns_adbaddrinfolist_t sorted;
|
||||
|
||||
/* Lame N^2 bubble sort. */
|
||||
ISC_LIST_INIT(sorted);
|
||||
while (!ISC_LIST_EMPTY(find->list)) {
|
||||
unsigned int best_srtt;
|
||||
best = ISC_LIST_HEAD(find->list);
|
||||
best_srtt = best->srtt;
|
||||
if (isc_sockaddr_pf(&best->sockaddr) != AF_INET6) {
|
||||
best_srtt += bias;
|
||||
}
|
||||
curr = ISC_LIST_NEXT(best, publink);
|
||||
while (curr != NULL) {
|
||||
unsigned int curr_srtt = curr->srtt;
|
||||
if (isc_sockaddr_pf(&curr->sockaddr) != AF_INET6) {
|
||||
curr_srtt += bias;
|
||||
}
|
||||
if (curr_srtt < best_srtt) {
|
||||
best = curr;
|
||||
best_srtt = curr_srtt;
|
||||
}
|
||||
curr = ISC_LIST_NEXT(curr, publink);
|
||||
}
|
||||
ISC_LIST_UNLINK(find->list, best, publink);
|
||||
ISC_LIST_APPEND(sorted, best, publink);
|
||||
}
|
||||
find->list = sorted;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort a list of finds by server RTT.
|
||||
*/
|
||||
static void
|
||||
sort_finds(dns_adbfindlist_t *findlist, unsigned int bias) {
|
||||
dns_adbfind_t *best = NULL;
|
||||
dns_adbfindlist_t sorted;
|
||||
dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;
|
||||
|
||||
/* Sort each find's addrinfo list by SRTT. */
|
||||
ISC_LIST_FOREACH(*findlist, curr, publink) {
|
||||
sort_adbfind(curr, bias);
|
||||
}
|
||||
|
||||
/* Lame N^2 bubble sort. */
|
||||
ISC_LIST_INIT(sorted);
|
||||
while (!ISC_LIST_EMPTY(*findlist)) {
|
||||
dns_adbfind_t *curr = NULL;
|
||||
unsigned int best_srtt;
|
||||
|
||||
best = ISC_LIST_HEAD(*findlist);
|
||||
bestaddrinfo = ISC_LIST_HEAD(best->list);
|
||||
INSIST(bestaddrinfo != NULL);
|
||||
best_srtt = bestaddrinfo->srtt;
|
||||
if (isc_sockaddr_pf(&bestaddrinfo->sockaddr) != AF_INET6) {
|
||||
best_srtt += bias;
|
||||
}
|
||||
curr = ISC_LIST_NEXT(best, publink);
|
||||
while (curr != NULL) {
|
||||
unsigned int curr_srtt;
|
||||
addrinfo = ISC_LIST_HEAD(curr->list);
|
||||
INSIST(addrinfo != NULL);
|
||||
curr_srtt = addrinfo->srtt;
|
||||
if (isc_sockaddr_pf(&addrinfo->sockaddr) != AF_INET6) {
|
||||
curr_srtt += bias;
|
||||
}
|
||||
if (curr_srtt < best_srtt) {
|
||||
best = curr;
|
||||
best_srtt = curr_srtt;
|
||||
}
|
||||
curr = ISC_LIST_NEXT(curr, publink);
|
||||
}
|
||||
ISC_LIST_UNLINK(*findlist, best, publink);
|
||||
ISC_LIST_APPEND(sorted, best, publink);
|
||||
}
|
||||
*findlist = sorted;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true iff the ADB find has an already pending fetch for 'type'. This
|
||||
* is used to find out whether we're in a loop, where a fetch is waiting for a
|
||||
|
|
@ -3388,7 +3314,8 @@ already_waiting_for(dns_adbfind_t *find, dns_rdatatype_t type) {
|
|||
static void
|
||||
findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
|
||||
unsigned int options, unsigned int flags, isc_stdtime_t now,
|
||||
bool *overquota, bool *need_alternate, bool *have_address) {
|
||||
bool *overquota, bool *need_alternate, bool *have_address,
|
||||
size_t maxfindlen, size_t *findlen) {
|
||||
dns_adbfind_t *find = NULL;
|
||||
dns_resolver_t *res = fctx->res;
|
||||
bool unshared = ((fctx->options & DNS_FETCHOPT_UNSHARED) != 0);
|
||||
|
|
@ -3429,7 +3356,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, options, now, res->view->dstport,
|
||||
fctx->depth + 1, fctx->qc, fctx->gqc, fctx,
|
||||
&find);
|
||||
maxfindlen, &find, findlen);
|
||||
|
||||
isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
|
||||
ISC_LOG_DEBUG(3), "fctx %p(%s): createfind for %s - %s",
|
||||
|
|
@ -3471,6 +3398,7 @@ findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & FCTX_ADDRINFO_DUALSTACK) != 0) {
|
||||
ISC_LIST_APPEND(fctx->altfinds, find, publink);
|
||||
} else {
|
||||
|
|
@ -3683,7 +3611,7 @@ fctx_getaddresses_addresses(fetchctx_t *fctx, isc_stdtime_t now,
|
|||
|
||||
ISC_LIST_FOREACH(fctx->delegset->delegs, deleg, link) {
|
||||
dns_adbfind_t *find = NULL;
|
||||
size_t maxaddrs = max_delegation_servers - *ns_processed;
|
||||
size_t maxfindlen = max_delegation_servers - *ns_processed;
|
||||
size_t findlen = 0;
|
||||
|
||||
if (*ns_processed >= max_delegation_servers) {
|
||||
|
|
@ -3703,7 +3631,7 @@ fctx_getaddresses_addresses(fetchctx_t *fctx, isc_stdtime_t now,
|
|||
fetchctx_ref(fctx);
|
||||
dns_adb_createaddrinfosfind(fctx->adb, &deleg->addresses,
|
||||
fctx->res->view->dstport, options,
|
||||
now, maxaddrs, &find, &findlen);
|
||||
now, maxfindlen, &find, &findlen);
|
||||
|
||||
if (find == NULL) {
|
||||
fetchctx_unref(fctx);
|
||||
|
|
@ -3791,6 +3719,12 @@ shufflens:
|
|||
unsigned int static_stub = 0;
|
||||
unsigned int no_fetch = 0;
|
||||
dns_name_t *ns = nameservers[i];
|
||||
size_t maxfindlen = max_delegation_servers - *ns_processed;
|
||||
size_t findlen = 0;
|
||||
|
||||
if (*ns_processed >= max_delegation_servers) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (fctx->delegset->staticstub &&
|
||||
dns_name_equal(ns, fctx->domain))
|
||||
|
|
@ -3807,15 +3741,15 @@ shufflens:
|
|||
}
|
||||
|
||||
findname(fctx, ns, 0, stdoptions | static_stub | no_fetch, 0,
|
||||
now, &overquota, need_alternatep, &have_address);
|
||||
now, &overquota, need_alternatep, &have_address,
|
||||
maxfindlen, &findlen);
|
||||
|
||||
if (!overquota) {
|
||||
*all_spilledp = false;
|
||||
}
|
||||
*ns_processed += findlen;
|
||||
|
||||
if (++(*ns_processed) >= max_delegation_servers) {
|
||||
break;
|
||||
}
|
||||
INSIST(*ns_processed <= max_delegation_servers);
|
||||
}
|
||||
|
||||
if (fctx->pending_running == 0 && !have_address) {
|
||||
|
|
@ -3841,7 +3775,8 @@ fctx_getaddresses_alternate(fetchctx_t *fctx, isc_stdtime_t now,
|
|||
if (!a->isaddress) {
|
||||
findname(fctx, &a->_u._n.name, a->_u._n.port,
|
||||
stdoptions, FCTX_ADDRINFO_DUALSTACK, now, NULL,
|
||||
NULL, NULL);
|
||||
NULL, NULL,
|
||||
fctx->res->view->max_delegation_servers, NULL);
|
||||
continue;
|
||||
}
|
||||
if (isc_sockaddr_pf(&a->_u.addr) != family) {
|
||||
|
|
@ -4032,8 +3967,6 @@ out:
|
|||
* We've found some addresses. We might still be
|
||||
* looking for more addresses.
|
||||
*/
|
||||
sort_finds(&fctx->finds, res->view->v6bias);
|
||||
sort_finds(&fctx->altfinds, 0);
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -4145,6 +4078,76 @@ possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr) {
|
|||
}
|
||||
}
|
||||
|
||||
static dns_adbaddrinfo_t *
|
||||
nextaddress(fetchctx_t *fctx) {
|
||||
dns_adbaddrinfo_t *prevai = fctx->foundaddrinfo, *lowestsrttai = NULL;
|
||||
unsigned int v6bias = fctx->res->view->v6bias, lowestsrtt = 0;
|
||||
|
||||
/*
|
||||
* Let's walk through the list of dns_adbaddrinfo_t to find the best
|
||||
* next server address to query. This is linear on the number of
|
||||
* dns_adbaddrinfo_t which are grouped in find list (for each ADB find).
|
||||
*/
|
||||
ISC_LIST_FOREACH(fctx->finds, find, publink) {
|
||||
ISC_LIST_FOREACH(find->list, ai, publink) {
|
||||
/*
|
||||
* This address has been marked already, skip it.
|
||||
*/
|
||||
if (!UNMARKED(ai)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* This address is the same as the previously used
|
||||
* address, it's a duplicate, mark it and skip it!
|
||||
*/
|
||||
if (prevai != NULL) {
|
||||
if (prevai->entry == ai->entry) {
|
||||
ai->flags |= FCTX_ADDRINFO_MARK;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark and skip this address if incompatible (i.e. IPv6
|
||||
* address on a v4 only server, or for ACL reason, etc.)
|
||||
*/
|
||||
possibly_mark(fctx, ai);
|
||||
if (!UNMARKED(ai)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* This address hasn't been tried yet and is a
|
||||
* good candidate. Let's keep track of it if it
|
||||
* has the lowest SRTT so far (or if there is no
|
||||
* address with lowest SRTT found yet).
|
||||
*/
|
||||
unsigned int aisrtt = ai->srtt;
|
||||
|
||||
if (isc_sockaddr_pf(&ai->sockaddr) != AF_INET6) {
|
||||
aisrtt += v6bias;
|
||||
}
|
||||
|
||||
if (lowestsrttai == NULL || aisrtt < lowestsrtt) {
|
||||
lowestsrttai = ai;
|
||||
lowestsrtt = aisrtt;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the next address to query. If this is NULL, we're done.
|
||||
*/
|
||||
if (lowestsrttai != NULL) {
|
||||
lowestsrttai->flags |= FCTX_ADDRINFO_MARK;
|
||||
}
|
||||
fctx->foundaddrinfo = lowestsrttai;
|
||||
|
||||
return lowestsrttai;
|
||||
}
|
||||
|
||||
static dns_adbaddrinfo_t *
|
||||
fctx_nextaddress(fetchctx_t *fctx) {
|
||||
dns_adbfind_t *find = NULL, *start = NULL;
|
||||
|
|
@ -4164,7 +4167,6 @@ fctx_nextaddress(fetchctx_t *fctx) {
|
|||
possibly_mark(fctx, ai);
|
||||
if (UNMARKED(ai)) {
|
||||
ai->flags |= FCTX_ADDRINFO_MARK;
|
||||
fctx->find = NULL;
|
||||
fctx->forwarding = true;
|
||||
|
||||
/*
|
||||
|
|
@ -4185,44 +4187,7 @@ fctx_nextaddress(fetchctx_t *fctx) {
|
|||
fctx->forwarding = false;
|
||||
FCTX_ATTR_SET(fctx, FCTX_ATTR_TRIEDFIND);
|
||||
|
||||
find = fctx->find;
|
||||
if (find == NULL) {
|
||||
find = ISC_LIST_HEAD(fctx->finds);
|
||||
} else {
|
||||
find = ISC_LIST_NEXT(find, publink);
|
||||
if (find == NULL) {
|
||||
find = ISC_LIST_HEAD(fctx->finds);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the first unmarked addrinfo.
|
||||
*/
|
||||
if (find != NULL) {
|
||||
start = find;
|
||||
do {
|
||||
ISC_LIST_FOREACH(find->list, ai, publink) {
|
||||
if (!UNMARKED(ai)) {
|
||||
continue;
|
||||
}
|
||||
possibly_mark(fctx, ai);
|
||||
if (UNMARKED(ai)) {
|
||||
ai->flags |= FCTX_ADDRINFO_MARK;
|
||||
faddrinfo = ai;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (faddrinfo != NULL) {
|
||||
break;
|
||||
}
|
||||
find = ISC_LIST_NEXT(find, publink);
|
||||
if (find == NULL) {
|
||||
find = ISC_LIST_HEAD(fctx->finds);
|
||||
}
|
||||
} while (find != start);
|
||||
}
|
||||
|
||||
fctx->find = find;
|
||||
faddrinfo = nextaddress(fctx);
|
||||
if (faddrinfo != NULL) {
|
||||
return faddrinfo;
|
||||
}
|
||||
|
|
@ -4298,6 +4263,39 @@ fctx_nextaddress(fetchctx_t *fctx) {
|
|||
return addrinfo;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
incr_query_counters(fetchctx_t *fctx) {
|
||||
isc_result_t result;
|
||||
|
||||
result = isc_counter_increment(fctx->qc);
|
||||
#if WANT_QUERYTRACE
|
||||
FCTXTRACE5("query", "max-recursion-queries, querycount=",
|
||||
isc_counter_used(fctx->qc));
|
||||
#endif
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
|
||||
ISC_LOG_DEBUG(3),
|
||||
"exceeded max queries resolving '%s' "
|
||||
"(max-recursion-queries, querycount=%u)",
|
||||
fctx->info, isc_counter_used(fctx->qc));
|
||||
} else if (fctx->gqc != NULL) {
|
||||
result = isc_counter_increment(fctx->gqc);
|
||||
#if WANT_QUERYTRACE
|
||||
FCTXTRACE5("query", "max-query-count, querycount=",
|
||||
isc_counter_used(fctx->gqc));
|
||||
#endif
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(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));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
fctx_try(fetchctx_t *fctx, bool retrying) {
|
||||
isc_result_t result;
|
||||
|
|
@ -4442,36 +4440,11 @@ fctx_try(fetchctx_t *fctx, bool retrying) {
|
|||
return;
|
||||
}
|
||||
|
||||
result = isc_counter_increment(fctx->qc);
|
||||
#if WANT_QUERYTRACE
|
||||
FCTXTRACE5("query", "max-recursion-queries, querycount=",
|
||||
isc_counter_used(fctx->qc));
|
||||
#endif
|
||||
result = incr_query_counters(fctx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
|
||||
ISC_LOG_DEBUG(3),
|
||||
"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 WANT_QUERYTRACE
|
||||
FCTXTRACE5("query", "max-query-count, querycount=",
|
||||
isc_counter_used(fctx->gqc));
|
||||
#endif
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(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;
|
||||
|
|
@ -7023,6 +6996,13 @@ is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* deny-answer-address doesn't apply to non-IN classes.
|
||||
*/
|
||||
if (rdataset->rdclass != dns_rdataclass_in) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, search the filter list for a match for each
|
||||
* address record. If a match is found, the address should be
|
||||
|
|
@ -7741,6 +7721,7 @@ resquery_response(isc_result_t eresult, isc_region_t *region, void *arg) {
|
|||
return;
|
||||
|
||||
cleanup:
|
||||
resquery_detach(&rctx->query);
|
||||
isc_mem_putanddetach(&rctx->mctx, rctx, sizeof(*rctx));
|
||||
}
|
||||
|
||||
|
|
@ -8101,6 +8082,7 @@ resquery_response_continue(void *arg, isc_result_t result) {
|
|||
rctx_done(rctx, result);
|
||||
|
||||
cleanup:
|
||||
resquery_detach(&rctx->query);
|
||||
isc_mem_putanddetach(&rctx->mctx, rctx, sizeof(*rctx));
|
||||
}
|
||||
|
||||
|
|
@ -8114,7 +8096,7 @@ static void
|
|||
rctx_respinit(resquery_t *query, fetchctx_t *fctx, isc_result_t result,
|
||||
isc_region_t *region, respctx_t *rctx) {
|
||||
*rctx = (respctx_t){ .result = result,
|
||||
.query = query,
|
||||
.query = resquery_ref(query),
|
||||
.fctx = fctx,
|
||||
.broken_type = badns_response,
|
||||
.retryopts = query->options };
|
||||
|
|
@ -9646,9 +9628,9 @@ rctx_nextserver(respctx_t *rctx, dns_message_t *message,
|
|||
* rctx_resend():
|
||||
*
|
||||
* Resend the query, probably with the options changed. Calls
|
||||
* fctx_query(), passing rctx->retryopts (which is based on
|
||||
* query->options, but may have been updated since the last time
|
||||
* fctx_query() was called).
|
||||
* fctx_query(), unless query counter limits are hit, passing
|
||||
* rctx->retryopts (which is based on query->options, but may have
|
||||
* been updated since the last time fctx_query() was called).
|
||||
*/
|
||||
static void
|
||||
rctx_resend(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo) {
|
||||
|
|
@ -9656,8 +9638,15 @@ rctx_resend(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo) {
|
|||
isc_result_t result;
|
||||
|
||||
FCTXTRACE("resend");
|
||||
inc_stats(fctx->res, dns_resstatscounter_retry);
|
||||
|
||||
CHECK(incr_query_counters(fctx));
|
||||
|
||||
result = fctx_query(fctx, addrinfo, rctx->retryopts);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
inc_stats(fctx->res, dns_resstatscounter_retry);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fctx_failure_detach(&rctx->fctx, result);
|
||||
}
|
||||
|
|
@ -9976,7 +9965,9 @@ rctx_badserver(respctx_t *rctx, isc_result_t result) {
|
|||
rctx->broken_server = DNS_R_BADVERS;
|
||||
rctx->next_server = true;
|
||||
#endif /* if DNS_EDNS_VERSION > 0 */
|
||||
} else if (rcode == dns_rcode_badcookie && rctx->query->rmessage->cc_ok)
|
||||
} else if (rcode == dns_rcode_badcookie &&
|
||||
rctx->query->rmessage->cc_ok &&
|
||||
(rctx->retryopts & DNS_FETCHOPT_TCP) == 0)
|
||||
{
|
||||
/*
|
||||
* We have recorded the new cookie.
|
||||
|
|
|
|||
|
|
@ -181,30 +181,22 @@ process_gsstkey(dns_message_t *msg, dns_name_t *name, dns_rdata_tkey_t *tkeyin,
|
|||
intoken = (isc_region_t){ tkeyin->key, tkeyin->keylen };
|
||||
result = dst_gssapi_acceptctx(tctx->gssapi_keytab, &intoken, &outtoken,
|
||||
&gss_ctx, principal, tctx->mctx);
|
||||
if (result == DNS_R_INVALIDTKEY) {
|
||||
if (tsigkey != NULL) {
|
||||
dns_tsigkey_detach(&tsigkey);
|
||||
}
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
tkeyout->error = dns_tsigerror_badkey;
|
||||
tkey_log("process_gsstkey(): dns_tsigerror_badkey");
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) {
|
||||
CHECK(result);
|
||||
CLEANUP(ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
|
||||
* Multi-round GSS-API negotiation (GSS_S_CONTINUE_NEEDED) is
|
||||
* rejected in dst_gssapi_acceptctx(), so if we reach here the
|
||||
* negotiation is complete and the principal must be set.
|
||||
*/
|
||||
if (dns_name_countlabels(principal) == 0U) {
|
||||
if (tsigkey != NULL) {
|
||||
dns_tsigkey_detach(&tsigkey);
|
||||
}
|
||||
dst_gssapi_deletectx(tctx->mctx, &gss_ctx);
|
||||
tkeyout->error = dns_tsigerror_badkey;
|
||||
tkey_log("process_gsstkey(): "
|
||||
"completed context with empty principal");
|
||||
return ISC_R_SUCCESS;
|
||||
CLEANUP(ISC_R_SUCCESS);
|
||||
} else if (tsigkey == NULL) {
|
||||
#if HAVE_GSSAPI
|
||||
OM_uint32 gret, minor, lifetime;
|
||||
|
|
@ -283,7 +275,9 @@ cleanup:
|
|||
isc_buffer_free(&outtoken);
|
||||
}
|
||||
|
||||
tkey_log("process_gsstkey(): %s", isc_result_totext(result));
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
tkey_log("process_gsstkey(): %s", isc_result_totext(result));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -678,9 +672,8 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
|
|||
NULL));
|
||||
|
||||
/*
|
||||
* XXXSRA This seems confused. If we got CONTINUE from initctx,
|
||||
* the GSS negotiation hasn't completed yet, so we can't sign
|
||||
* anything yet.
|
||||
* GSS negotiation is complete (CONTINUE returned earlier).
|
||||
* Create the TSIG key from the established context.
|
||||
*/
|
||||
CHECK(dns_tsigkey_createfromkey(tkeyname, DST_ALG_GSSAPI, dstkey, true,
|
||||
false, NULL, rtkey.inception,
|
||||
|
|
|
|||
|
|
@ -17278,9 +17278,11 @@ checkds_find_address(dns_checkds_t *checkds) {
|
|||
isc_result_t result;
|
||||
unsigned int options;
|
||||
dns_adb_t *adb = NULL;
|
||||
dns_view_t *view = NULL;
|
||||
|
||||
REQUIRE(DNS_CHECKDS_VALID(checkds));
|
||||
|
||||
view = checkds->zone->view;
|
||||
options = DNS_ADBFIND_WANTEVENT;
|
||||
if (isc_net_probeipv4() != ISC_R_DISABLED) {
|
||||
options |= DNS_ADBFIND_INET;
|
||||
|
|
@ -17289,7 +17291,7 @@ checkds_find_address(dns_checkds_t *checkds) {
|
|||
options |= DNS_ADBFIND_INET6;
|
||||
}
|
||||
|
||||
dns_view_getadb(checkds->zone->view, &adb);
|
||||
dns_view_getadb(view, &adb);
|
||||
if (adb == NULL) {
|
||||
goto destroy;
|
||||
}
|
||||
|
|
@ -17297,7 +17299,7 @@ checkds_find_address(dns_checkds_t *checkds) {
|
|||
result = dns_adb_createfind(
|
||||
adb, checkds->zone->loop, process_checkds_adb_event, checkds,
|
||||
&checkds->ns, options, 0, checkds->zone->view->dstport, 0, NULL,
|
||||
NULL, NULL, &checkds->find);
|
||||
NULL, NULL, view->max_delegation_servers, &checkds->find, NULL);
|
||||
dns_adb_detach(&adb);
|
||||
|
||||
/* Something failed? */
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <isc/mutex.h>
|
||||
#include <isc/os.h>
|
||||
#include <isc/overflow.h>
|
||||
#include <isc/random.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/stdtime.h>
|
||||
#include <isc/strerr.h>
|
||||
|
|
@ -126,7 +127,6 @@ static isc_mutex_t contextslock;
|
|||
typedef union {
|
||||
struct {
|
||||
atomic_int_fast64_t inuse;
|
||||
atomic_bool is_overmem;
|
||||
};
|
||||
char padding[ISC_OS_CACHELINE_SIZE];
|
||||
} isc__mem_stat_t;
|
||||
|
|
@ -620,7 +620,6 @@ mem_create(const char *name, isc_mem_t **ctxp, unsigned int debugging,
|
|||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(ctx->stat_s); i++) {
|
||||
atomic_init(&ctx->stat_s[i].inuse, 0);
|
||||
atomic_init(&ctx->stat_s[i].is_overmem, false);
|
||||
}
|
||||
|
||||
/* Reserve the [-1] index for ISC_TID_UNKNOWN */
|
||||
|
|
@ -1020,50 +1019,30 @@ bool
|
|||
isc_mem_isovermem(isc_mem_t *ctx) {
|
||||
REQUIRE(VALID_CONTEXT(ctx));
|
||||
|
||||
int32_t tid = isc_tid();
|
||||
|
||||
bool is_overmem = atomic_load_relaxed(&ctx->stat[tid].is_overmem);
|
||||
|
||||
if (!is_overmem) {
|
||||
/* We are not overmem, check whether we should be? */
|
||||
size_t hiwater = atomic_load_relaxed(&ctx->hi_water);
|
||||
if (hiwater == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t inuse = isc_mem_inuse(ctx);
|
||||
if (inuse <= hiwater) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ctx->debugging & ISC_MEM_DEBUGUSAGE) != 0) {
|
||||
fprintf(stderr,
|
||||
"overmem %s mctx %p inuse %zu hi_water %zu\n",
|
||||
ctx->name, ctx, inuse, hiwater);
|
||||
}
|
||||
|
||||
atomic_store_relaxed(&ctx->stat[tid].is_overmem, true);
|
||||
return true;
|
||||
} else {
|
||||
/* We are overmem, check whether we should not be? */
|
||||
size_t lowater = atomic_load_relaxed(&ctx->lo_water);
|
||||
if (lowater == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t inuse = isc_mem_inuse(ctx);
|
||||
if (inuse >= lowater) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((ctx->debugging & ISC_MEM_DEBUGUSAGE) != 0) {
|
||||
fprintf(stderr,
|
||||
"overmem %s mctx %p inuse %zu lo_water %zu\n",
|
||||
ctx->name, ctx, inuse, lowater);
|
||||
}
|
||||
atomic_store_relaxed(&ctx->stat[tid].is_overmem, false);
|
||||
size_t hiwater = atomic_load_relaxed(&ctx->hi_water);
|
||||
if (hiwater == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t inuse = isc_mem_inuse(ctx);
|
||||
if (inuse >= hiwater) {
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t lowater = atomic_load_relaxed(&ctx->lo_water);
|
||||
if (inuse <= lowater) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Between lo_water and hi_water, return true with a probability
|
||||
* that ramps linearly from 0 at lo_water to 1 at hi_water. This
|
||||
* spreads cache cleaning across many inserts instead of triggering
|
||||
* a thundering herd once the hi_water mark is crossed.
|
||||
*/
|
||||
uint32_t prob = (uint32_t)(((uint64_t)(inuse - lowater) * 256) /
|
||||
(hiwater - lowater));
|
||||
return isc_random8() < prob;
|
||||
}
|
||||
|
||||
const char *
|
||||
|
|
|
|||
|
|
@ -2743,6 +2743,8 @@ server_httpsend(isc_nmhandle_t *handle, isc_nmsocket_t *sock,
|
|||
} else {
|
||||
cb(handle, result, cbarg);
|
||||
}
|
||||
|
||||
isc_buffer_initnull(&sock->h2->wbuf);
|
||||
isc__nm_uvreq_put(&req);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2869,13 +2869,17 @@ check_mirror_zone_notify(const cfg_obj_t *zoptions, const char *znamestr) {
|
|||
*/
|
||||
static bool
|
||||
check_recursion(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
||||
const cfg_obj_t *goptions, cfg_aclconfctx_t *aclctx,
|
||||
isc_mem_t *mctx) {
|
||||
dns_rdataclass_t vclass, const cfg_obj_t *goptions,
|
||||
cfg_aclconfctx_t *aclctx, isc_mem_t *mctx) {
|
||||
dns_acl_t *acl = NULL;
|
||||
const cfg_obj_t *obj;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
bool retval = true;
|
||||
|
||||
if (vclass != dns_rdataclass_in) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the "recursion" option first.
|
||||
*/
|
||||
|
|
@ -3827,7 +3831,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
|||
* contradicts the purpose of the former.
|
||||
*/
|
||||
if (ztype == CFG_ZONE_MIRROR &&
|
||||
!check_recursion(config, voptions, goptions, aclctx, mctx))
|
||||
!check_recursion(config, voptions, zclass, goptions, aclctx, mctx))
|
||||
{
|
||||
cfg_obj_log(zoptions, ISC_LOG_ERROR,
|
||||
"zone '%s': mirror zones cannot be used if "
|
||||
|
|
@ -5646,6 +5650,17 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
|||
|
||||
cfg_aclconfctx_create(mctx, &aclctx);
|
||||
|
||||
if (vclass != dns_rdataclass_in) {
|
||||
if (check_recursion(config, voptions, dns_rdataclass_in,
|
||||
options, aclctx, mctx))
|
||||
{
|
||||
cfg_obj_log(opts, ISC_LOG_WARNING,
|
||||
"recursion will be disabled for "
|
||||
"non-IN view '%s'",
|
||||
viewname);
|
||||
}
|
||||
}
|
||||
|
||||
if (voptions != NULL) {
|
||||
(void)cfg_map_get(voptions, "zone", &zones);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include <dns/dispatch.h>
|
||||
#include <dns/dnstap.h>
|
||||
#include <dns/edns.h>
|
||||
#include <dns/enumclass.h>
|
||||
#include <dns/message.h>
|
||||
#include <dns/peer.h>
|
||||
#include <dns/rcode.h>
|
||||
|
|
@ -2082,7 +2083,9 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
}
|
||||
}
|
||||
|
||||
if (client->message->rdclass == 0) {
|
||||
char classbuf[DNS_RDATACLASS_FORMATSIZE];
|
||||
switch (client->message->rdclass) {
|
||||
case dns_rdataclass_reserved0:
|
||||
if ((client->inner.attributes & NS_CLIENTATTR_WANTCOOKIE) !=
|
||||
0 &&
|
||||
client->message->opcode == dns_opcode_query &&
|
||||
|
|
@ -2102,12 +2105,46 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
return;
|
||||
}
|
||||
|
||||
ns_client_dumpmessage(client,
|
||||
"message class could not be determined");
|
||||
ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
|
||||
return;
|
||||
case dns_rdataclass_in:
|
||||
break;
|
||||
case dns_rdataclass_chaos:
|
||||
break;
|
||||
case dns_rdataclass_hs:
|
||||
break;
|
||||
case dns_rdataclass_none:
|
||||
if (client->message->opcode != dns_opcode_update) {
|
||||
ns_client_dumpmessage(client,
|
||||
"message class NONE can be only "
|
||||
"used in DNS updates");
|
||||
ns_client_error(client, DNS_R_FORMERR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case dns_rdataclass_any:
|
||||
/*
|
||||
* Required for TKEY negotiation.
|
||||
*/
|
||||
if (client->message->tkey == 0) {
|
||||
ns_client_dumpmessage(client,
|
||||
"message class ANY can be only "
|
||||
"used for TKEY negotiation");
|
||||
ns_client_error(client, DNS_R_FORMERR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dns_rdataclass_format(client->message->rdclass, classbuf,
|
||||
sizeof(classbuf));
|
||||
ns_client_dumpmessage(client, "");
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
|
||||
"message class could not be determined");
|
||||
ns_client_dumpmessage(client, "message class could not be "
|
||||
"determined");
|
||||
ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
|
||||
"invalid message class: %s", classbuf);
|
||||
|
||||
ns_client_error(client, DNS_R_NOTIMP);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2192,9 +2229,6 @@ ns_client_request_continue(void *arg) {
|
|||
"SIG(0) checks quota reached");
|
||||
|
||||
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");
|
||||
}
|
||||
|
|
@ -2204,12 +2238,11 @@ ns_client_request_continue(void *arg) {
|
|||
dns_rdataclass_format(client->message->rdclass,
|
||||
classname, sizeof(classname));
|
||||
|
||||
ns_client_dumpmessage(client, "");
|
||||
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");
|
||||
}
|
||||
|
||||
dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL);
|
||||
|
|
@ -2459,6 +2492,10 @@ ns_client_request_continue(void *arg) {
|
|||
break;
|
||||
case dns_opcode_update:
|
||||
CTRACE("update");
|
||||
if (client->inner.view->rdclass != dns_rdataclass_in) {
|
||||
ns_client_error(client, DNS_R_NOTIMP);
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_DNSTAP
|
||||
dns_dt_send(client->inner.view, DNS_DTTYPE_UQ,
|
||||
&client->inner.peeraddr,
|
||||
|
|
@ -2472,6 +2509,10 @@ ns_client_request_continue(void *arg) {
|
|||
break;
|
||||
case dns_opcode_notify:
|
||||
CTRACE("notify");
|
||||
if (client->inner.view->rdclass != dns_rdataclass_in) {
|
||||
ns_client_error(client, DNS_R_NOTIMP);
|
||||
break;
|
||||
}
|
||||
ns_client_settimeout(client, 60);
|
||||
ns_notify_start(client, client->inner.handle);
|
||||
break;
|
||||
|
|
@ -2835,7 +2876,7 @@ ns_client_dumpmessage(ns_client_t *client, const char *reason) {
|
|||
int len = 1024;
|
||||
isc_result_t result;
|
||||
|
||||
if (!isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
|
||||
if (!isc_log_wouldlog(ISC_LOG_DEBUG(1)) || reason == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -966,7 +966,9 @@ ssu_checkrr(void *data, rr_t *rr) {
|
|||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
target = &ptr.ptr;
|
||||
}
|
||||
if (rr->rdata.type == dns_rdatatype_srv) {
|
||||
if (rr->rdata.rdclass == dns_rdataclass_in &&
|
||||
rr->rdata.type == dns_rdatatype_srv)
|
||||
{
|
||||
result = dns_rdata_tostruct(&rr->rdata, &srv, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
target = &srv.target;
|
||||
|
|
@ -1311,7 +1313,10 @@ replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
if (db_rr->type == dns_rdatatype_wks) {
|
||||
|
||||
if (db_rr->rdclass == dns_rdataclass_in &&
|
||||
db_rr->type == dns_rdatatype_wks)
|
||||
{
|
||||
/*
|
||||
* Compare the address and protocol fields only. These
|
||||
* form the first five bytes of the RR data. Do a
|
||||
|
|
@ -1451,9 +1456,8 @@ add_rr_prepare_action(void *data, rr_t *rr) {
|
|||
* 'rdata', and 'ttl', respectively.
|
||||
*/
|
||||
static void
|
||||
get_current_rr(dns_rdataclass_t zoneclass, dns_name_t *name, dns_rdata_t *rdata,
|
||||
dns_rdatatype_t *covers, dns_ttl_t *ttl,
|
||||
dns_rdataclass_t *update_class) {
|
||||
get_current_rr(dns_name_t *name, dns_rdata_t *rdata, dns_rdatatype_t *covers,
|
||||
dns_ttl_t *ttl, dns_rdataclass_t *update_class) {
|
||||
dns_rdataset_t *rdataset;
|
||||
isc_result_t result;
|
||||
rdataset = ISC_LIST_HEAD(name->list);
|
||||
|
|
@ -1466,7 +1470,7 @@ get_current_rr(dns_rdataclass_t zoneclass, dns_name_t *name, dns_rdata_t *rdata,
|
|||
dns_rdataset_current(rdataset, rdata);
|
||||
INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE);
|
||||
*update_class = rdata->rdclass;
|
||||
rdata->rdclass = zoneclass;
|
||||
rdata->rdclass = dns_rdataclass_in;
|
||||
}
|
||||
|
||||
/*%
|
||||
|
|
@ -1562,7 +1566,6 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
|
|||
dns_message_t *request = client->message;
|
||||
isc_mem_t *mctx = client->manager->mctx;
|
||||
dns_aclenv_t *env = client->manager->aclenv;
|
||||
dns_rdataclass_t zoneclass;
|
||||
dns_rdatatype_t covers;
|
||||
dns_name_t *zonename = NULL;
|
||||
unsigned int *maxbytype = NULL;
|
||||
|
|
@ -1574,11 +1577,13 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
|
|||
|
||||
CHECK(dns_zone_getdb(zone, &db));
|
||||
zonename = dns_db_origin(db);
|
||||
zoneclass = dns_db_class(db);
|
||||
dns_zone_getssutable(zone, &ssutable);
|
||||
options = dns_zone_getoptions(zone);
|
||||
dns_db_currentversion(db, &ver);
|
||||
|
||||
/* Updates are only supported for class IN. */
|
||||
INSIST(dns_zone_getclass(zone) == dns_rdataclass_in);
|
||||
|
||||
/*
|
||||
* Update message processing can leak record existence information
|
||||
* so check that we are allowed to query this zone. Additionally,
|
||||
|
|
@ -1623,13 +1628,12 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
|
|||
dns_rdataclass_t update_class;
|
||||
|
||||
INSIST(ssutable == NULL || update < maxbytypelen);
|
||||
get_current_rr(zoneclass, name, &rdata, &covers, &ttl,
|
||||
&update_class);
|
||||
get_current_rr(name, &rdata, &covers, &ttl, &update_class);
|
||||
|
||||
if (!dns_name_issubdomain(name, zonename)) {
|
||||
FAILC(DNS_R_NOTZONE, "update RR is outside zone");
|
||||
}
|
||||
if (update_class == zoneclass) {
|
||||
if (update_class == dns_rdataclass_in) {
|
||||
/*
|
||||
* Check for meta-RRs. The RFC2136 pseudocode says
|
||||
* check for ANY|AXFR|MAILA|MAILB, but the text adds
|
||||
|
|
@ -1643,6 +1647,7 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
|
|||
CLEANUP(DNS_R_REFUSED);
|
||||
}
|
||||
if ((options & DNS_ZONEOPT_CHECKSVCB) != 0 &&
|
||||
rdata.rdclass == dns_rdataclass_in &&
|
||||
rdata.type == dns_rdatatype_svcb)
|
||||
{
|
||||
result = dns_rdata_checksvcb(name, &rdata);
|
||||
|
|
@ -1731,7 +1736,6 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
|
|||
}
|
||||
|
||||
if (update_class == dns_rdataclass_any &&
|
||||
zoneclass == dns_rdataclass_in &&
|
||||
(rdata.type == dns_rdatatype_ptr ||
|
||||
rdata.type == dns_rdatatype_srv))
|
||||
{
|
||||
|
|
@ -2629,7 +2633,6 @@ update_action(void *arg) {
|
|||
isc_mem_t *mctx = client->manager->mctx;
|
||||
dns_rdatatype_t covers;
|
||||
dns_message_t *request = client->message;
|
||||
dns_rdataclass_t zoneclass;
|
||||
dns_name_t *zonename = NULL;
|
||||
dns_fixedname_t tmpnamefixed;
|
||||
dns_name_t *tmpname = NULL;
|
||||
|
|
@ -2646,9 +2649,10 @@ update_action(void *arg) {
|
|||
|
||||
CHECK(dns_zone_getdb(zone, &db));
|
||||
zonename = dns_db_origin(db);
|
||||
zoneclass = dns_db_class(db);
|
||||
options = dns_zone_getoptions(zone);
|
||||
|
||||
INSIST(dns_zone_getclass(zone) == dns_rdataclass_in);
|
||||
|
||||
is_inline = (!dns_zone_israw(zone) && dns_zone_issecure(zone));
|
||||
is_maintain = (dns_zone_getkasp(zone) != NULL) && !dns_zone_israw(zone);
|
||||
is_signing = is_inline || is_maintain;
|
||||
|
|
@ -2669,8 +2673,7 @@ update_action(void *arg) {
|
|||
dns_rdataclass_t update_class;
|
||||
bool flag;
|
||||
|
||||
get_current_rr(zoneclass, name, &rdata, &covers, &ttl,
|
||||
&update_class);
|
||||
get_current_rr(name, &rdata, &covers, &ttl, &update_class);
|
||||
|
||||
if (ttl != 0) {
|
||||
PREREQFAILC(DNS_R_FORMERR,
|
||||
|
|
@ -2733,7 +2736,7 @@ update_action(void *arg) {
|
|||
"prerequisite not satisfied");
|
||||
}
|
||||
}
|
||||
} else if (update_class == zoneclass) {
|
||||
} else if (update_class == dns_rdataclass_in) {
|
||||
/* "temp<rr.name, rr.type> += rr;" */
|
||||
temp_append(&temp, name, &rdata);
|
||||
} else {
|
||||
|
|
@ -2784,10 +2787,9 @@ update_action(void *arg) {
|
|||
|
||||
INSIST(ssutable == NULL || maxidx < maxbytypelen);
|
||||
|
||||
get_current_rr(zoneclass, name, &rdata, &covers, &ttl,
|
||||
&update_class);
|
||||
get_current_rr(name, &rdata, &covers, &ttl, &update_class);
|
||||
|
||||
if (update_class == zoneclass) {
|
||||
if (update_class == dns_rdataclass_in) {
|
||||
/*
|
||||
* RFC1123 doesn't allow MF and MD in master files.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -738,6 +738,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
|
|||
bool is_poll = false;
|
||||
bool is_dlz = false;
|
||||
bool is_ixfr = false;
|
||||
bool is_quota_applied = false;
|
||||
bool useviewacl = false;
|
||||
uint32_t begin_serial = 0, current_serial;
|
||||
|
||||
|
|
@ -754,16 +755,6 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
|
|||
|
||||
ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
|
||||
ISC_LOG_DEBUG(6), "%s request", mnemonic);
|
||||
/*
|
||||
* Apply quota.
|
||||
*/
|
||||
result = isc_quota_acquire(&client->manager->sctx->xfroutquota);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
|
||||
ISC_LOG_WARNING, "%s request denied: %s",
|
||||
mnemonic, isc_result_totext(result));
|
||||
goto max_quota;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpret the question section.
|
||||
|
|
@ -922,6 +913,19 @@ got_soa:
|
|||
FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply quota after ACL is checked, so that unauthorized clients
|
||||
* can not starve the authorized clients.
|
||||
*/
|
||||
result = isc_quota_acquire(&client->manager->sctx->xfroutquota);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
|
||||
ISC_LOG_WARNING, "%s request denied: %s",
|
||||
mnemonic, isc_result_totext(result));
|
||||
goto cleanup;
|
||||
}
|
||||
is_quota_applied = true;
|
||||
|
||||
/*
|
||||
* Look up the requesting server in the peer table.
|
||||
*/
|
||||
|
|
@ -1060,7 +1064,7 @@ have_stream:
|
|||
CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
|
||||
/*
|
||||
* Create the xfrout context object. This transfers the ownership
|
||||
* of "stream", "db", "ver", and "quota" to the xfrout context object.
|
||||
* of "stream", "db" and "ver" to the xfrout context object.
|
||||
*/
|
||||
|
||||
if (is_dlz) {
|
||||
|
|
@ -1179,10 +1183,13 @@ cleanup:
|
|||
}
|
||||
|
||||
if (xfr != NULL) {
|
||||
/* The quota will be released in xfrout_ctx_destroy(). */
|
||||
INSIST(is_quota_applied);
|
||||
xfrout_fail(xfr, result, "setting up zone transfer");
|
||||
} else if (result != ISC_R_SUCCESS) {
|
||||
isc_quota_release(&client->manager->sctx->xfroutquota);
|
||||
max_quota:
|
||||
if (is_quota_applied) {
|
||||
isc_quota_release(&client->manager->sctx->xfroutquota);
|
||||
}
|
||||
ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
|
||||
NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(3),
|
||||
"zone transfer setup failed");
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ ISC_LOOP_TEST_IMPL(overmempurge_bigrdata) {
|
|||
dns_db_t *db = NULL;
|
||||
isc_mem_t *mctx = NULL;
|
||||
isc_stdtime_t now = isc_stdtime_now();
|
||||
size_t i;
|
||||
size_t i = 0;
|
||||
|
||||
isc_mem_create("test", &mctx);
|
||||
|
||||
|
|
@ -140,21 +140,21 @@ ISC_LOOP_TEST_IMPL(overmempurge_bigrdata) {
|
|||
isc_mem_setwater(mctx, hiwater, lowater);
|
||||
|
||||
/*
|
||||
* Add cache entries with minimum size of data until 'overmem'
|
||||
* condition is triggered.
|
||||
* This should eventually happen, but we also limit the number of
|
||||
* iteration to avoid an infinite loop in case something gets wrong.
|
||||
* Add a lot of data entries sufficient to push the context
|
||||
* above the hi_water mark.
|
||||
*/
|
||||
for (i = 0; !isc_mem_isovermem(mctx) && i < (maxcache / 10); i++) {
|
||||
overmempurge_addrdataset(db, now, i, 50053, 0, false);
|
||||
while (isc_mem_inuse(mctx) < hiwater) {
|
||||
overmempurge_addrdataset(db, now, i, 50053, 0, true);
|
||||
i++;
|
||||
}
|
||||
assert_true(isc_mem_isovermem(mctx));
|
||||
assert_true(isc_mem_inuse(mctx) >= hiwater);
|
||||
assert_true(isc_mem_inuse(mctx) < maxcache);
|
||||
|
||||
/*
|
||||
* Then try to add the same number of entries, each has very large data.
|
||||
* 'overmem purge' should keep the total cache size from exceeding
|
||||
* the 'hiwater' mark too much. So we should be able to assume the
|
||||
* cache size doesn't reach the "max".
|
||||
* Probabilistic LRU cleaning should keep the total cache size from
|
||||
* exceeding the 'hiwater' mark too much. So we should be able to
|
||||
* assume the cache size doesn't reach the "max".
|
||||
*/
|
||||
while (i-- > 0) {
|
||||
overmempurge_addrdataset(db, now, i, 50054,
|
||||
|
|
@ -180,7 +180,7 @@ ISC_LOOP_TEST_IMPL(overmempurge_longname) {
|
|||
dns_db_t *db = NULL;
|
||||
isc_mem_t *mctx = NULL;
|
||||
isc_stdtime_t now = isc_stdtime_now();
|
||||
size_t i;
|
||||
size_t i = 0;
|
||||
|
||||
isc_mem_create("test", &mctx);
|
||||
|
||||
|
|
@ -192,21 +192,21 @@ ISC_LOOP_TEST_IMPL(overmempurge_longname) {
|
|||
isc_mem_setwater(mctx, hiwater, lowater);
|
||||
|
||||
/*
|
||||
* Add cache entries with minimum size of data until 'overmem'
|
||||
* condition is triggered.
|
||||
* This should eventually happen, but we also limit the number of
|
||||
* iteration to avoid an infinite loop in case something gets wrong.
|
||||
* Add a lot of data entries sufficient to push the context
|
||||
* above the hi_water mark.
|
||||
*/
|
||||
for (i = 0; !isc_mem_isovermem(mctx) && i < (maxcache / 10); i++) {
|
||||
overmempurge_addrdataset(db, now, i, 50053, 0, false);
|
||||
while (isc_mem_inuse(mctx) < hiwater) {
|
||||
overmempurge_addrdataset(db, now, i, 50053, 0, true);
|
||||
i++;
|
||||
}
|
||||
assert_true(isc_mem_isovermem(mctx));
|
||||
assert_true(isc_mem_inuse(mctx) >= hiwater);
|
||||
assert_true(isc_mem_inuse(mctx) < maxcache);
|
||||
|
||||
/*
|
||||
* Then try to add the same number of entries, each has very long name.
|
||||
* 'overmem purge' should keep the total cache size from not exceeding
|
||||
* the 'hiwater' mark too much. So we should be able to assume the cache
|
||||
* size doesn't reach the "max".
|
||||
* Probabilistic LRU cleaning should keep the total cache size from
|
||||
* exceeding the 'hiwater' mark too much. So we should be able to
|
||||
* assume the cache size doesn't reach the "max".
|
||||
*/
|
||||
while (i-- > 0) {
|
||||
overmempurge_addrdataset(db, now, i, 50054, 0, true);
|
||||
|
|
|
|||
|
|
@ -291,6 +291,17 @@ ISC_RUN_TEST_IMPL(isc_mem_reallocate) {
|
|||
isc_mem_free(isc_g_mctx, data);
|
||||
}
|
||||
|
||||
static bool
|
||||
at_least_one_overmem(isc_mem_t *mctx) {
|
||||
for (size_t i = 0; i < UINT16_MAX; i++) {
|
||||
/* The overmem is probability based in this range */
|
||||
if (isc_mem_isovermem(mctx)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ISC_RUN_TEST_IMPL(isc_mem_overmem) {
|
||||
isc_mem_t *mctx = NULL;
|
||||
isc_mem_create("test", &mctx);
|
||||
|
|
@ -298,27 +309,27 @@ ISC_RUN_TEST_IMPL(isc_mem_overmem) {
|
|||
|
||||
isc_mem_setwater(mctx, 1024, 512);
|
||||
|
||||
/* inuse < lo_water */
|
||||
/* inuse <= lo_water is always false */
|
||||
void *data1 = isc_mem_allocate(mctx, 256);
|
||||
assert_false(isc_mem_isovermem(mctx));
|
||||
|
||||
/* lo_water < inuse < hi_water */
|
||||
/* lo_water < inuse < hi_water might be true or false */
|
||||
void *data2 = isc_mem_allocate(mctx, 512);
|
||||
assert_false(isc_mem_isovermem(mctx));
|
||||
assert_true(at_least_one_overmem(mctx));
|
||||
|
||||
/* hi_water < inuse */
|
||||
/* hi_water <= inuse is always true */
|
||||
void *data3 = isc_mem_allocate(mctx, 512);
|
||||
assert_true(isc_mem_isovermem(mctx));
|
||||
|
||||
/* lo_water < inuse < hi_water */
|
||||
/* lo_water < inuse < hi_water might be true or false */
|
||||
isc_mem_free(mctx, data2);
|
||||
assert_true(isc_mem_isovermem(mctx));
|
||||
assert_true(at_least_one_overmem(mctx));
|
||||
|
||||
/* inuse < lo_water */
|
||||
/* inuse <= lo_water is always false */
|
||||
isc_mem_free(mctx, data3);
|
||||
assert_false(isc_mem_isovermem(mctx));
|
||||
|
||||
/* inuse == 0 */
|
||||
/* inuse == 0 is always false */
|
||||
isc_mem_free(mctx, data1);
|
||||
assert_false(isc_mem_isovermem(mctx));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue