32#include <boost/lexical_cast.hpp> 
   33#include <boost/shared_ptr.hpp> 
   39using boost::lexical_cast;
 
   46const size_t HEADERLEN = 12;
 
   48const unsigned int OPCODE_MASK = 0x7800;
 
   49const unsigned int OPCODE_SHIFT = 11;
 
   50const unsigned int RCODE_MASK = 0x000f;
 
   66const unsigned int HEADERFLAG_MASK = 0x87b0;
 
   76const char* 
const sectiontext[] = {
 
  198struct RenderSection {
 
  200        counter_(0), renderer_(renderer), partial_ok_(partial_ok),
 
  204    void operator()(
const T& entry) {
 
  209        const size_t pos0 = renderer_.getLength();
 
  210        counter_ += entry->toWire(renderer_);
 
  211        if (renderer_.isTruncated()) {
 
  215                renderer_.trim(renderer_.getLength() - pos0);
 
  220    unsigned int getTotalCount() {
 
  224    unsigned int counter_;
 
  226    AbstractMessageRenderer& renderer_;
 
  228    const bool partial_ok_;
 
  238                  "Message rendering attempted in non render mode");
 
  242                  "Message rendering attempted without Rcode set");
 
  246                  "Message rendering attempted without Opcode set");
 
  253    const size_t tsig_len = (tsig_ctx ? tsig_ctx->
getTSIGLength() : 0);
 
  265        if (tsig_len > orig_msg_len_limit) {
 
  267                      "too small limit for a TSIG (" <<
 
  268                      orig_msg_len_limit << 
")");
 
  278                  "too small limit for a Header");
 
  280    renderer.
skip(HEADERLEN);
 
  284                 RenderSection<QuestionPtr>(renderer, 
false)).getTotalCount();
 
  287    uint16_t ancount = 0;
 
  292                     RenderSection<RRsetPtr>(renderer, 
true)).getTotalCount();
 
  294    uint16_t nscount = 0;
 
  299                     RenderSection<RRsetPtr>(renderer, 
true)).getTotalCount();
 
  301    uint16_t arcount = 0;
 
  308                     RenderSection<RRsetPtr>(renderer, 
false)).getTotalCount();
 
  316        if (!local_edns && 
rcode_->getExtendedCode() != 0) {
 
  320            arcount += local_edns->toWire(renderer, 
rcode_->getExtendedCode());
 
  331        renderer.
skip(HEADERLEN);
 
  333                           RenderSection<QuestionPtr>(renderer,
 
  334                                                      false)).getTotalCount();
 
  351    size_t header_pos = 0;
 
  353    header_pos += 
sizeof(uint16_t);
 
  355    uint16_t codes_and_flags =
 
  356        (
opcode_->getCode() << OPCODE_SHIFT) & OPCODE_MASK;
 
  357    codes_and_flags |= (
rcode_->getCode() & RCODE_MASK);
 
  358    codes_and_flags |= (
flags_ & HEADERFLAG_MASK);
 
  360    header_pos += 
sizeof(uint16_t);
 
  363    header_pos += 
sizeof(uint16_t);
 
  365    header_pos += 
sizeof(uint16_t);
 
  367    header_pos += 
