Commit 89d7de8e authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[master] Merge branch 'trac1938'

parents 459cdc4a 9a3d9604
......@@ -266,9 +266,16 @@ bug ticket for this issue.
This is a debug message issued when the authoritative server has received
a command on the command channel.
% AUTH_RECEIVED_NOTIFY received incoming NOTIFY for zone name %1, zone class %2
% AUTH_RECEIVED_NOTIFY received incoming NOTIFY for zone %1/%2 from %3
This is a debug message reporting that an incoming NOTIFY was received.
% AUTH_RECEIVED_NOTIFY_NOTAUTH received bad NOTIFY for zone %1/%2 from %3
The authoritative server received a NOTIFY message, but the specified zone
doesn't match any of the zones served by the server. The server doesn't
process the message further, and returns a response with the Rcode being
NOTAUTH. Note: RFC 1996 does not specify the server behavior in this case;
responding with Rcode of NOTAUTH follows BIND 9's behavior.
% AUTH_RESPONSE_FAILURE exception while building response to query: %1
This is a debug message, generated by the authoritative server when an
attempt to create a response to a received DNS packet has failed. The
......
......@@ -747,6 +747,8 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
std::auto_ptr<TSIGContext> tsig_context,
MessageAttributes& stats_attrs)
{
const IOEndpoint& remote_ep = io_message.getRemoteEndpoint(); // for logs
// The incoming notify must contain exactly one question for SOA of the
// zone name.
if (message.getRRCount(Message::SECTION_QUESTION) != 1) {
......@@ -769,8 +771,23 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
// on, but we don't check these conditions. This behavior is compatible
// with BIND 9.
// TODO check with the conf-mgr whether current server is the auth of the
// zone
// See if we have the specified zone in our data sources; if not return
// NOTAUTH, following BIND 9 (this is not specified in RFC 1996).
bool is_auth = false;
{
auth::DataSrcClientsMgr::Holder datasrc_holder(datasrc_clients_mgr_);
const shared_ptr<datasrc::ClientList> dsrc_clients =
datasrc_holder.findClientList(question->getClass());
is_auth = dsrc_clients &&
dsrc_clients->find(question->getName(), true, false).exact_match_;
}
if (!is_auth) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RECEIVED_NOTIFY_NOTAUTH)
.arg(question->getName()).arg(question->getClass()).arg(remote_ep);
makeErrorMessage(renderer_, message, buffer, Rcode::NOTAUTH(),
stats_attrs, tsig_context);
return (true);
}
// In the code that follows, we simply ignore the notify if any internal
// error happens rather than returning (e.g.) SERVFAIL. RFC 1996 is
......@@ -782,10 +799,9 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
}
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RECEIVED_NOTIFY)
.arg(question->getName()).arg(question->getClass());
.arg(question->getName()).arg(question->getClass()).arg(remote_ep);
const string remote_ip_address =
io_message.getRemoteEndpoint().getAddress().toText();
const string remote_ip_address = remote_ep.getAddress().toText();
static const string command_template_start =
"{\"command\": [\"notify\", {\"zone_name\" : \"";
static const string command_template_master = "\", \"master\" : \"";
......
......@@ -244,6 +244,62 @@ createBuiltinVersionResponse(const qid_t qid, vector<uint8_t>& data) {
renderer.getLength());
}
void
installDataSrcClientLists(AuthSrv& server, ClientListMapPtr lists) {
// For now, we use explicit swap than reconfigure() because the latter
// involves a separate thread and cannot guarantee the new config is
// available for the subsequent test.
server.getDataSrcClientsMgr().setDataSrcClientLists(lists);
}
void
updateDatabase(AuthSrv& server, const char* params) {
const ConstElementPtr config(Element::fromJSON("{"
"\"IN\": [{"
" \"type\": \"sqlite3\","
" \"params\": " + string(params) +
"}]}"));
installDataSrcClientLists(server, configureDataSource(config));
}
// Note: if with_static is set to true, the corresponding test should be
// disabled in case of USE_STATIC_LINK.
void
updateInMemory(AuthSrv& server, const char* origin, const char* filename,
bool with_static = true)
{
string spec_txt = "{"
"\"IN\": [{"
" \"type\": \"MasterFiles\","
" \"params\": {"
" \"" + string(origin) + "\": \"" + string(filename) + "\""
" },"
" \"cache-enable\": true"
"}]";
if (with_static) {
spec_txt += ", \"CH\": [{"
" \"type\": \"static\","
" \"params\": \"" + string(STATIC_DSRC_FILE) + "\""
"}]";
}
spec_txt += "}";
const ConstElementPtr config(Element::fromJSON(spec_txt));
installDataSrcClientLists(server, configureDataSource(config));
}
// Note: tests using this function should be disabled in case of
// USE_STATIC_LINK.
void
updateBuiltin(AuthSrv& server) {
const ConstElementPtr config(Element::fromJSON("{"
"\"CH\": [{"
" \"type\": \"static\","
" \"params\": \"" + string(STATIC_DSRC_FILE) + "\""
"}]}"));
installDataSrcClientLists(server, configureDataSource(config));
}
// We did not configure any client lists. Therefore it should be REFUSED
TEST_F(AuthSrvTest, noClientList) {
UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
......@@ -647,8 +703,10 @@ TEST_F(AuthSrvTest, IXFRDisconnectFail) {
}
TEST_F(AuthSrvTest, notify) {
updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
default_qid, Name("example.com"),
default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
......@@ -664,7 +722,7 @@ TEST_F(AuthSrvTest, notify) {
stringValue());
ConstElementPtr notify_args =
notify_session.getSentMessage()->get("command")->get(1);
EXPECT_EQ("example.com.", notify_args->get("zone_name")->stringValue());
EXPECT_EQ("example.", notify_args->get("zone_name")->stringValue());
EXPECT_EQ(DEFAULT_REMOTE_ADDRESS,
notify_args->get("master")->stringValue());
EXPECT_EQ("IN", notify_args->get("zone_class")->stringValue());
......@@ -675,7 +733,7 @@ TEST_F(AuthSrvTest, notify) {
// The question must be identical to that of the received notify
ConstQuestionPtr question = *parse_message->beginQuestion();
EXPECT_EQ(Name("example.com"), question->getName());
EXPECT_EQ(Name("example"), question->getName());
EXPECT_EQ(RRClass::IN(), question->getClass());
EXPECT_EQ(RRType::SOA(), question->getType());
......@@ -690,10 +748,17 @@ TEST_F(AuthSrvTest, notify) {
checkStatisticsCounters(stats_after, expect);
}
#ifdef USE_STATIC_LINK
TEST_F(AuthSrvTest, DISABLED_notifyForCHClass) {
#else
TEST_F(AuthSrvTest, notifyForCHClass) {
// Same as the previous test, but for the CH RRClass.
#endif
// Same as the previous test, but for the CH RRClass (so we install the
// builtin (static) data source.
updateBuiltin(server);
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
default_qid, Name("example.com"),
default_qid, Name("bind"),
RRClass::CH(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
......@@ -773,9 +838,11 @@ TEST_F(AuthSrvTest, notifyNonSOAQuestion) {
}
TEST_F(AuthSrvTest, notifyWithoutAA) {
updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
// implicitly leave the AA bit off. our implementation will accept it.
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
default_qid, Name("example.com"),
default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
createRequestPacket(request_message, IPPROTO_UDP);
server.processMessage(*io_message, *parse_message, *response_obuffer,
......@@ -786,8 +853,10 @@ TEST_F(AuthSrvTest, notifyWithoutAA) {
}
TEST_F(AuthSrvTest, notifyWithErrorRcode) {
updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
default_qid, Name("example.com"),
default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
request_message.setRcode(Rcode::SERVFAIL());
......@@ -800,10 +869,12 @@ TEST_F(AuthSrvTest, notifyWithErrorRcode) {
}
TEST_F(AuthSrvTest, notifyWithoutSession) {
updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
server.setXfrinSession(NULL);
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
default_qid, Name("example.com"),
default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
......@@ -816,10 +887,12 @@ TEST_F(AuthSrvTest, notifyWithoutSession) {
}
TEST_F(AuthSrvTest, notifySendFail) {
updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
notify_session.disableSend();
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
default_qid, Name("example.com"),
default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
......@@ -830,10 +903,12 @@ TEST_F(AuthSrvTest, notifySendFail) {
}
TEST_F(AuthSrvTest, notifyReceiveFail) {
updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
notify_session.disableReceive();
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
default_qid, Name("example.com"),
default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
......@@ -843,10 +918,12 @@ TEST_F(AuthSrvTest, notifyReceiveFail) {
}
TEST_F(AuthSrvTest, notifyWithBogusSessionMessage) {
updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
notify_session.setMessage(Element::fromJSON("{\"foo\": 1}"));
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
default_qid, Name("example.com"),
default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
......@@ -856,11 +933,13 @@ TEST_F(AuthSrvTest, notifyWithBogusSessionMessage) {
}
TEST_F(AuthSrvTest, notifyWithSessionMessageError) {
updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
notify_session.setMessage(
Element::fromJSON("{\"result\": [1, \"FAIL\"]}"));
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
default_qid, Name("example.com"),
default_qid, Name("example"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
......@@ -869,49 +948,50 @@ TEST_F(AuthSrvTest, notifyWithSessionMessageError) {
EXPECT_FALSE(dnsserv.hasAnswer());
}
void
installDataSrcClientLists(AuthSrv& server, ClientListMapPtr lists) {
// For now, we use explicit swap than reconfigure() because the latter
// involves a separate thread and cannot guarantee the new config is
// available for the subsequent test.
server.getDataSrcClientsMgr().setDataSrcClientLists(lists);
}
TEST_F(AuthSrvTest, notifyNotAuth) {
// If the server doesn't have authority of the specified zone in NOTIFY,
// it will return NOTAUTH
updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
void
updateDatabase(AuthSrv& server, const char* params) {
const ConstElementPtr config(Element::fromJSON("{"
"\"IN\": [{"
" \"type\": \"sqlite3\","
" \"params\": " + string(params) +
"}]}"));
installDataSrcClientLists(server, configureDataSource(config));
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
default_qid, Name("example.com"),
RRClass::IN(), RRType::SOA());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
EXPECT_TRUE(dnsserv.hasAnswer());
headerCheck(*parse_message, default_qid, Rcode::NOTAUTH(),
Opcode::NOTIFY().getCode(), QR_FLAG /* no AA */, 1, 0, 0, 0);
}
void
updateInMemory(AuthSrv& server, const char* origin, const char* filename) {
const ConstElementPtr config(Element::fromJSON("{"
"\"IN\": [{"
" \"type\": \"MasterFiles\","
" \"params\": {"
" \"" + string(origin) + "\": \"" + string(filename) + "\""
" },"
" \"cache-enable\": true"
"}],"
"\"CH\": [{"
" \"type\": \"static\","
" \"params\": \"" + string(STATIC_DSRC_FILE) + "\""
"}]}"));
installDataSrcClientLists(server, configureDataSource(config));
TEST_F(AuthSrvTest, notifyNotAuthSubDomain) {
// Similar to the previous case, but checking partial match doesn't confuse
// the processing.
updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
default_qid, Name("child.example"),
RRClass::IN(), RRType::SOA());
createRequestPacket(request_message, IPPROTO_UDP);
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
headerCheck(*parse_message, default_qid, Rcode::NOTAUTH(),
Opcode::NOTIFY().getCode(), QR_FLAG, 1, 0, 0, 0);
}
void
updateBuiltin(AuthSrv& server) {
const ConstElementPtr config(Element::fromJSON("{"
"\"CH\": [{"
" \"type\": \"static\","
" \"params\": \"" + string(STATIC_DSRC_FILE) + "\""
"}]}"));
installDataSrcClientLists(server, configureDataSource(config));
TEST_F(AuthSrvTest, notifyNotAuthNoClass) {
// Likewise, and there's not even a data source in the specified class.
updateInMemory(server, "example.", CONFIG_INMEMORY_EXAMPLE, false);
UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
default_qid, Name("example"),
RRClass::CH(), RRType::SOA());
createRequestPacket(request_message, IPPROTO_UDP);
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
headerCheck(*parse_message, default_qid, Rcode::NOTAUTH(),
Opcode::NOTIFY().getCode(), QR_FLAG, 1, 0, 0, 0);
}
// Try giving the server a TSIG signed request and see it can anwer signed as
......
......@@ -314,16 +314,22 @@ class TestZonemgrRefresh(unittest.TestCase):
sqlite3_ds.get_zone_soa = old_get_zone_soa
def test_zone_handle_notify(self):
self.zone_refresh.zone_handle_notify(ZONE_NAME_CLASS1_IN,"127.0.0.1")
notify_master = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"]
self.assertTrue(self.zone_refresh.zone_handle_notify(
ZONE_NAME_CLASS1_IN, "127.0.0.1"))
notify_master = self.zone_refresh.\
_zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"]
self.assertEqual("127.0.0.1", notify_master)
zone_timeout = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
zone_timeout = self.zone_refresh.\
_zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
current_time = time.time()
self.assertTrue(zone_timeout <= current_time)
self.assertRaises(ZonemgrException, self.zone_refresh.zone_handle_notify,\
ZONE_NAME_CLASS3_CH, "127.0.0.1")
self.assertRaises(ZonemgrException, self.zone_refresh.zone_handle_notify,\
ZONE_NAME_CLASS3_IN, "127.0.0.1")
# If the specified zone does not in the configured secondary list,
# it should return False.
self.assertFalse(self.zone_refresh.zone_handle_notify(
ZONE_NAME_CLASS3_CH, "127.0.0.1"))
self.assertFalse(self.zone_refresh.zone_handle_notify(
ZONE_NAME_CLASS3_IN, "127.0.0.1"))
def test_zone_refresh_success(self):
soa_rdata = 'a.example.net. root.example.net. 2009073106 1800 900 2419200 21600'
......@@ -607,6 +613,19 @@ class TestZonemgrRefresh(unittest.TestCase):
config, self.cc_session)
class MyZonemgr(Zonemgr):
class DummySocket:
"""This dummy class simply steal send() to record any transmitted data.
"""
def __init__(self):
self.sent_data = []
def send(self, data):
self.sent_data.append(data)
class DummyLock:
def __enter__(self): pass
def __exit__(self, type, value, traceback): pass
def __init__(self):
self._db_file = TEST_SQLITE3_DBFILE
......@@ -621,6 +640,8 @@ class MyZonemgr(Zonemgr):
"reload_jitter" : 0.75,
"secondary_zones": []
}
self._lock = self.DummyLock()
self._master_socket = self.DummySocket()
def _start_zone_refresh_timer(self):
pass
......@@ -672,15 +693,21 @@ class TestZonemgr(unittest.TestCase):
self.assertEqual(TEST_SQLITE3_DBFILE, self.zonemgr.get_db_file())
def test_parse_cmd_params(self):
params1 = {"zone_name" : "example.com.", "zone_class" : "CH", "master" : "127.0.0.1"}
params1 = {"zone_name" : "example.com.", "zone_class" : "CH",
"master" : "127.0.0.1"}
answer1 = (ZONE_NAME_CLASS3_CH, "127.0.0.1")
self.assertEqual(answer1, self.zonemgr._parse_cmd_params(params1, ZONE_NOTIFY_COMMAND))
self.assertEqual(answer1,
self.zonemgr._parse_cmd_params(params1,
ZONE_NOTIFY_COMMAND))
params2 = {"zone_name" : "example.com.", "zone_class" : "IN"}
answer2 = ZONE_NAME_CLASS3_IN
self.assertEqual(answer2, self.zonemgr._parse_cmd_params(params2, notify_out.ZONE_NEW_DATA_READY_CMD))
self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params, params2, ZONE_NOTIFY_COMMAND)
self.assertEqual(answer2, self.zonemgr._parse_cmd_params(
params2, notify_out.ZONE_NEW_DATA_READY_CMD))
self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params,
params2, ZONE_NOTIFY_COMMAND)
params1 = {"zone_class" : "CH"}
self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params, params2, ZONE_NOTIFY_COMMAND)
self.assertRaises(ZonemgrException, self.zonemgr._parse_cmd_params,
params2, ZONE_NOTIFY_COMMAND)
def test_config_data_check(self):
# jitter should not be bigger than half of the original value
......@@ -697,6 +724,26 @@ class TestZonemgr(unittest.TestCase):
self.zonemgr.run()
self.assertTrue(self.zonemgr._module_cc.stopped)
def test_command_handler_notify(self):
"""Check the result of NOTIFY command."""
self.zonemgr._zone_refresh = MyZonemgrRefresh()
# On successful case, the other thread will be notified via
# _master_socket.
self.zonemgr._zone_refresh.zone_handle_notify = lambda x, y: True
self.zonemgr.command_handler("notify", {"zone_name": "example.",
"zone_class": "IN",
"master": "192.0.2.1"})
self.assertEqual([b" "], self.zonemgr._master_socket.sent_data)
# If the specified is not found in the secondary list, it doesn't
# bother to wake the thread (sent_data shouldn't change)
self.zonemgr._zone_refresh.zone_handle_notify = lambda x, y: False
self.zonemgr.command_handler("notify", {"zone_name": "example.",
"zone_class": "IN",
"master": "192.0.2.1"})
self.assertEqual([b" "], self.zonemgr._master_socket.sent_data)
if __name__== "__main__":
isc.log.resetUnitTestRootLogger()
unittest.main()
......@@ -191,14 +191,31 @@ class ZonemgrRefresh:
self._set_zone_retry_timer(zone_name_class)
def zone_handle_notify(self, zone_name_class, master):
"""Handle zone notify"""
if (self._zone_not_exist(zone_name_class)):
logger.error(ZONEMGR_UNKNOWN_ZONE_NOTIFIED, zone_name_class[0],
zone_name_class[1], master)
raise ZonemgrException("[b10-zonemgr] Notified zone (%s, %s) "
"doesn't belong to zonemgr" % zone_name_class)
"""Handle an incomding NOTIFY message via the Auth module.
It returns True if the specified zone matches one of the locally
configured list of secondary zones; otherwise returns False.
In the latter case it assumes the server is a primary (master) of the
zone; the Auth module should have rejected the case where it's not
even authoritative for the zone.
Note: to be more robust and less independent from other module's
behavior, it's probably safer to check the authority condition here,
too. But right now it uses SQLite3 specific API (to be deprecated),
so we rather rely on Auth.
Parameters:
zone_name_class (Name, RRClass): the notified zone name and class.
master (str): textual address of the NOTIFY sender.
"""
if self._zone_not_exist(zone_name_class):
logger.debug(DBG_ZONEMGR_BASIC, ZONEMGR_ZONE_NOTIFY_NOT_SECONDARY,
zone_name_class[0], zone_name_class[1], master)
return False
self._set_zone_notifier_master(zone_name_class, master)
self._set_zone_notify_timer(zone_name_class)
return True
def zonemgr_reload_zone(self, zone_name_class):
""" Reload a zone."""
......@@ -423,7 +440,7 @@ class ZonemgrRefresh:
# Ask the thread to stop
self._running = False
self._write_sock.send(b'shutdown') # make self._read_sock readble
self._write_sock.send(b'shutdown') # make self._read_sock readable
# Wait for it to actually finnish
self._thread.join()
# Wipe out what we do not need
......@@ -630,27 +647,33 @@ class Zonemgr:
""" Handle Auth notify command"""
# master is the source sender of the notify message.
zone_name_class, master = self._parse_cmd_params(args, command)
logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_NOTIFY, zone_name_class[0], zone_name_class[1])
logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_NOTIFY,
zone_name_class[0], zone_name_class[1])
with self._lock:
self._zone_refresh.zone_handle_notify(zone_name_class, master)
# Send notification to zonemgr timer thread
self._master_socket.send(b" ")# make self._slave_socket readble
need_refresh = self._zone_refresh.zone_handle_notify(
zone_name_class, master)
if need_refresh:
# Send notification to zonemgr timer thread by making
# self._slave_socket readable.
self._master_socket.send(b" ")
elif command == notify_out.ZONE_NEW_DATA_READY_CMD:
""" Handle xfrin success command"""
zone_name_class = self._parse_cmd_params(args, command)
logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_XFRIN_SUCCESS, zone_name_class[0], zone_name_class[1])
logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_XFRIN_SUCCESS,
zone_name_class[0], zone_name_class[1])
with self._lock:
self._zone_refresh.zone_refresh_success(zone_name_class)
self._master_socket.send(b" ")# make self._slave_socket readble
self._master_socket.send(b" ")# make self._slave_socket readable
elif command == notify_out.ZONE_XFRIN_FAILED:
""" Handle xfrin fail command"""
zone_name_class = self._parse_cmd_params(args, command)
logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_XFRIN_FAILED, zone_name_class[0], zone_name_class[1])
logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_XFRIN_FAILED,
zone_name_class[0], zone_name_class[1])
with self._lock:
self._zone_refresh.zone_refresh_fail(zone_name_class)
self._master_socket.send(b" ")# make self._slave_socket readble
self._master_socket.send(b" ")# make self._slave_socket readable
elif command == "shutdown":
logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_SHUTDOWN)
......
......@@ -138,14 +138,19 @@ zone, or, if this error appears without the administrator giving transfer
commands, it can indicate an error in the program, as it should not have
initiated transfers of unknown zones on its own.
% ZONEMGR_UNKNOWN_ZONE_NOTIFIED notified zone %1/%2 from %3 is not known to the zone manager
A NOTIFY was received but the zone that was the subject of the operation
is not being managed by the zone manager. This may indicate an error
in the program (as the operation should not have been initiated if this
were the case). Please submit a bug report.
% ZONEMGR_UNKNOWN_ZONE_SUCCESS zone %1 (class %2) is not known to the zone manager
An XFRIN operation has succeeded but the zone received is not being
managed by the zone manager. This may indicate an error in the program
(as the operation should not have been initiated if this were the case).
Please submit a bug report.
% ZONEMGR_ZONE_NOTIFY_NOT_SECONDARY notify for zone %1/%2 from %3 received but not in secondaries
A NOTIFY was received but the zone is not listed in the configured
secondary zones of the zone manager. The most common reason for this
is that it's simply received by a primary server of the zone. Another
possibility is a configuration error that it's not configured as a
secondary while it should be. In either case, the zone manager does
not take action in terms of zone management, and the authoritative
server will respond to it like in the secondary case. If this is a
configuration error, it will be noticed by the fact that the zone
isn't updated even after a change is made in the primary server.
......@@ -570,6 +570,10 @@ class NotifyOut:
logger.error(NOTIFY_OUT_REPLY_UNCAUGHT_EXCEPTION, err)
return _BAD_REPLY_PACKET
logger.debug(logger.DBGLVL_TRACE_BASIC, NOTIFY_OUT_REPLY_RECEIVED,
zone_notify_info.zone_name, zone_notify_info.zone_class,
from_addr[0], from_addr[1], msg.get_rcode())
return _REPLY_OK
def _get_notify_reply(self, sock, tgt_addr):
......
......@@ -60,6 +60,11 @@ given address, but the reply did not have the QR bit set to one.
Since there was a response, no more notifies will be sent to this
server for this notification event.
% NOTIFY_OUT_REPLY_RECEIVED Zone %1/%2: notify response from %3:%4: %5
The notify_out library sent a notify message to the nameserver at
the given address, and received a response. Its Rcode will be shown,