[svn] commit: r1039 - in /trunk/src/lib/dns/cpp: ./ tests/ tests/testdata/

BIND 10 source code commits bind10-changes at lists.isc.org
Sun Feb 28 08:39:15 UTC 2010


Author: jinmei
Date: Sun Feb 28 08:39:14 2010
New Revision: 1039

Log:
checkpoint: supported EDNS0 DO bit, receive side.

Added:
    trunk/src/lib/dns/cpp/tests/testdata/message_fromWire2
    trunk/src/lib/dns/cpp/tests/testdata/message_fromWire3
    trunk/src/lib/dns/cpp/tests/testdata/message_fromWire4
    trunk/src/lib/dns/cpp/tests/testdata/message_fromWire5
    trunk/src/lib/dns/cpp/tests/testdata/message_fromWire6
    trunk/src/lib/dns/cpp/tests/testdata/message_fromWire7
Modified:
    trunk/src/lib/dns/cpp/message.cc
    trunk/src/lib/dns/cpp/message.h
    trunk/src/lib/dns/cpp/name.h
    trunk/src/lib/dns/cpp/tests/message_unittest.cc
    trunk/src/lib/dns/cpp/tests/name_unittest.cc

Modified: trunk/src/lib/dns/cpp/message.cc
==============================================================================
--- trunk/src/lib/dns/cpp/message.cc (original)
+++ trunk/src/lib/dns/cpp/message.cc Sun Feb 28 08:39:14 2010
@@ -54,6 +54,8 @@
 static const flags_t FLAG_RA = 0x0080;
 static const flags_t FLAG_AD = 0x0020;
 static const flags_t FLAG_CD = 0x0010;
+
+static const flags_t EXTFLAG_DO = 0x8000;
 
 static const unsigned int OPCODE_MASK = 0x7800;
 static const unsigned int OPCODE_SHIFT = 11;
@@ -151,7 +153,18 @@
     return (rcodetext[code_]);
 }
 
