Browse Source

[2060] added the getAtOrigin() method to ZoneFinder::Context.

defining the common interface and the default implementation.
JINMEI Tatuya 12 years ago
parent
commit
d73842ed35

+ 2 - 1
src/lib/datasrc/tests/testdata/contexttest.zone

@@ -1,9 +1,10 @@
 ;; test zone file used for ZoneFinderContext tests.
 ;; RRSIGs are (obviouslly) faked ones for testing.
 
-example.org. 3600 IN SOA	ns1.example.org. bugs.x.w.example.org. 71 3600 300 3600000 3600
+example.org. 3600 IN SOA	ns1.example.org. bugs.x.w.example.org. 74 3600 300 3600000 3600
 example.org.			      3600 IN NS	ns1.example.org.
 example.org.			      3600 IN NS	ns2.example.org.
+example.org.			      3600 IN RRSIG	NS 7 3 3600 20150420235959 20051021000000 40430 example.org. FAKEFAKEFAKE
 example.org.			      3600 IN MX	1 mx1.example.org.
 example.org.			      3600 IN MX	2 mx2.example.org.
 example.org.			      3600 IN MX	3 mx.a.example.org.

+ 33 - 0
src/lib/datasrc/tests/zone_finder_context_unittest.cc

@@ -416,4 +416,37 @@ TEST_P(ZoneFinderContextTest, getAdditionalForAny) {
                 result_sets_.begin(), result_sets_.end());
 }
 
+TEST_P(ZoneFinderContextTest, getAtOrigin) {
+    ConstRRsetPtr expected_ns_rrset =
+        textToRRset("example.org. 3600 IN NS ns1.example.org.\n"
+                    "example.org. 3600 IN NS ns2.example.org.\n");
+
+    // Try getAtOrigin for an existing type (NS) record at the origin that
+    // has RRSIG.  The RRSIG will be associated iff the original query
+    // has the FIND_DNSSEC option.
+    ZoneFinderContextPtr ctx = finder_->find(Name("ns1.example.org"),
+                                             RRType::A());
+    EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
+    ConstRRsetPtr ns_rrset = ctx->getAtOrigin(RRType::NS());
+    ASSERT_TRUE(ns_rrset);
+    rrsetCheck(expected_ns_rrset, ns_rrset);
+    EXPECT_FALSE(ns_rrset->getRRsig());
+
+    ctx = finder_->find(Name("ns1.example.org"), RRType::A(),
+                        ZoneFinder::FIND_DNSSEC);
+    ns_rrset = ctx->getAtOrigin(RRType::NS());
+    ASSERT_TRUE(ns_rrset);
+    rrsetCheck(expected_ns_rrset, ns_rrset);
+    ASSERT_TRUE(ns_rrset->getRRsig());
+    rrsetCheck(textToRRset("example.org. 3600 IN RRSIG NS 7 3 3600 "
+                           "20150420235959 20051021000000 40430 "
+                           "example.org. FAKEFAKEFAKE"), ns_rrset->getRRsig());
+
+    // For non-existing type we simply get NULL.
+    EXPECT_FALSE(ctx->getAtOrigin(RRType::TXT()));
+
+    // Type ANY query isn't allowed.
+    EXPECT_THROW(ctx->getAtOrigin(RRType::ANY()), isc::InvalidParameter);
+}
+
 }

+ 68 - 0
src/lib/datasrc/zone.h

@@ -291,6 +291,67 @@ public:
             getAdditionalImpl(requested_types, result);
         }
 
