Parcourir la source

[2429] use SOA's minimum TTL as a last resort default TTL

JINMEI Tatuya il y a 12 ans
Parent
commit
f7470975b4
2 fichiers modifiés avec 46 ajouts et 12 suppressions
  1. 27 12
      src/lib/dns/master_loader.cc
  2. 19 0
      src/lib/dns/tests/master_loader_unittest.cc

+ 27 - 12
src/lib/dns/master_loader.cc

@@ -15,6 +15,7 @@
 #include <dns/master_loader.h>
 #include <dns/master_lexer.h>
 #include <dns/name.h>
+#include <dns/rdataclass.h>
 #include <dns/rrttl.h>
 #include <dns/rrclass.h>
 #include <dns/rrtype.h>
@@ -139,12 +140,16 @@ public:
         pushSource(filename);
     }
 
-    void setDefaultTTL(const string& ttl_txt) {
+    void setDefaultTTL(const RRTTL& ttl) {
         if (!default_ttl_) {
-            default_ttl_.reset(new RRTTL(ttl_txt));
+            default_ttl_.reset(new RRTTL(ttl));
         } else {
-            *default_ttl_ = RRTTL(ttl_txt);
+            *default_ttl_ = ttl;
         }
+    }
+
+    void setDefaultTTL(const string& ttl_txt) {
+        setDefaultTTL(RRTTL(ttl_txt));
         eatUntilEOL(true);
     }
 
@@ -302,15 +307,6 @@ MasterLoader::MasterLoaderImpl::loadIncremental(size_t count_limit) {
             const RRClass rrclass(rrparam_token.getString());
             const RRType rrtype(getString());
 
-            // If the TTL is not yet determined, complete it.
-            if (!current_ttl_) {
-                if (default_ttl_) {
-                    setCurrentTTL(*default_ttl_);
-                } // TBD: else: try SOA min TTL for default, then error
-            } else if (!explicit_ttl && default_ttl_) {
-                setCurrentTTL(*default_ttl_);
-            }
-
             // TODO: Some more validation?
             if (rrclass != zone_class_) {
                 // It doesn't really matter much what type of exception
@@ -330,6 +326,25 @@ MasterLoader::MasterLoaderImpl::loadIncremental(size_t count_limit) {
             // callbacks_ already. We need to decide if we want to continue
             // or not.
             if (data) {
+                // If the TTL is not yet determined, complete it.
+                if (!current_ttl_ && !default_ttl_) {
+                    if (rrtype == RRType::SOA()) {
+                        callbacks_.warning(lexer_.getSourceName(),
+                                           lexer_.getSourceLine(),
+                                           "no TTL specified; "
+                                           "using SOA MINTTL instead");
+                        const uint32_t ttl_val =
+                            dynamic_cast<const rdata::generic::SOA&>(*data).
+                            getMinimum();
+                        setDefaultTTL(RRTTL(ttl_val));
+                        setCurrentTTL(*default_ttl_);
+                    }
+                } else if (!explicit_ttl && default_ttl_) {
+                    setCurrentTTL(*default_ttl_);
+                } else if (!explicit_ttl) {
+                    ;           // warn it
+                }               // else, explicit_ttl, that's used
+
                 add_callback_(name, rrclass, rrtype, *current_ttl_, data);
 
                 // Good, we loaded another one

+ 19 - 0
src/lib/dns/tests/master_loader_unittest.cc

@@ -407,6 +407,25 @@ TEST_F(MasterLoaderTest, ttlDirective) {
     checkRR("a2.example.org", RRType::A(), "192.0.2.3", RRTTL(3600));
 }
 
+TEST_F(MasterLoaderTest, ttlFromSOA) {
+    // No $TTL, and the SOA doesn't have an explicit TTL field.  Its minimum
+    // TTL field will be used as the RR's TTL, and it'll be used as the
+    // default TTL for others.
+    stringstream zone_stream("example.org. IN SOA . . 0 0 0 0 1800\n"
+                             "a.example.org. IN A 192.0.2.1\n");
+    setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+              MasterLoader::DEFAULT);
+    loader_->load();
+    EXPECT_TRUE(loader_->loadedSucessfully());
+    checkRR("example.org", RRType::SOA(), ". . 0 0 0 0 1800", RRTTL(1800));
+    checkRR("a.example.org", RRType::A(), "192.0.2.1", RRTTL(1800));
+
+    // The use of SOA minimum TTL should have caused a warning.
+    EXPECT_EQ(1, warnings_.size());
+    EXPECT_EQ(0, warnings_.at(0).find(
+                  "no TTL specified; using SOA MINTTL instead"));
+}
+
 // Test the constructor rejects empty add callback.
 TEST_F(MasterLoaderTest, emptyCallback) {
     EXPECT_THROW(MasterLoader(TEST_DATA_SRCDIR "/example.org",