LCOV - code coverage report
Current view: top level - home/jelte/repos/coverage_bind10/src/bin/auth - query.h (source / functions) Hit Total Coverage
Test: report.info Lines: 27 28 96.4 %
Date: 2012-05-15 Functions: 9 17 52.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 17 36 47.2 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
       3                 :            :  *
       4                 :            :  * Permission to use, copy, modify, and/or distribute this software for any
       5                 :            :  * purpose with or without fee is hereby granted, provided that the above
       6                 :            :  * copyright notice and this permission notice appear in all copies.
       7                 :            :  *
       8                 :            :  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       9                 :            :  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
      10                 :            :  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      11                 :            :  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      12                 :            :  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      13                 :            :  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      14                 :            :  * PERFORMANCE OF THIS SOFTWARE.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <exceptions/exceptions.h>
      18                 :            : #include <dns/rrset.h>
      19                 :            : #include <datasrc/zone.h>
      20                 :            : 
      21                 :            : #include <boost/noncopyable.hpp>
      22                 :            : 
      23                 :            : #include <functional>
      24                 :            : #include <vector>
      25                 :            : 
      26                 :            : namespace isc {
      27                 :            : namespace dns {
      28                 :            : class Message;
      29                 :            : class Name;
      30                 :            : class RRType;
      31                 :            : class RRset;
      32                 :            : }
      33                 :            : 
      34                 :            : namespace datasrc {
      35                 :            : class DataSourceClient;
      36                 :            : }
      37                 :            : 
      38                 :            : namespace auth {
      39                 :            : 
      40                 :            : /// The \c Query class represents a standard DNS query that encapsulates
      41                 :            : /// processing logic to answer the query.
      42                 :            : ///
      43                 :            : /// Many of the design details for this class are still in flux.
      44                 :            : /// We'll revisit and update them as we add more functionality, for example:
      45                 :            : /// - as a related point, we may have to pass the RR class of the query.
      46                 :            : ///   in the initial implementation the RR class is an attribute of
      47                 :            : ///   datasource and omitted.  It's not clear if this assumption holds with
      48                 :            : ///   generic data sources.  On the other hand, it will help keep
      49                 :            : ///   implementation simpler, and we might rather want to modify the design
      50                 :            : ///   of the data source on this point.
      51                 :            : /// - return value of process().  rather than or in addition to setting the
      52                 :            : ///   Rcode, we might use it as a return value of \c process().
      53                 :            : /// - we'll have to be able to specify whether DNSSEC is requested.
      54                 :            : ///   It's an open question whether it should be in the constructor or via a
      55                 :            : ///   separate attribute setter.
      56                 :            : /// - likewise, we'll eventually need to do per zone access control, for which
      57                 :            : ///   we need querier's information such as its IP address.
      58                 :            : /// - datasrc_client and response may better be parameters to process() instead
      59                 :            : ///   of the constructor.
      60                 :            : ///
      61                 :            : /// <b>Note:</b> The class name is intentionally the same as the one used in
      62                 :            : /// the datasrc library.  This is because the plan is to eventually merge
      63                 :            : /// the two classes.  We could give it a different name such as "AuthQuery"
      64                 :            : /// to avoid possible ambiguity, but it may sound redundant in that it's
      65                 :            : /// obvious that this class is for authoritative queries.
      66                 :            : /// Since the interfaces are very different for now and it's less
      67                 :            : /// likely to misuse one of the classes instead of the other
      68                 :            : /// accidentally, and since it's considered a temporary development state,
      69                 :            : /// we keep this name at the moment.
      70 [ +  - ][ +  - ]:        274 : class Query : boost::noncopyable {
                 [ +  - ]
      71                 :            : private:
      72                 :            :     /// \brief Initial reserved size for the vectors in Query
      73                 :            :     ///
      74                 :            :     /// The value is larger than we expect the vectors to even become, and
      75                 :            :     /// has been chosen arbitrarily. The reason to set them quite high is
      76                 :            :     /// to prevent reallocation on addition.
      77                 :            :     static const size_t RESERVE_RRSETS = 64;
      78                 :            : 
      79                 :            :     /// \brief Adds a SOA.
      80                 :            :     ///
      81                 :            :     /// Adds a SOA of the zone into the authority zone of response_.
      82                 :            :     /// Can throw NoSOA.
      83                 :            :     ///
      84                 :            :     void addSOA(isc::datasrc::ZoneFinder& finder);
      85                 :            : 
      86                 :            :     /// \brief Adds the DS rrset for the given name, if available
      87                 :            :     ///
      88                 :            :     /// This is intended to be called when returning a delegation, and
      89                 :            :     /// if DNSSEC data is requested. If the DS record is not found
      90                 :            :     /// (signaled by find() returning NXRRSET), and the zone is signed
      91                 :            :     /// with NSEC, an NSEC denial of existence proof is added.
      92                 :            :     ///
      93                 :            :     /// \exception BadDS raised if find() returns anything other than
      94                 :            :     ///                  SUCCESS or NXRRSET when searching for the DS
      95                 :            :     ///                  record.
      96                 :            :     /// \param finder The ZoneFinder where the delegation was found
      97                 :            :     /// \param ds_name The name of the delegation RRset
      98                 :            :     void addDS(isc::datasrc::ZoneFinder& finder,
      99                 :            :                const isc::dns::Name& ds_name);
     100                 :            : 
     101                 :            :     /// \brief Adds NSEC(3) denial proof for the given NXRRset result
     102                 :            :     ///
     103                 :            :     /// If available, NSEC or NSEC3 records are added to the authority
     104                 :            :     /// section (depending on whether isNSECSigned() or isNSEC3Signed()
     105                 :            :     /// returns true).
     106                 :            :     ///
     107                 :            :     /// \param finder The ZoneFinder that was used to search for the missing
     108                 :            :     ///               data
     109                 :            :     /// \param db_result The ZoneFinder::FindResult returned by find()
     110                 :            :     void addNXRRsetProof(isc::datasrc::ZoneFinder& finder,
     111                 :            :                          const isc::datasrc::ZoneFinder::Context& db_context);
     112                 :            : 
     113                 :            :     /// Add NSEC RRs that prove an NXDOMAIN result.
     114                 :            :     ///
     115                 :            :     /// This corresponds to Section 3.1.3.2 of RFC 4035.
     116                 :            :     void addNXDOMAINProofByNSEC(isc::datasrc::ZoneFinder& finder,
     117                 :            :                                 isc::dns::ConstRRsetPtr nsec);
     118                 :            : 
     119                 :            :     /// Add NSEC3 RRs that prove an NXDOMAIN result.
     120                 :            :     ///
     121                 :            :     /// This corresponds to Section 7.2.2 of RFC 5155.
     122                 :            :     void addNXDOMAINProofByNSEC3(isc::datasrc::ZoneFinder& finder);
     123                 :            : 
     124                 :            :     /// Add NSEC or NSEC3 RRs that prove a wildcard answer is the best one.
     125                 :            :     ///
     126                 :            :     /// This corresponds to Section 3.1.3.3 of RFC 4035 and Section 7.2.6
     127                 :            :     /// of RFC5155.
     128                 :            :     void addWildcardProof(
     129                 :            :         isc::datasrc::ZoneFinder& finder,
     130                 :            :         const isc::datasrc::ZoneFinder::Context& db_context);
     131                 :            : 
     132                 :            :     /// \brief Adds one NSEC RR proved no matched QNAME,one NSEC RR proved no
     133                 :            :     /// matched <QNAME,QTYPE> through wildcard extension.
     134                 :            :     ///
     135                 :            :     /// Add NSEC RRs that prove an WILDCARD_NXRRSET result.
     136                 :            :     /// This corresponds to Section 3.1.3.4 of RFC 4035.
     137                 :            :     /// \param finder The ZoneFinder through which the authority data for the
     138                 :            :     /// query is to be found.
     139                 :            :     /// \param nsec The RRset (NSEC RR) which proved that there is no matched 
     140                 :            :     /// <QNAME,QTTYPE>.
     141                 :            :     void addWildcardNXRRSETProof(isc::datasrc::ZoneFinder& finder,
     142                 :            :                                  isc::dns::ConstRRsetPtr nsec);
     143                 :            : 
     144                 :            :     /// \brief Look up a zone's NS RRset and their address records for an
     145                 :            :     /// authoritative answer, and add them to the additional section.
     146                 :            :     ///
     147                 :            :     /// On returning an authoritative answer, insert a zone's NS into the
     148                 :            :     /// authority section and AAAA/A RRs of each of the NS RDATA into the
     149                 :            :     /// additional section.
     150                 :            :     ///
     151                 :            :     /// <b>Notes to developer:</b>
     152                 :            :     ///
     153                 :            :     /// We should omit address records which has already been provided in the
     154                 :            :     /// answer section from the additional.
     155                 :            :     ///
     156                 :            :     /// For now, in order to optimize the additional section processing, we
     157                 :            :     /// include AAAA/A RRs under a zone cut in additional section. (BIND 9
     158                 :            :     /// excludes under-cut RRs; NSD include them.)
     159                 :            :     ///
     160                 :            :     /// \param finder The \c ZoneFinder through which the NS and additional
     161                 :            :     /// data for the query are to be found.
     162                 :            :     void addAuthAdditional(isc::datasrc::ZoneFinder& finder,
     163                 :            :                            std::vector<isc::dns::ConstRRsetPtr>& additionals);
     164                 :            : 
     165                 :            :     /// \brief Process a DS query possible at the child side of zone cut.
     166                 :            :     ///
     167                 :            :     /// This private method is a subroutine of process(), and is called if
     168                 :            :     /// there's a possibility that this server has authority for the child
     169                 :            :     /// side of the DS's owner name (and it's detected that the server at
     170                 :            :     /// least doesn't have authority at the parent side).  This method
     171                 :            :     /// first checks if it has authority for the child, and if does,
     172                 :            :     /// just build a "no data" response with SOA for the zone origin
     173                 :            :     /// (possibly with a proof for the no data) as specified in Section
     174                 :            :     /// 2.2.1.1 of RFC3658.
     175                 :            :     ///
     176                 :            :     /// It returns true if this server has authority of the child; otherwise
     177                 :            :     /// it returns false.  In the former case, the caller is expected to
     178                 :            :     /// terminate the query processing, because it should have been completed
     179                 :            :     /// within this method.
     180                 :            :     bool processDSAtChild();
     181                 :            : 
     182                 :            :     /// \brief Add NSEC3 to the response for a closest encloser proof for a
     183                 :            :     /// given name.
     184                 :            :     ///
     185                 :            :     /// This method calls \c findNSEC3() of the given zone finder for the
     186                 :            :     /// given name in the recursive mode, and adds the returned NSEC3(s) to
     187                 :            :     /// the authority section of the response message associated with the
     188                 :            :     /// \c Query object.
     189                 :            :     ///
     190                 :            :     /// It returns the number of labels of the closest encloser (returned via
     191                 :            :     /// the \c findNSEC3() call) in case the caller needs to use that value
     192                 :            :     /// for subsequent processing, i.e, constructing the best possible wildcard
     193                 :            :     /// name that (would) match the query name.
     194                 :            :     ///
     195                 :            :     /// Unless \c exact_ok is true, \c name is expected to be non existent,
     196                 :            :     /// in which case findNSEC3() in the recursive mode must return both
     197                 :            :     /// closest and next proofs.  If the latter is NULL, it means a run time
     198                 :            :     /// collision (or the zone is broken in other way), and this method throws
     199                 :            :     /// a BadNSEC3 exception.
     200                 :            :     ///
     201                 :            :     /// If \c exact_ok is true, this method takes into account the case
     202                 :            :     /// where the name exists and may or may not be at a zone cut to an
     203                 :            :     /// optout zone.  In this case, depending on whether the zone is optout
     204                 :            :     /// or not, findNSEC3() may return non-NULL or NULL next_proof
     205                 :            :     /// (respectively).  This method adds the next proof if and only if
     206                 :            :     /// findNSEC3() returns non NULL value for it.  The Opt-Out flag
     207                 :            :     /// must be set or cleared accordingly, but this method doesn't check that
     208                 :            :     /// in this level (as long as the zone is signed validly and findNSEC3()
     209                 :            :     /// for the data source is implemented as documented, the condition
     210                 :            :     /// should be met; otherwise we'd let the validator detect the error).
     211                 :            :     ///
     212                 :            :     /// By default this method always adds the closest proof.
     213                 :            :     /// If \c add_closest is false, it only adds the next proof to the message.
     214                 :            :     /// This correspond to the case of "wildcard answer responses" as described
     215                 :            :     /// in Section 7.2.6 of RFC5155.
     216                 :            :     uint8_t addClosestEncloserProof(isc::datasrc::ZoneFinder& finder,
     217                 :            :                                     const isc::dns::Name& name, bool exact_ok,
     218                 :            :                                     bool add_closest = true);
     219                 :            : 
     220                 :            :     /// \brief Add matching or covering NSEC3 to the response for a give name.
     221                 :            :     ///
     222                 :            :     /// This method calls \c findNSEC3() of the given zone finder for the
     223                 :            :     /// given name in the non recursive mode, and adds the returned NSEC3 to
     224                 :            :     /// the authority section of the response message associated with the
     225                 :            :     /// \c Query object.
     226                 :            :     ///
     227                 :            :     /// Depending on the caller's context, the returned NSEC3 is one and
     228                 :            :     /// only one of matching or covering NSEC3.  If \c match is true the
     229                 :            :     /// returned NSEC3 must be a matching one; otherwise it must be a covering
     230                 :            :     /// one.  If this assumption isn't met this method throws a BadNSEC3
     231                 :            :     /// exception (if it must be a matching NSEC3 but is not, it means a broken
     232                 :            :     /// zone, maybe with incorrect optout NSEC3s; if it must be a covering
     233                 :            :     /// NSEC3 but is not, it means a run time collision; or the \c findNSEC3()
     234                 :            :     /// implementation is broken for both cases.)
     235                 :            :     void addNSEC3ForName(isc::datasrc::ZoneFinder& finder,
     236                 :            :                          const isc::dns::Name& name, bool match);
     237                 :            : 
     238                 :            :     /// Set up the Query object for a new query lookup
     239                 :            :     ///
     240                 :            :     /// This is the first step of the process() method, and initializes
     241                 :            :     /// the member data
     242                 :            :     ///
     243                 :            :     /// \param datasrc_client The datasource wherein the answer to the query is
     244                 :            :     /// to be found.
     245                 :            :     /// \param qname The query name
     246                 :            :     /// \param qtype The RR type of the query
     247                 :            :     /// \param response The response message to store the answer to the query.
     248                 :            :     /// \param dnssec If the answer should include signatures and NSEC/NSEC3 if
     249                 :            :     ///     possible.
     250                 :            :     void initialize(datasrc::DataSourceClient& datasrc_client,
     251                 :            :                     const isc::dns::Name& qname, const isc::dns::RRType& qtype,
     252                 :            :                     isc::dns::Message& response, bool dnssec = false);
     253                 :            : 
     254                 :            :     /// \brief Resets any partly built response data, and internal pointers
     255                 :            :     ///
     256                 :            :     /// Called by the QueryCleaner object upon its destruction
     257                 :            :     void reset();
     258                 :            : 
     259                 :            :     /// \brief Internal class used for cleanup of Query members
     260                 :            :     ///
     261                 :            :     /// The process() call creates an object of this class, which
     262                 :            :     /// upon its destruction, calls Query::reset(), so that outside
     263                 :            :     /// of single calls to process(), the query state is always clean.
     264                 :            :     class QueryCleaner {
     265                 :            :     public:
     266                 :        101 :         QueryCleaner(isc::auth::Query& query) : query_(query) {}
     267                 :        101 :         ~QueryCleaner() { query_.reset(); }
     268                 :            :     private:
     269                 :            :         isc::auth::Query& query_;
     270                 :            :     };
     271                 :            : 
     272                 :            : protected:
     273                 :            :     // Following methods declared protected so they can be accessed
     274                 :            :     // by unit tests.
     275                 :            : 
     276                 :            :     void createResponse();
     277                 :            : 
     278                 :            : public:
     279                 :            :     /// Default constructor.
     280                 :            :     ///
     281                 :            :     /// Query parameters will be set by the call to process()
     282                 :            :     ///
     283                 :            :     Query() :
     284                 :            :         datasrc_client_(NULL), qname_(NULL), qtype_(NULL),
     285                 :            :         dnssec_(false), dnssec_opt_(isc::datasrc::ZoneFinder::FIND_DEFAULT),
     286         [ +  - ]:         86 :         response_(NULL)
     287                 :            :     {
     288         [ +  - ]:        180 :         answers_.reserve(RESERVE_RRSETS);
     289         [ +  - ]:        180 :         authorities_.reserve(RESERVE_RRSETS);
     290         [ -  + ]:        180 :         additionals_.reserve(RESERVE_RRSETS);
     291                 :            :     }
     292                 :            : 
     293                 :            : 
     294                 :            :     /// Process the query.
     295                 :            :     ///
     296                 :            :     /// This method first identifies the zone that best matches the query
     297                 :            :     /// name (and in some cases RR type when the search is dependent on the
     298                 :            :     /// type) and then searches the zone for an entry that best matches the
     299                 :            :     /// query name.
     300                 :            :     /// It then updates the response message accordingly; for example, a
     301                 :            :     /// successful search would result in adding a corresponding RRset to
     302                 :            :     /// the answer section of the response.
     303                 :            :     ///
     304                 :            :     /// If no matching zone is found in the datasource, the RCODE of
     305                 :            :     /// SERVFAIL will be set in the response.
     306                 :            :     /// <b>Note:</b> this is different from the error code that BIND 9 returns
     307                 :            :     /// by default when it's configured as an authoritative-only server (and
     308                 :            :     /// from the behavior of the BIND 10 datasrc library, which was implemented
     309                 :            :     /// to be compatible with BIND 9).
     310                 :            :     /// The difference comes from the fact that BIND 9 returns REFUSED as a
     311                 :            :     /// result of access control check on the use of its cache.
     312                 :            :     /// Since BIND 10's authoritative server doesn't have the notion of cache
     313                 :            :     /// by design, it doesn't make sense to return REFUSED.  On the other hand,
     314                 :            :     /// providing compatible behavior may have its own benefit, so this point
     315                 :            :     /// should be revisited later.
     316                 :            :     ///
     317                 :            :     /// This might throw BadZone or any of its specific subclasses, but that
     318                 :            :     /// shouldn't happen in real-life (as BadZone means wrong data, it should
     319                 :            :     /// have been rejected upon loading).
     320                 :            :     ///
     321                 :            :     /// \param datasrc_client The datasource wherein the answer to the query is
     322                 :            :     /// to be found.
     323                 :            :     /// \param qname The query name
     324                 :            :     /// \param qtype The RR type of the query
     325                 :            :     /// \param response The response message to store the answer to the query.
     326                 :            :     /// \param dnssec If the answer should include signatures and NSEC/NSEC3 if
     327                 :            :     ///     possible.
     328                 :            :     void process(datasrc::DataSourceClient& datasrc_client,
     329                 :            :                  const isc::dns::Name& qname, const isc::dns::RRType& qtype,
     330                 :            :                  isc::dns::Message& response, bool dnssec = false);
     331                 :            : 
     332                 :            :     /// \short Bad zone data encountered.
     333                 :            :     ///
     334                 :            :     /// This is thrown when process encounteres misconfigured zone in a way
     335                 :            :     /// it can't continue. This throws, not sets the Rcode, because such
     336                 :            :     /// misconfigured zone should not be present in the data source and
     337                 :            :     /// should have been rejected sooner.
     338                 :         17 :     struct BadZone : public isc::Exception {
     339                 :         17 :         BadZone(const char* file, size_t line, const char* what) :
     340                 :         34 :             Exception(file, line, what)
     341                 :         17 :         {}
     342                 :            :     };
     343                 :            : 
     344                 :            :     /// \short Zone is missing its SOA record.
     345                 :            :     ///
     346                 :            :     /// We tried to add a SOA into the authoritative section, but the zone
     347                 :            :     /// does not contain one.
     348                 :          2 :     struct NoSOA : public BadZone {
     349                 :            :         NoSOA(const char* file, size_t line, const char* what) :
     350         [ +  - ]:          2 :             BadZone(file, line, what)
     351                 :            :         {}
     352                 :            :     };
     353                 :            : 
     354                 :            :     /// \short Zone is missing its apex NS records.
     355                 :            :     ///
     356                 :            :     /// We tried to add apex NS records into the authority section, but the
     357                 :            :     /// zone does not contain any.
     358                 :          1 :     struct NoApexNS: public BadZone {
     359                 :            :         NoApexNS(const char* file, size_t line, const char* what) :
     360         [ +  - ]:          1 :             BadZone(file, line, what)
     361                 :            :         {}
     362                 :            :     };
     363                 :            : 
     364                 :            :     /// An invalid result is given when a valid NSEC is expected
     365                 :            :     ///
     366                 :            :     /// This can only happen when the underlying data source implementation or
     367                 :            :     /// the zone is broken.  By throwing an exception we treat such cases
     368                 :            :     /// as SERVFAIL.
     369                 :          7 :     struct BadNSEC : public BadZone {
     370                 :            :         BadNSEC(const char* file, size_t line, const char* what) :
     371 [ #  # ][ #  # ]:          7 :             BadZone(file, line, what)
         [ +  - ][ +  - ]
                 [ +  - ]
     372                 :            :         {}
     373                 :            :     };
     374                 :            : 
     375                 :            :     /// An invalid result is given when a valid NSEC3 is expected
     376                 :            :     ///
     377                 :            :     /// This can only happen when the underlying data source implementation or
     378                 :            :     /// the zone is broken.  By throwing an exception we treat such cases
     379                 :            :     /// as SERVFAIL.
     380                 :          6 :     struct BadNSEC3 : public BadZone {
     381                 :            :         BadNSEC3(const char* file, size_t line, const char* what) :
     382 [ +  - ][ +  - ]:          6 :             BadZone(file, line, what)
     383                 :            :         {}
     384                 :            :     };
     385                 :            : 
     386                 :            :     /// An invalid result is given when a valid DS records (or NXRRSET) is
     387                 :            :     /// expected
     388                 :            :     ///
     389                 :            :     /// This can only happen when the underlying data source implementation
     390                 :            :     /// or the zone is broken. A DS query for a known delegation point should
     391                 :            :     /// either result in SUCCESS (if available) or NXRRSET
     392                 :          1 :     struct BadDS : public BadZone {
     393                 :            :         BadDS(const char* file, size_t line, const char* what) :
     394         [ +  - ]:          1 :             BadZone(file, line, what)
     395                 :            :         {}
     396                 :            :     };
     397                 :            : 
     398                 :            :     /// \brief Response Creator Class
     399                 :            :     ///
     400                 :            :     /// This is a helper class of Query, and is expected to be used during the
     401                 :            :     /// construction of the response message. This class performs the
     402                 :            :     /// duplicate RRset detection check.  It keeps a list of RRsets added
     403                 :            :     /// to the message and does not add an RRset if it is the same as one
     404                 :            :     /// already added.
     405                 :            :     ///
     406                 :            :     /// This class is essentially private to Query, but is visible to public
     407                 :            :     /// for testing purposes.  It's not expected to be used from a normal
     408                 :            :     /// application.
     409                 :        181 :     class ResponseCreator {
     410                 :            :     public:
     411                 :            :         /// \brief Constructor
     412                 :            :         ///
     413                 :            :         /// Reserves space for the list of RRsets.  Although the
     414                 :            :         /// ResponseCreator will be used to create a message from the
     415                 :            :         /// contents of the Query object's answers_, authorities_ and
     416                 :            :         /// additionals_ elements, and each of these are sized to
     417                 :            :         /// RESERVE_RRSETS, it is _extremely_ unlikely that all three will be
     418                 :            :         /// filled to capacity.  So we reserve more elements than in each of
     419                 :            :         /// these components, but not three times the amount.
     420                 :            :         ///
     421                 :            :         /// As with the answers_, authorities_ and additionals_ elements, the
     422                 :            :         /// reservation is made in the constructor to avoid dynamic allocation
     423                 :            :         /// of memory.  The ResponseCreator is a member variable of the Query
     424                 :            :         /// object so is constructed once and lasts as long as that object.
     425                 :            :         /// Internal state is cleared through the clear() method.
     426                 :        181 :         ResponseCreator() {
     427         [ +  + ]:        181 :             added_.reserve(2 * RESERVE_RRSETS);
     428                 :         87 :         }
     429                 :            : 
     430                 :            :         /// \brief Reset internal state
     431                 :            :         void clear() {
     432                 :        101 :             added_.clear();
     433                 :            :         }
     434                 :            : 
     435                 :            :         /// \brief Complete the response message with filling in the
     436                 :            :         /// response sections.
     437                 :            :         ///
     438                 :            :         /// This is the final step of the Query::process() method, and within
     439                 :            :         /// that method, it should be called before it returns (if any
     440                 :            :         /// response data is to be added)
     441                 :            :         ///
     442                 :            :         /// This will take a message to build and each RRsets for the answer,
     443                 :            :         /// authority, and additional sections, and add them to their
     444                 :            :         /// corresponding sections in the given message.  The RRsets are
     445                 :            :         /// filtered such that a particular RRset appears only once in the
     446                 :            :         /// message.
     447                 :            :         ///
     448                 :            :         /// If \c dnssec is true, it tells the message to include any RRSIGs
     449                 :            :         /// attached to the RRsets.
     450                 :            :         void create(
     451                 :            :             isc::dns::Message& message,
     452                 :            :             const std::vector<isc::dns::ConstRRsetPtr>& answers_,
     453                 :            :             const std::vector<isc::dns::ConstRRsetPtr>& authorities_,
     454                 :            :             const std::vector<isc::dns::ConstRRsetPtr>& additionals_,
     455                 :            :             const bool dnssec);
     456                 :            : 
     457                 :            :     private:
     458                 :            :         // \brief RRset comparison functor.
     459                 :            :         struct IsSameKind : public std::binary_function<
     460                 :            :                             const isc::dns::AbstractRRset*,
     461                 :            :                             const isc::dns::AbstractRRset*,
     462                 :            :                             bool> {
     463                 :          0 :             bool operator()(const isc::dns::AbstractRRset* r1,
     464                 :            :                             const isc::dns::AbstractRRset* r2) const {
     465                 :        399 :                 return (r1->isSameKind(*r2));
     466                 :            :             }
     467                 :            :         };
     468                 :            : 
     469                 :            :         /// Insertion operation
     470                 :            :         ///
     471                 :            :         /// \param message Message to which the RRset is to be added
     472                 :            :         /// \param section Section of the message in which the RRset is put
     473                 :            :         /// \param rrset Pointer to RRset to be added to the message
     474                 :            :         /// \param dnssec Whether RRSIG records should be added as well
     475                 :            :         void addRRset(isc::dns::Message& message,
     476                 :            :                       const isc::dns::Message::Section section,
     477                 :            :                       const isc::dns::ConstRRsetPtr& rrset, const bool dnssec);
     478                 :            : 
     479                 :            : 
     480                 :            :     private:
     481                 :            :         /// List of RRsets already added to the message
     482                 :            :         std::vector<const isc::dns::AbstractRRset*> added_;
     483                 :            :     };
     484                 :            : 
     485                 :            : private:
     486                 :            :     const isc::datasrc::DataSourceClient* datasrc_client_;
     487                 :            :     const isc::dns::Name* qname_;
     488                 :            :     const isc::dns::RRType* qtype_;
     489                 :            :     bool dnssec_;
     490                 :            :     isc::datasrc::ZoneFinder::FindOptions dnssec_opt_;
     491                 :            :     ResponseCreator response_creator_;
     492                 :            : 
     493                 :            :     isc::dns::Message* response_;
     494                 :            :     std::vector<isc::dns::ConstRRsetPtr> answers_;
     495                 :            :     std::vector<isc::dns::ConstRRsetPtr> authorities_;
     496                 :            :     std::vector<isc::dns::ConstRRsetPtr> additionals_;
     497                 :            : };
     498                 :            : 
     499                 :            : }
     500                 :            : }
     501                 :            : 
     502                 :            : // Local Variables:
     503                 :            : // mode: c++
     504                 :            : // End:

Generated by: LCOV version 1.9