[svn] commit: r513 - in /branches/jinmei-dnsrdata/src/lib/dns/cpp: rdata.cc rdata.h rdata_unittest.cc rrparamregistry.cc testdata/rdata_in_aaaa_fromWire testdata/rdata_mx_fromWire testdata/rdata_mx_toWire1 testdata/rdata_soa_fromWire

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Jan 26 09:56:32 UTC 2010


Author: jinmei
Date: Tue Jan 26 09:56:32 2010
New Revision: 513

Log:
quick implementation of AAAA/SOA/MX Rdata

Added:
    branches/jinmei-dnsrdata/src/lib/dns/cpp/testdata/rdata_in_aaaa_fromWire
    branches/jinmei-dnsrdata/src/lib/dns/cpp/testdata/rdata_mx_fromWire
    branches/jinmei-dnsrdata/src/lib/dns/cpp/testdata/rdata_mx_toWire1
    branches/jinmei-dnsrdata/src/lib/dns/cpp/testdata/rdata_soa_fromWire
Modified:
    branches/jinmei-dnsrdata/src/lib/dns/cpp/rdata.cc
    branches/jinmei-dnsrdata/src/lib/dns/cpp/rdata.h
    branches/jinmei-dnsrdata/src/lib/dns/cpp/rdata_unittest.cc
    branches/jinmei-dnsrdata/src/lib/dns/cpp/rrparamregistry.cc

Modified: branches/jinmei-dnsrdata/src/lib/dns/cpp/rdata.cc
==============================================================================
--- branches/jinmei-dnsrdata/src/lib/dns/cpp/rdata.cc (original)
+++ branches/jinmei-dnsrdata/src/lib/dns/cpp/rdata.cc Tue Jan 26 09:56:32 2010
@@ -20,6 +20,7 @@
 #include <stdint.h>
 #include <string.h>
 
+#include <boost/lexical_cast.hpp>
 #include <boost/shared_ptr.hpp>
 
 #include <arpa/inet.h> // XXX: for inet_pton/ntop(), not exist in C++ standards
@@ -109,6 +110,7 @@
 Generic::toText() const
 {
     // return rdata in the \# n xx xx format (TBD)
+    dns_throw(InvalidRdataText, "Not implemented yet");
 }
 
 void
@@ -176,6 +178,147 @@
     const NS& other_ns = dynamic_cast<const NS&>(other);
 
     return (compareNames(nsname_, other_ns.nsname_));
+}
+
+SOA::SOA(InputBuffer& buffer, size_t rdata_len) :
+    mname_(buffer), rname_(buffer)
+{
+    // we don't need rdata_len for parsing.  if necessary, the caller will
+    // check consistency.
+    buffer.readData(numdata_, sizeof(numdata_));
+}
+
+SOA::SOA(const std::string& soastr) :
+    mname_("."), rname_(".")
+{
+    dns_throw(InvalidRdataText, "Not implemented yet");
+}
+
+SOA::SOA(const Name& mname, const Name& rname, uint32_t serial,
+         uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum) :
+    mname_(mname), rname_(rname)
+{
+    OutputBuffer b(20);
+    b.writeUint32(serial);
+    b.writeUint32(refresh);
+    b.writeUint32(retry);
+    b.writeUint32(expire);
+    b.writeUint32(minimum);
+    assert(b.getLength() == sizeof(numdata_));
+    memcpy(numdata_, b.getData(), sizeof(numdata_));
+}
+
+SOA::SOA(const SOA& other) :
+    mname_(other.mname_), rname_(other.rname_)
+{
+    memcpy(numdata_, other.numdata_, sizeof(numdata_));
+}
+
+void
+SOA::toWire(OutputBuffer& buffer) const
+{
+    mname_.toWire(buffer);
+    rname_.toWire(buffer);
+    buffer.writeData(numdata_, sizeof(numdata_));
+}
+
+void
+SOA::toWire(MessageRenderer& renderer) const
+{
+    renderer.writeName(mname_);
+    renderer.writeName(rname_);
+    renderer.writeData(numdata_, sizeof(numdata_));
+}
+
+string
+SOA::toText() const
+{
+    InputBuffer b(numdata_, sizeof(numdata_));
+    uint32_t serial = b.readUint32();
+    uint32_t refresh = b.readUint32();
+    uint32_t retry = b.readUint32();
+    uint32_t expire = b.readUint32();
+    uint32_t minimum = b.readUint32();
+
+    return (mname_.toText() + " " + rname_.toText() + " " +
+            lexical_cast<string>(serial) + " " +
+            lexical_cast<string>(refresh) + " " +
+            lexical_cast<string>(retry) + " " +
+            lexical_cast<string>(expire) + " " +
+            lexical_cast<string>(minimum));
+}
+
+int
+SOA::compare(const Rdata& other) const
+{
+    const SOA& other_soa = dynamic_cast<const SOA&>(other);
+
+    int order = compareNames(mname_, other_soa.mname_);
+    if (order != 0) {
+        return (order);
+    }
+
+    order = compareNames(rname_, other_soa.rname_);
+    if (order != 0) {
+        return (order);
+    }
+
+    return (memcmp(numdata_, other_soa.numdata_, sizeof(numdata_)));
+}
+
+MX::MX(InputBuffer& buffer, size_t rdata_len) :
+    preference_(buffer.readUint16()), mxname_(buffer)
+{
+    // we don't need rdata_len for parsing.  if necessary, the caller will
+    // check consistency.
+}
+
+MX::MX(const std::string& soastr) :
+    preference_(0), mxname_(".")
+{
+    dns_throw(InvalidRdataText, "Not implemented yet");
+}
+
+MX::MX(uint16_t preference, const Name& mxname) :
+    preference_(preference), mxname_(mxname)
+{}
+
+MX::MX(const MX& other) :
+    preference_(other.preference_), mxname_(other.mxname_)
+{}
+
+void
+MX::toWire(OutputBuffer& buffer) const
+{
+    buffer.writeUint16(preference_);
+    mxname_.toWire(buffer);
+}
+
+void
+MX::toWire(MessageRenderer& renderer) const
+{
+    renderer.writeUint16(preference_);
+    renderer.writeName(mxname_);
+}
+
+string
+MX::toText() const
+{
+    return (lexical_cast<string>(preference_) + " " + mxname_.toText());
+}
+
+int
+MX::compare(const Rdata& other) const
+{
+    const MX& other_mx = dynamic_cast<const MX&>(other);
+
+    if (preference_ < other_mx.preference_) {
+        return (-1);
+    } else if (preference_ > other_mx.preference_) {
+        return (1);
+    }
+
+    return (compareNames(mxname_, other_mx.mxname_));
 }
 
 } // end of namespace generic
