Browse Source

Merge branch 'trac806'

JINMEI Tatuya 14 years ago
parent
commit
4e47d5f6b6

+ 2 - 1
src/lib/dns/rdata.cc

@@ -66,7 +66,8 @@ createRdata(const RRType& rrtype, const RRClass& rrclass,
                                                    len);
                                                    
     if (buffer.getPosition() - old_pos != len) {
-        isc_throw(InvalidRdataLength, "RDLENGTH mismatch");
+        isc_throw(InvalidRdataLength, "RDLENGTH mismatch: " <<
+                  buffer.getPosition() - old_pos << " != " << len);
     }
 
     return (rdata);

+ 11 - 0
src/lib/dns/rdata.h

@@ -161,6 +161,7 @@ public:
     ///
     /// \return A string representation of \c Rdata.
     virtual std::string toText() const = 0;
+
     /// \brief Render the \c Rdata in the wire format into a buffer.
     ///
     /// This is a pure virtual method without the definition; the actual
@@ -169,6 +170,7 @@ public:
     ///
     /// \param buffer An output buffer to store the wire data.
     virtual void toWire(OutputBuffer& buffer) const = 0;
+
     /// \brief Render the \c Rdata in the wire format into a
     /// \c MessageRenderer object.
     ///
@@ -251,6 +253,7 @@ public:
     /// \param rdata_string A string of textual representation of generic
     /// RDATA.
     explicit Generic(const std::string& rdata_string);
+
     ///
     /// \brief Constructor from wire-format data.
     ///
@@ -273,6 +276,7 @@ public:
     /// \c Rdata to parse.
     /// \param rdata_len The length in buffer of the \c Rdata.  In bytes.
     Generic(InputBuffer& buffer, size_t rdata_len);
+
     ///
     /// \brief The destructor.
     virtual ~Generic();
@@ -284,6 +288,7 @@ public:
     ///
     /// \param source A reference to a \c generic::Generic object to copy from.
     Generic(const Generic& source);
+
     ///
     /// \brief The assignment operator.
     ///
@@ -293,6 +298,7 @@ public:
     /// \param source A reference to a \c generic::Generic object to copy from.
     Generic& operator=(const Generic& source);
     //@}
+
     ///
     /// \name Converter methods
     ///
@@ -307,6 +313,7 @@ public:
     ///
     /// \return A string representation of \c generic::Generic.
     virtual std::string toText() const;
+
     ///
     /// \brief Render the \c generic::Generic in the wire format into a buffer.
     ///
@@ -317,6 +324,7 @@ public:
     ///
     /// \param buffer An output buffer to store the wire data.
     virtual void toWire(OutputBuffer& buffer) const;
+
     /// \brief Render the \c generic::Generic in the wire format into a
     /// \c MessageRenderer object.
     ///
@@ -329,6 +337,7 @@ public:
     /// output buffer in which the \c Generic object is to be stored.
     virtual void toWire(MessageRenderer& renderer) const;
     //@}
+
     ///
     /// \name Comparison method
     ///
@@ -421,6 +430,7 @@ std::ostream& operator<<(std::ostream& os, const Generic& rdata);
 /// object.
 RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
                      const std::string& rdata_string);
+
 /// \brief Create RDATA of a given pair of RR type and class from
 /// wire-format data.
 ///
@@ -444,6 +454,7 @@ RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
 /// object.
 RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
                      InputBuffer& buffer, size_t len);
+
 /// \brief Create RDATA of a given pair of RR type and class, copying
 /// of another RDATA of same kind.
 ///

+ 124 - 0
src/lib/dns/rdata/generic/rp_17.cc

