[svn] commit: r2109 - in /branches/feng-authnotify/src/bin/auth: Makefile.am asio_link.cc asio_link.h auth_srv.cc auth_srv.h auth_util.cc auth_util.h main.cc tests/Makefile.am tests/auth_srv_unittest.cc
BIND 10 source code commits
bind10-changes at lists.isc.org
Sun Jun 13 05:59:14 UTC 2010
Author: hanfeng
Date: Sun Jun 13 05:59:13 2010
New Revision: 2109
Log:
refactoring auth server code
Added:
branches/feng-authnotify/src/bin/auth/asio_link.cc
- copied, changed from r2034, trunk/src/bin/auth/asio_link.cc
branches/feng-authnotify/src/bin/auth/asio_link.h
- copied, changed from r2034, trunk/src/bin/auth/asio_link.h
branches/feng-authnotify/src/bin/auth/auth_util.cc
branches/feng-authnotify/src/bin/auth/auth_util.h
Modified:
branches/feng-authnotify/src/bin/auth/Makefile.am
branches/feng-authnotify/src/bin/auth/auth_srv.cc
branches/feng-authnotify/src/bin/auth/auth_srv.h
branches/feng-authnotify/src/bin/auth/main.cc
branches/feng-authnotify/src/bin/auth/tests/Makefile.am
branches/feng-authnotify/src/bin/auth/tests/auth_srv_unittest.cc
Modified: branches/feng-authnotify/src/bin/auth/Makefile.am
==============================================================================
--- branches/feng-authnotify/src/bin/auth/Makefile.am (original)
+++ branches/feng-authnotify/src/bin/auth/Makefile.am Sun Jun 13 05:59:13 2010
@@ -1,10 +1,9 @@
SUBDIRS = . tests
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
-if GCC_WERROR_OK
-AM_CPPFLAGS += -Werror
-endif
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns -lsqlit3
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
pkglibexecdir = $(libexecdir)/@PACKAGE@
@@ -26,9 +25,22 @@
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) -Wno-unused-parameter
+libasio_link_a_CPPFLAGS = $(AM_CPPFLAGS)
+
BUILT_SOURCES = spec_config.h
pkglibexec_PROGRAMS = b10-auth
-b10_auth_SOURCES = auth_srv.cc auth_srv.h
+b10_auth_SOURCES = auth_srv.cc auth_srv.h auth_util.cc auth_util.h
b10_auth_SOURCES += common.h
b10_auth_SOURCES += main.cc
b10_auth_LDADD = $(top_builddir)/src/lib/datasrc/.libs/libdatasrc.a
@@ -36,13 +48,10 @@
b10_auth_LDADD += $(top_builddir)/src/lib/config/.libs/libcfgclient.a
b10_auth_LDADD += $(top_builddir)/src/lib/cc/libcc.a
b10_auth_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
+b10_auth_LDADD += $(top_builddir)/src/bin/auth/libasio_link.a
b10_auth_LDADD += $(SQLITE_LIBS)
-if HAVE_BOOST_SYSTEM
if HAVE_BOOST_PYTHON
b10_auth_LDADD += $(top_builddir)/src/lib/xfr/.libs/libxfr.a
-endif
-b10_auth_LDFLAGS = $(AM_LDFLAGS) $(BOOST_LDFLAGS)
-b10_auth_LDADD += $(BOOST_SYSTEM_LIB)
endif
# TODO: config.h.in is wrong because doesn't honor pkgdatadir
Modified: branches/feng-authnotify/src/bin/auth/auth_srv.cc
==============================================================================
--- branches/feng-authnotify/src/bin/auth/auth_srv.cc (original)
+++ branches/feng-authnotify/src/bin/auth/auth_srv.cc Sun Jun 13 05:59:13 2010
@@ -18,6 +18,7 @@
#include <cassert>
#include <iostream>
#include <vector>
+#include <boost/utility.hpp>
#include <exceptions/exceptions.h>
@@ -32,6 +33,7 @@
#include <config/ccsession.h>
#include <cc/data.h>
#include <exceptions/exceptions.h>
+#include <xfr/xfrout_client.h>
#include <datasrc/query.h>
#include <datasrc/data_source.h>
@@ -42,6 +44,9 @@
#include "common.h"
#include "auth_srv.h"
+#include "asio_link.h"
+#include "auth_util.h"
+#include "spec_config.h"
#include <boost/lexical_cast.hpp>
@@ -53,16 +58,28 @@
using namespace isc::dns::rdata;
using namespace isc::data;
using namespace isc::config;
-
-class AuthSrvImpl {
+using namespace isc::xfr;
+
+class AuthSrvImpl : private boost::noncopyable{
+public:
+ enum {DEFAULT_LOCAL_UDPSIZE = 4096};
+ AuthSrvImpl();
+
+ isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
+ void setVerbose(bool on) { verbose_mode_ = on;}
+ bool getVerbose()const { return verbose_mode_;}
+ void setConfigSession(ModuleCCSession *cs) { cs_ = cs;}
+ ModuleCCSession *getConfigSession() { return cs_;}
+ void nag(const string &info){
+ if (verbose_mode_)
+ cerr << info;
+ }
+ void processQuery(asio_link::UserInfo &userInfo);
+
private:
- // prohibit copy
- AuthSrvImpl(const AuthSrvImpl& source);
- AuthSrvImpl& operator=(const AuthSrvImpl& source);
-public:
- AuthSrvImpl();
-
- isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
+ void processNormalQuery(asio_link::UserInfo &userInfo);
+ void processAxfrQuery(asio_link::UserInfo &uerInfo);
+ void processIxfrQuery(asio_link::UserInfo &userInfo, const std::string &queryZoneName);
std::string db_file_;
ModuleCCSession* cs_;
@@ -71,11 +88,7 @@
/// so that we can specifically remove that one should the database
/// file change
ConstDataSrcPtr cur_datasrc_;
-
bool verbose_mode_;
-
- /// Currently non-configurable, but will be.
- static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
};
AuthSrvImpl::AuthSrvImpl() : cs_(NULL), verbose_mode_(false)
@@ -83,183 +96,107 @@
// cur_datasrc_ is automatically initialized by the default constructor,
// effectively being an empty (sqlite) data source. once ccsession is up
// the datasource will be set by the configuration setting
-
// add static data source
data_sources_.addDataSrc(ConstDataSrcPtr(new StaticDataSrc));
}
-AuthSrv::AuthSrv() : impl_(new AuthSrvImpl) {
-}
-
-AuthSrv::~AuthSrv() {
- delete impl_;
-}
-
-namespace {
-class QuestionInserter {
-public:
- QuestionInserter(Message* message) : message_(message) {}
- void operator()(const QuestionPtr question) {
- message_->addQuestion(question);
- }
- Message* message_;
-};
-
-void
-makeErrorMessage(Message& message, MessageRenderer& renderer,
- 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(MessageFlag::RD());
- const bool cd = message.getHeaderFlag(MessageFlag::CD());
- const Opcode& opcode = message.getOpcode();
- vector<QuestionPtr> questions;
-
- // If this is an error to a query, we should also copy the question section.
- if (opcode == Opcode::QUERY()) {
- questions.assign(message.beginQuestion(), message.endQuestion());
- }
-
- message.clear(Message::RENDER);
- message.setQid(qid);
- message.setOpcode(opcode);
- message.setHeaderFlag(MessageFlag::QR());
- message.setUDPSize(AuthSrvImpl::DEFAULT_LOCAL_UDPSIZE);
- if (rd) {
- message.setHeaderFlag(MessageFlag::RD());
- }
- if (cd) {
- message.setHeaderFlag(MessageFlag::CD());
- }
- for_each(questions.begin(), questions.end(), QuestionInserter(&message));
- message.setRcode(rcode);
- message.toWire(renderer);
-
- if (verbose_mode) {
- cerr << "sending an error response (" <<
- boost::lexical_cast<string>(renderer.getLength())
- << " bytes):\n" << message.toText() << endl;
- }
-}
-}
-
-void
-AuthSrv::setVerbose(const bool on) {
- impl_->verbose_mode_ = on;
-}
-
-bool
-AuthSrv::getVerbose() const {
- return (impl_->verbose_mode_);
-}
-
-void
-AuthSrv::setConfigSession(ModuleCCSession* cs) {
- impl_->cs_ = cs;
-}
-
-ModuleCCSession*
-AuthSrv::configSession() const {
- return (impl_->cs_);
-}
-
-bool
-AuthSrv::processMessage(InputBuffer& request_buffer, Message& message,
- MessageRenderer& response_renderer,
- const bool udp_buffer)
-{
- // First, check the header part. If we fail even for the base header,
- // just drop the message.
+
+void
+AuthSrvImpl::processQuery(asio_link::UserInfo &userInfo)
+{
+ assert(userInfo.isMessageValid());
+ Message &message = userInfo.getMessage();
+ nag("[AuthSrv] received a message :\n" + message.toText() + "\n");
+ const Opcode &opcode = message.getOpcode();
+ if (opcode == Opcode::QUERY()){
+ QuestionPtr question = *message.beginQuestion();
+ const RRType &qtype = question->getType();
+ if (qtype == RRType::AXFR())
+ processAxfrQuery(userInfo);
+ else if (qtype == RRType::IXFR())
+ processIxfrQuery(userInfo, question->getName().toText());
+ else
+ processNormalQuery(userInfo);
+ }else{
+ nag("unsupported opcode\n");
+ auth_util::makeErrorMessage(message, Rcode::NOTIMP());
+ }
+}
+
+
+
+void
+AuthSrvImpl::processNormalQuery(asio_link::UserInfo &userInfo)
+{
+ Message &message = userInfo.getMessage();
+ if (message.getRRCount(Section::QUESTION()) != 1) {
+ auth_util::makeErrorMessage(message, Rcode::FORMERR());
+ }
+ else{
+ const bool dnssec_ok = message.isDNSSECSupported();
+ //const uint16_t remote_bufsize = message.getUDPSize();
+
+ message.makeResponse();
+ message.setHeaderFlag(MessageFlag::AA());
+ message.setRcode(Rcode::NOERROR());
+ message.setDNSSECSupported(dnssec_ok);
+ message.setUDPSize(AuthSrvImpl::DEFAULT_LOCAL_UDPSIZE);
+
+ try {
+ Query query(message, dnssec_ok);
+ data_sources_.doQuery(query);
+ } catch (const Exception& ex) {
+ nag(std::string("Internal error, returning SERVFAIL: ") + ex.what() + "\n");
+ auth_util::makeErrorMessage(message, Rcode::SERVFAIL());
+ }
+ //response_renderer.setLengthLimit(userInfo.getProtocolType() == asio_link::UserInfo::QueryThroughUDP ? remote_bufsize : 65535);
+ }
+
+ //message.toWire(response_renderer);
+ //nag(std::string("sending a response (") + boost::lexical_cast<string>(response_renderer.getLength())
+ // + " bytes):\n" + message.toText() + "\n");
+}
+
+void
+AuthSrvImpl::processAxfrQuery(asio_link::UserInfo &userInfo)
+{
+ string path(UNIX_SOCKET_FILE);
+ XfroutClient xfr_client(path);
try {
- message.parseHeader(request_buffer);
-
- // Ignore all responses.
- if (message.getHeaderFlag(MessageFlag::QR())) {
- if (impl_->verbose_mode_) {
- cerr << "received unexpected response, ignoring" << endl;
- }
- return (false);
- }
- } catch (const Exception& ex) {
- return (false);
- }
-
- // Parse the message. On failure, return an appropriate error.
- try {
- message.fromWire(request_buffer);
- } catch (const DNSProtocolError& error) {
- if (impl_->verbose_mode_) {
- cerr << "returning " << error.getRcode().toText() << ": "
- << error.what() << endl;
- }
- makeErrorMessage(message, response_renderer, error.getRcode(),
- impl_->verbose_mode_);
- return (true);
- } catch (const Exception& ex) {
- if (impl_->verbose_mode_) {
- cerr << "returning SERVFAIL: " << ex.what() << endl;
- }
- makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),
- impl_->verbose_mode_);
- return (true);
- } // other exceptions will be handled at a higher layer.
-
- if (impl_->verbose_mode_) {
- cerr << "[AuthSrv] received a message:\n" << message.toText() << endl;
- }
-
- // Perform further protocol-level validation.
-
- // In this implementation, we only support normal queries
- if (message.getOpcode() != Opcode::QUERY()) {
- if (impl_->verbose_mode_) {
- cerr << "unsupported opcode" << endl;
- }
- makeErrorMessage(message, response_renderer, Rcode::NOTIMP(),
- impl_->verbose_mode_);
- return (true);
- }
-
- if (message.getRRCount(Section::QUESTION()) != 1) {
- makeErrorMessage(message, response_renderer, Rcode::FORMERR(),
- impl_->verbose_mode_);
- return (true);
- }
-
- const bool dnssec_ok = message.isDNSSECSupported();
- const uint16_t remote_bufsize = message.getUDPSize();
-
- message.makeResponse();
- message.setHeaderFlag(MessageFlag::AA());
- message.setRcode(Rcode::NOERROR());
- message.setDNSSECSupported(dnssec_ok);
- message.setUDPSize(AuthSrvImpl::DEFAULT_LOCAL_UDPSIZE);
-
- try {
- Query query(message, dnssec_ok);
- impl_->data_sources_.doQuery(query);
- } catch (const Exception& ex) {
- if (impl_->verbose_mode_) {
- cerr << "Internal error, returning SERVFAIL: " << ex.what() << endl;
- }
- makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),
- impl_->verbose_mode_);
- return (true);
- }
-
- response_renderer.setLengthLimit(udp_buffer ? remote_bufsize : 65535);
- message.toWire(response_renderer);
- if (impl_->verbose_mode_) {
- cerr << "sending a response (" <<
- boost::lexical_cast<string>(response_renderer.getLength())
- << " bytes):\n" << message.toText() << endl;
- }
-
- return (true);
-}
+ xfr_client.connect();
+ OutputBuffer rawData(0);
+ auth_util::messageToWire(userInfo.getMessage(), rawData);
+ xfr_client.sendXfroutRequestInfo(userInfo.getSocket(), (uint8_t *)rawData.getData(),
+ rawData.getLength());
+ xfr_client.disconnect();
+ }
+ catch (const exception & err) {
+ nag(std::string("error handle xfr query:") + err.what() + "\n");
+ }
+}
+
+void
+AuthSrvImpl::processIxfrQuery(asio_link::UserInfo &userInfo, const std::string &queryZoneName)
+{
+ //TODO check with the conf-mgr whether current server is the auth of the zone
+ isc::cc::Session tmp_session_with_xfr;
+ tmp_session_with_xfr.establish();
+ const string remote_ip_address = userInfo.getIPAddress();
+ ElementPtr notify_command = Element::createFromString("{\"command\": [\"notify\", {\"zone_name\" : \""
+ + queryZoneName
+ + "\", \"master_ip\" : \""
+ + remote_ip_address
+ + "\"}]}");
+ unsigned int seq = tmp_session_with_xfr.group_sendmsg(notify_command, "Xfrin");
+ ElementPtr env, answer;
+ tmp_session_with_xfr.group_recvmsg(env, answer, false, seq);
+ int rcode;
+ ElementPtr err = parseAnswer(rcode, answer);
+ if (rcode != 0)
+ nag("notify send failed\n");
+
+}
+
ElementPtr
AuthSrvImpl::setDbFile(const isc::data::ElementPtr config) {
@@ -289,7 +226,7 @@
// exception guarantee: We first need to perform all operations that can
// fail, while acquiring resources in the RAII manner. We then perform
// delete and swap operations which should not fail.
- DataSrcPtr datasrc_ptr(DataSrcPtr(new Sqlite3DataSrc));
+ DataSrcPtr datasrc_ptr(new Sqlite3DataSrc);
datasrc_ptr->init(final);
data_sources_.addDataSrc(datasrc_ptr);
@@ -302,6 +239,42 @@
return (answer);
}
+
+AuthSrv::AuthSrv() : impl_(new AuthSrvImpl) {
+}
+
+AuthSrv::~AuthSrv() {
+ delete impl_;
+}
+
+
+void
+AuthSrv::setVerbose(const bool on) {
+ impl_->setVerbose(on);
+}
+
+bool
+AuthSrv::getVerbose() const {
+ return (impl_->getVerbose());
+}
+
+void
+AuthSrv::setConfigSession(ModuleCCSession* cs) {
+ impl_->setConfigSession(cs);
+}
+
+ModuleCCSession*
+AuthSrv::configSession() const {
+ return (impl_->getConfigSession());
+}
+
+void
+AuthSrv::processQuery(asio_link::UserInfo &userInfo)
+{
+ impl_->processQuery(userInfo);
+}
+
+
ElementPtr
AuthSrv::updateConfig(isc::data::ElementPtr new_config) {
try {
@@ -312,9 +285,7 @@
return answer;
} catch (const isc::Exception& error) {
- if (impl_->verbose_mode_) {
- cerr << "[AuthSrv] error: " << error.what() << endl;
- }
+ impl_->nag(std::string("[AuthSrv] error: ") + error.what() + "\n");
return isc::config::createAnswer(1, error.what());
}
}
Modified: branches/feng-authnotify/src/bin/auth/auth_srv.h
==============================================================================
--- branches/feng-authnotify/src/bin/auth/auth_srv.h (original)
+++ branches/feng-authnotify/src/bin/auth/auth_srv.h Sun Jun 13 05:59:13 2010
@@ -21,45 +21,35 @@
#include <cc/data.h>
#include <config/ccsession.h>
+#include <boost/utility.hpp>
-namespace isc {
-namespace dns {
-class InputBuffer;
-class Message;
-class MessageRenderer;
-}
+
+class AuthSrvImpl;
+namespace asio_link
+{
+ class UserInfo;
}
-class AuthSrvImpl;
-
-class AuthSrv {
+class AuthSrv : private boost::noncopyable{
///
/// \name Constructors, Assignment Operator and Destructor.
///
/// Note: The copy constructor and the assignment operator are intentionally
/// defined as private.
//@{
-private:
- AuthSrv(const AuthSrv& source);
- AuthSrv& operator=(const AuthSrv& source);
public:
- explicit AuthSrv();
+ AuthSrv();
~AuthSrv();
- //@}
- /// \return \c true if the \message contains a response to be returned;
- /// otherwise \c false.
- bool processMessage(isc::dns::InputBuffer& request_buffer,
- isc::dns::Message& message,
- isc::dns::MessageRenderer& response_renderer,
- bool udp_buffer);
+ void processQuery(asio_link::UserInfo &userInfo);
void setVerbose(bool on);
bool getVerbose() const;
void serve(std::string zone_name);
isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
isc::config::ModuleCCSession* configSession() const;
void setConfigSession(isc::config::ModuleCCSession* cs);
+
private:
- AuthSrvImpl* impl_;
+ AuthSrvImpl* impl_;
};
#endif // __AUTH_SRV_H
Modified: branches/feng-authnotify/src/bin/auth/main.cc
==============================================================================
--- branches/feng-authnotify/src/bin/auth/main.cc (original)
+++ branches/feng-authnotify/src/bin/auth/main.cc Sun Jun 13 05:59:13 2010
@@ -28,10 +28,6 @@
#include <iostream>
#include <boost/foreach.hpp>
-#ifdef HAVE_BOOST_SYSTEM
-#include <boost/bind.hpp>
-#include <boost/asio.hpp>
-#endif // HAVE_BOOST_SYSTEM
#include <exceptions/exceptions.h>
@@ -43,26 +39,12 @@
#include <cc/data.h>
#include <config/ccsession.h>
-#if defined(HAVE_BOOST_SYSTEM) && defined(HAVE_BOOST_PYTHON)
-#define USE_XFROUT
-#include <xfr/xfrout_client.h>
-#endif
-
#include "spec_config.h"
#include "common.h"
#include "auth_srv.h"
+#include "asio_link.h"
using namespace std;
-#ifdef USE_XFROUT
-using namespace isc::xfr;
-#endif
-
-#ifdef HAVE_BOOST_SYSTEM
-using namespace boost::asio;
-using ip::udp;
-using ip::tcp;
-#endif // HAVE_BOOST_SYSTEM
-
using namespace isc::data;
using namespace isc::cc;
using namespace isc::config;
@@ -79,13 +61,8 @@
* todo: turn this around, and put handlers in the authserver
* class itself? */
AuthSrv *auth_server;
-#ifdef HAVE_BOOST_SYSTEM
-// TODO: this should be a property of AuthSrv, and AuthSrv needs
-// a stop() method (so the shutdown command can be handled)
-boost::asio::io_service io_service_;
-#else
-bool running;
-#endif // HAVE_BOOST_SYSTEM
+
+asio_link::IOService* io_service;
ElementPtr
my_config_handler(ElementPtr new_config) {
@@ -101,660 +78,11 @@
/* let's add that message to our answer as well */
answer->get("result")->add(args);
} else if (command == "shutdown") {
-#ifdef HAVE_BOOST_SYSTEM
- io_service_.stop();
-#else
- running = false;
-#endif // HAVE_BOOST_SYSTEM
+ io_service->stop();
}
return answer;
}
-
-#ifdef USE_XFROUT
-//TODO. The sample way for checking axfr query, the code should be merged to auth server class
-static bool
-check_axfr_query(char *msg_data, uint16_t msg_len)
-{
- if (msg_len < 15)
- return false;
-
- uint16_t query_type = *(uint16_t *)(msg_data + (msg_len - 4));
- if ( query_type == 0xFC00)
- return true;
-
- return false;
-}
-
-//TODO. Send the xfr query to xfrout module, the code should be merged to auth server class
-static void
-dispatch_axfr_query(int tcp_sock, char axfr_query[], uint16_t query_len)
-{
- std::string path = string(UNIX_SOCKET_FILE);
- XfroutClient xfr_client(path);
- try {
- xfr_client.connect();
- xfr_client.sendXfroutRequestInfo(tcp_sock, (uint8_t *)axfr_query, query_len);
- xfr_client.disconnect();
- }
- catch (const std::exception & err) {
- //if (verbose_mode)
- cerr << "error handle xfr query:" << err.what() << endl;
- }
-}
-#endif
-
-bool isNotifyMessage(const uint8_t *data)
-{
- int opcode = (*(data + 2) & 0x78) >> 3;
- return opcode == 4;
-}
-
-void handleNotify(udp::endpoint &sender, uint8_t *data, size_t data_len)
-{
-#define MIN_NOTIFY_HEAD_LEN 12
- if (data_len < MIN_NOTIFY_HEAD_LEN)
- return;
- //get updated zone name and remote master's ip address and send to xfrin module
- InputBuffer name_buffer(data + MIN_NOTIFY_HEAD_LEN, data_len - MIN_NOTIFY_HEAD_LEN);
- try
- {
- Name name(name_buffer);
- //TODO check with the conf-mgr whether current server is the auth of the zone
- Session tmp_session_with_xfr;
- tmp_session_with_xfr.establish();
- const string remote_ip_address = sender.address().to_string();
- ElementPtr notify_command = Element::createFromString("{\"command\": [\"notify\", {\"zone_name\" : \""
- + name.toText()
- + "\", \"master_ip\" : \""
- + remote_ip_address
- + "\"}]}");
- unsigned int seq = tmp_session_with_xfr.group_sendmsg(notify_command, "Xfrin");
- ElementPtr env, answer;
- tmp_session_with_xfr.group_recvmsg(env, answer, false, seq);
- int rcode;
- ElementPtr err = parseAnswer(rcode, answer);
- if (rcode != 0)
- {
- cerr << "notify send failed" << std::endl;
- }
- }
- catch (const std::exception& ex)
- {
- cerr << "error handle notify query:" << ex.what() << endl;
- }
-
- //set the qr bit
- uint8_t *qr_start_byte = data + 2;
- *qr_start_byte |= 0x80;
-}
-
-
-#ifdef HAVE_BOOST_SYSTEM
-//
-// Helper classes for asynchronous I/O using boost::asio
-//
-class TCPClient {
-public:
- TCPClient(io_service& io_service) :
- socket_(io_service),
- response_buffer_(0),
- responselen_buffer_(TCP_MESSAGE_LENGTHSIZE),
- response_renderer_(response_buffer_),
- dns_message_(Message::PARSE)
- {}
-
- void start() {
- async_read(socket_, boost::asio::buffer(data_, TCP_MESSAGE_LENGTHSIZE),
- boost::bind(&TCPClient::headerRead, this,
- placeholders::error,
- placeholders::bytes_transferred));
- }
-
- tcp::socket& getSocket() { return (socket_); }
-
- void headerRead(const boost::system::error_code& error,
- size_t bytes_transferred)
- {
- if (!error) {
- InputBuffer dnsbuffer(data_, bytes_transferred);
-
- uint16_t msglen = dnsbuffer.readUint16();
- async_read(socket_, boost::asio::buffer(data_, msglen),
-
- boost::bind(&TCPClient::requestRead, this,
- placeholders::error,
- placeholders::bytes_transferred));
- } else {
- delete this;
- }
- }
-
- void requestRead(const boost::system::error_code& error,
- size_t bytes_transferred)
- {
- if (!error) {
- InputBuffer dnsbuffer(data_, bytes_transferred);
-#ifdef USE_XFROUT
- if (check_axfr_query(data_, bytes_transferred)) {
- dispatch_axfr_query(socket_.native(), data_, bytes_transferred);
- // start to get new query ?
- start();
- } else {
-#endif
- if (auth_server->processMessage(dnsbuffer, dns_message_,
- response_renderer_, false)) {
- responselen_buffer_.writeUint16(response_buffer_.getLength());
- async_write(socket_,
- boost::asio::buffer(
- responselen_buffer_.getData(),
- responselen_buffer_.getLength()),
- boost::bind(&TCPClient::responseWrite, this,
- placeholders::error));
- } else {
- delete this;
- }
-#ifdef USE_XFROUT
- }
-#endif
- } else {
- delete this;
- }
- }
-
- void responseWrite(const boost::system::error_code& error) {
- if (!error) {
- async_write(socket_,
- boost::asio::buffer(response_buffer_.getData(),
- response_buffer_.getLength()),
- boost::bind(&TCPClient::handleWrite, this,
- placeholders::error));
- } else {
- delete this;
- }
- }
-
- void handleWrite(const boost::system::error_code& error) {
- if (!error) {
- start(); // handle next request, if any.
- } else {
- delete this;
- }
- }
-
-private:
- tcp::socket socket_;
- OutputBuffer response_buffer_;
- OutputBuffer responselen_buffer_;
- MessageRenderer response_renderer_;
- Message dns_message_;
- enum { MAX_LENGTH = 65535 };
- static const size_t TCP_MESSAGE_LENGTHSIZE = 2;
- char data_[MAX_LENGTH];
-};
-
-class TCPServer {
-public:
- TCPServer(io_service& io_service, int af, short port) :
- io_service_(io_service), acceptor_(io_service_),
- listening_(new TCPClient(io_service_))
- {
- tcp::endpoint endpoint(af == AF_INET6 ? tcp::v6() : tcp::v4(), port);
- acceptor_.open(endpoint.protocol());
- // Set v6-only (we use a different instantiation for v4,
- // otherwise asio will bind to both v4 and v6
- if (af == AF_INET6) {
- acceptor_.set_option(ip::v6_only(true));
- }
- acceptor_.set_option(tcp::acceptor::reuse_address(true));
- acceptor_.bind(endpoint);
- acceptor_.listen();
- acceptor_.async_accept(listening_->getSocket(),
- boost::bind(&TCPServer::handleAccept, this,
- listening_, placeholders::error));
- }
-
- ~TCPServer() { delete listening_; }
-
- void handleAccept(TCPClient* new_client,
- const boost::system::error_code& error)
- {
- if (!error) {
- assert(new_client == listening_);
- new_client->start();
- listening_ = new TCPClient(io_service_);
- acceptor_.async_accept(listening_->getSocket(),
- boost::bind(&TCPServer::handleAccept,
- this, listening_,
- placeholders::error));
- } else {
- delete new_client;
- }
- }
-
-private:
- io_service& io_service_;
- tcp::acceptor acceptor_;
- TCPClient* listening_;
-};
-
-class UDPServer {
-public:
- UDPServer(io_service& io_service, int af, short port) :
- io_service_(io_service),
- socket_(io_service, af == AF_INET6 ? udp::v6() : udp::v4()),
- response_buffer_(0),
- response_renderer_(response_buffer_),
- dns_message_(Message::PARSE)
- {
- // Set v6-only (we use a different instantiation for v4,
- // otherwise asio will bind to both v4 and v6
- if (af == AF_INET6) {
- socket_.set_option(boost::asio::ip::v6_only(true));
- socket_.bind(udp::endpoint(udp::v6(), port));
- } else {
- socket_.bind(udp::endpoint(udp::v4(), port));
- }
- startReceive();
- }
-
- void handleRequest(const boost::system::error_code& error,
- size_t bytes_recvd)
- {
- if (!error && bytes_recvd > 0) {
- InputBuffer request_buffer(data_, bytes_recvd);
-
- if (isNotifyMessage((const uint8_t *)data_))
- {
- handleNotify(sender_endpoint_, (uint8_t *)data_, bytes_recvd);
- socket_.async_send_to(
- boost::asio::buffer(data_, bytes_recvd),
- sender_endpoint_,
- boost::bind(&UDPServer::sendCompleted,
- this,
- placeholders::error,
- placeholders::bytes_transferred));
-
- }
- else
- {
-
- dns_message_.clear(Message::PARSE);
- response_renderer_.clear();
- if (auth_server->processMessage(request_buffer, dns_message_,
- response_renderer_, true)) {
- socket_.async_send_to(
- boost::asio::buffer(response_buffer_.getData(),
- response_buffer_.getLength()),
- sender_endpoint_,
- boost::bind(&UDPServer::sendCompleted,
- this,
- placeholders::error,
- placeholders::bytes_transferred));
- } else {
- startReceive();
- }
- }
- } else {
- startReceive();
- }
- }
-
- void sendCompleted(const boost::system::error_code& error UNUSED_PARAM,
- size_t bytes_sent UNUSED_PARAM)
- {
- // Even if error occurred there's nothing to do. Simply handle
- // the next request.
- startReceive();
- }
-private:
- void startReceive() {
- socket_.async_receive_from(
- boost::asio::buffer(data_, MAX_LENGTH), sender_endpoint_,
- boost::bind(&UDPServer::handleRequest, this,
- placeholders::error,
- placeholders::bytes_transferred));
- }
-
-private:
- io_service& io_service_;
- udp::socket socket_;
- OutputBuffer response_buffer_;
- MessageRenderer response_renderer_;
- Message dns_message_;
- udp::endpoint sender_endpoint_;
- enum { MAX_LENGTH = 4096 };
- char data_[MAX_LENGTH];
-};
-
-struct ServerSet {
- ServerSet() : udp4_server(NULL), udp6_server(NULL),
- tcp4_server(NULL), tcp6_server(NULL)
- {}
- ~ServerSet() {
- delete udp4_server;
- delete udp6_server;
- delete tcp4_server;
- delete tcp6_server;
- }
- UDPServer* udp4_server;
- UDPServer* udp6_server;
- TCPServer* tcp4_server;
- TCPServer* tcp6_server;
-};
-
-void
-run_server(const char* port, const bool use_ipv4, const bool use_ipv6,
- AuthSrv* srv UNUSED_PARAM)
-{
- ServerSet servers;
- short portnum = atoi(port);
-
- if (use_ipv4) {
- servers.udp4_server = new UDPServer(io_service_, AF_INET, portnum);
- servers.tcp4_server = new TCPServer(io_service_, AF_INET, portnum);
- }
- if (use_ipv6) {
- servers.udp6_server = new UDPServer(io_service_, AF_INET6, portnum);
- servers.tcp6_server = new TCPServer(io_service_, AF_INET6, portnum);
- }
-
- cout << "Server started." << endl;
- io_service_.run();
-}
-#else // !HAVE_BOOST_SYSTEM
-struct SocketSet {
- SocketSet() : ups4(-1), tps4(-1), ups6(-1), tps6(-1) {}
- ~SocketSet() {
- if (ups4 >= 0) {
- close(ups4);
- }
- if (tps4 >= 0) {
- close(tps4);
- }
- if (ups6 >= 0) {
- close(ups6);
- }
- if (tps4 >= 0) {
- close(tps6);
- }
- }
- int ups4, tps4, ups6, tps6;
-};
-
-int
-getUDPSocket(int af, const char* port) {
- struct addrinfo hints, *res;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = af;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_flags = AI_PASSIVE;
- hints.ai_protocol = IPPROTO_UDP;
-
- int error = getaddrinfo(NULL, port, &hints, &res);
- if (error != 0) {
- isc_throw(FatalError, "getaddrinfo failed: " << gai_strerror(error));
- }
-
- int s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (s < 0) {
- isc_throw(FatalError, "failed to open socket");
- }
-
- if (af == AF_INET6) {
- int on = 1;
- if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
- cerr << "couldn't set IPV6_V6ONLY socket option" << endl;
- // proceed anyway
- }
- }
-
- if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
- isc_throw(FatalError, "binding socket failure");
- }
-
- return (s);
-}
-
-int
-getTCPSocket(int af, const char* port) {
- struct addrinfo hints, *res;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = af;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_PASSIVE;
- hints.ai_protocol = IPPROTO_TCP;
-
- int error = getaddrinfo(NULL, port, &hints, &res);
- if (error != 0) {
- isc_throw(FatalError, "getaddrinfo failed: " << gai_strerror(error));
- }
-
- int s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (s < 0) {
- isc_throw(FatalError, "failed to open socket");
- }
-
- int on = 1;
- if (af == AF_INET6) {
- if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
- cerr << "couldn't set IPV6_V6ONLY socket option" << endl;
- }
- // proceed anyway
- }
-
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
- cerr << "couldn't set SO_REUSEADDR socket option" << endl;
- }
-
- if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
- isc_throw(FatalError, "binding socket failure");
- }
-
- if (listen(s, 100) < 0) {
- isc_throw(FatalError, "failed to listen on a TCP socket");
- }
- return (s);
-}
-
-void
-processMessageUDP(const int fd, Message& dns_message,
- MessageRenderer& response_renderer)
-{
- struct sockaddr_storage ss;
- socklen_t sa_len = sizeof(ss);
- struct sockaddr* sa = static_cast<struct sockaddr*>((void*)&ss);
- char recvbuf[4096];
- int cc;
-
- dns_message.clear(Message::PARSE);
- response_renderer.clear();
- if ((cc = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, sa, &sa_len)) > 0) {
- InputBuffer buffer(recvbuf, cc);
- if (auth_server->processMessage(buffer, dns_message, response_renderer,
- true)) {
- cc = sendto(fd, response_renderer.getData(),
- response_renderer.getLength(), 0, sa, sa_len);
- if (cc != response_renderer.getLength()) {
- cerr << "UDP send error" << endl;
- }
- }
- } else if (verbose_mode) {
- cerr << "UDP receive error" << endl;
- }
-}
-
-// XXX: this function does not handle partial reads or partial writes,
-// and is VERY UNSAFE - will probably be removed or rewritten
-void
-processMessageTCP(const int fd, Message& dns_message,
- MessageRenderer& response_renderer)
-{
- struct sockaddr_storage ss;
- socklen_t sa_len = sizeof(ss);
- struct sockaddr* sa = static_cast<struct sockaddr*>((void*)&ss);
- char sizebuf[2];
- int cc;
-
- int ts = accept(fd, sa, &sa_len);
- if (ts < 0) {
- if (verbose_mode) {
- cerr << "[XX] TCP accept failure:" << endl;
- return;
- }
- }
-
- if (verbose_mode) {
- cerr << "[XX] process TCP" << endl;
- }
- cc = recv(ts, sizebuf, 2, 0);
- if (cc < 0) {
- if (verbose_mode) {
- cerr << "[XX] TCP recv failure:" << endl;
- }
- close(ts);
- return;
- }
- if (verbose_mode) {
- cerr << "[XX] got: " << cc << endl;
- }
- uint16_t size, size_n;
- memcpy(&size_n, sizebuf, 2);
- size = ntohs(size_n);
- if (verbose_mode) {
- cerr << "[XX] got: " << size << endl;
- }
-
- vector<char> message_buffer;
- message_buffer.reserve(size);
- cc = 0;
- while (cc < size) {
- if (verbose_mode) {
- cerr << "[XX] cc now: " << cc << " of " << size << endl;
- }
- const int cc0 = recv(ts, &message_buffer[0] + cc, size - cc, 0);
- if (cc0 < 0) {
- if (verbose_mode) {
- cerr << "TCP receive error" << endl;
- close(ts);
- return;
- }
- }
- if (cc0 == 0) {
- // client closed connection
- close(ts);
- return;
- }
- cc += cc0;
- }
-
- InputBuffer buffer(&message_buffer[0], size);
- dns_message.clear(Message::PARSE);
- response_renderer.clear();
- if (auth_server->processMessage(buffer, dns_message, response_renderer,
- false)) {
- size = response_renderer.getLength();
- size_n = htons(size);
- if (send(ts, &size_n, 2, 0) == 2) {
- cc = send(ts, response_renderer.getData(),
- response_renderer.getLength(), 0);
- if (cc == -1) {
- if (verbose_mode) {
- cerr << "[AuthSrv] error in sending TCP response message" <<
- endl;
- }
- } else {
- if (verbose_mode) {
- cerr << "[XX] sent TCP response: " << cc << " bytes"
- << endl;
- }
- }
- } else {
- if (verbose_mode) {
- cerr << "TCP send error" << endl;
- }
- }
- }
-
- // TODO: we don't check for more queries on the stream atm
- close(ts);
-}
-
-void
-run_server(const char* port, const bool use_ipv4, const bool use_ipv6,
- AuthSrv* srv)
-{
- SocketSet socket_set;
- fd_set fds_base;
- int nfds = -1;
-
- FD_ZERO(&fds_base);
- if (use_ipv4) {
- socket_set.ups4 = getUDPSocket(AF_INET, port);
- FD_SET(socket_set.ups4, &fds_base);
- nfds = max(nfds, socket_set.ups4);
- socket_set.tps4 = getTCPSocket(AF_INET, port);
- FD_SET(socket_set.tps4, &fds_base);
- nfds = max(nfds, socket_set.tps4);
- }
- if (use_ipv6) {
- socket_set.ups6 = getUDPSocket(AF_INET6, port);
- FD_SET(socket_set.ups6, &fds_base);
- nfds = max(nfds, socket_set.ups6);
- socket_set.tps6 = getTCPSocket(AF_INET6, port);
- FD_SET(socket_set.tps6, &fds_base);
- nfds = max(nfds, socket_set.tps6);
- }
- ++nfds;
-
- cout << "Server started." << endl;
-
- if (srv->configSession() == NULL) {
- isc_throw(FatalError, "Config session not initalized");
- }
-
- int ss = srv->configSession()->getSocket();
- Message dns_message(Message::PARSE);
- OutputBuffer resonse_buffer(0);
- MessageRenderer response_renderer(resonse_buffer);
-
- running = true;
- while (running) {
- fd_set fds = fds_base;
- FD_SET(ss, &fds);
- ++nfds;
-
- if (srv->configSession()->hasQueuedMsgs()) {
- srv->configSession()->checkCommand();
- }
- int n = select(nfds, &fds, NULL, NULL, NULL);
- if (n < 0) {
- if (errno != EINTR) {
- isc_throw(FatalError, "select error");
- }
- continue;
- }
-
- if (socket_set.ups4 >= 0 && FD_ISSET(socket_set.ups4, &fds)) {
- processMessageUDP(socket_set.ups4, dns_message, response_renderer);
- }
- if (socket_set.ups6 >= 0 && FD_ISSET(socket_set.ups6, &fds)) {
- processMessageUDP(socket_set.ups6, dns_message, response_renderer);
- }
- if (socket_set.tps4 >= 0 && FD_ISSET(socket_set.tps4, &fds)) {
- processMessageTCP(socket_set.tps4, dns_message, response_renderer);
- }
- if (socket_set.tps6 >= 0 && FD_ISSET(socket_set.tps6, &fds)) {
- processMessageTCP(socket_set.tps6, dns_message, response_renderer);
- }
- if (FD_ISSET(ss, &fds)) {
- srv->configSession()->checkCommand();
- }
- }
-}
-#endif // HAVE_BOOST_SYSTEM
void
usage() {
@@ -799,7 +127,7 @@
}
if (!use_ipv4 && !use_ipv6) {
- cerr << "-4 and -6 can't coexist" << endl;
+ cerr << "[b10-auth] Error: -4 and -6 can't coexist" << endl;
usage();
}
@@ -817,22 +145,23 @@
auth_server = new AuthSrv;
auth_server->setVerbose(verbose_mode);
-#ifdef HAVE_BOOST_SYSTEM
- ModuleCCSession cs(specfile, io_service_, my_config_handler,
- my_command_handler);
-#else
- ModuleCCSession cs(specfile, my_config_handler, my_command_handler);
-#endif
+ io_service = new asio_link::IOService(auth_server, port, use_ipv4,
+ use_ipv6);
+
+ ModuleCCSession cs(specfile, io_service->get_io_service(), my_config_handler, my_command_handler);
auth_server->setConfigSession(&cs);
auth_server->updateConfig(ElementPtr());
- run_server(port, use_ipv4, use_ipv6, auth_server);
+
+ cout << "[b10-auth] Server started." << endl;
+ io_service->run();
} catch (const std::exception& ex) {
cerr << ex.what() << endl;
ret = 1;
}
+ delete io_service;
delete auth_server;
return (ret);
}
Modified: branches/feng-authnotify/src/bin/auth/tests/Makefile.am
==============================================================================
--- branches/feng-authnotify/src/bin/auth/tests/Makefile.am (original)
+++ branches/feng-authnotify/src/bin/auth/tests/Makefile.am Sun Jun 13 05:59:13 2010
@@ -1,6 +1,8 @@
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += -I$(top_builddir)/src/lib/dns -I$(top_srcdir)/src/bin
AM_CPPFLAGS += -DTEST_DATA_DIR=\"$(srcdir)/testdata\"
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
CLEANFILES = *.gcno *.gcda
@@ -9,7 +11,7 @@
TESTS += run_unittests
run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
-run_unittests_SOURCES += ../auth_srv.h ../auth_srv.cc
+run_unittests_SOURCES += ../auth_srv.h ../auth_srv.cc ../asio_link.cc ../asio_link.h ../auth_util.h ../auth_util.cc
run_unittests_SOURCES += auth_srv_unittest.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
@@ -20,11 +22,8 @@
run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns.a
run_unittests_LDADD += $(top_builddir)/src/lib/config/.libs/libcfgclient.a
run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.a
-run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
-if HAVE_BOOST_SYSTEM
-run_unittests_LDFLAGS += $(BOOST_LDFLAGS)
-run_unittests_LDADD += $(BOOST_SYSTEM_LIB)
-endif
+run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
+run_unittests_LDADD += $(top_builddir)/src/lib/xfr/.libs/libxfr.a
endif
noinst_PROGRAMS = $(TESTS)
Modified: branches/feng-authnotify/src/bin/auth/tests/auth_srv_unittest.cc
==============================================================================
--- branches/feng-authnotify/src/bin/auth/tests/auth_srv_unittest.cc (original)
+++ branches/feng-authnotify/src/bin/auth/tests/auth_srv_unittest.cc Sun Jun 13 05:59:13 2010
@@ -26,8 +26,9 @@
#include <cc/data.h>
#include <auth/auth_srv.h>
-
+#include <auth/asio_link.h>
#include <dns/tests/unittest_util.h>
+#include <iostream>
using isc::UnitTestUtil;
using namespace std;
@@ -44,27 +45,19 @@
class AuthSrvTest : public ::testing::Test {
protected:
- AuthSrvTest() : request_message(Message::RENDER),
- parse_message(Message::PARSE), default_qid(0x1035),
+ AuthSrvTest() : default_qid(0x1035),
opcode(Opcode(Opcode::QUERY())), qname("www.example.com"),
- qclass(RRClass::IN()), qtype(RRType::A()), ibuffer(NULL),
- request_obuffer(0), request_renderer(request_obuffer),
- response_obuffer(0), response_renderer(response_obuffer)
+ qclass(RRClass::IN()), qtype(RRType::A()),
+ userInfo(asio_link::UserInfo::QueryThroughUDP)
{}
AuthSrv server;
- Message request_message;
- Message parse_message;
const qid_t default_qid;
const Opcode opcode;
const Name qname;
const RRClass qclass;
const RRType qtype;
- InputBuffer* ibuffer;
- OutputBuffer request_obuffer;
- MessageRenderer request_renderer;
- OutputBuffer response_obuffer;
- MessageRenderer response_renderer;
vector<uint8_t> data;
+ asio_link::UserInfo userInfo;
void createDataFromFile(const char* const datafile);
};
@@ -82,20 +75,20 @@
void
AuthSrvTest::createDataFromFile(const char* const datafile) {
- delete ibuffer;
data.clear();
UnitTestUtil::readWireData(datafile, data);
- ibuffer = new InputBuffer(&data[0], data.size());
+ userInfo.setQueryRawData((char *)&data[0], data.size());
}
void
-headerCheck(const Message& message, const qid_t qid, const Rcode& rcode,
+responseHeaderCheck(const asio_link::UserInfo &userInfo, const qid_t qid, const Rcode& rcode,
const uint16_t opcodeval, const unsigned int flags,
const unsigned int qdcount,
const unsigned int ancount, const unsigned int nscount,
const unsigned int arcount)
{
+ const Message &message = userInfo.getMessage();
EXPECT_EQ(qid, message.getQid());
EXPECT_EQ(rcode, message.getRcode());
EXPECT_EQ(opcodeval, message.getOpcode().getCode());
@@ -118,13 +111,15 @@
for (unsigned int i = 1; i < 16; ++i) {
// set Opcode to 'i', which iterators over all possible codes except
// the standard query (0)
+ if (i == 4 || i == 5)
+ continue;
createDataFromFile("simplequery_fromWire");
data[2] = ((i << 3) & 0xff);
-
- parse_message.clear(Message::PARSE);
- EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
- response_renderer, true));
- headerCheck(parse_message, default_qid, Rcode::NOTIMP(), i, QR_FLAG,
+ userInfo.setQueryRawData((char *)&data[0], data.size());
+
+ EXPECT_EQ(true, userInfo.isMessageValid());
+ server.processQuery(userInfo);
+ responseHeaderCheck(userInfo, default_qid, Rcode::NOTIMP(), i, QR_FLAG,
0, 0, 0, 0);
}
}
@@ -141,11 +136,13 @@
// Multiple questions. Should result in FORMERR.
TEST_F(AuthSrvTest, multiQuestion) {
createDataFromFile("multiquestion_fromWire");
- EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
- response_renderer, true));
- headerCheck(parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(),
+ EXPECT_EQ(true, userInfo.isMessageValid());
+ EXPECT_EQ(true, userInfo.needsReply());
+ server.processQuery(userInfo);
+ responseHeaderCheck(userInfo, default_qid, Rcode::FORMERR(), opcode.getCode(),
QR_FLAG, 2, 0, 0, 0);
+ Message &parse_message = userInfo.getMessage();
QuestionIterator qit = parse_message.beginQuestion();
EXPECT_EQ(Name("example.com"), (*qit)->getName());
EXPECT_EQ(RRClass::IN(), (*qit)->getClass());
@@ -162,8 +159,8 @@
// dropped.
TEST_F(AuthSrvTest, shortMessage) {
createDataFromFile("shortmessage_fromWire");
- EXPECT_EQ(false, server.processMessage(*ibuffer, parse_message,
- response_renderer, true));
+ EXPECT_EQ(false, userInfo.isMessageValid());
+ EXPECT_EQ(false, userInfo.needsReply());
}
// Response messages. Must be silently dropped, whether it's a valid response
@@ -171,43 +168,41 @@
TEST_F(AuthSrvTest, response) {
// A valid (although unusual) response
createDataFromFile("simpleresponse_fromWire");
- EXPECT_EQ(false, server.processMessage(*ibuffer, parse_message,
- response_renderer, true));
+ EXPECT_EQ(false, userInfo.isMessageValid());
+ EXPECT_EQ(false, userInfo.needsReply());
// A response with a broken question section. must be dropped rather than
// returning FORMERR.
createDataFromFile("shortresponse_fromWire");
- EXPECT_EQ(false, server.processMessage(*ibuffer, parse_message,
- response_renderer, true));
+ EXPECT_EQ(false, userInfo.isMessageValid());
+ EXPECT_EQ(false, userInfo.needsReply());
// A response to iquery. must be dropped rather than returning NOTIMP.
createDataFromFile("iqueryresponse_fromWire");
- EXPECT_EQ(false, server.processMessage(*ibuffer, parse_message,
- response_renderer, true));
+ EXPECT_EQ(false, userInfo.isMessageValid());
+ EXPECT_EQ(false, userInfo.needsReply());
}
// Query with a broken question
TEST_F(AuthSrvTest, shortQuestion) {
createDataFromFile("shortquestion_fromWire");
- EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
- response_renderer, true));
- // Since the query's question is broken, the question section of the
- // response should be empty.
- headerCheck(parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(),
- QR_FLAG, 0, 0, 0, 0);
+ EXPECT_EQ(false, userInfo.isMessageValid());
+ EXPECT_EQ(true, userInfo.needsReply());
+
+ responseHeaderCheck(userInfo, default_qid, Rcode::FORMERR(), opcode.getCode(),
+ QR_FLAG, 0, 0, 0, 0);
}
// Query with a broken answer section
TEST_F(AuthSrvTest, shortAnswer) {
createDataFromFile("shortanswer_fromWire");
- EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
- response_renderer, true));
-
- // This is a bogus query, but question section is valid. So the response
- // should copy the question section.
- headerCheck(parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(),
- QR_FLAG, 1, 0, 0, 0);
-
+ EXPECT_EQ(false, userInfo.isMessageValid());
+ EXPECT_EQ(true, userInfo.needsReply());
+
+ responseHeaderCheck(userInfo, default_qid, Rcode::FORMERR(), opcode.getCode(),
+ QR_FLAG, 1, 0, 0, 0);
+
+ Message &parse_message = userInfo.getMessage();
QuestionIterator qit = parse_message.beginQuestion();
EXPECT_EQ(Name("example.com"), (*qit)->getName());
EXPECT_EQ(RRClass::IN(), (*qit)->getClass());
@@ -216,17 +211,21 @@
EXPECT_TRUE(qit == parse_message.endQuestion());
}
+
+
// Query with unsupported version of EDNS.
TEST_F(AuthSrvTest, ednsBadVers) {
createDataFromFile("queryBadEDNS_fromWire");
- EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
- response_renderer, true));
+ EXPECT_EQ(false, userInfo.isMessageValid());
+ EXPECT_EQ(true, userInfo.needsReply());
// The response must have an EDNS OPT RR in the additional section.
// Note that the DNSSEC DO bit is cleared even if this bit in the query
// is set. This is a limitation of the current implementation.
- headerCheck(parse_message, default_qid, Rcode::BADVERS(), opcode.getCode(),
+ responseHeaderCheck(userInfo, default_qid, Rcode::BADVERS(), opcode.getCode(),
QR_FLAG, 1, 0, 0, 1);
+
+ Message &parse_message = userInfo.getMessage();
EXPECT_EQ(4096, parse_message.getUDPSize());
EXPECT_FALSE(parse_message.isDNSSECSupported());
}
@@ -253,9 +252,9 @@
// response should have the AA flag on, and have an RR in each answer
// and authority section.
createDataFromFile("examplequery_fromWire");
- EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
- response_renderer, true));
- headerCheck(parse_message, default_qid, Rcode::NOERROR(), opcode.getCode(),
+ EXPECT_EQ(true, userInfo.isMessageValid());
+ server.processQuery(userInfo);
+ responseHeaderCheck(userInfo, default_qid, Rcode::NOERROR(), opcode.getCode(),
QR_FLAG | AA_FLAG, 1, 1, 1, 0);
}
@@ -267,9 +266,9 @@
// in a SERVFAIL response, and the answer and authority sections should
// be empty.
createDataFromFile("badExampleQuery_fromWire");
- EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
- response_renderer, true));
- headerCheck(parse_message, default_qid, Rcode::SERVFAIL(), opcode.getCode(),
+ EXPECT_EQ(true, userInfo.isMessageValid());
+ server.processQuery(userInfo);
+ responseHeaderCheck(userInfo, default_qid, Rcode::SERVFAIL(), opcode.getCode(),
QR_FLAG, 1, 0, 0, 0);
}
@@ -282,9 +281,9 @@
// The original data source should still exist.
createDataFromFile("examplequery_fromWire");
- EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
- response_renderer, true));
- headerCheck(parse_message, default_qid, Rcode::NOERROR(), opcode.getCode(),
+ EXPECT_EQ(true, userInfo.isMessageValid());
+ server.processQuery(userInfo);
+ responseHeaderCheck(userInfo, default_qid, Rcode::NOERROR(), opcode.getCode(),
QR_FLAG | AA_FLAG, 1, 1, 1, 0);
}
}
More information about the bind10-changes
mailing list