BIND 10 master, updated. d5f52afdc5419756f514f79ecd53f59090555c43 Merge branch 'master' into trac2497

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Dec 4 06:11:35 UTC 2012


The branch, master has been updated
       via  d5f52afdc5419756f514f79ecd53f59090555c43 (commit)
       via  203b4a05936d027793b03316bffa333e539876ad (commit)
       via  20ff1f4962b99620990c326c50cad7fcef0d16dc (commit)
       via  ec24cb1c279c83107c9058cbdbd9115d84d3ea71 (commit)
       via  1a2787f32f2376d76367516f5cfb3a0059b76474 (commit)
       via  7237139f1b8ec9248fa26e9ae2e6987bfb54f288 (commit)
       via  3e5f22520515b1f1675c3217ff686106201fdfdf (commit)
       via  947a2d7aec3208efe49e266271860982d355c0d8 (commit)
       via  292db149be50cc3a38965be1e14ca1cf26cba2bb (commit)
       via  8ab540a511481e83c8db435c439e291d0f3e52ea (commit)
       via  45b4e930c9fa6e5eb6f8ef7c0c9cdd6818e82f18 (commit)
       via  9e98b4768d26c1ea8accf3f53f9c019ff66347b6 (commit)
       via  43292d60d91cd8656856c88dfefce186412b64b1 (commit)
       via  e3afa9c5286228971db62ff868785602e90a5513 (commit)
       via  c73280d2ebe15512cd4f09ddbb28c2f5030cd86f (commit)
       via  1c4683ddcc108f12b355c5e7b5476671fa6c8a33 (commit)
       via  25f65134a9058c888a4181ba413ec1756e6b1d45 (commit)
       via  5c8cd4010e950d6d0aa68586252c5a3039e5a248 (commit)
       via  3563065b6cc893ab8436973c41eb388dbbecc07e (commit)
       via  41754f406f6edb8d77bd84b34c52c4a2487143a8 (commit)
       via  5e0e2e53c5c5876ae540a0ab26934c0e7242a673 (commit)
       via  2b8518d98293f746baab407d7d6744bde367ced3 (commit)
       via  022d3888199e59b7a4bc256eaaf188a64db61cdf (commit)
       via  aac7b173828dde1f9bfb1807828132b15c58674a (commit)
       via  6921ae3d95c08a6f00f38dae2fb7f14622f49440 (commit)
       via  331d377c8fc5f5a1876cbe52ca714b2a002bb103 (commit)
       via  e980e67482b6b82fab84cd4d2b0aa15f07c23f79 (commit)
       via  0bfb997069b6574b985291a0a50f02487c3614dd (commit)
       via  1b6614825a75916836c64bbf7a52d7913b189910 (commit)
       via  1051eb47c63f0260729de5213cc4f95827edbd3e (commit)
       via  79968a268be53f0804141068ddbb433dc5ff1bbd (commit)
      from  403af3331c71af8cda87fd6ff5fcce407d4f935a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit d5f52afdc5419756f514f79ecd53f59090555c43
Merge: 203b4a0 403af33
Author: Mukund Sivaraman <muks at isc.org>
Date:   Tue Dec 4 10:16:23 2012 +0530

    Merge branch 'master' into trac2497

-----------------------------------------------------------------------

Summary of changes:
 src/lib/dns/Makefile.am                            |    1 +
 src/lib/dns/character_string.cc                    |    7 +-
 src/lib/dns/character_string.h                     |    5 +-
 src/lib/dns/gen-rdatacode.py.in                    |   28 ++++-
 src/lib/{asiodns/logger.cc => dns/master_loader.h} |   19 ++-
 src/lib/dns/master_loader_callbacks.h              |    2 +-
 src/lib/dns/rdata.cc                               |   51 +++++++-
 src/lib/dns/rdata.h                                |   28 ++++-
 src/lib/dns/rdata/generic/hinfo_13.cc              |   24 +++-
 src/lib/dns/rdata/generic/hinfo_13.h               |    9 +-
 src/lib/dns/rrparamregistry-placeholder.cc         |  127 +++++++++++++++-----
 src/lib/dns/rrparamregistry.h                      |   21 +++-
 src/lib/dns/tests/character_string_unittest.cc     |    7 +-
 src/lib/dns/tests/rdata_afsdb_unittest.cc          |   10 ++
 src/lib/dns/tests/rdata_cname_unittest.cc          |    6 +
 src/lib/dns/tests/rdata_dhcid_unittest.cc          |   10 ++
 src/lib/dns/tests/rdata_dname_unittest.cc          |    6 +
 src/lib/dns/tests/rdata_dnskey_unittest.cc         |   11 ++
 src/lib/dns/tests/rdata_ds_like_unittest.cc        |   10 ++
 src/lib/dns/tests/rdata_hinfo_unittest.cc          |   26 +++-
 src/lib/dns/tests/rdata_in_a_unittest.cc           |    5 +
 src/lib/dns/tests/rdata_in_aaaa_unittest.cc        |    6 +
 src/lib/dns/tests/rdata_minfo_unittest.cc          |    6 +
 src/lib/dns/tests/rdata_mx_unittest.cc             |   10 ++
 src/lib/dns/tests/rdata_naptr_unittest.cc          |   13 ++
 src/lib/dns/tests/rdata_ns_unittest.cc             |   10 ++
 src/lib/dns/tests/rdata_nsec3_unittest.cc          |   12 ++
 .../dns/tests/rdata_nsec3param_like_unittest.cc    |   11 ++
 src/lib/dns/tests/rdata_nsec3param_unittest.cc     |    7 ++
 src/lib/dns/tests/rdata_nsec_unittest.cc           |   11 ++
 src/lib/dns/tests/rdata_opt_unittest.cc            |    7 ++
 src/lib/dns/tests/rdata_ptr_unittest.cc            |    6 +
 src/lib/dns/tests/rdata_rp_unittest.cc             |   11 ++
 src/lib/dns/tests/rdata_rrsig_unittest.cc          |   61 +++++-----
 src/lib/dns/tests/rdata_soa_unittest.cc            |    7 ++
 src/lib/dns/tests/rdata_srv_unittest.cc            |   11 ++
 src/lib/dns/tests/rdata_sshfp_unittest.cc          |    6 +
 src/lib/dns/tests/rdata_tsig_unittest.cc           |   10 ++
 src/lib/dns/tests/rdata_txt_like_unittest.cc       |    6 +
 src/lib/dns/tests/rdata_unittest.cc                |   28 +++++
 src/lib/dns/tests/rdata_unittest.h                 |   11 +-
 src/lib/dns/tests/rrparamregistry_unittest.cc      |   40 ++++++
 42 files changed, 610 insertions(+), 93 deletions(-)
 copy src/lib/{asiodns/logger.cc => dns/master_loader.h} (70%)

-----------------------------------------------------------------------
diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am
index 78654aa..88f74fa 100644
--- a/src/lib/dns/Makefile.am
+++ b/src/lib/dns/Makefile.am
@@ -122,6 +122,7 @@ libb10_dns___la_SOURCES += tsigkey.h tsigkey.cc
 libb10_dns___la_SOURCES += tsigrecord.h tsigrecord.cc
 libb10_dns___la_SOURCES += character_string.h character_string.cc
 libb10_dns___la_SOURCES += master_loader_callbacks.h
+libb10_dns___la_SOURCES += master_loader.h
 libb10_dns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
 libb10_dns___la_SOURCES += rdata/generic/detail/nsec_bitmap.cc
 libb10_dns___la_SOURCES += rdata/generic/detail/nsec3param_common.cc
diff --git a/src/lib/dns/character_string.cc b/src/lib/dns/character_string.cc
index 3a289ac..8b31948 100644
--- a/src/lib/dns/character_string.cc
+++ b/src/lib/dns/character_string.cc
@@ -29,7 +29,8 @@ bool isDigit(char c) {
 
 std::string
 characterstr::getNextCharacterString(const std::string& input_str,
-                              std::string::const_iterator& input_iterator)
+                              std::string::const_iterator& input_iterator,
+                              bool* quoted)
 {
     string result;
 
@@ -119,6 +120,10 @@ characterstr::getNextCharacterString(const std::string& input_str,
         isc_throw(InvalidRdataText, "The quotes are not paired");
     }
 
+    if (quoted != NULL) {
+        *quoted = quotes_separated;
+    }
+
     return (result);
 }
 
