message.cc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  1. // Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <stdint.h>
  15. #include <algorithm>
  16. #include <cassert>
  17. #include <string>
  18. #include <sstream>
  19. #include <vector>
  20. #include <boost/foreach.hpp>
  21. #include <boost/lexical_cast.hpp>
  22. #include <boost/shared_ptr.hpp>
  23. #include <exceptions/exceptions.h>
  24. #include <util/buffer.h>
  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. using namespace std;
  40. using namespace boost;
  41. using namespace isc::dns::rdata;
  42. using namespace isc::util;
  43. namespace isc {
  44. namespace dns {
  45. namespace {
  46. // protocol constants
  47. const size_t HEADERLEN = 12;
  48. const unsigned int OPCODE_MASK = 0x7800;
  49. const unsigned int OPCODE_SHIFT = 11;
  50. const unsigned int RCODE_MASK = 0x000f;
  51. // This diagram shows the wire-format representation of the 2nd 16 bits of
  52. // the DNS header section, which contain all defined flag bits.
  53. //
  54. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  55. // |QR| Opcode |AA|TC|RD|RA| |AD|CD| RCODE |
  56. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  57. // 1 0 0 0| 0 1 1 1| 1 0 1 1| 0 0 0 0|
  58. // 0x8 0x7 0xb 0x0
  59. //
  60. // This mask covers all the flag bits, and those bits only.
  61. // Note: we reject a "flag" the is not covered by this mask in some of the
  62. // public methods. This means our current definition is not fully extendable;
  63. // applications cannot introduce a new flag bit temporarily without modifying
  64. // the source code.
  65. const unsigned int HEADERFLAG_MASK = 0x87b0;
  66. // This is a set of flag bits that should be preserved when building a reply
  67. // from a request.
  68. // Note: we assume the specific definition of HEADERFLAG_xx. We may change
  69. // the definition in future, in which case we need to adjust this definition,
  70. // too (see also the description about the Message::HeaderFlag type).
  71. const uint16_t MESSAGE_REPLYPRESERVE = (Message::HEADERFLAG_RD |
  72. Message::HEADERFLAG_CD);
  73. const char *sectiontext[] = {
  74. "QUESTION",
  75. "ANSWER",
  76. "AUTHORITY",
  77. "ADDITIONAL"
  78. };
  79. }
  80. class MessageImpl {
  81. public:
  82. MessageImpl(Message::Mode mode);
  83. // Open issues: should we rather have a header in wire-format
  84. // for efficiency?
  85. Message::Mode mode_;
  86. qid_t qid_;
  87. // We want to use NULL for [op,r]code_ to mean the code being not
  88. // correctly parsed or set. We store the real code object in
  89. // xxcode_placeholder_ and have xxcode_ refer to it when the object
  90. // is valid.
  91. const Rcode* rcode_;
  92. Rcode rcode_placeholder_;
  93. const Opcode* opcode_;
  94. Opcode opcode_placeholder_;
  95. uint16_t flags_; // wire-format representation of header flags.
  96. bool header_parsed_;
  97. static const unsigned int NUM_SECTIONS = 4; // TODO: revisit this design
  98. int counts_[NUM_SECTIONS]; // TODO: revisit this definition
  99. vector<QuestionPtr> questions_;
  100. vector<RRsetPtr> rrsets_[NUM_SECTIONS];
  101. ConstEDNSPtr edns_;
  102. // tsig/sig0: TODO
  103. // RRsetsSorter* sorter_; : TODO
  104. void init();
  105. void setOpcode(const Opcode& opcode);
  106. void setRcode(const Rcode& rcode);
  107. int parseQuestion(InputBuffer& buffer);
  108. int parseSection(const Message::Section section, InputBuffer& buffer);
  109. void toWire(AbstractMessageRenderer& renderer, TSIGContext* tsig_ctx);
  110. };
  111. MessageImpl::MessageImpl(Message::Mode mode) :
  112. mode_(mode),
  113. rcode_placeholder_(Rcode(0)), // as a placeholder the value doesn't matter
  114. opcode_placeholder_(Opcode(0)) // ditto
  115. {
  116. init();
  117. }
  118. void
  119. MessageImpl::init() {
  120. flags_ = 0;
  121. qid_ = 0;
  122. rcode_ = NULL;
  123. opcode_ = NULL;
  124. edns_ = EDNSPtr();
  125. for (int i = 0; i < NUM_SECTIONS; ++i) {
  126. counts_[i] = 0;
  127. }
  128. header_parsed_ = false;
  129. questions_.clear();
  130. rrsets_[Message::SECTION_ANSWER].clear();
  131. rrsets_[Message::SECTION_AUTHORITY].clear();
  132. rrsets_[Message::SECTION_ADDITIONAL].clear();
  133. }
  134. void
  135. MessageImpl::setOpcode(const Opcode& opcode) {
  136. opcode_placeholder_ = opcode;
  137. opcode_ = &opcode_placeholder_;
  138. }
  139. void
  140. MessageImpl::setRcode(const Rcode& rcode) {
  141. rcode_placeholder_ = rcode;
  142. rcode_ = &rcode_placeholder_;
  143. }
  144. namespace {
  145. template <typename T>
  146. struct RenderSection {
  147. RenderSection(AbstractMessageRenderer& renderer, const bool partial_ok) :
  148. counter_(0), renderer_(renderer), partial_ok_(partial_ok),
  149. truncated_(false)
  150. {}
  151. void operator()(const T& entry) {
  152. // If it's already truncated, ignore the rest of the section.
  153. if (truncated_) {
  154. return;
  155. }
  156. const size_t pos0 = renderer_.getLength();
  157. counter_ += entry->toWire(renderer_);
  158. if (renderer_.isTruncated()) {
  159. truncated_ = true;
  160. if (!partial_ok_) {
  161. // roll back to the end of the previous RRset.
  162. renderer_.trim(renderer_.getLength() - pos0);
  163. }
  164. }
  165. }
  166. unsigned int getTotalCount() { return (counter_); }
  167. unsigned int counter_;
  168. AbstractMessageRenderer& renderer_;
  169. const bool partial_ok_;
  170. bool truncated_;
  171. };
  172. }
  173. void
  174. MessageImpl::toWire(AbstractMessageRenderer& renderer, TSIGContext* tsig_ctx) {
  175. if (mode_ != Message::RENDER) {
  176. isc_throw(InvalidMessageOperation,
  177. "Message rendering attempted in non render mode");
  178. }
  179. if (rcode_ == NULL) {
  180. isc_throw(InvalidMessageOperation,
  181. "Message rendering attempted without Rcode set");
  182. }
  183. if (opcode_ == NULL) {
  184. isc_throw(InvalidMessageOperation,
  185. "Message rendering attempted without Opcode set");
  186. }
  187. // reserve room for the header
  188. renderer.skip(HEADERLEN);
  189. uint16_t qdcount =
  190. for_each(questions_.begin(), questions_.end(),
  191. RenderSection<QuestionPtr>(renderer, false)).getTotalCount();
  192. // TBD: sort RRsets in each section based on configuration policy.
  193. uint16_t ancount = 0;
  194. if (!renderer.isTruncated()) {
  195. ancount =
  196. for_each(rrsets_[Message::SECTION_ANSWER].begin(),
  197. rrsets_[Message::SECTION_ANSWER].end(),
  198. RenderSection<RRsetPtr>(renderer, true)).getTotalCount();
  199. }
  200. uint16_t nscount = 0;
  201. if (!renderer.isTruncated()) {
  202. nscount =
  203. for_each(rrsets_[Message::SECTION_AUTHORITY].begin(),
  204. rrsets_[Message::SECTION_AUTHORITY].end(),
  205. RenderSection<RRsetPtr>(renderer, true)).getTotalCount();
  206. }
  207. uint16_t arcount = 0;
  208. if (renderer.isTruncated()) {
  209. flags_ |= Message::HEADERFLAG_TC;
  210. } else {
  211. arcount =
  212. for_each(rrsets_[Message::SECTION_ADDITIONAL].begin(),
  213. rrsets_[Message::SECTION_ADDITIONAL].end(),
  214. RenderSection<RRsetPtr>(renderer, false)).getTotalCount();
  215. }
  216. // Add EDNS OPT RR if necessary. Basically, we add it only when EDNS
  217. // has been explicitly set. However, if the RCODE would require it and
  218. // no EDNS has been set we generate a temporary local EDNS and use it.
  219. if (!renderer.isTruncated()) {
  220. ConstEDNSPtr local_edns = edns_;
  221. if (!local_edns && rcode_->getExtendedCode() != 0) {
  222. local_edns = ConstEDNSPtr(new EDNS());
  223. }
  224. if (local_edns) {
  225. arcount += local_edns->toWire(renderer, rcode_->getExtendedCode());
  226. }
  227. }
  228. // Adjust the counter buffer.
  229. // XXX: these may not be equal to the number of corresponding entries
  230. // in rrsets_[] or questions_ if truncation occurred or an EDNS OPT RR
  231. // was inserted. This is not good, and we should revisit the entire
  232. // design.
  233. counts_[Message::SECTION_QUESTION] = qdcount;
  234. counts_[Message::SECTION_ANSWER] = ancount;
  235. counts_[Message::SECTION_AUTHORITY] = nscount;
  236. counts_[Message::SECTION_ADDITIONAL] = arcount;
  237. // fill in the header
  238. size_t header_pos = 0;
  239. renderer.writeUint16At(qid_, header_pos);
  240. header_pos += sizeof(uint16_t);
  241. uint16_t codes_and_flags =
  242. (opcode_->getCode() << OPCODE_SHIFT) & OPCODE_MASK;
  243. codes_and_flags |= (rcode_->getCode() & RCODE_MASK);
  244. codes_and_flags |= (flags_ & HEADERFLAG_MASK);
  245. renderer.writeUint16At(codes_and_flags, header_pos);
  246. header_pos += sizeof(uint16_t);
  247. // XXX: should avoid repeated pattern (TODO)
  248. renderer.writeUint16At(qdcount, header_pos);
  249. header_pos += sizeof(uint16_t);
  250. renderer.writeUint16At(ancount, header_pos);
  251. header_pos += sizeof(uint16_t);
  252. renderer.writeUint16At(nscount, header_pos);
  253. header_pos += sizeof(uint16_t);
  254. renderer.writeUint16At(arcount, header_pos);
  255. // Add TSIG, if necessary, at the end of the message.
  256. // TBD: truncate case consideration
  257. if (tsig_ctx != NULL) {
  258. tsig_ctx->sign(qid_, renderer.getData(),
  259. renderer.getLength())->toWire(renderer);
  260. // update the ARCOUNT for the TSIG RR
  261. ++arcount;
  262. assert(arcount != 0); // this should never happen for a sane message
  263. renderer.writeUint16At(arcount, header_pos);
  264. }
  265. }
  266. Message::Message(Mode mode) :
  267. impl_(new MessageImpl(mode))
  268. {}
  269. Message::~Message() {
  270. delete impl_;
  271. }
  272. bool
  273. Message::getHeaderFlag(const HeaderFlag flag) const {
  274. if (flag == 0 || (flag & ~HEADERFLAG_MASK) != 0) {
  275. isc_throw(InvalidParameter,
  276. "Message::getHeaderFlag:: Invalid flag is specified: " <<
  277. flag);
  278. }
  279. return ((impl_->flags_ & flag) != 0);
  280. }
  281. void
  282. Message::setHeaderFlag(const HeaderFlag flag, const bool on) {
  283. if (impl_->mode_ != Message::RENDER) {
  284. isc_throw(InvalidMessageOperation,
  285. "setHeaderFlag performed in non-render mode");
  286. }
  287. if (flag == 0 || (flag & ~HEADERFLAG_MASK) != 0) {
  288. isc_throw(InvalidParameter,
  289. "Message::getHeaderFlag:: Invalid flag is specified: " <<
  290. flag);
  291. }
  292. if (on) {
  293. impl_->flags_ |= flag;
  294. } else {
  295. impl_->flags_ &= ~flag;
  296. }
  297. }
  298. qid_t
  299. Message::getQid() const {
  300. return (impl_->qid_);
  301. }
  302. void
  303. Message::setQid(qid_t qid) {
  304. if (impl_->mode_ != Message::RENDER) {
  305. isc_throw(InvalidMessageOperation,
  306. "setQid performed in non-render mode");
  307. }
  308. impl_->qid_ = qid;
  309. }
  310. const Rcode&
  311. Message::getRcode() const {
  312. if (impl_->rcode_ == NULL) {
  313. isc_throw(InvalidMessageOperation, "getRcode attempted before set");
  314. }
  315. return (*impl_->rcode_);
  316. }
  317. void
  318. Message::setRcode(const Rcode& rcode) {
  319. if (impl_->mode_ != Message::RENDER) {
  320. isc_throw(InvalidMessageOperation,
  321. "setRcode performed in non-render mode");
  322. }
  323. impl_->setRcode(rcode);
  324. }
  325. const Opcode&
  326. Message::getOpcode() const {
  327. if (impl_->opcode_ == NULL) {
  328. isc_throw(InvalidMessageOperation, "getOpcode attempted before set");
  329. }
  330. return (*impl_->opcode_);
  331. }
  332. void
  333. Message::setOpcode(const Opcode& opcode) {
  334. if (impl_->mode_ != Message::RENDER) {
  335. isc_throw(InvalidMessageOperation,
  336. "setOpcode performed in non-render mode");
  337. }
  338. impl_->setOpcode(opcode);
  339. }
  340. ConstEDNSPtr
  341. Message::getEDNS() const {
  342. return (impl_->edns_);
  343. }
  344. void
  345. Message::setEDNS(ConstEDNSPtr edns) {
  346. if (impl_->mode_ != Message::RENDER) {
  347. isc_throw(InvalidMessageOperation,
  348. "setEDNS performed in non-render mode");
  349. }
  350. impl_->edns_ = edns;
  351. }
  352. unsigned int
  353. Message::getRRCount(const Section section) const {
  354. if (section >= MessageImpl::NUM_SECTIONS) {
  355. isc_throw(OutOfRange, "Invalid message section: " << section);
  356. }
  357. return (impl_->counts_[section]);
  358. }
  359. void
  360. Message::addRRset(const Section section, RRsetPtr rrset, const bool sign) {
  361. if (impl_->mode_ != Message::RENDER) {
  362. isc_throw(InvalidMessageOperation,
  363. "addRRset performed in non-render mode");
  364. }
  365. if (section >= MessageImpl::NUM_SECTIONS) {
  366. isc_throw(OutOfRange, "Invalid message section: " << section);
  367. }
  368. impl_->rrsets_[section].push_back(rrset);
  369. impl_->counts_[section] += rrset->getRdataCount();
  370. RRsetPtr sp = rrset->getRRsig();
  371. if (sign && sp != NULL) {
  372. impl_->rrsets_[section].push_back(sp);
  373. impl_->counts_[section] += sp->getRdataCount();
  374. }
  375. }
  376. bool
  377. Message::hasRRset(const Section section, const Name& name,
  378. const RRClass& rrclass, const RRType& rrtype)
  379. {
  380. if (section >= MessageImpl::NUM_SECTIONS) {
  381. isc_throw(OutOfRange, "Invalid message section: " << section);
  382. }
  383. BOOST_FOREACH(ConstRRsetPtr r, impl_->rrsets_[section]) {
  384. if (r->getClass() == rrclass &&
  385. r->getType() == rrtype &&
  386. r->getName() == name) {
  387. return (true);
  388. }
  389. }
  390. return (false);
  391. }
  392. bool
  393. Message::hasRRset(const Section section, const RRsetPtr& rrset) {
  394. return (hasRRset(section, rrset->getName(), rrset->getClass(), rrset->getType()));
  395. }
  396. bool
  397. Message::removeRRset(const Section section, RRsetIterator& iterator) {
  398. if (section >= MessageImpl::NUM_SECTIONS) {
  399. isc_throw(OutOfRange, "Invalid message section: " << section);
  400. }
  401. bool removed = false;
  402. for (vector<RRsetPtr>::iterator i = impl_->rrsets_[section].begin();
  403. i != impl_->rrsets_[section].end(); ++i) {
  404. if (((*i)->getName() == (*iterator)->getName()) &&
  405. ((*i)->getClass() == (*iterator)->getClass()) &&
  406. ((*i)->getType() == (*iterator)->getType())) {
  407. // Found the matching RRset so remove it & ignore rest
  408. impl_->counts_[section] -= (*iterator)->getRdataCount();
  409. impl_->rrsets_[section].erase(i);
  410. removed = true;
  411. break;
  412. }
  413. }
  414. return (removed);
  415. }
  416. void
  417. Message::clearSection(const Section section) {
  418. if (section >= MessageImpl::NUM_SECTIONS) {
  419. isc_throw(OutOfRange, "Invalid message section: " << section);
  420. }
  421. impl_->rrsets_[section].clear();
  422. impl_->counts_[section] = 0;
  423. }
  424. void
  425. Message::addQuestion(const QuestionPtr question) {
  426. if (impl_->mode_ != Message::RENDER) {
  427. isc_throw(InvalidMessageOperation,
  428. "addQuestion performed in non-render mode");
  429. }
  430. impl_->questions_.push_back(question);
  431. ++impl_->counts_[SECTION_QUESTION];
  432. }
  433. void
  434. Message::addQuestion(const Question& question) {
  435. addQuestion(QuestionPtr(new Question(question)));
  436. }
  437. void
  438. Message::toWire(AbstractMessageRenderer& renderer) {
  439. impl_->toWire(renderer, NULL);
  440. }
  441. void
  442. Message::toWire(AbstractMessageRenderer& renderer, TSIGContext& tsig_ctx) {
  443. impl_->toWire(renderer, &tsig_ctx);
  444. }
  445. void
  446. Message::parseHeader(InputBuffer& buffer) {
  447. if (impl_->mode_ != Message::PARSE) {
  448. isc_throw(InvalidMessageOperation,
  449. "Message parse attempted in non parse mode");
  450. }
  451. if ((buffer.getLength() - buffer.getPosition()) < HEADERLEN) {
  452. isc_throw(MessageTooShort, "Malformed DNS message (short length): "
  453. << buffer.getLength() - buffer.getPosition());
  454. }
  455. impl_->qid_ = buffer.readUint16();
  456. const uint16_t codes_and_flags = buffer.readUint16();
  457. impl_->setOpcode(Opcode((codes_and_flags & OPCODE_MASK) >> OPCODE_SHIFT));
  458. impl_->setRcode(Rcode(codes_and_flags & RCODE_MASK));
  459. impl_->flags_ = (codes_and_flags & HEADERFLAG_MASK);
  460. impl_->counts_[SECTION_QUESTION] = buffer.readUint16();
  461. impl_->counts_[SECTION_ANSWER] = buffer.readUint16();
  462. impl_->counts_[SECTION_AUTHORITY] = buffer.readUint16();
  463. impl_->counts_[SECTION_ADDITIONAL] = buffer.readUint16();
  464. impl_->header_parsed_ = true;
  465. }
  466. void
  467. Message::fromWire(InputBuffer& buffer) {
  468. if (impl_->mode_ != Message::PARSE) {
  469. isc_throw(InvalidMessageOperation,
  470. "Message parse attempted in non parse mode");
  471. }
  472. if (!impl_->header_parsed_) {
  473. parseHeader(buffer);
  474. }
  475. impl_->counts_[SECTION_QUESTION] = impl_->parseQuestion(buffer);
  476. impl_->counts_[SECTION_ANSWER] =
  477. impl_->parseSection(SECTION_ANSWER, buffer);
  478. impl_->counts_[SECTION_AUTHORITY] =
  479. impl_->parseSection(SECTION_AUTHORITY, buffer);
  480. impl_->counts_[SECTION_ADDITIONAL] =
  481. impl_->parseSection(SECTION_ADDITIONAL, buffer);
  482. }
  483. int
  484. MessageImpl::parseQuestion(InputBuffer& buffer) {
  485. unsigned int added = 0;
  486. for (unsigned int count = 0;
  487. count < counts_[Message::SECTION_QUESTION];
  488. ++count) {
  489. const Name name(buffer);
  490. if ((buffer.getLength() - buffer.getPosition()) <
  491. 2 * sizeof(uint16_t)) {
  492. isc_throw(DNSMessageFORMERR, "Question section too short: " <<
  493. (buffer.getLength() - buffer.getPosition()) << " bytes");
  494. }
  495. const RRType rrtype(buffer.readUint16());
  496. const RRClass rrclass(buffer.readUint16());
  497. // XXX: need a duplicate check. We might also want to have an
  498. // optimized algorithm that requires the question section contain
  499. // exactly one RR.
  500. questions_.push_back(QuestionPtr(new Question(name, rrclass, rrtype)));
  501. ++added;
  502. }
  503. return (added);
  504. }
  505. namespace {
  506. struct MatchRR : public unary_function<RRsetPtr, bool> {
  507. MatchRR(const Name& name, const RRType& rrtype, const RRClass& rrclass) :
  508. name_(name), rrtype_(rrtype), rrclass_(rrclass) {}
  509. bool operator()(const RRsetPtr& rrset) const {
  510. return (rrset->getType() == rrtype_ &&
  511. rrset->getClass() == rrclass_ &&
  512. rrset->getName() == name_);
  513. }
  514. const Name& name_;
  515. const RRType& rrtype_;
  516. const RRClass& rrclass_;
  517. };
  518. }
  519. // Note about design decision:
  520. // we need some type specific processing here, including EDNS and TSIG.
  521. // how much we should generalize/hardcode the special logic is subject
  522. // to discussion. In terms of modularity it would be ideal to introduce
  523. // an abstract class (say "MessageAttribute") and let other such
  524. // concrete notions as EDNS or TSIG inherit from it. Then we would
  525. // just do:
  526. // message->addAttribute(rrtype, rrclass, buffer);
  527. // to create and attach type-specific concrete object to the message.
  528. //
  529. // A major downside of this approach is, as usual, complexity due to
  530. // indirection and performance penalty. Also, it may not be so easy
  531. // to separate the processing logic because in many cases we'll need
  532. // parse context for which the message class is responsible (e.g.
  533. // to check the EDNS OPT RR only appears in the additional section,
  534. // and appears only once).
  535. //
  536. // Another point to consider is that we may not need so many special
  537. // types other than EDNS and TSIG (and when and if we implement it,
  538. // SIG(0)); newer optional attributes of the message would more likely
  539. // be standardized as new flags or options of EDNS. If that's the case,
  540. // introducing an abstract class with all the overhead and complexity
  541. // may not make much sense.
  542. //
  543. // Conclusion: don't over-generalize type-specific logic for now.
  544. // introduce separate concrete classes, and move context-independent
  545. // logic to that class; processing logic dependent on parse context
  546. // is hardcoded here.
  547. int
  548. MessageImpl::parseSection(const Message::Section section,
  549. InputBuffer& buffer)
  550. {
  551. assert(section < MessageImpl::NUM_SECTIONS);
  552. unsigned int added = 0;
  553. for (unsigned int count = 0; count < counts_[section]; ++count) {
  554. const Name name(buffer);
  555. // buffer must store at least RR TYPE, RR CLASS, TTL, and RDLEN.
  556. if ((buffer.getLength() - buffer.getPosition()) <
  557. 3 * sizeof(uint16_t) + sizeof(uint32_t)) {
  558. isc_throw(DNSMessageFORMERR, sectiontext[section] <<
  559. " section too short: " <<
  560. (buffer.getLength() - buffer.getPosition()) << " bytes");
  561. }
  562. const RRType rrtype(buffer.readUint16());
  563. const RRClass rrclass(buffer.readUint16());
  564. const RRTTL ttl(buffer.readUint32());
  565. const size_t rdlen = buffer.readUint16();
  566. ConstRdataPtr rdata = createRdata(rrtype, rrclass, buffer, rdlen);
  567. if (rrtype == RRType::OPT()) {
  568. if (section != Message::SECTION_ADDITIONAL) {
  569. isc_throw(DNSMessageFORMERR,
  570. "EDNS OPT RR found in an invalid section");
  571. }
  572. if (edns_) {
  573. isc_throw(DNSMessageFORMERR, "multiple EDNS OPT RR found");
  574. }
  575. uint8_t extended_rcode;
  576. edns_ = ConstEDNSPtr(createEDNSFromRR(name, rrclass, rrtype, ttl,
  577. *rdata, extended_rcode));
  578. setRcode(Rcode(rcode_->getCode(), extended_rcode));
  579. continue;
  580. } else {
  581. vector<RRsetPtr>::iterator it =
  582. find_if(rrsets_[section].begin(), rrsets_[section].end(),
  583. MatchRR(name, rrtype, rrclass));
  584. if (it != rrsets_[section].end()) {
  585. (*it)->setTTL(min((*it)->getTTL(), ttl));
  586. (*it)->addRdata(rdata);
  587. } else {
  588. RRsetPtr rrset =
  589. RRsetPtr(new RRset(name, rrclass, rrtype, ttl));
  590. rrset->addRdata(rdata);
  591. rrsets_[section].push_back(rrset);
  592. }
  593. ++added;
  594. }
  595. }
  596. return (added);
  597. }
  598. namespace {
  599. template <typename T>
  600. struct SectionFormatter {
  601. SectionFormatter(const Message::Section section, string& output) :
  602. section_(section), output_(output) {}
  603. void operator()(const T& entry) {
  604. if (section_ == Message::SECTION_QUESTION) {
  605. output_ += ";";
  606. }
  607. output_ += entry->toText();
  608. }
  609. const Message::Section section_;
  610. string& output_;
  611. };
  612. }
  613. string
  614. Message::toText() const {
  615. if (impl_->rcode_ == NULL) {
  616. isc_throw(InvalidMessageOperation,
  617. "Message::toText() attempted without Rcode set");
  618. }
  619. if (impl_->opcode_ == NULL) {
  620. isc_throw(InvalidMessageOperation,
  621. "Message::toText() attempted without Opcode set");
  622. }
  623. string s;
  624. s += ";; ->>HEADER<<- opcode: " + impl_->opcode_->toText();
  625. // for simplicity we don't consider extended rcode (unlike BIND9)
  626. s += ", status: " + impl_->rcode_->toText();
  627. s += ", id: " + boost::lexical_cast<string>(impl_->qid_);
  628. s += "\n;; flags: ";
  629. if (getHeaderFlag(HEADERFLAG_QR)) {
  630. s += "qr ";
  631. }
  632. if (getHeaderFlag(HEADERFLAG_AA)) {
  633. s += "aa ";
  634. }
  635. if (getHeaderFlag(HEADERFLAG_TC)) {
  636. s += "tc ";
  637. }
  638. if (getHeaderFlag(HEADERFLAG_RD)) {
  639. s += "rd ";
  640. }
  641. if (getHeaderFlag(HEADERFLAG_RA)) {
  642. s += "ra ";
  643. }
  644. if (getHeaderFlag(HEADERFLAG_AD)) {
  645. s += "ad ";
  646. }
  647. if (getHeaderFlag(HEADERFLAG_CD)) {
  648. s += "cd ";
  649. }
  650. // for simplicity, don't consider the update case for now
  651. s += "; QUESTION: " +
  652. lexical_cast<string>(impl_->counts_[SECTION_QUESTION]);
  653. s += ", ANSWER: " +
  654. lexical_cast<string>(impl_->counts_[SECTION_ANSWER]);
  655. s += ", AUTHORITY: " +
  656. lexical_cast<string>(impl_->counts_[SECTION_AUTHORITY]);
  657. unsigned int arcount = impl_->counts_[SECTION_ADDITIONAL];
  658. if (impl_->edns_ != NULL) {
  659. ++arcount;
  660. }
  661. s += ", ADDITIONAL: " + lexical_cast<string>(arcount) + "\n";
  662. if (impl_->edns_ != NULL) {
  663. s += "\n;; OPT PSEUDOSECTION:\n";
  664. s += impl_->edns_->toText();
  665. }
  666. if (!impl_->questions_.empty()) {
  667. s += "\n;; " +
  668. string(sectiontext[SECTION_QUESTION]) + " SECTION:\n";
  669. for_each(impl_->questions_.begin(), impl_->questions_.end(),
  670. SectionFormatter<QuestionPtr>(SECTION_QUESTION, s));
  671. }
  672. if (!impl_->rrsets_[SECTION_ANSWER].empty()) {
  673. s += "\n;; " +
  674. string(sectiontext[SECTION_ANSWER]) + " SECTION:\n";
  675. for_each(impl_->rrsets_[SECTION_ANSWER].begin(),
  676. impl_->rrsets_[SECTION_ANSWER].end(),
  677. SectionFormatter<RRsetPtr>(SECTION_ANSWER, s));
  678. }
  679. if (!impl_->rrsets_[SECTION_AUTHORITY].empty()) {
  680. s += "\n;; " +
  681. string(sectiontext[SECTION_AUTHORITY]) + " SECTION:\n";
  682. for_each(impl_->rrsets_[SECTION_AUTHORITY].begin(),
  683. impl_->rrsets_[SECTION_AUTHORITY].end(),
  684. SectionFormatter<RRsetPtr>(SECTION_AUTHORITY, s));
  685. }
  686. if (!impl_->rrsets_[SECTION_ADDITIONAL].empty()) {
  687. s += "\n;; " +
  688. string(sectiontext[SECTION_ADDITIONAL]) +
  689. " SECTION:\n";
  690. for_each(impl_->rrsets_[SECTION_ADDITIONAL].begin(),
  691. impl_->rrsets_[SECTION_ADDITIONAL].end(),
  692. SectionFormatter<RRsetPtr>(SECTION_ADDITIONAL, s));
  693. }
  694. return (s);
  695. }
  696. void
  697. Message::clear(Mode mode) {
  698. impl_->init();
  699. impl_->mode_ = mode;
  700. }
  701. void
  702. Message::appendSection(const Section section, const Message& source) {
  703. if (section >= MessageImpl::NUM_SECTIONS) {
  704. isc_throw(OutOfRange, "Invalid message section: " << section);
  705. }
  706. if (section == SECTION_QUESTION) {
  707. for (QuestionIterator qi = source.beginQuestion();
  708. qi != source.endQuestion();
  709. ++qi) {
  710. addQuestion(*qi);
  711. }
  712. } else {
  713. for (RRsetIterator rrsi = source.beginSection(section);
  714. rrsi != source.endSection(section);
  715. ++rrsi) {
  716. addRRset(section, *rrsi);
  717. }
  718. }
  719. }
  720. void
  721. Message::makeResponse() {
  722. if (impl_->mode_ != Message::PARSE) {
  723. isc_throw(InvalidMessageOperation,
  724. "makeResponse() is performed in non-parse mode");
  725. }
  726. impl_->mode_ = Message::RENDER;
  727. impl_->edns_ = EDNSPtr();
  728. impl_->flags_ &= MESSAGE_REPLYPRESERVE;
  729. setHeaderFlag(HEADERFLAG_QR, true);
  730. impl_->rrsets_[SECTION_ANSWER].clear();
  731. impl_->counts_[SECTION_ANSWER] = 0;
  732. impl_->rrsets_[SECTION_AUTHORITY].clear();
  733. impl_->counts_[SECTION_AUTHORITY] = 0;
  734. impl_->rrsets_[SECTION_ADDITIONAL].clear();
  735. impl_->counts_[SECTION_ADDITIONAL] = 0;
  736. }
  737. ///
  738. /// Template version of Section Iterator
  739. ///
  740. template <typename T>
  741. struct SectionIteratorImpl {
  742. SectionIteratorImpl(const typename vector<T>::const_iterator& it) :
  743. it_(it) {}
  744. typename vector<T>::const_iterator it_;
  745. };
  746. template <typename T>
  747. SectionIterator<T>::SectionIterator(const SectionIteratorImpl<T>& impl) {
  748. impl_ = new SectionIteratorImpl<T>(impl.it_);
  749. }
  750. template <typename T>
  751. SectionIterator<T>::~SectionIterator() {
  752. delete impl_;
  753. }
  754. template <typename T>
  755. SectionIterator<T>::SectionIterator(const SectionIterator<T>& source) :
  756. impl_(new SectionIteratorImpl<T>(source.impl_->it_))
  757. {}
  758. template <typename T>
  759. void
  760. SectionIterator<T>::operator=(const SectionIterator<T>& source) {
  761. if (impl_ == source.impl_) {
  762. return;
  763. }
  764. SectionIteratorImpl<T>* newimpl =
  765. new SectionIteratorImpl<T>(source.impl_->it_);
  766. delete impl_;
  767. impl_ = newimpl;
  768. }
  769. template <typename T>
  770. SectionIterator<T>&
  771. SectionIterator<T>::operator++() {
  772. ++(impl_->it_);
  773. return (*this);
  774. }
  775. template <typename T>
  776. SectionIterator<T>
  777. SectionIterator<T>::operator++(int) {
  778. SectionIterator<T> tmp(*this);
  779. ++(*this);
  780. return (tmp);
  781. }
  782. template <typename T>
  783. const T&
  784. SectionIterator<T>::operator*() const {
  785. return (*(impl_->it_));
  786. }
  787. template <typename T>
  788. const T*
  789. SectionIterator<T>::operator->() const {
  790. return (&(operator*()));
  791. }
  792. template <typename T>
  793. bool
  794. SectionIterator<T>::operator==(const SectionIterator<T>& other) const {
  795. return (impl_->it_ == other.impl_->it_);
  796. }
  797. template <typename T>
  798. bool
  799. SectionIterator<T>::operator!=(const SectionIterator<T>& other) const {
  800. return (impl_->it_ != other.impl_->it_);
  801. }
  802. ///
  803. /// We need to explicitly instantiate these template classes because these
  804. /// are public classes but defined in this implementation file.
  805. ///
  806. template class SectionIterator<QuestionPtr>;
  807. template class SectionIterator<RRsetPtr>;
  808. namespace {
  809. typedef SectionIteratorImpl<QuestionPtr> QuestionIteratorImpl;
  810. typedef SectionIteratorImpl<RRsetPtr> RRsetIteratorImpl;
  811. }
  812. ///
  813. /// Question iterator
  814. ///
  815. const QuestionIterator
  816. Message::beginQuestion() const {
  817. return (QuestionIterator(QuestionIteratorImpl(impl_->questions_.begin())));
  818. }
  819. const QuestionIterator
  820. Message::endQuestion() const {
  821. return (QuestionIterator(QuestionIteratorImpl(impl_->questions_.end())));
  822. }
  823. ///
  824. /// RRsets iterators
  825. ///
  826. const SectionIterator<RRsetPtr>
  827. Message::beginSection(const Section section) const {
  828. if (section >= MessageImpl::NUM_SECTIONS) {
  829. isc_throw(OutOfRange, "Invalid message section: " << section);
  830. }
  831. if (section == SECTION_QUESTION) {
  832. isc_throw(InvalidMessageSection,
  833. "RRset iterator is requested for question");
  834. }
  835. return (RRsetIterator(RRsetIteratorImpl(impl_->rrsets_[section].begin())));
  836. }
  837. const SectionIterator<RRsetPtr>
  838. Message::endSection(const Section section) const {
  839. if (section >= MessageImpl::NUM_SECTIONS) {
  840. isc_throw(OutOfRange, "Invalid message section: " << section);
  841. }
  842. if (section == SECTION_QUESTION) {
  843. isc_throw(InvalidMessageSection,
  844. "RRset iterator is requested for question");
  845. }
  846. return (RRsetIterator(RRsetIteratorImpl(impl_->rrsets_[section].end())));
  847. }
  848. ostream&
  849. operator<<(ostream& os, const Message& message) {
  850. return (os << message.toText());
  851. }
  852. } // end of namespace dns
  853. } // end of namespace isc