[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