Browse Source

supported SOA RR

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/f2f200910@212 e5f2f494-b856-4b98-b285-d166d9295462
JINMEI Tatuya 15 years ago
parent
commit
a45fffd3bf
5 changed files with 120 additions and 4 deletions
  1. 1 1
      src/lib/dns/buffer.h
  2. 1 0
      src/lib/dns/name_unittest.cc
  3. 62 2
      src/lib/dns/rrset.cc
  4. 38 0
      src/lib/dns/rrset.h
  5. 18 1
      src/lib/dns/rrset_unittest.cc

+ 1 - 1
src/lib/dns/buffer.h

@@ -104,7 +104,7 @@ public:
     size_t getCurrent() const { return (_readpos); }
     void setCurrent(size_t pos)
     {
-        if (pos >= buf_.size())
+        if (pos > buf_.size())
             throw isc::ISCBufferInvalidPosition();
         _readpos = pos;
     }

+ 1 - 0
src/lib/dns/name_unittest.cc

@@ -79,6 +79,7 @@ TEST_F(NameTest, toFromWire)
     isc::dns::NameDecompressor decompressor;
 
     example_name->toWire(buffer, compressor);
+    buffer.setCurrent(0);
     EXPECT_EQ(std::string("www.example.com."),
               Name(buffer, decompressor).toText(false));
 }

+ 62 - 2
src/lib/dns/rrset.cc

@@ -21,10 +21,11 @@
 
 #include <iostream>
 #include <stdexcept>
-//#include <cstring>
 #include <utility>
 #include <map>
 
+#include <boost/shared_ptr.hpp>
+
 #include <dns/buffer.h>
 #include <dns/rrset.h>
 
@@ -39,6 +40,7 @@ using isc::dns::TTL;
 using isc::dns::Rdata::IN::A;
 using isc::dns::Rdata::IN::AAAA;
 using isc::dns::Rdata::Generic::NS;
+using isc::dns::Rdata::Generic::SOA;
 using isc::dns::Rdata::Generic::TXT;
 using isc::dns::RRset;
 using isc::dns::Rdata::Rdata;
@@ -85,6 +87,8 @@ RRType::RRType(const std::string& typestr)
         typeval_ = 1;
     else if (typestr == "NS")
         typeval_ = 2;
+    else if (typestr == "SOA")
+        typeval_ = 6;
     else if (typestr == "TXT")
         typeval_ = 16;
     else if (typestr == "AAAA")
@@ -100,6 +104,8 @@ RRType::toText() const
         return ("A");
     else if (typeval_ == 2)
         return ("NS");
+    else if (typeval_ == 6)
+        return ("SOA");
     else if (typeval_ == 16)
         return ("TXT");
     else if (typeval_ == 28)
@@ -119,6 +125,7 @@ RRType::toWire(Buffer& buffer) const
 
 const RRType RRType::A("A");
 const RRType RRType::NS("NS");
+const RRType RRType::SOA("SOA");
 const RRType RRType::TXT("TXT");
 const RRType RRType::AAAA("AAAA");
 // ...more to follow
@@ -167,13 +174,17 @@ RdataFactoryRegister::RdataFactoryRegister()
     text_rdata_factory_repository.insert(pair<RRClassTypePair, TextRdataFactory>
                              (RRClassTypePair(RRClass::IN, RRType::AAAA),
                               createDataFromText<isc::dns::Rdata::IN::AAAA>));
-    //XXX: NS/TXT belongs to the 'generic' class.  should revisit it.
+    //XXX: NS/TXT/SOA belongs to the 'generic' class.  should revisit it.
     text_rdata_factory_repository.insert(pair<RRClassTypePair, TextRdataFactory>
                              (RRClassTypePair(RRClass::IN, RRType::NS),
                               createDataFromText<isc::dns::Rdata::Generic::NS>));
     text_rdata_factory_repository.insert(pair<RRClassTypePair, TextRdataFactory>
                              (RRClassTypePair(RRClass::IN, RRType::TXT),
                               createDataFromText<isc::dns::Rdata::Generic::TXT>));
+
+    // "fromText" for SOA is not yet implemented: parsing multi-field RDATA
+    // is not trivial.
+
     // XXX: we should treat class-agnostic type accordingly.
     text_rdata_factory_repository.insert(pair<RRClassTypePair, TextRdataFactory>
                              (RRClassTypePair(RRClass::CH, RRType::TXT),
@@ -188,6 +199,9 @@ RdataFactoryRegister::RdataFactoryRegister()
     wire_rdata_factory_repository.insert(pair<RRClassTypePair, WireRdataFactory>
                              (RRClassTypePair(RRClass::IN, RRType::NS),
                               createDataFromWire<isc::dns::Rdata::Generic::NS>));
+    wire_rdata_factory_repository.insert(pair<RRClassTypePair, WireRdataFactory>
+                             (RRClassTypePair(RRClass::IN, RRType::SOA),
+                              createDataFromWire<isc::dns::Rdata::Generic::SOA>));
 }
 
 Rdata *
@@ -322,6 +336,52 @@ NS::copy() const
     return (new NS(toText()));
 }
 