diff --git a/src/lib/dns/character_string.h b/src/lib/dns/character_string.h
index 2a68778..0bfa38b 100644
--- a/src/lib/dns/character_string.h
+++ b/src/lib/dns/character_string.h
@@ -39,9 +39,12 @@ namespace characterstr {
     /// \param input_iterator The iterator from which to start extracting,
     ///        the iterator will be updated to new position after the function
     ///        is returned
+    /// \param quoted If not \c NULL, returns \c true at this address if
+    ///        the string is quoted, \cfalse otherwise
     /// \return A std::string that contains the extracted <character-string>
     std::string getNextCharacterString(const std::string& input_str,
-                                       std::string::const_iterator& input_iterator);
+                                       std::string::const_iterator& input_iterator,
+                                       bool* quoted = NULL);
 
     /// Get a <character-string> from a input buffer
     ///
diff --git a/src/lib/dns/gen-rdatacode.py.in b/src/lib/dns/gen-rdatacode.py.in
index e51dfc5..5f0f2ef 100755
--- a/src/lib/dns/gen-rdatacode.py.in
+++ b/src/lib/dns/gen-rdatacode.py.in
@@ -24,6 +24,16 @@ from os.path import getmtime
 import re
 import sys
 
+# new_rdata_factory_users[] is a list of tuples of the form (rrtype,
+# rrclass). Items in the list use the (new) RdataFactory class, and
+# items which are not in the list use OldRdataFactory class.
+# Note: rrtype and rrclass must be specified in lowercase in
+# new_rdata_factory_users.
+#
+# Example:
+#     new_rdata_factory_users = [('a', 'in'), ('a', 'ch'), ('soa', 'generic')]
+new_rdata_factory_users = []
+
 re_typecode = re.compile('([\da-z]+)_(\d+)')
 classcode2txt = {}
 typecode2txt = {}
@@ -271,15 +281,29 @@ def generate_rrparam(fileprefix, basemtime):
         class_utxt = class_tuple[1].upper()
         indent = ' ' * 8
         typeandclassparams += indent
+
+        # By default, we use OldRdataFactory (see bug #2497). If you
+        # want to pick RdataFactory for a particular type, add it to
+        # new_rdata_factory_users.  Note that we explicitly generate (for
+        # optimization) class-independent ("generic") factories for class IN
+        # for optimization.
+        if (((type_txt.lower(), class_txt.lower()) in
+             new_rdata_factory_users) or
+            ((class_txt.lower() == 'in') and
+             ((type_txt.lower(), 'generic') in new_rdata_factory_users))):
+            rdf_class = 'RdataFactory'
+        else:
+            rdf_class = 'OldRdataFactory'
+
         if class_tuple[1] != 'generic':
             typeandclassparams += 'add("' + type_utxt + '", '
             typeandclassparams += str(type_code) + ', "' + class_utxt
             typeandclassparams += '", ' + str(class_code)
-            typeandclassparams += ', RdataFactoryPtr(new RdataFactory<'
+            typeandclassparams += ', RdataFactoryPtr(new ' + rdf_class + '<'
             typeandclassparams += class_txt + '::' + type_utxt + '>()));\n'
         else:
             typeandclassparams += 'add("' + type_utxt + '", ' + str(type_code)
-            typeandclassparams += ', RdataFactoryPtr(new RdataFactory<'
+            typeandclassparams += ', RdataFactoryPtr(new ' + rdf_class + '<'
             typeandclassparams += class_txt + '::' + type_utxt + '>()));\n'
 
     rrparam_temp = open(placeholder, 'r')
diff --git a/src/lib/dns/master_loader.h b/src/lib/dns/master_loader.h
new file mode 100644
index 0000000..5ecdd77
--- /dev/null
+++ b/src/lib/dns/master_loader.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef MASTER_LOADER_H
+#define MASTER_LOADER_H
+
+namespace isc {
+namespace dns {
+
+// Placeholder introduced by #2497. The real class should be updated in
+// #2377.
+class MasterLoader {
+public:
+    enum Options {
+         MANY_ERRORS, // lenient mode
+         // also eventually some check policies like "check NS name"
+    };
+};
+
+}
+}
+
+#endif // MASTER_LOADER_H
diff --git a/src/lib/dns/master_loader_callbacks.h b/src/lib/dns/master_loader_callbacks.h
index 2da6e47..77d9ac5 100644
--- a/src/lib/dns/master_loader_callbacks.h
+++ b/src/lib/dns/master_loader_callbacks.h
@@ -119,4 +119,4 @@ private:
 }
 }
 
-#endif // LOADER_CALLBACKS_H
+#endif // MASTER_LOADER_CALLBACKS_H
diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc
index c7eaa13..f8deec6 100644
--- a/src/lib/dns/rdata.cc
+++ b/src/lib/dns/rdata.cc
@@ -65,7 +65,7 @@ createRdata(const RRType& rrtype, const RRClass& rrclass,
     RdataPtr rdata =
         RRParamRegistry::getRegistry().createRdata(rrtype, rrclass, buffer,
                                                    len);
-                                                   
+
     if (buffer.getPosition() - old_pos != len) {
         isc_throw(InvalidRdataLength, "RDLENGTH mismatch: " <<
                   buffer.getPosition() - old_pos << " != " << len);
@@ -81,6 +81,25 @@ createRdata(const RRType& rrtype, const RRClass& rrclass, const Rdata& source)
                                                        source));
 }
 
