mirror of
https://github.com/isc-projects/bind9.git
synced 2026-07-11 22:05:27 -04:00
System test covering SERVFAIL cache and CNAME
Add a system test for the case where resolution SERVFAILs because the
fetch context reaches the `max-query-count` threshold while following a
CNAME.
Resolving the CNAME target independently should still work, because the
SERVFAIL cache stores the original query name rather than the target.
(cherry picked from commit d238b8eece)
This commit is contained in:
parent
294df42043
commit
a404d72d36
3 changed files with 113 additions and 0 deletions
53
bin/tests/system/sfcache_cname/ans1/ans.py
Normal file
53
bin/tests/system/sfcache_cname/ans1/ans.py
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# 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.name
|
||||
import dns.rcode
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
import dns.rrset
|
||||
|
||||
from isctest.asyncserver import AsyncDnsServer, QnameQtypeHandler, StaticResponseHandler
|
||||
|
||||
|
||||
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 Tld1Handler(QnameQtypeHandler, StaticResponseHandler):
|
||||
qnames = ["foo.tld1."]
|
||||
qtypes = [dns.rdatatype.A]
|
||||
answer = [rrset("foo.tld1.", dns.rdatatype.CNAME, "tld2.")]
|
||||
|
||||
|
||||
class Tld2Handler(QnameQtypeHandler, StaticResponseHandler):
|
||||
qnames = ["tld2."]
|
||||
qtypes = [dns.rdatatype.A]
|
||||
answer = [rrset("tld2.", dns.rdatatype.A, "1.2.3.4")]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
server = AsyncDnsServer(default_aa=True, default_rcode=dns.rcode.NOERROR)
|
||||
server.install_response_handlers(
|
||||
Tld1Handler(),
|
||||
Tld2Handler(),
|
||||
)
|
||||
server.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
26
bin/tests/system/sfcache_cname/ns2/named.conf.j2
Normal file
26
bin/tests/system/sfcache_cname/ns2/named.conf.j2
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
options {
|
||||
query-source address @ns.ip@;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { @ns.ip@; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
dnssec-validation no;
|
||||
qname-minimization off;
|
||||
servfail-ttl 5;
|
||||
max-query-count 2;
|
||||
};
|
||||
|
||||
{% include "_common/controls.conf.j2" %}
|
||||
|
||||
zone "tld1." {
|
||||
type forward;
|
||||
forward only;
|
||||
forwarders { 10.53.0.1; };
|
||||
};
|
||||
|
||||
zone "tld2." {
|
||||
type forward;
|
||||
forward only;
|
||||
forwarders { 10.53.0.1; };
|
||||
};
|
||||
34
bin/tests/system/sfcache_cname/tests_sfcache_cname.py
Normal file
34
bin/tests/system/sfcache_cname/tests_sfcache_cname.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# 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.message
|
||||
|
||||
import isctest
|
||||
|
||||
|
||||
# A SERVFAIL produced while following a CNAME must be cached against the
|
||||
# original query name, not the CNAME target.
|
||||
#
|
||||
# ans1 serves "foo.tld1 CNAME tld2" and "tld2 A 1.2.3.4"; ns2 forwards
|
||||
# both zones to it with "max-query-count 2". Resolving "foo.tld1/A"
|
||||
# follows the CNAME to "tld2" and then exhausts the query budget, so the
|
||||
# client gets SERVFAIL. That failure must be cached under the original
|
||||
# name ("foo.tld1"), so a subsequent direct query for the CNAME target
|
||||
# ("tld2") is not blocked by the SERVFAIL cache and resolves normally.
|
||||
def test_sfcache_cname(ns2):
|
||||
msg = dns.message.make_query("foo.tld1.", "A")
|
||||
res = isctest.query.udp(msg, ns2.ip)
|
||||
isctest.check.servfail(res)
|
||||
|
||||
msg = dns.message.make_query("tld2.", "A")
|
||||
res = isctest.query.udp(msg, ns2.ip)
|
||||
isctest.check.noerror(res)
|
||||
Loading…
Reference in a new issue