Browse Source

[2911] suppress IXFR-to-AXFR fallback if IXFR only is specified.

JINMEI Tatuya 12 years ago
parent
commit
9c25723eb9
3 changed files with 31 additions and 6 deletions
  1. 7 0
      src/bin/xfrin/tests/xfrin_test.py
  2. 13 6
      src/bin/xfrin/xfrin.py.in
  3. 11 0
      src/bin/xfrin/xfrin_messages.mes

+ 7 - 0
src/bin/xfrin/tests/xfrin_test.py

@@ -3329,6 +3329,13 @@ class TestXfrinProcess(unittest.TestCase):
         self.__do_test([XFRIN_FAIL, XFRIN_FAIL],
                        [RRType.IXFR, RRType.AXFR], ZoneInfo.REQUEST_IXFR_FIRST)
 
+    def test_ixfr_only(self):
+        """
+        The transfer fails and IXFR_ONLY is specified.  It shouldn't fall
+        back to AXFR and should report failure.
+        """
+        self.__do_test([XFRIN_FAIL], [RRType.IXFR], ZoneInfo.REQUEST_IXFR_ONLY)
+
     def test_send_loadzone(self):
         """
         Check the loadzone command is sent after successful transfer.

+ 13 - 6
src/bin/xfrin/xfrin.py.in

@@ -1208,12 +1208,19 @@ def __process_xfrin(server, zone_name, rrclass, db_file,
                     # IXFR failed for some reason. It might mean the server
                     # can't handle it, or we don't have the zone or we are out
                     # of sync or whatever else. So we retry with with AXFR, as
-                    # it may succeed in many such cases.
-                    retry = True
-                    request_type = RRType.AXFR
-                    logger.warn(XFRIN_XFR_TRANSFER_FALLBACK, conn.zone_str())
-                    conn.close()
-                    conn = None
+                    # it may succeed in many such cases; if "IXFR only" is
+                    # specified in request_ixfr, however, we suppress the
+                    # fallback.
+                    if request_ixfr == ZoneInfo.REQUEST_IXFR_ONLY:
+                        logger.warn(XFRIN_XFR_TRANSFER_FALLBACK_DISABLED,
+                                    conn.zone_str())
+                    else:
+                        retry = True
+                        request_type = RRType.AXFR
+                        logger.warn(XFRIN_XFR_TRANSFER_FALLBACK,
+                                    conn.zone_str())
+                        conn.close()
+                        conn = None
 
     except Exception as ex:
         # If exception happens, just remember it here so that we can re-raise

+ 11 - 0
src/bin/xfrin/xfrin_messages.mes

@@ -230,6 +230,17 @@ such that the remote server doesn't support IXFR, we don't have the SOA record
 (or the zone at all), we are out of sync, etc. In many of these situations,
 AXFR could still work. Therefore we try that one in case it helps.
 
+% XFRIN_XFR_TRANSFER_FALLBACK_DISABLED suppressing fallback from IXFR to AXFR for %1
+An IXFR transfer of the given zone failed.  By default AXFR will be
+tried next, but this fallback is disabled by configuration, so the
+whole transfer attempt failed at that point.  If the reason for the
+failure (which should be logged separately) is temporary, this is
+probably harmless or even desired as another IXFR will take place some
+time later (without falling back to the possibly expensive AXFR).  If
+this is a permanent error (e.g., some change at the master server
+completely disables IXFR), the secondary zone will eventually expire,
+so the configuration should be changed to allow AXFR.
+
 % XFRIN_XFR_TRANSFER_PROTOCOL_VIOLATION %1 transfer of zone %2 with %3 failed: %4
 The XFR transfer for the given zone has failed due to a protocol
 error, such as an unexpected response from the primary server.  The