Commit bf4ed539 authored by Michal Vaner's avatar Michal Vaner
Browse files

Merge #393

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac327@3602 e5f2f494-b856-4b98-b285-d166d9295462
parents fc971f48 24cf0a09
TBD. [func] vorner
New temporary logging function available in isc::log. It is used by
b10-recurse.
(Trac #393, r3602)
TBD. [func] vorner
The b10-recursive is configured through config manager.
It has "listen_on" and "forward_addresses" options.
......
......@@ -519,6 +519,7 @@ 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
])
......
......@@ -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/asiolink/
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/
# 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
......
......@@ -22,7 +22,7 @@
#include <stdlib.h>
#include <errno.h>
#include <cassert>
#include <string>
#include <iostream>
#include <boost/foreach.hpp>
......@@ -47,18 +47,17 @@
#include <recurse/spec_config.h>
#include <recurse/recursor.h>
#include <log/dummylog.h>
using namespace std;
using namespace isc::data;
using namespace isc::cc;
using namespace isc::config;
using namespace isc::dns;
using namespace isc::xfr;
using namespace isc::data;
using isc::log::dlog;
using namespace asiolink;
namespace {
static bool verbose_mode = false;
// Default port current 5300 for testing purposes
static const string PROGRAM = "Recurse";
......@@ -96,6 +95,7 @@ usage() {
int
main(int argc, char* argv[]) {
isc::log::dprefix = "b10-recurse";
int ch;
const char* uid = NULL;
......@@ -105,7 +105,7 @@ main(int argc, char* argv[]) {
uid = optarg;
break;
case 'v':
verbose_mode = true;
isc::log::denabled = true;
break;
case '?':
default:
......@@ -117,6 +117,14 @@ main(int argc, char* argv[]) {
usage();
}
if (isc::log::denabled) { // Show the command line
string cmdline("Command line:");
for (int i = 0; i < argc; ++ i) {
cmdline = cmdline + " " + argv[i];
}
dlog(cmdline);
}
int ret = 0;
Session* cc_session = NULL;
......@@ -131,8 +139,7 @@ main(int argc, char* argv[]) {
}
recursor = new Recursor();
recursor->setVerbose(verbose_mode);
cout << "[b10-recurse] Server created." << endl;
dlog("Server created.");
SimpleCallback* checkin = recursor->getCheckinProvider();
DNSLookup* lookup = recursor->getDNSLookupProvider();
......@@ -141,15 +148,15 @@ main(int argc, char* argv[]) {
DNSService dns_service(io_service, checkin, lookup, answer);
recursor->setDNSService(dns_service);
cout << "[b10-recurse] IOService created." << endl;
dlog("IOService created.");
cc_session = new Session(io_service.get_io_service());
cout << "[b10-recurse] Configuration session channel created." << endl;
dlog("Configuration session channel created.");
config_session = new ModuleCCSession(specfile, *cc_session,
my_config_handler,
my_command_handler);
cout << "[b10-recurse] Configuration channel established." << endl;
dlog("Configuration channel established.");
// FIXME: This does not belong here, but inside Boss
if (uid != NULL) {
......@@ -158,11 +165,12 @@ main(int argc, char* argv[]) {
recursor->setConfigSession(config_session);
recursor->updateConfig(config_session->getFullConfig());
dlog("Config loaded");
cout << "[b10-recurse] Server started." << endl;
dlog("Server started.");
io_service.run();
} catch (const std::exception& ex) {
cerr << "[b10-recurse] Server failed: " << ex.what() << endl;
dlog(string("Server failed: ") + ex.what());
ret = 1;
}
......
......@@ -19,19 +19,16 @@
#include <netinet/in.h>
#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>
#include <asiolink/asiolink.h>
#include <asiolink/ioaddress.h>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <config/ccsession.h>
#include <cc/data.h>
#include <exceptions/exceptions.h>
#include <dns/opcode.h>
......@@ -45,19 +42,17 @@
#include <dns/message.h>
#include <dns/messagerenderer.h>
#include <xfr/xfrout_client.h>
#include <log/dummylog.h>
#include <recurse/recursor.h>
using namespace std;
using namespace isc;
using namespace isc::cc;
using namespace isc::dns;
using namespace isc::dns::rdata;
using namespace isc::data;
using namespace isc::config;
using namespace isc::xfr;
using isc::log::dlog;
using namespace asiolink;
typedef pair<string, uint16_t> addr_t;
......@@ -70,7 +65,6 @@ private:
public:
RecursorImpl() :
config_session_(NULL),
verbose_mode_(false),
rec_query_()
{}
......@@ -79,10 +73,12 @@ public:
}
void querySetup(DNSService& dnss) {
dlog("Query setup");
rec_query_ = new RecursiveQuery(dnss, upstream_);
}
void queryShutdown() {
dlog("Query shutdown");
delete rec_query_;
rec_query_ = NULL;
}
......@@ -94,9 +90,14 @@ public:
upstream_ = upstream;
if (dnss) {
if (upstream_.empty()) {
cerr << "[b10-recurse] Asked to do full recursive," << endl <<
"but not implemented yet. I'll do nothing." << endl;
dlog("Asked to do full recursive, but not implemented yet. "
"I'll do nothing.");
} else {
dlog("Setting forward addresses:");
BOOST_FOREACH(const addr_t& address, upstream) {
dlog(" " + address.first + ":" +
boost::lexical_cast<string>(address.second));
}
querySetup(*dnss);
}
}
......@@ -111,7 +112,6 @@ public:
/// These members are public because Recursor accesses them directly.
ModuleCCSession* config_session_;
bool verbose_mode_;
/// Addresses of the forward nameserver
vector<addr_t> upstream_;
/// Addresses we listen on
......@@ -127,6 +127,8 @@ class QuestionInserter {
public:
QuestionInserter(MessagePtr message) : message_(message) {}
void operator()(const QuestionPtr question) {
dlog(string("Adding question ") + question->getName().toText() +
" to message");
message_->addQuestion(question);
}
MessagePtr message_;
......@@ -139,6 +141,8 @@ public:
message_(message), section_(sect), sign_(sign)
{}
void operator()(const RRsetPtr rrset) {
dlog("Adding RRSet to message section " +
boost::lexical_cast<string>(section_));
message_->addRRset(section_, rrset, true);
}
MessagePtr message_;
......@@ -148,7 +152,7 @@ public:
void
makeErrorMessage(MessagePtr message, OutputBufferPtr buffer,
const Rcode& rcode, const bool verbose_mode)
const Rcode& rcode)
{
// extract the parameters that should be kept.
// XXX: with the current implementation, it's not easy to set EDNS0
......@@ -180,10 +184,9 @@ makeErrorMessage(MessagePtr message, OutputBufferPtr buffer,
MessageRenderer renderer(*buffer);
message->toWire(renderer);
if (verbose_mode) {
cerr << "[b10-recurse] sending an error response (" <<
renderer.getLength() << " bytes):\n" << message->toText() << endl;
}
dlog(string("Sending an error response (") +
boost::lexical_cast<string>(renderer.getLength()) + " bytes):\n" +
message->toText());
}
// This is a derived class of \c DNSLookup, to serve as a
......@@ -281,11 +284,9 @@ public:
message->toWire(renderer);
if (server_->getVerbose()) {
cerr << "[b10-recurse] sending a response ("
<< renderer.getLength() << " bytes):\n"
<< message->toText() << endl;
}
dlog(string("sending a response (") +
boost::lexical_cast<string>(renderer.getLength()) + "bytes): \n" +
message->toText());
}
private:
......@@ -319,6 +320,7 @@ Recursor::~Recursor() {
delete checkin_;
delete dns_lookup_;
delete dns_answer_;
dlog("Deleting the Recursor");
}
void
......@@ -328,16 +330,6 @@ Recursor::setDNSService(asiolink::DNSService& dnss) {
dnss_ = &dnss;
}
void
Recursor::setVerbose(const bool on) {
impl_->verbose_mode_ = on;
}
bool
Recursor::getVerbose() const {
return (impl_->verbose_mode_);
}
void
Recursor::setConfigSession(ModuleCCSession* config_session) {
impl_->config_session_ = config_session;
......@@ -352,6 +344,7 @@ void
Recursor::processMessage(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer, DNSServer* server)
{
dlog("Got a DNS message");
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.
......@@ -360,17 +353,12 @@ Recursor::processMessage(const IOMessage& io_message, MessagePtr message,
// Ignore all responses.
if (message->getHeaderFlag(Message::HEADERFLAG_QR)) {
if (impl_->verbose_mode_) {
cerr << "[b10-recurse] received unexpected response, ignoring"
<< endl;
}
dlog("Received unexpected response, ignoring");
server->resume(false);
return;
}
} catch (const Exception& ex) {
if (impl_->verbose_mode_) {
cerr << "[b10-recurse] DNS packet exception: " << ex.what() << endl;
}
dlog(string("DNS packet exception: ") + ex.what());
server->resume(false);
return;
}
......@@ -379,57 +367,45 @@ Recursor::processMessage(const IOMessage& io_message, MessagePtr message,
try {
message->fromWire(request_buffer);
} catch (const DNSProtocolError& error) {
if (impl_->verbose_mode_) {
cerr << "[b10-recurse] returning " << error.getRcode().toText()
<< ": " << error.what() << endl;
}
makeErrorMessage(message, buffer, error.getRcode(),
impl_->verbose_mode_);
dlog(string("returning ") + error.getRcode().toText() + ": " +
error.what());
makeErrorMessage(message, buffer, error.getRcode());
server->resume(true);
return;
} catch (const Exception& ex) {
if (impl_->verbose_mode_) {
cerr << "[b10-recurse] returning SERVFAIL: " << ex.what() << endl;
}
makeErrorMessage(message, buffer, Rcode::SERVFAIL(),
impl_->verbose_mode_);
dlog(string("returning SERVFAIL: ") + ex.what());
makeErrorMessage(message, buffer, Rcode::SERVFAIL());
server->resume(true);
return;
} // other exceptions will be handled at a higher layer.
if (impl_->verbose_mode_) {
cerr << "[b10-recurse] received a message:\n"
<< message->toText() << endl;
}
dlog("received a message:\n" + message->toText());
// Perform further protocol-level validation.
bool sendAnswer = true;
if (message->getOpcode() == Opcode::NOTIFY()) {
makeErrorMessage(message, buffer, Rcode::NOTAUTH(),
impl_->verbose_mode_);
makeErrorMessage(message, buffer, Rcode::NOTAUTH());
dlog("Notify arrived, but we are not authoritative");
} else if (message->getOpcode() != Opcode::QUERY()) {
if (impl_->verbose_mode_) {
cerr << "[b10-recurse] unsupported opcode" << endl;
}
makeErrorMessage(message, buffer, Rcode::NOTIMP(),
impl_->verbose_mode_);
dlog("Unsupported opcode (got: " + message->getOpcode().toText() +
", expected: " + Opcode::QUERY().toText());
makeErrorMessage(message, buffer, Rcode::NOTIMP());
} else if (message->getRRCount(Message::SECTION_QUESTION) != 1) {
makeErrorMessage(message, buffer, Rcode::FORMERR(),
impl_->verbose_mode_);
dlog("The query contained " +
boost::lexical_cast<string>(message->getRRCount(
Message::SECTION_QUESTION) + " questions, exactly one expected"));
makeErrorMessage(message, buffer, Rcode::FORMERR());
} else {
ConstQuestionPtr question = *message->beginQuestion();
const RRType &qtype = question->getType();
if (qtype == RRType::AXFR()) {
if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
makeErrorMessage(message, buffer, Rcode::FORMERR(),
impl_->verbose_mode_);
makeErrorMessage(message, buffer, Rcode::FORMERR());
} else {
makeErrorMessage(message, buffer, Rcode::NOTIMP(),
impl_->verbose_mode_);
makeErrorMessage(message, buffer, Rcode::NOTIMP());
}
} else if (qtype == RRType::IXFR()) {
makeErrorMessage(message, buffer, Rcode::NOTIMP(),
impl_->verbose_mode_);
makeErrorMessage(message, buffer, Rcode::NOTIMP());
} else {
// The RecursiveQuery object will post the "resume" event to the
// DNSServer when an answer arrives, so we don't have to do it now.
......@@ -447,6 +423,7 @@ void
RecursorImpl::processNormalQuery(const Question& question, MessagePtr message,
OutputBufferPtr buffer, DNSServer* server)
{
dlog("Processing normal query");
ConstEDNSPtr edns(message->getEDNS());
const bool dnssec_ok = edns && edns->getDNSSECAwareness();
......@@ -504,9 +481,8 @@ parseAddresses(ConstElementPtr addresses) {
ConstElementPtr
Recursor::updateConfig(ConstElementPtr config) {
if (impl_->verbose_mode_) {
cout << "[b10-recurse] Update with config: " << config->str() << endl;
}
dlog("New config comes: " + config->toWire());
try {
// Parse forward_addresses
ConstElementPtr forwardAddressesE(config->get("forward_addresses"));
......@@ -523,9 +499,7 @@ Recursor::updateConfig(ConstElementPtr config) {
}
return (isc::config::createAnswer());
} catch (const isc::Exception& error) {
if (impl_->verbose_mode_) {
cerr << "[b10-recurse] error: " << error.what() << endl;
}
dlog(string("error in config: ") + error.what());
return (isc::config::createAnswer(1, error.what()));
}
}
......@@ -561,6 +535,10 @@ setAddresses(DNSService *service, const vector<addr_t>& addresses) {
void
Recursor::setListenAddresses(const vector<addr_t>& addresses) {
try {
dlog("Setting listen addresses:");
BOOST_FOREACH(const addr_t& addr, addresses) {
dlog(" " + addr.first + boost::lexical_cast<string>(addr.second));
}
setAddresses(dnss_, addresses);
impl_->listen_ = addresses;
}
......@@ -576,8 +554,8 @@ Recursor::setListenAddresses(const vector<addr_t>& addresses) {
setAddresses(dnss_, impl_->listen_);
}
catch (const exception& e2) {
cerr << "[b10-recurse] Unable to recover from error: " << e.what()
<< endl << "Rollback failed with: " << e2.what() << endl;
dlog(string("Unable to recover from error: ") + e.what() +
" Rollback failed with: " + e2.what());
abort();
}
throw e; // Let it fly a little bit further
......
......@@ -60,14 +60,6 @@ public:
isc::dns::OutputBufferPtr buffer,
asiolink::DNSServer* server);
/// \brief Set verbose flag
///
/// \param on The new value of the verbose flag
void setVerbose(bool on);
/// \brief Get the current value of the verbose flag
bool getVerbose() const;
/// \brief Set and get the config session
isc::config::ModuleCCSession* getConfigSession() const;
void setConfigSession(isc::config::ModuleCCSession* config_session);
......
......@@ -39,11 +39,6 @@ TEST_F(RecursorTest, unsupportedRequest) {
UNSUPPORTED_REQUEST_TEST;
}
// Simple API check
TEST_F(RecursorTest, verbose) {
VERBOSE_TEST;
}
// Multiple questions. Should result in FORMERR.
TEST_F(RecursorTest, multiQuestion) {
MULTI_QUESTION_TEST;
......
SUBDIRS = exceptions dns asiolink cc config datasrc python xfr bench testutils
SUBDIRS = exceptions dns cc config datasrc python xfr bench log asiolink \
testutils
......@@ -31,3 +31,4 @@ if USE_CLANGPP
libasiolink_la_CXXFLAGS += -Wno-error
endif
libasiolink_la_CPPFLAGS = $(AM_CPPFLAGS)
libasiolink_la_LIBADD = $(top_builddir)/src/lib/log/liblog.la
......@@ -36,12 +36,15 @@
#include <asiolink/internal/tcpdns.h>
#include <asiolink/internal/udpdns.h>
#include <log/dummylog.h>
using namespace asio;
using asio::ip::udp;
using asio::ip::tcp;
using namespace std;
using namespace isc::dns;
using isc::log::dlog;
namespace asiolink {
......@@ -273,14 +276,15 @@ void
RecursiveQuery::sendQuery(const Question& question, OutputBufferPtr buffer,
DNSServer* server)
{
int serverIndex(random() % upstream_.size());
dlog("Sending upstream query (" + question.toText() + ") to " +
upstream_[serverIndex].first);
// XXX: eventually we will need to be able to determine whether
// the message should be sent via TCP or UDP, or sent initially via
// UDP and then fall back to TCP on failure, but for the moment
// we're only going to handle UDP.
asio::io_service& io = dns_service_.get_io_service();
// TODO: Better way to choose the server
int serverIndex(random() % upstream_.size());
UDPQuery q(io, question, upstream_[serverIndex].first,
upstream_[serverIndex].second, buffer, server);
io.post(q);
......
......@@ -25,6 +25,7 @@ run_unittests_LDADD += $(SQLITE_LIBS)
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
# B10_CXXFLAGS)
run_unittests_CXXFLAGS = $(AM_CXXFLAGS)
......
......@@ -29,6 +29,7 @@
#include <dns/buffer.h>
#include <dns/message.h>
#include <dns/messagerenderer.h>
#include <log/dummylog.h>
#include <dns/opcode.h>
#include <dns/rcode.h>
......@@ -39,6 +40,7 @@
using namespace asio;
using asio::ip::udp;
using asio::ip::tcp;
using isc::log::dlog;
using namespace std;
using namespace isc::dns;
......@@ -208,6 +210,8 @@ UDPQuery::operator()(error_code ec, size_t length) {
msg.addQuestion(question_);
MessageRenderer renderer(*msgbuf_);
msg.toWire(renderer);
dlog("Sending " + msg.toText() + " to " +
remote_.address().to_string());
}
// Begin an asynchronous send, and then yield. When the
......@@ -224,6 +228,8 @@ UDPQuery::operator()(error_code ec, size_t length) {
/// completes, we will resume immediately after this point.
CORO_YIELD socket_->async_receive_from(buffer(data_.get(), MAX_LENGTH),
remote_, *this);
// The message is not rendered yet, so we can't print it easilly
dlog("Received response from " + remote_.address().to_string());
/// Copy the answer into the response buffer. (XXX: If the
/// OutputBuffer object were made to meet the requirements of
......
AM_CXXFLAGS = $(B10_CXXFLAGS)
lib_LTLIBRARIES = liblog.la
liblog_la_SOURCES = dummylog.cc dummylog.h
// Copyright (C) 2010 CZ NIC
//
// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC 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.
#include "dummylog.h"
#include <iostream>
using namespace std;
namespace isc {
namespace log {
bool denabled = false;
string dprefix;
void dlog(const string& message) {
if (denabled) {
if (!dprefix.empty()) {
cerr << "[" << dprefix << "] ";
}
cerr << message << endl;
}
}
}
}
// Copyright (C) 2010 CZ NIC
//
// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC 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.