LCOV - code coverage report
Current view: top level - home/jelte/repos/coverage_bind10/src/bin/auth - auth_srv.cc (source / functions) Hit Total Coverage
Test: report.info Lines: 306 338 90.5 %
Date: 2012-05-15 Functions: 41 47 87.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 399 767 52.0 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
       2                 :            : //
       3                 :            : // Permission to use, copy, modify, and/or distribute this software for any
       4                 :            : // purpose with or without fee is hereby granted, provided that the above
       5                 :            : // copyright notice and this permission notice appear in all copies.
       6                 :            : //
       7                 :            : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       8                 :            : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
       9                 :            : // AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      10                 :            : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      11                 :            : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      12                 :            : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      13                 :            : // PERFORMANCE OF THIS SOFTWARE.
      14                 :            : 
      15                 :            : #include <config.h>
      16                 :            : 
      17                 :            : #include <sys/types.h>
      18                 :            : #include <netinet/in.h>
      19                 :            : 
      20                 :            : #include <algorithm>
      21                 :            : #include <cassert>
      22                 :            : #include <iostream>
      23                 :            : #include <vector>
      24                 :            : #include <memory>
      25                 :            : 
      26                 :            : #include <boost/bind.hpp>
      27                 :            : 
      28                 :            : #include <asiolink/asiolink.h>
      29                 :            : 
      30                 :            : #include <config/ccsession.h>
      31                 :            : 
      32                 :            : #include <cc/data.h>
      33                 :            : 
      34                 :            : #include <exceptions/exceptions.h>
      35                 :            : 
      36                 :            : #include <util/buffer.h>
      37                 :            : 
      38                 :            : #include <dns/edns.h>
      39                 :            : #include <dns/exceptions.h>
      40                 :            : #include <dns/messagerenderer.h>
      41                 :            : #include <dns/name.h>
      42                 :            : #include <dns/question.h>
      43                 :            : #include <dns/opcode.h>
      44                 :            : #include <dns/rcode.h>
      45                 :            : #include <dns/rrset.h>
      46                 :            : #include <dns/rrttl.h>
      47                 :            : #include <dns/message.h>
      48                 :            : #include <dns/tsig.h>
      49                 :            : 
      50                 :            : #include <asiodns/dns_service.h>
      51                 :            : 
      52                 :            : #include <datasrc/query.h>
      53                 :            : #include <datasrc/data_source.h>
      54                 :            : #include <datasrc/memory_datasrc.h>
      55                 :            : #include <datasrc/static_datasrc.h>
      56                 :            : #include <datasrc/sqlite3_datasrc.h>
      57                 :            : 
      58                 :            : #include <xfr/xfrout_client.h>
      59                 :            : 
      60                 :            : #include <auth/common.h>
      61                 :            : #include <auth/auth_config.h>
      62                 :            : #include <auth/auth_srv.h>
      63                 :            : #include <auth/query.h>
      64                 :            : #include <auth/statistics.h>
      65                 :            : #include <auth/auth_log.h>
      66                 :            : 
      67                 :            : using namespace std;
      68                 :            : 
      69                 :            : using namespace isc;
      70                 :            : using namespace isc::cc;
      71                 :            : using namespace isc::datasrc;
      72                 :            : using namespace isc::dns;
      73                 :            : using namespace isc::util;
      74                 :            : using namespace isc::auth;
      75                 :            : using namespace isc::dns::rdata;
      76                 :            : using namespace isc::data;
      77                 :            : using namespace isc::config;
      78                 :            : using namespace isc::xfr;
      79                 :            : using namespace isc::asiolink;
      80                 :            : using namespace isc::asiodns;
      81                 :            : using namespace isc::server_common::portconfig;
      82                 :            : 
      83                 :            : namespace {
      84                 :            : // A helper class for cleaning up message renderer.
      85                 :            : //
      86                 :            : // A temporary object of this class is expected to be created before starting
      87                 :            : // response message rendering.  On construction, it (re)initialize the given
      88                 :            : // message renderer with the given buffer.  On destruction, it releases
      89                 :            : // the previously set buffer and then release any internal resource in the
      90                 :            : // renderer, no matter what happened during the rendering, especially even
      91                 :            : // when it resulted in an exception.
      92                 :            : //
      93                 :            : // Note: if we need this helper in many other places we might consider making
      94                 :            : // it visible to other modules.  As of this implementation this is the only
      95                 :            : // user of this class, so we hide it within the implementation.
      96                 :            : class RendererHolder {
      97                 :            : public:
      98                 :            :     RendererHolder(MessageRenderer& renderer, OutputBuffer* buffer) :
      99                 :        200 :         renderer_(renderer)
     100                 :            :     {
     101 [ +  - ][ +  - ]:        200 :         renderer.setBuffer(buffer);
                 [ +  - ]
     102                 :            :     }
     103                 :        200 :     ~RendererHolder() {
     104                 :        200 :         renderer_.setBuffer(NULL);
     105                 :        200 :         renderer_.clear();
     106                 :        200 :     }
     107                 :            : private:
     108                 :            :     MessageRenderer& renderer_;
     109                 :            : };
     110                 :            : }
     111                 :            : 
     112                 :            : class AuthSrvImpl {
     113                 :            : private:
     114                 :            :     // prohibit copy
     115                 :            :     AuthSrvImpl(const AuthSrvImpl& source);
     116                 :            :     AuthSrvImpl& operator=(const AuthSrvImpl& source);
     117                 :            : public:
     118                 :            :     AuthSrvImpl(const bool use_cache, AbstractXfroutClient& xfrout_client);
     119                 :            :     ~AuthSrvImpl();
     120                 :            :     isc::data::ConstElementPtr setDbFile(isc::data::ConstElementPtr config);
     121                 :            : 
     122                 :            :     bool processNormalQuery(const IOMessage& io_message, Message& message,
     123                 :            :                             OutputBuffer& buffer,
     124                 :            :                             auto_ptr<TSIGContext> tsig_context);
     125                 :            :     bool processXfrQuery(const IOMessage& io_message, Message& message,
     126                 :            :                          OutputBuffer& buffer,
     127                 :            :                          auto_ptr<TSIGContext> tsig_context);
     128                 :            :     bool processNotify(const IOMessage& io_message, Message& message,
     129                 :            :                        OutputBuffer& buffer,
     130                 :            :                        auto_ptr<TSIGContext> tsig_context);
     131                 :            : 
     132                 :            :     IOService io_service_;
     133                 :            : 
     134                 :            :     MessageRenderer renderer_;
     135                 :            :     /// Currently non-configurable, but will be.
     136                 :            :     static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
     137                 :            : 
     138                 :            :     /// These members are public because AuthSrv accesses them directly.
     139                 :            :     ModuleCCSession* config_session_;
     140                 :            :     AbstractSession* xfrin_session_;
     141                 :            : 
     142                 :            :     /// In-memory data source.  Currently class IN only for simplicity.
     143                 :            :     const RRClass memory_client_class_;
     144                 :            :     AuthSrv::InMemoryClientPtr memory_client_;
     145                 :            : 
     146                 :            :     /// Hot spot cache
     147                 :            :     isc::datasrc::HotCache cache_;
     148                 :            : 
     149                 :            :     /// Interval timer for periodic submission of statistics counters.
     150                 :            :     IntervalTimer statistics_timer_;
     151                 :            : 
     152                 :            :     /// Query counters for statistics
     153                 :            :     AuthCounters counters_;
     154                 :            : 
     155                 :            :     /// Addresses we listen on
     156                 :            :     AddressList listen_addresses_;
     157                 :            : 
     158                 :            :     /// The TSIG keyring
     159                 :            :     const boost::shared_ptr<TSIGKeyRing>* keyring_;
     160                 :            : 
     161                 :            :     /// Bind the ModuleSpec object in config_session_ with
     162                 :            :     /// isc:config::ModuleSpec::validateStatistics.
     163                 :            :     void registerStatisticsValidator();
     164                 :            : 
     165                 :            :     /// \brief Resume the server
     166                 :            :     ///
     167                 :            :     /// This is a wrapper call for DNSServer::resume(done), if 'done' is true,
     168                 :            :     /// the Rcode set in the given Message is counted in the statistics
     169                 :            :     /// counter.
     170                 :            :     ///
     171                 :            :     /// This method is expected to be called by processMessage()
     172                 :            :     ///
     173                 :            :     /// \param server The DNSServer as passed to processMessage()
     174                 :            :     /// \param message The response as constructed by processMessage()
     175                 :            :     /// \param done If true, the Rcode from the given message is counted,
     176                 :            :     ///             this value is then passed to server->resume(bool)
     177                 :            :     void resumeServer(isc::asiodns::DNSServer* server,
     178                 :            :                       isc::dns::Message& message,
     179                 :            :                       bool done);
     180                 :            : private:
     181                 :            :     std::string db_file_;
     182                 :            : 
     183                 :            :     MetaDataSrc data_sources_;
     184                 :            :     /// We keep a pointer to the currently running sqlite datasource
     185                 :            :     /// so that we can specifically remove that one should the database
     186                 :            :     /// file change
     187                 :            :     ConstDataSrcPtr cur_datasrc_;
     188                 :            : 
     189                 :            :     bool xfrout_connected_;
     190                 :            :     AbstractXfroutClient& xfrout_client_;
     191                 :            : 
     192                 :            :     /// Increment query counter
     193                 :            :     void incCounter(const int protocol);
     194                 :            : 
     195                 :            :     // validateStatistics
     196                 :            :     bool validateStatistics(isc::data::ConstElementPtr data) const;
     197                 :            : 
     198                 :            :     auth::Query query_;
     199                 :            : };
     200                 :            : 
     201                 :         94 : AuthSrvImpl::AuthSrvImpl(const bool use_cache,
     202                 :            :                          AbstractXfroutClient& xfrout_client) :
     203                 :            :     config_session_(NULL),
     204                 :            :     xfrin_session_(NULL),
     205                 :            :     memory_client_class_(RRClass::IN()),
     206                 :            :     statistics_timer_(io_service_),
     207                 :            :     counters_(),
     208                 :            :     keyring_(NULL),
     209                 :            :     xfrout_connected_(false),
     210 [ +  - ][ +  - ]:        188 :     xfrout_client_(xfrout_client)
         [ +  - ][ +  - ]
     211                 :            : {
     212                 :            :     // cur_datasrc_ is automatically initialized by the default constructor,
     213                 :            :     // effectively being an empty (sqlite) data source.  once ccsession is up
     214                 :            :     // the datasource will be set by the configuration setting
     215                 :            : 
     216                 :            :     // add static data source
     217 [ +  - ][ +  - ]:        188 :     data_sources_.addDataSrc(ConstDataSrcPtr(new StaticDataSrc));
                 [ +  - ]
     218                 :            : 
     219                 :            :     // enable or disable the cache
     220         [ +  - ]:         94 :     cache_.setEnabled(use_cache);
     221                 :         94 : }
     222                 :            : 
     223 [ +  - ][ +  - ]:        282 : AuthSrvImpl::~AuthSrvImpl() {
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     224         [ +  + ]:         94 :     if (xfrout_connected_) {
     225         [ +  - ]:          5 :         xfrout_client_.disconnect();
     226                 :          5 :         xfrout_connected_ = false;
     227                 :            :     }
     228                 :         94 : }
     229                 :            : 
     230                 :            : // This is a derived class of \c DNSLookup, to serve as a
     231                 :            : // callback in the asiolink module.  It calls
     232                 :            : // AuthSrv::processMessage() on a single DNS message.
     233                 :         94 : class MessageLookup : public DNSLookup {
     234                 :            : public:
     235                 :        188 :     MessageLookup(AuthSrv* srv) : server_(srv) {}
     236                 :          2 :     virtual void operator()(const IOMessage& io_message,
     237                 :            :                             MessagePtr message,
     238                 :            :                             MessagePtr, // Not used here
     239                 :            :                             OutputBufferPtr buffer,
     240                 :            :                             DNSServer* server) const
     241                 :            :     {
     242                 :          2 :         server_->processMessage(io_message, *message, *buffer, server);
     243                 :          2 :     }
     244                 :            : private:
     245                 :            :     AuthSrv* server_;
     246                 :            : };
     247                 :            : 
     248                 :            : // This is a derived class of \c DNSAnswer, to serve as a callback in the
     249                 :            : // asiolink module.  We actually shouldn't do anything in this class because
     250                 :            : // we build complete response messages in the process methods; otherwise
     251                 :            : // the response message will contain trailing garbage.  In future, we should
     252                 :            : // probably even drop the reliance on DNSAnswer.  We don't need the coroutine
     253                 :            : // tricks provided in that framework, and its overhead would be significant
     254                 :            : // in terms of performance consideration for the authoritative server
     255                 :            : // implementation.
     256                 :         94 : class MessageAnswer : public DNSAnswer {
     257                 :            : public:
     258                 :          0 :     MessageAnswer(AuthSrv*) {}
     259                 :          2 :     virtual void operator()(const IOMessage&, MessagePtr,
     260                 :            :                             MessagePtr, OutputBufferPtr) const
     261                 :          2 :     {}
     262                 :            : };
     263                 :            : 
     264                 :            : // This is a derived class of \c SimpleCallback, to serve
     265                 :            : // as a callback in the asiolink module.  It checks for queued
     266                 :            : // configuration messages, and executes them if found.
     267                 :         94 : class ConfigChecker : public SimpleCallback {
     268                 :            : public:
     269                 :        188 :     ConfigChecker(AuthSrv* srv) : server_(srv) {}
     270                 :          0 :     virtual void operator()(const IOMessage&) const {
     271                 :          0 :         ModuleCCSession* cfg_session = server_->getConfigSession();
     272 [ #  # ][ #  # ]:          0 :         if (cfg_session != NULL && cfg_session->hasQueuedMsgs()) {
                 [ #  # ]
     273                 :          0 :             cfg_session->checkCommand();
     274                 :            :         }
     275                 :          0 :     }
     276                 :            : private:
     277                 :            :     AuthSrv* server_;
     278                 :            : };
     279                 :            : 
     280                 :         94 : AuthSrv::AuthSrv(const bool use_cache, AbstractXfroutClient& xfrout_client)
     281                 :            : {
     282         [ +  - ]:         94 :     impl_ = new AuthSrvImpl(use_cache, xfrout_client);
     283                 :         94 :     checkin_ = new ConfigChecker(this);
     284                 :         94 :     dns_lookup_ = new MessageLookup(this);
     285                 :         94 :     dns_answer_ = new MessageAnswer(this);
     286                 :         94 : }
     287                 :            : 
     288                 :            : void
     289                 :          4 : AuthSrv::stop() {
     290                 :          4 :     impl_->io_service_.stop();
     291                 :          4 : }
     292                 :            : 
     293                 :         94 : AuthSrv::~AuthSrv() {
     294         [ +  - ]:         94 :     delete impl_;
     295         [ +  - ]:         94 :     delete checkin_;
     296         [ +  - ]:         94 :     delete dns_lookup_;
     297         [ +  - ]:         94 :     delete dns_answer_;
     298                 :         94 : }
     299                 :            : 
     300                 :            : namespace {
     301                 :            : class QuestionInserter {
     302                 :            : public:
     303                 :        178 :     QuestionInserter(Message& message) : message_(message) {}
     304                 :            :     void operator()(const QuestionPtr question) {
     305         [ +  - ]:         32 :         message_.addQuestion(question);
     306                 :            :     }
     307                 :            :     Message& message_;
     308                 :            : };
     309                 :            : 
     310                 :            : void
     311                 :        178 : makeErrorMessage(MessageRenderer& renderer, Message& message,
     312                 :            :                  OutputBuffer& buffer, const Rcode& rcode,
     313                 :            :                  std::auto_ptr<TSIGContext> tsig_context =
     314                 :            :                  std::auto_ptr<TSIGContext>())
     315                 :            : {
     316                 :            :     // extract the parameters that should be kept.
     317                 :            :     // XXX: with the current implementation, it's not easy to set EDNS0
     318                 :            :     // depending on whether the query had it.  So we'll simply omit it.
     319                 :        178 :     const qid_t qid = message.getQid();
     320                 :        178 :     const bool rd = message.getHeaderFlag(Message::HEADERFLAG_RD);
     321                 :        178 :     const bool cd = message.getHeaderFlag(Message::HEADERFLAG_CD);
     322                 :        178 :     const Opcode& opcode = message.getOpcode();
     323                 :        178 :     vector<QuestionPtr> questions;
     324                 :            : 
     325                 :            :     // If this is an error to a query or notify, we should also copy the
     326                 :            :     // question section.
     327 [ +  - ][ +  + ]:        178 :     if (opcode == Opcode::QUERY() || opcode == Opcode::NOTIFY()) {
         [ +  - ][ +  + ]
                 [ +  + ]
     328 [ +  - ][ +  - ]:         32 :         questions.assign(message.beginQuestion(), message.endQuestion());
         [ +  - ][ +  - ]
                 [ +  - ]
     329                 :            :     }
     330                 :            : 
     331         [ +  - ]:        178 :     message.clear(Message::RENDER);
     332         [ +  - ]:        178 :     message.setQid(qid);
     333         [ +  - ]:        178 :     message.setOpcode(opcode);
     334         [ +  - ]:        178 :     message.setHeaderFlag(Message::HEADERFLAG_QR);
     335         [ -  + ]:        178 :     if (rd) {
     336         [ #  # ]:          0 :         message.setHeaderFlag(Message::HEADERFLAG_RD);
     337                 :            :     }
     338         [ -  + ]:        178 :     if (cd) {
     339         [ #  # ]:          0 :         message.setHeaderFlag(Message::HEADERFLAG_CD);
     340                 :            :     }
     341         [ +  - ]:        178 :     for_each(questions.begin(), questions.end(), QuestionInserter(message));
     342                 :            : 
     343         [ +  - ]:        178 :     message.setRcode(rcode);
     344                 :            :     
     345         [ +  - ]:        178 :     RendererHolder holder(renderer, &buffer);
     346         [ +  + ]:        178 :     if (tsig_context.get() != NULL) {
     347         [ +  - ]:          3 :         message.toWire(renderer, *tsig_context);
     348                 :            :     } else {
     349         [ +  - ]:        175 :         message.toWire(renderer);
     350                 :            :     }
     351 [ +  - ][ +  - ]:        356 :     LOG_DEBUG(auth_logger, DBG_AUTH_MESSAGES, AUTH_SEND_ERROR_RESPONSE)
                 [ +  - ]
     352 [ +  - ][ +  - ]:        178 :               .arg(renderer.getLength()).arg(message);
                 [ +  - ]
     353                 :        178 : }
     354                 :            : }
     355                 :            : 
     356                 :            : IOService&
     357                 :         17 : AuthSrv::getIOService() {
     358                 :         17 :     return (impl_->io_service_);
     359                 :            : }
     360                 :            : 
     361                 :            : void
     362                 :          2 : AuthSrv::setCacheSlots(const size_t slots) {
     363                 :          2 :     impl_->cache_.setSlots(slots);
     364                 :          2 : }
     365                 :            : 
     366                 :            : size_t
     367                 :          2 : AuthSrv::getCacheSlots() const {
     368                 :          2 :     return (impl_->cache_.getSlots());
     369                 :            : }
     370                 :            : 
     371                 :            : void
     372                 :         57 : AuthSrv::setXfrinSession(AbstractSession* xfrin_session) {
     373                 :         57 :     impl_->xfrin_session_ = xfrin_session;
     374                 :         57 : }
     375                 :            : 
     376                 :            : void
     377                 :          1 : AuthSrv::setConfigSession(ModuleCCSession* config_session) {
     378                 :          1 :     impl_->config_session_ = config_session;
     379                 :          1 :     impl_->registerStatisticsValidator();
     380                 :          1 : }
     381                 :            : 
     382                 :            : void
     383                 :         69 : AuthSrv::setStatisticsSession(AbstractSession* statistics_session) {
     384                 :         69 :     impl_->counters_.setStatisticsSession(statistics_session);
     385                 :         69 : }
     386                 :            : 
     387                 :            : ModuleCCSession*
     388                 :         11 : AuthSrv::getConfigSession() const {
     389                 :         11 :     return (impl_->config_session_);
     390                 :            : }
     391                 :            : 
     392                 :            : AuthSrv::InMemoryClientPtr
     393                 :        148 : AuthSrv::getInMemoryClient(const RRClass& rrclass) {
     394                 :            :     // XXX: for simplicity, we only support the IN class right now.
     395         [ +  + ]:        148 :     if (rrclass != impl_->memory_client_class_) {
     396 [ +  - ][ +  - ]:          4 :         isc_throw(InvalidParameter,
     397                 :            :                   "Memory data source is not supported for RR class "
     398                 :            :                   << rrclass);
     399                 :            :     }
     400                 :        146 :     return (impl_->memory_client_);
     401                 :            : }
     402                 :            : 
     403                 :            : void
     404                 :         74 : AuthSrv::setInMemoryClient(const isc::dns::RRClass& rrclass,
     405                 :            :                            InMemoryClientPtr memory_client)
     406                 :            : {
     407                 :            :     // XXX: see above
     408         [ -  + ]:         74 :     if (rrclass != impl_->memory_client_class_) {
     409 [ #  # ][ #  # ]:          0 :         isc_throw(InvalidParameter,
     410                 :            :                   "Memory data source is not supported for RR class "
     411                 :            :                   << rrclass);
     412 [ +  + ][ +  + ]:        128 :     } else if (!impl_->memory_client_ && memory_client) {
                 [ +  + ]
     413         [ +  - ]:         62 :         LOG_DEBUG(auth_logger, DBG_AUTH_OPS, AUTH_MEM_DATASRC_ENABLED)
     414         [ +  - ]:         31 :                   .arg(rrclass);
     415 [ +  + ][ +  + ]:         43 :     } else if (impl_->memory_client_ && !memory_client) {
                 [ +  + ]
     416         [ +  - ]:         18 :         LOG_DEBUG(auth_logger, DBG_AUTH_OPS, AUTH_MEM_DATASRC_DISABLED)
     417         [ +  - ]:          9 :                   .arg(rrclass);
     418                 :            :     }
     419                 :         74 :     impl_->memory_client_ = memory_client;
     420                 :         74 : }
     421                 :            : 
     422                 :            : uint32_t
     423                 :          4 : AuthSrv::getStatisticsTimerInterval() const {
     424                 :          4 :     return (impl_->statistics_timer_.getInterval() / 1000);
     425                 :            : }
     426                 :            : 
     427                 :            : void
     428                 :          3 : AuthSrv::setStatisticsTimerInterval(uint32_t interval) {
     429         [ +  - ]:          3 :     if (interval == impl_->statistics_timer_.getInterval()) {
     430                 :          3 :         return;
     431                 :            :     }
     432         [ -  + ]:          3 :     if (interval > 86400) {
     433                 :            :         // It can't occur since the value is checked in
     434                 :            :         // statisticsIntervalConfig::build().
     435         [ #  # ]:          0 :         isc_throw(InvalidParameter, "Too long interval: " << interval);
     436                 :            :     }
     437         [ +  + ]:          3 :     if (interval == 0) {
     438                 :          1 :         impl_->statistics_timer_.cancel();
     439         [ +  - ]:          1 :         LOG_DEBUG(auth_logger, DBG_AUTH_OPS, AUTH_STATS_TIMER_DISABLED);
     440                 :            :     } else {
     441                 :            :         impl_->statistics_timer_.setup(boost::bind(&AuthSrv::submitStatistics,
     442                 :          2 :                                                    this),
     443         [ +  - ]:          2 :                                        interval * 1000);
     444         [ +  - ]:          4 :         LOG_DEBUG(auth_logger, DBG_AUTH_OPS, AUTH_STATS_TIMER_SET)
     445         [ +  - ]:          2 :                   .arg(interval);
     446                 :            :     }
     447                 :            : }
     448                 :            : 
     449                 :            : void
     450                 :        212 : AuthSrv::processMessage(const IOMessage& io_message, Message& message,
     451                 :            :                         OutputBuffer& buffer, DNSServer* server)
     452                 :            : {
     453                 :        212 :     InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
     454                 :            : 
     455                 :            :     // First, check the header part.  If we fail even for the base header,
     456                 :            :     // just drop the message.
     457                 :            :     try {
     458         [ +  + ]:        212 :         message.parseHeader(request_buffer);
     459                 :            : 
     460                 :            :         // Ignore all responses.
     461 [ +  - ][ +  + ]:        211 :         if (message.getHeaderFlag(Message::HEADERFLAG_QR)) {
     462 [ +  - ][ +  - ]:          3 :             LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RESPONSE_RECEIVED);
         [ +  - ][ +  - ]
     463         [ +  - ]:          3 :             impl_->resumeServer(server, message, false);
     464                 :            :             return;
     465                 :            :         }
     466         [ -  + ]:          2 :     } catch (const Exception& ex) {
     467 [ -  + ][ +  - ]:          2 :         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_HEADER_PARSE_FAIL)
                 [ -  + ]
     468 [ -  + ][ -  + ]:          1 :                   .arg(ex.what());
     469         [ -  + ]:          1 :         impl_->resumeServer(server, message, false);
     470                 :            :         return;
     471                 :            :     }
     472                 :            : 
     473                 :            :     try {
     474                 :            :         // Parse the message.
     475         [ +  + ]:        208 :         message.fromWire(request_buffer);
     476                 :          6 :     } catch (const DNSProtocolError& error) {
     477 [ -  + ][ +  - ]:          6 :         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_PACKET_PROTOCOL_ERROR)
                 [ -  + ]
     478 [ -  + ][ -  + ]:          6 :                   .arg(error.getRcode().toText()).arg(error.what());
         [ -  + ][ -  + ]
                 [ -  + ]
     479 [ -  + ][ -  + ]:          3 :         makeErrorMessage(impl_->renderer_, message, buffer, error.getRcode());
         [ -  + ][ -  + ]
     480         [ -  + ]:          3 :         impl_->resumeServer(server, message, true);
     481                 :            :         return;
     482      [ -  +  - ]:          3 :     } catch (const Exception& ex) {
     483 [ #  # ][ #  # ]:          0 :         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_PACKET_PARSE_ERROR)
                 [ #  # ]
     484 [ #  # ][ #  # ]:          0 :                   .arg(ex.what());
     485 [ #  # ][ #  # ]:          0 :         makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
         [ #  # ][ #  # ]
     486         [ #  # ]:          0 :         impl_->resumeServer(server, message, true);
     487                 :            :         return;
     488                 :            :     } // other exceptions will be handled at a higher layer.
     489                 :            : 
     490         [ +  - ]:        410 :     LOG_DEBUG(auth_logger, DBG_AUTH_MESSAGES, AUTH_PACKET_RECEIVED)
     491         [ +  - ]:        205 :               .arg(message);
     492                 :            : 
     493                 :            :     // Perform further protocol-level validation.
     494                 :            :     // TSIG first
     495                 :            :     // If this is set to something, we know we need to answer with TSIG as well
     496                 :        212 :     std::auto_ptr<TSIGContext> tsig_context;
     497         [ +  - ]:        205 :     const TSIGRecord* tsig_record(message.getTSIGRecord());
     498         [ +  - ]:        205 :     TSIGError tsig_error(TSIGError::NOERROR());
     499                 :            : 
     500                 :            :     // Do we do TSIG?
     501                 :            :     // The keyring can be null if we're in test
     502         [ +  + ]:        205 :     if (impl_->keyring_ != NULL && tsig_record != NULL) {
     503                 :            :         tsig_context.reset(new TSIGContext(tsig_record->getName(),
     504                 :          4 :                                            tsig_record->getRdata().
     505                 :            :                                                 getAlgorithm(),
     506 [ +  - ][ +  - ]:          8 :                                            **impl_->keyring_));
                 [ +  - ]
     507                 :            :         tsig_error = tsig_context->verify(tsig_record, io_message.getData(),
     508         [ +  - ]:          4 :                                           io_message.getDataSize());
     509                 :            :     }
     510                 :            : 
     511 [ +  - ][ +  + ]:        205 :     if (tsig_error != TSIGError::NOERROR()) {
     512                 :            :         makeErrorMessage(impl_->renderer_, message, buffer,
     513 [ +  - ][ +  - ]:          3 :                          tsig_error.toRcode(), tsig_context);
                 [ +  - ]
     514         [ +  - ]:          3 :         impl_->resumeServer(server, message, true);
     515                 :            :         return;
     516                 :            :     }
     517                 :            : 
     518                 :        202 :     bool send_answer = true;
     519                 :            :     try {
     520                 :            :         // update per opcode statistics counter.  This can only be reliable
     521                 :            :         // after TSIG check succeeds.
     522 [ +  - ][ +  - ]:        202 :         impl_->counters_.inc(message.getOpcode());
     523                 :            : 
     524 [ +  - ][ +  - ]:        202 :         if (message.getOpcode() == Opcode::NOTIFY()) {
                 [ +  + ]
     525                 :            :             send_answer = impl_->processNotify(io_message, message, buffer,
     526 [ +  - ][ +  - ]:         17 :                                                tsig_context);
     527 [ +  - ][ +  - ]:        185 :         } else if (message.getOpcode() != Opcode::QUERY()) {
                 [ +  + ]
     528 [ +  - ][ +  - ]:        290 :             LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_UNSUPPORTED_OPCODE)
                 [ +  - ]
     529 [ +  - ][ +  - ]:        290 :                       .arg(message.getOpcode().toText());
         [ +  - ][ +  - ]
     530                 :            :             makeErrorMessage(impl_->renderer_, message, buffer,
     531 [ +  - ][ +  - ]:        145 :                              Rcode::NOTIMP(), tsig_context);
     532 [ +  - ][ +  + ]:         40 :         } else if (message.getRRCount(Message::SECTION_QUESTION) != 1) {
     533                 :            :             makeErrorMessage(impl_->renderer_, message, buffer,
     534 [ +  - ][ +  - ]:          1 :                              Rcode::FORMERR(), tsig_context);
                 [ +  - ]
     535                 :            :         } else {
     536 [ +  - ][ +  - ]:         78 :             ConstQuestionPtr question = *message.beginQuestion();
                 [ +  - ]
     537                 :         39 :             const RRType &qtype = question->getType();
     538         [ +  + ]:         39 :             if (qtype == RRType::AXFR()) {
     539                 :            :                 send_answer = impl_->processXfrQuery(io_message, message,
     540 [ +  + ][ +  - ]:          7 :                                                      buffer, tsig_context);
     541         [ +  + ]:         32 :             } else if (qtype == RRType::IXFR()) {
     542                 :            :                 send_answer = impl_->processXfrQuery(io_message, message,
     543 [ +  + ][ +  - ]:          5 :                                                      buffer, tsig_context);
     544                 :            :             } else {
     545                 :            :                 send_answer = impl_->processNormalQuery(io_message, message,
     546 [ +  + ][ +  - ]:         27 :                                                         buffer, tsig_context);
     547                 :            :             }
     548                 :            :         }
     549                 :         16 :     } catch (const std::exception& ex) {
     550 [ -  + ][ +  - ]:         16 :         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RESPONSE_FAILURE)
                 [ -  + ]
     551 [ -  + ][ -  + ]:          8 :                   .arg(ex.what());
     552 [ -  + ][ -  + ]:          8 :         makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
         [ -  + ][ -  + ]
     553 [ +  - ][ #  # ]:          8 :     } catch (...) {
     554 [ #  # ][ #  # ]:          0 :         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RESPONSE_FAILURE_UNKNOWN);
         [ #  # ][ #  # ]
     555 [ #  # ][ #  # ]:          0 :         makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
         [ #  # ][ #  # ]
     556                 :            :     }
     557         [ +  - ]:        202 :     impl_->resumeServer(server, message, send_answer);
     558                 :            : }
     559                 :            : 
     560                 :            : bool
     561                 :         27 : AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
     562                 :            :                                 OutputBuffer& buffer,
     563                 :            :                                 auto_ptr<TSIGContext> tsig_context)
     564                 :            : {
     565                 :         27 :     ConstEDNSPtr remote_edns = message.getEDNS();
     566 [ +  + ][ -  + ]:         38 :     const bool dnssec_ok = remote_edns && remote_edns->getDNSSECAwareness();
     567                 :         11 :     const uint16_t remote_bufsize = remote_edns ? remote_edns->getUDPSize() :
     568         [ +  + ]:         27 :         Message::DEFAULT_MAX_UDPSIZE;
     569                 :            : 
     570         [ +  - ]:         27 :     message.makeResponse();
     571         [ +  - ]:         27 :     message.setHeaderFlag(Message::HEADERFLAG_AA);
     572 [ +  - ][ +  - ]:         27 :     message.setRcode(Rcode::NOERROR());
     573                 :            : 
     574                 :            :     // Increment query counter.
     575 [ +  - ][ +  - ]:         27 :     incCounter(io_message.getSocket().getProtocol());
     576                 :            : 
     577         [ +  + ]:         27 :     if (remote_edns) {
     578 [ +  - ][ +  - ]:         11 :         EDNSPtr local_edns = EDNSPtr(new EDNS());
     579                 :         22 :         local_edns->setDNSSECAwareness(dnssec_ok);
     580                 :         22 :         local_edns->setUDPSize(AuthSrvImpl::DEFAULT_LOCAL_UDPSIZE);
     581         [ +  - ]:         11 :         message.setEDNS(local_edns);
     582                 :            :     }
     583                 :            : 
     584                 :            :     try {
     585                 :            :         // If a memory data source is configured call the separate
     586                 :            :         // Query::process()
     587 [ +  - ][ +  - ]:         54 :         const ConstQuestionPtr question = *message.beginQuestion();
                 [ +  - ]
     588 [ +  + ][ +  + ]:         27 :         if (memory_client_ && memory_client_class_ == question->getClass()) {
                 [ +  + ]
     589                 :         15 :             const RRType& qtype = question->getType();
     590                 :         15 :             const Name& qname = question->getName();
     591         [ +  + ]:         15 :             query_.process(*memory_client_, qname, qtype, message, dnssec_ok);
     592                 :            :         } else {
     593 [ +  - ][ +  - ]:         24 :             datasrc::Query query(message, cache_, dnssec_ok);
     594         [ +  + ]:         12 :             data_sources_.doQuery(query);
     595                 :            :         }
     596         [ +  + ]:         14 :     } catch (const Exception& ex) {
     597 [ -  + ][ +  - ]:          5 :         LOG_ERROR(auth_logger, AUTH_PROCESS_FAIL).arg(ex.what());
         [ -  + ][ -  + ]
                 [ -  + ]
     598 [ -  + ][ -  + ]:          5 :         makeErrorMessage(renderer_, message, buffer, Rcode::SERVFAIL());
         [ -  + ][ -  + ]
     599                 :            :         return (true);
     600                 :            :     }
     601                 :            : 
     602         [ +  - ]:         18 :     RendererHolder holder(renderer_, &buffer);
     603                 :            :     const bool udp_buffer =
     604         [ +  - ]:         18 :         (io_message.getSocket().getProtocol() == IPPROTO_UDP);
     605 [ +  + ][ +  - ]:         18 :     renderer_.setLengthLimit(udp_buffer ? remote_bufsize : 65535);
     606         [ +  + ]:         18 :     if (tsig_context.get() != NULL) {
     607         [ +  - ]:          1 :         message.toWire(renderer_, *tsig_context);
     608                 :            :     } else {
     609         [ +  + ]:         17 :         message.toWire(renderer_);
     610                 :            :     }
     611 [ +  - ][ +  - ]:         32 :     LOG_DEBUG(auth_logger, DBG_AUTH_MESSAGES, AUTH_SEND_NORMAL_RESPONSE)
                 [ +  - ]
     612 [ +  - ][ +  - ]:         16 :               .arg(renderer_.getLength()).arg(message);
                 [ +  - ]
     613                 :            :     return (true);
     614                 :            : }
     615                 :            : 
     616                 :            : bool
     617                 :         12 : AuthSrvImpl::processXfrQuery(const IOMessage& io_message, Message& message,
     618                 :            :                              OutputBuffer& buffer,
     619                 :            :                              auto_ptr<TSIGContext> tsig_context)
     620                 :            : {
     621                 :            :     // Increment query counter.
     622                 :         12 :     incCounter(io_message.getSocket().getProtocol());
     623                 :            : 
     624         [ +  + ]:         12 :     if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
     625         [ +  - ]:          1 :         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_AXFR_UDP);
     626         [ +  - ]:          1 :         makeErrorMessage(renderer_, message, buffer, Rcode::FORMERR(),
     627         [ +  - ]:          1 :                          tsig_context);
     628                 :          1 :         return (true);
     629                 :            :     }
     630                 :            : 
     631                 :            :     try {
     632         [ +  + ]:         11 :         if (!xfrout_connected_) {
     633         [ +  + ]:          9 :             xfrout_client_.connect();
     634                 :          7 :             xfrout_connected_ = true;
     635                 :            :         }
     636                 :            :         xfrout_client_.sendXfroutRequestInfo(
     637                 :          9 :             io_message.getSocket().getNative(),
     638                 :            :             io_message.getData(),
     639 [ +  - ][ +  + ]:         14 :             io_message.getDataSize());
     640         [ -  + ]:         12 :     } catch (const XfroutError& err) {
     641         [ +  + ]:          6 :         if (xfrout_connected_) {
     642                 :            :             // disconnect() may trigger an exception, but since we try it
     643                 :            :             // only if we've successfully opened it, it shouldn't happen in
     644                 :            :             // normal condition.  Should this occur, we'll propagate it to the
     645                 :            :             // upper layer.
     646         [ +  + ]:          4 :             xfrout_client_.disconnect();
     647                 :          2 :             xfrout_connected_ = false;
     648                 :            :         }
     649                 :            : 
     650 [ -  + ][ +  - ]:          8 :         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_AXFR_ERROR)
                 [ -  + ]
     651 [ -  + ][ -  + ]:          4 :                   .arg(err.what());
     652         [ -  + ]:          4 :         makeErrorMessage(renderer_, message, buffer, Rcode::SERVFAIL(),
     653 [ -  + ][ -  + ]:          4 :                          tsig_context);
     654                 :            :         return (true);
     655                 :            :     }
     656                 :            : 
     657                 :            :     return (false);
     658                 :            : }
     659                 :            : 
     660                 :            : bool
     661                 :         17 : AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
     662                 :            :                            OutputBuffer& buffer,
     663                 :            :                            std::auto_ptr<TSIGContext> tsig_context)
     664                 :            : {
     665                 :            :     // The incoming notify must contain exactly one question for SOA of the
     666                 :            :     // zone name.
     667         [ +  + ]:         17 :     if (message.getRRCount(Message::SECTION_QUESTION) != 1) {
     668         [ +  - ]:          4 :         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_NOTIFY_QUESTIONS)
     669         [ +  - ]:          2 :                   .arg(message.getRRCount(Message::SECTION_QUESTION));
     670         [ +  - ]:          2 :         makeErrorMessage(renderer_, message, buffer, Rcode::FORMERR(),
     671         [ +  - ]:          2 :                          tsig_context);
     672                 :          2 :         return (true);
     673                 :            :     }
     674 [ +  - ][ +  - ]:         30 :     ConstQuestionPtr question = *message.beginQuestion();
     675         [ +  + ]:         15 :     if (question->getType() != RRType::SOA()) {
     676 [ +  - ][ +  - ]:         12 :         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_NOTIFY_RRTYPE)
                 [ +  - ]
     677 [ +  - ][ +  - ]:         12 :                   .arg(question->getType().toText());
                 [ +  - ]
     678         [ +  - ]:          6 :         makeErrorMessage(renderer_, message, buffer, Rcode::FORMERR(),
     679 [ +  - ][ +  - ]:          6 :                          tsig_context);
     680                 :            :         return (true);
     681                 :            :     }
     682                 :            : 
     683                 :            :     // According to RFC 1996, rcode should be "no error" and AA bit should be
     684                 :            :     // on, but we don't check these conditions.  This behavior is compatible
     685                 :            :     // with BIND 9.
     686                 :            : 
     687                 :            :     // TODO check with the conf-mgr whether current server is the auth of the
     688                 :            :     // zone
     689                 :            : 
     690                 :            :     // In the code that follows, we simply ignore the notify if any internal
     691                 :            :     // error happens rather than returning (e.g.) SERVFAIL.  RFC 1996 is
     692                 :            :     // silent about such cases, but there doesn't seem to be anything we can
     693                 :            :     // improve at the primary server side by sending an error anyway.
     694         [ +  + ]:          9 :     if (xfrin_session_ == NULL) {
     695 [ +  - ][ +  - ]:          1 :         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_NO_XFRIN);
         [ +  - ][ +  - ]
     696                 :            :         return (false);
     697                 :            :     }
     698                 :            : 
     699                 :            :     const string remote_ip_address =
     700 [ +  - ][ +  - ]:         16 :         io_message.getRemoteEndpoint().getAddress().toText();
     701                 :            :     static const string command_template_start =
     702 [ +  + ][ +  - ]:          8 :         "{\"command\": [\"notify\", {\"zone_name\" : \"";
                 [ +  - ]
     703 [ +  + ][ +  - ]:          8 :     static const string command_template_master = "\", \"master\" : \"";
                 [ +  - ]
     704 [ +  + ][ +  - ]:          8 :     static const string command_template_rrclass = "\", \"zone_class\" : \"";
                 [ +  - ]
     705 [ +  + ][ +  - ]:          8 :     static const string command_template_end = "\"}]}";
                 [ +  - ]
     706                 :            : 
     707                 :            :     try {
     708                 :            :         ConstElementPtr notify_command = Element::fromJSON(
     709                 :         16 :                 command_template_start + question->getName().toText() +
     710                 :          8 :                 command_template_master + remote_ip_address +
     711                 :         24 :                 command_template_rrclass + question->getClass().toText() +
     712   [ +  -  +  - ]:         24 :                 command_template_end);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     713                 :            :         const unsigned int seq =
     714                 :            :             xfrin_session_->group_sendmsg(notify_command, "Zonemgr",
     715 [ +  - ][ +  - ]:         24 :                                           "*", "*");
         [ +  - ][ +  + ]
     716                 :            :         ConstElementPtr env, answer, parsed_answer;
     717         [ +  + ]:          7 :         xfrin_session_->group_recvmsg(env, answer, false, seq);
     718                 :            :         int rcode;
     719 [ +  + ][ +  - ]:          6 :         parsed_answer = parseAnswer(rcode, answer);
     720         [ +  + ]:          5 :         if (rcode != 0) {
     721 [ +  - ][ +  - ]:          2 :             LOG_ERROR(auth_logger, AUTH_ZONEMGR_ERROR)
                 [ +  - ]
     722 [ +  - ][ +  - ]:          2 :                       .arg(parsed_answer->str());
                 [ +  - ]
     723                 :          1 :             return (false);
     724                 :            :         }
     725         [ -  + ]:          6 :     } catch (const Exception& ex) {
     726 [ -  + ][ +  - ]:          3 :         LOG_ERROR(auth_logger, AUTH_ZONEMGR_COMMS).arg(ex.what());
         [ -  + ][ -  + ]
                 [ -  + ]
     727                 :            :         return (false);
     728                 :            :     }
     729                 :            : 
     730         [ +  - ]:          4 :     message.makeResponse();
     731         [ +  - ]:          4 :     message.setHeaderFlag(Message::HEADERFLAG_AA);
     732 [ +  - ][ +  - ]:          4 :     message.setRcode(Rcode::NOERROR());
     733                 :            : 
     734         [ +  - ]:          4 :     RendererHolder holder(renderer_, &buffer);
     735         [ -  + ]:          4 :     if (tsig_context.get() != NULL) {
     736         [ #  # ]:          0 :         message.toWire(renderer_, *tsig_context);
     737                 :            :     } else {
     738         [ +  - ]:          4 :         message.toWire(renderer_);
     739                 :            :     }
     740                 :            :     return (true);
     741                 :            : }
     742                 :            : 
     743                 :            : void
     744                 :         39 : AuthSrvImpl::incCounter(const int protocol) {
     745                 :            :     // Increment query counter.
     746         [ +  + ]:         39 :     if (protocol == IPPROTO_UDP) {
     747                 :         27 :         counters_.inc(AuthCounters::SERVER_UDP_QUERY);
     748         [ +  - ]:         12 :     } else if (protocol == IPPROTO_TCP) {
     749                 :         12 :         counters_.inc(AuthCounters::SERVER_TCP_QUERY);
     750                 :            :     } else {
     751                 :            :         // unknown protocol
     752 [ #  # ][ #  # ]:          0 :         isc_throw(Unexpected, "Unknown protocol: " << protocol);
     753                 :            :     }
     754                 :         39 : }
     755                 :            : 
     756                 :            : void
     757                 :          1 : AuthSrvImpl::registerStatisticsValidator() {
     758                 :            :     counters_.registerStatisticsValidator(
     759         [ +  - ]:          2 :         boost::bind(&AuthSrvImpl::validateStatistics, this, _1));
     760                 :          1 : }
     761                 :            : 
     762                 :            : bool
     763                 :          0 : AuthSrvImpl::validateStatistics(isc::data::ConstElementPtr data) const {
     764         [ #  # ]:          0 :     if (config_session_ == NULL) {
     765                 :            :         return (false);
     766                 :            :     }
     767                 :            :     return (
     768                 :          0 :         config_session_->getModuleSpec().validateStatistics(
     769         [ #  # ]:          0 :             data, true));
     770                 :            : }
     771                 :            : 
     772                 :            : ConstElementPtr
     773                 :         20 : AuthSrvImpl::setDbFile(ConstElementPtr config) {
     774                 :         20 :     ConstElementPtr answer = isc::config::createAnswer();
     775                 :            : 
     776 [ +  - ][ +  - ]:         20 :     if (config && config->contains("database_file")) {
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
                 [ #  # ]
     777 [ +  - ][ +  - ]:         12 :         db_file_ = config->get("database_file")->stringValue();
                 [ +  - ]
     778         [ -  + ]:         16 :     } else if (config_session_ != NULL) {
     779                 :            :         bool is_default;
     780         [ #  # ]:          0 :         string item("database_file");
     781         [ #  # ]:          0 :         ConstElementPtr value = config_session_->getValue(is_default, item);
     782         [ #  # ]:          0 :         ElementPtr final = Element::createMap();
     783                 :            : 
     784                 :            :         // If the value is the default, and we are running from
     785                 :            :         // a specific directory ('from build'), we need to use
     786                 :            :         // a different value than the default (which may not exist)
     787                 :            :         // (btw, this should not be done here in the end, i think
     788                 :            :         //  the from-source script should have a check for this,
     789                 :            :         //  but for that we need offline access to config, so for
     790                 :            :         //  now this is a decent solution)
     791 [ #  # ][ #  # ]:          0 :         if (is_default && getenv("B10_FROM_BUILD")) {
                 [ #  # ]
     792                 :          0 :             value = Element::create(string(getenv("B10_FROM_BUILD")) +
     793 [ #  # ][ #  # ]:          0 :                                     "/bind10_zones.sqlite3");
                 [ #  # ]
     794                 :            :         }
     795         [ #  # ]:          0 :         final->set(item, value);
     796         [ #  # ]:          0 :         config = final;
     797                 :            : 
     798         [ #  # ]:          0 :         db_file_ = value->stringValue();
     799                 :            :     } else {
     800                 :            :         return (answer);
     801                 :            :     }
     802 [ +  - ][ +  - ]:          4 :     LOG_DEBUG(auth_logger, DBG_AUTH_OPS, AUTH_DATA_SOURCE).arg(db_file_);
         [ +  - ][ +  - ]
                 [ +  - ]
     803                 :            : 
     804                 :            :     // create SQL data source
     805                 :            :     // Note: the following step is tricky to be exception-safe and to ensure
     806                 :            :     // exception guarantee: We first need to perform all operations that can
     807                 :            :     // fail, while acquiring resources in the RAII manner.  We then perform
     808                 :            :     // delete and swap operations which should not fail.
     809 [ +  - ][ +  - ]:          4 :     DataSrcPtr datasrc_ptr(DataSrcPtr(new Sqlite3DataSrc));
     810         [ +  + ]:          4 :     datasrc_ptr->init(config);
     811         [ +  - ]:          3 :     data_sources_.addDataSrc(datasrc_ptr);
     812                 :            : 
     813                 :            :     // The following code should be exception free.
     814         [ -  + ]:          3 :     if (cur_datasrc_ != NULL) {
     815         [ #  # ]:          0 :         data_sources_.removeDataSrc(cur_datasrc_);
     816                 :            :     }
     817                 :          3 :     cur_datasrc_ = datasrc_ptr;
     818                 :            : 
     819                 :            :     return (answer);
     820                 :            : }
     821                 :            : 
     822                 :            : void
     823                 :        212 : AuthSrvImpl::resumeServer(DNSServer* server, Message& message, bool done) {
     824         [ +  + ]:        212 :     if (done) {
     825                 :        198 :         counters_.inc(message.getRcode());
     826                 :            :     }
     827                 :        212 :     server->resume(done);
     828                 :        212 : }
     829                 :            : 
     830                 :            : ConstElementPtr
     831                 :         27 : AuthSrv::updateConfig(ConstElementPtr new_config) {
     832                 :            :     try {
     833                 :            :         // the ModuleCCSession has already checked if we have
     834                 :            :         // the correct ElementPtr type as specified in our .spec file
     835         [ +  - ]:         27 :         if (new_config) {
     836         [ +  + ]:         27 :             configureAuthServer(*this, new_config);
     837                 :            :         }
     838         [ +  + ]:         20 :         return (impl_->setDbFile(new_config));
     839         [ -  + ]:         16 :     } catch (const isc::Exception& error) {
     840 [ -  + ][ +  - ]:          8 :         LOG_ERROR(auth_logger, AUTH_CONFIG_UPDATE_FAIL).arg(error.what());
         [ -  + ][ -  + ]
                 [ -  + ]
     841 [ -  + ][ -  + ]:          8 :         return (isc::config::createAnswer(1, error.what()));
     842                 :            :     }
     843                 :            : }
     844                 :            : 
     845                 :          1 : bool AuthSrv::submitStatistics() const {
     846                 :          1 :     return (impl_->counters_.submitStatistics());
     847                 :            : }
     848                 :            : 
     849                 :            : uint64_t
     850                 :          8 : AuthSrv::getCounter(const AuthCounters::ServerCounterType type) const {
     851                 :          8 :     return (impl_->counters_.getCounter(type));
     852                 :            : }
     853                 :            : 
     854                 :            : uint64_t
     855                 :         35 : AuthSrv::getCounter(const Opcode opcode) const {
     856                 :         35 :     return (impl_->counters_.getCounter(opcode));
     857                 :            : }
     858                 :            : 
     859                 :            : uint64_t
     860                 :        289 : AuthSrv::getCounter(const Rcode rcode) const {
     861                 :        289 :     return (impl_->counters_.getCounter(rcode));
     862                 :            : }
     863                 :            : 
     864                 :            : const AddressList&
     865                 :         13 : AuthSrv::getListenAddresses() const {
     866                 :         13 :     return (impl_->listen_addresses_);
     867                 :            : }
     868                 :            : 
     869                 :            : void
     870                 :          4 : AuthSrv::setListenAddresses(const AddressList& addresses) {
     871                 :            :     // For UDP servers we specify the "SYNC_OK" option because in our usage
     872                 :            :     // it can act in the synchronous mode.
     873                 :            :     installListenAddresses(addresses, impl_->listen_addresses_, *dnss_,
     874                 :          4 :                            DNSService::SERVER_SYNC_OK);
     875                 :          3 : }
     876                 :            : 
     877                 :            : void
     878                 :         81 : AuthSrv::setDNSService(isc::asiodns::DNSServiceBase& dnss) {
     879                 :         81 :     dnss_ = &dnss;
     880                 :         81 : }
     881                 :            : 
     882                 :            : void
     883                 :          4 : AuthSrv::setTSIGKeyRing(const boost::shared_ptr<TSIGKeyRing>* keyring) {
     884                 :          4 :     impl_->keyring_ = keyring;
     885                 :         16 : }

Generated by: LCOV version 1.9