Browse Source

checkpoint: more support for incoming EDNS0 (unsupported version handling,
UDP buffer size)


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1047 e5f2f494-b856-4b98-b285-d166d9295462

JINMEI Tatuya 15 years ago
parent
commit
21b837ca58

+ 18 - 7
src/lib/dns/cpp/message.cc

@@ -179,6 +179,7 @@ public:
     vector<QuestionPtr> questions_;
     vector<RRsetPtr> rrsets_[SECTION_MAX];
     RRsetPtr edns_;
+    uint16_t udpsize_;
 
 #ifdef notyet
     // tsig/sig0: TODO
@@ -191,12 +192,9 @@ public:
                       InputBuffer& buffer);
 };
 
-MessageImpl::MessageImpl() :
-    qid_(0), rcode_(NULL), opcode_(NULL), flags_(0), dnssec_ok_(false)
+MessageImpl::MessageImpl()
 {
-    for (int i = 0; i < SECTION_MAX; i++) {
-        counts_[i] = 0;
-    }
+    init();
 }
 
 void
@@ -208,6 +206,7 @@ MessageImpl::init()
     opcode_ = NULL;
     dnssec_ok_ = false;
     edns_ = RRsetPtr();
+    udpsize_ = Message::DEFAULT_MAX_UDPSIZE;
 
     for (int i = 0; i < SECTION_MAX; i++) {
         counts_[i] = 0;
@@ -253,6 +252,12 @@ Message::isDNSSECSupported() const
     return (impl_->dnssec_ok_);
 }
 
+uint16_t
+Message::getUDPSize() const
+{
+    return (impl_->udpsize_);
+}
+
 qid_t
 Message::getQid() const
 {
@@ -479,16 +484,22 @@ MessageImpl::parseSection(Message& messge, const Section& section,
             if (edns_ != NULL) {
                 dns_throw(DNSMessageFORMERR, "multiple EDNS OPT RR found");
             }
+            if (((ttl.getValue() & 0x00ff0000) >> 16) >
+                Message::EDNS0_SUPPORTED_VERSION) {
+                dns_throw(DNSMessageBADVERS, "unsupported EDNS version");
+            }
             if (name != Name::ROOT_NAME()) {
                 dns_throw(DNSMessageFORMERR,
-                          "invalid owner name for  EDNS OPT RR");
+                          "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);
-
+            if (rrclass.getCode() > Message::DEFAULT_MAX_UDPSIZE) {
+                udpsize_ = rrclass.getCode();
+            }
             continue;
         }
 

+ 22 - 1
src/lib/dns/cpp/message.h

@@ -42,6 +42,12 @@ public:
         DNSProtocolError(file, line, what) {}
 };
 
+class DNSMessageBADVERS : public DNSProtocolError {
+public:
+    DNSMessageBADVERS(const char* file, size_t line, const char* what) :
+        DNSProtocolError(file, line, what) {}
+};
+
 ///
 /// \brief A standard DNS module exception ...[TBD]
 ///
@@ -495,7 +501,8 @@ public:
     void setHeaderFlag(const MessageFlag& flag);
     void clearHeaderFlag(const MessageFlag& flag);
     bool isDNSSECSupported() const;
-    void setDNSSECSupported(bool on);
+    void setDNSSECSupported(bool on); // not yet
+    uint16_t getUDPSize() const;
     qid_t getQid() const;
     void setQid(qid_t qid);
     const Rcode& getRcode() const;
@@ -540,6 +547,20 @@ public:
     /// \brief Parse a DNS message.
     void fromWire(InputBuffer& buffer);
 
+    ///
+    /// \name Protocol constants
+    ///
+    //@{
+    /// \brief The default maximum size of UDP DNS messages that don't cause
+    /// truncation.
+    ///
+    /// With EDNS0 the maximum size can be increases per message.
+    static const uint16_t DEFAULT_MAX_UDPSIZE = 512;
+
+    /// \brief The highest EDNS0 version this implementation supports.
+    static const uint8_t EDNS0_SUPPORTED_VERSION = 0;
+    //@}
+
 private:
     MessageImpl* impl_;
 };

+ 27 - 2
src/lib/dns/cpp/tests/message_unittest.cc

