From: Matthijs Mekking Date: Fri, 27 Mar 2026 09:32:48 +0000 (+0100) Subject: Add serve-stale test case for CNAME to A X-Git-Tag: v9.21.23~54^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4ee526cb6d3c34ea2736154e15dbc19211e08321;p=thirdparty%2Fbind9.git Add serve-stale test case for CNAME to A Add a serve-stale system test case where the authority changes a CNAME RRset to A (at cname2.stale.test). The CNAME that is in the cache is stale and should be refreshed. The target A record (at a2.stale.test) has a longer TTL and is also still in the cache. The next query should return the refreshed A RRset to the client. Then the authority changes back the A RRset to CNAME. The A RRset has become stale and should be refreshed. The next query should return the refreshed CNAME RRset plus the already cached a2.stale.test A record. This test requires ns1 to allow dynamic updates to stale.test, and prefetch to be disabled. The latter is to ensure the record is not prefetched, but only refreshed when stale (and logs the expected "an attempt to refresh the RRset" messages). --- diff --git a/bin/tests/system/serve_stale/ns1/named.conf.j2 b/bin/tests/system/serve_stale/ns1/named.conf.j2 index 3dff62358cc..17b09dd4000 100644 --- a/bin/tests/system/serve_stale/ns1/named.conf.j2 +++ b/bin/tests/system/serve_stale/ns1/named.conf.j2 @@ -42,5 +42,6 @@ zone "." { zone "stale.test" { type primary; file "stale.test.db"; + allow-update { any; }; }; {% endif %} diff --git a/bin/tests/system/serve_stale/ns1/named4.conf.in b/bin/tests/system/serve_stale/ns1/named4.conf.in index 92c485542c3..28eb0fd67b2 100644 --- a/bin/tests/system/serve_stale/ns1/named4.conf.in +++ b/bin/tests/system/serve_stale/ns1/named4.conf.in @@ -34,4 +34,5 @@ zone "." { zone "stale.test" { type primary; file "stale.test.db"; + allow-update { any; }; }; diff --git a/bin/tests/system/serve_stale/ns3/named.conf.j2 b/bin/tests/system/serve_stale/ns3/named.conf.j2 index aff0b003275..227daa0703f 100644 --- a/bin/tests/system/serve_stale/ns3/named.conf.j2 +++ b/bin/tests/system/serve_stale/ns3/named.conf.j2 @@ -18,6 +18,7 @@ options { recursion yes; dnssec-validation no; qname-minimization off; + prefetch 0; stale-answer-enable yes; stale-cache-enable yes; diff --git a/bin/tests/system/serve_stale/ns3/named1.conf.j2 b/bin/tests/system/serve_stale/ns3/named1.conf.j2 index 165dacfe1bf..c67313e0bf3 100644 --- a/bin/tests/system/serve_stale/ns3/named1.conf.j2 +++ b/bin/tests/system/serve_stale/ns3/named1.conf.j2 @@ -19,6 +19,7 @@ options { dump-file "named_dump3.db"; stale-cache-enable yes; dnssec-validation no; + prefetch 0; }; zone "." { diff --git a/bin/tests/system/serve_stale/ns3/named2.conf.j2 b/bin/tests/system/serve_stale/ns3/named2.conf.j2 index 6537de9fa59..f6ad7954f35 100644 --- a/bin/tests/system/serve_stale/ns3/named2.conf.j2 +++ b/bin/tests/system/serve_stale/ns3/named2.conf.j2 @@ -29,6 +29,7 @@ options { max-stale-ttl 3600; resolver-query-timeout 30000; # 30 seconds qname-minimization disabled; + prefetch 0; }; zone "." { diff --git a/bin/tests/system/serve_stale/ns3/named3.conf.j2 b/bin/tests/system/serve_stale/ns3/named3.conf.j2 index 65bddea352b..0661a7cc5e1 100644 --- a/bin/tests/system/serve_stale/ns3/named3.conf.j2 +++ b/bin/tests/system/serve_stale/ns3/named3.conf.j2 @@ -27,6 +27,7 @@ options { stale-refresh-time 0; max-stale-ttl 3600; resolver-query-timeout 10000; # 10 seconds + prefetch 0; }; zone "." { diff --git a/bin/tests/system/serve_stale/ns3/named4.conf.j2 b/bin/tests/system/serve_stale/ns3/named4.conf.j2 index dbca82b3a48..85da1d1bf9e 100644 --- a/bin/tests/system/serve_stale/ns3/named4.conf.j2 +++ b/bin/tests/system/serve_stale/ns3/named4.conf.j2 @@ -29,6 +29,7 @@ options { resolver-query-timeout 10000; # 10 seconds max-stale-ttl 3600; recursive-clients 10; + prefetch 0; }; zone "." { diff --git a/bin/tests/system/serve_stale/ns3/named5.conf.j2 b/bin/tests/system/serve_stale/ns3/named5.conf.j2 index 753a84ba3ff..845ee820b61 100644 --- a/bin/tests/system/serve_stale/ns3/named5.conf.j2 +++ b/bin/tests/system/serve_stale/ns3/named5.conf.j2 @@ -28,6 +28,7 @@ options { stale-refresh-time 4; resolver-query-timeout 10000; # 10 seconds max-stale-ttl 3600; + prefetch 0; }; zone "." { diff --git a/bin/tests/system/serve_stale/ns3/named6.conf.j2 b/bin/tests/system/serve_stale/ns3/named6.conf.j2 index d23ec8515a7..59a3266af38 100644 --- a/bin/tests/system/serve_stale/ns3/named6.conf.j2 +++ b/bin/tests/system/serve_stale/ns3/named6.conf.j2 @@ -25,6 +25,7 @@ options { fetches-per-zone 1 fail; fetches-per-server 1 fail; max-stale-ttl 3600; + prefetch 0; }; zone "." { diff --git a/bin/tests/system/serve_stale/ns3/named7.conf.j2 b/bin/tests/system/serve_stale/ns3/named7.conf.j2 index 85586401094..79b197bbd14 100644 --- a/bin/tests/system/serve_stale/ns3/named7.conf.j2 +++ b/bin/tests/system/serve_stale/ns3/named7.conf.j2 @@ -33,6 +33,7 @@ options { fetches-per-zone 1 fail; fetches-per-server 1 fail; max-stale-ttl 3600; + prefetch 0; }; zone "." { diff --git a/bin/tests/system/serve_stale/ns3/named9.conf.j2 b/bin/tests/system/serve_stale/ns3/named9.conf.j2 index cac3de04bfb..dd46102be76 100644 --- a/bin/tests/system/serve_stale/ns3/named9.conf.j2 +++ b/bin/tests/system/serve_stale/ns3/named9.conf.j2 @@ -21,6 +21,7 @@ options { stale-cache-enable yes; stale-answer-ttl 3; stale-answer-client-timeout 0; + prefetch 0; }; zone "." { diff --git a/bin/tests/system/serve_stale/tests.sh b/bin/tests/system/serve_stale/tests.sh index 71d7468c8b1..90841afe6aa 100755 --- a/bin/tests/system/serve_stale/tests.sh +++ b/bin/tests/system/serve_stale/tests.sh @@ -2359,6 +2359,89 @@ grep "cname-b3\.stale\.test\..*3.*IN.*A.*192\.0\.2\.2" dig.out.test$n >/dev/null if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) +# Change CNAME to A. +n=$((n + 1)) +echo_i "change cname2.stale.test. CNAME to A (stale-answer-client-timeout 0) ($n)" +ret=0 +( + echo zone stale.test. + echo server 10.53.0.1 "${PORT}" + echo update del cname2.stale.test. CNAME a2.stale.test. + echo update add cname2.stale.test. 1 A 192.0.0.2 + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "check stale cname2.stale.test A comes from cache (stale-answer-client-timeout 0) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 cname2.stale.test A >dig.out.test$n || ret=1 +wait_for_log 5 "cname2.stale.test A stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +grep "cname2\.stale\.test\..*3.*IN.*CNAME.*a2\.stale\.test\." dig.out.test$n >/dev/null || ret=1 +# We can't reliably test the TTL of the a2.stale.test A record. +grep "a2\.stale\.test\..*IN.*A.*192\.0\.2\.2" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "check stale cname2.stale.test A is refreshed (stale-answer-client-timeout 0) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 cname2.stale.test A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "cname2\.stale\.test\..*IN.*A.*192\.0\.0\.2" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Change A to CNAME. +n=$((n + 1)) +echo_i "change cname2.stale.test. A to CNAME (stale-answer-client-timeout 0) ($n)" +ret=0 +( + echo zone stale.test. + echo server 10.53.0.1 "${PORT}" + echo update del cname2.stale.test. A 192.0.0.2 + echo update add cname2.stale.test. 1 CNAME a2.stale.test. + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Allow A record to become stale. +sleep 1 + +n=$((n + 1)) +ret=0 +echo_i "check stale cname2.stale.test A comes from cache (stale-answer-client-timeout 0) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 cname2.stale.test A >dig.out.test$n || ret=1 +wait_for_log 5 "cname2.stale.test A stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "cname2\.stale\.test\..*3.*IN.*A.*192\.0\.0\.2" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "check stale cname2.stale.test A is refreshed (stale-answer-client-timeout 0) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 cname2.stale.test A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +# We can't reliably test the TTL of the these records. +grep "cname2\.stale\.test\..*IN.*CNAME.*a2\.stale\.test\." dig.out.test$n >/dev/null || ret=1 +grep "a2\.stale\.test\..*IN.*A.*192\.0\.2\.2" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + #################################################################### # Test for stale-answer-client-timeout 0 and stale-refresh-time 4. # #################################################################### diff --git a/bin/tests/system/serve_stale/tests_sh_serve_stale.py b/bin/tests/system/serve_stale/tests_sh_serve_stale.py index 1f96485cd2e..b7bb320a5e2 100644 --- a/bin/tests/system/serve_stale/tests_sh_serve_stale.py +++ b/bin/tests/system/serve_stale/tests_sh_serve_stale.py @@ -22,6 +22,7 @@ pytestmark = pytest.mark.extra_artifacts( "ns*/named_dump*", "ns*/named.stats*", "ns*/root.bk", + "ns1/stale.test.db.jnl", ] )