allow IXFR-to-AXFR fallback on DNS_R_TOOMANYRECORDS

This change allows fallback from an IXFR failure to AXFR when the
reason is DNS_R_TOOMANYRECORDS. This is because this error condition
could be temporary only in an intermediate version of IXFR
transactions and it's possible that the latest version of the zone
doesn't have that condition. In such a case, the secondary would never
be able to update the zone (even if it could) without this fallback.

This fallback behavior is particularly useful with the recently
introduced max-records-per-type and max-types-per-name options:
the primary may not have these limitations and may temporarily
introduce "too many" records, breaking IXFR. If the primary side
subsequently deletes these records, this fallback will help recover
the zone transfer failure automatically; without it, the secondary
side would first need to increase the limit, which requires more
operational overhead and has its own adverse effect.

This change also fixes a minor glitch that DNS_R_TOOMANYRECORDS wasn't
logged in xfrin_fail.

(cherry picked from commit 7289090683)
This commit is contained in:
JINMEI Tatuya 2024-08-16 16:53:38 +09:00 committed by Nicki Křížek
parent 1cdde5656d
commit a93b6f2040
2 changed files with 40 additions and 2 deletions

View file

@ -65,6 +65,7 @@ zone "nil" {
type secondary;
file "myftp.db";
primaries { 10.53.0.2; };
max-records-per-type 5; # use a small value for fallback test
};
EOF
@ -144,6 +145,44 @@ $DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'fallback AXFR' >/dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "testing AXFR fallback after IXFR failure (too many records) ($n)"
ret=0
# Provide an IXFR response that would cause a "too many records" condition
sendcmd <<EOF
/SOA/
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
/IXFR/
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
nil. 300 TXT "text 1"
nil. 300 TXT "text 2"
nil. 300 TXT "text 3"
nil. 300 TXT "text 4"
nil. 300 TXT "text 5"
nil. 300 TXT "text 6: causing too many records"
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
/AXFR/
nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
nil. 300 NS ns.nil.
nil. 300 TXT "fallback AXFR on too many records"
/AXFR/
nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
EOF
sleep 1
$RNDCCMD 10.53.0.1 refresh nil | sed 's/^/ns1 /' | cat_i
sleep 2
$DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'AXFR on too many records' >/dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "testing AXFR fallback after IXFR failure (bad SOA owner) ($n)"
ret=0

View file

@ -859,8 +859,7 @@ xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
(void)isc_timer_reset(xfr->max_idle_timer,
isc_timertype_inactive, NULL, NULL, true);
if (result != DNS_R_UPTODATE && result != DNS_R_TOOMANYRECORDS)
{
if (result != DNS_R_UPTODATE) {
xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg,
isc_result_totext(result));
if (xfr->is_ixfr) {