+RdataPtr
+createRdata(const RRType& rrtype, const RRClass& rrclass,
+            MasterLexer& lexer, const Name* origin,
+            MasterLoader::Options options,
+            MasterLoaderCallbacks& callbacks)
+{
+    RdataPtr ret;
+
+    try {
+        ret = RRParamRegistry::getRegistry().createRdata(rrtype, rrclass,
+                                                         lexer, origin,
+                                                         options, callbacks);
+    } catch (...) {
+        // ret is NULL here.
+    }
+
+    return (ret);
+}
+
 int
 compareNames(const Name& n1, const Name& n2) {
     size_t len1 = n1.getLength();
@@ -119,7 +138,8 @@ Generic::Generic(isc::util::InputBuffer& buffer, size_t rdata_len) {
     impl_ = new GenericImpl(data);
 }
 
-Generic::Generic(const std::string& rdata_string) {
+void
+Generic::constructHelper(const std::string& rdata_string) {
     istringstream iss(rdata_string);
     string unknown_mark;
     iss >> unknown_mark;
@@ -180,6 +200,33 @@ Generic::Generic(const std::string& rdata_string) {
     impl_ = new GenericImpl(data);
 }
 
+Generic::Generic(const std::string& rdata_string) {
+    constructHelper(rdata_string);
+}
+
+Generic::Generic(MasterLexer& lexer, const Name*,
+                 MasterLoader::Options,
+                 MasterLoaderCallbacks&)
+{
+    std::string s;
+
+    while (true) {
+        const MasterLexer::Token& token = lexer.getNextToken();
+        if ((token.getType() == MasterLexer::Token::END_OF_FILE) ||
+            (token.getType() == MasterLexer::Token::END_OF_LINE)) {
+            break;
+        }
+
+        if (!s.empty()) {
+            s += " ";
+        }
+
+        s += token.getString();
+    }
+
+    constructHelper(s);
+}
+
 Generic::~Generic() {
     delete impl_;
 }
diff --git a/src/lib/dns/rdata.h b/src/lib/dns/rdata.h
index f77ea6e..e7811c9 100644
--- a/src/lib/dns/rdata.h
+++ b/src/lib/dns/rdata.h
@@ -15,11 +15,15 @@
 #ifndef RDATA_H
 #define RDATA_H 1
 
-#include <stdint.h>
+#include <dns/master_lexer.h>
+#include <dns/master_loader.h>
+#include <dns/master_loader_callbacks.h>
+
+#include <exceptions/exceptions.h>
 
 #include <boost/shared_ptr.hpp>
 
-#include <exceptions/exceptions.h>
+#include <stdint.h>
 
 namespace isc {
 namespace util {
@@ -279,6 +283,11 @@ public:
     /// \param rdata_len The length in buffer of the \c Rdata.  In bytes.
     Generic(isc::util::InputBuffer& buffer, size_t rdata_len);
 
+    /// \brief Constructor from master lexer.
+    ///
+    Generic(MasterLexer& lexer, const Name* name,
+            MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+
     ///
     /// \brief The destructor.
     virtual ~Generic();
@@ -367,7 +376,10 @@ public:
     /// \return > 0 if \c this would be sorted after \c other.
     virtual int compare(const Rdata& other) const;
     //@}
+
 private:
+    void constructHelper(const std::string& rdata_string);
+
     GenericImpl* impl_;
 };
 
@@ -472,6 +484,14 @@ RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
 /// \c Rdata object.
 RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
                      const Rdata& source);
+
+/// \brief Create RDATA of a given pair of RR type and class from the
+/// master lexer.
+RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
+                     MasterLexer& lexer, const Name* origin,
+                     MasterLoader::Options options,
+                     MasterLoaderCallbacks& callbacks);
+
 //@}
 
 ///
@@ -511,6 +531,6 @@ int compareNames(const Name& n1, const Name& n2);
 }
 #endif  // RDATA_H
 
-// Local Variables: 
+// Local Variables:
 // mode: c++
-// End: 
+// End:
diff --git a/src/lib/dns/rdata/generic/hinfo_13.cc b/src/lib/dns/rdata/generic/hinfo_13.cc
index 12f034c..77bfdfd 100644
--- a/src/lib/dns/rdata/generic/hinfo_13.cc
+++ b/src/lib/dns/rdata/generic/hinfo_13.cc
@@ -39,11 +39,22 @@ using namespace isc::dns::characterstr;
 
 HINFO::HINFO(const std::string& hinfo_str) {
     string::const_iterator input_iterator = hinfo_str.begin();
-    cpu_ = getNextCharacterString(hinfo_str, input_iterator);
 
-    skipLeftSpaces(hinfo_str, input_iterator);
+    bool quoted;
+    cpu_ = getNextCharacterString(hinfo_str, input_iterator, &quoted);
+
+    skipLeftSpaces(hinfo_str, input_iterator, quoted);
 
     os_ = getNextCharacterString(hinfo_str, input_iterator);
+
+    // Skip whitespace at the end.
+    while (input_iterator < hinfo_str.end() && isspace(*input_iterator)) {
+        ++input_iterator;
+    }
+    if (input_iterator < hinfo_str.end()) {
+        isc_throw(InvalidRdataText,
+                  "Invalid HINFO text format: too many fields.");
+    }
 }
 
 HINFO::HINFO(InputBuffer& buffer, size_t rdata_len) {
@@ -108,16 +119,17 @@ HINFO::getOS() const {
 
 void
 HINFO::skipLeftSpaces(const std::string& input_str,
-                      std::string::const_iterator& input_iterator)
+                      std::string::const_iterator& input_iterator,
+                      bool optional)
 {
     if (input_iterator >= input_str.end()) {
         isc_throw(InvalidRdataText,
-                  "Invalid HINFO text format, field is missing.");
+                  "Invalid HINFO text format: field is missing.");
     }
 
-    if (!isspace(*input_iterator)) {
+    if (!isspace(*input_iterator) && !optional) {
         isc_throw(InvalidRdataText,
-            "Invalid HINFO text format, fields are not separated by space.");
+            "Invalid HINFO text format: fields are not separated by space.");
     }
     // Skip white spaces
     while (input_iterator < input_str.end() && isspace(*input_iterator)) {
diff --git a/src/lib/dns/rdata/generic/hinfo_13.h b/src/lib/dns/rdata/generic/hinfo_13.h
index 8513419..5534a7e 100644
--- a/src/lib/dns/rdata/generic/hinfo_13.h
+++ b/src/lib/dns/rdata/generic/hinfo_13.h
@@ -46,10 +46,17 @@ public:
 private:
     /// Skip the left whitespaces of the input string
     ///
+    /// If \c optional argument is \c true and no spaces occur at the
+    /// current location, then nothing happens. If \c optional is
+    /// \c false and no spaces occur at the current location, then
+    /// the \c InvalidRdataText exception is thrown.
+    ///
     /// \param input_str The input string
     /// \param input_iterator From which the skipping started
+    /// \param optional If true, the spaces are optionally skipped.
     void skipLeftSpaces(const std::string& input_str,
-                        std::string::const_iterator& input_iterator);
+                        std::string::const_iterator& input_iterator,
+                        bool optional);
 
     /// Helper template function for toWire()
     ///
diff --git a/src/lib/dns/rrparamregistry-placeholder.cc b/src/lib/dns/rrparamregistry-placeholder.cc
index f7f3a1a..e818e29 100644
--- a/src/lib/dns/rrparamregistry-placeholder.cc
+++ b/src/lib/dns/rrparamregistry-placeholder.cc
@@ -37,10 +37,39 @@ using namespace std;
 using namespace boost;
 
 using namespace isc::util;
-using namespace isc::dns::rdata; 
+using namespace isc::dns::rdata;
 
 namespace isc {
 namespace dns {
+
+namespace rdata {
+
+RdataPtr
+AbstractRdataFactory::create(MasterLexer& lexer, const Name*,
+                             MasterLoader::Options,
+                             MasterLoaderCallbacks&) const
+{
+    std::string s;
+
+    while (true) {
+        const MasterLexer::Token& token = lexer.getNextToken();
+        if ((token.getType() == MasterLexer::Token::END_OF_FILE) ||
+            (token.getType() == MasterLexer::Token::END_OF_LINE)) {
+            break;
+        }
+
+        if (!s.empty()) {
+            s += " ";
+        }
+
+        s += token.getString();
+    }
+
+    return (create(s));
+}
+
+} // end of namespace isc::dns::rdata
+
 namespace {
 ///
 /// The following function and class are a helper to define case-insensitive
@@ -161,8 +190,10 @@ typedef map<RRTypeClass, RdataFactoryPtr> RdataFactoryMap;
 typedef map<RRType, RdataFactoryPtr> GenericRdataFactoryMap;
 
 template <typename T>
-class RdataFactory : public AbstractRdataFactory {
+class OldRdataFactory : public AbstractRdataFactory {
 public:
+    using AbstractRdataFactory::create;
+
     virtual RdataPtr create(const string& rdata_str) const
     {
         return (RdataPtr(new T(rdata_str)));
@@ -179,6 +210,18 @@ public:
     }
 };
 
+template <typename T>
+class RdataFactory : public OldRdataFactory<T> {
+public:
+    using OldRdataFactory<T>::create;
+
+    virtual RdataPtr create(MasterLexer& lexer, const Name* origin,
+                            MasterLoader::Options options,
+                            MasterLoaderCallbacks& callbacks) const {
+        return (RdataPtr(new T(lexer, origin, options, callbacks)));
+    }
+};
+
 ///
 /// \brief The \c RRParamRegistryImpl class is the actual implementation of
 /// \c RRParamRegistry.
@@ -305,7 +348,7 @@ namespace {
 /// This could be simplified using strncasecmp(), but unfortunately it's not
 /// included in <cstring>.  To be as much as portable within the C++ standard
 /// we take the "in house" approach here.
-/// 
+///
 bool CICharEqual(char c1, char c2) {
     return (tolower(static_cast<unsigned char>(c1)) ==
             tolower(static_cast<unsigned char>(c2)));
@@ -468,6 +511,27 @@ RRParamRegistry::codeToClassText(uint16_t code) const {
                                                      impl_->code2classmap));
 }
 
+namespace {
+inline const AbstractRdataFactory*
+findRdataFactory(RRParamRegistryImpl* reg_impl,
+                 const RRType& rrtype, const RRClass& rrclass)
+{
+    RdataFactoryMap::const_iterator found;
+    found = reg_impl->rdata_factories.find(RRTypeClass(rrtype, rrclass));
+    if (found != reg_impl->rdata_factories.end()) {
+        return (found->second.get());
+    }
+
+    GenericRdataFactoryMap::const_iterator genfound =
+        reg_impl->genericrdata_factories.find(rrtype);
+    if (genfound != reg_impl->genericrdata_factories.end()) {
+        return (genfound->second.get());
+    }
+
+    return (NULL);
+}
+}
+
 RdataPtr
 RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
                              const std::string& rdata_string)
@@ -475,16 +539,10 @@ RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
     // If the text indicates that it's rdata of an "unknown" type (beginning
     // with '\# n'), parse it that way. (TBD)
 
-    RdataFactoryMap::const_iterator found;
-    found = impl_->rdata_factories.find(RRTypeClass(rrtype, rrclass));
-    if (found != impl_->rdata_factories.end()) {
-        return (found->second->create(rdata_string));
-    }
-
-    GenericRdataFactoryMap::const_iterator genfound =
-        impl_->genericrdata_factories.find(rrtype);
-    if (genfound != impl_->genericrdata_factories.end()) {
-        return (genfound->second->create(rdata_string));
+    const AbstractRdataFactory* factory =
+        findRdataFactory(impl_, rrtype, rrclass);
+    if (factory != NULL) {
+        return (factory->create(rdata_string));
     }
 
     return (RdataPtr(new generic::Generic(rdata_string)));
@@ -494,16 +552,10 @@ RdataPtr
 RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
                              InputBuffer& buffer, size_t rdata_len)
 {
-    RdataFactoryMap::const_iterator found =
-        impl_->rdata_factories.find(RRTypeClass(rrtype, rrclass));
-    if (found != impl_->rdata_factories.end()) {
-        return (found->second->create(buffer, rdata_len));
-    }
-
-    GenericRdataFactoryMap::const_iterator genfound =
-        impl_->genericrdata_factories.find(rrtype);
-    if (genfound != impl_->genericrdata_factories.end()) {
-        return (genfound->second->create(buffer, rdata_len));
+    const AbstractRdataFactory* factory =
+        findRdataFactory(impl_, rrtype, rrclass);
+    if (factory != NULL) {
+        return (factory->create(buffer, rdata_len));
     }
 
     return (RdataPtr(new generic::Generic(buffer, rdata_len)));
@@ -513,20 +565,29 @@ RdataPtr
 RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
                              const Rdata& source)
 {
-    RdataFactoryMap::const_iterator found =
-        impl_->rdata_factories.find(RRTypeClass(rrtype, rrclass));
-    if (found != impl_->rdata_factories.end()) {
-        return (found->second->create(source));
-    }
-
-    GenericRdataFactoryMap::const_iterator genfound =
-        impl_->genericrdata_factories.find(rrtype);
-    if (genfound != impl_->genericrdata_factories.end()) {
-        return (genfound->second->create(source));
+    const AbstractRdataFactory* factory =
+        findRdataFactory(impl_, rrtype, rrclass);
+    if (factory != NULL) {
+        return (factory->create(source));
     }
 
     return (RdataPtr(new rdata::generic::Generic(
                          dynamic_cast<const generic::Generic&>(source))));
 }
+
+RdataPtr
+RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
+                             MasterLexer& lexer, const Name* name,
+                             MasterLoader::Options options,
+                             MasterLoaderCallbacks& callbacks)
+{
+    const AbstractRdataFactory* factory =
+        findRdataFactory(impl_, rrtype, rrclass);
+    if (factory != NULL) {
+        return (factory->create(lexer, name, options, callbacks));
+    }
+
+    return (RdataPtr(new generic::Generic(lexer, name, options, callbacks)));
+}
 }
 }
diff --git a/src/lib/dns/rrparamregistry.h b/src/lib/dns/rrparamregistry.h
index b1ca225..e156dc9 100644
--- a/src/lib/dns/rrparamregistry.h
+++ b/src/lib/dns/rrparamregistry.h
@@ -82,7 +82,7 @@ public:
     /// \name Factory methods for polymorphic creation.
     ///
     //@{
-    ///
+
     /// \brief Create RDATA from a string.
     ///
     /// This method creates from a string an \c Rdata object of specific class
@@ -91,7 +91,7 @@ public:
     /// \param rdata_str A string of textual representation of the \c Rdata.
     /// \return An \c RdataPtr object pointing to the created \c Rdata object.
     virtual RdataPtr create(const std::string& rdata_str) const = 0;
-    ///
+
     /// \brief Create RDATA from wire-format data.
     ///
     /// This method creates from wire-format binary data an \c Rdata object
@@ -103,7 +103,7 @@ public:
     /// \param rdata_len The length in buffer of the \c Rdata.  In bytes.
     /// \return An \c RdataPtr object pointing to the created \c Rdata object.
     virtual RdataPtr create(isc::util::InputBuffer& buffer, size_t rdata_len) const = 0;
-    ///
+
     /// \brief Create RDATA from another \c Rdata object of the same type.
     ///
     /// This method creates an \c Rdata object of specific class corresponding
@@ -118,6 +118,11 @@ public:
     /// be copied to the created \c Rdata object.
     /// \return An \c RdataPtr object pointing to the created \c Rdata object.
     virtual RdataPtr create(const rdata::Rdata& source) const = 0;
+
+    /// \brief Create RDATA from MasterLexer
+    virtual RdataPtr create(MasterLexer& lexer, const Name*,
+                            MasterLoader::Options,
+                            MasterLoaderCallbacks&) const;
     //@}
 };
 
@@ -498,6 +503,12 @@ public:
     /// \c rdata::Rdata object.
     rdata::RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
                                 const rdata::Rdata& source);
+
+    /// \brief Create RDATA from MasterLexer
+    rdata::RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
+                                MasterLexer& lexer, const Name* name,
+                                MasterLoader::Options options,
+                                MasterLoaderCallbacks& callbacks);
     //@}
 
 private:
@@ -508,6 +519,6 @@ private:
 }
 #endif  // RRPARAMREGISTRY_H
 
-// Local Variables: 
+// Local Variables:
 // mode: c++
-// End: 
+// End:
diff --git a/src/lib/dns/tests/character_string_unittest.cc b/src/lib/dns/tests/character_string_unittest.cc
index 5fed9eb..e8f5884 100644
--- a/src/lib/dns/tests/character_string_unittest.cc
+++ b/src/lib/dns/tests/character_string_unittest.cc
@@ -33,11 +33,13 @@ class CharacterString {
 public:
     CharacterString(const string& str){
         string::const_iterator it = str.begin();
-        characterStr_ = getNextCharacterString(str, it);
+        characterStr_ = getNextCharacterString(str, it, &is_quoted_);
     }
     const string& str() const { return characterStr_; }
+    bool quoted() const { return (is_quoted_); }
 private:
     string characterStr_;
+    bool is_quoted_;
 };
 
 TEST(CharacterStringTest, testNormalCase) {
@@ -47,14 +49,17 @@ TEST(CharacterStringTest, testNormalCase) {
     // Test <character-string> that separated by space
     CharacterString cstr2("foo bar");
     EXPECT_EQ(string("foo"), cstr2.str());
+    EXPECT_FALSE(cstr2.quoted());
 
     // Test <character-string> that separated by quotes
     CharacterString cstr3("\"foo bar\"");
     EXPECT_EQ(string("foo bar"), cstr3.str());
+    EXPECT_TRUE(cstr3.quoted());
 
     // Test <character-string> that not separate by quotes but ended with quotes
     CharacterString cstr4("foo\"");
     EXPECT_EQ(string("foo\""), cstr4.str());
+    EXPECT_FALSE(cstr4.quoted());
 }
 
 TEST(CharacterStringTest, testBadCase) {
diff --git a/src/lib/dns/tests/rdata_afsdb_unittest.cc b/src/lib/dns/tests/rdata_afsdb_unittest.cc
index 521bec5..9bb64b7 100644
--- a/src/lib/dns/tests/rdata_afsdb_unittest.cc
+++ b/src/lib/dns/tests/rdata_afsdb_unittest.cc
@@ -114,6 +114,16 @@ TEST_F(Rdata_AFSDB_Test, createFromWire) {
                  DNSMessageFORMERR);
 }
 
+TEST_F(Rdata_AFSDB_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_afsdb.compare(
+        *test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
+                                     afsdb_text)));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
+                                             "1root.example.com."));
+}
+
 TEST_F(Rdata_AFSDB_Test, toWireBuffer) {
     // construct actual data
     rdata_afsdb.toWire(obuffer);
diff --git a/src/lib/dns/tests/rdata_cname_unittest.cc b/src/lib/dns/tests/rdata_cname_unittest.cc
index 2cce9bc..6451f72 100644
--- a/src/lib/dns/tests/rdata_cname_unittest.cc
+++ b/src/lib/dns/tests/rdata_cname_unittest.cc
@@ -87,6 +87,12 @@ TEST_F(Rdata_CNAME_Test, createFromWire) {
                  InvalidRdataLength);
 }
 
