Commit 0bb032a0 authored by chenzhengzhang's avatar chenzhengzhang
Browse files

Merge branch 'master' into trac955

parents 99785047 be1bc7ac
246. [func] stephen
255. [func] zhang likun
src/lib/cache: remove empty code in lib/cache and the corresponding
suppression rule in src/cppcheck-suppress.lst.
(Trac639, git 4f714bac4547d0a025afd314c309ca5cb603e212)
254. [bug] jinmei
b10-xfrout: failed to send notifies over IPv6 correctly.
(Trac964, git 3255c92714737bb461fb67012376788530f16e40)
253. [func] jelte
Add configuration options for logging through the virtual module
Logging.
(Trac 736, git 9fa2a95177265905408c51d13c96e752b14a0824)
252. [func] stephen
Add syslog as destination for logging.
(Trac976, git 31a30f5485859fd3df2839fc309d836e3206546e)
251. [bug]* jinmei
Make sure bindctl private files are non readable to anyone except
the owner or users in the same group. Note that if BIND 10 is run
with changing the user, this change means that the file owner or
group will have to be adjusted. Also note that this change is
only effective for a fresh install; if these files already exist,
their permissions must be adjusted by hand (if necessary).
(Trac870, git 461fc3cb6ebabc9f3fa5213749956467a14ebfd4)
250. [bug] ocean
src/lib/util/encode, in some conditions, the DecodeNormalizer's
iterator may reach the end() and when later being dereferenced
it will cause crash on some platform.
(Trac838, git 83e33ec80c0c6485d8b116b13045b3488071770f)
249. [func] jerry
xfrout: add support for TSIG verification.
(Trac816, git 3b2040e2af2f8139c1c319a2cbc429035d93f217)
248. [func] stephen
Add file and stderr as destinations for logging.
(Trac555, git 38b3546867425bd64dbc5920111a843a3330646b)
247. [func] jelte
Upstream queries from the resolver now set EDNS0 buffer size.
(Trac834, git 48e10c2530fe52c9bde6197db07674a851aa0f5d)
246. [func] stephen
Implement logging using log4cplus (http://log4cplus.sourceforge.net)
(Trac899, git 31d3f525dc01638aecae460cb4bc2040c9e4df10)
245. [func] vorner
245. [func] vorner
Authoritative server can now sign the answers using TSIG
(configured in tsig_keys/keys, list of strings like
"name:<base64-secret>:sha1-hmac"). It doesn't use them for
......
......@@ -890,7 +890,11 @@ AC_OUTPUT([doc/version.ent
src/lib/dns/tests/testdata/gen-wiredata.py
src/lib/cc/session_config.h.pre
src/lib/cc/tests/session_unittests_config.h
src/lib/log/tests/run_time_init_test.sh
src/lib/log/tests/console_test.sh
src/lib/log/tests/destination_test.sh
src/lib/log/tests/local_file_test.sh
src/lib/log/tests/severity_test.sh
src/lib/log/tests/tempdir.h
src/lib/util/python/mkpywrapper.py
src/lib/server_common/tests/data_path.h
tests/system/conf.sh
......@@ -917,7 +921,10 @@ AC_OUTPUT([doc/version.ent
chmod +x src/bin/msgq/tests/msgq_test
chmod +x src/lib/dns/gen-rdatacode.py
chmod +x src/lib/dns/tests/testdata/gen-wiredata.py
chmod +x src/lib/log/tests/run_time_init_test.sh
chmod +x src/lib/log/tests/local_file_test.sh
chmod +x src/lib/log/tests/console_test.sh
chmod +x src/lib/log/tests/destination_test.sh
chmod +x src/lib/log/tests/severity_test.sh
chmod +x src/lib/util/python/mkpywrapper.py
chmod +x tests/system/conf.sh
])
......
......@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <gtest/gtest.h>
#include <log/logger_support.h>
#include <util/unittests/run_all.h>
#include <dns/tests/unittest_util.h>
......@@ -22,6 +23,7 @@ main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
isc::UnitTestUtil::addDataPath(TEST_DATA_DIR);
isc::UnitTestUtil::addDataPath(TEST_DATA_BUILDDIR);
isc::log::initLogger();
return (isc::util::unittests::run_all());
}
SUBDIRS = tests
EXTRA_DIST = README tsig_keys.py tsig_keys.spec
EXTRA_DIST += logging.spec b10logging.py
config_plugindir = @prefix@/share/@PACKAGE@/config_plugins
config_plugin_DATA = tsig_keys.py tsig_keys.spec
# Copyright (C) 2011 Internet Systems Consortium.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# This is the configuration plugin for logging options
# The name is 'b10logging' because logging.py is an existing module
#
# For a technical background, see
# http://bind10.isc.org/wiki/LoggingCppApiDesign
#
from isc.config.module_spec import module_spec_from_file
from isc.util.file import path_search
from bind10_config import PLUGIN_PATHS
spec = module_spec_from_file(path_search('logging.spec', PLUGIN_PATHS))
ALLOWED_SEVERITIES = [ 'default',
'debug',
'info',
'warn',
'error',
'fatal',
'none' ]
ALLOWED_DESTINATIONS = [ 'console',
'file',
'syslog' ]
ALLOWED_STREAMS = [ 'stdout',
'stderr' ]
def check(config):
# Check the data layout first
errors=[]
if not spec.validate_config(False, config, errors):
return ' '.join(errors)
# The 'layout' is ok, now check for specific values
if 'loggers' in config:
for logger in config['loggers']:
# name should always be present
name = logger['name']
if 'severity' in logger and\
logger['severity'].lower() not in ALLOWED_SEVERITIES:
errors.append("bad severity value for logger " + name +
": " + logger['severity'])
if 'output_options' in logger:
for output_option in logger['output_options']:
if 'destination' in output_option:
destination = output_option['destination'].lower()
if destination not in ALLOWED_DESTINATIONS:
errors.append("bad destination for logger " +
name + ": " + output_option['destination'])
else:
# if left to default, output is stdout, and
# it will not show in the updated config,
# so 1. we only need to check it if present,
# and 2. if destination is changed, so should
# output. So first check checks 'in', and the
# others 'not in' for 'output'
if destination == "console" and\
'output' in output_option and\
output_option['output'] not in ALLOWED_STREAMS:
errors.append("bad output for logger " + name +
": " + output_option['stream'] +
", must be stdout or stderr")
elif destination == "file" and\
'output' not in output_option or\
output_option['output'] == "":
errors.append("destination set to file but "
"output not set to any "
"filename for logger "
+ name)
elif destination == "syslog" and\
'output' not in output_option or\
output_option['output'] == "":
errors.append("destination set to syslog but "
"output not set to any facility"
" for logger " + name)
if errors:
return ', '.join(errors)
return None
def load():
return (spec, check)
{
"module_spec": {
"module_name": "Logging",
"module_description": "Logging options",
"config_data": [
{
"item_name": "loggers",
"item_type": "list",
"item_optional": false,
"item_default": [],
"list_item_spec": {
"item_name": "logger",
"item_type": "map",
"item_optional": false,
"item_default": {},
"map_item_spec": [
{ "item_name": "name",
"item_type": "string",
"item_optional": false,
"item_default": ""
},
{ "item_name": "severity",
"item_type": "string",
"item_optional": false,
"item_default": "INFO"
},
{ "item_name": "debuglevel",
"item_type": "integer",
"item_optional": false,
"item_default": 0
},
{ "item_name": "additive",
"item_type": "boolean",
"item_optional": false,
"item_default": false
},
{ "item_name": "output_options",
"item_type": "list",
"item_optional": false,
"item_default": [],
"list_item_spec": {
"item_name": "output_option",
"item_type": "map",
"item_optional": false,
"item_default": {},
"map_item_spec": [
{ "item_name": "destination",
"item_type": "string",
"item_optional": false,
"item_default": "console"
},
{ "item_name": "output",
"item_type": "string",
"item_optional": false,
"item_default": "stdout"
},
{ "item_name": "flush",
"item_type": "boolean",
"item_optional": false,
"item_default": false
},
{ "item_name": "maxsize",
"item_type": "integer",
"item_optional": false,
"item_default": 0
},
{ "item_name": "maxver",
"item_type": "integer",
"item_optional": false,
"item_default": 0
}
]
}
}
]
}
}
],
"commands": []
}
}
......@@ -86,7 +86,7 @@ class TSigKeysTest(unittest.TestCase):
self.assertEqual("TSIG: Invalid TSIG key string: invalid.key",
tsig_keys.check({'keys': ['invalid.key']}))
self.assertEqual(
"TSIG: attempt to decode a value not in base64 char set",
"TSIG: Unexpected end of input in BASE decoder",
tsig_keys.check({'keys': ['invalid.key:123']}))
def test_bad_format(self):
......
......@@ -40,12 +40,13 @@ b10-cmdctl: cmdctl.py
if INSTALL_CONFIGURATIONS
# TODO: permissions handled later
# Below we intentionally use ${INSTALL} -m 640 instead of $(INSTALL_DATA)
# because these file will contain sensitive information.
install-data-local:
$(mkinstalldirs) $(DESTDIR)/@sysconfdir@/@PACKAGE@
for f in $(CMDCTL_CONFIGURATIONS) ; do \
if test ! -f $(DESTDIR)$(sysconfdir)/@PACKAGE@/$$f; then \
$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(sysconfdir)/@PACKAGE@/ ; \
${INSTALL} -m 640 $(srcdir)/$$f $(DESTDIR)$(sysconfdir)/@PACKAGE@/ ; \
fi ; \
done
......
......@@ -208,7 +208,8 @@ main(int argc, char* argv[]) {
cc_session = new Session(io_service.get_io_service());
config_session = new ModuleCCSession(specfile, *cc_session,
my_config_handler,
my_command_handler);
my_command_handler,
true, true);
LOG_DEBUG(resolver_logger, RESOLVER_DBG_INIT, RESOLVER_CONFIGCHAN);
// FIXME: This does not belong here, but inside Boss
......
......@@ -34,9 +34,7 @@ run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
run_unittests_LDADD = $(GTEST_LDADD)
run_unittests_LDADD += $(SQLITE_LIBS)
run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libtestutils.la
run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
......
......@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <gtest/gtest.h>
#include <log/logger_support.h>
#include <util/unittests/run_all.h>
#include <dns/tests/unittest_util.h>
......@@ -22,6 +23,7 @@ main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
isc::UnitTestUtil::addDataPath(TEST_DATA_DIR);
isc::UnitTestUtil::addDataPath(TEST_DATA_BUILDDIR);
isc::log::initLogger();
return (isc::util::unittests::run_all());
}
......@@ -18,11 +18,14 @@
import unittest
import os
from isc.testutils.tsigctx_mock import MockTSIGContext
from isc.cc.session import *
from pydnspp import *
from xfrout import *
import xfrout
TSIG_KEY = TSIGKey("example.com:SFuWd/q99SzF8Yzd1QbB9g==")
# our fake socket, where we can read and insert messages
class MySocket():
def __init__(self, family, type):
......@@ -85,10 +88,36 @@ class TestXfroutSession(unittest.TestCase):
msg.from_wire(self.mdata)
return msg
def create_mock_tsig_ctx(self, error):
# This helper function creates a MockTSIGContext for a given key
# and TSIG error to be used as a result of verify (normally faked
# one)
mock_ctx = MockTSIGContext(TSIG_KEY)
mock_ctx.error = error
return mock_ctx
def message_has_tsig(self, msg):
return msg.get_tsig_record() is not None
def create_request_data_with_tsig(self):
msg = Message(Message.RENDER)
query_id = 0x1035
msg.set_qid(query_id)
msg.set_opcode(Opcode.QUERY())
msg.set_rcode(Rcode.NOERROR())
query_question = Question(Name("example.com."), RRClass.IN(), RRType.AXFR())
msg.add_question(query_question)
renderer = MessageRenderer()
tsig_ctx = MockTSIGContext(TSIG_KEY)
msg.to_wire(renderer, tsig_ctx)
reply_data = renderer.get_data()
return reply_data
def setUp(self):
self.sock = MySocket(socket.AF_INET,socket.SOCK_STREAM)
self.log = isc.log.NSLogger('xfrout', '', severity = 'critical', log_to_console = False )
self.xfrsess = MyXfroutSession(self.sock, None, Dbserver(), self.log)
self.xfrsess = MyXfroutSession(self.sock, None, Dbserver(), self.log, TSIGKeyRing())
self.mdata = bytes(b'\xd6=\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\x03com\x00\x00\xfc\x00\x01')
self.soa_record = (4, 3, 'example.com.', 'com.example.', 3600, 'SOA', None, 'master.example.com. admin.example.com. 1234 3600 1800 2419200 7200')
......@@ -96,6 +125,18 @@ class TestXfroutSession(unittest.TestCase):
[get_rcode, get_msg] = self.xfrsess._parse_query_message(self.mdata)
self.assertEqual(get_rcode.to_text(), "NOERROR")
# tsig signed query message
request_data = self.create_request_data_with_tsig()
# BADKEY
[rcode, msg] = self.xfrsess._parse_query_message(request_data)
self.assertEqual(rcode.to_text(), "NOTAUTH")
self.assertTrue(self.xfrsess._tsig_ctx is not None)
# NOERROR
self.xfrsess._tsig_key_ring.add(TSIG_KEY)
[rcode, msg] = self.xfrsess._parse_query_message(request_data)
self.assertEqual(rcode.to_text(), "NOERROR")
self.assertTrue(self.xfrsess._tsig_ctx is not None)
def test_get_query_zone_name(self):
msg = self.getmsg()
self.assertEqual(self.xfrsess._get_query_zone_name(msg), "example.com.")
......@@ -111,6 +152,14 @@ class TestXfroutSession(unittest.TestCase):
get_msg = self.sock.read_msg()
self.assertEqual(get_msg.get_rcode().to_text(), "NXDOMAIN")
# tsig signed message
msg = self.getmsg()
self.xfrsess._tsig_ctx = self.create_mock_tsig_ctx(TSIGError.NOERROR)
self.xfrsess._reply_query_with_error_rcode(msg, self.sock, Rcode(3))
get_msg = self.sock.read_msg()
self.assertEqual(get_msg.get_rcode().to_text(), "NXDOMAIN")
self.assertTrue(self.message_has_tsig(get_msg))
def test_send_message(self):
msg = self.getmsg()
msg.make_response()
......@@ -152,6 +201,14 @@ class TestXfroutSession(unittest.TestCase):
get_msg = self.sock.read_msg()
self.assertEqual(get_msg.get_rcode().to_text(), "FORMERR")
# tsig signed message
msg = self.getmsg()
self.xfrsess._tsig_ctx = self.create_mock_tsig_ctx(TSIGError.NOERROR)
self.xfrsess._reply_query_with_format_error(msg, self.sock)
get_msg = self.sock.read_msg()
self.assertEqual(get_msg.get_rcode().to_text(), "FORMERR")
self.assertTrue(self.message_has_tsig(get_msg))
def test_create_rrset_from_db_record(self):
rrset = self.xfrsess._create_rrset_from_db_record(self.soa_record)
self.assertEqual(rrset.get_name().to_text(), "example.com.")
......@@ -162,11 +219,16 @@ class TestXfroutSession(unittest.TestCase):
def test_send_message_with_last_soa(self):
rrset_soa = self.xfrsess._create_rrset_from_db_record(self.soa_record)
msg = self.getmsg()
msg.make_response()
self.xfrsess._send_message_with_last_soa(msg, self.sock, rrset_soa, 0)
# packet number less than TSIG_SIGN_EVERY_NTH
packet_neet_not_sign = xfrout.TSIG_SIGN_EVERY_NTH - 1
self.xfrsess._send_message_with_last_soa(msg, self.sock, rrset_soa,
0, packet_neet_not_sign)
get_msg = self.sock.read_msg()
# tsig context is not exist
self.assertFalse(self.message_has_tsig(get_msg))
self.assertEqual(get_msg.get_rr_count(Message.SECTION_QUESTION), 1)
self.assertEqual(get_msg.get_rr_count(Message.SECTION_ANSWER), 1)
......@@ -180,6 +242,42 @@ class TestXfroutSession(unittest.TestCase):
rdata = answer.get_rdata()
self.assertEqual(rdata[0].to_text(), self.soa_record[7])
# msg is the TSIG_SIGN_EVERY_NTH one
# sending the message with last soa together
self.xfrsess._send_message_with_last_soa(msg, self.sock, rrset_soa,
0, TSIG_SIGN_EVERY_NTH)
get_msg = self.sock.read_msg()
# tsig context is not exist
self.assertFalse(self.message_has_tsig(get_msg))
def test_send_message_with_last_soa_with_tsig(self):
# create tsig context
self.xfrsess._tsig_ctx = self.create_mock_tsig_ctx(TSIGError.NOERROR)
rrset_soa = self.xfrsess._create_rrset_from_db_record(self.soa_record)
msg = self.getmsg()
msg.make_response()
# packet number less than TSIG_SIGN_EVERY_NTH
packet_neet_not_sign = xfrout.TSIG_SIGN_EVERY_NTH - 1
# msg is not the TSIG_SIGN_EVERY_NTH one
# sending the message with last soa together
self.xfrsess._send_message_with_last_soa(msg, self.sock, rrset_soa,
0, packet_neet_not_sign)
get_msg = self.sock.read_msg()
self.assertTrue(self.message_has_tsig(get_msg))
self.assertEqual(get_msg.get_rr_count(Message.SECTION_QUESTION), 1)
self.assertEqual(get_msg.get_rr_count(Message.SECTION_ANSWER), 1)
self.assertEqual(get_msg.get_rr_count(Message.SECTION_AUTHORITY), 0)
# msg is the TSIG_SIGN_EVERY_NTH one
# sending the message with last soa together
self.xfrsess._send_message_with_last_soa(msg, self.sock, rrset_soa,
0, TSIG_SIGN_EVERY_NTH)
get_msg = self.sock.read_msg()
self.assertTrue(self.message_has_tsig(get_msg))
def test_trigger_send_message_with_last_soa(self):
rrset_a = RRset(Name("example.com"), RRClass.IN(), RRType.A(), RRTTL(3600))
rrset_a.add_rdata(Rdata(RRType.A(), RRClass.IN(), "192.0.2.1"))
......@@ -187,15 +285,21 @@ class TestXfroutSession(unittest.TestCase):
msg = self.getmsg()
msg.make_response()
msg.add_rrset(Message.SECTION_ANSWER, rrset_a)
# give the function a value that is larger than MAX-len(rrset)
self.xfrsess._send_message_with_last_soa(msg, self.sock, rrset_soa, 65520)
# length larger than MAX-len(rrset)
length_need_split = xfrout.XFROUT_MAX_MESSAGE_SIZE - get_rrset_len(rrset_soa) + 1
# packet number less than TSIG_SIGN_EVERY_NTH
packet_neet_not_sign = xfrout.TSIG_SIGN_EVERY_NTH - 1
# give the function a value that is larger than MAX-len(rrset)
# this should have triggered the sending of two messages
# (1 with the rrset we added manually, and 1 that triggered
# the sending in _with_last_soa)
self.xfrsess._send_message_with_last_soa(msg, self.sock, rrset_soa, length_need_split,
packet_neet_not_sign)
get_msg = self.sock.read_msg()
self.assertFalse(self.message_has_tsig(get_msg))
self.assertEqual(get_msg.get_rr_count(Message.SECTION_QUESTION), 1)
self.assertEqual(get_msg.get_rr_count(Message.SECTION_ANSWER), 1)
self.assertEqual(get_msg.get_rr_count(Message.SECTION_AUTHORITY), 0)
......@@ -208,6 +312,7 @@ class TestXfroutSession(unittest.TestCase):
self.assertEqual(rdata[0].to_text(), "192.0.2.1")
get_msg = self.sock.read_msg()
self.assertFalse(self.message_has_tsig(get_msg))
self.assertEqual(get_msg.get_rr_count(Message.SECTION_QUESTION), 0)
self.assertEqual(get_msg.get_rr_count(Message.SECTION_ANSWER), 1)
self.assertEqual(get_msg.get_rr_count(Message.SECTION_AUTHORITY), 0)
......@@ -223,6 +328,45 @@ class TestXfroutSession(unittest.TestCase):
# and it should not have sent anything else
self.assertEqual(0, len(self.sock.sendqueue))
def test_trigger_send_message_with_last_soa_with_tsig(self):
self.xfrsess._tsig_ctx = self.create_mock_tsig_ctx(TSIGError.NOERROR)
rrset_soa = self.xfrsess._create_rrset_from_db_record(self.soa_record)
msg = self.getmsg()
msg.make_response()
msg.add_rrset(Message.SECTION_ANSWER, rrset_soa)
# length larger than MAX-len(rrset)
length_need_split = xfrout.XFROUT_MAX_MESSAGE_SIZE - get_rrset_len(rrset_soa) + 1
# packet number less than TSIG_SIGN_EVERY_NTH
packet_neet_not_sign = xfrout.TSIG_SIGN_EVERY_NTH - 1
# give the function a value that is larger than MAX-len(rrset)
# this should have triggered the sending of two messages
# (1 with the rrset we added manually, and 1 that triggered
# the sending in _with_last_soa)
self.xfrsess._send_message_with_last_soa(msg, self.sock, rrset_soa, length_need_split,
packet_neet_not_sign)
get_msg = self.sock.read_msg()
# msg is not the TSIG_SIGN_EVERY_NTH one, it shouldn't be tsig signed
self.assertFalse(self.message_has_tsig(get_msg))
# the last packet should be tsig signed
get_msg = self.sock.read_msg()
self.assertTrue(self.message_has_tsig(get_msg))
# and it should not have sent anything else
self.assertEqual(0, len(self.sock.sendqueue))
# msg is the TSIG_SIGN_EVERY_NTH one, it should be tsig signed
self.xfrsess._send_message_with_last_soa(msg, self.sock, rrset_soa, length_need_split,
xfrout.TSIG_SIGN_EVERY_NTH)
get_msg = self.sock.read_msg()
self.assertTrue(self.message_has_tsig(get_msg))
# the last packet should be tsig signed
get_msg = self.sock.read_msg()
self.assertTrue(self.message_has_tsig(get_msg))
# and it should not have sent anything else
self.assertEqual(0, len(self.sock.sendqueue))
def test_get_rrset_len(self):
rrset_soa = self.xfrsess._create_rrset_from_db_record(self.soa_record)
self.assertEqual(82, get_rrset_len(rrset_soa))
......@@ -313,6 +457,51 @@ class TestXfroutSession(unittest.TestCase):
reply_msg = self.sock.read_msg()
self.assertEqual(reply_msg.get_rr_count(Message.SECTION_ANSWER), 2)
def test_reply_xfrout_query_noerror_with_tsig(self):
rrset_data = (4, 3, 'a.example.com.', 'com.example.', 3600, 'A', None, '192.168.1.1')
global sqlite3_ds
global xfrout
def get_zone_soa(zonename, file):
return self.soa_record
def get_zone_datas(zone, file):
zone_rrsets = []
for i in range(0, 100):
zone_rrsets.insert(i, rrset_data)
return zone_rrsets
def get_rrset_len(rrset):
return 65520
sqlite3_ds.get_zone_soa = get_zone_soa
sqlite3_ds.get_zone_datas = get_zone_datas
xfrout.get_rrset_len = get_rrset_len
self.xfrsess._tsig_ctx = self.create_mock_tsig_ctx(TSIGError.NOERROR)
self.xfrsess._reply_xfrout_query(self.getmsg(), self.sock, "example.com.")
# tsig signed first package
reply_msg = self.sock.read_msg()
self.assertEqual(reply_msg.get_rr_count(Message.SECTION_ANSWER), 1)
self.assertTrue(self.message_has_tsig(reply_msg))
# (TSIG_SIGN_EVERY_NTH - 1) packets have no tsig
for i in range(0, xfrout.TSIG_SIGN_EVERY_NTH - 1):
reply_msg = self.sock.read_msg()
self.assertFalse(self.message_has_tsig(reply_msg))
# TSIG_SIGN_EVERY_NTH packet has tsig
reply_msg = self.sock.read_msg()
self.assertTrue(self.message_has_tsig(reply_msg))
for i in range(0, 100 - TSIG_SIGN_EVERY_NTH):
reply_msg = self.sock.read_msg()
self.assertFalse(self.message_has_tsig(reply_msg))
# tsig signed last package
reply_msg = self.sock.read_msg()
self.assertTrue(self.message_has_tsig(reply_msg))
# and it should not have sent anything else