@@ -0,0 +1,124 @@
+// Copyright (C) 2011  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.
+
+#include <string>
+#include <sstream>
+
+#include <dns/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+using namespace isc::dns;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+/// \brief Constructor from string.
+///
+/// \c rp_str must be formatted as follows:
+/// \code <mailbox name> <text name>
+/// \endcode
+/// where both fields must represent a valid domain name.
+///
+/// \exception InvalidRdataText The number of RDATA fields (must be 2) is
+/// incorrect.
+/// \exception Other The constructor of the \c Name class will throw if the
+/// given name is invalid.
+/// \exception std::bad_alloc Memory allocation for names fails.
+RP::RP(const std::string& rp_str) :
+    // We cannot construct both names in the initialization list due to the
+    // necessary text processing, so we have to initialize them with a dummy
+    // name and replace them later.
+    mailbox_(Name::ROOT_NAME()), text_(Name::ROOT_NAME())
+{
+    istringstream iss(rp_str);
+    string mailbox_str, text_str;
+    iss >> mailbox_str >> text_str;
+
+    // Validation: A valid RP RR must have exactly two fields.
+    if (iss.bad() || iss.fail()) {
+        isc_throw(InvalidRdataText, "Invalid RP text: " << rp_str);
+    }
+    if (!iss.eof()) {
+        isc_throw(InvalidRdataText, "Invalid RP text (redundant field): "
+                  << rp_str);
+    }
+
+    mailbox_ = Name(mailbox_str);
+    text_ = Name(text_str);
+}
+
+/// \brief Constructor from wire-format data.
+///
+/// This constructor doesn't check the validity of the second parameter (rdata
+/// length) for parsing.
+/// If necessary, the caller will check consistency.
+///
+/// \exception std::bad_alloc Memory allocation for names fails.
+/// \exception Other The constructor of the \c Name class will throw if the
+/// names in the wire is invalid.
+RP::RP(InputBuffer& buffer, size_t) : mailbox_(buffer), text_(buffer) {
+}
+
+/// \brief Copy constructor.
+///
+/// \exception std::bad_alloc Memory allocation fails in copying internal
+/// member variables (this should be very rare).
+RP::RP(const RP& other) :
+    Rdata(), mailbox_(other.mailbox_), text_(other.text_)
+{}
+
+/// \brief Convert the \c RP to a string.
+///
+/// The output of this method is formatted as described in the "from string"
+/// constructor (\c RP(const std::string&))).
+///
+/// \exception std::bad_alloc Internal resource allocation fails.
+///
+/// \return A \c string object that represents the \c RP object.
+std::string
+RP::toText() const {
+    return (mailbox_.toText() + " " + text_.toText());
+}
+
+void
+RP::toWire(OutputBuffer& buffer) const {
+    mailbox_.toWire(buffer);
+    text_.toWire(buffer);
+}
+
+void
+RP::toWire(MessageRenderer& renderer) const {
+    // Type RP is not "well-known", and name compression must be disabled
+    // per RFC3597.
+    renderer.writeName(mailbox_, false);
+    renderer.writeName(text_, false);
+}
+
+int
+RP::compare(const Rdata& other) const {
+    const RP& other_rp = dynamic_cast<const RP&>(other);
+
+    const int cmp = compareNames(mailbox_, other_rp.mailbox_);
+    if (cmp != 0) {
+        return (cmp);
+    }
+    return (compareNames(text_, other_rp.text_));
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE

+ 88 - 0
src/lib/dns/rdata/generic/rp_17.h

@@ -0,0 +1,88 @@
+// Copyright (C) 2011  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.
+
+// BEGIN_HEADER_GUARD
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+// BEGIN_ISC_NAMESPACE
+
+// BEGIN_COMMON_DECLARATIONS
+// END_COMMON_DECLARATIONS
+
+// BEGIN_RDATA_NAMESPACE
+
+/// \brief \c rdata::generic::RP class represents the RP RDATA as defined in
+/// RFC1183.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// RP RDATA.
+class RP : public Rdata {
+public:
+    // BEGIN_COMMON_MEMBERS
+    // END_COMMON_MEMBERS
+
+    /// We use the default copy constructor and assignment operator.
+
+    /// \brief Constructor from RDATA field parameters.
+    ///
+    /// The parameters are a straightforward mapping of %RP RDATA
+    /// fields as defined in RFC1183.
+    RP(const Name& mailbox, const Name& text) :
+        mailbox_(mailbox), text_(text)
+    {}
+
+    /// \brief Return the value of the mailbox field.
+    ///
+    /// This method normally does not throw an exception, but if resource
+    /// allocation for the returned \c Name object fails, a corresponding
+    /// standard exception will be thrown.
+    ///
+    /// \note
+    /// Unlike the case of some other RDATA classes (such as
+    /// \c NS::getNSName()), this method constructs a new \c Name object
+    /// and returns it, instead of returning a reference to a \c Name object
+    /// internally maintained in the class (which is a private member).
+    /// This is based on the observation that this method will be rarely used
+    /// and even when it's used it will not be in a performance context
+    /// (for example, a recursive resolver won't need this field in its
+    /// resolution process).  By returning a new object we have flexibility of
+    /// changing the internal representation without the risk of changing
+    /// the interface or method property.
+    /// The same note applies to the \c getText() method.
+    Name getMailbox() const { return (mailbox_); }
+
+    /// \brief Return the value of the text field.
+    ///
+    /// This method normally does not throw an exception, but if resource
+    /// allocation for the returned \c Name object fails, a corresponding
+    /// standard exception will be thrown.
+    Name getText() const { return (text_); }
+
+private:
+    Name mailbox_;
+    Name text_;
+};
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
+// END_HEADER_GUARD
+
+// Local Variables:
+// mode: c++
+// End:

+ 1 - 0
src/lib/dns/tests/Makefile.am

@@ -39,6 +39,7 @@ run_unittests_SOURCES += rdata_nsec3_unittest.cc
 run_unittests_SOURCES += rdata_nsecbitmap_unittest.cc
 run_unittests_SOURCES += rdata_nsec3param_unittest.cc
 run_unittests_SOURCES += rdata_rrsig_unittest.cc
+run_unittests_SOURCES += rdata_rp_unittest.cc
 run_unittests_SOURCES += rdata_tsig_unittest.cc
 run_unittests_SOURCES += rrset_unittest.cc rrsetlist_unittest.cc
 run_unittests_SOURCES += question_unittest.cc

+ 162 - 0
src/lib/dns/tests/rdata_rp_unittest.cc

@@ -0,0 +1,162 @@
+// Copyright (C) 2011  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.
+
+#include <string>
+
+#include <dns/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/rdataclass.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+
+using isc::UnitTestUtil;
+using namespace std;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+
+namespace {
+class Rdata_RP_Test : public RdataTest {
+protected:
+    Rdata_RP_Test() :
+        mailbox_name("root.example.com."),
+        text_name("rp-text.example.com."),
+        // this also serves as a test for "from text" constructor in a normal
+        // case.
+        rdata_rp("root.example.com. rp-text.example.com."),
+        obuffer(0), renderer(obuffer)
+    {}
+
+    const Name mailbox_name, text_name;
+    const generic::RP rdata_rp; // commonly used test RDATA
+    OutputBuffer obuffer;
+    MessageRenderer renderer;
+    vector<uint8_t> expected_wire;
+};
+
+TEST_F(Rdata_RP_Test, createFromText) {
+    EXPECT_EQ(mailbox_name, rdata_rp.getMailbox());
+    EXPECT_EQ(text_name, rdata_rp.getText());
+
+    // Invalid textual input cases follow:
+    // names are invalid
+    EXPECT_THROW(generic::RP("bad..name. rp-text.example.com"), EmptyLabel);
+    EXPECT_THROW(generic::RP("mailbox.example.com. bad..name"), EmptyLabel);
+
+    // missing field
+    EXPECT_THROW(generic::RP("mailbox.example.com."), InvalidRdataText);
+
+    // redundant field
+    EXPECT_THROW(generic::RP("mailbox.example.com. rp-text.example.com. "
+                             "redundant.example."), InvalidRdataText);
+}
+
+TEST_F(Rdata_RP_Test, createFromWire) {
+    RdataPtr rdata(rdataFactoryFromFile(RRType::RP(), RRClass::IN(),
+                                        "rdata_rp_fromWire1.wire"));
+    EXPECT_EQ(mailbox_name, dynamic_cast<generic::RP&>(*rdata).getMailbox());
+    EXPECT_EQ(text_name, dynamic_cast<generic::RP&>(*rdata).getText());
+
+    // a similar test with names being compressed
+    rdata = rdataFactoryFromFile(RRType::RP(), RRClass::IN(),
+                                 "rdata_rp_fromWire2.wire", 30);
+    EXPECT_EQ(mailbox_name, dynamic_cast<generic::RP&>(*rdata).getMailbox());
+    EXPECT_EQ(Name("rp-text.example.net"),
+              dynamic_cast<generic::RP&>(*rdata).getText());
+}
+
+TEST_F(Rdata_RP_Test, badFromWire) {
+    // RDLEN is too short
+    EXPECT_THROW(rdataFactoryFromFile(RRType::RP(), RRClass::IN(),
+                                      "rdata_rp_fromWire3.wire"),
+                 InvalidRdataLength);
+
+    // RDLEN is too long
+    EXPECT_THROW(rdataFactoryFromFile(RRType::RP(), RRClass::IN(),
+                                      "rdata_rp_fromWire4.wire"),
+                 InvalidRdataLength);
+
+    // bogus mailbox name
+    EXPECT_THROW(rdataFactoryFromFile(RRType::RP(), RRClass::IN(),
+                                      "rdata_rp_fromWire5.wire"),
+                 DNSMessageFORMERR);
+
+    // bogus text name
+    EXPECT_THROW(rdataFactoryFromFile(RRType::RP(), RRClass::IN(),
+                                      "rdata_rp_fromWire6.wire"),
+                 DNSMessageFORMERR);
+}
+
+TEST_F(Rdata_RP_Test, createFromParams) {
+    EXPECT_EQ(mailbox_name, generic::RP(mailbox_name, text_name).getMailbox());
+    EXPECT_EQ(text_name, generic::RP(mailbox_name, text_name).getText());
+}
+
+TEST_F(Rdata_RP_Test, toWireBuffer) {
+    // construct expected data
+    UnitTestUtil::readWireData("rdata_rp_toWire1.wire", expected_wire);
+
+    // construct actual data
+    rdata_rp.toWire(obuffer);
+
+    // then compare them
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        obuffer.getData(), obuffer.getLength(),
+                        &expected_wire[0], expected_wire.size());
+}
+
+TEST_F(Rdata_RP_Test, toWireRenderer) {
+    // similar to toWireBuffer, but names in RDATA could be compressed due to
+    // preceding names.  Actually they must not be compressed according to
+    // RFC3597, and this test checks that.
+
+    UnitTestUtil::readWireData("rdata_rp_toWire2.wire", expected_wire);
+
+    renderer.writeName(Name("a.example.com"));
+    renderer.writeName(Name("b.example.net"));
+    generic::RP(mailbox_name, Name("rp-text.example.net")).toWire(renderer);
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        renderer.getData(), renderer.getLength(),
+                        &expected_wire[0], expected_wire.size());
+}
+
+TEST_F(Rdata_RP_Test, toText) {
+    // there's not much to test for this method.  Only checking a simple case.
+    EXPECT_EQ("root.example.com. rp-text.example.com.", rdata_rp.toText());
+}
+
+TEST_F(Rdata_RP_Test, compare) {
+    // check reflexivity
+    EXPECT_EQ(0, rdata_rp.compare(rdata_rp));
+
+    // names must be compared in case-insensitive manner
+    EXPECT_EQ(0, rdata_rp.compare(generic::RP("ROOT.example.com. "
+                                              "rp-text.EXAMPLE.com.")));
+
+    // another RP whose mailbox name is larger than that of rdata_rp.
+    const generic::RP large1_rp("zzzz.example.com. rp-text.example.com.");
+    EXPECT_GT(0, rdata_rp.compare(large1_rp));
+    EXPECT_LT(0, large1_rp.compare(rdata_rp));
+
+    // yet another RP whose text name is larger than that of rdata_rp.
+    const generic::RP large2_rp("root.example.com. zzzzzzz.example.com.");
+    EXPECT_GT(0, rdata_rp.compare(large2_rp));
+    EXPECT_LT(0, large2_rp.compare(rdata_rp));
+
+    // comparison attempt between incompatible RR types should be rejected
+    EXPECT_THROW(rdata_rp.compare(*RdataTest::rdata_nomatch), bad_cast);
+}
+}