-struct MessageImpl {
+namespace {
+inline unsigned int
+sectionCodeToId(const Section& section)
+{
+    unsigned int code = section.getCode();
+    assert(code > 0);
+    return (section.getCode() - 1);
+}
+}
+
+class MessageImpl {
+public:
     MessageImpl();
     // Open issues: should we rather have a header in wire-format
     // for efficiency?
@@ -159,39 +172,51 @@
     const Rcode* rcode_;
     const Opcode* opcode_;
     flags_t flags_;
+    bool dnssec_ok_;
 
     static const unsigned int SECTION_MAX = 4; // TODO: revisit this design
     int counts_[SECTION_MAX];   // TODO: revisit this definition
     vector<QuestionPtr> questions_;
     vector<RRsetPtr> rrsets_[SECTION_MAX];
+    RRsetPtr edns_;
 
 #ifdef notyet
     // tsig/sig0: TODO
-    EDNS* edns_;
     RRsetsSorter* sorter_;
 #endif
 
+    void init();
     void parseQuestion(Message& message, InputBuffer& buffer);
     void parseSection(Message& messge, const Section& section,
                       InputBuffer& buffer);
 };
 
 MessageImpl::MessageImpl() :
-    qid_(0), rcode_(NULL), opcode_(NULL), flags_(0)
+    qid_(0), rcode_(NULL), opcode_(NULL), flags_(0), dnssec_ok_(false)
 {
     for (int i = 0; i < SECTION_MAX; i++) {
         counts_[i] = 0;
     }
 }
 
-namespace {
-inline unsigned int
-sectionCodeToId(const Section& section)
-{
-    unsigned int code = section.getCode();
-    assert(code > 0);
-    return (section.getCode() - 1);
-}
+void
+MessageImpl::init()
+{
+    flags_ = 0;
+    qid_ = 0;
+    rcode_ = NULL;
+    opcode_ = NULL;
+    dnssec_ok_ = false;
+    edns_ = RRsetPtr();
+
+    for (int i = 0; i < SECTION_MAX; i++) {
+        counts_[i] = 0;
+    }
+
+    questions_.clear();
+    rrsets_[sectionCodeToId(Section::ANSWER())].clear();
+    rrsets_[sectionCodeToId(Section::AUTHORITY())].clear();
+    rrsets_[sectionCodeToId(Section::ADDITIONAL())].clear();
 }
 
 Message::Message() :
@@ -220,6 +245,12 @@
 Message::clearHeaderFlag(const MessageFlag& flag)
 {
     impl_->flags_ &= ~flag.getBit();
+}
+
+bool
+Message::isDNSSECSupported() const
+{
+    return (impl_->dnssec_ok_);
 }
 
 qid_t
@@ -436,6 +467,30 @@
         RRTTL ttl(buffer.readUint32());
         size_t rdlen = buffer.readUint16();
         RdataPtr rdata = createRdata(rrtype, rrclass, buffer, rdlen);
+
+        // XXX: we wanted to avoid hardcoding type-specific logic here,
+        // but this would be the fastest way for a proof-of-concept
+        // implementation.  We'll revisit this part later.
+        if (rrtype == RRType::OPT()) {
+            if (section != Section::ADDITIONAL()) {
+                dns_throw(DNSMessageFORMERR,
+                          "EDNS OPT RR found in an invalid section");
+            }
+            if (edns_ != NULL) {
+                dns_throw(DNSMessageFORMERR, "multiple EDNS OPT RR found");
+            }
+            if (name != Name::ROOT_NAME()) {
+                dns_throw(DNSMessageFORMERR,
+                          "invalid owner name for  EDNS OPT RR");
+            }
+
+            edns_ = RRsetPtr(new RRset(name, rrclass, rrtype, ttl));
+            edns_->addRdata(rdata);
+
+            dnssec_ok_ = (((ttl.getValue() & 0xffff) & EXTFLAG_DO) != 0);
+
+            continue;
+        }
 
         vector<RRsetPtr>::iterator it =
             find_if(rrsets_[sectionCodeToId(section)].begin(),
@@ -546,14 +601,23 @@
 }
 
 void
+Message::clear()
+{
+    impl_->init();
+}
+
+void
 Message::makeResponse()
 {
     impl_->flags_ &= MESSAGE_REPLYPRESERVE;
     setHeaderFlag(MessageFlag::QR());
 
     impl_->rrsets_[sectionCodeToId(Section::ANSWER())].clear();
+    impl_->counts_[Section::ANSWER().getCode()] = 0;
     impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].clear();
+    impl_->counts_[Section::AUTHORITY().getCode()] = 0;
     impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].clear();
+    impl_->counts_[Section::ADDITIONAL().getCode()] = 0;
 }
 
 ///

Modified: trunk/src/lib/dns/cpp/message.h
==============================================================================
--- trunk/src/lib/dns/cpp/message.h (original)
+++ trunk/src/lib/dns/cpp/message.h Sun Feb 28 08:39:14 2010
@@ -20,14 +20,27 @@
 #include <iterator>
 #include <string>
 
