LCOV - code coverage report
Current view: top level - datasrc - zone.h (source / functions) Hit Total Coverage
Test: report.info Lines: 22 26 84.6 %
Date: 2012-05-15 Functions: 5 15 33.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 54 116 46.6 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2010  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                 :            : #ifndef __ZONE_H
      16                 :            : #define __ZONE_H 1
      17                 :            : 
      18                 :            : #include <dns/name.h>
      19                 :            : #include <dns/rrset.h>
      20                 :            : #include <dns/rrtype.h>
      21                 :            : 
      22                 :            : #include <datasrc/result.h>
      23                 :            : 
      24                 :            : #include <utility>
      25                 :            : #include <vector>
      26                 :            : 
      27                 :            : namespace isc {
      28                 :            : namespace datasrc {
      29                 :            : 
      30                 :            : /// \brief Out of zone exception
      31                 :            : ///
      32                 :            : /// This is thrown when a method is called for a name or RRset which
      33                 :            : /// is not in or below the zone.
      34                 :         39 : class OutOfZone : public Exception {
      35                 :            : public:
      36                 :            :     OutOfZone(const char* file, size_t line, const char* what) :
      37 [ +  - ][ +  - ]:         39 :         isc::Exception(file, line, what) {}
         [ +  - ][ +  - ]
      38                 :            : };
      39                 :            : 
      40                 :            : /// \brief The base class to search a zone for RRsets
      41                 :            : ///
      42                 :            : /// The \c ZoneFinder class is an abstract base class for representing
      43                 :            : /// an object that performs DNS lookups in a specific zone accessible via
      44                 :            : /// a data source.  In general, different types of data sources (in-memory,
      45                 :            : /// database-based, etc) define their own derived classes of \c ZoneFinder,
      46                 :            : /// implementing ways to retrieve the required data through the common
      47                 :            : /// interfaces declared in the base class.  Each concrete \c ZoneFinder
      48                 :            : /// object is therefore (conceptually) associated with a specific zone
      49                 :            : /// of one specific data source instance.
      50                 :            : ///
      51                 :            : /// The origin name and the RR class of the associated zone are available
      52                 :            : /// via the \c getOrigin() and \c getClass() methods, respectively.
      53                 :            : ///
      54                 :            : /// The most important method of this class is \c find(), which performs
      55                 :            : /// the lookup for a given domain and type.  See the description of the
      56                 :            : /// method for details.
      57                 :            : ///
      58                 :            : /// \note It's not clear whether we should request that a zone finder form a
      59                 :            : /// "transaction", that is, whether to ensure the finder is not susceptible
      60                 :            : /// to changes made by someone else than the creator of the finder.  If we
      61                 :            : /// don't request that, for example, two different lookup results for the
      62                 :            : /// same name and type can be different if other threads or programs make
      63                 :            : /// updates to the zone between the lookups.  We should revisit this point
      64                 :            : /// as we gain more experiences.
      65                 :            : class ZoneFinder {
      66                 :            : public:
      67                 :            :     /// Result codes of the \c find() method.
      68                 :            :     ///
      69                 :            :     /// Note: the codes are tentative.  We may need more, or we may find
      70                 :            :     /// some of them unnecessary as we implement more details.
      71                 :            :     ///
      72                 :            :     /// See the description of \c find() for further details of how
      73                 :            :     /// these results should be interpreted.
      74                 :            :     enum Result {
      75                 :            :         SUCCESS,                ///< An exact match is found.
      76                 :            :         DELEGATION,             ///< The search encounters a zone cut.
      77                 :            :         NXDOMAIN, ///< There is no domain name that matches the search name
      78                 :            :         NXRRSET,  ///< There is a matching name but no RRset of the search type
      79                 :            :         CNAME,    ///< The search encounters and returns a CNAME RR
      80                 :            :         DNAME    ///< The search encounters and returns a DNAME RR
      81                 :            :     };
      82                 :            : 
      83                 :            :     /// Special attribute flags on the result of the \c find() method
      84                 :            :     ///
      85                 :            :     /// The flag values defined here are intended to signal to the caller
      86                 :            :     /// that it may need special handling on the result.  This is particularly
      87                 :            :     /// of concern when DNSSEC is requested.  For example, for negative
      88                 :            :     /// responses the caller would want to know whether the zone is signed
      89                 :            :     /// with NSEC or NSEC3 so that it can subsequently provide necessary
      90                 :            :     /// proof of the result.
      91                 :            :     ///
      92                 :            :     /// The caller is generally expected to get access to the information
      93                 :            :     /// via read-only getter methods of \c FindContext so that it won't rely
      94                 :            :     /// on specific details of the representation of the flags.  So these
      95                 :            :     /// definitions are basically only meaningful for data source
      96                 :            :     /// implementations.
      97                 :            :     enum FindResultFlags {
      98                 :            :         RESULT_DEFAULT = 0,       ///< The default flags
      99                 :            :         RESULT_WILDCARD = 1,      ///< find() resulted in a wildcard match
     100                 :            :         RESULT_NSEC_SIGNED = 2,   ///< The zone is signed with NSEC RRs
     101                 :            :         RESULT_NSEC3_SIGNED = 4   ///< The zone is signed with NSEC3 RRs
     102                 :            :     };
     103                 :            : 
     104                 :            :     /// Find options.
     105                 :            :     ///
     106                 :            :     /// The option values are used as a parameter for \c find().
     107                 :            :     /// These are values of a bitmask type.  Bitwise operations can be
     108                 :            :     /// performed on these values to express compound options.
     109                 :            :     enum FindOptions {
     110                 :            :         FIND_DEFAULT = 0,       ///< The default options
     111                 :            :         FIND_GLUE_OK = 1,       ///< Allow search under a zone cut
     112                 :            :         FIND_DNSSEC = 2,        ///< Require DNSSEC data in the answer
     113                 :            :                                 ///< (RRSIG, NSEC, etc.). The implementation
     114                 :            :                                 ///< is allowed to include it even if it is
     115                 :            :                                 ///< not set.
     116                 :            :         NO_WILDCARD = 4         ///< Do not try wildcard matching.
     117                 :            :     };
     118                 :            : 
     119                 :            : protected:
     120                 :            :     /// \brief A convenient tuple representing a set of find() results.
     121                 :            :     ///
     122                 :            :     /// This helper structure is specifically expected to be used as an input
     123                 :            :     /// for the construct of the \c Context class object used by derived
     124                 :            :     /// ZoneFinder implementations.  This is therefore defined as protected.
     125                 :       1568 :     struct ResultContext {
     126                 :            :         ResultContext(Result code_param,
     127                 :            :                       isc::dns::ConstRRsetPtr rrset_param,
     128                 :            :                       FindResultFlags flags_param = RESULT_DEFAULT) :
     129                 :       2800 :             code(code_param), rrset(rrset_param), flags(flags_param)
     130                 :            :         {}
     131                 :            :         const Result code;
     132                 :            :         const isc::dns::ConstRRsetPtr rrset;
     133                 :            :         const FindResultFlags flags;
     134                 :            :     };
     135                 :            : 
     136                 :            : public:
     137                 :            :     /// \brief Context of the result of a find() call.
     138                 :            :     ///
     139                 :            :     /// This class encapsulates results and (possibly) associated context
     140                 :            :     /// of a call to the \c find() method.   The public member variables of
     141                 :            :     /// this class reprsent the result of the call.  They are a
     142                 :            :     /// straightforward tuple of the result code and a pointer (and
     143                 :            :     /// optionally special flags) to the found RRset.
     144                 :            :     ///
     145                 :            :     /// These member variables will be initialized on construction and never
     146                 :            :     /// change, so for convenience we allow the applications to refer to some
     147                 :            :     /// of the members directly.  For some others we provide read-only accessor
     148                 :            :     /// methods to hide specific representation.
     149                 :            :     ///
     150                 :            :     /// Another role of this class is to provide the interface to some common
     151                 :            :     /// processing logic that may be necessary using the result of \c find().
     152                 :            :     /// Specifically, it's expected to be used in the context of DNS query
     153                 :            :     /// handling, where the caller would need to look into the data source
     154                 :            :     /// again based on the \c find() result.  For example, it would need to
     155                 :            :     /// get A and/or AAAA records for some of the answer or authority RRs.
     156                 :            :     ///
     157                 :            :     /// This class defines (a set of) method(s) that can be commonly used
     158                 :            :     /// for such purposes for any type of data source (as long as it conforms
     159                 :            :     /// to the public \c find() interface).  In some cases, a specific data
     160                 :            :     /// source implementation may want to (and can) optimize the processing
     161                 :            :     /// exploiting its internal data structure and the knowledge of the context
     162                 :            :     /// of the precedent \c find() call.  Such a data source implementation
     163                 :            :     /// can define a derived class of the base Context and override the
     164                 :            :     /// specific virtual method.
     165                 :            :     ///
     166                 :            :     /// This class object is generally expected to be associated with the
     167                 :            :     /// ZoneFinder that originally performed the \c find() call, and expects
     168                 :            :     /// the finder is valid throughout the lifetime of this object.  It's
     169                 :            :     /// caller's responsibility to ensure that assumption.
     170                 :            :     class Context {
     171                 :            :     public:
     172                 :            :         /// \brief The constructor for the normal find call.
     173                 :            :         ///
     174                 :            :         /// This constructor is expected to be called from the \c find()
     175                 :            :         /// method when it constructs the return value.
     176                 :            :         ///
     177                 :            :         /// \param finder The ZoneFinder on which find() is called.
     178                 :            :         /// \param options The find options specified for the find() call.
     179                 :            :         /// \param result The result of the find() call.
     180                 :            :         Context(ZoneFinder& finder, FindOptions options,
     181                 :            :                 const ResultContext& result) :
     182                 :            :             code(result.code), rrset(result.rrset),
     183                 :       2482 :             finder_(finder), flags_(result.flags), options_(options)
     184                 :            :         {}
     185                 :            : 
     186                 :            :         /// \brief The constructor for the normal findAll call.
     187                 :            :         ///
     188                 :            :         /// This constructor is expected to be called from the \c findAll()
     189                 :            :         /// method when it constructs the return value.
     190                 :            :         ///
     191                 :            :         /// It copies the vector that is to be returned to the caller of
     192                 :            :         /// \c findAll() for possible subsequent use.  Note that it cannot
     193                 :            :         /// simply hold a reference to the vector because the caller may
     194                 :            :         /// alter it after the \c findAll() call.
     195                 :            :         ///
     196                 :            :         /// \param finder The ZoneFinder on which findAll() is called.
     197                 :            :         /// \param options The find options specified for the findAll() call.
     198                 :            :         /// \param result The result of the findAll() call (whose rrset is
     199                 :            :         ///        expected to be NULL).
     200                 :            :         /// \param all_set Reference to the vector given by the caller of
     201                 :            :         ///       \c findAll(), storing the RRsets to be returned.
     202                 :            :         Context(ZoneFinder& finder, FindOptions options,
     203                 :            :                 const ResultContext& result,
     204                 :            :                 const std::vector<isc::dns::ConstRRsetPtr> &all_set) :
     205                 :            :             code(result.code), rrset(result.rrset),
     206                 :            :             finder_(finder), flags_(result.flags), options_(options),
     207                 :        114 :             all_set_(all_set)
     208                 :            :         {}
     209                 :            : 
     210                 :            :         /// \brief The destructor.
     211         [ #  # ]:       3332 :         virtual ~Context() {}
           [ #  #  +  - ]
     212                 :            : 
     213                 :            :         const Result code;
     214                 :            :         const isc::dns::ConstRRsetPtr rrset;
     215                 :            : 
     216                 :            :         /// Return true iff find() results in a wildcard match.
     217                 :          0 :         bool isWildcard() const { return ((flags_ & RESULT_WILDCARD) != 0); }
     218                 :            : 
     219                 :            :         /// Return true when the underlying zone is signed with NSEC.
     220                 :            :         ///
     221                 :            :         /// The \c find() implementation allows this to return false if
     222                 :            :         /// \c FIND_DNSSEC isn't specified regardless of whether the zone
     223                 :            :         /// is signed or which of NSEC/NSEC3 is used.
     224                 :            :         ///
     225                 :            :         /// When this is returned, the implementation of find() must ensure
     226                 :            :         /// that \c rrset be a valid NSEC RRset as described in \c find()
     227                 :            :         /// documentation.
     228                 :          0 :         bool isNSECSigned() const {
     229                 :          0 :             return ((flags_ & RESULT_NSEC_SIGNED) != 0);
     230                 :            :         }
     231                 :            : 
     232                 :            :         /// Return true when the underlying zone is signed with NSEC3.
     233                 :            :         ///
     234                 :            :         /// The \c find() implementation allows this to return false if
     235                 :            :         /// \c FIND_DNSSEC isn't specified regardless of whether the zone
     236                 :            :         /// is signed or which of NSEC/NSEC3 is used.
     237                 :          0 :         bool isNSEC3Signed() const {
     238         [ +  - ]:          3 :             return ((flags_ & RESULT_NSEC3_SIGNED) != 0);
     239                 :            :         }
     240                 :            : 
     241                 :            :         /// \brief Find and return additional RRsets corresponding to the
     242                 :            :         ///        result of \c find().
     243                 :            :         ///
     244                 :            :         /// If this context is based on a normal find() call that resulted
     245                 :            :         /// in SUCCESS or DELEGATION, it examines the returned RRset (in many
     246                 :            :         /// cases NS, sometimes MX or others), searches the data source for
     247                 :            :         /// specified type of additional RRs for each RDATA of the RRset
     248                 :            :         /// (e.g., A or AAAA for the name server addresses), and stores the
     249                 :            :         /// result in the given vector.  The vector may not be empty; this
     250                 :            :         /// method appends any found RRsets to it, without touching existing
     251                 :            :         /// elements.
     252                 :            :         ///
     253                 :            :         /// If this context is based on a findAll() call that resulted in
     254                 :            :         /// SUCCESS, it performs the same process for each RRset returned in
     255                 :            :         /// the \c findAll() call.
     256                 :            :         ///
     257                 :            :         /// The caller specifies desired RR types of the additional RRsets
     258                 :            :         /// in \c requested_types.  Normally it consists of A and/or AAAA
     259                 :            :         /// types, but other types can be specified.
     260                 :            :         ///
     261                 :            :         /// This method is meaningful only when the precedent find()/findAll()
     262                 :            :         /// call resulted in SUCCESS or DELEGATION.  Otherwise this method
     263                 :            :         /// does nothing.
     264                 :            :         ///
     265                 :            :         /// \note The additional RRsets returned via method are limited to
     266                 :            :         /// ones contained in the zone which the corresponding find/findAll
     267                 :            :         /// call searched (possibly including glues under a zone cut where
     268                 :            :         /// they are applicable).  If the caller needs to get out-of-zone
     269                 :            :         /// additional RRsets, it needs to explicitly finds them by
     270                 :            :         /// identifying the corresponding zone and calls \c find() for it.
     271                 :            :         ///
     272                 :            :         /// \param requested_types A vector of RR types for desired additional
     273                 :            :         ///  RRsets.
     274                 :            :         /// \param result A vector to which any found additional RRsets are
     275                 :            :         /// to be inserted.
     276                 :            :         void getAdditional(
     277                 :            :             const std::vector<isc::dns::RRType>& requested_types,
     278                 :            :             std::vector<isc::dns::ConstRRsetPtr>& result)
     279                 :            :         {
     280                 :            :             // Perform common checks, and delegate the process to the default
     281                 :            :             // or specialized implementation.
     282   [ +  -  +  -  :        121 :             if (code != SUCCESS && code != DELEGATION) {
          +  +  -  +  -  
          +  -  +  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     283                 :            :                 return;
     284                 :            :             }
     285                 :            : 
     286 [ +  - ][ +  - ]:        113 :             getAdditionalImpl(requested_types, result);
         [ +  - ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     287                 :            :         }
     288                 :            : 
     289                 :            :     protected:
     290                 :            :         /// \brief Actual implementation of getAdditional().
     291                 :            :         ///
     292                 :            :         /// This base class defines a default implementation that can be
     293                 :            :         /// used for any type of data sources.  A data source implementation
     294                 :            :         /// can override it.
     295                 :            :         virtual void getAdditionalImpl(
     296                 :            :             const std::vector<isc::dns::RRType>& requested_types,
     297                 :            :             std::vector<isc::dns::ConstRRsetPtr>& result);
     298                 :            : 
     299                 :            :     private:
     300                 :            :         ZoneFinder& finder_;
     301                 :            :         const FindResultFlags flags_;
     302                 :            :         const FindOptions options_;
     303                 :            :         std::vector<isc::dns::ConstRRsetPtr> all_set_;
     304                 :            :     };
     305                 :            : 
     306                 :            :     ///
     307                 :            :     /// \name Constructors and Destructor.
     308                 :            :     ///
     309                 :            :     //@{
     310                 :            : protected:
     311                 :            :     /// The default constructor.
     312                 :            :     ///
     313                 :            :     /// This is intentionally defined as \c protected as this base class should
     314                 :            :     /// never be instantiated (except as part of a derived class).
     315                 :        780 :     ZoneFinder() {}
     316                 :            : public:
     317                 :            :     /// The destructor.
     318                 :        780 :     virtual ~ZoneFinder() {}
     319                 :            :     //@}
     320                 :            : 
     321                 :            :     ///
     322                 :            :     /// \name Getter Methods
     323                 :            :     ///
     324                 :            :     /// These methods should never throw an exception.
     325                 :            :     //@{
     326                 :            :     /// Return the origin name of the zone.
     327                 :            :     virtual isc::dns::Name getOrigin() const = 0;
     328                 :            : 
     329                 :            :     /// Return the RR class of the zone.
     330                 :            :     virtual isc::dns::RRClass getClass() const = 0;
     331                 :            :     //@}
     332                 :            : 
     333                 :            :     ///
     334                 :            :     /// \name Search Methods
     335                 :            :     ///
     336                 :            :     //@{
     337                 :            :     /// Search the zone for a given pair of domain name and RR type.
     338                 :            :     ///
     339                 :            :     /// Each derived version of this method searches the underlying backend
     340                 :            :     /// for the data that best matches the given name and type.
     341                 :            :     /// This method is expected to be "intelligent", and identifies the
     342                 :            :     /// best possible answer for the search key.  Specifically,
     343                 :            :     ///
     344                 :            :     /// - If the search name belongs under a zone cut, it returns the code
     345                 :            :     ///   of \c DELEGATION and the NS RRset at the zone cut.
     346                 :            :     /// - If there is no matching name, it returns the code of \c NXDOMAIN.
     347                 :            :     /// - If there is a matching name but no RRset of the search type, it
     348                 :            :     ///   returns the code of \c NXRRSET.  This case includes the search name
     349                 :            :     ///   matches an empty node of the zone.
     350                 :            :     /// - If there is a CNAME RR of the searched name but there is no
     351                 :            :     ///   RR of the searched type of the name (so this type is different from
     352                 :            :     ///   CNAME), it returns the code of \c CNAME and that CNAME RR.
     353                 :            :     ///   Note that if the searched RR type is CNAME, it is considered
     354                 :            :     ///   a successful match, and the code of \c SUCCESS will be returned.
     355                 :            :     /// - If the search name matches a delegation point of DNAME, it returns
     356                 :            :     ///   the code of \c DNAME and that DNAME RR.
     357                 :            :     ///
     358                 :            :     /// No RRset will be returned in the \c NXDOMAIN and \c NXRRSET cases
     359                 :            :     /// (\c rrset member of \c FindContext will be NULL), unless DNSSEC data
     360                 :            :     /// are required.  See below for the cases with DNSSEC.
     361                 :            :     ///
     362                 :            :     /// The returned \c FindContext object can also provide supplemental
     363                 :            :     /// information about the search result via its methods returning a
     364                 :            :     /// boolean value.  Such information may be useful for the caller if
     365                 :            :     /// the caller wants to collect additional DNSSEC proofs based on the
     366                 :            :     /// search result.
     367                 :            :     ///
     368                 :            :     /// The \c options parameter specifies customized behavior of the search.
     369                 :            :     /// Their semantics is as follows (they are or bit-field):
     370                 :            :     ///
     371                 :            :     /// - \c FIND_GLUE_OK Allow search under a zone cut.  By default the search
     372                 :            :     ///   will stop once it encounters a zone cut.  If this option is specified
     373                 :            :     ///   it remembers information about the highest zone cut and continues
     374                 :            :     ///   the search until it finds an exact match for the given name or it
     375                 :            :     ///   detects there is no exact match.  If an exact match is found,
     376                 :            :     ///   RRsets for that name are searched just like the normal case;
     377                 :            :     ///   otherwise, if the search has encountered a zone cut, \c DELEGATION
     378                 :            :     ///   with the information of the highest zone cut will be returned.
     379                 :            :     /// - \c FIND_DNSSEC Request that DNSSEC data (like NSEC, RRSIGs) are
     380                 :            :     ///   returned with the answer. It is allowed for the data source to
     381                 :            :     ///   include them even when not requested.
     382                 :            :     /// - \c NO_WILDCARD Do not try wildcard matching.  This option is of no
     383                 :            :     ///   use for normal lookups; it's intended to be used to get a DNSSEC
     384                 :            :     ///   proof of the non existence of any matching wildcard or non existence
     385                 :            :     ///   of an exact match when a wildcard match is found.
     386                 :            :     ///
     387                 :            :     /// In general, \c name is expected to be included in the zone, that is,
     388                 :            :     /// it should be equal to or a subdomain of the zone origin.  Otherwise
     389                 :            :     /// this method will return \c NXDOMAIN with an empty RRset.  But such a
     390                 :            :     /// case should rather be considered a caller's bug.
     391                 :            :     ///
     392                 :            :     /// \note For this reason it's probably better to throw an exception
     393                 :            :     /// than returning \c NXDOMAIN.  This point should be revisited in a near
     394                 :            :     /// future version.  In any case applications shouldn't call this method
     395                 :            :     /// for an out-of-zone name.
     396                 :            :     ///
     397                 :            :     /// <b>DNSSEC considerations:</b>
     398                 :            :     /// The result when DNSSEC data are required can be very complicated,
     399                 :            :     /// especially if it involves negative result or wildcard match.
     400                 :            :     /// Specifically, if an application calls this method for DNS query
     401                 :            :     /// processing with DNSSEC data, and if the search result code is
     402                 :            :     /// either \c NXDOMAIN or \c NXRRRSET, and/or \c isWildcard() returns
     403                 :            :     /// true, then the application will need to find additional NSEC or
     404                 :            :     /// NSEC3 records for supplemental proofs.  This method helps the
     405                 :            :     /// application for such post search processing.
     406                 :            :     ///
     407                 :            :     /// First, it tells the application whether the zone is signed with
     408                 :            :     /// NSEC or NSEC3 via the \c isNSEC(3)Signed() method.  Any sanely signed
     409                 :            :     /// zone should be signed with either (and only one) of these two types
     410                 :            :     /// of RRs; however, the application should expect that the zone could
     411                 :            :     /// be broken and these methods could both return false.  But this method
     412                 :            :     /// should ensure that not both of these methods return true.
     413                 :            :     ///
     414                 :            :     /// In case it's signed with NSEC3, there is no further information
     415                 :            :     /// returned from this method.
     416                 :            :     ///
     417                 :            :     /// In case it's signed with NSEC, this method will possibly return
     418                 :            :     /// a related NSEC RRset in the \c rrset member of \c FindContext.
     419                 :            :     /// What kind of NSEC is returned depends on the result code
     420                 :            :     /// (\c NXDOMAIN or \c NXRRSET) and on whether it's a wildcard match:
     421                 :            :     ///
     422                 :            :     /// - In case of NXDOMAIN, the returned NSEC covers the queried domain
     423                 :            :     ///   that proves that the query name does not exist in the zone.  Note
     424                 :            :     ///   that this does not necessarily prove it doesn't even match a
     425                 :            :     ///   wildcard (even if the result of NXDOMAIN can only happen when
     426                 :            :     ///   there's no matching wildcard either).  It is caller's
     427                 :            :     ///   responsibility to provide a proof that there is no matching
     428                 :            :     ///   wildcard if that proof is necessary.
     429                 :            :     /// - In case of NXRRSET, we need to consider the following cases
     430                 :            :     ///   referring to Section 3.1.3 of RFC4035:
     431                 :            :     ///
     432                 :            :     /// -# (Normal) no data: there is a matching non-wildcard name with a
     433                 :            :     ///    different RR type.  This is the "No Data" case of the RFC.
     434                 :            :     /// -# (Normal) empty non terminal: there is no matching (exact or
     435                 :            :     ///    wildcard) name, but there is a subdomain with an RR of the query
     436                 :            :     ///    name.  This is one case of "Name Error" of the RFC.
     437                 :            :     /// -# Wildcard empty non terminal: similar to 2a, but the empty name
     438                 :            :     ///    is a wildcard, and matches the query name by wildcard expansion.
     439                 :            :     ///    This is a special case of "Name Error" of the RFC.
     440                 :            :     /// -# Wildcard no data: there is no exact match name, but there is a
     441                 :            :     ///    wildcard name that matches the query name with a different type
     442                 :            :     ///    of RR.  This is the "Wildcard No Data" case of the RFC.
     443                 :            :     ///
     444                 :            :     /// In case 1, \c find() returns NSEC of the matching name.
     445                 :            :     ///
     446                 :            :     /// In case 2, \c find() will return NSEC for the interval where the
     447                 :            :     /// empty nonterminal lives. The end of the interval is the subdomain
     448                 :            :     /// causing existence of the empty nonterminal (if there's
     449                 :            :     /// sub.x.example.com, and no record in x.example.com, then
     450                 :            :     /// x.example.com exists implicitly - is the empty nonterminal and
     451                 :            :     /// sub.x.example.com is the subdomain causing it).  Note that this NSEC
     452                 :            :     /// proves not only the existence of empty non terminal name but also
     453                 :            :     /// the non existence of possibly matching wildcard name, because
     454                 :            :     /// there can be no better wildcard match than the exact matching empty
     455                 :            :     /// name.
     456                 :            :     ///
     457                 :            :     /// In case 3, \c find() will return NSEC for the interval where the
     458                 :            :     /// wildcard empty nonterminal lives.   Cases 2 and 3 are especially
     459                 :            :     /// complicated and confusing.  See the examples below.
     460                 :            :     ///
     461                 :            :     /// In case 4, \c find() will return NSEC of the matching wildcard name.
     462                 :            :     ///
     463                 :            :     /// Examples: if zone "example.com" has the following record:
     464                 :            :     /// \code
     465                 :            :     /// a.example.com. NSEC a.b.example.com.
     466                 :            :     /// \endcode
     467                 :            :     /// a call to \c find() for "b.example.com." with the FIND_DNSSEC option
     468                 :            :     /// will result in NXRRSET, and this NSEC will be returned.
     469                 :            :     /// Likewise, if zone "example.org" has the following record,
     470                 :            :     /// \code
     471                 :            :     /// a.example.org. NSEC x.*.b.example.org.
     472                 :            :     /// \endcode
     473                 :            :     /// a call to \c find() for "y.b.example.org" with FIND_DNSSEC will
     474                 :            :     /// result in NXRRSET and this NSEC; \c isWildcard() on the returned
     475                 :            :     /// \c FindContext object will return true.
     476                 :            :     ///
     477                 :            :     /// \exception std::bad_alloc Memory allocation such as for constructing
     478                 :            :     ///  the resulting RRset fails
     479                 :            :     /// \throw OutOfZone The Name \c name is outside of the origin of the
     480                 :            :     /// zone of this ZoneFinder.
     481                 :            :     /// \exception DataSourceError Derived class specific exception, e.g.
     482                 :            :     /// when encountering a bad zone configuration or database connection
     483                 :            :     /// failure.  Although these are considered rare, exceptional events,
     484                 :            :     /// it can happen under relatively usual conditions (unlike memory
     485                 :            :     /// allocation failure).  So, in general, the application is expected
     486                 :            :     /// to catch this exception, either specifically or as a result of
     487                 :            :     /// catching a base exception class, and handle it gracefully.
     488                 :            :     ///
     489                 :            :     /// \param name The domain name to be searched for.
     490                 :            :     /// \param type The RR type to be searched for.
     491                 :            :     /// \param options The search options.
     492                 :            :     /// \return A \c FindContext object enclosing the search result
     493                 :            :     ///         (see above).
     494                 :            :     virtual boost::shared_ptr<Context> find(const isc::dns::Name& name,
     495                 :            :                                             const isc::dns::RRType& type,
     496                 :            :                                             const FindOptions options
     497                 :            :                                             = FIND_DEFAULT) = 0;
     498                 :            : 
     499                 :            :     ///
     500                 :            :     /// \brief Finds all RRsets in the given name.
     501                 :            :     ///
     502                 :            :     /// This function works almost exactly in the same way as the find one. The
     503                 :            :     /// only difference is, when the lookup is successful (eg. the code is
     504                 :            :     /// SUCCESS), all the RRsets residing in the named node are
     505                 :            :     /// copied into the \c target parameter and the rrset member of the result
     506                 :            :     /// is NULL. All the other (unsuccessful) cases are handled the same,
     507                 :            :     /// including returning delegations, NSEC/NSEC3 availability and NSEC
     508                 :            :     /// proofs, wildcard information etc. The options parameter works the
     509                 :            :     /// same way and it should conform to the same exception restrictions.
     510                 :            :     ///
     511                 :            :     /// \param name \see find, parameter name
     512                 :            :     /// \param target the successfull result is returned through this
     513                 :            :     /// \param options \see find, parameter options
     514                 :            :     /// \return \see find and it's result
     515                 :            :     virtual boost::shared_ptr<Context> findAll(
     516                 :            :         const isc::dns::Name& name,
     517                 :            :         std::vector<isc::dns::ConstRRsetPtr> &target,
     518                 :            :         const FindOptions options = FIND_DEFAULT) = 0;
     519                 :            : 
     520                 :            :     /// A helper structure to represent the search result of \c findNSEC3().
     521                 :            :     ///
     522                 :            :     /// The idea is similar to that of \c FindContext, but \c findNSEC3() has
     523                 :            :     /// special interface and semantics, we use a different structure to
     524                 :            :     /// represent the result.
     525                 :         56 :     struct FindNSEC3Result {
     526                 :         26 :         FindNSEC3Result(bool param_matched, uint8_t param_closest_labels,
     527                 :            :                         isc::dns::ConstRRsetPtr param_closest_proof,
     528                 :            :                         isc::dns::ConstRRsetPtr param_next_proof) :
     529                 :            :             matched(param_matched), closest_labels(param_closest_labels),
     530                 :            :             closest_proof(param_closest_proof),
     531                 :        100 :             next_proof(param_next_proof)
     532                 :         26 :         {}
     533                 :            : 
     534                 :            :         /// true iff closest_proof is a matching NSEC3
     535                 :            :         const bool matched;
     536                 :            : 
     537                 :            :         /// The number of labels of the identified closest encloser.
     538                 :            :         const uint8_t closest_labels;
     539                 :            : 
     540                 :            :         /// Either the NSEC3 for the closest provable encloser of the given
     541                 :            :         /// name or NSEC3 that covers the name
     542                 :            :         const isc::dns::ConstRRsetPtr closest_proof;
     543                 :            : 
     544                 :            :         /// When non NULL, NSEC3 for the next closer name.
     545                 :            :         const isc::dns::ConstRRsetPtr next_proof;
     546                 :            :     };
     547                 :            : 
     548                 :            :     /// Search the zone for the NSEC3 RR(s) that prove existence or non
     549                 :            :     /// existence of a give name.
     550                 :            :     ///
     551                 :            :     /// It searches the NSEC3 namespace of the zone (how that namespace is
     552                 :            :     /// implemented can vary in specific data source implementation) for NSEC3
     553                 :            :     /// RRs that match or cover the NSEC3 hash value for the given name.
     554                 :            :     ///
     555                 :            :     /// If \c recursive is false, it will first look for the NSEC3 that has
     556                 :            :     /// a matching hash.  If it doesn't exist, it identifies the covering NSEC3
     557                 :            :     /// for the hash.  In either case the search stops at that point and the
     558                 :            :     /// found NSEC3 RR(set) will be returned in the closest_proof member of
     559                 :            :     /// \c FindNSEC3Result.  \c matched is true or false depending on
     560                 :            :     /// the found NSEC3 is a matched one or covering one.  \c next_proof
     561                 :            :     /// is always NULL.  closest_labels must be equal to the number of
     562                 :            :     /// labels of \c name (and therefore meaningless).
     563                 :            :     ///
     564                 :            :     /// If \c recursive is true, it will continue the search toward the zone
     565                 :            :     /// apex (origin name) until it finds a provable encloser, that is,
     566                 :            :     /// an ancestor of \c name that has a matching NSEC3.  This is the closest
     567                 :            :     /// provable encloser of \c name as defined in RFC5155.  In this case,
     568                 :            :     /// if the found encloser is not equal to \c name, the search should
     569                 :            :     /// have seen a covering NSEC3 for the immediate child of the found
     570                 :            :     /// encloser.  That child name is the next closer name as defined in
     571                 :            :     /// RFC5155.  In this case, this method returns the NSEC3 for the
     572                 :            :     /// closest encloser in \c closest_proof, and the NSEC3 for the next
     573                 :            :     /// closer name in \c next_proof of \c FindNSEC3Result.  This set of
     574                 :            :     /// NSEC3 RRs provide the closest encloser proof as defined in RFC5155.
     575                 :            :     /// closest_labels will be set to the number of labels of the identified
     576                 :            :     /// closest encloser.  This will be useful when the caller needs to
     577                 :            :     /// construct the closest encloser name from the original \c name.
     578                 :            :     /// If, on the other hand, the found closest name is equal to \c name,
     579                 :            :     /// this method simply returns it in \c closest_proof.  \c next_proof
     580                 :            :     /// is set to NULL.  In all cases \c matched is set to true.
     581                 :            :     /// closest_labels will be set to the number of labels of \c name.
     582                 :            :     ///
     583                 :            :     /// When looking for NSEC3, this method retrieves NSEC3 parameters from
     584                 :            :     /// the corresponding zone to calculate hash values.  Actual implementation
     585                 :            :     /// of how to do this will differ in different data sources.  If the
     586                 :            :     /// NSEC3 parameters are not available \c DataSourceError exception
     587                 :            :     /// will be thrown.
     588                 :            :     ///
     589                 :            :     /// \note This implicitly means this method assumes the zone does not
     590                 :            :     /// have more than one set of parameters.  This assumption should be
     591                 :            :     /// reasonable in actual deployment and will help simplify the interface
     592                 :            :     /// and implementation.  But if there's a real need for supporting
     593                 :            :     /// multiple sets of parameters in a single zone, we will have to
     594                 :            :     /// extend this method so that, e.g., the caller can specify the parameter
     595                 :            :     /// set.
     596                 :            :     ///
     597                 :            :     /// In general, this method expects the zone is properly signed with NSEC3
     598                 :            :     /// RRs.  Specifically, it assumes at least the apex node has a matching
     599                 :            :     /// NSEC3 RR (so the search in the recursive mode must always succeed);
     600                 :            :     /// it also assumes that it can retrieve NSEC parameters (iterations,
     601                 :            :     /// algorithm, and salt) from the zone as noted above.  If these
     602                 :            :     /// assumptions aren't met, \c DataSourceError exception will be thrown.
     603                 :            :     ///
     604                 :            :     /// \exception OutOfZone name is not a subdomain of the zone origin
     605                 :            :     /// \exception DataSourceError Low-level or internal datasource errors
     606                 :            :     /// happened, or the zone isn't properly signed with NSEC3
     607                 :            :     /// (NSEC3 parameters cannot be found, no NSEC3s are available, etc).
     608                 :            :     /// \exception std::bad_alloc The underlying implementation involves
     609                 :            :     /// memory allocation and it fails
     610                 :            :     ///
     611                 :            :     /// \param name The name for which NSEC3 RRs are to be found.  It must
     612                 :            :     /// be a subdomain of the zone.
     613                 :            :     /// \param recursive Whether or not search should continue until it finds
     614                 :            :     /// a provable encloser (see above).
     615                 :            :     ///
     616                 :            :     /// \return The search result and whether or not the closest_proof is
     617                 :            :     /// a matching NSEC3, in the form of \c FindNSEC3Result object.
     618                 :            :     virtual FindNSEC3Result
     619                 :            :     findNSEC3(const isc::dns::Name& name, bool recursive) = 0;
     620                 :            : 
     621                 :            :     /// \brief Get previous name in the zone
     622                 :            :     ///
     623                 :            :     /// Gets the previous name in the DNSSEC order. This can be used
     624                 :            :     /// to find the correct NSEC records for proving nonexistence
     625                 :            :     /// of domains.
     626                 :            :     ///
     627                 :            :     /// The concrete implementation might throw anything it thinks appropriate,
     628                 :            :     /// however it is recommended to stick to the ones listed here. The user
     629                 :            :     /// of this method should be able to handle any exceptions.
     630                 :            :     ///
     631                 :            :     /// This method does not include under-zone-cut data (glue data).
     632                 :            :     ///
     633                 :            :     /// \param query The name for which one we look for a previous one. The
     634                 :            :     ///     queried name doesn't have to exist in the zone.
     635                 :            :     /// \return The preceding name
     636                 :            :     ///
     637                 :            :     /// \throw NotImplemented in case the data source backend doesn't support
     638                 :            :     ///     DNSSEC or there is no previous in the zone (NSEC records might be
     639                 :            :     ///     missing in the DB, the queried name is less or equal to the apex).
     640                 :            :     /// \throw DataSourceError for low-level or internal datasource errors
     641                 :            :     ///     (like broken connection to database, wrong data living there).
     642                 :            :     /// \throw std::bad_alloc For allocation errors.
     643                 :            :     virtual isc::dns::Name findPreviousName(const isc::dns::Name& query)
     644                 :            :         const = 0;
     645                 :            :     //@}
     646                 :            : };
     647                 :            : 
     648                 :            : /// \brief Operator to combine FindOptions
     649                 :            : ///
     650                 :            : /// We would need to manually static-cast the options if we put or
     651                 :            : /// between them, which is undesired with bit-flag options. Therefore
     652                 :            : /// we hide the cast here, which is the simplest solution and it still
     653                 :            : /// provides reasonable level of type safety.
     654                 :            : inline ZoneFinder::FindOptions operator |(ZoneFinder::FindOptions a,
     655                 :            :                                           ZoneFinder::FindOptions b)
     656                 :            : {
     657                 :            :     return (static_cast<ZoneFinder::FindOptions>(static_cast<unsigned>(a) |
     658                 :        142 :                                                  static_cast<unsigned>(b)));
     659                 :            : }
     660                 :            : 
     661                 :            : /// \brief Operator to combine FindResultFlags
     662                 :            : ///
     663                 :            : /// Similar to the same operator for \c FindOptions.  Refer to the description
     664                 :            : /// of that function.
     665                 :            : inline ZoneFinder::FindResultFlags operator |(
     666                 :            :     ZoneFinder::FindResultFlags a,
     667                 :            :     ZoneFinder::FindResultFlags b)
     668                 :            : {
     669                 :            :     return (static_cast<ZoneFinder::FindResultFlags>(
     670                 :        185 :                 static_cast<unsigned>(a) | static_cast<unsigned>(b)));
     671                 :            : }
     672                 :            : 
     673                 :            : /// \brief A pointer-like type pointing to a \c ZoneFinder object.
     674                 :            : typedef boost::shared_ptr<ZoneFinder> ZoneFinderPtr;
     675                 :            : 
     676                 :            : /// \brief A pointer-like type pointing to an immutable \c ZoneFinder object.
     677                 :            : typedef boost::shared_ptr<const ZoneFinder> ConstZoneFinderPtr;
     678                 :            : 
     679                 :            : /// \brief A pointer-like type pointing to a \c ZoneFinder::Context object.
     680                 :            : typedef boost::shared_ptr<ZoneFinder::Context> ZoneFinderContextPtr;
     681                 :            : 
     682                 :            : /// \brief A pointer-like type pointing to an immutable
     683                 :            : /// \c ZoneFinder::Context object.
     684                 :            : typedef boost::shared_ptr<ZoneFinder::Context> ConstZoneFinderContextPtr;
     685                 :            : 
     686                 :            : /// The base class to make updates to a single zone.
     687                 :            : ///
     688                 :            : /// On construction, each derived class object will start a "transaction"
     689                 :            : /// for making updates to a specific zone (this means a constructor of
     690                 :            : /// a derived class would normally take parameters to identify the zone
     691                 :            : /// to be updated).  The underlying realization of a "transaction" will differ
     692                 :            : /// for different derived classes; if it uses a general purpose database
     693                 :            : /// as a backend, it will involve performing some form of "begin transaction"
     694                 :            : /// statement for the database.
     695                 :            : ///
     696                 :            : /// Updates (adding or deleting RRs) are made via \c addRRset() and
     697                 :            : /// \c deleteRRset() methods.  Until the \c commit() method is called the
     698                 :            : /// changes are local to the updater object.  For example, they won't be
     699                 :            : /// visible via a \c ZoneFinder object except the one returned by the
     700                 :            : /// updater's own \c getFinder() method.  The \c commit() completes the
     701                 :            : /// transaction and makes the changes visible to others.
     702                 :            : ///
     703                 :            : /// This class does not provide an explicit "rollback" interface.  If
     704                 :            : /// something wrong or unexpected happens during the updates and the
     705                 :            : /// caller wants to cancel the intermediate updates, the caller should
     706                 :            : /// simply destruct the updater object without calling \c commit().
     707                 :            : /// The destructor is supposed to perform the "rollback" operation,
     708                 :            : /// depending on the internal details of the derived class.
     709                 :            : ///
     710                 :            : /// \note This initial implementation provides a quite simple interface of
     711                 :            : /// adding and deleting RRs (see the description of the related methods).
     712                 :            : /// It may be revisited as we gain more experiences.
     713                 :            : class ZoneUpdater {
     714                 :            : protected:
     715                 :            :     /// The default constructor.
     716                 :            :     ///
     717                 :            :     /// This is intentionally defined as protected to ensure that this base
     718                 :            :     /// class is never instantiated directly.
     719                 :        149 :     ZoneUpdater() {}
     720                 :            : 
     721                 :            : public:
     722                 :            :     /// The destructor
     723                 :            :     ///
     724                 :            :     /// Each derived class implementation must ensure that if \c commit()
     725                 :            :     /// has not been performed by the time of the call to it, then it
     726                 :            :     /// "rollbacks" the updates made via the updater so far.
     727                 :        149 :     virtual ~ZoneUpdater() {}
     728                 :            : 
     729                 :            :     /// Return a finder for the zone being updated.
     730                 :            :     ///
     731                 :            :     /// The returned finder provides the functionalities of \c ZoneFinder
     732                 :            :     /// for the zone as updates are made via the updater.  That is, before
     733                 :            :     /// making any update, the finder will be able to find all RRsets that
     734                 :            :     /// exist in the zone at the time the updater is created.  If RRsets
     735                 :            :     /// are added or deleted via \c addRRset() or \c deleteRRset(),
     736                 :            :     /// this finder will find the added ones or miss the deleted ones
     737                 :            :     /// respectively.
     738                 :            :     ///
     739                 :            :     /// The finder returned by this method is effective only while the updates
     740                 :            :     /// are performed, i.e., from the construction of the corresponding
     741                 :            :     /// updater until \c commit() is performed or the updater is destructed
     742                 :            :     /// without commit.  The result of a subsequent call to this method (or
     743                 :            :     /// the use of the result) after that is undefined.
     744                 :            :     ///
     745                 :            :     /// \return A reference to a \c ZoneFinder for the updated zone
     746                 :            :     virtual ZoneFinder& getFinder() = 0;
     747                 :            : 
     748                 :            :     /// Add an RRset to a zone via the updater
     749                 :            :     ///
     750                 :            :     /// This may be revisited in a future version, but right now the intended
     751                 :            :     /// behavior of this method is simple: It "naively" adds the specified
     752                 :            :     /// RRset to the zone specified on creation of the updater.
     753                 :            :     /// It performs minimum level of validation on the specified RRset:
     754                 :            :     /// - Whether the RR class is identical to that for the zone to be updated
     755                 :            :     /// - Whether the RRset is not empty, i.e., it has at least one RDATA
     756                 :            :     /// - Whether the RRset is not associated with an RRSIG, i.e.,
     757                 :            :     ///   whether \c getRRsig() on the RRset returns a NULL pointer.
     758                 :            :     ///
     759                 :            :     /// and otherwise does not check any oddity.  For example, it doesn't
     760                 :            :     /// check whether the owner name of the specified RRset is a subdomain
     761                 :            :     /// of the zone's origin; it doesn't care whether or not there is already
     762                 :            :     /// an RRset of the same name and RR type in the zone, and if there is,
     763                 :            :     /// whether any of the existing RRs have duplicate RDATA with the added
     764                 :            :     /// ones.  If these conditions matter the calling application must examine
     765                 :            :     /// the existing data beforehand using the \c ZoneFinder returned by
     766                 :            :     /// \c getFinder().
     767                 :            :     ///
     768                 :            :     /// The validation requirement on the associated RRSIG is temporary.
     769                 :            :     /// If we find it more reasonable and useful to allow adding a pair of
     770                 :            :     /// RRset and its RRSIG RRset as we gain experiences with the interface,
     771                 :            :     /// we may remove this restriction.  Until then we explicitly check it
     772                 :            :     /// to prevent accidental misuse.
     773                 :            :     ///
     774                 :            :     /// Conceptually, on successful call to this method, the zone will have
     775                 :            :     /// the specified RRset, and if there is already an RRset of the same
     776                 :            :     /// name and RR type, these two sets will be "merged".  "Merged" means
     777                 :            :     /// that a subsequent call to \c ZoneFinder::find() for the name and type
     778                 :            :     /// will result in success and the returned RRset will contain all
     779                 :            :     /// previously existing and newly added RDATAs with the TTL being the
     780                 :            :     /// minimum of the two RRsets.  The underlying representation of the
     781                 :            :     /// "merged" RRsets may vary depending on the characteristic of the
     782                 :            :     /// underlying data source.  For example, if it uses a general purpose
     783                 :            :     /// database that stores each RR of the same RRset separately, it may
     784                 :            :     /// simply be a larger sets of RRs based on both the existing and added
     785                 :            :     /// RRsets; the TTLs of the RRs may be different within the database, and
     786                 :            :     /// there may even be duplicate RRs in different database rows.  As long
     787                 :            :     /// as the RRset returned via \c ZoneFinder::find() conforms to the
     788                 :            :     /// concept of "merge", the actual internal representation is up to the
     789                 :            :     /// implementation.
     790                 :            :     ///
     791                 :            :     /// This method must not be called once commit() is performed.  If it
     792                 :            :     /// calls after \c commit() the implementation must throw a
     793                 :            :     /// \c DataSourceError exception.
     794                 :            :     ///
     795                 :            :     /// If journaling was requested when getting this updater, it will reject
     796                 :            :     /// to add the RRset if the squence doesn't look like and IXFR (see
     797                 :            :     /// DataSourceClient::getUpdater). In such case isc::BadValue is thrown.
     798                 :            :     ///
     799                 :            :     /// \todo As noted above we may have to revisit the design details as we
     800                 :            :     /// gain experiences:
     801                 :            :     ///
     802                 :            :     /// - we may want to check (and maybe reject) if there is already a
     803                 :            :     /// duplicate RR (that has the same RDATA).
     804                 :            :     /// - we may want to check (and maybe reject) if there is already an
     805                 :            :     /// RRset of the same name and RR type with different TTL
     806                 :            :     /// - we may even want to check if there is already any RRset of the
     807                 :            :     /// same name and RR type.
     808                 :            :     /// - we may want to add an "options" parameter that can control the
     809                 :            :     /// above points
     810                 :            :     /// - we may want to have this method return a value containing the
     811                 :            :     /// information on whether there's a duplicate, etc.
     812                 :            :     ///
     813                 :            :     /// \exception DataSourceError Called after \c commit(), RRset is invalid
     814                 :            :     /// (see above), internal data source error
     815                 :            :     /// \exception isc::BadValue Journaling is enabled and the current RRset
     816                 :            :     ///   doesn't fit into the IXFR sequence (see above).
     817                 :            :     /// \exception std::bad_alloc Resource allocation failure
     818                 :            :     ///
     819                 :            :     /// \param rrset The RRset to be added
     820                 :            :     virtual void addRRset(const isc::dns::AbstractRRset& rrset) = 0;
     821                 :            : 
     822                 :            :     /// Delete an RRset from a zone via the updater
     823                 :            :     ///
     824                 :            :     /// Like \c addRRset(), the detailed semantics and behavior of this method
     825                 :            :     /// may have to be revisited in a future version.  The following are
     826                 :            :     /// based on the initial implementation decisions.
     827                 :            :     ///
     828                 :            :     /// On successful completion of this method, it will remove from the zone
     829                 :            :     /// the RRs of the specified owner name and RR type that match one of
     830                 :            :     /// the RDATAs of the specified RRset.  There are several points to be
     831                 :            :     /// noted:
     832                 :            :     /// - Existing RRs that don't match any of the specified RDATAs will
     833                 :            :     ///   remain in the zone.
     834                 :            :     /// - Any RRs of the specified RRset that doesn't exist in the zone will
     835                 :            :     ///   simply be ignored; the implementation of this method is not supposed
     836                 :            :     ///   to check that condition.
     837                 :            :     /// - The TTL of the RRset is ignored; matching is only performed by
     838                 :            :     ///   the owner name, RR type and RDATA
     839                 :            :     ///
     840                 :            :     /// Ignoring the TTL may not look sensible, but it's based on the
     841                 :            :     /// observation that it will result in more intuitive result, especially
     842                 :            :     /// when the underlying data source is a general purpose database.
     843                 :            :     /// See also \c DatabaseAccessor::deleteRecordInZone() on this point.
     844                 :            :     /// It also matches the dynamic update protocol (RFC2136), where TTLs
     845                 :            :     /// are ignored when deleting RRs.
     846                 :            :     ///
     847                 :            :     /// \note Since the TTL is ignored, this method could take the RRset
     848                 :            :     /// to be deleted as a tuple of name, RR type, and a list of RDATAs.
     849                 :            :     /// But in practice, it's quite likely that the caller has the RRset
     850                 :            :     /// in the form of the \c RRset object (e.g., extracted from a dynamic
     851                 :            :     /// update request message), so this interface would rather be more
     852                 :            :     /// convenient.  If it turns out not to be true we can change or extend
     853                 :            :     /// the method signature.
     854                 :            :     ///
     855                 :            :     /// This method performs minimum level of validation on the specified
     856                 :            :     /// RRset:
     857                 :            :     /// - Whether the RR class is identical to that for the zone to be updated
     858                 :            :     /// - Whether the RRset is not empty, i.e., it has at least one RDATA
     859                 :            :     /// - Whether the RRset is not associated with an RRSIG, i.e.,
     860                 :            :     ///   whether \c getRRsig() on the RRset returns a NULL pointer.
     861                 :            :     ///
     862                 :            :     /// This method must not be called once commit() is performed.  If it
     863                 :            :     /// calls after \c commit() the implementation must throw a
     864                 :            :     /// \c DataSourceError exception.
     865                 :            :     ///
     866                 :            :     /// If journaling was requested when getting this updater, it will reject
     867                 :            :     /// to add the RRset if the squence doesn't look like and IXFR (see
     868                 :            :     /// DataSourceClient::getUpdater). In such case isc::BadValue is thrown.
     869                 :            :     ///
     870                 :            :     /// \todo As noted above we may have to revisit the design details as we
     871                 :            :     /// gain experiences:
     872                 :            :     ///
     873                 :            :     /// - we may want to check (and maybe reject) if some or all of the RRs
     874                 :            :     ///   for the specified RRset don't exist in the zone
     875                 :            :     /// - we may want to allow an option to "delete everything" for specified
     876                 :            :     ///   name and/or specified name + RR type.
     877                 :            :     /// - as mentioned above, we may want to include the TTL in matching the
     878                 :            :     ///   deleted RRs
     879                 :            :     /// - we may want to add an "options" parameter that can control the
     880                 :            :     ///   above points
     881                 :            :     /// - we may want to have this method return a value containing the
     882                 :            :     ///   information on whether there's any RRs that are specified but don't
     883                 :            :     ///   exit, the number of actually deleted RRs, etc.
     884                 :            :     ///
     885                 :            :     /// \exception DataSourceError Called after \c commit(), RRset is invalid
     886                 :            :     /// (see above), internal data source error
     887                 :            :     /// \exception isc::BadValue Journaling is enabled and the current RRset
     888                 :            :     ///   doesn't fit into the IXFR sequence (see above).
     889                 :            :     /// \exception std::bad_alloc Resource allocation failure
     890                 :            :     ///
     891                 :            :     /// \param rrset The RRset to be deleted
     892                 :            :     virtual void deleteRRset(const isc::dns::AbstractRRset& rrset) = 0;
     893                 :            : 
     894                 :            :     /// Commit the updates made in the updater to the zone
     895                 :            :     ///
     896                 :            :     /// This method completes the "transaction" started at the creation
     897                 :            :     /// of the updater.  After successful completion of this method, the
     898                 :            :     /// updates will be visible outside the scope of the updater.
     899                 :            :     /// The actual internal behavior will defer for different derived classes.
     900                 :            :     /// For a derived class with a general purpose database as a backend,
     901                 :            :     /// for example, this method would perform a "commit" statement for the
     902                 :            :     /// database.
     903                 :            :     ///
     904                 :            :     /// This operation can only be performed at most once.  A duplicate call
     905                 :            :     /// must result in a DatasourceError exception.
     906                 :            :     ///
     907                 :            :     /// \exception DataSourceError Duplicate call of the method,
     908                 :            :     /// internal data source error
     909                 :            :     /// \exception isc::BadValue Journaling is enabled and the update is not
     910                 :            :     ///    complete IXFR sequence.
     911                 :            :     virtual void commit() = 0;
     912                 :            : };
     913                 :            : 
     914                 :            : /// \brief A pointer-like type pointing to a \c ZoneUpdater object.
     915                 :            : typedef boost::shared_ptr<ZoneUpdater> ZoneUpdaterPtr;
     916                 :            : 
     917                 :            : /// The base class for retrieving differences between two versions of a zone.
     918                 :            : ///
     919                 :            : /// On construction, each derived class object will internally set up
     920                 :            : /// retrieving sequences of differences between two specific version of
     921                 :            : /// a specific zone managed in a particular data source.  So the constructor
     922                 :            : /// of a derived class would normally take parameters to identify the zone
     923                 :            : /// and the two versions for which the differences should be retrieved.
     924                 :            : /// See \c DataSourceClient::getJournalReader for more concrete details
     925                 :            : /// used in this API.
     926                 :            : ///
     927                 :            : /// Once constructed, an object of this class will act like an iterator
     928                 :            : /// over the sequences.  Every time the \c getNextDiff() method is called
     929                 :            : /// it returns one element of the differences in the form of an \c RRset
     930                 :            : /// until it reaches the end of the entire sequences.
     931                 :            : class ZoneJournalReader {
     932                 :            : public:
     933                 :            :     /// Result codes used by a factory method for \c ZoneJournalReader
     934                 :            :     enum Result {
     935                 :            :         SUCCESS, ///< A \c ZoneJournalReader object successfully created
     936                 :            :         NO_SUCH_ZONE, ///< Specified zone does not exist in the data source
     937                 :            :         NO_SUCH_VERSION ///< Specified versions do not exist in the diff storage
     938                 :            :     };
     939                 :            : 
     940                 :            : protected:
     941                 :            :     /// The default constructor.
     942                 :            :     ///
     943                 :            :     /// This is intentionally defined as protected to ensure that this base
     944                 :            :     /// class is never instantiated directly.
     945                 :         19 :     ZoneJournalReader() {}
     946                 :            : 
     947                 :            : public:
     948                 :            :     /// The destructor
     949                 :         19 :     virtual ~ZoneJournalReader() {}
     950                 :            : 
     951                 :            :     /// Return the next difference RR of difference sequences.
     952                 :            :     ///
     953                 :            :     /// In this API, the difference between two versions of a zone is
     954                 :            :     /// conceptually represented as IXFR-style difference sequences:
     955                 :            :     /// Each difference sequence is a sequence of RRs: an older version of
     956                 :            :     /// SOA (to be deleted), zero or more other deleted RRs, the
     957                 :            :     /// post-transaction SOA (to be added), and zero or more other
     958                 :            :     /// added RRs.  (Note, however, that the underlying data source
     959                 :            :     /// implementation may or may not represent the difference in
     960                 :            :     /// straightforward realization of this concept.  The mapping between
     961                 :            :     /// the conceptual difference and the actual implementation is hidden
     962                 :            :     /// in each derived class).
     963                 :            :     ///
     964                 :            :     /// This method provides an application with a higher level interface
     965                 :            :     /// to retrieve the difference along with the conceptual model: the
     966                 :            :     /// \c ZoneJournalReader object iterates over the entire sequences
     967                 :            :     /// from the beginning SOA (which is to be deleted) to one of the
     968                 :            :     /// added RR of with the ending SOA, and each call to this method returns
     969                 :            :     /// one RR in the form of an \c RRset that contains exactly one RDATA
     970                 :            :     /// in the order of the sequences.
     971                 :            :     ///
     972                 :            :     /// Note that the ordering of the sequences specifies the semantics of
     973                 :            :     /// each difference: add or delete.  For example, the first RR is to
     974                 :            :     /// be deleted, and the last RR is to be added.  So the return value
     975                 :            :     /// of this method does not explicitly indicate whether the RR is to be
     976                 :            :     /// added or deleted.
     977                 :            :     ///
     978                 :            :     /// This method ensures the returned \c RRset represents an RR, that is,
     979                 :            :     /// it contains exactly one RDATA.  However, it does not necessarily
     980                 :            :     /// ensure that the resulting sequences are in the form of IXFR-style.
     981                 :            :     /// For example, the first RR is supposed to be an SOA, and it should
     982                 :            :     /// normally be the case, but this interface does not necessarily require
     983                 :            :     /// the derived class implementation ensure this.  Normally the
     984                 :            :     /// differences are expected to be stored using this API (via a
     985                 :            :     /// \c ZoneUpdater object), and as long as that is the case and the
     986                 :            :     /// underlying implementation follows the requirement of the API, the
     987                 :            :     /// result of this method should be a valid IXFR-style sequences.
     988                 :            :     /// So this API does not mandate the almost redundant check as part of
     989                 :            :     /// the interface.  If the application needs to make it sure 100%, it
     990                 :            :     /// must check the resulting sequence itself.
     991                 :            :     ///
     992                 :            :     /// Once the object reaches the end of the sequences, this method returns
     993                 :            :     /// \c Null.  Any subsequent call will result in an exception of
     994                 :            :     /// class \c InvalidOperation.
     995                 :            :     ///
     996                 :            :     /// \exception InvalidOperation The method is called beyond the end of
     997                 :            :     /// the difference sequences.
     998                 :            :     /// \exception DataSourceError Underlying data is broken and the RR
     999                 :            :     /// cannot be created or other low level data source error.
    1000                 :            :     ///
    1001                 :            :     /// \return An \c RRset that contains one RDATA corresponding to the
    1002                 :            :     /// next difference in the sequences.
    1003                 :            :     virtual isc::dns::ConstRRsetPtr getNextDiff() = 0;
    1004                 :            : };
    1005                 :            : 
    1006                 :            : /// \brief A pointer-like type pointing to a \c ZoneUpdater object.
    1007                 :            : typedef boost::shared_ptr<ZoneJournalReader> ZoneJournalReaderPtr;
    1008                 :            : 
    1009                 :            : } // end of datasrc
    1010                 :            : } // end of isc
    1011                 :            : 
    1012                 :            : #endif  // __ZONE_H
    1013                 :            : 
    1014                 :            : // Local Variables:
    1015                 :            : // mode: c++
    1016                 :            : // End:

Generated by: LCOV version 1.9