+ 8 - 0
src/lib/dns/tests/testdata/Makefile.am

@@ -16,6 +16,10 @@ BUILT_SOURCES += rdata_nsec3_fromWire10.wire rdata_nsec3_fromWire11.wire
 BUILT_SOURCES += rdata_nsec3_fromWire12.wire rdata_nsec3_fromWire13.wire
 BUILT_SOURCES += rdata_nsec3_fromWire14.wire rdata_nsec3_fromWire15.wire
 BUILT_SOURCES += rdata_rrsig_fromWire2.wire
+BUILT_SOURCES += rdata_rp_fromWire1.wire rdata_rp_fromWire2.wire
+BUILT_SOURCES += rdata_rp_fromWire3.wire rdata_rp_fromWire4.wire
+BUILT_SOURCES += rdata_rp_fromWire5.wire rdata_rp_fromWire6.wire
+BUILT_SOURCES += rdata_rp_toWire1.wire rdata_rp_toWire2.wire
 BUILT_SOURCES += rdata_soa_toWireUncompressed.wire
 BUILT_SOURCES += rdata_txt_fromWire2.wire rdata_txt_fromWire3.wire
 BUILT_SOURCES += rdata_txt_fromWire4.wire rdata_txt_fromWire5.wire
@@ -67,6 +71,10 @@ EXTRA_DIST += rdata_nsec3_fromWire12.spec rdata_nsec3_fromWire13.spec
 EXTRA_DIST += rdata_nsec3_fromWire14.spec rdata_nsec3_fromWire15.spec
 EXTRA_DIST += rdata_opt_fromWire rdata_rrsig_fromWire1
 EXTRA_DIST += rdata_rrsig_fromWire2.spec
