]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
Fix problems with the IXFR state machine which caused long diffs to
authorBob Halley <halley@dnspython.org>
Wed, 11 Dec 2013 14:31:08 +0000 (06:31 -0800)
committerBob Halley <halley@dnspython.org>
Wed, 11 Dec 2013 14:31:08 +0000 (06:31 -0800)
fail.  Thanks to James Raftery for the fix and the repeated prodding
to get it applied :)

ChangeLog
dns/query.py

index a66722ca46bf9011c6484a0ee4382296c4557f6b..56aeb41bad34dec20c2befaf443ba4e0078ac1e7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-12-11  Bob Halley  <halley@dnspython.org>
+
+       * dns/query.py: Fix problems with the IXFR state machine which caused
+         long diffs to fail.  Thanks to James Raftery for the fix and the
+         repeated prodding to get it applied :)
+
 2013-09-02  Bob Halley  <halley@dnspython.org>
 
        * (Version 1.11.1 released)
index 2dc3f804333d4ea71c95c97ae7ef347e3ee0817f..2a252c72855c96c279484f50510179c7b7cf28e5 100644 (file)
@@ -411,6 +411,8 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
         tcpmsg = struct.pack("!H", l) + wire
         _net_write(s, tcpmsg, expiration)
     done = False
+    delete_mode = True
+    expecting_SOA = False
     soa_rrset = None
     soa_count = 0
     if relativize:
@@ -439,18 +441,16 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
         tsig_ctx = r.tsig_ctx
         first = False
         answer_index = 0
-        delete_mode = False
-        expecting_SOA = False
         if soa_rrset is None:
             if not r.answer or r.answer[0].name != oname:
-                raise dns.exception.FormError
+                raise dns.exception.FormError("No answer or RRset not for qname")
             rrset = r.answer[0]
             if rrset.rdtype != dns.rdatatype.SOA:
                 raise dns.exception.FormError("first RRset is not an SOA")
             answer_index = 1
             soa_rrset = rrset.copy()
             if rdtype == dns.rdatatype.IXFR:
-                if soa_rrset[0].serial == serial:
+                if soa_rrset[0].serial <= serial:
                     #
                     # We're already up-to-date.
                     #
@@ -471,7 +471,14 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
                     expecting_SOA = False
                 elif rdtype == dns.rdatatype.IXFR:
                     delete_mode = not delete_mode
-                if rrset == soa_rrset and not delete_mode:
+                #
+                # If this SOA RRset is equal to the first we saw then we're
+                # finished. If this is an IXFR we also check that we're seeing
+                # the record in the expected part of the response.
+                #
+                if rrset == soa_rrset and \
+                        (rdtype == dns.rdatatype.AXFR or \
+                        (rdtype == dns.rdatatype.IXFR and delete_mode)):
                     done = True
             elif expecting_SOA:
                 #