@@ -235,6 +378,58 @@
     const A& other_a = dynamic_cast<const A&>(other);
     return (memcmp(&addr_, &other_a.addr_, sizeof(addr_)));
 }
+
+AAAA::AAAA(const string& addrstr)
+{
+    if (inet_pton(AF_INET6, addrstr.c_str(), &addr_) != 1) {
+        dns_throw(InvalidRdataText,
+                  "failed to parse IPv6 address for IN/AAAA RDATA");
+    }
+}
+
+AAAA::AAAA(InputBuffer& buffer, size_t rdata_len)
+{
+    if (rdata_len != sizeof(addr_)) {
+        dns_throw(InvalidRdataLength, "Length mismatch for IN/AAAA RDATA");
+    }
+    buffer.readData(&addr_, sizeof(addr_));
+}
+
+AAAA::AAAA(const AAAA& other)
+{
+    memcpy(addr_, other.addr_, sizeof(addr_));
+}
+
+void
+AAAA::toWire(OutputBuffer& buffer) const
+{
+    buffer.writeData(&addr_, sizeof(addr_));
+}
+
+void
+AAAA::toWire(MessageRenderer& renderer) const
+{
+    renderer.writeData(&addr_, sizeof(addr_));
+}
+
+string
+AAAA::toText() const
+{
+    char addr_string[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+
+    if (inet_ntop(AF_INET6, &addr_, addr_string, sizeof(addr_string)) == NULL) {
+        dns_throw(Unexpected, "inet_ntop failed for an IPv6 address");
+    }
+
+    return (string(addr_string));
+}
+
+int
+AAAA::compare(const Rdata& other) const
+{
+    const AAAA& other_a = dynamic_cast<const AAAA&>(other);
+    return (memcmp(&addr_, &other_a.addr_, sizeof(addr_)));
+}
 } // end of namespace in
 
 namespace ch {
@@ -269,6 +464,7 @@
 A::toText() const
 {
     // TBD
+    dns_throw(InvalidRdataText, "Not implemented yet");
 }
 
 int

Modified: branches/jinmei-dnsrdata/src/lib/dns/cpp/rdata.h
==============================================================================
--- branches/jinmei-dnsrdata/src/lib/dns/cpp/rdata.h (original)
+++ branches/jinmei-dnsrdata/src/lib/dns/cpp/rdata.h Tue Jan 26 09:56:32 2010
@@ -139,24 +139,82 @@
 private:
     Name nsname_;
 };