@@ -32,11 +32,12 @@ using namespace std;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 
+const uint16_t Message::DEFAULT_MAX_UDPSIZE;
+
 namespace {
 class MessageTest : public ::testing::Test {
 protected:
-    MessageTest() : obuffer(0), renderer(obuffer)
-    {}
+    MessageTest() : obuffer(0), renderer(obuffer) {}
     static Question factoryFromFile(const char* datafile);
     OutputBuffer obuffer;
     MessageRenderer renderer;
@@ -92,18 +93,38 @@ TEST_F(MessageTest, fromWire)
 
 TEST_F(MessageTest, EDNS0DOBit)
 {
+    // Without EDNS0, DNSSEC is considered to be unsupported.
     factoryFromFile(message, "testdata/message_fromWire1");
     EXPECT_FALSE(message.isDNSSECSupported());
 
+    // If DO bit is on, DNSSEC is considered to be supported.
     message.clear();
     factoryFromFile(message, "testdata/message_fromWire2");
     EXPECT_TRUE(message.isDNSSECSupported());
 
+    // If DO bit is off, DNSSEC is considered to be unsupported.
     message.clear();
     factoryFromFile(message, "testdata/message_fromWire3");
     EXPECT_FALSE(message.isDNSSECSupported());
 }
 
+TEST_F(MessageTest, EDNS0UDPSize)
+{
+    // Without EDNS0, the default max UDP size is used.
+    factoryFromFile(message, "testdata/message_fromWire1");
+    EXPECT_EQ(Message::DEFAULT_MAX_UDPSIZE, message.getUDPSize());
+
+    // If the size specified in EDNS0 > default max, use it.
+    message.clear();
+    factoryFromFile(message, "testdata/message_fromWire2");
+    EXPECT_EQ(4096, message.getUDPSize());
+
+    // If the size specified in EDNS0 < default max, keep using the default.
+    message.clear();
+    factoryFromFile(message, "testdata/message_fromWire8");
+    EXPECT_EQ(Message::DEFAULT_MAX_UDPSIZE, message.getUDPSize());
+}
+
 TEST_F(MessageTest, BadEDNS0)
 {
     // OPT RR in the answer section
@@ -122,6 +143,10 @@ TEST_F(MessageTest, BadEDNS0)
     // We accept it, but is it okay?
     message.clear();
     EXPECT_NO_THROW(factoryFromFile(message, "testdata/message_fromWire7"));
+    // Unsupported Version
+    message.clear();
+    EXPECT_THROW(factoryFromFile(message, "testdata/message_fromWire9"),
+                 DNSMessageBADVERS);
 }
 
 TEST_F(MessageTest, toWire)

+ 22 - 0
src/lib/dns/cpp/tests/testdata/message_fromWire8

@@ -0,0 +1,22 @@
+#
+# A simple DNS query message with a valid EDNS0 OPT RR (but unusual UDP size)
+# ID = 0x1035
+# QR=0 (query), Opcode=0, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=0, NSCOUNT=0, ARCOUNT=1
+# Question: test.example.com. IN A
+1035 0100
+0001 0000 0000 0001
+#(4) t  e  s  t (7) e  x  a  m  p  l  e (3) c  o  m  .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# EDNS0 OPT RR
+# owner name: "."
+00
+# TYPE: OPT (41 = 0x29)
+00 29
+# CLASS (= UDP size): 500
+01f4
+# TTL (extended RCODE and flags): RCODE=0, version=0, flags=DO
+0000 8000
+# RDLEN = 0
+0000

+ 22 - 0
src/lib/dns/cpp/tests/testdata/message_fromWire9

@@ -0,0 +1,22 @@
+#
+# A simple DNS query message with an unsupported version of EDNS0
+# ID = 0x1035
+# QR=0 (query), Opcode=0, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=0, NSCOUNT=0, ARCOUNT=1
+# Question: test.example.com. IN A
+1035 0100
+0001 0000 0000 0001
+#(4) t  e  s  t (7) e  x  a  m  p  l  e (3) c  o  m  .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# EDNS0 OPT RR
+# owner name: "."
+00
+# TYPE: OPT (41 = 0x29)
+00 29
+# CLASS (= UDP size): 4096
+1000
+# TTL (extended RCODE and flags): RCODE=0, version=1, flags=DO
+0001 8000
+# RDLEN = 0
+0000