message.cc 27 KB

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