Browse Source

[2310] extend findAtOrigin so it can handle use_minttl correctly.

JINMEI Tatuya 12 years ago
parent
commit
4760fba1fc

+ 33 - 7
src/lib/datasrc/memory/zone_finder.cc

@@ -23,10 +23,13 @@
 #include <dns/name.h>
 #include <dns/name.h>
 #include <dns/rrset.h>
 #include <dns/rrset.h>
 #include <dns/rrtype.h>
 #include <dns/rrtype.h>
+#include <dns/rrttl.h>
 #include <dns/nsec3hash.h>
 #include <dns/nsec3hash.h>
 
 
 #include <datasrc/logger.h>
 #include <datasrc/logger.h>
 
 
+#include <util/buffer.h>
+
 #include <boost/scoped_ptr.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <boost/bind.hpp>
 #include <boost/bind.hpp>
 
 
@@ -104,14 +107,19 @@ createTreeNodeRRset(const ZoneNode* node,
                     const RdataSet* rdataset,
                     const RdataSet* rdataset,
                     const RRClass& rrclass,
                     const RRClass& rrclass,
                     ZoneFinder::FindOptions options,
                     ZoneFinder::FindOptions options,
-                    const Name* realname = NULL)
+                    const Name* realname = NULL,
+                    const void* ttl_data = NULL)
 {
 {
     const bool dnssec = ((options & ZoneFinder::FIND_DNSSEC) != 0);
     const bool dnssec = ((options & ZoneFinder::FIND_DNSSEC) != 0);
-    if (node != NULL && rdataset != NULL) {
-        if (realname != NULL) {
+    if (node && rdataset) {
+        if (realname) {
             return (TreeNodeRRsetPtr(new TreeNodeRRset(*realname, rrclass,
             return (TreeNodeRRsetPtr(new TreeNodeRRset(*realname, rrclass,
                                                        node, rdataset,
                                                        node, rdataset,
                                                        dnssec)));
                                                        dnssec)));
+        } else if (ttl_data) {
+            assert(!realname);  // these two cases should be mixed in our use
+            return (TreeNodeRRsetPtr(new TreeNodeRRset(rrclass, node, rdataset,
+                                                       dnssec, ttl_data)));
         } else {
         } else {
             return (TreeNodeRRsetPtr(new TreeNodeRRset(rrclass, node, rdataset,
             return (TreeNodeRRsetPtr(new TreeNodeRRset(rrclass, node, rdataset,
                                                        dnssec)));
                                                        dnssec)));
@@ -229,6 +237,12 @@ createNSEC3RRset(const ZoneNode* node, const RRClass& rrclass) {
                                 ZoneFinder::FIND_DNSSEC));
                                 ZoneFinder::FIND_DNSSEC));
 }
 }
 
 
+inline RRTTL
+createTTLFromData(const void* ttl_data) {
+    util::InputBuffer b(ttl_data, sizeof(uint32_t));
+    return (RRTTL(b));
+}
+
 // convenience function to fill in the final details
 // convenience function to fill in the final details
 //
 //
 // Set up ZoneFinderResultContext object as a return value of find(),
 // Set up ZoneFinderResultContext object as a return value of find(),
@@ -250,7 +264,8 @@ createFindResult(const RRClass& rrclass,
                  const RdataSet* rdataset,
                  const RdataSet* rdataset,
                  ZoneFinder::FindOptions options,
                  ZoneFinder::FindOptions options,
                  bool wild = false,
                  bool wild = false,
-                 const Name* qname = NULL)
+                 const Name* qname = NULL,
+                 bool use_minttl = false)
 {
 {
     ZoneFinder::FindResultFlags flags = ZoneFinder::RESULT_DEFAULT;
     ZoneFinder::FindResultFlags flags = ZoneFinder::RESULT_DEFAULT;
     const Name* rename = NULL;
     const Name* rename = NULL;
@@ -268,6 +283,15 @@ createFindResult(const RRClass& rrclass,
         }
         }
     }
     }
 
 