+TEST_F(Rdata_CNAME_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_cname.compare(
+        *test::createRdataUsingLexer(RRType::CNAME(), RRClass::IN(),
+                                     "cn.example.com")));
+}
+
 TEST_F(Rdata_CNAME_Test, toWireBuffer) {
     rdata_cname.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
diff --git a/src/lib/dns/tests/rdata_dhcid_unittest.cc b/src/lib/dns/tests/rdata_dhcid_unittest.cc
index 38b1459..8d56c0e 100644
--- a/src/lib/dns/tests/rdata_dhcid_unittest.cc
+++ b/src/lib/dns/tests/rdata_dhcid_unittest.cc
@@ -63,6 +63,16 @@ TEST_F(Rdata_DHCID_Test, createFromWire) {
     // TBD: more tests
 }
 
+TEST_F(Rdata_DHCID_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_dhcid.compare(
+        *test::createRdataUsingLexer(RRType::DHCID(), RRClass::IN(),
+                                     string_dhcid)));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::DHCID(), RRClass::IN(),
+                                             "00"));
+}
+
 TEST_F(Rdata_DHCID_Test, toWireRenderer) {
     rdata_dhcid.toWire(renderer);
 
diff --git a/src/lib/dns/tests/rdata_dname_unittest.cc b/src/lib/dns/tests/rdata_dname_unittest.cc
index eb221d8..c4e517c 100644
--- a/src/lib/dns/tests/rdata_dname_unittest.cc
+++ b/src/lib/dns/tests/rdata_dname_unittest.cc
@@ -89,6 +89,12 @@ TEST_F(Rdata_DNAME_Test, createFromWire) {
                  InvalidRdataLength);
 }
 