+
+class SOA : public Rdata {
+public:
+    explicit SOA(const std::string& namestr);
+    explicit SOA(InputBuffer& buffer, size_t rdata_len);
+    explicit SOA(const Name& mname, const Name& rname, uint32_t serial,
+                 uint32_t refresh, uint32_t retry, uint32_t expire,
+                 uint32_t minimum);
+    SOA(const SOA& other);
+    virtual ~SOA() {}
+    virtual std::string toText() const;
+    virtual void toWire(OutputBuffer& buffer) const;
+    virtual void toWire(MessageRenderer& buffer) const;
+    virtual int compare(const Rdata& other) const;
+private:
+    /// Note: this is a prototype version; we may reconsider
+    /// this representation later.
+    Name mname_;
+    Name rname_;
+    /// serial, refresh, retry, expire, minimum, stored in network byte order
+    uint8_t numdata_[20];
+};
+
+class MX : public Rdata {
+public:
+    explicit MX(const std::string& namestr);
+    explicit MX(InputBuffer& buffer, size_t rdata_len);
+    explicit MX(uint16_t preference, const Name& mxname);
+    MX(const MX& other);
+    virtual std::string toText() const;
+    virtual void toWire(OutputBuffer& buffer) const;
+    virtual void toWire(MessageRenderer& buffer) const;
+    virtual int compare(const Rdata& other) const;
+private:
+    /// Note: this is a prototype version; we may reconsider
+    /// this representation later.
+    uint16_t preference_;
+    Name mxname_;
+};
 } // end of namespace "generic"
 
 namespace in {
 class A : public Rdata {
 public:
-    /// Constructor from a textual IPv4 address.
+    /// \brief Constructor from a textual IPv4 address.
     explicit A(const std::string& addrstr);
     explicit A(InputBuffer& buffer, size_t rdata_len);
     A(const A& ohter);
-    virtual ~A() {}
-    std::string toText() const;
-    virtual void toWire(OutputBuffer& buffer) const;
-    virtual void toWire(MessageRenderer& renderer) const;
+    virtual std::string toText() const;
+    virtual void toWire(OutputBuffer& buffer) const;
+    virtual void toWire(MessageRenderer& renderer) const;
+    virtual int compare(const Rdata& other) const;
+    //We can use the default destructor.
+    //virtual ~A() {}
     // notyet:
     //const struct in_addr& getAddress() const { return (addr_); }
-    virtual int compare(const Rdata& other) const;
 private:
     uint32_t addr_;             // raw IPv4 address (network byte order)
+};
+
+class AAAA : public Rdata {
+public:
+    /// \brief Constructor from a textual IPv6 address.
+    explicit AAAA(const std::string& addrstr);
+    explicit AAAA(InputBuffer& buffer, size_t rdata_len);
+    AAAA(const AAAA& ohter);
+    virtual std::string toText() const;
+    virtual void toWire(OutputBuffer& buffer) const;
+    virtual void toWire(MessageRenderer& renderer) const;
+    virtual int compare(const Rdata& other) const;
+    //We can use the default destructor.
+    //virtual ~AAAA() {}
+    // notyet:
+    //const struct in6_addr& getAddress() const { return (addr_); }
+private:
+    uint8_t addr_[16];        // raw IPv6 address (network byte order)
 };
 } // end of namespace "in"
 
@@ -166,7 +224,7 @@
     explicit A(const std::string& addrstr);
     explicit A(InputBuffer& buffer, size_t rdata_len);
     A(const A& ohter);
-    std::string toText() const;
+    virtual std::string toText() const;
     virtual void toWire(OutputBuffer& buffer) const;
     virtual void toWire(MessageRenderer& renderer) const;
     virtual int compare(const Rdata& other) const;

Modified: branches/jinmei-dnsrdata/src/lib/dns/cpp/rdata_unittest.cc
==============================================================================
--- branches/jinmei-dnsrdata/src/lib/dns/cpp/rdata_unittest.cc (original)
+++ branches/jinmei-dnsrdata/src/lib/dns/cpp/rdata_unittest.cc Tue Jan 26 09:56:32 2010
@@ -14,6 +14,8 @@
 
 // $Id: rrtype_unittest.cc 476 2010-01-19 00:29:28Z jinmei $
 
+#include <vector>
+
 #include "buffer.h"
 #include "messagerenderer.h"
 #include "rdata.h"
@@ -40,18 +42,30 @@
     OutputBuffer obuffer;
     MessageRenderer renderer;
     static const in::A rdata_in_a;
+    static const in::AAAA rdata_in_aaaa;
     static const uint8_t wiredata_in_a[];
