Commit e653adac authored by Yoshitaka Aharen's avatar Yoshitaka Aharen
Browse files

Merge branch 'trac2157_merge'

Conflicts:
	ChangeLog
parents 54e52000 8131da32
581. [func]* y-aharen
Added statistics items in b10-auth based on
http://bind10.isc.org/wiki/StatisticsItems. Qtype counters are
dropped as it requires further spec design discussion.
(Trac #2154, Trac #2155,
git 61d7c3959eb991b22bc1c0ef8f4ecb96b65d9325)
(Trac #2157, git TBD)
bind10-1.0.0-rc released on February 14, 2013
580. [func]* muks
......
......@@ -1359,6 +1359,7 @@ AC_OUTPUT([doc/version.ent
src/bin/auth/tests/testdata/example.zone
src/bin/auth/tests/testdata/example-base.zone
src/bin/auth/tests/testdata/example-nsec3.zone
src/bin/auth/gen-statisticsitems.py.pre
src/bin/dhcp4/spec_config.h.pre
src/bin/dhcp6/spec_config.h.pre
src/bin/tests/process_rename_test.py
......
......@@ -18,6 +18,9 @@ pkglibexecdir = $(libexecdir)/@PACKAGE@
CLEANFILES = *.gcno *.gcda auth.spec spec_config.h
CLEANFILES += auth_messages.h auth_messages.cc
CLEANFILES += gen-statisticsitems.py
# auto-generated by gen-statisticsitems.py
CLEANFILES += statistics.cc statistics_items.h b10-auth.xml tests/statistics_unittest.cc
man_MANS = b10-auth.8
DISTCLEANFILES = $(man_MANS)
......@@ -26,7 +29,7 @@ EXTRA_DIST = $(man_MANS) b10-auth.xml
if GENERATE_DOCS
b10-auth.8: b10-auth.xml
@XSLTPROC@ --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-auth.xml
@XSLTPROC@ --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(builddir)/b10-auth.xml
else
......@@ -36,8 +39,18 @@ $(man_MANS):
endif
auth.spec: auth.spec.pre
$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" auth.spec.pre >$@
auth.spec: auth.spec.pre statistics_msg_items.def
b10-auth.xml: b10-auth.xml.pre statistics_msg_items.def
statistics_items.h: statistics_items.h.pre statistics_msg_items.def
statistics.cc: statistics.cc.pre statistics_msg_items.def
tests/statistics_unittest.cc: tests/statistics_unittest.cc.pre statistics_msg_items.def
gen-statisticsitems.py: gen-statisticsitems.py.pre
$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" gen-statisticsitems.py.pre >$@
chmod +x $@
auth.spec b10-auth.xml statistics_items.h statistics.cc tests/statistics_unittest.cc: Makefile gen-statisticsitems.py
./gen-statisticsitems.py
spec_config.h: spec_config.h.pre
$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" spec_config.h.pre >$@
......@@ -46,6 +59,8 @@ auth_messages.h auth_messages.cc: auth_messages.mes
$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/bin/auth/auth_messages.mes
BUILT_SOURCES = spec_config.h auth_messages.h auth_messages.cc
# auto-generated by gen-statisticsitems.py
BUILT_SOURCES += statistics_items.h statistics.cc
pkglibexec_PROGRAMS = b10-auth
b10_auth_SOURCES = query.cc query.h
......@@ -54,13 +69,18 @@ b10_auth_SOURCES += auth_log.cc auth_log.h
b10_auth_SOURCES += auth_config.cc auth_config.h
b10_auth_SOURCES += command.cc command.h
b10_auth_SOURCES += common.h common.cc
b10_auth_SOURCES += statistics.cc statistics.h statistics_items.h
b10_auth_SOURCES += statistics.h
b10_auth_SOURCES += datasrc_clients_mgr.h
b10_auth_SOURCES += datasrc_config.h datasrc_config.cc
b10_auth_SOURCES += main.cc
nodist_b10_auth_SOURCES = auth_messages.h auth_messages.cc
nodist_b10_auth_SOURCES += statistics.cc statistics_items.h
EXTRA_DIST += auth_messages.mes
EXTRA_DIST += statistics_msg_items.def
EXTRA_DIST += b10-auth.xml.pre
EXTRA_DIST += statistics_items.h.pre statistics.cc.pre
EXTRA_DIST += tests/statistics_unittest.cc.pre
b10_auth_LDADD = $(top_builddir)/src/lib/datasrc/libb10-datasrc.la
b10_auth_LDADD += $(top_builddir)/src/lib/dns/libb10-dns++.la
......
......@@ -122,7 +122,7 @@
"item_name": "class", "item_type": "string",
"item_optional": true, "item_default": "IN"
},
{
{
"item_name": "origin", "item_type": "string",
"item_optional": false, "item_default": ""
}
......@@ -140,222 +140,6 @@
}
],
"statistics": [
{
"item_name": "queries.tcp",
"item_type": "integer",
"item_optional": false,
"item_default": 0,
"item_title": "Queries TCP",
"item_description": "A number of total query counts which all auth servers receive over TCP since they started initially"
},
{
"item_name": "queries.udp",
"item_type": "integer",
"item_optional": false,
"item_default": 0,
"item_title": "Queries UDP",
"item_description": "A number of total query counts which all auth servers receive over UDP since they started initially"
},
{
"item_name": "opcode.query",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Received query requests",
"item_description": "The number of total request counts whose opcode is query"
},
{
"item_name": "opcode.iquery",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Received inverse query requests",
"item_description": "The number of total request counts whose opcode is inverse query"
},
{
"item_name": "opcode.status",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Received status requests",
"item_description": "The number of total request counts whose opcode is status"
},
{
"item_name": "opcode.notify",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Received notify requests",
"item_description": "The number of total request counts whose opcode is notify"
},
{
"item_name": "opcode.update",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Received update requests",
"item_description": "The number of total request counts whose opcode is update"
},
{
"item_name": "opcode.other",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Received requests opcode other",
"item_description": "The number of total request counts whose opcode is other (not well-known)"
},
{
"item_name": "rcode.noerror",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent success response",
"item_description": "The number of total responses with rcode 0 (NOERROR)"
},
{
"item_name": "rcode.formerr",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'format error' response",
"item_description": "The number of total responses with rcode 1 (FORMERR)"
},
{
"item_name": "rcode.servfail",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'server failure' response",
"item_description": "The number of total responses with rcode 2 (SERVFAIL)"
},
{
"item_name": "rcode.nxdomain",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'name error' response",
"item_description": "The number of total responses with rcode 3 (NXDOMAIN)"
},
{
"item_name": "rcode.notimp",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'not implemented' response",
"item_description": "The number of total responses with rcode 4 (NOTIMP)"
},
{
"item_name": "rcode.refused",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'refused' response",
"item_description": "The number of total responses with rcode 5 (REFUSED)"
},
{
"item_name": "rcode.yxdomain",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'name unexpectedly exists' response",
"item_description": "The number of total responses with rcode 6 (YXDOMAIN)"
},
{
"item_name": "rcode.yxrrset",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'rrset unexpectedly exists' response",
"item_description": "The number of total responses with rcode 7 (YXRRSET)"
},
{
"item_name": "rcode.nxrrset",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'no such rrset' response",
"item_description": "The number of total responses with rcode 8 (NXRRSET)"
},
{
"item_name": "rcode.notauth",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'not authoritative' response",
"item_description": "The number of total responses with rcode 9 (NOTAUTH)"
},
{
"item_name": "rcode.notzone",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'name not in zone' response",
"item_description": "The number of total responses with rcode 10 (NOTZONE)"
},
{
"item_name": "rcode.badsigvers",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'EDNS version not implemented' response",
"item_description": "The number of total responses with rcode 16 (BADVERS)"
},
{
"item_name": "rcode.badkey",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'Key not recognized' response",
"item_description": "The number of total responses with rcode 17 (BADKEY)"
},
{
"item_name": "rcode.badtime",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'Signature out of time window' response",
"item_description": "The number of total responses with rcode 18 (BADTIME)"
},
{
"item_name": "rcode.badmode",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'Bad TKEY Mode' response",
"item_description": "The number of total responses with rcode 19 (BADMODE)"
},
{
"item_name": "rcode.badname",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'Duplicate key name' response",
"item_description": "The number of total responses with rcode 20 (BADNAME)"
},
{
"item_name": "rcode.badalg",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'Algorithm not supported' response",
"item_description": "The number of total responses with rcode 21 (BADALG)"
},
{
"item_name": "rcode.badtrunc",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent 'Bad Truncation' response",
"item_description": "The number of total responses with rcode 22 (BADTRUNC)"
},
{
"item_name": "rcode.other",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
"item_title": "Sent responses with rcode other",
"item_description": "The number of total responses with rcode other (not well-known)"
}
]
}
}
......@@ -86,6 +86,7 @@ using namespace isc::asiolink;
using namespace isc::asiodns;
using namespace isc::server_common::portconfig;
using isc::auth::statistics::Counters;
using isc::auth::statistics::MessageAttributes;
namespace {
// A helper class for cleaning up message renderer.
......@@ -102,17 +103,21 @@ namespace {
// user of this class, so we hide it within the implementation.
class RendererHolder {
public:
RendererHolder(MessageRenderer& renderer, OutputBuffer* buffer) :
renderer_(renderer)
RendererHolder(MessageRenderer& renderer, OutputBuffer* buffer,
MessageAttributes& stats_attrs) :
renderer_(renderer),
stats_attrs_(stats_attrs)
{
renderer.setBuffer(buffer);
}
~RendererHolder() {
stats_attrs_.setResponseTruncated(renderer_.isTruncated());
renderer_.setBuffer(NULL);
renderer_.clear();
}
private:
MessageRenderer& renderer_;
MessageAttributes& stats_attrs_;
};
// Similar to Renderer holder, this is a very basic RAII-style class
......@@ -239,15 +244,19 @@ public:
BaseSocketSessionForwarder& ddns_forwarder);
~AuthSrvImpl();
bool processNormalQuery(const IOMessage& io_message, Message& message,
bool processNormalQuery(const IOMessage& io_message,
ConstEDNSPtr remote_edns, Message& message,
OutputBuffer& buffer,
auto_ptr<TSIGContext> tsig_context);
auto_ptr<TSIGContext> tsig_context,
MessageAttributes& stats_attrs);
bool processXfrQuery(const IOMessage& io_message, Message& message,
OutputBuffer& buffer,
auto_ptr<TSIGContext> tsig_context);
auto_ptr<TSIGContext> tsig_context,
MessageAttributes& stats_attrs);
bool processNotify(const IOMessage& io_message, Message& message,
OutputBuffer& buffer,
auto_ptr<TSIGContext> tsig_context);
auto_ptr<TSIGContext> tsig_context,
MessageAttributes& stats_attrs);
bool processUpdate(const IOMessage& io_message);
IOService io_service_;
......@@ -272,10 +281,6 @@ public:
/// The data source client list manager
auth::DataSrcClientsMgr datasrc_clients_mgr_;
/// Bind the ModuleSpec object in config_session_ with
/// isc:config::ModuleSpec::validateStatistics.
void registerStatisticsValidator();
/// Socket session forwarder for dynamic update requests
BaseSocketSessionForwarder& ddns_base_forwarder_;
......@@ -293,25 +298,17 @@ public:
///
/// \param server The DNSServer as passed to processMessage()
/// \param message The response as constructed by processMessage()
/// \param stats_attrs Query/response attributes for statistics which is
/// not in \p messsage.
/// Note: This parameter is modified inside this method
/// to store whether the answer has been sent and
/// the response is truncated.
/// \param done If true, it indicates there is a response.
/// this value will be passed to server->resume(bool)
void resumeServer(isc::asiodns::DNSServer* server,
isc::dns::Message& message,
statistics::QRAttributes& stats_attrs,
MessageAttributes& stats_attrs,
const bool done);
private:
bool xfrout_connected_;
AbstractXfroutClient& xfrout_client_;
// validateStatistics
bool validateStatistics(isc::data::ConstElementPtr data) const;
auth::Query query_;
};
......@@ -423,6 +420,7 @@ public:
void
makeErrorMessage(MessageRenderer& renderer, Message& message,
OutputBuffer& buffer, const Rcode& rcode,
MessageAttributes& stats_attrs,
std::auto_ptr<TSIGContext> tsig_context =
std::auto_ptr<TSIGContext>())
{
......@@ -455,9 +453,10 @@ makeErrorMessage(MessageRenderer& renderer, Message& message,
message.setRcode(rcode);
RendererHolder holder(renderer, &buffer);
RendererHolder holder(renderer, &buffer, stats_attrs);
if (tsig_context.get() != NULL) {
message.toWire(renderer, *tsig_context);
stats_attrs.setResponseTSIG(true);
} else {
message.toWire(renderer);
}
......@@ -484,7 +483,6 @@ AuthSrv::setXfrinSession(AbstractSession* xfrin_session) {
void
AuthSrv::setConfigSession(ModuleCCSession* config_session) {
impl_->config_session_ = config_session;
impl_->registerStatisticsValidator();
}
ModuleCCSession*
......@@ -497,11 +495,11 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
OutputBuffer& buffer, DNSServer* server)
{
InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
statistics::QRAttributes stats_attrs;
MessageAttributes stats_attrs;
// statistics: check transport carrying the message (IP, transport)
stats_attrs.setQueryIPVersion(io_message.getRemoteEndpoint().getFamily());
stats_attrs.setQueryTransportProtocol(
stats_attrs.setRequestIPVersion(
io_message.getRemoteEndpoint().getFamily());
stats_attrs.setRequestTransportProtocol(
io_message.getRemoteEndpoint().getProtocol());
// First, check the header part. If we fail even for the base header,
......@@ -522,19 +520,26 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
return;
}
const Opcode& opcode = message.getOpcode();
// Get opcode at this point; for all requests regardless of message body
// sanity check.
stats_attrs.setRequestOpCode(opcode);
try {
// Parse the message.
message.fromWire(request_buffer);
} catch (const DNSProtocolError& error) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_PACKET_PROTOCOL_FAILURE)
.arg(error.getRcode().toText()).arg(error.what());
makeErrorMessage(impl_->renderer_, message, buffer, error.getRcode());
makeErrorMessage(impl_->renderer_, message, buffer, error.getRcode(),
stats_attrs);
impl_->resumeServer(server, message, stats_attrs, true);
return;
} catch (const Exception& ex) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_PACKET_PARSE_FAILED)
.arg(ex.what());
makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL(),
stats_attrs);
impl_->resumeServer(server, message, stats_attrs, true);
return;
} // other exceptions will be handled at a higher layer.
......@@ -558,85 +563,82 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
**impl_->keyring_));
tsig_error = tsig_context->verify(tsig_record, io_message.getData(),
io_message.getDataSize());
// statistics: check TSIG attributes
// SIG(0) is currently not implemented in Auth, but it is implemented
// in BIND 9. At the point we support it, the code to check if the
// signature is valid would be around here.
stats_attrs.setQuerySig(true, false,
tsig_error == TSIGError::NOERROR());
stats_attrs.setRequestTSIG(true, tsig_error != TSIGError::NOERROR());
}
if (tsig_error != TSIGError::NOERROR()) {
makeErrorMessage(impl_->renderer_, message, buffer,
tsig_error.toRcode(), tsig_context);
tsig_error.toRcode(), stats_attrs, tsig_context);
impl_->resumeServer(server, message, stats_attrs, true);
return;
}
const Opcode opcode = message.getOpcode();
bool send_answer = true;
try {
// statistics: check EDNS
// note: This can only be reliable after TSIG check succeeds.
// note: This can only be reliable after TSIG check succeeds.
ConstEDNSPtr edns = message.getEDNS();
if (edns != NULL) {
stats_attrs.setQueryEDNS(true, edns->getVersion() == 0);
stats_attrs.setQueryDO(edns->getDNSSECAwareness());
if (edns) {
stats_attrs.setRequestEDNS0(true);
stats_attrs.setRequestDO(edns->getDNSSECAwareness());
}
// statistics: check OpCode
// note: This can only be reliable after TSIG check succeeds.
stats_attrs.setQueryOpCode(opcode.getCode());
// note: This can only be reliable after TSIG check succeeds.
if (opcode == Opcode::NOTIFY()) {
send_answer = impl_->processNotify(io_message, message, buffer,
tsig_context);
tsig_context, stats_attrs);
} else if (opcode == Opcode::UPDATE()) {
if (impl_->ddns_forwarder_) {
send_answer = impl_->processUpdate(io_message);
} else {
makeErrorMessage(impl_->renderer_, message, buffer,
Rcode::NOTIMP(), tsig_context);
Rcode::NOTIMP(), stats_attrs, tsig_context);
}
} else if (opcode != Opcode::QUERY()) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_UNSUPPORTED_OPCODE)
.arg(message.getOpcode().toText());
makeErrorMessage(impl_->renderer_, message, buffer,
Rcode::NOTIMP(), tsig_context);
Rcode::NOTIMP(), stats_attrs, tsig_context);
} else if (message.getRRCount(Message::SECTION_QUESTION) != 1) {
makeErrorMessage(impl_->renderer_, message, buffer,
Rcode::FORMERR(), tsig_context);
Rcode::FORMERR(), stats_attrs, tsig_context);
} else {
ConstQuestionPtr question = *message.beginQuestion();
const RRType& qtype = question->getType();
if (qtype == RRType::AXFR()) {
send_answer = impl_->processXfrQuery(io_message, message,
buffer, tsig_context);
buffer, tsig_context,
stats_attrs);
} else if (qtype == RRType::IXFR()) {
send_answer = impl_->processXfrQuery(io_message, message,
buffer, tsig_context);
buffer, tsig_context,
stats_attrs);
} else {
send_answer = impl_->processNormalQuery(io_message, message,
buffer, tsig_context);
send_answer = impl_->processNormalQuery(io_message, edns,
message, buffer,
tsig_context,
stats_attrs);
}
}
} catch (const std::exception& ex) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RESPONSE_FAILURE)
.arg(ex.what());
makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL(),
stats_attrs);
} catch (...) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RESPONSE_FAILURE_UNKNOWN);
makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL(),
stats_attrs);
}
impl_->resumeServer(server, message, stats_attrs, send_answer);
}
bool
AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
AuthSrvImpl::processNormalQuery(const IOMessage& io_message,
ConstEDNSPtr remote_edns, Message& message,
OutputBuffer& buffer,
auto_ptr<TSIGContext> tsig_context)
auto_ptr<TSIGContext> tsig_context,
MessageAttributes& stats_attrs)
{
ConstEDNSPtr remote_edns = message.getEDNS();
const bool dnssec_ok = remote_edns && remote_edns->getDNSSECAwareness();
const uint16_t remote_bufsize = remote_edns ? remote_edns->getUDPSize() :
Message::DEFAULT_MAX_UDPSIZE;
......@@ -666,21 +668,24 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
const Name& qname = question->getName();
query_.process(*list, qname, qtype, message, dnssec_ok);
} else {
makeErrorMessage(renderer_, message, buffer, Rcode::REFUSED());
makeErrorMessage(renderer_, message, buffer, Rcode::REFUSED(),
stats_attrs);
return (true);
}
} catch (const Exception& ex) {
LOG_ERROR(auth_logger, AUTH_PROCESS_FAIL).arg(ex.what());
makeErrorMessage(renderer_, message, buffer, Rcode::SERVFAIL());
makeErrorMessage(renderer_, message, buffer, Rcode::SERVFAIL(),
stats_attrs);
return (true);
}
RendererHolder holder(renderer_, &buffer);
RendererHolder holder(renderer_, &buffer, stats_attrs);
const bool udp_buffer =
(io_message.getSocket().getProtocol() == IPPROTO_UDP);
renderer_.setLengthLimit(udp_buffer ? remote_bufsize : 65535);
if (tsig_context.get() != NULL) {
message.toWire(renderer_, *tsig_context);
stats_attrs.setResponseTSIG(true);
} else {
message.toWire(renderer_);
}
......@@ -697,12 +702,13 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
bool