+EXTRA_DIST += rdata_rp_fromWire1.spec rdata_rp_fromWire2.spec
+EXTRA_DIST += rdata_rp_fromWire3.spec rdata_rp_fromWire4.spec
+EXTRA_DIST += rdata_rp_fromWire5.spec rdata_rp_fromWire6.spec
+EXTRA_DIST += rdata_rp_toWire1.spec rdata_rp_toWire2.spec
 EXTRA_DIST += rdata_soa_fromWire rdata_soa_toWireUncompressed.spec
 EXTRA_DIST += rdata_txt_fromWire1 rdata_txt_fromWire2.spec
 EXTRA_DIST += rdata_txt_fromWire3.spec rdata_txt_fromWire4.spec

+ 32 - 3
src/lib/dns/tests/testdata/gen-wiredata.py.in

@@ -90,7 +90,7 @@ def encode_name(name, absolute=True):
     for l in labels:
         if len(l) > 4 and l[0:4] == 'ptr=':
             # special meta-syntax for compression pointer
-            wire += ' %04x' % (0xc000 | int(l[4:]))
+            wire += '%04x' % (0xc000 | int(l[4:]))
             break
         if absolute or len(l) > 0:
             wire += '%02x' % len(l)
@@ -277,6 +277,34 @@ class TXT:
                                     ' ' if len(wirestring_list[i]) > 0 else '',
                                     wirestring_list[i]))
 