+    static const uint8_t wiredata_in_aaaa[];
     static const uint8_t wiredata_ns[];
     static const uint8_t wiredata_ns2[];
     static const generic::NS rdata_ns;
     static const generic::NS rdata_ns2;
+    static const generic::SOA rdata_soa;
+    static const generic::MX rdata_mx;
 };
 
 const in::A RdataTest::rdata_in_a("192.0.2.1");
+const in::AAAA RdataTest::rdata_in_aaaa("2001:db8::1234");
 const generic::NS RdataTest::rdata_ns("ns.example.com");
 const generic::NS RdataTest::rdata_ns2("ns2.example.com");
+const generic::SOA RdataTest::rdata_soa(Name("ns.example.com"),
+                                        Name("root.example.com"),
+                                        2010012601, 3600, 300, 3600000, 1200);
+const generic::MX RdataTest::rdata_mx(10, Name("mx.example.com"));
 
 const uint8_t RdataTest::wiredata_in_a[] = { 192, 0, 2, 1 };
+const uint8_t RdataTest::wiredata_in_aaaa[] = {
+    0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x12, 0x34 };
 const uint8_t RdataTest::wiredata_ns[] = {
     0x02, 0x6e, 0x73, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
     0x63, 0x6f, 0x6d, 0x00 };
@@ -154,6 +168,65 @@
     EXPECT_THROW(rdata_in_a.compare(rdata_ns), bad_cast); 
 }
 
+TEST_F(RdataTest, createFromText_IN_AAAA)
+{
+    rdata_in_aaaa.compare(in::AAAA(string("2001:db8::1234")));
+    EXPECT_THROW(in::AAAA("192.0.2.1"), InvalidRdataText);
+    EXPECT_THROW(in::AAAA("xxx"), InvalidRdataText);
+}
+
+TEST_F(RdataTest, createFromWire_IN_AAAA)
+{
+    // Valid data
+    EXPECT_EQ(0, rdata_in_aaaa.compare(
+                  *rdataFactoryFromFile(RRType("AAAA"), RRClass("IN"),
+                                        "testdata/rdata_in_aaaa_fromWire")));
+    //TBD: more tests
+}
+
+TEST_F(RdataTest, toWireBuffer_IN_AAAA)
+{
+    rdata_in_aaaa.toWire(obuffer);
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        obuffer.getData(), obuffer.getLength(),
+                        wiredata_in_aaaa, sizeof(wiredata_in_aaaa));
+}
+
+TEST_F(RdataTest, toWireRenderer_IN_AAAA)
+{
+    rdata_in_aaaa.toWire(renderer);
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        obuffer.getData(), obuffer.getLength(),
+                        wiredata_in_aaaa, sizeof(wiredata_in_aaaa));
+}
+
+TEST_F(RdataTest, toText_IN_AAAA)
+{
+    EXPECT_EQ("2001:db8::1234", rdata_in_aaaa.toText());
+}
+
+TEST_F(RdataTest, compare_IN_AAAA)
+{
+    in::AAAA small1("::1");
+    in::AAAA small2("1:2:3:4:5:6:7:8");
+    in::AAAA large1("ffff::");
+    in::AAAA large2("8:7:6:5:4:3:2:1");
+
+    // trivial case: self equivalence
+    EXPECT_EQ(0, small1.compare(small1));
+
+    // confirm these are compared as unsigned values
+    EXPECT_GT(0, small1.compare(large1));
+    EXPECT_LT(0, large1.compare(small1));
+
+    // confirm these are compared in network byte order
+    EXPECT_GT(0, small2.compare(large2));
+    EXPECT_LT(0, large2.compare(small2));
+
+    // comparison attempt between incompatible RR types should be rejected
+    EXPECT_THROW(rdata_in_aaaa.compare(rdata_ns), bad_cast); 
+}
+
 TEST_F(RdataTest, createFromText_NS)
 {
     EXPECT_EQ(0, rdata_ns.compare(generic::NS("ns.example.com")));
@@ -222,4 +295,86 @@
     EXPECT_GT(0, small.compare(large));
 }
 
