Commit 7ad9d497 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

- separated Rcode class declarations and definitions in different files

- added more detailed tests for the Rcode class
- added some methods for the recent introduction of EDNS class (Trac #311)
- adjusted and enhanced python binding.

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac351@3038 e5f2f494-b856-4b98-b285-d166d9295462
parent 18d6983f
......@@ -29,6 +29,7 @@
#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>
......
......@@ -23,6 +23,7 @@
#include <dns/message.h>
#include <dns/messagerenderer.h>
#include <dns/opcode.h>
#include <dns/rcode.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
......@@ -281,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));
}
......@@ -578,6 +580,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);
......
......@@ -29,6 +29,7 @@
#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>
......
......@@ -27,6 +27,7 @@
#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>
......
......@@ -23,6 +23,7 @@
#include <dns/message.h>
#include <dns/name.h>
#include <dns/opcode.h>
#include <dns/rcode.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
......@@ -81,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>
......
......@@ -27,6 +27,7 @@
#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>
......
......@@ -69,6 +69,7 @@ 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,7 @@
#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>
......@@ -63,11 +64,11 @@ const flags_t FLAG_AD = 0x0020;
const flags_t FLAG_CD = 0x0010;
//
// EDNS related constants
// EDNS related constants (THESE SHOULD BE REMOVED ON MERGE)
//
const uint32_t EXTRCODE_MASK = 0xff000000;
const flags_t EXTFLAG_MASK = 0xffff;
const flags_t EXTFLAG_DO = 0x8000;
const uint32_t EXTRCODE_MASK = 0xff000000;
const uint32_t EDNSVERSION_MASK = 0x00ff0000;
const unsigned int OPCODE_MASK = 0x7800;
......@@ -77,46 +78,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 char *sectiontext[] = {
"QUESTION",
"ANSWER",
......@@ -125,23 +86,6 @@ const char *sectiontext[] = {
};
}
Rcode::Rcode(uint16_t code) : code_(code) {
if (code_ > MAX_RCODE) {
isc_throw(OutOfRange, "Rcode is too large to construct");
}
}
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) {
......@@ -158,12 +102,16 @@ public:
// for efficiency?
Message::Mode mode_;
qid_t qid_;
Rcode rcode_;
// We want to use NULL for opcode_ to mean Opcode isn't correctly parsed or
// set. We store the real Opcode object in opcode_placeholder_ and have
// opcode_ refer to it when the object is valid.
// 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 dnssec_ok_;
......@@ -184,14 +132,15 @@ public:
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()),
opcode_placeholder_(Opcode(0)) // as a placeholder the value doesn't matter
rcode_placeholder_(Rcode(0)), // as a placeholder the value doesn't matter
opcode_placeholder_(Opcode(0)) // ditto
{
init();
}
......@@ -200,7 +149,7 @@ void
MessageImpl::init() {
flags_ = 0;
qid_ = 0;
rcode_ = Rcode::NOERROR(); // XXX
rcode_ = NULL;
opcode_ = NULL;
dnssec_ok_ = false;
remote_edns_ = RRsetPtr();
......@@ -225,6 +174,12 @@ MessageImpl::setOpcode(const Opcode& opcode) {
opcode_ = &opcode_placeholder_;
}
void
MessageImpl::setRcode(const Rcode& rcode) {
rcode_placeholder_ = rcode;
rcode_ = &rcode_placeholder_;
}
Message::Message(Mode mode) :
impl_(new MessageImpl(mode))
{}
......@@ -304,7 +259,7 @@ Message::setQid(qid_t qid) {
const Rcode&
Message::getRcode() const {
return (impl_->rcode_);
return (*impl_->rcode_);
}
void
......@@ -313,7 +268,7 @@ Message::setRcode(const Rcode& rcode) {
isc_throw(InvalidMessageOperation,
"setRcode performed in non-render mode");
}
impl_->rcode_ = rcode;
impl_->setRcode(rcode);
}
const Opcode&
......@@ -421,7 +376,8 @@ addEDNS(MessageImpl* mimpl, MessageRenderer& renderer) {
// if the Rcode is BADVERS, which is EDNS specific.
// XXX: this logic is tricky. We should revisit this later.
if (!is_query) {
if (mimpl->remote_edns_ == NULL && mimpl->rcode_ != Rcode::BADVERS()) {
if (mimpl->remote_edns_ == NULL &&
*mimpl->rcode_ != Rcode::BADVERS()) {
return (false);
}
} else {
......@@ -431,7 +387,7 @@ addEDNS(MessageImpl* mimpl, MessageRenderer& renderer) {
// Extended Rcode is to be specified.
if (mimpl->udpsize_ == Message::DEFAULT_MAX_UDPSIZE &&
!mimpl->dnssec_ok_ &&
mimpl->rcode_.getCode() < 0x10) {
mimpl->rcode_->getCode() < 0x10) {
return (false);
}
}
......@@ -444,7 +400,7 @@ addEDNS(MessageImpl* mimpl, MessageRenderer& renderer) {
}
// Render EDNS OPT RR
uint32_t extrcode_flags = ((mimpl->rcode_.getCode() & 0xff0) << 24);
uint32_t extrcode_flags = ((mimpl->rcode_->getCode() & 0xff0) << 24);
if (mimpl->dnssec_ok_) {
extrcode_flags |= 0x8000; // set DO bit
}
......@@ -466,6 +422,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");
}
if (impl_->opcode_ == NULL) {
isc_throw(InvalidMessageOperation,
"Message rendering attempted without Opcode");
}
// reserve room for the header
renderer.skip(HEADERLEN);
......@@ -524,7 +488,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);
......@@ -554,7 +518,7 @@ Message::parseHeader(InputBuffer& buffer) {
impl_->qid_ = buffer.readUint16();
const uint16_t codes_and_flags = buffer.readUint16();
impl_->setOpcode(Opcode((codes_and_flags & OPCODE_MASK) >> OPCODE_SHIFT));
impl_->rcode_ = rcodes[(codes_and_flags & RCODE_MASK)];
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();
......@@ -685,8 +649,8 @@ MessageImpl::parseSection(const Section& section, InputBuffer& buffer) {
if (rrclass.getCode() > Message::DEFAULT_MAX_UDPSIZE) {
udpsize_ = rrclass.getCode();
}
rcode_ = Rcode(((ttl.getValue() & EXTRCODE_MASK) >> 20) |
rcode_.getCode());
setRcode(Rcode(((ttl.getValue() & EXTRCODE_MASK) >> 20) |
rcode_->getCode()));
continue;
}
......@@ -730,7 +694,7 @@ Message::toText() const {
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()))
......@@ -975,11 +939,6 @@ Message::endSection(const Section& section) const {
impl_->rrsets_[sectionCodeToId(section)].end())));
}
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,7 @@ class MessageRenderer;
class Message;
class MessageImpl;
class Opcode;
class Rcode;
template <typename T>
struct SectionIteratorImpl;
......@@ -160,162 +161,6 @@ MessageFlag::CD()
return (f);
}
/// \brief The \c Rcode class objects represent standard Response Codes
/// (RCODEs) of the header section of DNS messages, and extended response
/// codes as defined in the EDNS specification.
///
/// Constant objects are defined for standard flags.
class Rcode {
public:
Rcode(uint16_t code);
uint16_t getCode() const { return (code_); }
bool operator==(const Rcode& other) const { return (code_ == other.code_); }
bool operator!=(const Rcode& other) const { return (code_ != other.code_); }
std::string toText() const;
static const Rcode& NOERROR();
static const Rcode& FORMERR();
static const Rcode& SERVFAIL();
static const Rcode& NXDOMAIN();
static const Rcode& NOTIMP();
static const Rcode& REFUSED();
static const Rcode& YXDOMAIN();
static const Rcode& YXRRSET();
static const Rcode& NXRRSET();
static const Rcode& NOTAUTH();
static const Rcode& NOTZONE();
static const Rcode& RESERVED11();
static const Rcode& RESERVED12();
static const Rcode& RESERVED13();
static const Rcode& RESERVED14();
static const Rcode& RESERVED15();
// Extended Rcodes follow (EDNS required):
static const Rcode& BADVERS();
private:
uint16_t code_;
// EDNS-extended RCODEs are 12-bit unsigned integers.
static const uint16_t MAX_RCODE = 0xfff;
};
inline const Rcode&
Rcode::NOERROR()
{
static Rcode c(0);
return (c);
}
inline const Rcode&
Rcode::FORMERR()
{
static Rcode c(1);
return (c);
}
inline const Rcode&
Rcode::SERVFAIL()
{
static Rcode c(2);
return (c);
}
inline const Rcode&
Rcode::NXDOMAIN()
{
static Rcode c(3);
return (c);
}
inline const Rcode&
Rcode::NOTIMP()
{
static Rcode c(4);
return (c);
}
inline const Rcode&
Rcode::REFUSED()
{
static Rcode c(5);
return (c);
}
inline const Rcode&
Rcode::YXDOMAIN()
{
static Rcode c(6);
return (c);
}
inline const Rcode&
Rcode::YXRRSET()
{
static Rcode c(7);
return (c);
}
inline const Rcode&
Rcode::NXRRSET()
{
static Rcode c(8);
return (c);
}
inline const Rcode&
Rcode::NOTAUTH()
{
static Rcode c(9);
return (c);
}
inline const Rcode&
Rcode::NOTZONE()
{
static Rcode c(10);
return (c);
}
inline const Rcode&
Rcode::RESERVED11()
{
static Rcode c(11);
return (c);
}
inline const Rcode&
Rcode::RESERVED12()
{
static Rcode c(12);
return (c);
}
inline const Rcode&
Rcode::RESERVED13()
{
static Rcode c(13);
return (c);
}
inline const Rcode&
Rcode::RESERVED14()
{
static Rcode c(14);
return (c);
}
inline const Rcode&
Rcode::RESERVED15()
{
static Rcode c(15);
return (c);
}
inline const Rcode&
Rcode::BADVERS()
{
static Rcode c(16);
return (c);
}
/// \brief The \c Section class objects represent DNS message sections such
/// as the header, question, or answer.
///
......@@ -651,8 +496,6 @@ private:
MessageImpl* impl_;
};
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);
}
}
......
......@@ -16,6 +16,8 @@
/* $Id$ */
#include <stdint.h>
#include <ostream>
#ifndef __OPCODE_H
......@@ -186,7 +188,7 @@ Opcode::RESERVED15() {
/// \brief Insert the \c Opcode as a string into stream.
///
/// This method convert \c edns into a string and inserts it into the
/// This method convert \c opcode into a string and inserts it into the
/// output stream \c os.
///
/// \param os A \c std::ostream object on which the insertion operation is
......
......@@ -16,6 +16,7 @@ EXTRA_DIST += message_python.cc
EXTRA_DIST += rrclass_python.cc
EXTRA_DIST += name_python.cc
EXTRA_DIST += opcode_python.cc
EXTRA_DIST += rcode_python.cc
EXTRA_DIST += rrset_python.cc
EXTRA_DIST += question_python.cc
EXTRA_DIST += rrttl_python.cc
......
......@@ -191,311 +191,6 @@ MessageFlag_CD(s_MessageFlag* self UNUSED_PARAM) {
// End of MessageFlag wrapper
//
//
// Rcode
//
// We added a helper variable static_code here
// Since we can create Rcodes dynamically with Rcode(int), but also
// use the static globals (Rcode::NOERROR() etc), we use this
// variable to see if the code came from one of the latter, in which
// case Rcode_destroy should not free it (the other option is to
// allocate new Rcodes for every use of the static ones, but this
// seems more efficient).
class s_Rcode : public PyObject {
public:
const Rcode* rcode;
bool static_code;
};
static int Rcode_init(s_Rcode* self, PyObject* args);
static void Rcode_destroy(s_Rcode* self);
static PyObject* Rcode_getCode(s_Rcode* self);
static PyObject* Rcode_toText(s_Rcode* self);
static PyObject* Rcode_str(PyObject* self);
static PyObject* Rcode_NOERROR(s_Rcode* self);
static PyObject* Rcode_FORMERR(s_Rcode* self);
static PyObject* Rcode_SERVFAIL(s_Rcode* self);
static PyObject* Rcode_NXDOMAIN(s_Rcode* self);
static PyObject* Rcode_NOTIMP(s_Rcode* self);
static PyObject* Rcode_REFUSED(s_Rcode* self);
static PyObject* Rcode_YXDOMAIN(s_Rcode* self);
static PyObject* Rcode_YXRRSET(s_Rcode* self);
static PyObject* Rcode_NXRRSET(s_Rcode* self);
static PyObject* Rcode_NOTAUTH(s_Rcode* self);
static PyObject* Rcode_NOTZONE(s_Rcode* self);
static PyObject* Rcode_RESERVED11(s_Rcode* self);
static PyObject* Rcode_RESERVED12(s_Rcode* self);
static PyObject* Rcode_RESERVED13(s_Rcode* self);
static PyObject* Rcode_RESERVED14(s_Rcode* self);
static PyObject* Rcode_RESERVED15(s_Rcode* self);
static PyObject* Rcode_BADVERS(s_Rcode* self);
static PyObject* Rcode_richcmp(s_Rcode* self, s_Rcode* other, int op);
static PyMethodDef Rcode_methods[] = {
{ "get_code", reinterpret_cast<PyCFunction>(Rcode_getCode), METH_NOARGS, "Returns the code value" },
{ "to_text", reinterpret_cast<PyCFunction>(Rcode_toText), METH_NOARGS, "Returns the text representation" },
{ "NOERROR", reinterpret_cast<PyCFunction>(Rcode_NOERROR), METH_NOARGS | METH_STATIC, "Creates a NOERROR Rcode" },
{ "FORMERR", reinterpret_cast<PyCFunction>(Rcode_FORMERR), METH_NOARGS | METH_STATIC, "Creates a FORMERR Rcode" },
{ "SERVFAIL", reinterpret_cast<PyCFunction>(Rcode_SERVFAIL), METH_NOARGS | METH_STATIC, "Creates a SERVFAIL Rcode" },
{ "NXDOMAIN", reinterpret_cast<PyCFunction>(Rcode_NXDOMAIN), METH_NOARGS | METH_STATIC, "Creates a NXDOMAIN Rcode" },
{ "NOTIMP", reinterpret_cast<PyCFunction>(Rcode_NOTIMP), METH_NOARGS | METH_STATIC, "Creates a NOTIMP Rcode" },
{ "REFUSED", reinterpret_cast<PyCFunction>(Rcode_REFUSED), METH_NOARGS | METH_STATIC, "Creates a REFUSED Rcode" },