+TEST_F(Rdata_DNAME_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_dname.compare(
+        *test::createRdataUsingLexer(RRType::DNAME(), RRClass::IN(),
+                                     "dn.example.com")));
+}
+
 TEST_F(Rdata_DNAME_Test, toWireBuffer) {
     rdata_dname.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
diff --git a/src/lib/dns/tests/rdata_dnskey_unittest.cc b/src/lib/dns/tests/rdata_dnskey_unittest.cc
index 86b8f69..58d29bf 100644
--- a/src/lib/dns/tests/rdata_dnskey_unittest.cc
+++ b/src/lib/dns/tests/rdata_dnskey_unittest.cc
@@ -82,6 +82,17 @@ TEST_F(Rdata_DNSKEY_Test, DISABLED_badText) {
                  InvalidRdataText);
 }
 
+TEST_F(Rdata_DNSKEY_Test, createFromLexer) {
+    generic::DNSKEY rdata_dnskey(dnskey_txt);
+    EXPECT_EQ(0, rdata_dnskey.compare(
+        *test::createRdataUsingLexer(RRType::DNSKEY(), RRClass::IN(),
+                                     dnskey_txt)));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::DNSKEY(), RRClass::IN(),
+                                             "257 3 5"));
+}
+
 TEST_F(Rdata_DNSKEY_Test, toWireRenderer) {
     renderer.skip(2);
     generic::DNSKEY rdata_dnskey(dnskey_txt);
diff --git a/src/lib/dns/tests/rdata_ds_like_unittest.cc b/src/lib/dns/tests/rdata_ds_like_unittest.cc
index 6172431..28a2e17 100644
--- a/src/lib/dns/tests/rdata_ds_like_unittest.cc
+++ b/src/lib/dns/tests/rdata_ds_like_unittest.cc
@@ -85,6 +85,16 @@ TYPED_TEST(Rdata_DS_LIKE_Test, createFromWire_DS_LIKE) {
                                           "rdata_ds_fromWire")));
 }
 
+TYPED_TEST(Rdata_DS_LIKE_Test, createFromLexer_DS_LIKE) {
+    EXPECT_EQ(0, this->rdata_ds_like.compare(
+        *test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(),
+                                     ds_like_txt)));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(),
+                                             "99999 5 2 BEEF"));
+}
+
 TYPED_TEST(Rdata_DS_LIKE_Test, assignment_DS_LIKE) {
     TypeParam copy((string(ds_like_txt)));
     copy = this->rdata_ds_like;
diff --git a/src/lib/dns/tests/rdata_hinfo_unittest.cc b/src/lib/dns/tests/rdata_hinfo_unittest.cc
index c934a4f..f592066 100644
--- a/src/lib/dns/tests/rdata_hinfo_unittest.cc
+++ b/src/lib/dns/tests/rdata_hinfo_unittest.cc
@@ -41,6 +41,7 @@ static uint8_t hinfo_rdata[] = {0x07,0x50,0x65,0x6e,0x74,0x69,0x75,0x6d,0x05,
 static const char *hinfo_str = "\"Pentium\" \"Linux\"";
 static const char *hinfo_str1 = "\"Pen\\\"tium\" \"Linux\"";
 
+static const char *hinfo_str_equal = "\"Pentium\"\"Linux\"";
 static const char *hinfo_str_small1 = "\"Lentium\" \"Linux\"";
 static const char *hinfo_str_small2 = "\"Pentium\" \"Kinux\"";
 static const char *hinfo_str_large1 = "\"Qentium\" \"Linux\"";
@@ -57,8 +58,11 @@ TEST_F(Rdata_HINFO_Test, createFromText) {
 }
 
 TEST_F(Rdata_HINFO_Test, badText) {
-    // Fields must be seperated by spaces
-    EXPECT_THROW(const HINFO hinfo("\"Pentium\"\"Linux\""), InvalidRdataText);
+    // Only 2 fields must exist
+    EXPECT_THROW(const HINFO hinfo("\"Pentium\"\"Linux\"\"Computer\""),
+                 InvalidRdataText);
+    EXPECT_THROW(const HINFO hinfo("\"Pentium\" \"Linux\" \"Computer\""),
+                 InvalidRdataText);
     // Field cannot be missing
     EXPECT_THROW(const HINFO hinfo("Pentium"), InvalidRdataText);
     // The <character-string> cannot exceed 255 characters
@@ -77,6 +81,23 @@ TEST_F(Rdata_HINFO_Test, createFromWire) {
     EXPECT_EQ(string("Linux"), hinfo.getOS());
 }
 
+TEST_F(Rdata_HINFO_Test, createFromLexer) {
+    HINFO rdata_hinfo(hinfo_str);
+    EXPECT_EQ(0, rdata_hinfo.compare(
+        *test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(),
+                                     hinfo_str)));
+    EXPECT_EQ(0, rdata_hinfo.compare(
+        *test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(),
+                                     "\"Pentium\"\"Linux\"")));
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(),
+                                             "\"Pentium\"\"Linux\""
+                                             "\"Computer\""));
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(),
+                                             "\"Pentium\" \"Linux\" "
+                                             "\"Computer\""));
+}
+
 TEST_F(Rdata_HINFO_Test, toText) {
     HINFO hinfo(hinfo_str);
     EXPECT_EQ(hinfo_str, hinfo.toText());
@@ -107,6 +128,7 @@ TEST_F(Rdata_HINFO_Test, compare) {
     HINFO hinfo_large2(hinfo_str_large2);
 
     EXPECT_EQ(0, hinfo.compare(HINFO(hinfo_str)));
+    EXPECT_EQ(0, hinfo.compare(HINFO(hinfo_str_equal)));
     EXPECT_EQ(1, hinfo.compare(HINFO(hinfo_str_small1)));
     EXPECT_EQ(1, hinfo.compare(HINFO(hinfo_str_small2)));
     EXPECT_EQ(-1, hinfo.compare(HINFO(hinfo_str_large1)));
diff --git a/src/lib/dns/tests/rdata_in_a_unittest.cc b/src/lib/dns/tests/rdata_in_a_unittest.cc
index 2fea9a3..7ab3423 100644
--- a/src/lib/dns/tests/rdata_in_a_unittest.cc
+++ b/src/lib/dns/tests/rdata_in_a_unittest.cc
@@ -68,6 +68,11 @@ TEST_F(Rdata_IN_A_Test, createFromWire) {
                  DNSMessageFORMERR);
 }
 
+TEST_F(Rdata_IN_A_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_in_a.compare(
+        *test::createRdataUsingLexer(RRType::A(), RRClass::IN(), "192.0.2.1")));
+}
+
 TEST_F(Rdata_IN_A_Test, toWireBuffer) {
     rdata_in_a.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
diff --git a/src/lib/dns/tests/rdata_in_aaaa_unittest.cc b/src/lib/dns/tests/rdata_in_aaaa_unittest.cc
index d8ed1d6..74a3e3f 100644
--- a/src/lib/dns/tests/rdata_in_aaaa_unittest.cc
+++ b/src/lib/dns/tests/rdata_in_aaaa_unittest.cc
@@ -66,6 +66,12 @@ TEST_F(Rdata_IN_AAAA_Test, createFromWire) {
                  DNSMessageFORMERR);
 }
 