+class RP:
+    '''Implements rendering RP RDATA in the wire format.
+    Configurable parameters are as follows:
+    - rdlen: 16-bit RDATA length.  If omitted, the accurate value is auto
+      calculated and used; if negative, the RDLEN field will be omitted from
+      the output data.
+    - mailbox: The mailbox field.
+    - text: The text field.
+    All of these parameters have the default values and can be omitted.
+    '''
+    rdlen = None                # auto-calculate
+    mailbox = 'root.example.com'
+    text = 'rp-text.example.com'
+    def dump(self, f):
+        mailbox_wire = encode_name(self.mailbox)
+        text_wire = encode_name(self.text)
+        if self.rdlen is None:
+            self.rdlen = (len(mailbox_wire) + len(text_wire)) / 2
+        else:
+            self.rdlen = int(self.rdlen)
+        if self.rdlen >= 0:
+            f.write('\n# RP RDATA (RDLEN=%d)\n' % self.rdlen)
+            f.write('%04x\n' % self.rdlen)
+        else:
+            f.write('\n# RP RDATA (RDLEN omitted)\n')
+        f.write('# MAILBOX=%s TEXT=%s\n' % (self.mailbox, self.text))
+        f.write('%s %s\n' % (mailbox_wire, text_wire))
+
 class NSECBASE:
     '''Implements rendering NSEC/NSEC3 type bitmaps commonly used for
     these RRs.  The NSEC and NSEC3 classes will be inherited from this
@@ -461,8 +489,9 @@ def get_config_param(section):
                     'header' : (DNSHeader, header_xtables),
                     'question' : (DNSQuestion, question_xtables),
                     'edns' : (EDNS, {}), 'soa' : (SOA, {}), 'txt' : (TXT, {}),
-                    'rrsig' : (RRSIG, {}), 'nsec' : (NSEC, {}),
-                    'nsec3' : (NSEC3, {}), 'tsig' : (TSIG, {}) }
+                    'rp' : (RP, {}), 'rrsig' : (RRSIG, {}),
+                    'nsec' : (NSEC, {}), 'nsec3' : (NSEC3, {}),
+                    'tsig' : (TSIG, {}) }
     s = section
     m = re.match('^([^:]+)/\d+$', section)
     if m:

+ 6 - 0
src/lib/dns/tests/testdata/rdata_rp_fromWire1.spec

@@ -0,0 +1,6 @@
+#
+# A simplest form of RP: all default parameters
+#
+[custom]
+sections: rp
+[rp]

+ 12 - 0
src/lib/dns/tests/testdata/rdata_rp_fromWire2.spec

@@ -0,0 +1,12 @@
+#
+# A simplest form of RP: names are compressed.
+#
+[custom]
+sections: name/1:name/2:rp
+[name/1]
+name: a.example.com
+[name/2]
+name: b.example.net
+[rp]
+mailbox: root.ptr=2
+text: rp-text.ptr=17

+ 7 - 0
src/lib/dns/tests/testdata/rdata_rp_fromWire3.spec

@@ -0,0 +1,7 @@
+#
+# RP-like RDATA but RDLEN is too short.
+#
+[custom]
+sections: rp
+[rp]
+rdlen: 38

+ 7 - 0
src/lib/dns/tests/testdata/rdata_rp_fromWire4.spec

@@ -0,0 +1,7 @@
+#
+# RP-like RDATA but RDLEN is too long.
+#
+[custom]
+sections: rp
+[rp]
+rdlen: 40

+ 7 - 0
src/lib/dns/tests/testdata/rdata_rp_fromWire5.spec

@@ -0,0 +1,7 @@
+#
+# RP-like RDATA but mailbox name is broken.
+#
+[custom]
+sections: rp
+[rp]
+mailbox: "01234567890123456789012345678901234567890123456789012345678901234"

+ 7 - 0
src/lib/dns/tests/testdata/rdata_rp_fromWire6.spec

@@ -0,0 +1,7 @@
+#
+# RP-like RDATA but text name is broken.
+#
+[custom]
+sections: rp
+[rp]
+text: "01234567890123456789012345678901234567890123456789012345678901234"

+ 8 - 0
src/lib/dns/tests/testdata/rdata_rp_toWire1.spec

@@ -0,0 +1,8 @@
+#
+# A simplest form of RP for toWire test: all default parameters except rdlen,
+# which is to be omitted.
+#
+[custom]
+sections: rp
+[rp]
+rdlen: -1

+ 14 - 0
src/lib/dns/tests/testdata/rdata_rp_toWire2.spec

@@ -0,0 +1,14 @@
+#
+# A simple form of RP: names could be compressed (but MUST NOT).
+# rdlen is omitted for the "to wire" test.
+#
+[custom]
+sections: name/1:name/2:rp
+[name/1]
+name: a.example.com
+[name/2]
+name: b.example.net
+[rp]
+rdlen: -1
+mailbox: root.example.com
+text: rp-text.example.net