-#include <boost/shared_ptr.hpp>
-
 #include <exceptions/exceptions.h>
 #include "question.h"
 #include "rrset.h"
 
 namespace isc {
 namespace dns {
+
+///
+/// \brief A standard DNS module exception ...[TBD]
+///
+class DNSProtocolError : public Exception {
+public:
+    DNSProtocolError(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+class DNSMessageFORMERR : public DNSProtocolError {
+public:
+    DNSMessageFORMERR(const char* file, size_t line, const char* what) :
+        DNSProtocolError(file, line, what) {}
+};
 
 ///
 /// \brief A standard DNS module exception ...[TBD]
@@ -403,6 +416,8 @@
     unsigned int getCode() const { return (code_); }
     bool operator==(const Section& other) const
         { return (code_ == other.code_); }
+    bool operator!=(const Section& other) const
+        { return (code_ != other.code_); }
 
     static const Section& QUESTION();
     static const Section& ANSWER();
@@ -474,11 +489,13 @@
     ~Message();
 private:
     Message(const Message& source);
-    void operator=(const Message& source);
+    Message& operator=(const Message& source);
 public:
     bool getHeaderFlag(const MessageFlag& flag) const;
     void setHeaderFlag(const MessageFlag& flag);
     void clearHeaderFlag(const MessageFlag& flag);
+    bool isDNSSECSupported() const;
+    void setDNSSECSupported(bool on);
     qid_t getQid() const;
     void setQid(qid_t qid);
     const Rcode& getRcode() const;
@@ -509,45 +526,26 @@
     //void addRR(const Section& section, const RR& rr);
     //void removeRR(const Section& section, const RR& rr);
 
+    void clear();
+
     // prepare for making a response from a request.  This will clear the
     // DNS header except those fields that should be kept for the response,
     // and clear answer and the following sections.
     // see also dns_message_reply() of BIND9.
     void makeResponse();
 
-    /// Render message
+    /// \brief Render message.
     void toWire(MessageRenderer& renderer);
 
     /// \brief Parse a DNS message.
     void fromWire(InputBuffer& buffer);
 
-public:
-    // public protocol constants
-    static const rcode_t RCODE_NOERROR = 0;
-    static const rcode_t RCODE_FORMERR = 1;
-    static const rcode_t RCODE_SERVFAIL = 2;
-    static const rcode_t RCODE_NXDOMAIN = 3;
-    static const rcode_t RCODE_NOTIMP = 4;
-    static const rcode_t RCODE_REFUSED = 5;
-    static const rcode_t RCODE_YXDOMAIN = 6;
-    static const rcode_t RCODE_YXRRSET = 7;
-    static const rcode_t RCODE_NXRRSET = 8;
-    static const rcode_t RCODE_NOTAUTH = 9;
-    static const rcode_t RCODE_NOTZONE = 10;
-    // ...more to follow
-
-    static const opcode_t OPCODE_QUERY = 0;
-    static const opcode_t OPCODE_IQUERY = 1;
-    static const opcode_t OPCODE_STATUS = 2;
-    static const opcode_t OPCODE_NOTIFY = 4;
-    static const opcode_t OPCODE_UPDATE = 5;
-
 private:
     MessageImpl* impl_;
 };
 
-std::ostream& operator<<(std::ostream& os, const Opcode& rrset);
-std::ostream& operator<<(std::ostream& os, const Rcode& rrset);
+std::ostream& operator<<(std::ostream& os, const Opcode& opcode);
+std::ostream& operator<<(std::ostream& os, const Rcode& rcode);
 std::ostream& operator<<(std::ostream& os, const Message& message);
 }
 }

Modified: trunk/src/lib/dns/cpp/name.h
==============================================================================
--- trunk/src/lib/dns/cpp/name.h (original)
+++ trunk/src/lib/dns/cpp/name.h Sun Feb 28 08:39:14 2010
@@ -599,12 +599,27 @@
     static const uint16_t COMPRESS_POINTER_MARK16 = 0xc000;
     //@}
 
+    ///
+    /// \name Well-known name constants
+    ///
+    //@{
+    /// \brief Root name (i.e. ".").
+    static const Name& ROOT_NAME();
+    //@}
+
 private:
     std::string ndata_;
     std::vector<unsigned char> offsets_;
     unsigned int length_;
     unsigned int labelcount_;
 };
+
+inline const Name&
+Name::ROOT_NAME()
+{
+    static Name root_name(".");
+    return (root_name);
+}
 
 ///
 /// \brief Insert the name as a string into stream.

Modified: trunk/src/lib/dns/cpp/tests/message_unittest.cc
==============================================================================
--- trunk/src/lib/dns/cpp/tests/message_unittest.cc (original)
+++ trunk/src/lib/dns/cpp/tests/message_unittest.cc Sun Feb 28 08:39:14 2010
@@ -44,6 +44,8 @@
     static void factoryFromFile(Message& message, const char* datafile);
 };
 