+TEST_F(Rdata_IN_AAAA_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_in_aaaa.compare(
+        *test::createRdataUsingLexer(RRType::AAAA(), RRClass::IN(),
+                                     "2001:db8::1234")));
+}
+
 TEST_F(Rdata_IN_AAAA_Test, toWireBuffer) {
     rdata_in_aaaa.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
diff --git a/src/lib/dns/tests/rdata_minfo_unittest.cc b/src/lib/dns/tests/rdata_minfo_unittest.cc
index 78e8325..2f717fe 100644
--- a/src/lib/dns/tests/rdata_minfo_unittest.cc
+++ b/src/lib/dns/tests/rdata_minfo_unittest.cc
@@ -103,6 +103,12 @@ TEST_F(Rdata_MINFO_Test, createFromWire) {
                  DNSMessageFORMERR);
 }
 
+TEST_F(Rdata_MINFO_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_minfo.compare(
+        *test::createRdataUsingLexer(RRType::MINFO(), RRClass::IN(),
+                                     minfo_txt)));
+}
+
 TEST_F(Rdata_MINFO_Test, assignment) {
     generic::MINFO copy((string(minfo_txt2)));
     copy = rdata_minfo;
diff --git a/src/lib/dns/tests/rdata_mx_unittest.cc b/src/lib/dns/tests/rdata_mx_unittest.cc
index 7dc774d..6c6039a 100644
--- a/src/lib/dns/tests/rdata_mx_unittest.cc
+++ b/src/lib/dns/tests/rdata_mx_unittest.cc
@@ -62,6 +62,16 @@ TEST_F(Rdata_MX_Test, createFromWire) {
     // TBD: more tests
 }
 
+TEST_F(Rdata_MX_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_mx.compare(
+        *test::createRdataUsingLexer(RRType::MX(), RRClass::IN(),
+                                     "10 mx.example.com")));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::MX(), RRClass::IN(),
+                                             "10 mx. example.com"));
+}
+
 TEST_F(Rdata_MX_Test, toWireRenderer) {
     renderer.writeName(Name("example.com"));
     rdata_mx.toWire(renderer);
diff --git a/src/lib/dns/tests/rdata_naptr_unittest.cc b/src/lib/dns/tests/rdata_naptr_unittest.cc
index 5abcaef..fed98cb 100644
--- a/src/lib/dns/tests/rdata_naptr_unittest.cc
+++ b/src/lib/dns/tests/rdata_naptr_unittest.cc
@@ -128,6 +128,19 @@ TEST_F(Rdata_NAPTR_Test, createFromWire) {
     EXPECT_EQ(Name("_sip._udp.example.com."), naptr.getReplacement());
 }
 
+TEST_F(Rdata_NAPTR_Test, createFromLexer) {
+    const NAPTR rdata_naptr(naptr_str);
+
+    EXPECT_EQ(0, rdata_naptr.compare(
+        *test::createRdataUsingLexer(RRType::NAPTR(), RRClass::IN(),
+                                     naptr_str)));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::NAPTR(), RRClass::IN(),
+                                             "65536 10 S SIP \"\" "
+                                             "_sip._udp.example.com."));
+}
+
 TEST_F(Rdata_NAPTR_Test, toWire) {
     NAPTR naptr(naptr_str);
     naptr.toWire(obuffer);
diff --git a/src/lib/dns/tests/rdata_ns_unittest.cc b/src/lib/dns/tests/rdata_ns_unittest.cc
index 47582ce..d536393 100644
--- a/src/lib/dns/tests/rdata_ns_unittest.cc
+++ b/src/lib/dns/tests/rdata_ns_unittest.cc
@@ -86,6 +86,16 @@ TEST_F(Rdata_NS_Test, createFromWire) {
                  InvalidRdataLength);
 }
 
+TEST_F(Rdata_NS_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_ns.compare(
+        *test::createRdataUsingLexer(RRType::NS(), RRClass::IN(),
+                                     "ns.example.com")));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::NS(), RRClass::IN(),
+                                             ""));
+}
+
 TEST_F(Rdata_NS_Test, toWireBuffer) {
     rdata_ns.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
diff --git a/src/lib/dns/tests/rdata_nsec3_unittest.cc b/src/lib/dns/tests/rdata_nsec3_unittest.cc
index edd2d4b..0fec3eb 100644
--- a/src/lib/dns/tests/rdata_nsec3_unittest.cc
+++ b/src/lib/dns/tests/rdata_nsec3_unittest.cc
@@ -130,6 +130,18 @@ TEST_F(Rdata_NSEC3_Test, createFromWire) {
     }
 }
 
+TEST_F(Rdata_NSEC3_Test, createFromLexer) {
+    const generic::NSEC3 rdata_nsec3(nsec3_txt);
+    EXPECT_EQ(0, rdata_nsec3.compare(
+        *test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(),
+                                     nsec3_txt)));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(),
+                                             "1 1 1 ADDAFEEE CPNMU=== "
+                                             "A NS SOA"));
+}
+
 TEST_F(Rdata_NSEC3_Test, assign) {
     generic::NSEC3 rdata_nsec3(nsec3_txt);
     generic::NSEC3 other_nsec3 = rdata_nsec3;
diff --git a/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc b/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc
index 51fef01..23d6d0e 100644
--- a/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc
+++ b/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc
@@ -208,6 +208,17 @@ TYPED_TEST(NSEC3PARAMLikeTest, createFromWire) {
     EXPECT_EQ(0, this->convert(*rdata).getSalt().size());
 }
 
+TYPED_TEST(NSEC3PARAMLikeTest, createFromLexer) {
+    EXPECT_EQ(0, this->fromText(this->salt_txt).compare(
+        *test::createRdataUsingLexer(this->getType(), RRClass::IN(),
+                                     this->salt_txt)));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(this->getType(), RRClass::IN(),
+                                             "1000000 1 1 ADDAFEEE" +
+                                             this->getCommonText()));
+}
+
 template <typename OUTPUT_TYPE>
 void
 toWireCheck(RRType rrtype, OUTPUT_TYPE& output, const string& data_file) {
diff --git a/src/lib/dns/tests/rdata_nsec3param_unittest.cc b/src/lib/dns/tests/rdata_nsec3param_unittest.cc
index 7558b42..115d3d3 100644
--- a/src/lib/dns/tests/rdata_nsec3param_unittest.cc
+++ b/src/lib/dns/tests/rdata_nsec3param_unittest.cc
@@ -86,6 +86,13 @@ TEST_F(Rdata_NSEC3PARAM_Test, createFromWire) {
     }
 }
 
+TEST_F(Rdata_NSEC3PARAM_Test, createFromLexer) {
+    const generic::NSEC3PARAM rdata_nsec3param(nsec3param_txt);
+    EXPECT_EQ(0, rdata_nsec3param.compare(
+        *test::createRdataUsingLexer(RRType::NSEC3PARAM(), RRClass::IN(),
+                                     nsec3param_txt)));
+}
+
 TEST_F(Rdata_NSEC3PARAM_Test, toWireRenderer) {
     renderer.skip(2);
     const generic::NSEC3PARAM rdata_nsec3param(nsec3param_txt);
diff --git a/src/lib/dns/tests/rdata_nsec_unittest.cc b/src/lib/dns/tests/rdata_nsec_unittest.cc
index 88c6201..4092c6d 100644
--- a/src/lib/dns/tests/rdata_nsec_unittest.cc
+++ b/src/lib/dns/tests/rdata_nsec_unittest.cc
@@ -66,6 +66,17 @@ TEST_F(Rdata_NSEC_Test, createFromWire_NSEC) {
     // Invalid bitmap cases are tested in Rdata_NSECBITMAP_Test.
 }
 
+TEST_F(Rdata_NSEC_Test, createFromLexer_NSEC) {
+    const generic::NSEC rdata_nsec(nsec_txt);
+    EXPECT_EQ(0, rdata_nsec.compare(
+        *test::createRdataUsingLexer(RRType::NSEC(), RRClass::IN(),
+                                     nsec_txt)));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::NSEC(), RRClass::IN(),
+                                             "www.isc.org."));
+}
+
 TEST_F(Rdata_NSEC_Test, toWireRenderer_NSEC) {
     renderer.skip(2);
     const generic::NSEC rdata_nsec(nsec_txt);
diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc
index 698d586..5699259 100644
--- a/src/lib/dns/tests/rdata_opt_unittest.cc
+++ b/src/lib/dns/tests/rdata_opt_unittest.cc
@@ -56,6 +56,13 @@ TEST_F(Rdata_OPT_Test, createFromWire) {
                  InvalidRdataLength);
 }
 
