Commit 1d5ba709 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

refactoring: moved XFR logic from asio_link to auth_srv.


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac221@2177 e5f2f494-b856-4b98-b285-d166d9295462
parent 9a7ab5ec
......@@ -26,15 +26,9 @@
#include <dns/message.h>
#include <dns/messagerenderer.h>
#if defined(HAVE_BOOST_PYTHON)
#define USE_XFROUT
#include <xfr/xfrout_client.h>
#endif
#include <asio_link.h>
#include "spec_config.h" // for XFROUT. should not be here.
#include "auth_srv.h"
#include <auth/auth_srv.h>
using namespace asio;
using asio::ip::udp;
......@@ -42,56 +36,6 @@ using asio::ip::tcp;
using namespace std;
using namespace isc::dns;
#ifdef USE_XFROUT
using namespace isc::xfr;
#endif
namespace {
// As a short term workaround, we have XFROUT specific code. We should soon
// refactor the code with some abstraction so that we can separate this level
// details from the (AS)IO module.
#ifdef USE_XFROUT
//TODO. The sample way for checking axfr query, the code should be merged to auth server class
bool
check_axfr_query(char* const msg_data, const uint16_t msg_len) {
if (msg_len < 15) {
return false;
}
const 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
void
dispatch_axfr_query(const int tcp_sock, char const axfr_query[],
const uint16_t query_len)
{
string path;
if (getenv("B10_FROM_BUILD")) {
path = string(getenv("B10_FROM_BUILD")) + "/auth_xfrout_conn";
} else {
path = 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 exception & err) {
//if (verbose_mode)
cerr << "error handle xfr query:" << err.what() << endl;
}
}
#endif
}
namespace asio_link {
IOAddress::IOAddress(const string& address_str) :
......@@ -243,29 +187,19 @@ public:
return;
}
#ifdef USE_XFROUT
if (check_axfr_query(data_, bytes_transferred)) {
dispatch_axfr_query(socket_.native(), data_, bytes_transferred);
// start to get new query ?
start();
if (auth_server_->processMessage(io_message, dns_message_,
response_renderer_)) {
responselen_buffer_.writeUint16(
response_buffer_.getLength());
async_write(socket_,
asio::buffer(
responselen_buffer_.getData(),
responselen_buffer_.getLength()),
boost::bind(&TCPClient::responseWrite, this,
placeholders::error));
} else {
#endif
if (auth_server_->processMessage(io_message, dns_message_,
response_renderer_)) {
responselen_buffer_.writeUint16(
response_buffer_.getLength());
async_write(socket_,
asio::buffer(
responselen_buffer_.getData(),
responselen_buffer_.getLength()),
boost::bind(&TCPClient::responseWrite, this,
placeholders::error));
} else {
delete this;
}
#ifdef USE_XFROUT
delete this;
}
#endif
} else {
delete this;
}
......
......@@ -14,6 +14,8 @@
// $Id$
#include <config.h> // for UNUSED_PARAM
#include <netinet/in.h>
#include <algorithm>
......@@ -42,9 +44,15 @@
#include <cc/data.h>
#if defined(HAVE_BOOST_PYTHON)
#define USE_XFROUT
#include <xfr/xfrout_client.h>
#endif
#include <auth/common.h>
#include <auth/auth_srv.h>
#include <auth/asio_link.h>
#include <auth/spec_config.h>
#include <boost/lexical_cast.hpp>
......@@ -56,6 +64,9 @@ using namespace isc::dns;
using namespace isc::dns::rdata;
using namespace isc::data;
using namespace isc::config;
#ifdef USE_XFROUT
using namespace isc::xfr;
#endif
using namespace asio_link;
class AuthSrvImpl {
......@@ -65,9 +76,13 @@ private:
AuthSrvImpl& operator=(const AuthSrvImpl& source);
public:
AuthSrvImpl();
isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
bool processNormalQuery(const IOMessage& io_message, Message& message,
MessageRenderer& response_renderer);
bool processAxfrQuery(const IOMessage& io_message) const;
bool processIxfrQuery(const IOMessage& io_message,
const ConstQuestionPtr question) const;
std::string db_file_;
ModuleCCSession* cs_;
MetaDataSrc data_sources_;
......@@ -78,11 +93,14 @@ public:
bool verbose_mode_;
const string xfr_path_; // currently non configurable
/// Currently non-configurable, but will be.
static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
};
AuthSrvImpl::AuthSrvImpl() : cs_(NULL), verbose_mode_(false)
AuthSrvImpl::AuthSrvImpl() : cs_(NULL), verbose_mode_(false),
xfr_path_(UNIX_SOCKET_FILE)
{
// cur_datasrc_ is automatically initialized by the default constructor,
// effectively being an empty (sqlite) data source. once ccsession is up
......@@ -234,6 +252,22 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
return (true);
}
ConstQuestionPtr question = *message.beginQuestion();
const RRType &qtype = question->getType();
if (qtype == RRType::AXFR()) {
return (impl_->processAxfrQuery(io_message));
} else if (qtype == RRType::IXFR()) {
return (impl_->processIxfrQuery(io_message, question));
} else {
return (impl_->processNormalQuery(io_message, message,
response_renderer));
}
}
bool
AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
MessageRenderer& response_renderer)
{
const bool dnssec_ok = message.isDNSSECSupported();
const uint16_t remote_bufsize = message.getUDPSize();
......@@ -245,13 +279,14 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
try {
Query query(message, dnssec_ok);
impl_->data_sources_.doQuery(query);
data_sources_.doQuery(query);
} catch (const Exception& ex) {
if (impl_->verbose_mode_) {
cerr << "[b10-auth] Internal error, returning SERVFAIL: " << ex.what() << endl;
if (verbose_mode_) {
cerr << "[b10-auth] Internal error, returning SERVFAIL: " <<
ex.what() << endl;
}
makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),
impl_->verbose_mode_);
verbose_mode_);
return (true);
}
......@@ -259,7 +294,7 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
(io_message.getSocket().getProtocol() == IPPROTO_UDP);
response_renderer.setLengthLimit(udp_buffer ? remote_bufsize : 65535);
message.toWire(response_renderer);
if (impl_->verbose_mode_) {
if (verbose_mode_) {
cerr << "[b10-auth] sending a response (" <<
boost::lexical_cast<string>(response_renderer.getLength())
<< " bytes):\n" << message.toText() << endl;
......@@ -268,6 +303,78 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
return (true);
}
#ifdef USE_XFROUT
bool
AuthSrvImpl::processAxfrQuery(const IOMessage& io_message) const {
XfroutClient xfr_client(xfr_path_);
// XXX: should reject AXFR/UDP here.
try {
xfr_client.connect();
xfr_client.sendXfroutRequestInfo(io_message.getSocket().getNative(),
io_message.getData(),
io_message.getDataSize());
xfr_client.disconnect();
} catch (const exception& err) { // XXX: avoid catch-all catch!!
if (verbose_mode_) {
cerr << "[b10-auth] Error in handling XFR request:" << err.what()
<< endl;
}
// XXX: should return an error (SERVFAIL?)
}
return (false);
}
#else
bool
AuthSrvImpl::processAxfrQuery(const IOMessage& io_message UNUSED_PARAM) const {
// should better to return an error message, but hopefully this case
// is short term workaround.
return (false);
}
#endif
bool
AuthSrvImpl::processIxfrQuery(const IOMessage& io_message,
const ConstQuestionPtr question) const
{
// XXX: this function seems unacceptably expensive. Also, error cases
// aren't handled at all, which is bad.
// TODO check with the conf-mgr whether current server is the auth of the
// zone
isc::cc::Session tmp_session_with_xfr;
// this can block, expensive, and may throw exception. all bad.
tmp_session_with_xfr.establish();
// XXX: the following is super expensive.
const string remote_ip_address = io_message.getRemoteAddress().toText();
ElementPtr notify_command = Element::createFromString(
"{\"command\": [\"notify\", {\"zone_name\" : \"" +
question->getName().toText() + "\", \"master_ip\" : \"" +
remote_ip_address + "\"}]}");
// what if this fails?
const unsigned int seq =
tmp_session_with_xfr.group_sendmsg(notify_command, "Xfrin");
// this can trigger an exception. handle it.
ElementPtr env, answer;
tmp_session_with_xfr.group_recvmsg(env, answer, false, seq);
int rcode;
ElementPtr err = parseAnswer(rcode, answer);
if (rcode != 0) {
if (verbose_mode_) {
// XXX: should add the reason for the error
cerr << "[b10=auth] notify send failed" << endl;
}
// XXX: should return an error (SERVFAIL?)
}
return (false);
}
ElementPtr
AuthSrvImpl::setDbFile(const isc::data::ElementPtr config) {
ElementPtr answer = isc::config::createAnswer();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment