Commit 4a682159 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[1372] some small updates for IXFR support. commiting it to share.

parent 315f4999
......@@ -159,15 +159,32 @@ class TestXfroutSessionBase(unittest.TestCase):
def message_has_tsig(self, msg):
return msg.get_tsig_record() is not None
def create_request_data(self, with_question=True, with_tsig=False):
def create_request_data(self, with_question=True, with_tsig=False,
ixfr=None):
'''Create a commonly used XFR request data.
By default the request type is AXFR; if 'ixfr' is an integer,
the request type will be IXFR and an SOA with the serial being
the value of the parameter will be included in the authority
section.
'''
msg = Message(Message.RENDER)
query_id = 0x1035
msg.set_qid(query_id)
msg.set_opcode(Opcode.QUERY())
msg.set_rcode(Rcode.NOERROR())
req_type = RRType.AXFR() if ixfr is None else RRType.IXFR()
if with_question:
msg.add_question(Question(Name("example.com"), RRClass.IN(),
RRType.AXFR()))
req_type))
if req_type == RRType.IXFR():
soa = RRset(Name('example.com'), RRClass.IN(), RRType.SOA(),
RRTTL(0))
# In the RDATA only the serial matters.
soa.add_rdata(Rdata(RRType.SOA(), RRClass.IN(),
'm r ' + str(ixfr) + ' 1 1 1 1'))
msg.add_rrset(Message.SECTION_AUTHORITY, soa)
renderer = MessageRenderer()
if with_tsig:
......@@ -241,9 +258,17 @@ class TestXfroutSession(TestXfroutSessionBase):
XfroutSession._handle(self.xfrsess)
def test_parse_query_message(self):
# Valid AXFR
[get_rcode, get_msg] = self.xfrsess._parse_query_message(self.mdata)
self.assertEqual(RRType.AXFR(), self.xfrsess._request_type)
self.assertEqual(get_rcode.to_text(), "NOERROR")
# Valid IXFR
request_data = self.create_request_data(ixfr=2011111801)
rcode, msg = self.xfrsess._parse_query_message(request_data)
self.assertEqual(RRType.IXFR(), self.xfrsess._request_type)
self.assertEqual(Rcode.NOERROR(), rcode)
# Broken request: no question
request_data = self.create_request_data(with_question=False)
rcode, msg = self.xfrsess._parse_query_message(request_data)
......
......@@ -143,7 +143,8 @@ class XfroutSession():
self._tsig_ctx = None
self._tsig_len = 0
self._remote = remote
self._request_type = 'AXFR' # could be IXFR when we support it
self._request_type = None
self._request_typestr = None
self._acl = default_acl
self._zone_config = zone_config
self.ClientClass = client_class # parameterize this for testing
......@@ -222,20 +223,32 @@ class XfroutSession():
# we check it by ourselves.
if msg.get_rr_count(Message.SECTION_QUESTION) != 1:
return Rcode.FORMERR(), msg
question = msg.get_question()[0]
# Identify the request type
self._request_type = question.get_type()
if self._request_type == RRType.AXFR():
self._request_typestr = 'AXFR'
elif self._request_type == RRType.IXFR():
self._request_typestr = 'IXFR'
else:
# Likewise, this should be impossible.
raise Runtimeerror('Unexpected XFR type: ' + \
str(self._request_type))
# ACL checks
zone_name = msg.get_question()[0].get_name()
zone_class = msg.get_question()[0].get_class()
zone_name = question.get_name()
zone_class = question.get_class()
acl = self._get_transfer_acl(zone_name, zone_class)
acl_result = acl.execute(
isc.acl.dns.RequestContext(self._remote[2], msg.get_tsig_record()))
if acl_result == DROP:
logger.info(XFROUT_QUERY_DROPPED, self._request_type,
logger.info(XFROUT_QUERY_DROPPED, self._request_typestr,
format_addrinfo(self._remote),
format_zone_str(zone_name, zone_class))
return None, None
elif acl_result == REJECT:
logger.info(XFROUT_QUERY_REJECTED, self._request_type,
logger.info(XFROUT_QUERY_REJECTED, self._request_typestr,
format_addrinfo(self._remote),
format_zone_str(zone_name, zone_class))
return Rcode.REFUSED(), msg
......@@ -348,7 +361,7 @@ class XfroutSession():
return self._reply_query_with_error_rcode(msg, sock_fd,
Rcode.FORMERR())
elif not quota_ok:
logger.warn(XFROUT_QUERY_QUOTA_EXCCEEDED, self._request_type,
logger.warn(XFROUT_QUERY_QUOTA_EXCCEEDED, self._request_typestr,
format_addrinfo(self._remote),
self._server._max_transfers_out)
return self._reply_query_with_error_rcode(msg, sock_fd,
......@@ -363,23 +376,23 @@ class XfroutSession():
try:
rcode_ = self._check_xfrout_available(zone_name)
except Exception as ex:
logger.error(XFROUT_XFR_TRANSFER_CHECK_ERROR, self._request_type,
logger.error(XFROUT_XFR_TRANSFER_CHECK_ERROR, self._request_typestr,
format_addrinfo(self._remote), zone_str, ex)
rcode_ = Rcode.SERVFAIL()
if rcode_ != Rcode.NOERROR():
logger.info(XFROUT_AXFR_TRANSFER_FAILED, self._request_type,
logger.info(XFROUT_AXFR_TRANSFER_FAILED, self._request_typestr,
format_addrinfo(self._remote), zone_str, rcode_)
return self._reply_query_with_error_rcode(msg, sock_fd, rcode_)
try:
logger.info(XFROUT_AXFR_TRANSFER_STARTED, self._request_type,
logger.info(XFROUT_AXFR_TRANSFER_STARTED, self._request_typestr,
format_addrinfo(self._remote), zone_str)
self._reply_xfrout_query(msg, sock_fd)
except Exception as err:
logger.error(XFROUT_AXFR_TRANSFER_ERROR, self._request_type,
logger.error(XFROUT_AXFR_TRANSFER_ERROR, self._request_typestr,
format_addrinfo(self._remote), zone_str, err)
pass
logger.info(XFROUT_AXFR_TRANSFER_DONE, self._request_type,
logger.info(XFROUT_AXFR_TRANSFER_DONE, self._request_typestr,
format_addrinfo(self._remote), zone_str)
def _clear_message(self, msg):
......
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