Browse Source

[2387] Add NSEC3 lexer constructor implementation

Mukund Sivaraman 12 years ago
parent
commit
240e533301

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

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

+ 43 - 0
src/lib/dns/rdata/generic/detail/nsec3param_common.cc

@@ -89,6 +89,49 @@ parseNSEC3ParamText(const char* const rrtype_name,
 }
 
 ParseNSEC3ParamResult
+parseNSEC3ParamFromLexer(const char* const rrtype_name,
+                         MasterLexer& lexer, vector<uint8_t>& salt)
+{
+    const uint32_t hashalg =
+        lexer.getNextToken(MasterToken::NUMBER).getNumber();
+    if (hashalg > 0xff) {
+        isc_throw(InvalidRdataText, rrtype_name <<
+                  " hash algorithm out of range: " << hashalg);
+    }
+
+    const uint32_t flags =
+        lexer.getNextToken(MasterToken::NUMBER).getNumber();
+    if (flags > 0xff) {
+        isc_throw(InvalidRdataText, rrtype_name << " flags out of range: " <<
+                  flags);
+    }
+
+    const uint32_t iterations =
+        lexer.getNextToken(MasterToken::NUMBER).getNumber();
+    if (iterations > 0xffff) {
+        isc_throw(InvalidRdataText, rrtype_name <<
+                  " iterations out of range: " <<
+            iterations);
+    }
+
+    const string salthex =
+        lexer.getNextToken(MasterToken::STRING).getString();
+
+    // Salt is up to 255 bytes, and space is not allowed in the HEX encoding,
+    // so the encoded string cannot be longer than the double of max length
+    // of the actual salt.
+    if (salthex.size() > 255 * 2) {
+        isc_throw(InvalidRdataText, rrtype_name << " salt is too long: "
+                  << salthex.size() << " (encoded) bytes");
+    }
+    if (salthex != "-") {       // "-" means a 0-length salt
+        decodeHex(salthex, salt);
+    }
+
+    return (ParseNSEC3ParamResult(hashalg, flags, iterations));
+}
+
+ParseNSEC3ParamResult
 parseNSEC3ParamWire(const char* const rrtype_name,
                     InputBuffer& buffer,
                     size_t& rdata_len, std::vector<uint8_t>& salt)

+ 6 - 0
src/lib/dns/rdata/generic/detail/nsec3param_common.h

@@ -15,6 +15,8 @@
 #ifndef NSEC3PARAM_COMMON_H
 #define NSEC3PARAM_COMMON_H 1
 
+#include <dns/master_lexer.h>
+
 #include <util/buffer.h>
 
 #include <stdint.h>
@@ -90,6 +92,10 @@ ParseNSEC3ParamResult parseNSEC3ParamText(const char* const rrtype_name,
                                           std::istringstream& iss,
                                           std::vector<uint8_t>& salt);
 
+ParseNSEC3ParamResult parseNSEC3ParamFromLexer(const char* const rrtype_name,
+                                               isc::dns::MasterLexer& lexer,
+                                               std::vector<uint8_t>& salt);
+
 /// \brief Extract NSEC3 parameters from wire-format data.
 ///
 /// This function takes an input buffer that stores wire-format NSEC3 or

+ 37 - 0
src/lib/dns/rdata/generic/nsec3_50.cc

@@ -104,6 +104,43 @@ NSEC3::NSEC3(const std::string& nsec3_str) :
                           salt, next, typebits);
 }
 
+NSEC3::NSEC3(MasterLexer& lexer, const Name*, MasterLoader::Options,
+             MasterLoaderCallbacks&) :
+    impl_(NULL)
+{
+    vector<uint8_t> salt;
+    const ParseNSEC3ParamResult params =
+        parseNSEC3ParamFromLexer("NSEC3", lexer, salt);
+
+    const string nexthash = lexer.getNextToken(MasterToken::STRING).getString();
+    if (*nexthash.rbegin() == '=') {
+        isc_throw(InvalidRdataText, "NSEC3 hash has padding: " << nexthash);
+    }
+
+    vector<uint8_t> next;
+    decodeBase32Hex(nexthash, next);
+    if (next.size() > 255) {
+        isc_throw(InvalidRdataText, "NSEC3 hash is too long: "
+                  << next.size() << " bytes");
+    }
+
+    // For NSEC3 empty bitmap is possible and allowed.
+    if (lexer.getNextToken().getType() == MasterToken::END_OF_FILE) {
+        impl_ = new NSEC3Impl(params.algorithm, params.flags,
+                              params.iterations, salt, next,
+                              vector<uint8_t>());
+        return;
+    }
+
+    lexer.ungetToken();
+
+    vector<uint8_t> typebits;
+    buildBitmapsFromLexer("NSEC3", lexer, typebits);
+
+    impl_ = new NSEC3Impl(params.algorithm, params.flags, params.iterations,
+                          salt, next, typebits);
+}
+
 NSEC3::NSEC3(InputBuffer& buffer, size_t rdata_len) {
     vector<uint8_t> salt;
     const ParseNSEC3ParamResult params =