From 04c88f405266ab515d9916f99740c78a5909fd22 Mon Sep 17 00:00:00 2001 From: Bob Halley Date: Wed, 11 Dec 2013 06:29:29 -0800 Subject: 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 :) --- ChangeLog | 6 ++++++ dns/query.py | 17 ++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5537eb9..2e48d9c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2013-12-11 Bob Halley + + * 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 * (Version 1.11.1 released) diff --git a/dns/query.py b/dns/query.py index 7a1b1f4..29965ca 100644 --- a/dns/query.py +++ b/dns/query.py @@ -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: # -- cgit v1.2.1