+TEST_F(Rdata_OPT_Test, createFromLexer) {
+    // OPT RR cannot be created from text. Exceptions cause NULL to be
+    // returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::OPT(), RRClass::IN(),
+                                             "this does not matter"));
+}
+
 TEST_F(Rdata_OPT_Test, toWireBuffer) {
     rdata_opt.toWire(obuffer);
     EXPECT_EQ(0, obuffer.getLength());
diff --git a/src/lib/dns/tests/rdata_ptr_unittest.cc b/src/lib/dns/tests/rdata_ptr_unittest.cc
index 86160fb..44b849a 100644
--- a/src/lib/dns/tests/rdata_ptr_unittest.cc
+++ b/src/lib/dns/tests/rdata_ptr_unittest.cc
@@ -90,6 +90,12 @@ TEST_F(Rdata_PTR_Test, createFromWire) {
                  InvalidRdataLength);
 }
 
+TEST_F(Rdata_PTR_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_ptr.compare(
+        *test::createRdataUsingLexer(RRType::PTR(), RRClass::IN(),
+                                     "ns.example.com")));
+}
+
 TEST_F(Rdata_PTR_Test, toWireBuffer) {
     rdata_ptr.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
diff --git a/src/lib/dns/tests/rdata_rp_unittest.cc b/src/lib/dns/tests/rdata_rp_unittest.cc
index 20f32b9..5508d9c 100644
--- a/src/lib/dns/tests/rdata_rp_unittest.cc
+++ b/src/lib/dns/tests/rdata_rp_unittest.cc
@@ -106,6 +106,17 @@ TEST_F(Rdata_RP_Test, createFromParams) {
     EXPECT_EQ(text_name, generic::RP(mailbox_name, text_name).getText());
 }
 
+TEST_F(Rdata_RP_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_rp.compare(
+        *test::createRdataUsingLexer(RRType::RP(), RRClass::IN(),
+                                     "root.example.com. "
+                                     "rp-text.example.com.")));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::RP(), RRClass::IN(),
+                                             "mailbox.example.com."));
+}
+
 TEST_F(Rdata_RP_Test, toWireBuffer) {
     // construct expected data
     UnitTestUtil::readWireData("rdata_rp_toWire1.wire", expected_wire);
diff --git a/src/lib/dns/tests/rdata_rrsig_unittest.cc b/src/lib/dns/tests/rdata_rrsig_unittest.cc
index 3324b99..d758ff3 100644
--- a/src/lib/dns/tests/rdata_rrsig_unittest.cc
+++ b/src/lib/dns/tests/rdata_rrsig_unittest.cc
@@ -36,16 +36,21 @@ using namespace isc::dns::rdata;
 
 namespace {
 class Rdata_RRSIG_Test : public RdataTest {
-    // there's nothing to specialize
+public:
+    Rdata_RRSIG_Test() :
+        rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
+                  "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+                  "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+                  "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+                  "f49t+sXKPzbipN9g+s1ZPiIyofc="),
+        rdata_rrsig(rrsig_txt)
+    {}
+
+    const string rrsig_txt;
+    const generic::RRSIG rdata_rrsig;
 };
 
 TEST_F(Rdata_RRSIG_Test, fromText) {
-    string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
-                     "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
-                     "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
-                     "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
-                     "f49t+sXKPzbipN9g+s1ZPiIyofc=");
-    generic::RRSIG rdata_rrsig(rrsig_txt);
     EXPECT_EQ(rrsig_txt, rdata_rrsig.toText());
     EXPECT_EQ(isc::dns::RRType::A(), rdata_rrsig.typeCovered());
 }
@@ -96,35 +101,37 @@ TEST_F(Rdata_RRSIG_Test, DISABLED_badText) {
                                 "8496isc.org. ofc="), InvalidRdataText);
 }
 
+TEST_F(Rdata_RRSIG_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_rrsig.compare(
+        *test::createRdataUsingLexer(RRType::RRSIG(), RRClass::IN(),
+                                     rrsig_txt)));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::RRSIG(), RRClass::IN(),
+                                             "INVALIDINPUT"));
+}
+
 TEST_F(Rdata_RRSIG_Test, toWireRenderer) {
-    string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
-                     "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
-                     "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
-                     "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
-                     "f49t+sXKPzbipN9g+s1ZPiIyofc=");
-    generic::RRSIG rdata_rrsig(rrsig_txt);
+    // FIXME: This doesn't check the result.
     rdata_rrsig.toWire(renderer);
 }
 
 TEST_F(Rdata_RRSIG_Test, toWireBuffer) {
-    string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
-                     "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
-                     "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
-                     "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
-                     "f49t+sXKPzbipN9g+s1ZPiIyofc=");
-    generic::RRSIG rdata_rrsig(rrsig_txt);
+    // FIXME: This doesn't check the result.
     rdata_rrsig.toWire(obuffer);
 }
 
 TEST_F(Rdata_RRSIG_Test, createFromWire) {
-    string rrsig_txt("A 5 2 43200 20100327070149 20100225070149 2658 isc.org. "
-                "HkJk/xZTvzePU8NENl/ley8bbUumhk1hXciyqhLnz1VQFzkDooej6neX"
-                "ZgWZzQKeTKPOYWrnYtdZW4PnPQFeUl3orgLev7F8J6FZlDn0y/J/ThR5"
-                "m36Mo2/Gdxjj8lJ/IjPVkdpKyBpcnYND8KEIma5MyNCNeyO1UkfPQZGHNSQ=");
-    EXPECT_EQ(rrsig_txt, rdataFactoryFromFile(RRType("RRSIG"), RRClass("IN"),
-                             "rdata_rrsig_fromWire1")->toText());
-    generic::RRSIG rdata_rrsig(rrsig_txt);
-    EXPECT_EQ(0, rdata_rrsig.compare(
+    const string rrsig_txt2(
+        "A 5 2 43200 20100327070149 20100225070149 2658 isc.org. "
+        "HkJk/xZTvzePU8NENl/ley8bbUumhk1hXciyqhLnz1VQFzkDooej6neX"
+        "ZgWZzQKeTKPOYWrnYtdZW4PnPQFeUl3orgLev7F8J6FZlDn0y/J/ThR5"
+        "m36Mo2/Gdxjj8lJ/IjPVkdpKyBpcnYND8KEIma5MyNCNeyO1UkfPQZGHNSQ=");
+    EXPECT_EQ(rrsig_txt2,
+              rdataFactoryFromFile(RRType("RRSIG"), RRClass("IN"),
+                                   "rdata_rrsig_fromWire1")->toText());
+    const generic::RRSIG rdata_rrsig2(rrsig_txt2);
+    EXPECT_EQ(0, rdata_rrsig2.compare(
                       *rdataFactoryFromFile(RRType("RRSIG"), RRClass("IN"),
                                           "rdata_rrsig_fromWire1")));
 
diff --git a/src/lib/dns/tests/rdata_soa_unittest.cc b/src/lib/dns/tests/rdata_soa_unittest.cc
index a9d782c..2df711c 100644
--- a/src/lib/dns/tests/rdata_soa_unittest.cc
+++ b/src/lib/dns/tests/rdata_soa_unittest.cc
@@ -49,6 +49,13 @@ TEST_F(Rdata_SOA_Test, createFromWire) {
     // TBD: more tests
 }
 
+TEST_F(Rdata_SOA_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_soa.compare(
+        *test::createRdataUsingLexer(RRType::SOA(), RRClass::IN(),
+                                     "ns.example.com. root.example.com. "
+                                     "2010012601 3600 300 3600000 1200")));
+}
+
 TEST_F(Rdata_SOA_Test, toWireRenderer) {
     renderer.skip(2);
     rdata_soa.toWire(renderer);
diff --git a/src/lib/dns/tests/rdata_srv_unittest.cc b/src/lib/dns/tests/rdata_srv_unittest.cc
index b194b1c..066755f 100644
--- a/src/lib/dns/tests/rdata_srv_unittest.cc
+++ b/src/lib/dns/tests/rdata_srv_unittest.cc
@@ -119,6 +119,17 @@ TEST_F(Rdata_SRV_Test, createFromWire) {
                                       "rdata_srv_fromWire", 89)));
 }
 
