Kea  1.5.0
dns/message.cc
Go to the documentation of this file.
1 // Copyright (C) 2009-2015 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 #include <stdint.h>
10 
11 #include <algorithm>
12 #include <cassert>
13 #include <string>
14 #include <sstream>
15 #include <vector>
16 
17 #include <boost/foreach.hpp>
18 #include <boost/lexical_cast.hpp>
19 #include <boost/shared_ptr.hpp>
20 
21 #include <exceptions/exceptions.h>
22 
23 #include <util/buffer.h>
24 
25 #include <dns/edns.h>
26 #include <dns/exceptions.h>
27 #include <dns/message.h>
28 #include <dns/messagerenderer.h>
29 #include <dns/name.h>
30 #include <dns/opcode.h>
31 #include <dns/rcode.h>
32 #include <dns/question.h>
33 #include <dns/rdataclass.h>
34 #include <dns/rrclass.h>
35 #include <dns/rrtype.h>
36 #include <dns/rrttl.h>
37 #include <dns/rrset.h>
38 #include <dns/tsig.h>
39 
40 using namespace std;
41 using boost::lexical_cast;
42 using namespace isc::dns::rdata;
43 using namespace isc::util;
44 
45 namespace isc {
46 namespace dns {
47 
48 namespace {
49 // protocol constants
50 const size_t HEADERLEN = 12;
51 
52 const unsigned int OPCODE_MASK = 0x7800;
53 const unsigned int OPCODE_SHIFT = 11;
54 const unsigned int RCODE_MASK = 0x000f;
55 
56 // This diagram shows the wire-format representation of the 2nd 16 bits of
57 // the DNS header section, which contain all defined flag bits.
58 //
59 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
60 // |QR| Opcode |AA|TC|RD|RA| |AD|CD| RCODE |
61 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
62 // 1 0 0 0| 0 1 1 1| 1 0 1 1| 0 0 0 0|
63 // 0x8 0x7 0xb 0x0
64 //
65 // This mask covers all the flag bits, and those bits only.
66 // Note: we reject a "flag" the is not covered by this mask in some of the
67 // public methods. This means our current definition is not fully extendable;
68 // applications cannot introduce a new flag bit temporarily without modifying
69 // the source code.
70 const unsigned int HEADERFLAG_MASK = 0x87b0;
71 
72 // This is a set of flag bits that should be preserved when building a reply
73 // from a request.
74 // Note: we assume the specific definition of HEADERFLAG_xx. We may change
75 // the definition in future, in which case we need to adjust this definition,
76 // too (see also the description about the Message::HeaderFlag type).
77 const uint16_t MESSAGE_REPLYPRESERVE = (Message::HEADERFLAG_RD |
78  Message::HEADERFLAG_CD);
79 
80 const char* const sectiontext[] = {
81  "QUESTION",
82  "ANSWER",
83  "AUTHORITY",
84  "ADDITIONAL"
85 };
86 }
87 
88 class MessageImpl {
89 public:
91  // Open issues: should we rather have a header in wire-format
92  // for efficiency?
95 
96  // We want to use NULL for [op,r]code_ to mean the code being not
97  // correctly parsed or set. We store the real code object in
98  // xxcode_placeholder_ and have xxcode_ refer to it when the object
99  // is valid.
100  const Rcode* rcode_;
102  const Opcode* opcode_;
104 
105  uint16_t flags_; // wire-format representation of header flags.
106 
108  static const unsigned int NUM_SECTIONS = 4; // TODO: revisit this design
109  int counts_[NUM_SECTIONS]; // TODO: revisit this definition
110  vector<QuestionPtr> questions_;
111  vector<RRsetPtr> rrsets_[NUM_SECTIONS];
114 
115  // RRsetsSorter* sorter_; : TODO
116 
117  void init();
118  void setOpcode(const Opcode& opcode);
119  void setRcode(const Rcode& rcode);
120  int parseQuestion(InputBuffer& buffer);
121  int parseSection(const Message::Section section, InputBuffer& buffer,
122  Message::ParseOptions options);
123  void addRR(Message::Section section, const Name& name,
124  const RRClass& rrclass, const RRType& rrtype,
125  const RRTTL& ttl, ConstRdataPtr rdata,
126  Message::ParseOptions options);
127  // There are also times where an RR needs to be added that
128  // represents an empty RRset. There is no Rdata in that case
129  void addRR(Message::Section section, const Name& name,
130  const RRClass& rrclass, const RRType& rrtype,
131  const RRTTL& ttl, Message::ParseOptions options);
132  void addEDNS(Message::Section section, const Name& name,
133  const RRClass& rrclass, const RRType& rrtype,
134  const RRTTL& ttl, const Rdata& rdata);
135  void addTSIG(Message::Section section, unsigned int count,
136  const InputBuffer& buffer, size_t start_position,
137  const Name& name, const RRClass& rrclass,
138  const RRTTL& ttl, const Rdata& rdata);
139  void toWire(AbstractMessageRenderer& renderer, TSIGContext* tsig_ctx);
140 };
141 
142 MessageImpl::MessageImpl(Message::Mode mode) :
143  mode_(mode),
144  rcode_placeholder_(Rcode(0)), // as a placeholder the value doesn't matter
145  opcode_placeholder_(Opcode(0)) // ditto
146 {
147  init();
148 }
149 
150 void
152  flags_ = 0;
153  qid_ = 0;
154  rcode_ = NULL;
155  opcode_ = NULL;
156  edns_ = EDNSPtr();
158 
159  for (int i = 0; i < NUM_SECTIONS; ++i) {
160  counts_[i] = 0;
161  }
162 
163  header_parsed_ = false;
164  questions_.clear();
168 }
169 
170 void
172  opcode_placeholder_ = opcode;
174 }
175 
176 void
178  rcode_placeholder_ = rcode;
180 }
181 
182 namespace {
183 // This helper class is used by MessageImpl::toWire() to render a set of
184 // RRsets of a specific section of message to a given MessageRenderer.
185 //
186 // A RenderSection object is expected to be used with a QuestionIterator or
187 // SectionIterator. Its operator() is called for each RRset as the iterator
188 // iterates over the corresponding section, and it renders the RRset to
189 // the given MessageRenderer, while counting the number of RRs (note: not
190 // RRsets) successfully rendered. If the MessageRenderer reports the need
191 // for truncation (via its isTruncated() method), the RenderSection object
192 // stops rendering further RRsets. In addition, unless partial_ok (given on
193 // construction) is true, it removes any RRs that are partially rendered
194 // from the MessageRenderer.
195 //
196 // On the completion of rendering the entire section, the owner of the
197 // RenderSection object can get the number of rendered RRs via the
198 // getTotalCount() method.
199 template <typename T>
200 struct RenderSection {
201  RenderSection(AbstractMessageRenderer& renderer, const bool partial_ok) :
202  counter_(0), renderer_(renderer), partial_ok_(partial_ok),
203  truncated_(false)
204  {}
205  void operator()(const T& entry) {
206  // If it's already truncated, ignore the rest of the section.
207  if (truncated_) {
208  return;
209  }
210  const size_t pos0 = renderer_.getLength();
211  counter_ += entry->toWire(renderer_);
212  if (renderer_.isTruncated()) {
213  truncated_ = true;
214  if (!partial_ok_) {
215  // roll back to the end of the previous RRset.
216  renderer_.trim(renderer_.getLength() - pos0);
217  }
218  }
219  }
220  unsigned int getTotalCount() { return (counter_); }
221  unsigned int counter_;
222  AbstractMessageRenderer& renderer_;
223  const bool partial_ok_;
225 };
226 }
227 
228 void
230  if (mode_ != Message::RENDER) {
232  "Message rendering attempted in non render mode");
233  }
234  if (rcode_ == NULL) {
236  "Message rendering attempted without Rcode set");
237  }
238  if (opcode_ == NULL) {
240  "Message rendering attempted without Opcode set");
241  }
242 
243  // Reserve the space for TSIG (if needed) so that we can handle truncation
244  // case correctly later when that happens. orig_xxx variables remember
245  // some configured parameters of renderer in case they are needed in
246  // truncation processing below.
247  const size_t tsig_len = (tsig_ctx != NULL) ? tsig_ctx->getTSIGLength() : 0;
248  const size_t orig_msg_len_limit = renderer.getLengthLimit();
249  const AbstractMessageRenderer::CompressMode orig_compress_mode =
250  renderer.getCompressMode();
251 
252  // We are going to skip soon, so we need to clear the renderer
253  // But we'll leave the length limit and the compress mode intact
254  // (or shortened in case of TSIG)
255  renderer.clear();
256  renderer.setCompressMode(orig_compress_mode);
257 
258  if (tsig_len > 0) {
259  if (tsig_len > orig_msg_len_limit) {
260  isc_throw(InvalidParameter, "Failed to render DNS message: "
261  "too small limit for a TSIG (" <<
262  orig_msg_len_limit << ")");
263  }
264  renderer.setLengthLimit(orig_msg_len_limit - tsig_len);
265  } else {
266  renderer.setLengthLimit(orig_msg_len_limit);
267  }
268 
269  // reserve room for the header
270  if (renderer.getLengthLimit() < HEADERLEN) {
271  isc_throw(InvalidParameter, "Failed to render DNS message: "
272  "too small limit for a Header");
273  }
274  renderer.skip(HEADERLEN);
275 
276  uint16_t qdcount =
277  for_each(questions_.begin(), questions_.end(),
278  RenderSection<QuestionPtr>(renderer, false)).getTotalCount();
279 
280  // TODO: sort RRsets in each section based on configuration policy.
281  uint16_t ancount = 0;
282  if (!renderer.isTruncated()) {
283  ancount =
284  for_each(rrsets_[Message::SECTION_ANSWER].begin(),
286  RenderSection<RRsetPtr>(renderer, true)).getTotalCount();
287  }
288  uint16_t nscount = 0;
289  if (!renderer.isTruncated()) {
290  nscount =
291  for_each(rrsets_[Message::SECTION_AUTHORITY].begin(),
293  RenderSection<RRsetPtr>(renderer, true)).getTotalCount();
294  }
295  uint16_t arcount = 0;
296  if (renderer.isTruncated()) {
298  } else {
299  arcount =
300  for_each(rrsets_[Message::SECTION_ADDITIONAL].begin(),
302  RenderSection<RRsetPtr>(renderer, false)).getTotalCount();
303  }
304 
305  // Add EDNS OPT RR if necessary. Basically, we add it only when EDNS
306  // has been explicitly set. However, if the RCODE would require it and
307  // no EDNS has been set we generate a temporary local EDNS and use it.
308  if (!renderer.isTruncated()) {
309  ConstEDNSPtr local_edns = edns_;
310  if (!local_edns && rcode_->getExtendedCode() != 0) {
311  local_edns = ConstEDNSPtr(new EDNS());
312  }
313  if (local_edns) {
314  arcount += local_edns->toWire(renderer, rcode_->getExtendedCode());
315  }
316  }
317 
318  // If we're adding a TSIG to a truncated message, clear all RRsets
319  // from the message except for the question before adding the TSIG.
320  // If even (some of) the question doesn't fit, don't include it.
321  if (tsig_ctx != NULL && renderer.isTruncated()) {
322  renderer.clear();
323  renderer.setLengthLimit(orig_msg_len_limit - tsig_len);
324  renderer.setCompressMode(orig_compress_mode);
325  renderer.skip(HEADERLEN);
326  qdcount = for_each(questions_.begin(), questions_.end(),
327  RenderSection<QuestionPtr>(renderer,
328  false)).getTotalCount();
329  ancount = 0;
330  nscount = 0;
331  arcount = 0;
332  }
333 
334  // Adjust the counter buffer.
335  // XXX: these may not be equal to the number of corresponding entries
336  // in rrsets_[] or questions_ if truncation occurred or an EDNS OPT RR
337  // was inserted. This is not good, and we should revisit the entire
338  // design.
340  counts_[Message::SECTION_ANSWER] = ancount;
343 
344  // fill in the header
345  size_t header_pos = 0;
346  renderer.writeUint16At(qid_, header_pos);
347  header_pos += sizeof(uint16_t);
348 
349  uint16_t codes_and_flags =
350  (opcode_->getCode() << OPCODE_SHIFT) & OPCODE_MASK;
351  codes_and_flags |= (rcode_->getCode() & RCODE_MASK);
352  codes_and_flags |= (flags_ & HEADERFLAG_MASK);
353  renderer.writeUint16At(codes_and_flags, header_pos);
354  header_pos += sizeof(uint16_t);
355  // TODO: should avoid repeated pattern
356  renderer.writeUint16At(qdcount, header_pos);
357  header_pos += sizeof(uint16_t);
358  renderer.writeUint16At(ancount, header_pos);
359  header_pos += sizeof(uint16_t);
360  renderer.writeUint16At(nscount, header_pos);
361  header_pos += sizeof(uint16_t);
362  renderer.writeUint16At(arcount, header_pos);
363 
364  // Add TSIG, if necessary, at the end of the message.
365  if (tsig_ctx != NULL) {
366  // Release the reserved space in the renderer.
367  renderer.setLengthLimit(orig_msg_len_limit);
368 
369  const int tsig_count =
370  tsig_ctx->sign(qid_, renderer.getData(),
371  renderer.getLength())->toWire(renderer);
372  if (tsig_count != 1) {
373  isc_throw(Unexpected, "Failed to render a TSIG RR");
374  }
375 
376  // update the ARCOUNT for the TSIG RR. Note that for a sane DNS
377  // message arcount should never overflow to 0.
378  renderer.writeUint16At(++arcount, header_pos);
379  }
380 }
381 
383  impl_(new MessageImpl(mode))
384 {}
385 
387  delete impl_;
388 }
389 
390 bool
392  if (flag == 0 || (flag & ~HEADERFLAG_MASK) != 0) {
394  "Message::getHeaderFlag:: Invalid flag is specified: " <<
395  "0x" << std::hex << flag);
396  }
397  return ((impl_->flags_ & flag) != 0);
398 }
399 
400 void
401 Message::setHeaderFlag(const HeaderFlag flag, const bool on) {
402  if (impl_->mode_ != Message::RENDER) {
404  "setHeaderFlag performed in non-render mode");
405  }
406  if (flag == 0 || (flag & ~HEADERFLAG_MASK) != 0) {
408  "Message::getHeaderFlag:: Invalid flag is specified: " <<
409  "0x" << std::hex << flag);
410  }
411  if (on) {
412  impl_->flags_ |= flag;
413  } else {
414  impl_->flags_ &= ~flag;
415  }
416 }
417 
418 qid_t
420  return (impl_->qid_);
421 }
422 
423 void
425  if (impl_->mode_ != Message::RENDER) {
427  "setQid performed in non-render mode");
428  }
429  impl_->qid_ = qid;
430 }
431 
432 const Rcode&
434  if (impl_->rcode_ == NULL) {
435  isc_throw(InvalidMessageOperation, "getRcode attempted before set");
436  }
437  return (*impl_->rcode_);
438 }
439 
440 void
441 Message::setRcode(const Rcode& rcode) {
442  if (impl_->mode_ != Message::RENDER) {
444  "setRcode performed in non-render mode");
445  }
446  impl_->setRcode(rcode);
447 }
448 
449 const Opcode&
451  if (impl_->opcode_ == NULL) {
452  isc_throw(InvalidMessageOperation, "getOpcode attempted before set");
453  }
454  return (*impl_->opcode_);
455 }
456 
457 void
458 Message::setOpcode(const Opcode& opcode) {
459  if (impl_->mode_ != Message::RENDER) {
461  "setOpcode performed in non-render mode");
462  }
463  impl_->setOpcode(opcode);
464 }
465 
468  return (impl_->edns_);
469 }
470 
471 void
473  if (impl_->mode_ != Message::RENDER) {
475  "setEDNS performed in non-render mode");
476  }
477  impl_->edns_ = edns;
478 }
479 
480 const TSIGRecord*
482  if (impl_->mode_ != Message::PARSE) {
484  "getTSIGRecord performed in non-parse mode");
485  }
486 
487  return (impl_->tsig_rr_.get());
488 }
489 
490 unsigned int
491 Message::getRRCount(const Section section) const {
492  if (static_cast<int>(section) >= MessageImpl::NUM_SECTIONS) {
493  isc_throw(OutOfRange, "Invalid message section: " << section);
494  }
495  return (impl_->counts_[section]);
496 }
497 
498 void
499 Message::addRRset(const Section section, RRsetPtr rrset) {
500  if (!rrset) {
502  "NULL RRset is given to Message::addRRset");
503  }
504  if (impl_->mode_ != Message::RENDER) {
506  "addRRset performed in non-render mode");
507  }
508  if (static_cast<int>(section) >= MessageImpl::NUM_SECTIONS) {
509  isc_throw(OutOfRange, "Invalid message section: " << section);
510  }
511 
512  impl_->rrsets_[section].push_back(rrset);
513  impl_->counts_[section] += rrset->getRdataCount();
514  impl_->counts_[section] += rrset->getRRsigDataCount();
515 }
516 
517 bool
518 Message::hasRRset(const Section section, const Name& name,
519  const RRClass& rrclass, const RRType& rrtype) const
520 {
521  if (static_cast<int>(section) >= MessageImpl::NUM_SECTIONS) {
522  isc_throw(OutOfRange, "Invalid message section: " << section);
523  }
524 
525  BOOST_FOREACH(ConstRRsetPtr r, impl_->rrsets_[section]) {
526  if (r->getClass() == rrclass &&
527  r->getType() == rrtype &&
528  r->getName() == name) {
529  return (true);
530  }
531  }
532 
533  return (false);
534 }
535 
536 bool
537 Message::hasRRset(const Section section, const RRsetPtr& rrset) const {
538  return (hasRRset(section, rrset->getName(),
539  rrset->getClass(), rrset->getType()));
540 }
541 
542 bool
543 Message::removeRRset(const Section section, RRsetIterator& iterator) {
544  if (static_cast<int>(section) >= MessageImpl::NUM_SECTIONS) {
545  isc_throw(OutOfRange, "Invalid message section: " << section);
546  }
547 
548  bool removed = false;
549  for (vector<RRsetPtr>::iterator i = impl_->rrsets_[section].begin();
550  i != impl_->rrsets_[section].end(); ++i) {
551  if (((*i)->getName() == (*iterator)->getName()) &&
552  ((*i)->getClass() == (*iterator)->getClass()) &&
553  ((*i)->getType() == (*iterator)->getType())) {
554 
555  // Found the matching RRset so remove it & ignore rest
556  impl_->counts_[section] -= (*iterator)->getRdataCount();
557  impl_->counts_[section] -= (*iterator)->getRRsigDataCount();
558  impl_->rrsets_[section].erase(i);
559  removed = true;
560  break;
561  }
562  }
563 
564  return (removed);
565 }
566 
567 void
569  if (impl_->mode_ != Message::RENDER) {
571  "clearSection performed in non-render mode");
572  }
573  if (static_cast<int>(section) >= MessageImpl::NUM_SECTIONS) {
574  isc_throw(OutOfRange, "Invalid message section: " << section);
575  }
576  if (section == Message::SECTION_QUESTION) {
577  impl_->questions_.clear();
578  } else {
579  impl_->rrsets_[section].clear();
580  }
581  impl_->counts_[section] = 0;
582 }
583 
584 void
586  if (impl_->mode_ != Message::RENDER) {
588  "addQuestion performed in non-render mode");
589  }
590 
591  impl_->questions_.push_back(question);
592  ++impl_->counts_[SECTION_QUESTION];
593 }
594 
595 void
596 Message::addQuestion(const Question& question) {
597  addQuestion(QuestionPtr(new Question(question)));
598 }
599 
600 void
602  impl_->toWire(renderer, tsig_ctx);
603 }
604 
605 void
607  if (impl_->mode_ != Message::PARSE) {
609  "Message parse attempted in non parse mode");
610  }
611 
612  if (impl_->header_parsed_) {
613  return;
614  }
615 
616  if ((buffer.getLength() - buffer.getPosition()) < HEADERLEN) {
617  isc_throw(MessageTooShort, "Malformed DNS message (short length): "
618  << buffer.getLength() - buffer.getPosition());
619  }
620 
621  impl_->qid_ = buffer.readUint16();
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);
626  impl_->counts_[SECTION_QUESTION] = buffer.readUint16();
627  impl_->counts_[SECTION_ANSWER] = buffer.readUint16();
628  impl_->counts_[SECTION_AUTHORITY] = buffer.readUint16();
629  impl_->counts_[SECTION_ADDITIONAL] = buffer.readUint16();
630 
631  impl_->header_parsed_ = true;
632 }
633 
634 void
636  if (impl_->mode_ != Message::PARSE) {
638  "Message parse attempted in non parse mode");
639  }
640 
641  // Clear any old parsed data
643 
644  buffer.setPosition(0);
645  parseHeader(buffer);
646 
647  impl_->counts_[SECTION_QUESTION] = impl_->parseQuestion(buffer);
648  impl_->counts_[SECTION_ANSWER] =
649  impl_->parseSection(SECTION_ANSWER, buffer, options);
650  impl_->counts_[SECTION_AUTHORITY] =
651  impl_->parseSection(SECTION_AUTHORITY, buffer, options);
652  impl_->counts_[SECTION_ADDITIONAL] =
653  impl_->parseSection(SECTION_ADDITIONAL, buffer, options);
654 }
655 
656 int
658  unsigned int added = 0;
659 
660  for (unsigned int count = 0;
662  ++count) {
663  const Name name(buffer);
664 
665  if ((buffer.getLength() - buffer.getPosition()) <
666  2 * sizeof(uint16_t)) {
667  isc_throw(DNSMessageFORMERR, "Question section too short: " <<
668  (buffer.getLength() - buffer.getPosition()) << " bytes");
669  }
670  const RRType rrtype(buffer.readUint16());
671  const RRClass rrclass(buffer.readUint16());
672 
673  // XXX: need a duplicate check. We might also want to have an
674  // optimized algorithm that requires the question section contain
675  // exactly one RR.
676 
677  questions_.push_back(QuestionPtr(new Question(name, rrclass, rrtype)));
678  ++added;
679  }
680 
681  return (added);
682 }
683 
684 namespace {
685 struct MatchRR : public unary_function<RRsetPtr, bool> {
686  MatchRR(const Name& name, const RRType& rrtype, const RRClass& rrclass) :
687  name_(name), rrtype_(rrtype), rrclass_(rrclass) {}
688  bool operator()(const RRsetPtr& rrset) const {
689  return (rrset->getType() == rrtype_ &&
690  rrset->getClass() == rrclass_ &&
691  rrset->getName() == name_);
692  }
693  const Name& name_;
694  const RRType& rrtype_;
695  const RRClass& rrclass_;
696 };
697 }
698 
699 // Note about design decision:
700 // we need some type specific processing here, including EDNS and TSIG.
701 // how much we should generalize/hardcode the special logic is subject
702 // to discussion. In terms of modularity it would be ideal to introduce
703 // an abstract class (say "MessageAttribute") and let other such
704 // concrete notions as EDNS or TSIG inherit from it. Then we would
705 // just do:
706 // message->addAttribute(rrtype, rrclass, buffer);
707 // to create and attach type-specific concrete object to the message.
708 //
709 // A major downside of this approach is, as usual, complexity due to
710 // indirection and performance penalty. Also, it may not be so easy
711 // to separate the processing logic because in many cases we'll need
712 // parse context for which the message class is responsible (e.g.
713 // to check the EDNS OPT RR only appears in the additional section,
714 // and appears only once).
715 //
716 // Another point to consider is that we may not need so many special
717 // types other than EDNS and TSIG (and when and if we implement it,
718 // SIG(0)); newer optional attributes of the message would more likely
719 // be standardized as new flags or options of EDNS. If that's the case,
720 // introducing an abstract class with all the overhead and complexity
721 // may not make much sense.
722 //
723 // Conclusion: don't over-generalize type-specific logic for now.
724 // introduce separate concrete classes, and move context-independent
725 // logic to that class; processing logic dependent on parse context
726 // is hardcoded here.
727 int
729  InputBuffer& buffer, Message::ParseOptions options)
730 {
731  assert(static_cast<int>(section) < MessageImpl::NUM_SECTIONS);
732 
733  unsigned int added = 0;
734 
735  for (unsigned int count = 0; count < counts_[section]; ++count) {
736  // We need to remember the start position for TSIG processing
737  const size_t start_position = buffer.getPosition();
738 
739  const Name name(buffer);
740 
741  // buffer must store at least RR TYPE, RR CLASS, TTL, and RDLEN.
742  if ((buffer.getLength() - buffer.getPosition()) <
743  3 * sizeof(uint16_t) + sizeof(uint32_t)) {
744  isc_throw(DNSMessageFORMERR, sectiontext[section] <<
745  " section too short: " <<
746  (buffer.getLength() - buffer.getPosition()) << " bytes");
747  }
748 
749  const RRType rrtype(buffer.readUint16());
750  const RRClass rrclass(buffer.readUint16());
751  const RRTTL ttl(buffer.readUint32());
752  const size_t rdlen = buffer.readUint16();
753 
754  // If class is ANY or NONE, rdlength may be zero, to signal
755  // an empty RRset.
756  // (the class check must be done to differentiate from RRTypes
757  // that can have zero length rdata
758  if ((rrclass == RRClass::ANY() || rrclass == RRClass::NONE()) &&
759  rdlen == 0) {
760  addRR(section, name, rrclass, rrtype, ttl, options);
761  ++added;
762  continue;
763  }
764  ConstRdataPtr rdata = createRdata(rrtype, rrclass, buffer, rdlen);
765 
766  if (rrtype == RRType::OPT()) {
767  addEDNS(section, name, rrclass, rrtype, ttl, *rdata);
768  } else if (rrtype == RRType::TSIG()) {
769  addTSIG(section, count, buffer, start_position, name, rrclass, ttl,
770  *rdata);
771  } else {
772  addRR(section, name, rrclass, rrtype, ttl, rdata, options);
773  ++added;
774  }
775  }
776 
777  return (added);
778 }
779 
780 void
782  const RRClass& rrclass, const RRType& rrtype,
783  const RRTTL& ttl, ConstRdataPtr rdata,
784  Message::ParseOptions options)
785 {
786  if ((options & Message::PRESERVE_ORDER) == 0) {
787  vector<RRsetPtr>::iterator it =
788  find_if(rrsets_[section].begin(), rrsets_[section].end(),
789  MatchRR(name, rrtype, rrclass));
790  if (it != rrsets_[section].end()) {
791  (*it)->setTTL(min((*it)->getTTL(), ttl));
792  (*it)->addRdata(rdata);
793  return;
794  }
795  }
796  RRsetPtr rrset(new RRset(name, rrclass, rrtype, ttl));
797  rrset->addRdata(rdata);
798  rrsets_[section].push_back(rrset);
799 }
800 
801 void
803  const RRClass& rrclass, const RRType& rrtype,
804  const RRTTL& ttl, Message::ParseOptions options)
805 {
806  if ((options & Message::PRESERVE_ORDER) == 0) {
807  vector<RRsetPtr>::iterator it =
808  find_if(rrsets_[section].begin(), rrsets_[section].end(),
809  MatchRR(name, rrtype, rrclass));
810  if (it != rrsets_[section].end()) {
811  (*it)->setTTL(min((*it)->getTTL(), ttl));
812  return;
813  }
814  }
815  RRsetPtr rrset(new RRset(name, rrclass, rrtype, ttl));
816  rrsets_[section].push_back(rrset);
817 }
818 
819 void
821  const RRClass& rrclass, const RRType& rrtype,
822  const RRTTL& ttl, const Rdata& rdata)
823 {
824  if (section != Message::SECTION_ADDITIONAL) {
826  "EDNS OPT RR found in an invalid section");
827  }
828  if (edns_) {
829  isc_throw(DNSMessageFORMERR, "multiple EDNS OPT RR found");
830  }
831 
832  uint8_t extended_rcode;
833  edns_ = ConstEDNSPtr(createEDNSFromRR(name, rrclass, rrtype, ttl, rdata,
834  extended_rcode));
835  setRcode(Rcode(rcode_->getCode(), extended_rcode));
836 }
837 
838 void
839 MessageImpl::addTSIG(Message::Section section, unsigned int count,
840  const InputBuffer& buffer, size_t start_position,
841  const Name& name, const RRClass& rrclass,
842  const RRTTL& ttl, const Rdata& rdata)
843 {
844  if (section != Message::SECTION_ADDITIONAL) {
846  "TSIG RR found in an invalid section");
847  }
848  if (count != counts_[section] - 1) {
849  isc_throw(DNSMessageFORMERR, "TSIG RR is not the last record");
850  }
851  // This check will never fail as the multiple TSIG RR case is
852  // caught before by the not the last record check...
853  if (tsig_rr_) {
854  isc_throw(DNSMessageFORMERR, "multiple TSIG RRs found");
855  }
856  tsig_rr_ = ConstTSIGRecordPtr(new TSIGRecord(name, rrclass,
857  ttl, rdata,
858  buffer.getPosition() -
859  start_position));
860 }
861 
862 namespace {
863 template <typename T>
864 struct SectionFormatter {
865  SectionFormatter(const Message::Section section, string& output) :
866  section_(section), output_(output) {}
867  void operator()(const T& entry) {
869  output_ += ";";
870  output_ += entry->toText();
871  output_ += "\n";
872  } else {
873  output_ += entry->toText();
874  }
875  }
877  string& output_;
878 };
879 }
880 
881 string
883  if (impl_->rcode_ == NULL) {
885  "Message::toText() attempted without Rcode set");
886  }
887  if (impl_->opcode_ == NULL) {
889  "Message::toText() attempted without Opcode set");
890  }
891 
892  string s;
893 
894  s += ";; ->>HEADER<<- opcode: " + impl_->opcode_->toText();
895  // for simplicity we don't consider extended rcode (unlike BIND9)
896  s += ", status: " + impl_->rcode_->toText();
897  s += ", id: " + boost::lexical_cast<string>(impl_->qid_);
898  s += "\n;; flags:";
900  s += " qr";
901  }
903  s += " aa";
904  }
906  s += " tc";
907  }
909  s += " rd";
910  }
912  s += " ra";
913  }
915  s += " ad";
916  }
918  s += " cd";
919  }
920 
921  // for simplicity, don't consider the update case for now
922  s += "; QUERY: " + // note: not "QUESTION" to be compatible with BIND 9 dig
923  lexical_cast<string>(impl_->counts_[SECTION_QUESTION]);
924  s += ", ANSWER: " +
925  lexical_cast<string>(impl_->counts_[SECTION_ANSWER]);
926  s += ", AUTHORITY: " +
927  lexical_cast<string>(impl_->counts_[SECTION_AUTHORITY]);
928 
929  unsigned int arcount = impl_->counts_[SECTION_ADDITIONAL];
930  if (impl_->edns_ != NULL) {
931  ++arcount;
932  }
933  if (impl_->tsig_rr_ != NULL) {
934  ++arcount;
935  }
936  s += ", ADDITIONAL: " + lexical_cast<string>(arcount) + "\n";
937 
938  if (impl_->edns_ != NULL) {
939  s += "\n;; OPT PSEUDOSECTION:\n";
940  s += impl_->edns_->toText();
941  }
942 
943  if (!impl_->questions_.empty()) {
944  s += "\n;; " +
945  string(sectiontext[SECTION_QUESTION]) + " SECTION:\n";
946  for_each(impl_->questions_.begin(), impl_->questions_.end(),
947  SectionFormatter<QuestionPtr>(SECTION_QUESTION, s));
948  }
949  if (!impl_->rrsets_[SECTION_ANSWER].empty()) {
950  s += "\n;; " +
951  string(sectiontext[SECTION_ANSWER]) + " SECTION:\n";
952  for_each(impl_->rrsets_[SECTION_ANSWER].begin(),
953  impl_->rrsets_[SECTION_ANSWER].end(),
954  SectionFormatter<RRsetPtr>(SECTION_ANSWER, s));
955  }
956  if (!impl_->rrsets_[SECTION_AUTHORITY].empty()) {
957  s += "\n;; " +
958  string(sectiontext[SECTION_AUTHORITY]) + " SECTION:\n";
959  for_each(impl_->rrsets_[SECTION_AUTHORITY].begin(),
960  impl_->rrsets_[SECTION_AUTHORITY].end(),
961  SectionFormatter<RRsetPtr>(SECTION_AUTHORITY, s));
962  }
963  if (!impl_->rrsets_[SECTION_ADDITIONAL].empty()) {
964  s += "\n;; " +
965  string(sectiontext[SECTION_ADDITIONAL]) +
966  " SECTION:\n";
967  for_each(impl_->rrsets_[SECTION_ADDITIONAL].begin(),
968  impl_->rrsets_[SECTION_ADDITIONAL].end(),
969  SectionFormatter<RRsetPtr>(SECTION_ADDITIONAL, s));
970  }
971 
972  if (impl_->tsig_rr_ != NULL) {
973  s += "\n;; TSIG PSEUDOSECTION:\n";
974  s += impl_->tsig_rr_->toText();
975  }
976 
977  return (s);
978 }
979 
980 void
982  impl_->init();
983  impl_->mode_ = mode;
984 }
985 
986 void
987 Message::appendSection(const Section section, const Message& source) {
988  if (static_cast<int>(section) >= MessageImpl::NUM_SECTIONS) {
989  isc_throw(OutOfRange, "Invalid message section: " << section);
990  }
991 
992  if (section == SECTION_QUESTION) {
993  for (QuestionIterator qi = source.beginQuestion();
994  qi != source.endQuestion();
995  ++qi) {
996  addQuestion(*qi);
997  }
998  } else {
999  for (RRsetIterator rrsi = source.beginSection(section);
1000  rrsi != source.endSection(section);
1001  ++rrsi) {
1002  addRRset(section, *rrsi);
1003  }
1004  }
1005 }
1006 
1007 void
1009  if (impl_->mode_ != Message::PARSE) {
1011  "makeResponse() is performed in non-parse mode");
1012  }
1013 
1014  impl_->mode_ = Message::RENDER;
1015 
1016  impl_->edns_ = EDNSPtr();
1017  impl_->flags_ &= MESSAGE_REPLYPRESERVE;
1019 
1020  impl_->rrsets_[SECTION_ANSWER].clear();
1021  impl_->counts_[SECTION_ANSWER] = 0;
1022  impl_->rrsets_[SECTION_AUTHORITY].clear();
1023  impl_->counts_[SECTION_AUTHORITY] = 0;
1024  impl_->rrsets_[SECTION_ADDITIONAL].clear();
1025  impl_->counts_[SECTION_ADDITIONAL] = 0;
1026 }
1027 
1031 template <typename T>
1033  SectionIteratorImpl(const typename vector<T>::const_iterator& it) :
1034  it_(it) {}
1035  typename vector<T>::const_iterator it_;
1036 };
1037 
1038 template <typename T>
1040  impl_ = new SectionIteratorImpl<T>(impl.it_);
1041 }
1042 
1043 template <typename T>
1045  delete impl_;
1046 }
1047 
1048 template <typename T>
1050  impl_(new SectionIteratorImpl<T>(source.impl_->it_))
1051 {}
1052 
1053 template <typename T>
1054 void
1056  if (impl_ == source.impl_) {
1057  return;
1058  }
1059  SectionIteratorImpl<T>* newimpl =
1060  new SectionIteratorImpl<T>(source.impl_->it_);
1061  delete impl_;
1062  impl_ = newimpl;
1063 }
1064 
1065 template <typename T>
1068  ++(impl_->it_);
1069  return (*this);
1070 }
1071 
1072 template <typename T>
1075  SectionIterator<T> tmp(*this);
1076  ++(*this);
1077  return (tmp);
1078 }
1079 
1080 template <typename T>
1081 const T&
1083  return (*(impl_->it_));
1084 }
1085 
1086 template <typename T>
1087 const T*
1089  return (&(operator*()));
1090 }
1091 
1092 template <typename T>
1093 bool
1095  return (impl_->it_ == other.impl_->it_);
1096 }
1097 
1098 template <typename T>
1099 bool
1101  return (impl_->it_ != other.impl_->it_);
1102 }
1103 
1108 template class SectionIterator<QuestionPtr>;
1109 template class SectionIterator<RRsetPtr>;
1110 
1111 namespace {
1112 typedef SectionIteratorImpl<QuestionPtr> QuestionIteratorImpl;
1113 typedef SectionIteratorImpl<RRsetPtr> RRsetIteratorImpl;
1114 }
1115 
1119 const QuestionIterator
1121  return (QuestionIterator(QuestionIteratorImpl(impl_->questions_.begin())));
1122 }
1123 
1124 const QuestionIterator
1126  return (QuestionIterator(QuestionIteratorImpl(impl_->questions_.end())));
1127 }
1128 
1133 Message::beginSection(const Section section) const {
1134  if (static_cast<int>(section) >= MessageImpl::NUM_SECTIONS) {
1135  isc_throw(OutOfRange, "Invalid message section: " << section);
1136  }
1137  if (section == SECTION_QUESTION) {
1139  "RRset iterator is requested for question");
1140  }
1141 
1142  return (RRsetIterator(RRsetIteratorImpl(impl_->rrsets_[section].begin())));
1143 }
1144 
1146 Message::endSection(const Section section) const {
1147  if (static_cast<int>(section) >= MessageImpl::NUM_SECTIONS) {
1148  isc_throw(OutOfRange, "Invalid message section: " << section);
1149  }
1150  if (section == SECTION_QUESTION) {
1152  "RRset iterator is requested for question");
1153  }
1154 
1155  return (RRsetIterator(RRsetIteratorImpl(impl_->rrsets_[section].end())));
1156 }
1157 
1158 ostream&
1159 operator<<(ostream& os, const Message& message) {
1160  return (os << message.toText());
1161 }
1162 } // end of namespace dns
1163 } // end of namespace isc
isc::dns::SectionIteratorImpl::it_
vector< T >::const_iterator it_
Definition: dns/message.cc:1035
isc::dns::RRClass::ANY
static const RRClass & ANY()
Definition: rrclass.h:313
truncated_
bool truncated_
Definition: dns/message.cc:224
isc::dns::QuestionPtr
boost::shared_ptr< Question > QuestionPtr
A pointer-like type pointing to an Question object.
Definition: question.h:28
isc::Unexpected
A generic exception that is thrown when an unexpected error condition occurs.
Definition: exceptions/exceptions.h:153
isc::dns::Message::SECTION_AUTHORITY
@ SECTION_AUTHORITY
Authority section.
Definition: message.h:236
isc::dns::AbstractMessageRenderer::getCompressMode
virtual CompressMode getCompressMode() const =0
Return the compression mode of the renderer class object.
isc::dns::Message::removeRRset
bool removeRRset(const Section section, RRsetIterator &iterator)
Remove RRSet from Message.
Definition: dns/message.cc:543
isc::dns::SectionIterator::operator!=
bool operator!=(const SectionIterator< T > &other) const
Definition: dns/message.cc:1100
renderer_
AbstractMessageRenderer & renderer_
Definition: dns/message.cc:222
isc::dns::AbstractMessageRenderer::getLength
size_t getLength() const
Return the length of data written in the internal buffer.
Definition: messagerenderer.h:144
isc::dns::ConstEDNSPtr
boost::shared_ptr< const EDNS > ConstEDNSPtr
A pointer-like type pointing to an immutable EDNS object.
Definition: edns.h:37
isc::dns::Message::makeResponse
void makeResponse()
Prepare for making a response from a request.
Definition: dns/message.cc:1008
isc::dns::Message::HEADERFLAG_AD
@ HEADERFLAG_AD
Authentic data (RFC4035)
Definition: message.h:199
isc::dns::RRsetPtr
boost::shared_ptr< AbstractRRset > RRsetPtr
A pointer-like type pointing to an RRset object.
Definition: rrset.h:47
isc::dns::AbstractMessageRenderer::isTruncated
virtual bool isTruncated() const =0
Return whether truncation has occurred while rendering.
isc::dns::AbstractMessageRenderer::setLengthLimit
virtual void setLengthLimit(size_t len)=0
Set the maximum length of rendered data that can fit in the corresponding DNS message without truncat...
isc::dns::Opcode
The Opcode class objects represent standard OPCODEs of the header section of DNS messages as defined ...
Definition: opcode.h:32
isc::dns::MessageImpl::questions_
vector< QuestionPtr > questions_
Definition: dns/message.cc:110
isc::dns::MessageImpl::init
void init()
Definition: dns/message.cc:151
isc::dns::Message::HEADERFLAG_TC
@ HEADERFLAG_TC
Truncation.
Definition: message.h:196
opcode.h
isc::dns::AbstractMessageRenderer::CompressMode
CompressMode
Compression mode constants.
Definition: messagerenderer.h:93
rrttl.h
isc::dns::Message::getEDNS
ConstEDNSPtr getEDNS() const
Return, if any, the EDNS associated with the message.
Definition: dns/message.cc:467
isc::dns::MessageImpl::parseSection
int parseSection(const Message::Section section, InputBuffer &buffer, Message::ParseOptions options)
Definition: dns/message.cc:728
rrclass_
const RRClass & rrclass_
Definition: dns/message.cc:695
isc::dns::Message::HeaderFlag
HeaderFlag
Constants for flag bit fields of a DNS message header.
Definition: message.h:193
isc::dns::EDNSPtr
boost::shared_ptr< EDNS > EDNSPtr
A pointer-like type pointing to an EDNS object.
Definition: edns.h:31
name.h
mode_
CompressMode mode_
Definition: rdatafields.cc:97
isc::dns::Message::HEADERFLAG_QR
@ HEADERFLAG_QR
Query (if cleared) or response (if set)
Definition: message.h:194
isc::dns::Message::getQid
qid_t getQid() const
Return the query ID given in the header section of the message.
Definition: dns/message.cc:419
isc::dns::Message::setEDNS
void setEDNS(ConstEDNSPtr edns)
Set EDNS for the message.
Definition: dns/message.cc:472
isc::dns::Message::getRRCount
unsigned int getRRCount(const Section section) const
Returns the number of RRs contained in the given section.
Definition: dns/message.cc:491
rdataclass.h
isc::dns::RRsetIterator
SectionIterator< RRsetPtr > RRsetIterator
Definition: message.h:109
isc::dns::Message::SECTION_ADDITIONAL
@ SECTION_ADDITIONAL
Additional section.
Definition: message.h:237
isc::dns::SectionIterator::operator=
void operator=(const SectionIterator< T > &source)
Definition: dns/message.cc:1055
isc::dns::Message::getHeaderFlag
bool getHeaderFlag(const HeaderFlag flag) const
Return whether the specified header flag bit is set in the header section.
Definition: dns/message.cc:391
isc::dns::rdata::Rdata
The Rdata class is an abstract base class that provides a set of common interfaces to manipulate conc...
Definition: rdata.h:123
isc::dns::MessageImpl::qid_
qid_t qid_
Definition: dns/message.cc:94
isc::dns::Message::Mode
Mode
Constants to specify the operation mode of the Message.
Definition: message.h:146
isc::util::InputBuffer::readUint32
uint32_t readUint32()
Read an unsigned 32-bit integer in network byte order from the buffer, convert it to host byte order,...
Definition: buffer.h:162
isc::dns::SectionIterator
SectionIterator is a templated class to provide standard-compatible iterators for Questions and RRset...
Definition: message.h:91
isc::dns::MessageImpl::header_parsed_
bool header_parsed_
Definition: dns/message.cc:107
edns.h
exceptions.h
isc::dns::MessageImpl::opcode_placeholder_
Opcode opcode_placeholder_
Definition: dns/message.cc:103
isc::dns::MessageImpl::edns_
ConstEDNSPtr edns_
Definition: dns/message.cc:112
rrclass.h
isc::dns::AbstractMessageRenderer
The AbstractMessageRenderer class is an abstract base class that provides common interfaces for rende...
Definition: messagerenderer.h:68
rrtype_
const RRType & rrtype_
Definition: dns/message.cc:694
isc::dns::MessageImpl::addRR
void addRR(Message::Section section, const Name &name, const RRClass &rrclass, const RRType &rrtype, const RRTTL &ttl, ConstRdataPtr rdata, Message::ParseOptions options)
Definition: dns/message.cc:781
isc::dns::MessageImpl::NUM_SECTIONS
static const unsigned int NUM_SECTIONS
Definition: dns/message.cc:108
isc::dns::Message::setQid
void setQid(qid_t qid)
Set the query ID of the header section of the message.
Definition: dns/message.cc:424
isc::dns::MessageImpl::opcode_
const Opcode * opcode_
Definition: dns/message.cc:102
isc::util
Definition: edns.h:19
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc::util::InputBuffer::readUint16
uint16_t readUint16()
Read an unsigned 16-bit integer in network byte order from the buffer, convert it to host byte order,...
Definition: buffer.h:142
isc::dns::TSIGRecord
TSIG resource record.
Definition: tsigrecord.h:54
isc::dns::Message::fromWire
void fromWire(isc::util::InputBuffer &buffer, ParseOptions options=PARSE_DEFAULT)
(Re)build a Message object from wire-format data.
Definition: dns/message.cc:635
isc::dns::MessageImpl::setRcode
void setRcode(const Rcode &rcode)
Definition: dns/message.cc:177
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
isc::dns::Message::RENDER
@ RENDER
Render mode (building an outgoing message)
Definition: message.h:148
isc::dns::TSIGContext::getTSIGLength
size_t getTSIGLength() const
Return the expected length of TSIG RR after sign()
Definition: tsig.cc:295
isc::dns::Message::~Message
~Message()
The destructor.
Definition: dns/message.cc:386
isc::dns::TSIGContext::sign
ConstTSIGRecordPtr sign(const uint16_t qid, const void *const data, const size_t data_len)
Sign a DNS message.
Definition: tsig.cc:344
isc::dns::EDNS
The EDNS class represents the EDNS OPT RR defined in RFC2671.
Definition: edns.h:123
isc::InvalidParameter
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
Definition: exceptions/exceptions.h:124
isc::dns::MessageImpl::rcode_
const Rcode * rcode_
Definition: dns/message.cc:100
question.h
section_
const Message::Section section_
Definition: dns/message.cc:876
isc::dns::Question
The Question class encapsulates the common search key of DNS lookup, consisting of owner name,...
Definition: question.h:95
isc::dns::SectionIterator::~SectionIterator
~SectionIterator()
Definition: dns/message.cc:1044
isc::dns::operator<<
ostream & operator<<(std::ostream &os, const EDNS &edns)
Insert the EDNS as a string into stream.
Definition: edns.cc:172
message.h
isc::dns::Rcode::getCode
uint16_t getCode() const
Returns the Rcode code value.
Definition: rcode.h:106
isc::dns::qid_t
uint16_t qid_t
Definition: message.h:75
isc::dns::Message::HEADERFLAG_RD
@ HEADERFLAG_RD
Recursion desired.
Definition: message.h:197
isc::dns::QuestionIterator
SectionIterator< QuestionPtr > QuestionIterator
Definition: message.h:108
rrset.h
isc::dns::Message::SECTION_QUESTION
@ SECTION_QUESTION
Question section
Definition: message.h:234
isc::dns::Name
The Name class encapsulates DNS names.
Definition: name.h:223
isc::dns::SectionIterator::operator->
const T * operator->() const
Definition: dns/message.cc:1088
isc::dns::Message::hasRRset
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...
Definition: dns/message.cc:518
isc::dns::Message::setOpcode
void setOpcode(const Opcode &opcode)
Set the OPCODE of the header section of the message.
Definition: dns/message.cc:458
isc::dns::RRClass::NONE
static const RRClass & NONE()
Definition: rrclass.h:307
isc::dns::Message::beginSection
const RRsetIterator beginSection(const Section section) const
Return an iterator corresponding to the beginning of the given section (other than Question) of the m...
Definition: dns/message.cc:1133
isc::dns::InvalidMessageSection
A standard DNS module exception that is thrown if a section iterator is being constructed for an inco...
Definition: message.h:47
isc::dns::SectionIterator::operator++
SectionIterator< T > & operator++()
Definition: dns/message.cc:1067
isc::dns::SectionIterator::operator==
bool operator==(const SectionIterator< T > &other) const
Definition: dns/message.cc:1094
isc::ha::impl
HAImplPtr impl
Definition: ha_callouts.cc:23
isc::dns::RRType::TSIG
static const RRType & TSIG()
Definition: rrtype.h:371
isc::dns::MessageTooShort
A standard DNS module exception that is thrown if a wire format message parser encounters a short len...
Definition: message.h:36
isc::dns::MessageImpl::rrsets_
vector< RRsetPtr > rrsets_[NUM_SECTIONS]
Definition: dns/message.cc:111
isc::dns::RRType::OPT
static const RRType & OPT()
Definition: rrtype.h:599
isc::dns::Message::endSection
const RRsetIterator endSection(const Section section) const
Return an iterator corresponding to the end of the given section (other than Question) of the message...
Definition: dns/message.cc:1146
isc::dns::Message::beginQuestion
const QuestionIterator beginQuestion() const
Return an iterator corresponding to the beginning of the Question section of the message.
Definition: dns/message.cc:1120
rrtype.h
isc::dns::AbstractMessageRenderer::skip
void skip(size_t len)
Insert a specified length of gap at the end of the buffer.
Definition: messagerenderer.h:241
isc::dns::Message::HEADERFLAG_RA
@ HEADERFLAG_RA
Recursion available.
Definition: message.h:198
isc::dns::Rcode::getExtendedCode
uint8_t getExtendedCode() const
Returns the upper 8-bit of the Rcode code value.
Definition: rcode.cc:75
tsig.h
isc::dns::Message::getRcode
const Rcode & getRcode() const
Return the Response Code of the message.
Definition: dns/message.cc:433
isc::dns::MessageImpl::parseQuestion
int parseQuestion(InputBuffer &buffer)
Definition: dns/message.cc:657
isc::dns::RRTTL
The RRTTL class encapsulates TTLs used in DNS resource records.
Definition: rrttl.h:55
buffer.h
isc::dns::Message::PRESERVE_ORDER
@ PRESERVE_ORDER
Preserve RR order and don't combine them.
Definition: message.h:589
isc::dns::Message::HEADERFLAG_CD
@ HEADERFLAG_CD
DNSSEC checking disabled (RFC4035)
Definition: message.h:200
isc::dns::SectionIterator::operator*
const T & operator*() const
Definition: dns/message.cc:1082
isc::dns::Opcode::toText
std::string toText() const
Convert the Opcode to a string.
Definition: opcode.cc:53
isc::util::InputBuffer::setPosition
void setPosition(size_t position)
Set the read position of the buffer to the given value.
Definition: buffer.h:115
isc::dns::Message::ParseOptions
ParseOptions
Parse options.
Definition: message.h:587
isc::util::InputBuffer::getLength
size_t getLength() const
Return the length of the data stored in the buffer.
Definition: buffer.h:100
isc::dns::ConstTSIGRecordPtr
boost::shared_ptr< const TSIGRecord > ConstTSIGRecordPtr
A pointer-like type pointing to an immutable TSIGRecord object.
Definition: tsigrecord.h:280
isc::dns::MessageImpl::counts_
int counts_[NUM_SECTIONS]
Definition: dns/message.cc:109
partial_ok_
const bool partial_ok_
Definition: dns/message.cc:223
isc::util::InputBuffer
The InputBuffer class is a buffer abstraction for manipulating read-only data.
Definition: buffer.h:81
isc::dns::MessageImpl::tsig_rr_
ConstTSIGRecordPtr tsig_rr_
Definition: dns/message.cc:113
isc::dns::MessageImpl::flags_
uint16_t flags_
Definition: dns/message.cc:105
isc::dns::Message::getTSIGRecord
const TSIGRecord * getTSIGRecord() const
Return, if any, the TSIG record contained in the received message.
Definition: dns/message.cc:481
isc::dns::Message::addRRset
void addRRset(const Section section, RRsetPtr rrset)
Add a (pointer like object of) RRset to the given section of the message.
Definition: dns/message.cc:499
isc::dns::MessageImpl::mode_
Message::Mode mode_
Definition: dns/message.cc:93
isc::dns::rdata
Definition: dns_fwd.h:32
isc::dns::AbstractMessageRenderer::writeUint16At
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 ...
Definition: messagerenderer.h:291
isc::OutOfRange
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
Definition: exceptions/exceptions.h:115
isc::dns::Message::setRcode
void setRcode(const Rcode &rcode)
Set the Response Code of the message.
Definition: dns/message.cc:441
isc::dns::DNSMessageFORMERR
Definition: dns/exceptions.h:56
isc::dns::AbstractMessageRenderer::getData
const void * getData() const
Return a pointer to the head of the data stored in the internal buffer.
Definition: messagerenderer.h:139
isc::dns::rdata::ConstRdataPtr
boost::shared_ptr< const Rdata > ConstRdataPtr
Definition: rdata.h:72
isc::dns::MessageImpl::addTSIG
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)
Definition: dns/message.cc:839
counter_
unsigned int counter_
Definition: dns/message.cc:221
isc::dns::Opcode::getCode
CodeValue getCode() const
Returns the Opcode code value.
Definition: opcode.h:78
isc::dns::Message
The Message class encapsulates a standard DNS message.
Definition: message.h:143
isc::dns::Message::clearSection
void clearSection(const Section section)
Remove all RRSets from the given Section.
Definition: dns/message.cc:568
exceptions.h
isc::dns::Message::parseHeader
void parseHeader(isc::util::InputBuffer &buffer)
Parse the header section of the Message.
Definition: dns/message.cc:606
name_
const Name & name_
Definition: dns/message.cc:693
isc::dns::RRset
The RRset class is a concrete derived class of BasicRRset which contains a pointer to an additional R...
Definition: rrset.h:847
isc::dns::SectionIteratorImpl::SectionIteratorImpl
SectionIteratorImpl(const typename vector< T >::const_iterator &it)
Definition: dns/message.cc:1033
isc::dns::InvalidMessageOperation
A standard DNS module exception that is thrown if a Message class method is called that is prohibited...
Definition: message.h:58
isc::dns::AbstractMessageRenderer::getLengthLimit
virtual size_t getLengthLimit() const =0
Return the maximum length of rendered data that can fit in the corresponding DNS message without trun...
isc::dns::MessageImpl::toWire
void toWire(AbstractMessageRenderer &renderer, TSIGContext *tsig_ctx)
Definition: dns/message.cc:229
isc::dns::MessageImpl::addEDNS
void addEDNS(Message::Section section, const Name &name, const RRClass &rrclass, const RRType &rrtype, const RRTTL &ttl, const Rdata &rdata)
Definition: dns/message.cc:820
isc::util::InputBuffer::getPosition
size_t getPosition() const
Return the current read position.
Definition: buffer.h:102
isc::dns::ConstRRsetPtr
boost::shared_ptr< const AbstractRRset > ConstRRsetPtr
A pointer-like type pointing to an (immutable) RRset object.
Definition: rrset.h:60
isc::dns::rdata::createRdata
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.
Definition: rdata.cc:56
isc::dns::Message::toWire
void toWire(AbstractMessageRenderer &renderer, TSIGContext *tsig_ctx=NULL)
Render the message in wire formant into a message renderer object with (or without) TSIG.
Definition: dns/message.cc:601
isc::dns::Message::clear
void clear(Mode mode)
Clear the message content (if any) and reinitialize it in the specified mode.
Definition: dns/message.cc:981
isc::dns::Message::setHeaderFlag
void setHeaderFlag(const HeaderFlag flag, const bool on=true)
Set or clear the specified header flag bit in the header section.
Definition: dns/message.cc:401
isc::dns::Message::SECTION_ANSWER
@ SECTION_ANSWER
Answer section.
Definition: message.h:235
rcode.h
output_
string & output_
Definition: dns/message.cc:877
isc::dns::MessageImpl::setOpcode
void setOpcode(const Opcode &opcode)
Definition: dns/message.cc:171
isc::dns::Message::HEADERFLAG_AA
@ HEADERFLAG_AA
Authoritative answer.
Definition: message.h:195
isc::dns::AbstractMessageRenderer::setCompressMode
virtual void setCompressMode(CompressMode mode)=0
Set the compression mode of the renderer class object.
isc::dns::RRType
The RRType class encapsulates DNS resource record types.
Definition: rrtype.h:106
isc::dns::SectionIteratorImpl
Template version of Section Iterator.
Definition: dns/message.cc:1032
isc::dns::Message::PARSE
@ PARSE
Parse mode (handling an incoming message)
Definition: message.h:147
isc::dns::Message::toText
std::string toText() const
Convert the Message to a string.
Definition: dns/message.cc:882
isc::dns::Message::getOpcode
const Opcode & getOpcode() const
Return the OPCODE given in the header section of the message.
Definition: dns/message.cc:450
isc::dns::Message::Section
Section
Constants to specify sections of a DNS message.
Definition: message.h:233
isc::dns::RRClass
The RRClass class encapsulates DNS resource record classes.
Definition: rrclass.h:98
isc::dns::MessageImpl
Definition: dns/message.cc:88
isc::dns::AbstractMessageRenderer::clear
virtual void clear()
Clear the internal buffer and other internal resources.
Definition: messagerenderer.cc:392
isc::dns::TSIGContext
TSIG session context.
Definition: tsig.h:172
isc::dns::Message::endQuestion
const QuestionIterator endQuestion() const
Return an iterator corresponding to the end of the Question section of the message.
Definition: dns/message.cc:1125
isc::dns::createEDNSFromRR
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.
Definition: edns.cc:157
isc::dns::Message::appendSection
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...
Definition: dns/message.cc:987
isc::dns::Rcode::toText
std::string toText() const
Convert the Rcode to a string.
Definition: rcode.cc:80
isc::dns::Rcode
DNS Response Codes (RCODEs) class.
Definition: rcode.h:40
isc::dns::MessageImpl::rcode_placeholder_
Rcode rcode_placeholder_
Definition: dns/message.cc:101
messagerenderer.h
isc::dns::Message::Message
Message(Mode mode)
The constructor.
Definition: dns/message.cc:382
isc::dns::Message::addQuestion
void addQuestion(QuestionPtr question)
Add a (pointer like object of) Question to the message.
Definition: dns/message.cc:585
isc::dns::SectionIterator::SectionIterator
SectionIterator()
Definition: message.h:93