-}
+TEST_F(RdataTest, createFromText_SOA)
+{
+    //TBD
+}
+
+TEST_F(RdataTest, createFromWire_SOA)
+{
+    EXPECT_EQ(0, rdata_soa.compare(
+                  *rdataFactoryFromFile(RRType("SOA"), RRClass("IN"),
+                                        "testdata/rdata_soa_fromWire")));
+    // TBD: more tests
+}
+
+TEST_F(RdataTest, toWireRenderer_SOA)
+{
+    renderer.skip(2);
+    rdata_soa.toWire(renderer);
+
+    vector<unsigned char> data;
+    UnitTestUtil::readWireData("testdata/rdata_soa_fromWire", data);
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        static_cast<const uint8_t *>(obuffer.getData()) + 2,
+                        obuffer.getLength() - 2, &data[0] + 2, data.size() - 2);
+}
+
+TEST_F(RdataTest, toText_SOA)
+{
+    EXPECT_EQ("ns.example.com. root.example.com. "
+              "2010012601 3600 300 3600000 1200", rdata_soa.toText());
+}
+
+TEST_F(RdataTest, createFromText_MX)
+{
+    //TBD
+}
+
+TEST_F(RdataTest, createFromWire_MX)
+{
+    EXPECT_EQ(0, rdata_mx.compare(
+                  *rdataFactoryFromFile(RRType("MX"), RRClass("IN"),
+                                        "testdata/rdata_mx_fromWire")));
+    // TBD: more tests
+}
+
+TEST_F(RdataTest, toWireRenderer_MX)
+{
+    renderer.writeName(Name("example.com"));
+    rdata_mx.toWire(renderer);
+
+    vector<unsigned char> data;
+    UnitTestUtil::readWireData("testdata/rdata_mx_toWire1", data);
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),
+                        obuffer.getLength(), &data[0], data.size());
+}
+
+TEST_F(RdataTest, toText_MX)
+{
+    EXPECT_EQ("10 mx.example.com.", rdata_mx.toText());
+}
+
+TEST_F(RdataTest, compare_IN_MX)
+{
+    generic::MX small1(1, Name("mx.example.com"));
+    generic::MX small2(10, Name("mx.example.com"));
+    generic::MX large1(65535, Name("mx.example.com"));
+    generic::MX large2(256, Name("mx.example.com"));
+
+    // trivial case: self equivalence
+    EXPECT_EQ(0, small1.compare(small1));
+
+    // confirm these are compared as unsigned values
+    EXPECT_GT(0, small1.compare(large1));
+    EXPECT_LT(0, large1.compare(small1));
+
+    // confirm these are compared in network byte order
+    EXPECT_GT(0, small2.compare(large2));
+    EXPECT_LT(0, large2.compare(small2));
+
+    // comparison attempt between incompatible RR types should be rejected
+    EXPECT_THROW(rdata_mx.compare(rdata_ns), bad_cast); 
+}
+
+}

Modified: branches/jinmei-dnsrdata/src/lib/dns/cpp/rrparamregistry.cc
==============================================================================
--- branches/jinmei-dnsrdata/src/lib/dns/cpp/rrparamregistry.cc (original)
+++ branches/jinmei-dnsrdata/src/lib/dns/cpp/rrparamregistry.cc Tue Jan 26 09:56:32 2010
@@ -170,7 +170,11 @@
     // set up parameters for well-known RRs
     // XXX: this should eventually be more automatic.
     try {
+        // Class-IN specific types
         add("A", 1, "IN", 1, RdataFactoryPtr(new RdataFactory<in::A>()));
+        add("AAAA", 28, "IN", 1, RdataFactoryPtr(new RdataFactory<in::AAAA>()));
+
+        // Class-CH specific types
         add("A", 1, "CH", 3, RdataFactoryPtr(new RdataFactory<ch::A>()));
 
         // should we add factories for class-independent (generic) types to
@@ -178,17 +182,18 @@
         // of "generic" as a last resort?
         add("NS", 2, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NS>()));
         add("NS", 2, "CH", 3, RdataFactoryPtr(new RdataFactory<generic::NS>()));
-
-        // XXX merge this to add().
-        //impl_->rdata_factories.insert(
-        //  pair<RRTypeClass, RdataFactoryPtr>(RRTypeClass(RRType(2),
-        //                                                 RRClass(1)),
-        //                                     RdataFactoryPtr(new RdataFactory<generic::NS>())));
+        add("SOA", 6, "IN", 1,
+            RdataFactoryPtr(new RdataFactory<generic::SOA>()));
+        add("SOA", 6, "CH", 3,
+            RdataFactoryPtr(new RdataFactory<generic::SOA>()));
+        add("MX", 15, "IN", 1,
+            RdataFactoryPtr(new RdataFactory<generic::MX>()));
+        add("MX", 15, "CH", 3,
+            RdataFactoryPtr(new RdataFactory<generic::MX>()));
     } catch (...) {
         delete impl_;
         throw;
     }
-    //...
 }
 
 RRParamRegistry::~RRParamRegistry()




More information about the bind10-changes mailing list