Parcourir la source

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
JINMEI Tatuya il y a 15 ans
Parent
commit
1d5ba709cb
2 fichiers modifiés avec 126 ajouts et 85 suppressions
  1. 12 78
      src/bin/auth/asio_link.cc
  2. 114 7
      src/bin/auth/auth_srv.cc

+ 12 - 78
src/bin/auth/asio_link.cc

@@ -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;
         }

+ 114 - 7
src/bin/auth/auth_srv.cc

@@ -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();