Commit 91b68d7e authored by Han Feng's avatar Han Feng
Browse files

refine code for notify process

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac221@2210 e5f2f494-b856-4b98-b285-d166d9295462
parent 4be5e8c9
......@@ -76,13 +76,15 @@ private:
AuthSrvImpl& operator=(const AuthSrvImpl& source);
public:
AuthSrvImpl();
~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;
bool processAxfrQuery(const IOMessage& io_message, Message& message,
MessageRenderer& response_renderer) const;
bool processNotify(const IOMessage& io_message, Message& message,
MessageRenderer& response_renderer) ;
std::string db_file_;
ModuleCCSession* cs_;
MetaDataSrc data_sources_;
......@@ -94,13 +96,15 @@ public:
bool verbose_mode_;
const string xfr_path_; // currently non configurable
bool is_xfrin_connection_established_;
isc::cc::Session session_with_xfrin_;
/// Currently non-configurable, but will be.
static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
};
AuthSrvImpl::AuthSrvImpl() : cs_(NULL), verbose_mode_(false),
xfr_path_(UNIX_SOCKET_FILE)
xfr_path_(UNIX_SOCKET_FILE), is_xfrin_connection_established_(false)
{
// cur_datasrc_ is automatically initialized by the default constructor,
// effectively being an empty (sqlite) data source. once ccsession is up
......@@ -110,6 +114,13 @@ AuthSrvImpl::AuthSrvImpl() : cs_(NULL), verbose_mode_(false),
data_sources_.addDataSrc(ConstDataSrcPtr(new StaticDataSrc));
}
AuthSrvImpl::~AuthSrvImpl() {
if (is_xfrin_connection_established_) {
session_with_xfrin_.disconnect();
is_xfrin_connection_established_ = false;
}
}
AuthSrv::AuthSrv() : impl_(new AuthSrvImpl) {
}
......@@ -237,7 +248,9 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
// Perform further protocol-level validation.
// In this implementation, we only support normal queries
if (message.getOpcode() != Opcode::QUERY()) {
if (message.getOpcode() == Opcode::NOTIFY()) {
return (impl_->processNotify(io_message, message, response_renderer));
} else if (message.getOpcode() != Opcode::QUERY()) {
if (impl_->verbose_mode_) {
cerr << "[b10-auth] unsupported opcode" << endl;
}
......@@ -255,9 +268,11 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
ConstQuestionPtr question = *message.beginQuestion();
const RRType &qtype = question->getType();
if (qtype == RRType::AXFR()) {
return (impl_->processAxfrQuery(io_message));
return (impl_->processAxfrQuery(io_message, message, response_renderer));
} else if (qtype == RRType::IXFR()) {
return (impl_->processIxfrQuery(io_message, question));
makeErrorMessage(message, response_renderer, Rcode::NOTIMP(),
impl_->verbose_mode_);
return (true);
} else {
return (impl_->processNormalQuery(io_message, message,
response_renderer));
......@@ -305,11 +320,18 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
#ifdef USE_XFROUT
bool
AuthSrvImpl::processAxfrQuery(const IOMessage& io_message) const {
XfroutClient xfr_client(xfr_path_);
// XXX: should reject AXFR/UDP here.
AuthSrvImpl::processAxfrQuery(const IOMessage& io_message, Message& message,
MessageRenderer& response_renderer) const {
if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
if (verbose_mode_) {
cerr << "[b10-auth] user query axfr through udp which isn't allowed"
<< endl;
}
makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),verbose_mode_);
return true;
}
XfroutClient xfr_client(xfr_path_);
try {
xfr_client.connect();
xfr_client.sendXfroutRequestInfo(io_message.getSocket().getNative(),
......@@ -321,14 +343,14 @@ AuthSrvImpl::processAxfrQuery(const IOMessage& io_message) const {
cerr << "[b10-auth] Error in handling XFR request: " << err.what()
<< endl;
}
// XXX: should return an error (SERVFAIL?)
makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),verbose_mode_);
}
return (false);
return (true);
}
#else
bool
AuthSrvImpl::processAxfrQuery(const IOMessage& io_message UNUSED_PARAM) const {
AuthSrvImpl::processAxfrQuery(const IOMessage& io_message UNUSED_PARAM, Message& message UNUSED_PARAM,
MessageRenderer& response_renderer UNUSED_PARAM) const {
// should better to return an error message, but hopefully this case
// is short term workaround.
return (false);
......@@ -336,44 +358,66 @@ AuthSrvImpl::processAxfrQuery(const IOMessage& io_message UNUSED_PARAM) const {
#endif
bool
AuthSrvImpl::processIxfrQuery(const IOMessage& io_message,
const ConstQuestionPtr question) const
AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
MessageRenderer& response_renderer)
{
// 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();
if (!is_xfrin_connection_established_) {
try {
session_with_xfrin_.establish();
is_xfrin_connection_established_ = true;
} catch ( isc::cc::SessionError &err) {
if (verbose_mode_) {
cerr << "[b10-auth] Error in connection with xfrin module: " << err.what()
<< endl;
}
makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),
verbose_mode_);
is_xfrin_connection_established_ = false;
return (true);
}
}
// XXX: the following is super expensive.
ConstQuestionPtr question = *message.beginQuestion();
const string remote_ip_address =
io_message.getRemoteEndpoint().getAddress().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) {
static const string command_template("{\"command\": [\"notify\", {\"zone_name\" : \"*\", \"master_ip\" : \"&\"}]}");
static const size_t name_holder_pos = command_template.find("*");
static const size_t ip_addr_holder_from_end = command_template.length() - command_template.find("&");
string command = command_template;
command.replace(name_holder_pos, 1, question->getName().toText());
command.replace(command.length() - ip_addr_holder_from_end, 1, remote_ip_address);
ElementPtr notify_command = Element::createFromString(command);
try {
const unsigned int seq =
session_with_xfrin_.group_sendmsg(notify_command, "Xfrin");
ElementPtr env, answer;
session_with_xfrin_.group_recvmsg(env, answer, false, seq);
int rcode;
parseAnswer(rcode, answer);
} catch ( isc::cc::SessionError &err) {
if (verbose_mode_) {
cerr << "[b10-auth] Send message to xfrin module failed: " << err.what()
<< endl;
}
makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),
verbose_mode_);
return (true);
} catch ( CCSessionError &err) {
if (verbose_mode_) {
// XXX: should add the reason for the error
cerr << "[b10=auth] notify send failed" << endl;
cerr << "[b10-auth] Receive wrong response from xfrin module: " << err.what() << endl;
makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),
verbose_mode_);
}
// XXX: should return an error (SERVFAIL?)
return (true);
}
return (false);
message.makeResponse();
message.setRcode(Rcode::NOERROR());
message.toWire(response_renderer);
return (true);
}
ElementPtr
......
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