+    if (use_minttl && rdataset &&
+        createTTLFromData(zone_data.getMinTTLData()) <
+        createTTLFromData(rdataset->getTTLData())) {
+        return (ZoneFinderResultContext(
+                    code,
+                    createTreeNodeRRset(node, rdataset, rrclass, options,
+                                        rename, zone_data.getMinTTLData()),
+                    flags, zone_data, node, rdataset));
+    }
     return (ZoneFinderResultContext(code, createTreeNodeRRset(node, rdataset,
     return (ZoneFinderResultContext(code, createTreeNodeRRset(node, rdataset,
                                                               rrclass, options,
                                                               rrclass, options,
                                                               rename),
                                                               rename),
@@ -743,7 +767,7 @@ InMemoryZoneFinder::findAll(const isc::dns::Name& name,
 
 
 boost::shared_ptr<ZoneFinder::Context>
 boost::shared_ptr<ZoneFinder::Context>
 InMemoryZoneFinder::findAtOrigin(const isc::dns::RRType& type,
 InMemoryZoneFinder::findAtOrigin(const isc::dns::RRType& type,
-                                 bool /*use_minttl*/, // not yet supported
+                                 bool use_minttl,
                                  const FindOptions options)
                                  const FindOptions options)
 {
 {
     const ZoneNode* const node = zone_data_.getOriginNode();
     const ZoneNode* const node = zone_data_.getOriginNode();
@@ -755,7 +779,8 @@ InMemoryZoneFinder::findAtOrigin(const isc::dns::RRType& type,
         return (ZoneFinderContextPtr(
         return (ZoneFinderContextPtr(
                     new Context(*this, options, rrclass_,
                     new Context(*this, options, rrclass_,
                                 createFindResult(rrclass_, zone_data_, SUCCESS,
                                 createFindResult(rrclass_, zone_data_, SUCCESS,
-                                                 node, found, options))));
+                                                 node, found, options, false,
+                                                 NULL, use_minttl))));
     }
     }
     return (ZoneFinderContextPtr(
     return (ZoneFinderContextPtr(
                     new Context(*this, options, rrclass_,
                     new Context(*this, options, rrclass_,
@@ -764,7 +789,8 @@ InMemoryZoneFinder::findAtOrigin(const isc::dns::RRType& type,
                                                  getNSECForNXRRSET(zone_data_,
                                                  getNSECForNXRRSET(zone_data_,
                                                                    options,
                                                                    options,
                                                                    node),
                                                                    node),
-                                                 options))));
+                                                 options, false, NULL,
+                                                 use_minttl))));
 }
 }
 
 
 ZoneFinderResultContext
 ZoneFinderResultContext

+ 4 - 0
src/lib/datasrc/memory/zone_finder.h

@@ -62,6 +62,10 @@ public:
 
 
     /// \brief Search for an RRset of given RR type at the zone origin
     /// \brief Search for an RRset of given RR type at the zone origin
     /// specialized for in-memory data source.
     /// specialized for in-memory data source.
+    ///
+    /// This specialized version exploits internal data structure to find
+    /// RRsets at the zone origin and (if \c use_minttl is true) extract
+    /// the SOA Minimum TTL much more efficiently.
     virtual boost::shared_ptr<Context> findAtOrigin(
     virtual boost::shared_ptr<Context> findAtOrigin(
         const isc::dns::RRType& type, bool use_minttl,
         const isc::dns::RRType& type, bool use_minttl,
         FindOptions options);
         FindOptions options);

+ 57 - 5
src/lib/datasrc/tests/memory/zone_finder_unittest.cc

@@ -63,7 +63,11 @@ using result::EXIST;
 /// be a concern here.
 /// be a concern here.
 ConstRRsetPtr
 ConstRRsetPtr
 convertRRset(ConstRRsetPtr src) {
 convertRRset(ConstRRsetPtr src) {
-    return (textToRRset(src->toText()));
+    // If the type is SOA, textToRRset performs a stricter check, so we should
+    // specify the origin.
+    const Name& origin = (src->getType() == RRType::SOA()) ?
+        src->getName() : Name::ROOT_NAME();
+    return (textToRRset(src->toText(), src->getClass(), origin));
 }
 }
 
 
 /// \brief Test fixture for the InMemoryZoneFinder class
 /// \brief Test fixture for the InMemoryZoneFinder class
@@ -322,7 +326,7 @@ protected:
                           memory::InMemoryZoneFinder* zone_finder = NULL,
                           memory::InMemoryZoneFinder* zone_finder = NULL,
                           ZoneFinder::FindOptions options =
                           ZoneFinder::FindOptions options =
                           ZoneFinder::FIND_DEFAULT,
                           ZoneFinder::FIND_DEFAULT,
-                          bool check_wild_answer = false)
+                          bool use_minttl = false)
     {
     {
         SCOPED_TRACE("findAtOriginTest for " + rrtype.toText());
         SCOPED_TRACE("findAtOriginTest for " + rrtype.toText());
 
 
@@ -330,9 +334,9 @@ protected:
             zone_finder = &zone_finder_;
             zone_finder = &zone_finder_;
         }
         }
         ZoneFinderContextPtr find_result(zone_finder->findAtOrigin(
         ZoneFinderContextPtr find_result(zone_finder->findAtOrigin(
-                                             rrtype, false, options));
+                                             rrtype, use_minttl, options));
         findTestCommon(origin_, result, find_result, check_answer, answer,
         findTestCommon(origin_, result, find_result, check_answer, answer,
-                       expected_flags, options, check_wild_answer);
+                       expected_flags, options, false);
     }
     }
 
 
 private:
 private:
@@ -627,7 +631,6 @@ TEST_F(InMemoryZoneFinderTest, glue) {
     findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::DELEGATION,
     findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::DELEGATION,
              true, rr_child_ns_);
              true, rr_child_ns_);
 
 
-
     // If we do it in the "glue OK" mode, we should find the exact match.
     // If we do it in the "glue OK" mode, we should find the exact match.
     findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::SUCCESS, true,
     findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::SUCCESS, true,
              rr_child_glue_, ZoneFinder::RESULT_DEFAULT, NULL,
              rr_child_glue_, ZoneFinder::RESULT_DEFAULT, NULL,
@@ -701,6 +704,55 @@ TEST_F(InMemoryZoneFinderTest, findAtOrigin) {
                      ZoneFinder::FIND_DNSSEC);
                      ZoneFinder::FIND_DNSSEC);
 }
 }
 
 
+TEST_F(InMemoryZoneFinderTest, findAtOriginWithMinTTL) {
+    // Install zone's SOA.  This also sets internal zone data min TTL field.
+    addToZoneData(rr_soa_);
+
+    // Specify the use of min TTL, then the resulting TTL should be derived
+    // from the SOA MINTTL (which is smaller).
+    findAtOriginTest(RRType::SOA(), ZoneFinder::SUCCESS, true,
+                     textToRRset("example.org. 100 IN SOA . . 0 0 0 0 100",
+                                 class_, origin_),
+                     ZoneFinder::RESULT_DEFAULT, NULL,
+                     ZoneFinder::FIND_DEFAULT, true);
+
+    // Add signed NS for the following test.
+    RRsetPtr ns_rrset(textToRRset("example.org. 300 IN NS ns.example.org."));
+    ns_rrset->addRRsig(createRdata(RRType::RRSIG(), RRClass::IN(),
+                                   "NS 5 3 3600 20120814220826 20120715220826 "
+                                   "1234 example.org. FAKE"));
+    addToZoneData(ns_rrset);
+
+    // If DNSSEC is requested, TTL of the RRSIG should also be the min.
+    ns_rrset->setTTL(RRTTL(100));      // reset TTL to the expected one
+    findAtOriginTest(RRType::NS(), ZoneFinder::SUCCESS, true, ns_rrset,
+                     ZoneFinder::RESULT_DEFAULT, NULL,
+                     ZoneFinder::FIND_DEFAULT, true);
+
+    // If we don't request the use of min TTL, the original TTL will be used.
+    findAtOriginTest(RRType::SOA(), ZoneFinder::SUCCESS, true, rr_soa_,
+                     ZoneFinder::RESULT_DEFAULT, NULL,
+                     ZoneFinder::FIND_DEFAULT, false);
+
+    // If no RRset is returned, use_minttl doesn't matter (it shouldn't cause
+    // disruption)
+    findAtOriginTest(RRType::TXT(), ZoneFinder::NXRRSET, true, ConstRRsetPtr(),
+                     ZoneFinder::RESULT_DEFAULT, NULL,
+                     ZoneFinder::FIND_DEFAULT, true);
+
+    // If it results in NXRRSET with NSEC, and if we specify the use of min
+    // TTL, the NSEC and RRSIG should have the min TTL (again, though, this
+    // use case is not really the intended one)
+    rr_nsec_->addRRsig(createRdata(RRType::RRSIG(), RRClass::IN(),
+                                   "NSEC 5 3 3600 20120814220826 "
+                                   "20120715220826 1234 example.org. FAKE"));
+    addToZoneData(rr_nsec_);
+    rr_nsec_->setTTL(RRTTL(100)); // reset it to the expected one
+    findAtOriginTest(RRType::TXT(), ZoneFinder::NXRRSET, true, rr_nsec_,
+                     ZoneFinder::RESULT_NSEC_SIGNED, NULL,
+                     ZoneFinder::FIND_DNSSEC, true);
+}
+
 /**
 /**
  * \brief Test searching.
  * \brief Test searching.
  *
  *