Commit 707402ac authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

merged trac #351 (Opcode and Rcode cleanup)


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@3056 e5f2f494-b856-4b98-b285-d166d9295462
parents 1514cff7 bfeca5b9
......@@ -29,6 +29,8 @@
#include <dns/messagerenderer.h>
#include <dns/name.h>
#include <dns/question.h>
#include <dns/opcode.h>
#include <dns/rcode.h>
#include <dns/rrset.h>
#include <dns/rrttl.h>
#include <dns/message.h>
......
......@@ -22,6 +22,8 @@
#include <dns/name.h>
#include <dns/message.h>
#include <dns/messagerenderer.h>
#include <dns/opcode.h>
#include <dns/rcode.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
......@@ -114,7 +116,7 @@ protected:
AuthSrvTest() : server(true, xfrout),
request_message(Message::RENDER),
parse_message(Message::PARSE), default_qid(0x1035),
opcode(Opcode(Opcode::QUERY())), qname("www.example.com"),
opcode(Opcode::QUERY()), qname("www.example.com"),
qclass(RRClass::IN()), qtype(RRType::A()),
io_message(NULL), endpoint(NULL), request_obuffer(0),
request_renderer(request_obuffer),
......@@ -280,6 +282,7 @@ AuthSrvTest::createRequestMessage(const Opcode& opcode,
{
request_message.clear(Message::RENDER);
request_message.setOpcode(opcode);
request_message.setRcode(Rcode::NOERROR());
request_message.setQid(default_qid);
request_message.addQuestion(Question(request_name, rrclass, rrtype));
}
......@@ -584,6 +587,7 @@ TEST_F(AuthSrvTest, notifyForCHClass) {
TEST_F(AuthSrvTest, notifyEmptyQuestion) {
request_message.clear(Message::RENDER);
request_message.setOpcode(Opcode::NOTIFY());
request_message.setRcode(Rcode::NOERROR());
request_message.setHeaderFlag(MessageFlag::AA());
request_message.setQid(default_qid);
request_message.toWire(request_renderer);
......
......@@ -28,6 +28,8 @@
#include <dns/name.h>
#include <dns/message.h>
#include <dns/messagerenderer.h>
#include <dns/opcode.h>
#include <dns/rcode.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
#include <dns/rrset.h>
......
......@@ -26,6 +26,8 @@
#include <dns/name.h>
#include <dns/message.h>
#include <dns/messagerenderer.h>
#include <dns/opcode.h>
#include <dns/rcode.h>
#include <dns/rrtype.h>
#include <dns/rrclass.h>
#include <dns/question.h>
......
......@@ -22,6 +22,8 @@
#include <dns/buffer.h>
#include <dns/message.h>
#include <dns/name.h>
#include <dns/opcode.h>
#include <dns/rcode.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
......@@ -80,7 +82,6 @@ public:
EXPECT_EQ(0, message.getQid());
EXPECT_EQ(Opcode::QUERY(), message.getOpcode());
EXPECT_EQ(Rcode::NOERROR(), message.getRcode());
EXPECT_EQ(Rcode::NOERROR(), message.getRcode());
EXPECT_FALSE(message.getHeaderFlag(MessageFlag::QR()));
EXPECT_FALSE(message.getHeaderFlag(MessageFlag::AA()));
EXPECT_EQ(1, message.getRRCount(Section::QUESTION()));
......
......@@ -32,6 +32,7 @@
#include <dns/buffer.h>
#include <dns/message.h>
#include <dns/name.h>
#include <dns/rcode.h>
#include <dns/rdataclass.h>
#include <dns/rrset.h>
#include <dns/rrsetlist.h>
......
......@@ -26,6 +26,8 @@
#include <dns/message.h>
#include <dns/messagerenderer.h>
#include <dns/question.h>
#include <dns/opcode.h>
#include <dns/rcode.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rrclass.h>
......
......@@ -19,6 +19,7 @@
#include <dns/buffer.h>
#include <dns/message.h>
#include <dns/name.h>
#include <dns/opcode.h>
#include <dns/rrtype.h>
#include <dns/rrclass.h>
......
......@@ -69,6 +69,8 @@ libdns___la_SOURCES += util/hex.h
libdns___la_SOURCES += message.h message.cc
libdns___la_SOURCES += messagerenderer.h messagerenderer.cc
libdns___la_SOURCES += name.h name.cc
libdns___la_SOURCES += opcode.h opcode.cc
libdns___la_SOURCES += rcode.h rcode.cc
libdns___la_SOURCES += rdata.h rdata.cc
libdns___la_SOURCES += rrclass.cc
libdns___la_SOURCES += rrparamregistry.h
......
......@@ -15,7 +15,7 @@
// $Id$
#include <dns/exceptions.h>
#include <dns/message.h>
#include <dns/rcode.h>
namespace isc {
namespace dns {
......
......@@ -33,6 +33,8 @@
#include <dns/message.h>
#include <dns/messagerenderer.h>
#include <dns/name.h>
#include <dns/opcode.h>
#include <dns/rcode.h>
#include <dns/question.h>
#include <dns/rdataclass.h>
#include <dns/rrclass.h>
......@@ -62,11 +64,6 @@ const flags_t FLAG_RA = 0x0080;
const flags_t FLAG_AD = 0x0020;
const flags_t FLAG_CD = 0x0010;
//
// EDNS related constants
//
const uint32_t EXTRCODE_MASK = 0xff000000;
const unsigned int OPCODE_MASK = 0x7800;
const unsigned int OPCODE_SHIFT = 11;
const unsigned int RCODE_MASK = 0x000f;
......@@ -74,84 +71,6 @@ const unsigned int FLAG_MASK = 0x8ff0;
const unsigned int MESSAGE_REPLYPRESERVE = (FLAG_RD | FLAG_CD);
const Rcode rcodes[] = {
Rcode::NOERROR(),
Rcode::FORMERR(),
Rcode::SERVFAIL(),
Rcode::NXDOMAIN(),
Rcode::NOTIMP(),
Rcode::REFUSED(),
Rcode::YXDOMAIN(),
Rcode::YXRRSET(),
Rcode::NXRRSET(),
Rcode::NOTAUTH(),
Rcode::NOTZONE(),
Rcode::RESERVED11(),
Rcode::RESERVED12(),
Rcode::RESERVED13(),
Rcode::RESERVED14(),
Rcode::RESERVED15(),
Rcode::BADVERS()
};
const char *rcodetext[] = {
"NOERROR",
"FORMERR",
"SERVFAIL",
"NXDOMAIN",
"NOTIMP",
"REFUSED",
"YXDOMAIN",
"YXRRSET",
"NXRRSET",
"NOTAUTH",
"NOTZONE",
"RESERVED11",
"RESERVED12",
"RESERVED13",
"RESERVED14",
"RESERVED15",
"BADVERS"
};
const Opcode* opcodes[] = {
&Opcode::QUERY(),
&Opcode::IQUERY(),
&Opcode::STATUS(),
&Opcode::RESERVED3(),
&Opcode::NOTIFY(),
&Opcode::UPDATE(),
&Opcode::RESERVED6(),
&Opcode::RESERVED7(),
&Opcode::RESERVED8(),
&Opcode::RESERVED9(),
&Opcode::RESERVED10(),
&Opcode::RESERVED11(),
&Opcode::RESERVED12(),
&Opcode::RESERVED13(),
&Opcode::RESERVED14(),
&Opcode::RESERVED15()
};
const char *opcodetext[] = {
"QUERY",
"IQUERY",
"STATUS",
"RESERVED3",
"NOTIFY",
"UPDATE",
"RESERVED6",
"RESERVED7",
"RESERVED8",
"RESERVED9",
"RESERVED10",
"RESERVED11",
"RESERVED12",
"RESERVED13",
"RESERVED14",
"RESERVED15"
};
const char *sectiontext[] = {
"QUESTION",
"ANSWER",
......@@ -160,55 +79,6 @@ const char *sectiontext[] = {
};
}
string
Opcode::toText() const {
return (opcodetext[code_]);
}
namespace {
// This diagram shows the wire-format representation of the 12-bit extended
// form RCODEs and its relationship with implementation specific parameters.
//
// 0 3 11 15
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |UNUSED | EXTENDED-RCODE | RCODE |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// <= EXTRCODE_SHIFT (4 bits)
const unsigned int EXTRCODE_SHIFT = 4;
}
Rcode::Rcode(const uint16_t code) : code_(code) {
if (code_ > MAX_RCODE) {
isc_throw(OutOfRange, "Rcode is too large to construct: " << code_);
}
}
Rcode::Rcode(const uint8_t code, const uint8_t extended_code) :
code_((extended_code << EXTRCODE_SHIFT) | (code & RCODE_MASK))
{
if (code > RCODE_MASK) {
isc_throw(OutOfRange,
"Base Rcode is too large to construct: "
<< static_cast<unsigned int>(code));
}
}
uint8_t
Rcode::getExtendedCode() const {
return (code_ >> EXTRCODE_SHIFT);
}
string
Rcode::toText() const {
if (code_ < sizeof(rcodetext) / sizeof (const char *)) {
return (rcodetext[code_]);
}
ostringstream oss;
oss << code_;
return (oss.str());
}
namespace {
inline unsigned int
sectionCodeToId(const Section& section) {
......@@ -225,8 +95,16 @@ public:
// for efficiency?
Message::Mode mode_;
qid_t qid_;
Rcode rcode_;
// We want to use NULL for [op,r]code_ to mean the code being not
// correctly parsed or set. We store the real code object in
// xxcode_placeholder_ and have xxcode_ refer to it when the object
// is valid.
const Rcode* rcode_;
Rcode rcode_placeholder_;
const Opcode* opcode_;
Opcode opcode_placeholder_;
flags_t flags_;
bool header_parsed_;
......@@ -242,12 +120,16 @@ public:
#endif
void init();
void setOpcode(const Opcode& opcode);
void setRcode(const Rcode& rcode);
int parseQuestion(InputBuffer& buffer);
int parseSection(const Section& section, InputBuffer& buffer);
};
MessageImpl::MessageImpl(Message::Mode mode) :
mode_(mode), rcode_(Rcode::NOERROR())
mode_(mode),
rcode_placeholder_(Rcode(0)), // as a placeholder the value doesn't matter
opcode_placeholder_(Opcode(0)) // ditto
{
init();
}
......@@ -256,7 +138,7 @@ void
MessageImpl::init() {
flags_ = 0;
qid_ = 0;
rcode_ = Rcode::NOERROR(); // XXX
rcode_ = NULL;
opcode_ = NULL;
edns_ = EDNSPtr();
......@@ -271,6 +153,18 @@ MessageImpl::init() {
rrsets_[sectionCodeToId(Section::ADDITIONAL())].clear();
}
void
MessageImpl::setOpcode(const Opcode& opcode) {
opcode_placeholder_ = opcode;
opcode_ = &opcode_placeholder_;
}
void
MessageImpl::setRcode(const Rcode& rcode) {
rcode_placeholder_ = rcode;
rcode_ = &rcode_placeholder_;
}
Message::Message(Mode mode) :
impl_(new MessageImpl(mode))
{}
......@@ -318,7 +212,10 @@ Message::setQid(qid_t qid) {
const Rcode&
Message::getRcode() const {
return (impl_->rcode_);
if (impl_->rcode_ == NULL) {
isc_throw(InvalidMessageOperation, "getRcode attempted before set");
}
return (*impl_->rcode_);
}
void
......@@ -327,11 +224,14 @@ Message::setRcode(const Rcode& rcode) {
isc_throw(InvalidMessageOperation,
"setRcode performed in non-render mode");
}
impl_->rcode_ = rcode;
impl_->setRcode(rcode);
}
const Opcode&
Message::getOpcode() const {
if (impl_->opcode_ == NULL) {
isc_throw(InvalidMessageOperation, "getOpcode attempted before set");
}
return (*impl_->opcode_);
}
......@@ -341,7 +241,7 @@ Message::setOpcode(const Opcode& opcode) {
isc_throw(InvalidMessageOperation,
"setOpcode performed in non-render mode");
}
impl_->opcode_ = &opcode;
impl_->setOpcode(opcode);
}
ConstEDNSPtr
......@@ -446,6 +346,14 @@ Message::toWire(MessageRenderer& renderer) {
isc_throw(InvalidMessageOperation,
"Message rendering attempted in non render mode");
}
if (impl_->rcode_ == NULL) {
isc_throw(InvalidMessageOperation,
"Message rendering attempted without Rcode set");
}
if (impl_->opcode_ == NULL) {
isc_throw(InvalidMessageOperation,
"Message rendering attempted without Opcode set");
}
// reserve room for the header
renderer.skip(HEADERLEN);
......@@ -484,12 +392,12 @@ Message::toWire(MessageRenderer& renderer) {
// no EDNS has been set we generate a temporary local EDNS and use it.
if (!renderer.isTruncated()) {
ConstEDNSPtr local_edns = impl_->edns_;
if (!local_edns && impl_->rcode_.getExtendedCode() != 0) {
if (!local_edns && impl_->rcode_->getExtendedCode() != 0) {
local_edns = ConstEDNSPtr(new EDNS());
}
if (local_edns) {
arcount += local_edns->toWire(renderer,
impl_->rcode_.getExtendedCode());
impl_->rcode_->getExtendedCode());
}
}
......@@ -512,7 +420,7 @@ Message::toWire(MessageRenderer& renderer) {
uint16_t codes_and_flags =
(impl_->opcode_->getCode() << OPCODE_SHIFT) & OPCODE_MASK;
codes_and_flags |= (impl_->rcode_.getCode() & RCODE_MASK);
codes_and_flags |= (impl_->rcode_->getCode() & RCODE_MASK);
codes_and_flags |= (impl_->flags_ & FLAG_MASK);
renderer.writeUint16At(codes_and_flags, header_pos);
header_pos += sizeof(uint16_t);
......@@ -541,8 +449,8 @@ Message::parseHeader(InputBuffer& buffer) {
impl_->qid_ = buffer.readUint16();
const uint16_t codes_and_flags = buffer.readUint16();
impl_->opcode_ = opcodes[((codes_and_flags & OPCODE_MASK) >> OPCODE_SHIFT)];
impl_->rcode_ = rcodes[(codes_and_flags & RCODE_MASK)];
impl_->setOpcode(Opcode((codes_and_flags & OPCODE_MASK) >> OPCODE_SHIFT));
impl_->setRcode(Rcode(codes_and_flags & RCODE_MASK));
impl_->flags_ = (codes_and_flags & FLAG_MASK);
impl_->counts_[Section::QUESTION().getCode()] = buffer.readUint16();
impl_->counts_[Section::ANSWER().getCode()] = buffer.readUint16();
......@@ -677,7 +585,7 @@ MessageImpl::parseSection(const Section& section, InputBuffer& buffer) {
uint8_t extended_rcode;
edns_ = ConstEDNSPtr(createEDNSFromRR(name, rrclass, rrtype, ttl,
*rdata, extended_rcode));
rcode_ = Rcode(rcode_.getCode(), extended_rcode);
setRcode(Rcode(rcode_->getCode(), extended_rcode));
continue;
} else {
vector<RRsetPtr>::iterator it =
......@@ -718,11 +626,20 @@ struct SectionFormatter {
string
Message::toText() const {
if (impl_->rcode_ == NULL) {
isc_throw(InvalidMessageOperation,
"Message::toText() attempted without Rcode set");
}
if (impl_->opcode_ == NULL) {
isc_throw(InvalidMessageOperation,
"Message::toText() attempted without Opcode set");
}
string s;
s += ";; ->>HEADER<<- opcode: " + impl_->opcode_->toText();
// for simplicity we don't consider extended rcode (unlike BIND9)
s += ", status: " + impl_->rcode_.toText();
s += ", status: " + impl_->rcode_->toText();
s += ", id: " + boost::lexical_cast<string>(impl_->qid_);
s += "\n;; flags: ";
if (getHeaderFlag(MessageFlag::QR()))
......@@ -947,16 +864,6 @@ Message::endSection(const Section& section) const {
impl_->rrsets_[sectionCodeToId(section)].end())));
}
ostream&
operator<<(ostream& os, const Opcode& opcode) {
return (os << opcode.toText());
}
ostream&
operator<<(ostream& os, const Rcode& rcode) {
return (os << rcode.toText());
}
ostream&
operator<<(ostream& os, const Message& message) {
return (os << message.toText());
......
......@@ -82,6 +82,8 @@ class InputBuffer;
class MessageRenderer;
class Message;
class MessageImpl;
class Opcode;
class Rcode;
template <typename T>
struct SectionIteratorImpl;
......@@ -160,312 +162,6 @@ MessageFlag::CD()
return (f);
}
/// \brief The \c Opcode class objects represent standard OPCODEs
/// of the header section of DNS messages.
///
/// Note: since there are only 15 possible values, it may make more sense to
/// simply define an enum type to represent these values.
///
/// Constant objects are defined for standard flags.
class Opcode {
public:
uint16_t getCode() const { return (code_); }
bool operator==(const Opcode& other) const
{ return (code_ == other.code_); }
bool operator!=(const Opcode& other) const
{ return (code_ != other.code_); }
std::string toText() const;
static const Opcode& QUERY();
static const Opcode& IQUERY();
static const Opcode& STATUS();
static const Opcode& RESERVED3();
static const Opcode& NOTIFY();
static const Opcode& UPDATE();
static const Opcode& RESERVED6();
static const Opcode& RESERVED7();
static const Opcode& RESERVED8();
static const Opcode& RESERVED9();
static const Opcode& RESERVED10();
static const Opcode& RESERVED11();
static const Opcode& RESERVED12();
static const Opcode& RESERVED13();
static const Opcode& RESERVED14();
static const Opcode& RESERVED15();
private:
Opcode(uint16_t code) : code_(code) {}
uint16_t code_;
};
inline const Opcode&
Opcode::QUERY()
{
static Opcode c(0);
return (c);
}
inline const Opcode&
Opcode::IQUERY()
{
static Opcode c(1);
return (c);
}
inline const Opcode&
Opcode::STATUS()
{
static Opcode c(2);
return (c);
}
inline const Opcode&
Opcode::RESERVED3()
{
static Opcode c(3);
return (c);
}
inline const Opcode&
Opcode::NOTIFY()
{
static Opcode c(4);
return (c);
}
inline const Opcode&
Opcode::UPDATE()
{
static Opcode c(5);
return (c);
}
inline const Opcode&
Opcode::RESERVED6()
{
static Opcode c(6);
return (c);
}
inline const Opcode&
Opcode::RESERVED7()
{
static Opcode c(7);
return (c);
}
inline const Opcode&
Opcode::RESERVED8()
{
static Opcode c(8);
return (c);
}
inline const Opcode&
Opcode::RESERVED9()
{
static Opcode c(9);
return (c);
}
inline const Opcode&
Opcode::RESERVED10()
{
static Opcode c(10);
return (c);
}
inline const Opcode&
Opcode::RESERVED11()
{
static Opcode c(11);
return (c);
}
inline const Opcode&
Opcode::RESERVED12()
{
static Opcode c(12);
return (c);
}
inline const Opcode&
Opcode::RESERVED13()
{
static Opcode c(13);
return (c);