[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