sizeof(uint16_t);
 
  375        const int tsig_count =
 
  378        if (tsig_count != 1) {
 
 
  394    if (flag == 0 || (flag & ~HEADERFLAG_MASK) != 0) {
 
  396                  "Message::getHeaderFlag:: Invalid flag is specified: " <<
 
  397                  "0x" << std::hex << flag);
 
  399    return ((impl_->flags_ & flag) != 0);
 
 
  406                  "setHeaderFlag performed in non-render mode");
 
  408    if (flag == 0 || (flag & ~HEADERFLAG_MASK) != 0) {
 
  410                  "Message::getHeaderFlag:: Invalid flag is specified: " <<
 
  411                  "0x" << std::hex << 
static_cast<int>(flag));
 
  414        impl_->flags_ |= flag;
 
  416        impl_->flags_ &= ~flag;
 
 
  422    return (impl_->qid_);
 
 
  429                  "setQid performed in non-render mode");
 
 
  436    if (!impl_->rcode_) {
 
  439    return (*impl_->rcode_);
 
 
  446                  "setRcode performed in non-render mode");
 
  448    impl_->setRcode(rcode);
 
 
  453    if (!impl_->opcode_) {
 
  456    return (*impl_->opcode_);
 
 
  463                  "setOpcode performed in non-render mode");
 
  465    impl_->setOpcode(opcode);
 
 
  470    return (impl_->edns_);
 
 
  477                  "setEDNS performed in non-render mode");
 
 
  486                  "getTSIGRecord performed in non-parse mode");
 
  489    return (impl_->tsig_rr_.get());
 
 
  497    return (impl_->counts_[section]);
 
 
  504                  "null RRset is given to Message::addRRset");
 
  508                  "addRRset performed in non-render mode");
 
  514    impl_->rrsets_[section].push_back(rrset);
 
  515    impl_->counts_[section] += rrset->getRdataCount();
 
  516    impl_->counts_[section] += rrset->getRRsigDataCount();
 
 
  526    for (
auto const& r : impl_->rrsets_[section]) {
 
  527        if (r->getClass() == rrclass &&
 
  528            r->getType() == rrtype &&
 
  529            r->getName() == 
name) {
 
 
  539    return (
hasRRset(section, rrset->getName(),
 
  540                     rrset->getClass(), rrset->getType()));
 
 
  549    bool removed = 
false;
 
  550    for (
auto i = impl_->rrsets_[section].begin(); i != impl_->rrsets_[section].end(); ++i) {
 
  551        if (((*i)->getName() == (*iterator)->getName()) &&
 
  552            ((*i)->getClass() == (*iterator)->getClass()) &&
 
  553            ((*i)->getType() == (*iterator)->getType())) {
 
  556            impl_->counts_[section] -= (*iterator)->getRdataCount();
 
  557            impl_->counts_[section] -= (*iterator)->getRRsigDataCount();
 
  558            impl_->rrsets_[section].erase(i);
 
 
  571                  "clearSection performed in non-render mode");
 
  577        impl_->questions_.clear();
 
  579        impl_->rrsets_[section].clear();
 
  581    impl_->counts_[section] = 0;
 
 
  588                  "addQuestion performed in non-render mode");
 
  591    impl_->questions_.push_back(question);
 
 
  602    impl_->toWire(renderer, tsig_ctx);
 
 
  609                  "Message parse attempted in non parse mode");
 
  612    if (impl_->header_parsed_) {
 
  622    const uint16_t codes_and_flags = buffer.
readUint16();
 
  623    impl_->setOpcode(
Opcode((codes_and_flags & OPCODE_MASK) >> OPCODE_SHIFT));
 
  624    impl_->setRcode(
Rcode(codes_and_flags & RCODE_MASK));
 
  625    impl_->flags_ = (codes_and_flags & HEADERFLAG_MASK);
 
  631    impl_->header_parsed_ = 
true;
 
 
  638                  "Message parse attempted in non parse mode");
 
 
  658    unsigned int added = 0;
 
  660    for (
unsigned int count = 0;
 
  666            2 * 
sizeof(uint16_t)) {
 
 
  687        name_(
name), rrtype_(rrtype), rrclass_(rrclass) {
 
  690    bool operator()(
const RRsetPtr& rrset)
 const {
 
  691        return (rrset->getType() == rrtype_ &&
 
  692                rrset->getClass() == rrclass_ &&
 
  693                rrset->getName() == name_);
 
  739    unsigned int added = 0;
 
  741    for (
unsigned int count = 0;
 
  742         static_cast<int>(count) < 
counts_[section];
 
  745        const size_t start_position = buffer.
getPosition();
 
  751            3 * 
sizeof(uint16_t) + 
sizeof(uint32_t)) {
 
  753                      " section too short: " <<
 
  768            addRR(section, 
name, rrclass, rrtype, ttl, options);
 
  777            addTSIG(section, count, buffer, start_position, 
name, rrclass, ttl,
 
 
  796                    MatchRR(
name, rrtype, rrclass));
 
  797        if (it != 
rrsets_[section].end()) {
 
  798            (*it)->setTTL(min((*it)->getTTL(), ttl));
 
  799            (*it)->addRdata(
rdata);
 
  804    rrset->addRdata(
rdata);
 
  805    rrsets_[section].push_back(rrset);
 
 
  815                    MatchRR(
name, rrtype, rrclass));
 
  816        if (it != 
rrsets_[section].end()) {
 
  817            (*it)->setTTL(min((*it)->getTTL(), ttl));
 
  822    rrsets_[section].push_back(rrset);
 
 
  831                  "EDNS OPT RR found in an invalid section");
 
  837    uint8_t extended_rcode;
 
 
  850                  "TSIG RR found in an invalid section");
 
  852    if (
static_cast<int>(count) != 
counts_[section] - 1) {
 
 
  868struct SectionFormatter {
 
  870        section_(section), output_(output) {
 
  873    void operator()(
const T& entry) {
 
  876            output_ += entry->toText();
 
  879            output_ += entry->toText();
 
  891    if (!impl_->rcode_) {
 
  893                  "Message::toText() attempted without Rcode set");
 
  895    if (!impl_->opcode_) {
 
  897                  "Message::toText() attempted without Opcode set");
 
  902    s += 
";; ->>HEADER<<- opcode: " + impl_->opcode_->toText();
 
  904    s += 
", status: " + impl_->rcode_->toText();
 
  905    s += 
", id: " + boost::lexical_cast<string>(impl_->qid_);
 
  934    s += 
", AUTHORITY: " +
 
  941    if (impl_->tsig_rr_) {
 
  944    s += 
", ADDITIONAL: " + lexical_cast<string>(arcount) + 
"\n";
 
  947        s += 
"\n;; OPT PSEUDOSECTION:\n";
 
  948        s += impl_->edns_->toText();
 
  951    if (!impl_->questions_.empty()) {
 
  954        for_each(impl_->questions_.begin(), impl_->questions_.end(),
 
  980    if (impl_->tsig_rr_) {
 
  981        s += 
"\n;; TSIG PSEUDOSECTION:\n";
 
  982        s += impl_->tsig_rr_->toText();
 
 
 1015                  "makeResponse() is performed in non-parse mode");
 
 1021    impl_->flags_ &= MESSAGE_REPLYPRESERVE;
 
 
 1035template <
typename T>
 
 1044template <
typename T>
 
 1049template <
typename T>
 
 1054template <
typename T>
 
 1059template <
typename T>
 
 1062    if (impl_ == source.impl_) {
 
 
 1071template <
typename T>
 
 1078template <
typename T>
 
 1086template <
typename T>
 
 1089    return (*(impl_->it_));
 
 
 1092template <
typename T>
 
 1095    return (&(
operator*()));
 
 
 1098template <
typename T>
 
 1101    return (impl_->it_ == other.impl_->it_);
 
 
 1104template <
typename T>
 
 1107    return (impl_->it_ != other.impl_->it_);
 
 
 1127    return (
QuestionIterator(QuestionIteratorImpl(impl_->questions_.begin())));
 
 
 1145                  "RRset iterator is requested for question");
 
 1148    return (
RRsetIterator(RRsetIteratorImpl(impl_->rrsets_[section].begin())));
 
 
 1158                  "RRset iterator is requested for question");
 
 1161    return (
RRsetIterator(RRsetIteratorImpl(impl_->rrsets_[section].end())));
 
 
 1166    return (os << message.
toText());
 
 
The RRType class encapsulates DNS resource record types.
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
A generic exception that is thrown when an unexpected error condition occurs.
The AbstractMessageRenderer class is an abstract base class that provides common interfaces for rende...
virtual void setLengthLimit(size_t len)=0
Set the maximum length of rendered data that can fit in the corresponding DNS message without truncat...
size_t getLength() const
Return the length of data written in the internal buffer.
virtual void clear()
Clear the internal buffer and other internal resources.
virtual size_t getLengthLimit() const =0
Return the maximum length of rendered data that can fit in the corresponding DNS message without trun...
virtual void setCompressMode(CompressMode mode)=0
Set the compression mode of the renderer class object.
const void * getData() const
Return a pointer to the head of the data stored in the internal buffer.
virtual CompressMode getCompressMode() const =0
Return the compression mode of the renderer class object.
virtual bool isTruncated() const =0
Return whether truncation has occurred while rendering.
void skip(size_t len)
Insert a specified length of gap at the end of the buffer.
void writeUint16At(uint16_t data, size_t pos)
Write an unsigned 16-bit integer in host byte order at the specified position of the internal buffer ...
CompressMode
Compression mode constants.
The EDNS class represents the EDNS OPT RR defined in RFC2671.
A standard DNS module exception that is thrown if a Message class method is called that is prohibited...
A standard DNS module exception that is thrown if a section iterator is being constructed for an inco...
void toWire(AbstractMessageRenderer &renderer, TSIGContext *tsig_ctx)
void addRR(Message::Section section, const Name &name, const RRClass &rrclass, const RRType &rrtype, const RRTTL &ttl, ConstRdataPtr rdata, Message::ParseOptions options)
static const unsigned int NUM_SECTIONS
vector< QuestionPtr > questions_
vector< RRsetPtr > rrsets_[NUM_SECTIONS]
int parseSection(const Message::Section section, InputBuffer &buffer, Message::ParseOptions options)
Opcode opcode_placeholder_
MessageImpl(Message::Mode mode)
void setOpcode(const Opcode &opcode)
void addTSIG(Message::Section section, unsigned int count, const InputBuffer &buffer, size_t start_position, const Name &name, const RRClass &rrclass, const RRTTL &ttl, const Rdata &rdata)
void addEDNS(Message::Section section, const Name &name, const RRClass &rrclass, const RRType &rrtype, const RRTTL &ttl, const Rdata &rdata)
ConstTSIGRecordPtr tsig_rr_
int parseQuestion(InputBuffer &buffer)
void setRcode(const Rcode &rcode)
int counts_[NUM_SECTIONS]
A standard DNS module exception that is thrown if a wire format message parser encounters a short len...
The Message class encapsulates a standard DNS message.
const QuestionIterator beginQuestion() const
Return an iterator corresponding to the beginning of the Question section of the message.
const QuestionIterator endQuestion() const
Return an iterator corresponding to the end of the Question section of the message.
void toWire(AbstractMessageRenderer &renderer, TSIGContext *tsig_ctx=0)
Render the message in wire formant into a message renderer object with (or without) TSIG.
const Rcode & getRcode() const
Return the Response Code of the message.
bool getHeaderFlag(const HeaderFlag flag) const
Return whether the specified header flag bit is set in the header section.
void clear(Mode mode)
Clear the message content (if any) and reinitialize it in the specified mode.
void clearSection(const Section section)
Remove all RRSets from the given Section.
Section
Constants to specify sections of a DNS message.
ParseOptions
Parse options.
Mode
Constants to specify the operation mode of the Message.
unsigned int getRRCount(const Section section) const
Returns the number of RRs contained in the given section.
void setOpcode(const Opcode &opcode)
Set the OPCODE of the header section of the message.
bool removeRRset(const Section section, RRsetIterator &iterator)
Remove RRSet from Message.
void addRRset(const Section section, RRsetPtr rrset)
Add a (pointer like object of) RRset to the given section of the message.
void fromWire(isc::util::InputBuffer &buffer, ParseOptions options=PARSE_DEFAULT)
(Re)build a Message object from wire-format data.
HeaderFlag
Constants for flag bit fields of a DNS message header.
const RRsetIterator endSection(const Section section) const
Return an iterator corresponding to the end of the given section (other than Question) of the message...
const TSIGRecord * getTSIGRecord() const
Return, if any, the TSIG record contained in the received message.
std::string toText() const
Convert the Message to a string.
void makeResponse()
Prepare for making a response from a request.
void setHeaderFlag(const HeaderFlag flag, const bool on=true)
Set or clear the specified header flag bit in the header section.
ConstEDNSPtr getEDNS() const
Return, if any, the EDNS associated with the message.
const Opcode & getOpcode() const
Return the OPCODE given in the header section of the message.
void parseHeader(isc::util::InputBuffer &buffer)
Parse the header section of the Message.
bool hasRRset(const Section section, const Name &name, const RRClass &rrclass, const RRType &rrtype) const
Determine whether the given section already has an RRset matching the given name, RR class and RR typ...
void appendSection(const Section section, const Message &source)
Adds all rrsets from the source the given section in the source message to the same section of this m...
void addQuestion(QuestionPtr question)
Add a (pointer like object of) Question to the message.
void setQid(qid_t qid)
Set the query ID of the header section of the message.
qid_t getQid() const
Return the query ID given in the header section of the message.
const RRsetIterator beginSection(const Section section) const
Return an iterator corresponding to the beginning of the given section (other than Question) of the m...
void setRcode(const Rcode &rcode)
Set the Response Code of the message.
Message(Mode mode)
The constructor.
void setEDNS(ConstEDNSPtr edns)
Set EDNS for the message.
The Name class encapsulates DNS names.
The Opcode class objects represent standard OPCODEs of the header section of DNS messages as defined ...
The Question class encapsulates the common search key of DNS lookup, consisting of owner name,...
The RRClass class encapsulates DNS resource record classes.
static const RRClass & ANY()
static const RRClass & NONE()
The RRTTL class encapsulates TTLs used in DNS resource records.
The RRType class encapsulates DNS resource record types.
static const RRType & TSIG()
static const RRType & OPT()
The RRset class is a concrete derived class of BasicRRset which contains a pointer to an additional R...
DNS Response Codes (RCODEs) class.
SectionIterator is a templated class to provide standard-compatible iterators for Questions and RRset...
const T & operator*() const
const T * operator->() const
bool operator!=(const SectionIterator< T > &other) const
bool operator==(const SectionIterator< T > &other) const
SectionIterator< T > & operator++()
void operator=(const SectionIterator< T > &source)
virtual ConstTSIGRecordPtr sign(const uint16_t qid, const void *const data, const size_t data_len)
Sign a DNS message.
virtual size_t getTSIGLength() const
Return the expected length of TSIG RR after sign()
The Rdata class is an abstract base class that provides a set of common interfaces to manipulate conc...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< const Rdata > ConstRdataPtr
RdataPtr createRdata(const RRType &rrtype, const RRClass &rrclass, const std::string &rdata_string)
Create RDATA of a given pair of RR type and class from a string.
boost::shared_ptr< MessageImpl > MessageImplPtr
Pointer to the MessageImpl object.
boost::shared_ptr< const TSIGRecord > ConstTSIGRecordPtr
A pointer-like type pointing to an immutable TSIGRecord object.
boost::shared_ptr< Question > QuestionPtr
A pointer-like type pointing to an Question object.
SectionIterator< QuestionPtr > QuestionIterator
boost::shared_ptr< AbstractRRset > RRsetPtr
A pointer-like type pointing to an RRset object.
ostream & operator<<(std::ostream &os, const EDNS &edns)
Insert the EDNS as a string into stream.
EDNS * createEDNSFromRR(const Name &name, const RRClass &rrclass, const RRType &rrtype, const RRTTL &ttl, const Rdata &rdata, uint8_t &extended_rcode)
Create a new EDNS object from a set of RR parameters, also providing the extended RCODE value.
boost::shared_ptr< const EDNS > ConstEDNSPtr
A pointer-like type pointing to an immutable EDNS object.
boost::shared_ptr< EDNS > EDNSPtr
A pointer-like type pointing to an EDNS object.
SectionIterator< RRsetPtr > RRsetIterator
Defines the logger used by the top-level component of kea-lfc.
Template version of Section Iterator.
vector< T >::const_iterator it_
SectionIteratorImpl(const typename vector< T >::const_iterator &it)