Commit 289a358d authored by Jerry's avatar Jerry
Browse files

sync with trunk


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac439@3981 e5f2f494-b856-4b98-b285-d166d9295462
parents af0c2907 b5ff3f23
135. [bug] jelte
bindctl (and the configuration manager in general) now no longer
accepts 'unknown' data; i.e. data for modules that it does not know
about, or configuration items that are not specified in the .spec
files.
(Trac #202, svn r3967)
134. [func] vorner
b10-recurse supports timeouts and retries in forwarder mode.
(Trac #401, svn r3660)
133. [func] vorner
New temporary logging function available in isc::log. It is used by
b10-recurse.
(Trac #393, r3602)
132. [func] vorner
The b10-recursive is configured through config manager.
It has "listen_on" and "forward_addresses" options.
(Trac #389, r3448)
131. [func] feng, jerry
src/lib/datasrc: Introduced two template classes RBTree and RBNode
to provide the generic map with domain name as key and anything as
the value. Because of some unresolved design issue, the new classes
are only intended to be used by memory zone and zone table.
(Trac #397, svn r3890)
130. [func] jerry
src/lib/datasrc: Introduced a new class MemoryDataSrc to provide
src/lib/datasrc: Introduced a new class MemoryDataSrc to provide
the general interface for memory data source. For the initial
implementation, we don't make it a derived class of AbstractDataSrc
because the interface is so different(we'll eventually consider this
......
......@@ -195,14 +195,15 @@ fi
# specify the default warning flags in CXXFLAGS and let specific modules
# "override" the default.
# This may be used to try compiler flags.
# This may be used to try linker flags.
AC_DEFUN([BIND10_CXX_TRY_FLAG], [
AC_MSG_CHECKING([whether $CXX supports $1])
bind10_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $1"
AC_COMPILE_IFELSE([ ], [bind10_cxx_flag=yes], [bind10_cxx_flag=no])
AC_LINK_IFELSE([int main(void){ return 0;} ],
[bind10_cxx_flag=yes], [bind10_cxx_flag=no])
CXXFLAGS="$bind10_save_CXXFLAGS"
if test "x$bind10_cxx_flag" = "xyes"; then
......@@ -367,13 +368,31 @@ CPPFLAGS_SAVES="$CPPFLAGS"
LIBS_SAVES="$LIBS"
CPPFLAGS="$BOOST_INCLUDES $CPPFLAGS $MULTITHREADING_FLAG"
need_libboost_thread=0
need_sunpro_workaround=0
AC_TRY_LINK([
#include <boost/thread.hpp>
],[
boost::mutex m;
],
[ AC_MSG_RESULT(yes (without libboost_thread)) ],
[ LIBS=" $LIBS -lboost_thread"
# there is one specific problem with SunStudio 5.10
# where including boost/thread causes a compilation failure
# There is a workaround in boost but it checks the version not being 5.10
# This will probably be fixed in the future, in which case this
# is only a temporary workaround
[ AC_TRY_LINK([
#if defined(__SUNPRO_CC) && __SUNPRO_CC == 0x5100
#undef __SUNPRO_CC
#define __SUNPRO_CC 0x5090
#endif
#include <boost/thread.hpp>
],[
boost::mutex m;
],
[ AC_MSG_RESULT(yes (with SUNOS workaround))
need_sunpro_workaround=1 ],
[ LIBS=" $LIBS -lboost_thread"
AC_TRY_LINK([
#include <boost/thread.hpp>
],[
......@@ -385,10 +404,13 @@ boost::mutex m;
AC_MSG_ERROR([boost::mutex cannot be linked in this build environment.
Perhaps you are using an older version of Boost that requires libboost_thread for the mutex support, which does not appear to be available.
You may want to check the availability of the library or to upgrade Boost.])
])])
])])])
CPPFLAGS="$CPPFLAGS_SAVES"
LIBS="$LIBS_SAVES"
AM_CONDITIONAL(NEED_LIBBOOST_THREAD, test $need_libboost_thread = 1)
if test $need_sunpro_workaround = 1; then
AC_DEFINE([NEED_SUNPRO_WORKAROUND], [], [Need boost sunstudio workaround])
fi
#
# Check availability of gtest, which will be used for unit tests.
......@@ -534,9 +556,9 @@ AC_CONFIG_FILES([Makefile
src/bin/msgq/tests/Makefile
src/bin/auth/Makefile
src/bin/auth/tests/Makefile
src/bin/auth/tests/testdata/Makefile
src/bin/auth/benchmarks/Makefile
src/bin/recurse/Makefile
src/bin/recurse/tests/Makefile
src/bin/xfrin/Makefile
src/bin/xfrin/tests/Makefile
src/bin/xfrout/Makefile
......@@ -553,6 +575,8 @@ AC_CONFIG_FILES([Makefile
src/bin/usermgr/Makefile
src/bin/tests/Makefile
src/lib/Makefile
src/lib/asiolink/Makefile
src/lib/asiolink/tests/Makefile
src/lib/bench/Makefile
src/lib/bench/example/Makefile
src/lib/bench/tests/Makefile
......@@ -587,6 +611,9 @@ AC_CONFIG_FILES([Makefile
src/lib/datasrc/Makefile
src/lib/datasrc/tests/Makefile
src/lib/xfr/Makefile
src/lib/log/Makefile
src/lib/testutils/Makefile
src/lib/testutils/testdata/Makefile
src/lib/nsas/Makefile
src/lib/nsas/tests/Makefile
])
......@@ -603,9 +630,8 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py
src/bin/xfrout/xfrout.spec.pre
src/bin/xfrout/tests/xfrout_test
src/bin/xfrout/run_b10-xfrout.sh
src/bin/recurse/recurse.py
src/bin/recurse/recurse.spec.pre
src/bin/recurse/run_b10-recurse.sh
src/bin/recurse/spec_config.h.pre
src/bin/zonemgr/zonemgr.py
src/bin/zonemgr/zonemgr.spec.pre
src/bin/zonemgr/tests/zonemgr_test
......
......@@ -568,7 +568,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = ../src/lib/cc ../src/lib/config ../src/lib/dns ../src/lib/exceptions ../src/lib/datasrc ../src/bin/auth ../src/lib/bench ../src/lib/nsas
INPUT = ../src/lib/cc ../src/lib/config ../src/lib/dns ../src/lib/exceptions ../src/lib/datasrc ../src/bin/auth ../src/lib/bench ../src/lib/log ../src/lib/asiolink/ ../src/lib/nsas
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
......
......@@ -3,8 +3,9 @@ SUBDIRS = . tests benchmarks
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
AM_CPPFLAGS += -I$(top_builddir)/src/lib/cc
AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/cc -I$(top_builddir)/src/lib/cc
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiolink
AM_CPPFLAGS += -I$(top_builddir)/src/lib/asiolink
AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CXXFLAGS = $(B10_CXXFLAGS)
......@@ -33,26 +34,6 @@ auth.spec: auth.spec.pre
spec_config.h: spec_config.h.pre
$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" spec_config.h.pre >$@
# This is a wrapper library solely used for b10-auth. The ASIO header files
# have some code fragments that would hit gcc's unused-parameter warning,
# which would make the build fail with -Werror (our default setting).
# We don't want to lower the warning level for our own code just for ASIO,
# so as a workaround we extract the ASIO related code into a separate library,
# only for which we accept the unused-parameter warning.
lib_LIBRARIES = libasio_link.a
libasio_link_a_SOURCES = asio_link.cc asio_link.h
# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
# B10_CXXFLAGS)
libasio_link_a_CXXFLAGS = $(AM_CXXFLAGS)
if USE_GXX
libasio_link_a_CXXFLAGS += -Wno-unused-parameter
endif
if USE_CLANGPP
# Same for clang++, but we need to turn off -Werror completely.
libasio_link_a_CXXFLAGS += -Wno-error
endif
libasio_link_a_CPPFLAGS = $(AM_CPPFLAGS)
BUILT_SOURCES = spec_config.h
pkglibexec_PROGRAMS = b10-auth
b10_auth_SOURCES = query.cc query.h
......@@ -65,7 +46,7 @@ b10_auth_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
b10_auth_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
b10_auth_LDADD += $(top_builddir)/src/lib/cc/libcc.la
b10_auth_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
b10_auth_LDADD += libasio_link.a
b10_auth_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
b10_auth_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
b10_auth_LDADD += $(SQLITE_LIBS)
......
This diff is collapsed.
......@@ -14,6 +14,8 @@
// $Id$
#include <config.h>
#include <netinet/in.h>
#include <algorithm>
......@@ -21,6 +23,12 @@
#include <iostream>
#include <vector>
#include <asiolink/asiolink.h>
#include <config/ccsession.h>
#include <cc/data.h>
#include <exceptions/exceptions.h>
#include <dns/buffer.h>
......@@ -34,9 +42,6 @@
#include <dns/rrset.h>
#include <dns/rrttl.h>
#include <dns/message.h>
#include <config/ccsession.h>
#include <cc/data.h>
#include <exceptions/exceptions.h>
#include <datasrc/query.h>
#include <datasrc/data_source.h>
......@@ -44,13 +49,10 @@
#include <datasrc/sqlite3_datasrc.h>
#include <datasrc/memory_datasrc.h>
#include <cc/data.h>
#include <xfr/xfrout_client.h>
#include <auth/common.h>
#include <auth/auth_srv.h>
#include <auth/asio_link.h>
#include <auth/query.h>
using namespace std;
......@@ -64,7 +66,7 @@ using namespace isc::dns::rdata;
using namespace isc::data;
using namespace isc::config;
using namespace isc::xfr;
using namespace asio_link;
using namespace asiolink;
class AuthSrvImpl {
private:
......@@ -76,33 +78,35 @@ public:
~AuthSrvImpl();
isc::data::ConstElementPtr setConfig(isc::data::ConstElementPtr config);
bool processNormalQuery(const IOMessage& io_message, Message& message,
MessageRenderer& response_renderer);
bool processAxfrQuery(const IOMessage& io_message, Message& message,
MessageRenderer& response_renderer);
bool processNotify(const IOMessage& io_message, Message& message,
MessageRenderer& response_renderer);
std::string db_file_;
bool processNormalQuery(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer);
bool processAxfrQuery(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer);
bool processNotify(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer);
/// Currently non-configurable, but will be.
static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
/// These members are public because AuthSrv accesses them directly.
ModuleCCSession* config_session_;
bool verbose_mode_;
AbstractSession* xfrin_session_;
/// Hot spot cache
isc::datasrc::HotCache cache_;
private:
std::string db_file_;
MetaDataSrc data_sources_;
/// We keep a pointer to the currently running sqlite datasource
/// so that we can specifically remove that one should the database
/// file change
ConstDataSrcPtr cur_datasrc_;
bool verbose_mode_;
AbstractSession* xfrin_session_;
bool xfrout_connected_;
AbstractXfroutClient& xfrout_client_;
/// Currently non-configurable, but will be.
static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
/// Hot spot cache
isc::datasrc::HotCache cache_;
// enable memory data source
bool use_memory_datasrc_;
/// Currently, MemoryDataSrc isn't a derived class of AbstractDataSrc
......@@ -136,60 +140,127 @@ AuthSrvImpl::~AuthSrvImpl() {
}
}
// This is a derived class of \c DNSLookup, to serve as a
// callback in the asiolink module. It calls
// AuthSrv::processMessage() on a single DNS message.
class MessageLookup : public DNSLookup {
public:
MessageLookup(AuthSrv* srv) : server_(srv) {}
virtual void operator()(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer, DNSServer* server) const
{
server_->processMessage(io_message, message, buffer, server);
}
private:
AuthSrv* server_;
};
// This is a derived class of \c DNSAnswer, to serve as a
// callback in the asiolink module. It takes a completed
// set of answer data from the DNS lookup and assembles it
// into a wire-format response.
class MessageAnswer : public DNSAnswer {
public:
MessageAnswer(AuthSrv* srv) : server_(srv) {}
virtual void operator()(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer) const
{
MessageRenderer renderer(*buffer);
if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
ConstEDNSPtr edns(message->getEDNS());
renderer.setLengthLimit(edns ? edns->getUDPSize() :
Message::DEFAULT_MAX_UDPSIZE);
} else {
renderer.setLengthLimit(65535);
}
message->toWire(renderer);
if (server_->getVerbose()) {
cerr << "[b10-auth] sending a response (" << renderer.getLength()
<< " bytes):\n" << message->toText() << endl;
}
}
private:
AuthSrv* server_;
};
// This is a derived class of \c SimpleCallback, to serve
// as a callback in the asiolink module. It checks for queued
// configuration messages, and executes them if found.
class ConfigChecker : public SimpleCallback {
public:
ConfigChecker(AuthSrv* srv) : server_(srv) {}
virtual void operator()(const IOMessage&) const {
if (server_->getConfigSession()->hasQueuedMsgs()) {
server_->getConfigSession()->checkCommand();
}
}
private:
AuthSrv* server_;
};
AuthSrv::AuthSrv(const bool use_cache, AbstractXfroutClient& xfrout_client) :
impl_(new AuthSrvImpl(use_cache, xfrout_client))
impl_(new AuthSrvImpl(use_cache, xfrout_client)),
checkin_(new ConfigChecker(this)),
dns_lookup_(new MessageLookup(this)),
dns_answer_(new MessageAnswer(this))
{}
AuthSrv::~AuthSrv() {
delete impl_;
delete checkin_;
delete dns_lookup_;
delete dns_answer_;
}
namespace {
class QuestionInserter {
public:
QuestionInserter(Message* message) : message_(message) {}
QuestionInserter(MessagePtr message) : message_(message) {}
void operator()(const QuestionPtr question) {
message_->addQuestion(question);
}
Message* message_;
MessagePtr message_;
};
void
makeErrorMessage(Message& message, MessageRenderer& renderer,
makeErrorMessage(MessagePtr message, OutputBufferPtr buffer,
const Rcode& rcode, const bool verbose_mode)
{
// extract the parameters that should be kept.
// XXX: with the current implementation, it's not easy to set EDNS0
// depending on whether the query had it. So we'll simply omit it.
const qid_t qid = message.getQid();
const bool rd = message.getHeaderFlag(Message::HEADERFLAG_RD);
const bool cd = message.getHeaderFlag(Message::HEADERFLAG_CD);
const Opcode& opcode = message.getOpcode();
const qid_t qid = message->getQid();
const bool rd = message->getHeaderFlag(Message::HEADERFLAG_RD);
const bool cd = message->getHeaderFlag(Message::HEADERFLAG_CD);
const Opcode& opcode = message->getOpcode();
vector<QuestionPtr> questions;
// If this is an error to a query or notify, we should also copy the
// question section.
if (opcode == Opcode::QUERY() || opcode == Opcode::NOTIFY()) {
questions.assign(message.beginQuestion(), message.endQuestion());
questions.assign(message->beginQuestion(), message->endQuestion());
}
message.clear(Message::RENDER);
message.setQid(qid);
message.setOpcode(opcode);
message.setHeaderFlag(Message::HEADERFLAG_QR);
message->clear(Message::RENDER);
message->setQid(qid);
message->setOpcode(opcode);
message->setHeaderFlag(Message::HEADERFLAG_QR);
if (rd) {
message.setHeaderFlag(Message::HEADERFLAG_RD);
message->setHeaderFlag(Message::HEADERFLAG_RD);
}
if (cd) {
message.setHeaderFlag(Message::HEADERFLAG_CD);
message->setHeaderFlag(Message::HEADERFLAG_CD);
}
for_each(questions.begin(), questions.end(), QuestionInserter(&message));
message.setRcode(rcode);
message.toWire(renderer);
for_each(questions.begin(), questions.end(), QuestionInserter(message));
message->setRcode(rcode);
MessageRenderer renderer(*buffer);
message->toWire(renderer);
if (verbose_mode) {
cerr << "[b10-auth] sending an error response (" <<
renderer.getLength() << " bytes):\n" << message.toText() << endl;
renderer.getLength() << " bytes):\n" << message->toText() << endl;
}
}
}
......@@ -229,105 +300,108 @@ AuthSrv::getConfigSession() const {
return (impl_->config_session_);
}
bool
AuthSrv::processMessage(const IOMessage& io_message, Message& message,
MessageRenderer& response_renderer)
void
AuthSrv::processMessage(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer, DNSServer* server)
{
InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
// First, check the header part. If we fail even for the base header,
// just drop the message.
try {
message.parseHeader(request_buffer);
message->parseHeader(request_buffer);
// Ignore all responses.
if (message.getHeaderFlag(Message::HEADERFLAG_QR)) {
if (message->getHeaderFlag(Message::HEADERFLAG_QR)) {
if (impl_->verbose_mode_) {
cerr << "[b10-auth] received unexpected response, ignoring"
<< endl;
}
return (false);
server->resume(false);
return;
}
} catch (const Exception& ex) {
return (false);
if (impl_->verbose_mode_) {
cerr << "[b10-auth] DNS packet exception: " << ex.what() << endl;
}
server->resume(false);
return;
}
// Parse the message. On failure, return an appropriate error.
try {
message.fromWire(request_buffer);
// Parse the message.
message->fromWire(request_buffer);
} catch (const DNSProtocolError& error) {
if (impl_->verbose_mode_) {
cerr << "[b10-auth] returning " << error.getRcode().toText()
<< ": " << error.what() << endl;
}
makeErrorMessage(message, response_renderer, error.getRcode(),
makeErrorMessage(message, buffer, error.getRcode(),
impl_->verbose_mode_);
return (true);
server->resume(true);
return;
} catch (const Exception& ex) {
if (impl_->verbose_mode_) {
cerr << "[b10-auth] returning SERVFAIL: " << ex.what() << endl;
}
makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),
makeErrorMessage(message, buffer, Rcode::SERVFAIL(),
impl_->verbose_mode_);
return (true);
server->resume(true);
return;
} // other exceptions will be handled at a higher layer.
if (impl_->verbose_mode_) {
cerr << "[b10-auth] received a message:\n" << message.toText() << endl;
cerr << "[b10-auth] received a message:\n" << message->toText() << endl;
}
// Perform further protocol-level validation.
if (message.getOpcode() == Opcode::NOTIFY()) {
return (impl_->processNotify(io_message, message, response_renderer));
} else if (message.getOpcode() != Opcode::QUERY()) {
bool sendAnswer = true;
if (message->getOpcode() == Opcode::NOTIFY()) {
sendAnswer = impl_->processNotify(io_message, message, buffer);
} else if (message->getOpcode() != Opcode::QUERY()) {
if (impl_->verbose_mode_) {
cerr << "[b10-auth] unsupported opcode" << endl;
}
makeErrorMessage(message, response_renderer, Rcode::NOTIMP(),
makeErrorMessage(message, buffer, Rcode::NOTIMP(),
impl_->verbose_mode_);
return (true);
}
if (message.getRRCount(Message::SECTION_QUESTION) != 1) {
makeErrorMessage(message, response_renderer, Rcode::FORMERR(),
} else if (message->getRRCount(Message::SECTION_QUESTION) != 1) {
makeErrorMessage(message, buffer, Rcode::FORMERR(),
impl_->verbose_mode_);
return (true);
}
ConstQuestionPtr question = *message.beginQuestion();
const RRType &qtype = question->getType();
if (qtype == RRType::AXFR()) {
return (impl_->processAxfrQuery(io_message, message,
response_renderer));
} else if (qtype == RRType::IXFR()) {
makeErrorMessage(message, response_renderer, Rcode::NOTIMP(),
impl_->verbose_mode_);
return (true);
} else {
return (impl_->processNormalQuery(io_message, message,
response_renderer));
ConstQuestionPtr question = *message->beginQuestion();
const RRType &qtype = question->getType();
if (qtype == RRType::AXFR()) {
sendAnswer = impl_->processAxfrQuery(io_message, message, buffer);
} else if (qtype == RRType::IXFR()) {
makeErrorMessage(message, buffer, Rcode::NOTIMP(),
impl_->verbose_mode_);
} else {
sendAnswer = impl_->processNormalQuery(io_message, message, buffer);
}
}
server->resume(sendAnswer);
}
bool
AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
MessageRenderer& response_renderer)
AuthSrvImpl::processNormalQuery(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer)
{
ConstEDNSPtr remote_edns = message.getEDNS();
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;
message.makeResponse();
message.setHeaderFlag(Message::HEADERFLAG_AA);
message.setRcode(Rcode::NOERROR());
message->makeResponse();
message->setHeaderFlag(Message::HEADERFLAG_AA);
message->setRcode(Rcode::NOERROR());
if (remote_edns) {
EDNSPtr local_edns = EDNSPtr(new EDNS());
local_edns->setDNSSECAwareness(dnssec_ok);
local_edns->setUDPSize(AuthSrvImpl::DEFAULT_LOCAL_UDPSIZE);
message.setEDNS(local_edns);
message->setEDNS(local_edns);
}
try {
......@@ -340,7 +414,7 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
isc::auth::Query query(memory_datasrc_, qname, qtype, message);
query.process();
} else {
isc::datasrc::Query query(message, cache_, dnssec_ok);
isc::datasrc::Query query(*message, cache_, dnssec_ok);
data_sources_.doQuery(query);
}
} catch (const Exception& ex) {
......@@ -348,34 +422,35 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
cerr << "[b10-auth] Internal error, returning SERVFAIL: " <<
ex.what() << endl;
}
makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),
verbose_mode_);
makeErrorMessage(message, buffer, Rcode::SERVFAIL(), verbose_mode_);
return (true);
}
MessageRenderer renderer(*buffer);
const bool udp_buffer =