+TEST_F(Rdata_SRV_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_srv.compare(
+        *test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(),
+                                     "1 5 1500 a.example.com.")));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(),
+                                             "1 5 281474976710656 "
+                                             "a.example.com."));
+}
+
 TEST_F(Rdata_SRV_Test, toWireBuffer) {
     rdata_srv.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
diff --git a/src/lib/dns/tests/rdata_sshfp_unittest.cc b/src/lib/dns/tests/rdata_sshfp_unittest.cc
index dccd8b1..6c13ad9 100644
--- a/src/lib/dns/tests/rdata_sshfp_unittest.cc
+++ b/src/lib/dns/tests/rdata_sshfp_unittest.cc
@@ -68,6 +68,12 @@ TEST_F(Rdata_SSHFP_Test, createFromText) {
     EXPECT_EQ(0, rdata_sshfp4.compare(rdata_sshfp));
 }
 
+TEST_F(Rdata_SSHFP_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_sshfp.compare(
+        *test::createRdataUsingLexer(RRType::SSHFP(), RRClass::IN(),
+                                     "2 1 123456789abcdef67890123456789abcdef67890")));
+}
+
 TEST_F(Rdata_SSHFP_Test, algorithmTypes) {
     // Some of these may not be RFC conformant, but we relax the check
     // in our code to work with algorithm and fingerprint types that may
diff --git a/src/lib/dns/tests/rdata_tsig_unittest.cc b/src/lib/dns/tests/rdata_tsig_unittest.cc
index c8ee8ac..df35842 100644
--- a/src/lib/dns/tests/rdata_tsig_unittest.cc
+++ b/src/lib/dns/tests/rdata_tsig_unittest.cc
@@ -247,6 +247,16 @@ TEST_F(Rdata_TSIG_Test, createFromParams) {
                  isc::InvalidParameter);
 }
 
+TEST_F(Rdata_TSIG_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_tsig.compare(
+        *test::createRdataUsingLexer(RRType::TSIG(), RRClass::ANY(),
+                                     valid_text1)));
+
+    // Exceptions cause NULL to be returned.
+    EXPECT_FALSE(test::createRdataUsingLexer(RRType::TSIG(), RRClass::ANY(),
+                                             "foo 0 0 0 0 BADKEY 0 0"));
+}
+
 TEST_F(Rdata_TSIG_Test, assignment) {
     any::TSIG copy((string(valid_text2)));
     copy = rdata_tsig;
diff --git a/src/lib/dns/tests/rdata_txt_like_unittest.cc b/src/lib/dns/tests/rdata_txt_like_unittest.cc
index 981265e..b894fae 100644
--- a/src/lib/dns/tests/rdata_txt_like_unittest.cc
+++ b/src/lib/dns/tests/rdata_txt_like_unittest.cc
@@ -185,6 +185,12 @@ TYPED_TEST(Rdata_TXT_LIKE_Test, createFromWire) {
                  DNSMessageFORMERR);
 }
 
+TYPED_TEST(Rdata_TXT_LIKE_Test, createFromLexer) {
+    EXPECT_EQ(0, this->rdata_txt_like.compare(
+        *test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(),
+                                     "Test String")));
+}
+
 TYPED_TEST(Rdata_TXT_LIKE_Test, toWireBuffer) {
     this->rdata_txt_like.toWire(this->obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
diff --git a/src/lib/dns/tests/rdata_unittest.cc b/src/lib/dns/tests/rdata_unittest.cc
index bf1f5f7..bc91f7a 100644
--- a/src/lib/dns/tests/rdata_unittest.cc
+++ b/src/lib/dns/tests/rdata_unittest.cc
@@ -28,6 +28,8 @@
 #include <dns/tests/unittest_util.h>
 #include <dns/tests/rdata_unittest.h>
 
+#include <boost/bind.hpp>
+
 using isc::UnitTestUtil;
 using namespace std;
 using namespace isc::dns;
@@ -54,6 +56,32 @@ RdataTest::rdataFactoryFromFile(const RRType& rrtype, const RRClass& rrclass,
     uint16_t rdlen = buffer.readUint16();
     return (createRdata(rrtype, rrclass, buffer, rdlen));
 }
+
+namespace test {
+
+void
+dummyCallback(const string&, size_t, const string&) {
+}
+
+RdataPtr
+createRdataUsingLexer(const RRType& rrtype, const RRClass& rrclass,
+                      const std::string& str)
+{
+    std::stringstream ss(str);
+    MasterLexer lexer;
+    lexer.pushSource(ss);
+
+    const MasterLoaderCallbacks::IssueCallback callback
+        (boost::bind(&dummyCallback, _1, _2, _3));
+    MasterLoaderCallbacks callbacks(callback, callback);
+    const Name origin("example.org.");
+
+    return (createRdata(rrtype, rrclass, lexer, &origin,
+                        MasterLoader::MANY_ERRORS, callbacks));
+}
+
+} // end of namespace isc::dns::rdata::test
+
 }
 }
 }
diff --git a/src/lib/dns/tests/rdata_unittest.h b/src/lib/dns/tests/rdata_unittest.h
index f593609..3efb5d8 100644
--- a/src/lib/dns/tests/rdata_unittest.h
+++ b/src/lib/dns/tests/rdata_unittest.h
@@ -41,11 +41,18 @@ protected:
     /// used to test the compare() method against a well-known RR type.
     RdataPtr rdata_nomatch;
 };
+
+namespace test {
+RdataPtr
+createRdataUsingLexer(const RRType& rrtype, const RRClass& rrclass,
+                      const std::string& str);
+}
+
 }
 }
 }
 #endif // RDATA_UNITTEST_H
 
-// Local Variables: 
+// Local Variables:
 // mode: c++
-// End: 
+// End:
diff --git a/src/lib/dns/tests/rrparamregistry_unittest.cc b/src/lib/dns/tests/rrparamregistry_unittest.cc
index c155b53..0ae0a76 100644
--- a/src/lib/dns/tests/rrparamregistry_unittest.cc
+++ b/src/lib/dns/tests/rrparamregistry_unittest.cc
@@ -24,6 +24,10 @@
 #include <dns/rdataclass.h>
 #include <dns/rrparamregistry.h>
 #include <dns/rrtype.h>
+#include <dns/master_loader.h>
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/bind.hpp>
 
 using namespace std;
 using namespace isc::dns;
@@ -104,6 +108,7 @@ TEST_F(RRParamRegistryTest, addError) {
 
 class TestRdataFactory : public AbstractRdataFactory {
 public:
+    using AbstractRdataFactory::create;
     virtual RdataPtr create(const string& rdata_str) const
     { return (RdataPtr(new in::A(rdata_str))); }
     virtual RdataPtr create(InputBuffer& buffer, size_t rdata_len) const
@@ -152,4 +157,39 @@ TEST_F(RRParamRegistryTest, addRemoveFactory) {
                      RRType(test_type_code)));
 }
 
+void
+dummyCallback(const string&, size_t, const string&) {
+}
+
+RdataPtr
+createRdataHelper(const std::string& str) {
+    boost::scoped_ptr<AbstractRdataFactory> rdf(new TestRdataFactory);
+
+    std::stringstream ss(str);
+    MasterLexer lexer;
+    lexer.pushSource(ss);
+
+    const MasterLoaderCallbacks::IssueCallback callback
+        (boost::bind(&dummyCallback, _1, _2, _3));
+    MasterLoaderCallbacks callbacks(callback, callback);
+    const Name origin("example.org.");
+
+    return (rdf->create(lexer, &origin,
+                        MasterLoader::MANY_ERRORS,
+                        callbacks));
+}
+
+TEST_F(RRParamRegistryTest, createFromLexer) {
+    // This test basically checks that the string version of
+    // AbstractRdataFactory::create() is called by the MasterLexer
+    // variant of create().
+    EXPECT_EQ(0, in::A("192.168.0.1").compare(
+              *createRdataHelper("192.168.0.1")));
+
+    // This should parse only up to the end of line. Everything that
+    // comes afterwards is not parsed.
+    EXPECT_EQ(0, in::A("192.168.0.42").compare(
+              *createRdataHelper("192.168.0.42\na b c d e f")));
+}
+
 }



More information about the bind10-changes mailing list