+        /// \brief Find and return given type of RRset at the zone origin.
+        ///
+        /// DNS query processing often requires supplemental RRsets at the
+        /// zone origin; for example, for some negative answers we need to
+        /// provide the zone's SOA record; a full positive response normally
+        /// includes the zone's NS RRset.  The application can easily get
+        /// these using the generic \c ZoneFinder::find() interface, but
+        /// depending on the underlying data source implementation, the generic
+        /// version could be more expensive and/or it might be possible to
+        /// substantially improve this particular case.
+        ///
+        /// This method allows the underlying implementation to do such
+        /// optimization.  The interface is simplified; it just takes
+        /// an `RRType` and returns the corresponding RRset if found;
+        /// if not found it returns NULL.
+        ///
+        /// This method tries to find and return RRSIGs of the found RRset
+        /// if and only if the original lookup by \c ZoneFinder::find() has
+        /// the \c FIND_DNSSEC option.
+        ///
+        /// Type ANY must not be specified for this method.  It will result
+        /// in \c isc::InvalidParameter exception.  If the application
+        /// needs to get all types of RRsets at the origin, it should use
+        /// the \c ZoneFinder::findAll() method with the zone name.
+        ///
+        /// Note that the origin name should always exist, so there
+        /// shouldn't be the case where the name itself is not found
+        /// in the zone (i.e., the NXDOMAIN) case.  But in any event
+        /// it does not distinguish such a hypothetical case from the
+        /// case where the specified type isn't found at the origin.
+        /// It simply returns NULL when the required type isn't found.
+        /// This also means it doesn't provide a DNSSEC proof of the
+        /// non-existence.  If the application needs that proof, it must use
+        /// the generic \c find() method.
+        ///
+        /// A CNAME RR shouldn't exist at the zone origin at any sanely
+        /// configured zone (because there should be at least SOA there and
+        /// CNAME cannot coexist with it), and it's generally expected
+        /// the underlying implementation rejects the case where a CNAME
+        /// somehow exists at the zone origin.  Even if such a situation
+        /// happens, this method does not return the CNAME when the given
+        /// type of RRset isn't found; it will just return NULL like in the
+        /// normal case.
+        ///
+        /// \throw isc::InvalidParameter Type ANY is specified
+        /// \throw std::bad_alloc Internal resource allocation failure
+        ///
+        /// \param type The RR type for which an RRset at the origin is to be
+        /// found.
+        /// \return A shared pointer to the requested type of RRset or NULL
+        /// if not found.
+        dns::ConstRRsetPtr getAtOrigin(const dns::RRType& type) {
+            // Perform common check, then delegate the actual work to
+            // derived class implementation, if provided.
+            if (type == dns::RRType::ANY()) {
+                isc_throw(isc::InvalidParameter,
+                          "Type ANY isn't allowed for getAtOrigin");
+            }
+            return (getAtOriginImpl(type));
+        }
+
     protected:
         /// \brief Actual implementation of getAdditional().
         ///
@@ -301,6 +362,13 @@ public:
             const std::vector<isc::dns::RRType>& requested_types,
             std::vector<isc::dns::ConstRRsetPtr>& result);
 
+        /// \brief Actual implementation of getAtOrigin().
+        ///
+        /// This base class defines a default implementation that can be
+        /// used for any type of data sources.  A data source implementation
+        /// can override it.
+        virtual dns::ConstRRsetPtr getAtOriginImpl(const dns::RRType& type);
+
     private:
         ZoneFinder& finder_;
         const FindResultFlags flags_;

+ 13 - 0
src/lib/datasrc/zone_finder_context.cc

@@ -98,5 +98,18 @@ ZoneFinder::Context::getAdditionalImpl(const vector<RRType>& requested_types,
     }
 }
 
+ConstRRsetPtr
+ZoneFinder::Context::getAtOriginImpl(const dns::RRType& type) {
+    const ZoneFinder::FindOptions options =
+        (options_ & ZoneFinder::FIND_DNSSEC) != 0 ?
+        ZoneFinder::FIND_DNSSEC : ZoneFinder::FIND_DEFAULT;
+    ConstZoneFinderContextPtr ctx = finder_.find(finder_.getOrigin(), type,
+                                                 options);
+    if (ctx->code == ZoneFinder::SUCCESS) {
+        return (ctx->rrset);
+    }
+    return (ConstRRsetPtr());
+}
+
 } // namespace datasrc
 } // datasrc isc