diff --git a/bin/tests/system/sfcache_cname/ns1/named.conf.j2 b/bin/tests/system/sfcache_cname/ns1/named.conf.j2 new file mode 100644 index 0000000000..9f2271e709 --- /dev/null +++ b/bin/tests/system/sfcache_cname/ns1/named.conf.j2 @@ -0,0 +1,16 @@ +options { + query-source address @ns.ip@; + notify-source @ns.ip@; + transfer-source @ns.ip@; + port @PORT@; + pid-file "named.pid"; + listen-on { @ns.ip@; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/sfcache_cname/ns1/root.db b/bin/tests/system/sfcache_cname/ns1/root.db new file mode 100644 index 0000000000..d2357839be --- /dev/null +++ b/bin/tests/system/sfcache_cname/ns1/root.db @@ -0,0 +1,6 @@ +$TTL 300 +. IN SOA ns. hostmaster. 1 600 600 1200 600 +. NS ns +ns A 10.53.0.1 +foo.tld1. CNAME tld2. +tld2. A 1.2.3.4 diff --git a/bin/tests/system/sfcache_cname/ns2/named.conf.j2 b/bin/tests/system/sfcache_cname/ns2/named.conf.j2 new file mode 100644 index 0000000000..8bc955aceb --- /dev/null +++ b/bin/tests/system/sfcache_cname/ns2/named.conf.j2 @@ -0,0 +1,22 @@ +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; +}; + +zone "tld1." { + type static-stub; + server-addresses { 10.53.0.1; }; +}; + +zone "tld2." { + type static-stub; + server-addresses { 10.53.0.1; }; +}; diff --git a/bin/tests/system/sfcache_cname/tests_sfcache_cname.py b/bin/tests/system/sfcache_cname/tests_sfcache_cname.py new file mode 100644 index 0000000000..2c5fbe8363 --- /dev/null +++ b/bin/tests/system/sfcache_cname/tests_sfcache_cname.py @@ -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. +# +# ns1 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) diff --git a/lib/ns/client.c b/lib/ns/client.c index 45fdab1c58..7c38b2a4b0 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -1030,6 +1030,9 @@ ns_client_error(ns_client_t *client, isc_result_t result) { isc_time_t expire; isc_interval_t i; uint32_t flags = 0; + dns_name_t *qname = client->query.origqname != NULL + ? client->query.origqname + : client->query.qname; if ((message->flags & DNS_MESSAGEFLAG_CD) != 0) { flags = NS_FAILCACHE_CD; @@ -1038,8 +1041,7 @@ ns_client_error(ns_client_t *client, isc_result_t result) { isc_interval_set(&i, client->inner.view->fail_ttl, 0); result = isc_time_nowplusinterval(&expire, &i); if (result == ISC_R_SUCCESS) { - dns_badcache_add(client->inner.view->failcache, - client->query.qname, + dns_badcache_add(client->inner.view->failcache, qname, client->query.qtype, flags, isc_time_seconds(&expire)); }