Browse Source

[2386] Add NSEC implementation

Mukund Sivaraman 12 years ago
parent
commit
3fc36f8aba

+ 1 - 0
src/lib/dns/gen-rdatacode.py.in

@@ -41,6 +41,7 @@ new_rdata_factory_users = [('aaaa', 'in'),
                            ('naptr', 'generic'),
                            ('mx', 'generic'),
                            ('ns', 'generic'),
+                           ('nsec', 'generic'),
                            ('ptr', 'generic'),
                            ('soa', 'generic'),
                            ('spf', 'generic'),

+ 53 - 0
src/lib/dns/rdata/generic/detail/nsec_bitmap.cc

@@ -118,6 +118,59 @@ buildBitmapsFromText(const char* const rrtype_name,
     }
 }
 
+// Note: this function shares common code with buildBitmapsFromText()
+// above, but it is expected that buildBitmapsFromText() will be deleted
+// entirely once the transition to MasterLexer is done for all dependent
+// RR types. So a common method is not made from the two.
+void
+buildBitmapsFromLexer(const char* const rrtype_name,
+                      MasterLexer& lexer, vector<uint8_t>& typebits)
+{
+    uint8_t bitmap[8 * 1024];       // 64k bits
+    memset(bitmap, 0, sizeof(bitmap));
+
+    bool have_rrtypes = false;
+    while (true) {
+        const MasterToken& token = lexer.getNextToken();
+        if (token.getType() == MasterToken::END_OF_FILE) {
+            break;
+        }
+
+        have_rrtypes = true;
+        std::string type_str;
+        try {
+            type_str = token.getString();
+            const int code = RRType(type_str).getCode();
+            bitmap[code / 8] |= (0x80 >> (code % 8));
+        } catch (const InvalidRRType&) {
+            isc_throw(InvalidRdataText, "Invalid RRtype in "
+                      << rrtype_name << " bitmap: " << type_str);
+        }
+    }
+
+    if (!have_rrtypes) {
+         isc_throw(InvalidRdataText,
+                   rrtype_name << " record does not end with RR type string");
+    }
+
+    for (int window = 0; window < 256; ++window) {
+        int octet;
+        for (octet = 31; octet >= 0; octet--) {
+            if (bitmap[window * 32 + octet] != 0) {
+                break;
+            }
+        }
+        if (octet < 0) {
+            continue;
+        }
+        typebits.push_back(window);
+        typebits.push_back(octet + 1);
+        for (int i = 0; i <= octet; ++i) {
+            typebits.push_back(bitmap[window * 32 + i]);
+        }
+    }
+}
+
 void
 bitmapsToText(const vector<uint8_t>& typebits, ostringstream& oss) {
     // In the following loop we use string::at() rather than operator[].

+ 22 - 0
src/lib/dns/rdata/generic/detail/nsec_bitmap.h

@@ -15,6 +15,8 @@
 #ifndef NSECBITMAP_H
 #define NSECBITMAP_H 1
 
+#include <dns/master_lexer.h>
+
 #include <stdint.h>
 
 #include <sstream>
@@ -75,6 +77,26 @@ void buildBitmapsFromText(const char* const rrtype_name,
                           std::istringstream& iss,
                           std::vector<uint8_t>& typebits);
 
+/// \brief Convert textual sequence of RR types read from a lexer into
+/// type bitmaps.
+///
+/// See the other variant above for description.
+///
+/// \exception InvalidRdataText Data read from the given lexer does not
+/// meet the assumption (e.g. including invalid form of RR type, not
+/// ending with an RR type string).
+///
+/// \param rrtype_name Either "NSEC" or "NSEC3"; used as part of exception
+/// messages.
+/// \param lexer MasterLexer that provides consists of a complete
+/// sequence of textual lexemes of RR types for which the corresponding
+/// bits are set.
+/// \param typebits A placeholder for the resulting bitmaps.  Expected to be
+/// empty, but it's not checked.
+void buildBitmapsFromLexer(const char* const rrtype_name,
+                           isc::dns::MasterLexer& lexer,
+                           std::vector<uint8_t>& typebits);
+
 /// \brief Convert type bitmaps to textual sequence of RR types.
 ///
 /// This function converts wire-format data of type bitmaps for NSEC/NSEC3

+ 13 - 0
src/lib/dns/rdata/generic/nsec_47.cc

@@ -27,6 +27,7 @@
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
 #include <dns/rdata/generic/detail/nsec_bitmap.h>
+#include <dns/rdata/generic/detail/lexer_util.h>
 
 #include <stdio.h>
 #include <time.h>
@@ -35,6 +36,7 @@ using namespace std;
 using namespace isc::util;
 using namespace isc::util::encode;
 using namespace isc::dns::rdata::generic::detail::nsec;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
 
 // BEGIN_ISC_NAMESPACE
 // BEGIN_RDATA_NAMESPACE
@@ -87,6 +89,17 @@ NSEC::NSEC(InputBuffer& buffer, size_t rdata_len) {
     impl_ = new NSECImpl(nextname, typebits);
 }
 
+NSEC::NSEC(MasterLexer& lexer, const Name* origin, MasterLoader::Options,
+           MasterLoaderCallbacks&)
+{
+    const Name origin_name(createNameFromLexer(lexer, origin));
+
+    vector<uint8_t> typebits;
+    buildBitmapsFromLexer("NSEC", lexer, typebits);
+
+    impl_ = new NSECImpl(origin_name, typebits);
+}
+
 NSEC::NSEC(const NSEC& source) :
     Rdata(), impl_(new NSECImpl(*source.impl_))
 {}