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

[master] Merge branch 'trac1784' with fixing conflicts.

parents 79af4f91 bd2da897
405.? [bug] jinmei
Make sure disabling Boost threads if the default configuration is
to disable it for the system. This fixes a crash and hang up
problem on OpenBSD, where the use of Boost thread could be
different in different program files depending on the order of
including various header files, and could introduce inconsistent
states between a library and a program. Explicitly forcing the
original default throughout the BIND 10 build environment will
prevent this from happening.
(Trac #1727, git TBD)
404. [bug] naokikambe
The statistic counters are now properly accumulated across multiple
instances of b10-auth (if there are multiple instances), instead of
......
......@@ -47,6 +47,8 @@
#include <dns/message.h>
#include <dns/tsig.h>
#include <asiodns/dns_service.h>
#include <datasrc/query.h>
#include <datasrc/data_source.h>
#include <datasrc/memory_datasrc.h>
......@@ -866,11 +868,14 @@ AuthSrv::getListenAddresses() const {
void
AuthSrv::setListenAddresses(const AddressList& addresses) {
installListenAddresses(addresses, impl_->listen_addresses_, *dnss_);
// For UDP servers we specify the "SYNC_OK" option because in our usage
// it can act in the synchronous mode.
installListenAddresses(addresses, impl_->listen_addresses_, *dnss_,
DNSService::SERVER_SYNC_OK);
}
void
AuthSrv::setDNSService(isc::asiodns::DNSService& dnss) {
AuthSrv::setDNSService(isc::asiodns::DNSServiceBase& dnss) {
dnss_ = &dnss;
}
......
......@@ -28,6 +28,7 @@
#include <util/buffer.h>
#include <asiodns/dns_server.h>
#include <asiodns/dns_service.h>
#include <asiodns/dns_lookup.h>
#include <asiodns/dns_answer.h>
#include <asiolink/io_message.h>
......@@ -384,7 +385,7 @@ public:
const;
/// \brief Assign an ASIO DNS Service queue to this Auth object
void setDNSService(isc::asiodns::DNSService& dnss);
void setDNSService(isc::asiodns::DNSServiceBase& dnss);
/// \brief Sets the keyring used for verifying and signing
///
......@@ -400,7 +401,7 @@ private:
isc::asiolink::SimpleCallback* checkin_;
isc::asiodns::DNSLookup* dns_lookup_;
isc::asiodns::DNSAnswer* dns_answer_;
isc::asiodns::DNSService* dnss_;
isc::asiodns::DNSServiceBase* dnss_;
};
#endif // __AUTH_SRV_H
......
......@@ -41,6 +41,7 @@
#include <dns/tests/unittest_util.h>
#include <testutils/dnsmessage_test.h>
#include <testutils/srv_test.h>
#include <testutils/mockups.h>
#include <testutils/portconfig.h>
#include <testutils/socket_request.h>
......@@ -75,7 +76,7 @@ const char* const CONFIG_INMEMORY_EXAMPLE =
class AuthSrvTest : public SrvTestBase {
protected:
AuthSrvTest() :
dnss_(ios_, NULL, NULL, NULL),
dnss_(),
server(true, xfrout),
rrclass(RRClass::IN()),
// The empty string is expected value of the parameter of
......@@ -135,8 +136,7 @@ protected:
opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
}
IOService ios_;
DNSService dnss_;
MockDNSService dnss_;
MockSession statistics_session;
MockXfroutClient xfrout;
AuthSrv server;
......@@ -1079,10 +1079,11 @@ TEST_F(AuthSrvTest, processNormalQuery_reuseRenderer1) {
UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
default_qid, Name("example.com"),
RRClass::IN(), RRType::NS());
request_message.setHeaderFlag(Message::HEADERFLAG_AA);
createRequestPacket(request_message, IPPROTO_UDP);
server.processMessage(*io_message, *parse_message, *response_obuffer, &dnsserv);
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
EXPECT_NE(request_message.getRcode(), parse_message->getRcode());
}
......@@ -1090,12 +1091,14 @@ TEST_F(AuthSrvTest, processNormalQuery_reuseRenderer2) {
UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
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);
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
ConstQuestionPtr question = *parse_message->beginQuestion();
EXPECT_STRNE(question->getType().toText().c_str(),RRType::NS().toText().c_str());
EXPECT_STRNE(question->getType().toText().c_str(),
RRType::NS().toText().c_str());
}
//
// Tests for catching exceptions in various stages of the query processing
......
......@@ -49,6 +49,7 @@ using namespace isc::dns;
using namespace isc::data;
using namespace isc::datasrc;
using namespace isc::config;
using namespace isc::testutils;
namespace {
class AuthCommandTest : public ::testing::Test {
......
......@@ -37,13 +37,13 @@ using namespace isc::dns;
using namespace isc::data;
using namespace isc::datasrc;
using namespace isc::asiodns;
using namespace isc::asiolink;
using namespace isc::testutils;
namespace {
class AuthConfigTest : public ::testing::Test {
protected:
AuthConfigTest() :
dnss_(ios_, NULL, NULL, NULL),
dnss_(),
rrclass(RRClass::IN()),
server(true, xfrout),
// The empty string is expected value of the parameter of
......@@ -53,8 +53,7 @@ protected:
{
server.setDNSService(dnss_);
}
IOService ios_;
DNSService dnss_;
MockDNSService dnss_;
const RRClass rrclass;
MockXfroutClient xfrout;
AuthSrv server;
......@@ -146,6 +145,14 @@ TEST_F(AuthConfigTest, invalidListenAddressConfig) {
// Try setting addresses trough config
TEST_F(AuthConfigTest, listenAddressConfig) {
isc::testutils::portconfig::listenAddressConfig(server);
// listenAddressConfig should have attempted to create 4 DNS server
// objects: two IP addresses, TCP and UDP for each. For UDP, the "SYNC_OK"
// option should have been specified.
EXPECT_EQ(2, dnss_.getTCPFdParams().size());
EXPECT_EQ(2, dnss_.getUDPFdParams().size());
EXPECT_EQ(DNSService::SERVER_SYNC_OK, dnss_.getUDPFdParams().at(0).options);
EXPECT_EQ(DNSService::SERVER_SYNC_OK, dnss_.getUDPFdParams().at(1).options);
}
class MemoryDatasrcConfigTest : public AuthConfigTest {
......
......@@ -92,7 +92,7 @@ public:
queryShutdown();
}
void querySetup(DNSService& dnss,
void querySetup(DNSServiceBase& dnss,
isc::nsas::NameserverAddressStore& nsas,
isc::cache::ResolverCache& cache)
{
......@@ -121,10 +121,10 @@ public:
}
void setForwardAddresses(const AddressList& upstream,
DNSService *dnss)
DNSServiceBase* dnss)
{
upstream_ = upstream;
if (dnss) {
if (dnss != NULL) {
if (!upstream_.empty()) {
BOOST_FOREACH(const AddressPair& address, upstream) {
LOG_INFO(resolver_logger, RESOLVER_FORWARD_ADDRESS)
......@@ -137,10 +137,10 @@ public:
}
void setRootAddresses(const AddressList& upstream_root,
DNSService *dnss)
DNSServiceBase* dnss)
{
upstream_root_ = upstream_root;
if (dnss) {
if (dnss != NULL) {
if (!upstream_root_.empty()) {
BOOST_FOREACH(const AddressPair& address, upstream_root) {
LOG_INFO(resolver_logger, RESOLVER_SET_ROOT_ADDRESS)
......@@ -377,7 +377,7 @@ Resolver::~Resolver() {
}
void
Resolver::setDNSService(isc::asiodns::DNSService& dnss) {
Resolver::setDNSService(isc::asiodns::DNSServiceBase& dnss) {
dnss_ = &dnss;
}
......
......@@ -104,7 +104,7 @@ public:
bool startup = false);
/// \brief Assign an ASIO IO Service queue to this Resolver object
void setDNSService(isc::asiodns::DNSService& dnss);
void setDNSService(isc::asiodns::DNSServiceBase& dnss);
/// \brief Assign a NameserverAddressStore to this Resolver object
void setNameserverAddressStore(isc::nsas::NameserverAddressStore &nsas);
......@@ -113,7 +113,7 @@ public:
void setCache(isc::cache::ResolverCache& cache);
/// \brief Return this object's ASIO IO Service queue
isc::asiodns::DNSService& getDNSService() const { return (*dnss_); }
isc::asiodns::DNSServiceBase& getDNSService() const { return (*dnss_); }
/// \brief Returns this object's NSAS
isc::nsas::NameserverAddressStore& getNameserverAddressStore() const {
......@@ -258,7 +258,7 @@ public:
private:
ResolverImpl* impl_;
isc::asiodns::DNSService* dnss_;
isc::asiodns::DNSServiceBase* dnss_;
isc::asiolink::SimpleCallback* checkin_;
isc::asiodns::DNSLookup* dns_lookup_;
isc::asiodns::DNSAnswer* dns_answer_;
......
......@@ -48,6 +48,7 @@
#include <dns/tests/unittest_util.h>
#include <testutils/srv_test.h>
#include <testutils/mockups.h>
#include <testutils/portconfig.h>
#include <testutils/socket_request.h>
......@@ -76,15 +77,13 @@ public:
class ResolverConfig : public ::testing::Test {
protected:
IOService ios;
DNSService dnss;
MockDNSService dnss;
Resolver server;
scoped_ptr<const IOEndpoint> endpoint;
scoped_ptr<const IOMessage> query_message;
scoped_ptr<const Client> client;
scoped_ptr<const RequestContext> request;
ResolverConfig() :
dnss(ios, NULL, NULL, NULL),
// The empty string is expected value of the parameter of
// requestSocket, not the app_name (there's no fallback, it checks
// the empty string is passed).
......@@ -320,6 +319,15 @@ TEST_F(ResolverConfig, invalidForwardAddresses) {
// Try setting the addresses directly
TEST_F(ResolverConfig, listenAddresses) {
isc::testutils::portconfig::listenAddresses(server);
// listenAddressConfig should have attempted to create 4 DNS server
// objects: two IP addresses, TCP and UDP for each. For UDP, the "SYNC_OK"
// option (or anything else) should have NOT been specified.
EXPECT_EQ(2, dnss.getTCPFdParams().size());
EXPECT_EQ(2, dnss.getUDPFdParams().size());
EXPECT_EQ(DNSService::SERVER_DEFAULT, dnss.getUDPFdParams().at(0).options);
EXPECT_EQ(DNSService::SERVER_DEFAULT, dnss.getUDPFdParams().at(1).options);
// Check it requests the correct addresses
const char* tokens[] = {
"TCP:127.0.0.1:53210:1",
......
......@@ -22,6 +22,8 @@
#include <log/dummylog.h>
#include <exceptions/exceptions.h>
#include <asio.hpp>
#include <dns_service.h>
#include <asiolink/io_service.h>
......@@ -63,11 +65,10 @@ convertAddr(const std::string& address) {
class DNSServiceImpl {
public:
DNSServiceImpl(IOService& io_service, const char& port,
const asio::ip::address* v4addr,
const asio::ip::address* v6addr,
SimpleCallback* checkin, DNSLookup* lookup,
DNSAnswer* answer,
const UDPVersion param_flags);
const asio::ip::address* v4addr,
const asio::ip::address* v6addr,
SimpleCallback* checkin, DNSLookup* lookup,
DNSAnswer* answe);
IOService& io_service_;
......@@ -87,38 +88,24 @@ public:
servers_.push_back(server);
}
void addServer(uint16_t port, const asio::ip::address& address,
const UDPVersion param_flags) {
void addServer(uint16_t port, const asio::ip::address& address) {
try {
dlog(std::string("Initialize TCP server at ") + address.to_string() + ":" + boost::lexical_cast<std::string>(port));
dlog(std::string("Initialize TCP server at ") +
address.to_string() + ":" +
boost::lexical_cast<std::string>(port));
TCPServerPtr tcpServer(new TCPServer(io_service_.get_io_service(),
address, port, checkin_, lookup_, answer_));
address, port, checkin_,
lookup_, answer_));
(*tcpServer)();
servers_.push_back(tcpServer);
dlog(std::string("Initialize UDP server at ") + address.to_string() + ":" + boost::lexical_cast<std::string>(port));
// Use param_flags to generate diff UDPServers.
switch(param_flags) {
case SYNC_: {
SyncUDPServerPtr syncUdpServer(new SyncUDPServer(io_service_.get_io_service(),
address, port, checkin_, lookup_, answer_));
(*syncUdpServer)();
servers_.push_back(syncUdpServer);
break;
}
case ASYNC_: {
UDPServerPtr udpServer(new UDPServer(io_service_.get_io_service(),
address, port, checkin_, lookup_, answer_));
(*udpServer)();
servers_.push_back(udpServer);
break;
}
default:
// If nerther asyn UDPServer nor sync UDNServer, it throws.
isc_throw(IOError, "Bad UDPServer Version!");
break;
}
}
catch (const asio::system_error& err) {
dlog(std::string("Initialize UDP server at ") +
address.to_string() + ":" +
boost::lexical_cast<std::string>(port));
UDPServerPtr udpServer(new UDPServer(io_service_.get_io_service(),
address, port, checkin_, lookup_, answer_));
(*udpServer)();
servers_.push_back(udpServer);
} catch (const asio::system_error& err) {
// We need to catch and convert any ASIO level exceptions.
// This can happen for unavailable address, binding a privilege port
// without the privilege, etc.
......@@ -126,8 +113,7 @@ public:
err.what());
}
}
void addServer(const char& port, const asio::ip::address& address,
const UDPVersion param_flags) {
void addServer(const char& port, const asio::ip::address& address) {
uint16_t portnum;
try {
// XXX: SunStudio with stlport4 doesn't reject some invalid
......@@ -143,7 +129,7 @@ public:
isc_throw(IOError, "Invalid port number '" << &port << "': " <<
ex.what());
}
addServer(portnum, address,param_flags);
addServer(portnum, address);
}
};
......@@ -153,8 +139,7 @@ DNSServiceImpl::DNSServiceImpl(IOService& io_service,
const asio::ip::address* const v6addr,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer,
const UDPVersion param_flags):
DNSAnswer* answer) :
io_service_(io_service),
checkin_(checkin),
lookup_(lookup),
......@@ -162,10 +147,10 @@ DNSServiceImpl::DNSServiceImpl(IOService& io_service,
{
if (v4addr) {
addServer(port, *v4addr,param_flags);
addServer(port, *v4addr);
}
if (v6addr) {
addServer(port, *v6addr,param_flags);
addServer(port, *v6addr);
}
}
......@@ -173,12 +158,12 @@ DNSService::DNSService(IOService& io_service,
const char& port, const char& address,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer,
const UDPVersion param_flags) :
DNSAnswer* answer) :
impl_(new DNSServiceImpl(io_service, port, NULL, NULL, checkin, lookup,
answer,param_flags)), io_service_(io_service)
answer)),
io_service_(io_service)
{
addServer(port, &address,param_flags);
addServer(port, &address);
}
DNSService::DNSService(IOService& io_service,
......@@ -186,8 +171,7 @@ DNSService::DNSService(IOService& io_service,
const bool use_ipv4, const bool use_ipv6,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer,
const UDPVersion param_flags) :
DNSAnswer* answer) :
impl_(NULL), io_service_(io_service)
{
const asio::ip::address v4addr_any =
......@@ -196,13 +180,14 @@ DNSService::DNSService(IOService& io_service,
const asio::ip::address v6addr_any =
asio::ip::address(asio::ip::address_v6::any());
const asio::ip::address* const v6addrp = use_ipv6 ? &v6addr_any : NULL;
impl_ = new DNSServiceImpl(io_service, port, v4addrp, v6addrp, checkin, lookup, answer,param_flags);
impl_ = new DNSServiceImpl(io_service, port, v4addrp, v6addrp, checkin,
lookup, answer);
}
DNSService::DNSService(IOService& io_service, SimpleCallback* checkin,
DNSLookup* lookup, DNSAnswer *answer,const UDPVersion param_flags) :
DNSLookup* lookup, DNSAnswer *answer) :
impl_(new DNSServiceImpl(io_service, *"0", NULL, NULL, checkin, lookup,
answer,param_flags)), io_service_(io_service)
answer)), io_service_(io_service)
{
}
......@@ -211,24 +196,30 @@ DNSService::~DNSService() {
}
void
DNSService::addServer(const char& port, const std::string& address,UDPVersion param_flags) {
impl_->addServer(port, convertAddr(address),param_flags);
DNSService::addServer(const char& port, const std::string& address) {
impl_->addServer(port, convertAddr(address));
}
void
DNSService::addServer(uint16_t port, const std::string& address,UDPVersion param_flags) {
impl_->addServer(port, convertAddr(address),param_flags);
DNSService::addServer(uint16_t port, const std::string& address) {
impl_->addServer(port, convertAddr(address));
}
void DNSService::addServerTCPFromFD(int fd, int af) {
impl_->addServerFromFD<DNSServiceImpl::TCPServerPtr, TCPServer>(fd, af);
}
void DNSService::addServerUDPFromFD(int fd, int af,const UDPVersion param_flags) {
if(SYNC_ == param_flags) {
impl_->addServerFromFD<DNSServiceImpl::SyncUDPServerPtr, SyncUDPServer>(fd, af);
} else if(ASYNC_ == param_flags) {
impl_->addServerFromFD<DNSServiceImpl::UDPServerPtr, UDPServer>(fd, af);
void DNSService::addServerUDPFromFD(int fd, int af, ServerFlag options) {
if ((~SERVER_DEFINED_FLAGS & static_cast<unsigned int>(options)) != 0) {
isc_throw(isc::InvalidParameter, "Invalid DNS/UDP server option: "
<< options);
}
if ((options & SERVER_SYNC_OK) != 0) {
impl_->addServerFromFD<DNSServiceImpl::SyncUDPServerPtr,
SyncUDPServer>(fd, af);
} else {
impl_->addServerFromFD<DNSServiceImpl::UDPServerPtr, UDPServer>(
fd, af);
}
}
......
......@@ -27,13 +27,64 @@ class DNSLookup;
class DNSAnswer;
class DNSServiceImpl;
/// Codes for UDPServers used in addServer()method.
/// \brief A base class for common \c DNSService interfaces.
///
/// This class is defined mainly for test code so it can use a faked/mock
/// version of a derived class and test scenarios that would involve
/// \c DNSService without actually instantiating the real service class.
///
/// Note: the codes only used in how to create the UDPServers.
enum UDPVersion {
SYNC_ = 1, ///< used synchronous UDPServer
ASYNC_ = 2 ///< used asynchronous UDPServer
/// It doesn't intend to be a customization for other purposes - we generally
/// expect non test code only use \c DNSService directly.
/// For this reason most of the detailed description are given in the
/// \c DNSService class. See that for further details of specific methods
/// and class behaviors.
class DNSServiceBase {
protected:
/// \brief Default constructor.
///
/// This is protected so this class couldn't be accidentally instantiated
/// directly, even if there were no pure virtual functions.
DNSServiceBase() {}
public:
/// \brief Flags for optional server properties.
///
/// The values of this enumerable type are intended to be used to specify
/// a particular property of the server created via the \c addServer
/// variants. As we see need for more such properties, a compound
/// form of flags (i.e., a single value generated by bitwise OR'ed
/// multiple flag values) will be allowed.
///
/// Note: the description is given here because it's used in the method
/// signature. It essentially belongs to the derived \c DNSService
/// class.
enum ServerFlag {
SERVER_DEFAULT = 0, ///< The default flag (no particular property)
SERVER_SYNC_OK = 1 ///< The server can act in the "synchronous" mode.
///< In this mode, the client ensures that the
///< lookup provider always completes the query
///< process and it immediately releases the
///< ownership of the given buffer. This allows
///< the server implementation to introduce some
///< optimization such as omitting unnecessary
///< operation or reusing internal resources.
///< Note that in functionality the non
///< "synchronous" mode is compatible with the
///< synchronous mode; it's up to the server
///< implementation whether it exploits the
///< information given by the client.
};
public:
/// \brief The destructor.
virtual ~DNSServiceBase() {}
virtual void addServerTCPFromFD(int fd, int af) = 0;
virtual void addServerUDPFromFD(int fd, int af,
ServerFlag options = SERVER_DEFAULT) = 0;
virtual void clearServers() = 0;
virtual asiolink::IOService& getIOService() = 0;
};
/// \brief Handle DNS Queries
......@@ -43,7 +94,7 @@ enum UDPVersion {
/// logic that is shared between the authoritative and the recursive
/// server implementations. As such, it handles asio, including config
/// updates (through the 'Checkinprovider'), and listening sockets.
class DNSService {
class DNSService : public DNSServiceBase {
///
/// \name Constructors and Destructor
///
......@@ -54,6 +105,12 @@ private:
DNSService(const DNSService& source);
DNSService& operator=(const DNSService& source);
private:
// Bit or'ed all defined \c ServerFlag values. Used internally for
// compatibility check. Note that this doesn't have to be used by
// applications, and doesn't have to be defined in the "base" class.
static const unsigned int SERVER_DEFINED_FLAGS = 1;
public:
/// \brief The constructor with a specific IP address and port on which
/// the services listen on.
......@@ -66,8 +123,8 @@ public:
/// \param answer The answer provider (see \c DNSAnswer)
DNSService(asiolink::IOService& io_service, const char& port,
const char& address, isc::asiolink::SimpleCallback* checkin,
DNSLookup* lookup, DNSAnswer* answer,
const UDPVersion param_flags = SYNC_);
DNSLookup* lookup, DNSAnswer* answer);
/// \brief The constructor with a specific port on which the services
/// listen on.
///
......@@ -85,23 +142,21 @@ public:
DNSService(asiolink::IOService& io_service, const char& port,
const bool use_ipv4, const bool use_ipv6,
isc::asiolink::SimpleCallback* checkin, DNSLookup* lookup,
DNSAnswer* answer,
const UDPVersion param_flags = SYNC_);
DNSAnswer* answer);
/// \brief The constructor without any servers.
///
/// Use addServer() to add some servers.
DNSService(asiolink::IOService& io_service, isc::asiolink::SimpleCallback* checkin,
DNSLookup* lookup, DNSAnswer* answer,
const UDPVersion param_flags = SYNC_);
DNSService(asiolink::IOService& io_service,
isc::asiolink::SimpleCallback* checkin,
DNSLookup* lookup, DNSAnswer* answer);
/// \brief The destructor.
~DNSService();
virtual ~DNSService();
//@}