BIND 10 trac1262, updated. 703cd3ed5855e673443e898d427fdc7768c5bceb [1262] Implement the AXFR fallback
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Oct 5 11:23:08 UTC 2011
The branch, trac1262 has been updated
via 703cd3ed5855e673443e898d427fdc7768c5bceb (commit)
via 1a035954731fce34faf09705bc61b7eb0ad34ac6 (commit)
via ae43bdedcfaabacbc8e4455313e6a5b4d98a68cd (commit)
via 017b4e1bcc7fe62f11650444518f422934c925ff (commit)
from e9e29a281b0b8b9d91fe9097e51c7e5df6d3ff78 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 703cd3ed5855e673443e898d427fdc7768c5bceb
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Oct 5 13:15:59 2011 +0200
[1262] Implement the AXFR fallback
commit 1a035954731fce34faf09705bc61b7eb0ad34ac6
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Oct 5 13:11:27 2011 +0200
[1262] Tests for the AXFR fallback
commit ae43bdedcfaabacbc8e4455313e6a5b4d98a68cd
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Oct 5 13:10:35 2011 +0200
[1262] Extend the state machine comment
So it includes the AXFR part as well.
commit 017b4e1bcc7fe62f11650444518f422934c925ff
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Oct 5 12:18:18 2011 +0200
[1262] Allow the diff to remove old data
-----------------------------------------------------------------------
Summary of changes:
src/bin/xfrin/tests/xfrin_test.py | 39 ++++++++++++++++++++++-
src/bin/xfrin/xfrin.py.in | 43 +++++++++++++++++++++++---
src/lib/python/isc/xfrin/diff.py | 7 ++--
src/lib/python/isc/xfrin/tests/diff_tests.py | 11 ++++++-
4 files changed, 89 insertions(+), 11 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/xfrin/tests/xfrin_test.py b/src/bin/xfrin/tests/xfrin_test.py
index b013b2e..09a5d67 100644
--- a/src/bin/xfrin/tests/xfrin_test.py
+++ b/src/bin/xfrin/tests/xfrin_test.py
@@ -458,12 +458,47 @@ class TestXfrinAXFR(TestXfrinState):
self.state = XfrinAXFR()
def test_handle_rr(self):
- self.assertRaises(XfrinException, self.state.handle_rr, self.conn,
- soa_rrset)
+ """
+ Test we can put data inside.
+ """
+ # Put some data inside
+ data = RRset(TEST_ZONE_NAME, TEST_RRCLASS, RRType.A(), RRTTL(3600))
+ data.add_rdata(Rdata(RRType.A(), TEST_RRCLASS, '192.0.2.1'))
+ self.assertTrue(self.state.handle_rr(self.conn, data))
+ # This test uses internal Diff structure to check the behaviour of
+ # XfrinAXFR. Maybe there could be a cleaner way, but it would be more
+ # complicated.
+ self.assertEqual([('add', data)],
+ self.state._XfrinAXFR__diff.get_buffer())
+ # This SOA terminates the transef
+ self.assertTrue(self.state.handle_rr(self.conn, soa_rrset))
+ # It should have changed the state
+ self.assertEqual(type(XfrinAXFREnd()), type(self.conn.get_xfrstate()))
+ # The data should have been commited
+ # FIXME: Or, should we wait and see there are no data after this,
+ # to do the commit? Pass it to the AXFREnd?
+ self.assertEqual([], self.state._XfrinAXFR__diff.get_buffer())
+ self.assertRaises(ValueError, self.state._XfrinAXFR__diff.commit)
def test_finish_message(self):
+ """
+ Check normal end of message.
+ """
+ # When a message ends, nothing happens usually
self.assertTrue(self.state.finish_message(self.conn))
+class TestXfrinAXFREnd(TestXfrinState):
+ def setUp(self):
+ super().setUp()
+ self.state = XfrinAXFREnd()
+
+ def test_handle_rr(self):
+ self.assertRaises(XfrinProtocolError, self.state.handle_rr, self.conn,
+ self.ns_rrset)
+
+ def test_finish_message(self):
+ self.assertFalse(self.state.finish_message(self.conn))
+
class TestXfrinConnection(unittest.TestCase):
'''Convenient parent class for XFR-protocol tests.
diff --git a/src/bin/xfrin/xfrin.py.in b/src/bin/xfrin/xfrin.py.in
index 86c3281..5b1f900 100755
--- a/src/bin/xfrin/xfrin.py.in
+++ b/src/bin/xfrin/xfrin.py.in
@@ -142,7 +142,6 @@ class XfrinState:
machine because they cannot be distinguished immediately - an AXFR
response to an IXFR request can only be detected when the first two (2)
response RRs have already been received.
- NOTE: the AXFR part of the state machine is incomplete at this point.
The following diagram summarizes the state transition. After sending
the query, xfrin starts the process with the InitialSOA state (all
@@ -151,8 +150,13 @@ class XfrinState:
process successfully completes.
- (recv SOA) (AXFR-style IXFR)
- InitialSOA------->FirstData------------->AXFR
+ (recv SOA) (AXFR-style IXFR) (SOA)
+ InitialSOA------->FirstData------------->AXFR--------->AXFREnd
+ | | ^
+ | | |
+ | +--+
+ | (non SOA)
+ |
| (non SOA, delete)
(pure IXFR,| +-------+
keep handling)| (Delete SOA) V |
@@ -328,9 +332,38 @@ class XfrinIXFREnd(XfrinState):
return False
class XfrinAXFR(XfrinState):
+ def __init__(self):
+ self.__diff = None
+
+ def handle_rr(self, conn, rr):
+ """
+ Handle the RR by putting it into the zone.
+ """
+ if self.__diff is None:
+ # This is the first RR there. So create the diff to accumulate
+ # data
+ self.__diff = Diff(conn._datasrc_client, conn._zone_name, True)
+ self.__diff.add_data(rr)
+ if rr.get_type() == RRType.SOA():
+ # Soa means end. We commit the data and move to the final state
+ self.set_xfrstate(conn, XfrinAXFREnd())
+ self.__diff.commit()
+ # Yes, we've eaten this RR.
+ return True
+
+class XfrinAXFREnd(XfrinState):
def handle_rr(self, conn, rr):
- raise XfrinException('Falling back from IXFR to AXFR not ' +
- 'supported yet')
+ raise XfrinProtocolError('Extra data after the end of AXFR: ' +
+ rr.to_text())
+
+ def finish_message(self, conn):
+ """
+ Final processing after processing an entire AXFR session.
+
+ There might be more actions here, but for now we simply return False,
+ indicating there will be no more message to receive.
+ """
+ return False
class XfrinConnection(asyncore.dispatcher):
'''Do xfrin in this class. '''
diff --git a/src/lib/python/isc/xfrin/diff.py b/src/lib/python/isc/xfrin/diff.py
index f2f442b..8842fdb 100644
--- a/src/lib/python/isc/xfrin/diff.py
+++ b/src/lib/python/isc/xfrin/diff.py
@@ -40,19 +40,20 @@ class Diff:
the changes to underlying data source right away, but keeps them for
a while.
"""
- def __init__(self, datasource, zone):
+ def __init__(self, datasource, zone, replace=False):
"""
Initializes the diff to a ready state. It checks the zone exists
in the datasource and if not, NoSuchZone is raised. This also creates
a transaction in the data source.
The datasource is the one containing the zone. Zone is isc.dns.Name
- object representing the name of the zone (its apex).
+ object representing the name of the zone (its apex). If replace is true,
+ the content of the whole zone is wiped out before applying the diff.
You can also expect isc.datasrc.Error or isc.datasrc.NotImplemented
exceptions.
"""
- self.__updater = datasource.get_updater(zone, False)
+ self.__updater = datasource.get_updater(zone, replace)
if self.__updater is None:
# The no such zone case
raise NoSuchZone("Zone " + str(zone) +
diff --git a/src/lib/python/isc/xfrin/tests/diff_tests.py b/src/lib/python/isc/xfrin/tests/diff_tests.py
index 3749c6b..e1ba561 100644
--- a/src/lib/python/isc/xfrin/tests/diff_tests.py
+++ b/src/lib/python/isc/xfrin/tests/diff_tests.py
@@ -37,6 +37,7 @@ class DiffTest(unittest.TestCase):
self.__data_operations = []
self.__apply_called = False
self.__commit_called = False
+ self.__should_replace = False
# Some common values
self.__rrclass = RRClass.IN()
self.__type = RRType.A()
@@ -103,7 +104,7 @@ class DiffTest(unittest.TestCase):
it returns self.
"""
# The diff should not delete the old data.
- self.assertFalse(replace)
+ self.assertEqual(self.__should_replace, replace)
self.__updater_requested = True
# Pretend this zone doesn't exist
if zone_name == Name('none.example.org.'):
@@ -322,6 +323,14 @@ class DiffTest(unittest.TestCase):
diff.compact()
check()
+ def test_relpace(self):
+ """
+ Test that when we want to replace the whole zone, it is propagated.
+ """
+ self.__should_replace = True
+ diff = Diff(self, "example.org.", True)
+ self.assertTrue(self.__updater_requested)
+
if __name__ == "__main__":
isc.log.init("bind10")
unittest.main()
More information about the bind10-changes
mailing list