+const Name test_name("test.example.com");
+
 void
 MessageTest::factoryFromFile(Message& message, const char* datafile)
 {
@@ -65,12 +67,16 @@
     EXPECT_TRUE(message.getHeaderFlag(MessageFlag::AA()));
 
     QuestionPtr q = *message.beginQuestion();
-    EXPECT_EQ(Name("test.example.com"), q->getName());
+    EXPECT_EQ(test_name, q->getName());
     EXPECT_EQ(RRType::A(), q->getType());
     EXPECT_EQ(RRClass::IN(), q->getClass());
+    EXPECT_EQ(1, message.getRRCount(Section::QUESTION()));
+    EXPECT_EQ(2, message.getRRCount(Section::ANSWER()));
+    EXPECT_EQ(0, message.getRRCount(Section::AUTHORITY()));
+    EXPECT_EQ(0, message.getRRCount(Section::ADDITIONAL()));
 
     RRsetPtr rrset = *message.beginSection(Section::ANSWER());
-    EXPECT_EQ(Name("test.example.com"), rrset->getName());
+    EXPECT_EQ(test_name, rrset->getName());
     EXPECT_EQ(RRType::A(), rrset->getType());
     EXPECT_EQ(RRClass::IN(), rrset->getClass());
     // TTL should be 3600, even though that of the 2nd RR is 7200
@@ -82,6 +88,40 @@
     EXPECT_EQ("192.0.2.2", it->getCurrent().toText());
     it->next();
     EXPECT_TRUE(it->isLast());
+}
+
+TEST_F(MessageTest, EDNS0DOBit)
+{
+    factoryFromFile(message, "testdata/message_fromWire1");
+    EXPECT_FALSE(message.isDNSSECSupported());
+
+    message.clear();
+    factoryFromFile(message, "testdata/message_fromWire2");
+    EXPECT_TRUE(message.isDNSSECSupported());
+
+    message.clear();
+    factoryFromFile(message, "testdata/message_fromWire3");
+    EXPECT_FALSE(message.isDNSSECSupported());
+}
+
+TEST_F(MessageTest, BadEDNS0)
+{
+    // OPT RR in the answer section
+    EXPECT_THROW(factoryFromFile(message, "testdata/message_fromWire4"),
+                 DNSMessageFORMERR);
+    // multiple OPT RRs (in the additional section)
+    message.clear();
+    EXPECT_THROW(factoryFromFile(message, "testdata/message_fromWire5"),
+                 DNSMessageFORMERR);
+    // OPT RR of a non root name
+    message.clear();
+    EXPECT_THROW(factoryFromFile(message, "testdata/message_fromWire6"),
+                 DNSMessageFORMERR);
+    // Compressed owner name of OPT RR points to a root name.
+    // Not necessarily bogus, but very unusual and mostly pathological.
+    // We accept it, but is it okay?
+    message.clear();
+    EXPECT_NO_THROW(factoryFromFile(message, "testdata/message_fromWire7"));
 }
 
 TEST_F(MessageTest, toWire)

Modified: trunk/src/lib/dns/cpp/tests/name_unittest.cc
==============================================================================
--- trunk/src/lib/dns/cpp/tests/name_unittest.cc (original)
+++ trunk/src/lib/dns/cpp/tests/name_unittest.cc Sun Feb 28 08:39:14 2010
@@ -583,6 +583,11 @@
     EXPECT_FALSE(small_name > large_name);
 }
 
+TEST_F(NameTest, constants)
+{
+    EXPECT_EQ(Name("."), Name::ROOT_NAME());
+}
+
 // test operator<<.  We simply confirm it appends the result of toText().
 TEST_F(NameTest, LeftShiftOperator)
 {




More information about the bind10-changes mailing list