+SOA::SOA(Buffer& buffer, NameDecompressor& decompressor)
+{
+    size_t len = buffer.readUint16();
+    mname_ = Name(buffer, decompressor);
+    rname_ = Name(buffer, decompressor);
+    serial_ = buffer.readUint32();
+    refresh_ = buffer.readUint32();
+    retry_ = buffer.readUint32();
+    expire_ = buffer.readUint32();
+    ttl_ = TTL(buffer.readUint32());
+}
+
+void
+SOA::toWire(Buffer& buffer, NameCompressor& compressor) const
+{
+    // XXX: note that a complete implementation cannot be this simple
+    // because we need to disable compression for the NS name.
+    buffer.writeUint16(mname_.getLength() + rname_.getLength() +
+                       5 * sizeof(uint32_t));
+    mname_.toWire(buffer, compressor);
+    rname_.toWire(buffer, compressor);
+    buffer.writeUint32(serial_);
+    buffer.writeUint32(refresh_);
+    buffer.writeUint32(retry_);
+    buffer.writeUint32(expire_);
+    ttl_.toWire(buffer);
+}
+
+std::string
+SOA::toText() const
+{
+    return (mname_.toText() + " " + rname_.toText() + " " +
+            boost::lexical_cast<std::string>(serial_) + " " +
+            boost::lexical_cast<std::string>(refresh_) + " " +
+            boost::lexical_cast<std::string>(retry_) + " " +
+            boost::lexical_cast<std::string>(expire_) + " " +
+            ttl_.toText());
+}
+
+Rdata*
+SOA::copy() const
+{
+    return (new SOA(mname_.toText(), rname_.toText(), serial_, refresh_, retry_,
+                    expire_, ttl_));
+}
+
 TXT::TXT(const std::string& text_data)
 {
     size_t length = text_data.size();

+ 38 - 0
src/lib/dns/rrset.h

@@ -81,6 +81,7 @@ public:
     // (Some) Well-known RRtype constants
     static const RRType A;
     static const RRType NS;
+    static const RRType SOA;
     static const RRType TXT;
     static const RRType AAAA;
     // more to follow...
@@ -166,6 +167,43 @@ private:
     Name nsname_;
 };
 
+class SOA : public Rdata::Rdata {
+public:
+    SOA() {}
+    explicit SOA(const std::string& mname, const std::string& rname,
+                 uint32_t serial, uint32_t refresh, uint32_t retry,
+                 uint32_t expire, const TTL& ttl) :
+        mname_(mname), rname_(rname), serial_(serial), refresh_(refresh),
+        retry_(retry), expire_(expire), ttl_(ttl) {}
+    explicit SOA(Buffer& buffer, NameDecompressor& decompressor);
+    unsigned int count() const { return (1); }
+    const RRType& getType() const { return (RRType::SOA); }
+    static const RRType& getTypeStatic() { return (RRType::SOA); }
+    std::string toText() const;
+    void toWire(Buffer& buffer, NameCompressor& compressor) const;
+    bool operator==(const SOA &other) const;
+    virtual bool operator!=(const SOA &other) const
+    { return !(*this == other); }
+    virtual Rdata* copy() const;
+private:
+    Name mname_;
+    Name rname_;
+    uint32_t serial_;
+    uint32_t refresh_;
+    uint32_t retry_;
+    uint32_t expire_;
+    TTL ttl_;
+};
+
+inline bool
+SOA::operator==(const SOA& other) const
+{
+    return (mname_ == other.mname_ && rname_ == other.rname_ &&
+            serial_ == other.serial_ && refresh_ == other.refresh_ &&
+            retry_ == other.retry_ && expire_ == other.expire_ &&
+            ttl_ == other.ttl_);
+}
+
 // A quick hack implementation of TXT RR.  It currently supports only one
 // "character-string".
 class TXT : public Rdata::Rdata {

+ 18 - 1
src/lib/dns/rrset_unittest.cc

@@ -30,6 +30,7 @@ using isc::dns::Rdata::Rdata;
 using isc::dns::Rdata::IN::A;
 using isc::dns::Rdata::IN::AAAA;
 using isc::dns::Rdata::Generic::NS;
+using isc::dns::Rdata::Generic::SOA;
 using isc::dns::Rdata::Generic::TXT;
 using isc::dns::RRset;
 using isc::dns::RR;
@@ -114,7 +115,7 @@ TEST_F(Rdata_IN_A_Test, fromToText)
     EXPECT_THROW(A("2001:db8::1234"), isc::ISCInvalidAddressString);
 }
 
-// The fixture for testing class IN/AAAA Rdata
+// The fixture for testing IN/AAAA Rdata class
 class Rdata_IN_AAAA_Test : public ::testing::Test {
 protected:
     Rdata_IN_AAAA_Test() : rdata("2001:db8::abcd") {}
@@ -139,6 +140,22 @@ TEST_F(Rdata_Generic_NS_Test, fromToText)
     EXPECT_EQ("ns.example.com.", rdata.toText());
 }
 
+// The fixture for testing class Generic/SOA Rdata
+class Rdata_Generic_SOA_Test : public ::testing::Test {
+protected:
+    Rdata_Generic_SOA_Test()
+    {
+        rdata = SOA("ns.example.com", "root.example.com", 2009102700, 7200,
+                    3600, 24796800, TTL(1200));
+    }
+    SOA rdata;
+};
+
+TEST_F(Rdata_Generic_SOA_Test, fromToText)
+{
+    EXPECT_EQ("ns.example.com. root.example.com. 2009102700 7200 3600 24796800 1200", rdata.toText());
+}
+
 // The fixture for testing Generic/TXT Rdata class
 class Rdata_Generic_TXT_Test : public ::testing::Test {
 protected: