Commit 9b1c64b7 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[1371] supported the case where the requested IXFR serial is the latest one.

parent 96bf3ab5
......@@ -729,6 +729,15 @@ class TestXfroutSession(TestXfroutSessionBase):
self.assertNotEqual(None, self.xfrsess._iterator)
self.assertEqual(None, self.xfrsess._jnl_reader)
# Successful case, but the requested SOA serial is equal to that of
# the local SOA. Both iterator and jnl_reader should be None,
# indicating that the response will contain just one SOA.
self.mdata = self.create_request_data(ixfr=SOA_CURRENT_VERSION)
self.assertEqual(self.xfrsess._xfrout_setup(
self.getmsg(), TEST_ZONE_NAME, TEST_RRCLASS), Rcode.NOERROR())
self.assertEqual(None, self.xfrsess._iterator)
self.assertEqual(None, self.xfrsess._jnl_reader)
# The data source doesn't support journaling. Should fallback to AXFR.
zone_name = Name('nojournal.example.com')
self.mdata = self.create_request_data(ixfr=IXFR_OK_VERSION,
......@@ -851,7 +860,7 @@ class TestXfroutSession(TestXfroutSessionBase):
self.assertEqual(0, len(self.sock.sendqueue))
def test_reply_xfrout_query_ixfr(self):
# Creating an pure (incremental) IXFR response. Intermediate SOA
# Creating a pure (incremental) IXFR response. Intermediate SOA
# RRs won't be skipped.
self.xfrsess._soa = create_soa(SOA_CURRENT_VERSION)
self.xfrsess._iterator = [create_soa(IXFR_OK_VERSION),
......@@ -866,6 +875,20 @@ class TestXfroutSession(TestXfroutSessionBase):
self.assertEqual(reply_msg.get_rr_count(Message.SECTION_ANSWER),
len(self.xfrsess._iterator) + 2)
def test_reply_xfrout_query_ixfr_soa_only(self):
# Creating an IXFR response that contains only one RR, which is the
# SOA of the current version.
self.xfrsess._soa = create_soa(SOA_CURRENT_VERSION)
self.xfrsess._iterator = None
self.xfrsess._jnl_reader = None
self.xfrsess._reply_xfrout_query(self.getmsg(), self.sock)
reply_msg = self.sock.read_msg(Message.PRESERVE_ORDER)
answer = reply_msg.get_section(Message.SECTION_ANSWER)
self.assertEqual(1, len(answer))
self.assertEqual(RRType.SOA(), answer[0].get_type())
self.assertEqual(SOA_CURRENT_VERSION,
xfrout.get_soa_serial(answer[0].get_rdata()[0]))
class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
'''Tests for XFR-out sessions using an SQLite3 DB.
......@@ -942,6 +965,19 @@ class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
self.assertEqual(SOA_CURRENT_VERSION,
xfrout.get_soa_serial(soa.get_rdata()[0]))
def test_ixfr_soa_only(self):
# The requested SOA serial is the latest one. The response should
# contain exactly one SOA of that serial.
self.xfrsess._request_data = \
self.create_request_data(ixfr=SOA_CURRENT_VERSION)
XfroutSession._handle(self.xfrsess)
response = self.sock.read_msg(Message.PRESERVE_ORDER);
answers = response.get_section(Message.SECTION_ANSWER)
self.assertEqual(1, len(answers))
self.assertEqual(RRType.SOA(), answers[0].get_type())
self.assertEqual(SOA_CURRENT_VERSION,
xfrout.get_soa_serial(answers[0].get_rdata()[0]))
class MyUnixSockServer(UnixSockServer):
def __init__(self):
self._shutdown_event = threading.Event()
......
......@@ -399,9 +399,25 @@ class XfroutSession():
rcode, self._soa = self._get_zone_soa(zone_name)
if rcode != Rcode.NOERROR():
return rcode
# RFC1995 says "If an IXFR query with the same or newer version
# number than that of the server is received, it is replied to with
# a single SOA record of the server's current version, just as
# in AXFR". The claim about AXFR is incorrect, but other than that,
# we do as the RFC says.
# Note: until we complete #1278 we can only check equality of the
# two serials. The "newer version" case would fall back to AXFR-style.
begin_serial = get_soa_serial(remote_soa.get_rdata()[0])
end_serial = get_soa_serial(self._soa.get_rdata()[0])
if begin_serial == end_serial:
# clear both iterator and jnl_reader to signal we won't do
# iteration in response generation
self._iterator = None
self._jnl_reader = None
# Log it.
return Rcode.NOERROR()
try:
begin_serial = get_soa_serial(remote_soa.get_rdata()[0])
end_serial = get_soa_serial(self._soa.get_rdata()[0])
code, self._jnl_reader = self._datasrc_client.get_journal_reader(
zone_name, begin_serial, end_serial)
except isc.datasrc.NotImplemented as ex:
......@@ -531,10 +547,18 @@ class XfroutSession():
#TODO, there should be a better way to insert rrset.
msg.make_response()
msg.set_header_flag(Message.HEADERFLAG_AA)
msg.add_rrset(Message.SECTION_ANSWER, self._soa)
# If the iterator is None, we are responding to IXFR with a single
# SOA RR.
if self._iterator is None:
self._send_message_with_last_soa(msg, sock_fd, self._soa, 0)
return
# Add the beginning SOA
msg.add_rrset(Message.SECTION_ANSWER, self._soa)
message_upper_len = get_rrset_len(self._soa) + self._tsig_len
# Add the rest of the zone/diff contets
for rrset in self._iterator:
# Check if xfrout is shutdown
if self._server._shutdown_event.is_set():
......@@ -564,6 +588,7 @@ class XfroutSession():
# Reserve tsig space for signed packet
message_upper_len = rrset_len + self._tsig_len
# Add and send the trailing SOA
self._send_message_with_last_soa(msg, sock_fd, self._soa,
message_upper_len)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment