message.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947
  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/lexical_cast.hpp>
  21. #include <boost/shared_ptr.hpp>
  22. #include <exceptions/exceptions.h>
  23. #include "buffer.h"
  24. #include "message.h"
  25. #include "messagerenderer.h"
  26. #include "name.h"
  27. #include "question.h"
  28. #include "rdataclass.h"
  29. #include "rrclass.h"
  30. #include "rrtype.h"
  31. #include "rrttl.h"
  32. #include "rrset.h"
  33. using namespace std;
  34. using namespace boost;
  35. using namespace isc::dns;
  36. using namespace isc::dns::rdata;
  37. namespace isc {
  38. namespace dns {
  39. namespace {
  40. typedef uint16_t flags_t;
  41. // protocol constants
  42. static const size_t HEADERLEN = 12;
  43. static const flags_t FLAG_QR = 0x8000;
  44. static const flags_t FLAG_AA = 0x0400;
  45. static const flags_t FLAG_TC = 0x0200;
  46. static const flags_t FLAG_RD = 0x0100;
  47. static const flags_t FLAG_RA = 0x0080;
  48. static const flags_t FLAG_AD = 0x0020;
  49. static const flags_t FLAG_CD = 0x0010;
  50. //
  51. // EDNS related constants
  52. //
  53. static const flags_t EXTFLAG_MASK = 0xffff;
  54. static const flags_t EXTFLAG_DO = 0x8000;
  55. static const uint32_t EXTRCODE_MASK = 0xff000000;
  56. static const uint32_t EDNSVERSION_MASK = 0x00ff0000;
  57. static const unsigned int OPCODE_MASK = 0x7800;
  58. static const unsigned int OPCODE_SHIFT = 11;
  59. static const unsigned int RCODE_MASK = 0x000f;
  60. static const unsigned int FLAG_MASK = 0x8ff0;
  61. static const unsigned int MESSAGE_REPLYPRESERVE = (FLAG_RD | FLAG_CD);
  62. static const Rcode rcodes[] = {
  63. Rcode::NOERROR(),
  64. Rcode::FORMERR(),
  65. Rcode::SERVFAIL(),
  66. Rcode::NXDOMAIN(),
  67. Rcode::NOTIMP(),
  68. Rcode::REFUSED(),
  69. Rcode::YXDOMAIN(),
  70. Rcode::YXRRSET(),
  71. Rcode::NXRRSET(),
  72. Rcode::NOTAUTH(),
  73. Rcode::NOTZONE(),
  74. Rcode::RESERVED11(),
  75. Rcode::RESERVED12(),
  76. Rcode::RESERVED13(),
  77. Rcode::RESERVED14(),
  78. Rcode::RESERVED15(),
  79. Rcode::BADVERS()
  80. };
  81. static const char *rcodetext[] = {
  82. "NOERROR",
  83. "FORMERR",
  84. "SERVFAIL",
  85. "NXDOMAIN",
  86. "NOTIMP",
  87. "REFUSED",
  88. "YXDOMAIN",
  89. "YXRRSET",
  90. "NXRRSET",
  91. "NOTAUTH",
  92. "NOTZONE",
  93. "RESERVED11",
  94. "RESERVED12",
  95. "RESERVED13",
  96. "RESERVED14",
  97. "RESERVED15",
  98. "BADVERS"
  99. };
  100. static const Opcode* opcodes[] = {
  101. &Opcode::QUERY(),
  102. &Opcode::IQUERY(),
  103. &Opcode::STATUS(),
  104. &Opcode::RESERVED3(),
  105. &Opcode::NOTIFY(),
  106. &Opcode::UPDATE(),
  107. &Opcode::RESERVED6(),
  108. &Opcode::RESERVED7(),
  109. &Opcode::RESERVED8(),
  110. &Opcode::RESERVED9(),
  111. &Opcode::RESERVED10(),
  112. &Opcode::RESERVED11(),
  113. &Opcode::RESERVED12(),
  114. &Opcode::RESERVED13(),
  115. &Opcode::RESERVED14(),
  116. &Opcode::RESERVED15()
  117. };
  118. static const char *opcodetext[] = {
  119. "QUERY",
  120. "IQUERY",
  121. "STATUS",
  122. "RESERVED3",
  123. "NOTIFY",
  124. "UPDATE",
  125. "RESERVED6",
  126. "RESERVED7",
  127. "RESERVED8",
  128. "RESERVED9",
  129. "RESERVED10",
  130. "RESERVED11",
  131. "RESERVED12",
  132. "RESERVED13",
  133. "RESERVED14",
  134. "RESERVED15"
  135. };
  136. }
  137. string
  138. Opcode::toText() const
  139. {
  140. return (opcodetext[code_]);
  141. }
  142. Rcode::Rcode(uint16_t code) : code_(code)
  143. {
  144. if (code_ > MAX_RCODE) {
  145. isc_throw(OutOfRange, "Rcode is too large to construct");
  146. }
  147. }
  148. string
  149. Rcode::toText() const
  150. {
  151. if (code_ < sizeof(rcodetext) / sizeof (const char *)) {
  152. return (rcodetext[code_]);
  153. }
  154. ostringstream oss;
  155. oss << code_;
  156. return (oss.str());
  157. }
  158. namespace {
  159. inline unsigned int
  160. sectionCodeToId(const Section& section)
  161. {
  162. unsigned int code = section.getCode();
  163. assert(code > 0);
  164. return (section.getCode() - 1);
  165. }
  166. }
  167. class MessageImpl {
  168. public:
  169. MessageImpl(Message::Mode mode);
  170. // Open issues: should we rather have a header in wire-format
  171. // for efficiency?
  172. Message::Mode mode_;
  173. qid_t qid_;
  174. Rcode rcode_;
  175. const Opcode* opcode_;
  176. flags_t flags_;
  177. bool dnssec_ok_;
  178. static const unsigned int SECTION_MAX = 4; // TODO: revisit this design
  179. int counts_[SECTION_MAX]; // TODO: revisit this definition
  180. vector<QuestionPtr> questions_;
  181. vector<RRsetPtr> rrsets_[SECTION_MAX];
  182. RRsetPtr remote_edns_;
  183. uint16_t remote_udpsize_;
  184. RRsetPtr local_edns_;
  185. uint16_t udpsize_;
  186. #ifdef notyet
  187. // tsig/sig0: TODO
  188. RRsetsSorter* sorter_;
  189. #endif
  190. void init();
  191. int parseQuestion(Message& message, InputBuffer& buffer);
  192. int parseSection(Message& messge, const Section& section,
  193. InputBuffer& buffer);
  194. };
  195. MessageImpl::MessageImpl(Message::Mode mode) :
  196. mode_(mode), rcode_(Rcode::NOERROR())
  197. {
  198. init();
  199. }
  200. void
  201. MessageImpl::init()
  202. {
  203. flags_ = 0;
  204. qid_ = 0;
  205. rcode_ = Rcode::NOERROR(); // XXX
  206. opcode_ = NULL;
  207. dnssec_ok_ = false;
  208. remote_edns_ = RRsetPtr();
  209. remote_udpsize_ = Message::DEFAULT_MAX_UDPSIZE;
  210. local_edns_ = RRsetPtr();
  211. udpsize_ = Message::DEFAULT_MAX_UDPSIZE;
  212. for (int i = 0; i < SECTION_MAX; i++) {
  213. counts_[i] = 0;
  214. }
  215. questions_.clear();
  216. rrsets_[sectionCodeToId(Section::ANSWER())].clear();
  217. rrsets_[sectionCodeToId(Section::AUTHORITY())].clear();
  218. rrsets_[sectionCodeToId(Section::ADDITIONAL())].clear();
  219. }
  220. Message::Message(Mode mode) :
  221. impl_(new MessageImpl(mode))
  222. {
  223. }
  224. Message::~Message()
  225. {
  226. delete impl_;
  227. }
  228. bool
  229. Message::getHeaderFlag(const MessageFlag& flag) const
  230. {
  231. return ((impl_->flags_ & flag.getBit()) != 0);
  232. }
  233. void
  234. Message::setHeaderFlag(const MessageFlag& flag)
  235. {
  236. impl_->flags_ |= flag.getBit();
  237. }
  238. void
  239. Message::clearHeaderFlag(const MessageFlag& flag)
  240. {
  241. impl_->flags_ &= ~flag.getBit();
  242. }
  243. bool
  244. Message::isDNSSECSupported() const
  245. {
  246. return (impl_->dnssec_ok_);
  247. }
  248. void
  249. Message::setDNSSECSupported(bool on)
  250. {
  251. if (impl_->mode_ != Message::RENDER) {
  252. isc_throw(InvalidMessageOperation,
  253. "setDNSSECSupported performed in non-render mode");
  254. }
  255. impl_->dnssec_ok_ = on;
  256. }
  257. uint16_t
  258. Message::getUDPSize() const
  259. {
  260. return (impl_->udpsize_);
  261. }
  262. void
  263. Message::setUDPSize(uint16_t size)
  264. {
  265. if (impl_->mode_ != Message::RENDER) {
  266. isc_throw(InvalidMessageOperation,
  267. "setUDPSize performed in non-render mode");
  268. }
  269. if (size < DEFAULT_MAX_UDPSIZE) {
  270. isc_throw(InvalidMessageUDPSize,
  271. "Specified UDP message size is too small");
  272. }
  273. impl_->udpsize_ = size;
  274. }
  275. qid_t
  276. Message::getQid() const
  277. {
  278. return (impl_->qid_);
  279. }
  280. void
  281. Message::setQid(qid_t qid)
  282. {
  283. impl_->qid_ = qid;
  284. }
  285. const Rcode&
  286. Message::getRcode() const
  287. {
  288. return (impl_->rcode_);
  289. }
  290. void
  291. Message::setRcode(const Rcode& rcode)
  292. {
  293. impl_->rcode_ = rcode;
  294. }
  295. const Opcode&
  296. Message::getOpcode() const
  297. {
  298. return (*impl_->opcode_);
  299. }
  300. void
  301. Message::setOpcode(const Opcode& opcode)
  302. {
  303. impl_->opcode_ = &opcode;
  304. }
  305. unsigned int
  306. Message::getRRCount(const Section& section) const
  307. {
  308. return (impl_->counts_[section.getCode()]);
  309. }
  310. void
  311. Message::addRRset(const Section& section, RRsetPtr rrset, bool sign)
  312. {
  313. // Note: should check duplicate (TBD)
  314. impl_->rrsets_[sectionCodeToId(section)].push_back(rrset);
  315. impl_->counts_[section.getCode()] += rrset->getRdataCount();
  316. RRsetPtr sp = rrset->getRRsig();
  317. if (sign && sp) {
  318. impl_->rrsets_[sectionCodeToId(section)].push_back(sp);
  319. impl_->counts_[section.getCode()] += sp->getRdataCount();
  320. }
  321. }
  322. void
  323. Message::addQuestion(const QuestionPtr question)
  324. {
  325. impl_->questions_.push_back(question);
  326. impl_->counts_[Section::QUESTION().getCode()]++;
  327. }
  328. void
  329. Message::addQuestion(const Question& question)
  330. {
  331. addQuestion(QuestionPtr(new Question(question)));
  332. }
  333. namespace {
  334. template <typename T>
  335. struct RenderSection
  336. {
  337. RenderSection(MessageRenderer& renderer) :
  338. counter_(0), renderer_(renderer) {}
  339. void operator()(const T& entry)
  340. {
  341. // TBD: if truncation is necessary, do something special.
  342. // throw an exception, set an internal flag, etc.
  343. counter_ += entry->toWire(renderer_);
  344. }
  345. unsigned int getTotalCount() { return (counter_); }
  346. unsigned int counter_;
  347. MessageRenderer& renderer_;
  348. };
  349. }
  350. namespace {
  351. bool
  352. addEDNS(MessageImpl* mimpl, MessageRenderer& renderer)
  353. {
  354. bool is_query = ((mimpl->flags_ & MessageFlag::QR().getBit()) == 0);
  355. // If this is a reply and the request didn't have EDNS, we shouldn't add it.
  356. if (mimpl->remote_edns_ == NULL && !is_query) {
  357. return (false);
  358. }
  359. // For queries, we add EDNS only when necessary:
  360. // Local UDP size is not the default value, or
  361. // DNSSEC DO bit is to be set, or
  362. // Extended Rcode is to be specified.
  363. if (is_query && mimpl->udpsize_ == Message::DEFAULT_MAX_UDPSIZE &&
  364. !mimpl->dnssec_ok_ &&
  365. mimpl->rcode_.getCode() < 0x10) {
  366. return (false);
  367. }
  368. // Render EDNS OPT RR
  369. uint32_t extrcode_flags = ((mimpl->rcode_.getCode() & 0xff0) << 24);
  370. if (mimpl->dnssec_ok_) {
  371. extrcode_flags |= 0x8000; // set DO bit
  372. }
  373. mimpl->local_edns_ = RRsetPtr(new RRset(Name::ROOT_NAME(),
  374. RRClass(mimpl->udpsize_),
  375. RRType::OPT(),
  376. RRTTL(extrcode_flags)));
  377. // We don't support any options in this simple implementation
  378. mimpl->local_edns_->addRdata(ConstRdataPtr(new generic::OPT()));
  379. mimpl->local_edns_->toWire(renderer);
  380. return (true);
  381. }
  382. }
  383. void
  384. Message::toWire(MessageRenderer& renderer)
  385. {
  386. uint16_t codes_and_flags;
  387. // reserve room for the header
  388. renderer.skip(HEADERLEN);
  389. uint16_t qdcount =
  390. for_each(impl_->questions_.begin(), impl_->questions_.end(),
  391. RenderSection<QuestionPtr>(renderer)).getTotalCount();
  392. // TBD: sort RRsets in each section based on configuration policy.
  393. uint16_t ancount =
  394. for_each(impl_->rrsets_[sectionCodeToId(Section::ANSWER())].begin(),
  395. impl_->rrsets_[sectionCodeToId(Section::ANSWER())].end(),
  396. RenderSection<RRsetPtr>(renderer)).getTotalCount();
  397. uint16_t nscount =
  398. for_each(impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].begin(),
  399. impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].end(),
  400. RenderSection<RRsetPtr>(renderer)).getTotalCount();
  401. uint16_t arcount =
  402. for_each(impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].begin(),
  403. impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].end(),
  404. RenderSection<RRsetPtr>(renderer)).getTotalCount();
  405. // Added EDNS OPT RR if necessary (we want to avoid hardcoding specialized
  406. // logic, see the parser case)
  407. if (addEDNS(this->impl_, renderer)) {
  408. ++arcount;
  409. }
  410. // TBD: EDNS, TSIG, etc.
  411. // fill in the header
  412. size_t header_pos = 0;
  413. renderer.writeUint16At(impl_->qid_, header_pos);
  414. header_pos += sizeof(uint16_t);
  415. codes_and_flags = (impl_->opcode_->getCode() << OPCODE_SHIFT) & OPCODE_MASK;
  416. codes_and_flags |= (impl_->rcode_.getCode() & RCODE_MASK);
  417. codes_and_flags |= (impl_->flags_ & FLAG_MASK);
  418. renderer.writeUint16At(codes_and_flags, header_pos);
  419. header_pos += sizeof(uint16_t);
  420. // XXX: should avoid repeated pattern (TODO)
  421. renderer.writeUint16At(qdcount, header_pos);
  422. header_pos += sizeof(uint16_t);
  423. renderer.writeUint16At(ancount, header_pos);
  424. header_pos += sizeof(uint16_t);
  425. renderer.writeUint16At(nscount, header_pos);
  426. header_pos += sizeof(uint16_t);
  427. renderer.writeUint16At(arcount, header_pos);
  428. header_pos += sizeof(uint16_t);
  429. }
  430. void
  431. Message::fromWire(InputBuffer& buffer)
  432. {
  433. if ((buffer.getLength() - buffer.getPosition()) < HEADERLEN) {
  434. isc_throw(MessageTooShort, "");
  435. }
  436. impl_->qid_ = buffer.readUint16();
  437. uint16_t codes_and_flags = buffer.readUint16();
  438. impl_->opcode_ = opcodes[((codes_and_flags & OPCODE_MASK) >> OPCODE_SHIFT)];
  439. impl_->rcode_ = rcodes[(codes_and_flags & RCODE_MASK)];
  440. impl_->flags_ = (codes_and_flags & FLAG_MASK);
  441. impl_->counts_[Section::QUESTION().getCode()] = buffer.readUint16();
  442. impl_->counts_[Section::ANSWER().getCode()] = buffer.readUint16();
  443. impl_->counts_[Section::AUTHORITY().getCode()] = buffer.readUint16();
  444. impl_->counts_[Section::ADDITIONAL().getCode()] = buffer.readUint16();
  445. impl_->counts_[Section::QUESTION().getCode()] =
  446. impl_->parseQuestion(*this, buffer);
  447. impl_->counts_[Section::ANSWER().getCode()] =
  448. impl_->parseSection(*this, Section::ANSWER(), buffer);
  449. impl_->counts_[Section::AUTHORITY().getCode()] =
  450. impl_->parseSection(*this, Section::AUTHORITY(), buffer);
  451. impl_->counts_[Section::ADDITIONAL().getCode()] =
  452. impl_->parseSection(*this, Section::ADDITIONAL(), buffer);
  453. }
  454. int
  455. MessageImpl::parseQuestion(Message& message, InputBuffer& buffer)
  456. {
  457. unsigned int added = 0;
  458. for (unsigned int count = 0;
  459. count < counts_[Section::QUESTION().getCode()];
  460. count++) {
  461. Name name(buffer);
  462. if ((buffer.getLength() - buffer.getPosition()) <
  463. 2 * sizeof(uint16_t)) {
  464. isc_throw(MessageTooShort, "");
  465. }
  466. RRType rrtype(buffer.readUint16());
  467. RRClass rrclass(buffer.readUint16());
  468. // XXX: need a duplicate check. We might also want to have an optimized
  469. // algorithm that requires the question section contain exactly one
  470. // RR.
  471. questions_.push_back(QuestionPtr(new Question(name, rrclass, rrtype)));
  472. ++added;
  473. }
  474. return (added);
  475. }
  476. namespace {
  477. struct MatchRR : public unary_function<RRsetPtr, bool> {
  478. MatchRR(const Name& name, const RRType& rrtype, const RRClass& rrclass) :
  479. name_(name), rrtype_(rrtype), rrclass_(rrclass) {}
  480. bool operator()(const RRsetPtr& rrset) const
  481. {
  482. return (rrset->getType() == rrtype_ &&
  483. rrset->getClass() == rrclass_ &&
  484. rrset->getName() == name_);
  485. }
  486. const Name& name_;
  487. const RRType& rrtype_;
  488. const RRClass& rrclass_;
  489. };
  490. }
  491. int
  492. MessageImpl::parseSection(Message& message, const Section& section,
  493. InputBuffer& buffer)
  494. {
  495. unsigned int added = 0;
  496. for (unsigned int count = 0; count < counts_[section.getCode()]; count++) {
  497. Name name(buffer);
  498. // buffer must store at least RR TYPE, RR CLASS, TTL, and RDLEN.
  499. if ((buffer.getLength() - buffer.getPosition()) <
  500. 3 * sizeof(uint16_t) + sizeof(uint32_t)) {
  501. isc_throw(MessageTooShort, "");
  502. }
  503. RRType rrtype(buffer.readUint16());
  504. RRClass rrclass(buffer.readUint16());
  505. RRTTL ttl(buffer.readUint32());
  506. size_t rdlen = buffer.readUint16();
  507. RdataPtr rdata = createRdata(rrtype, rrclass, buffer, rdlen);
  508. // XXX: we wanted to avoid hardcoding type-specific logic here,
  509. // but this would be the fastest way for a proof-of-concept
  510. // implementation. We'll revisit this part later.
  511. if (rrtype == RRType::OPT()) {
  512. if (section != Section::ADDITIONAL()) {
  513. isc_throw(DNSMessageFORMERR,
  514. "EDNS OPT RR found in an invalid section");
  515. }
  516. if (remote_edns_ != NULL) {
  517. isc_throw(DNSMessageFORMERR, "multiple EDNS OPT RR found");
  518. }
  519. if (((ttl.getValue() & EDNSVERSION_MASK) >> 16) >
  520. Message::EDNS_SUPPORTED_VERSION) {
  521. // XXX: we should probably not reject the message yet, because
  522. // it's better to let the requestor know the responder-side
  523. // highest version as indicated in Section 4.6 of RFC2671.
  524. // This is probably because why BIND 9 does the version check
  525. // in the client code.
  526. // This is a TODO item. Right now we simply reject it.
  527. isc_throw(DNSMessageBADVERS, "unsupported EDNS version");
  528. }
  529. if (name != Name::ROOT_NAME()) {
  530. isc_throw(DNSMessageFORMERR,
  531. "invalid owner name for EDNS OPT RR");
  532. }
  533. remote_edns_ = RRsetPtr(new RRset(name, rrclass, rrtype, ttl));
  534. remote_edns_->addRdata(rdata);
  535. dnssec_ok_ = (((ttl.getValue() & EXTFLAG_MASK) & EXTFLAG_DO) != 0);
  536. if (rrclass.getCode() > Message::DEFAULT_MAX_UDPSIZE) {
  537. udpsize_ = rrclass.getCode();
  538. }
  539. rcode_ = Rcode(((ttl.getValue() & EXTRCODE_MASK) >> 20) |
  540. rcode_.getCode());
  541. continue;
  542. }
  543. vector<RRsetPtr>::iterator it =
  544. find_if(rrsets_[sectionCodeToId(section)].begin(),
  545. rrsets_[sectionCodeToId(section)].end(),
  546. MatchRR(name, rrtype, rrclass));
  547. if (it != rrsets_[sectionCodeToId(section)].end()) {
  548. (*it)->setTTL(min((*it)->getTTL(), ttl));
  549. (*it)->addRdata(rdata);
  550. } else {
  551. RRsetPtr rrset = RRsetPtr(new RRset(name, rrclass, rrtype, ttl));
  552. rrset->addRdata(rdata);
  553. rrsets_[sectionCodeToId(section)].push_back(rrset);
  554. }
  555. ++added;
  556. }
  557. return (added);
  558. }
  559. namespace {
  560. static const char *sectiontext[] = {
  561. "QUESTION",
  562. "ANSWER",
  563. "AUTHORITY",
  564. "ADDITIONAL"
  565. };
  566. template <typename T>
  567. struct SectionFormatter
  568. {
  569. SectionFormatter(const Section& section, string& output) :
  570. section_(section), output_(output) {}
  571. void operator()(const T& entry)
  572. {
  573. if (section_ == Section::QUESTION()) {
  574. output_ += ";";
  575. }
  576. output_ += entry->toText();
  577. }
  578. const Section& section_;
  579. string& output_;
  580. };
  581. }
  582. string
  583. Message::toText() const
  584. {
  585. string s;
  586. s += ";; ->>HEADER<<- opcode: " + impl_->opcode_->toText();
  587. // for simplicity we don't consider extended rcode (unlike BIND9)
  588. s += ", status: " + impl_->rcode_.toText();
  589. s += ", id: " + boost::lexical_cast<string>(impl_->qid_);
  590. s += "\n;; flags: ";
  591. if (getHeaderFlag(MessageFlag::QR()))
  592. s += "qr ";
  593. if (getHeaderFlag(MessageFlag::AA()))
  594. s += "aa ";
  595. if (getHeaderFlag(MessageFlag::TC()))
  596. s += "tc ";
  597. if (getHeaderFlag(MessageFlag::RD()))
  598. s += "rd ";
  599. if (getHeaderFlag(MessageFlag::RA()))
  600. s += "ra ";
  601. if (getHeaderFlag(MessageFlag::AD()))
  602. s += "ad ";
  603. if (getHeaderFlag(MessageFlag::CD()))
  604. s += "cd ";
  605. // for simplicity, don't consider the update case for now
  606. s += "; QUESTION: " +
  607. lexical_cast<string>(impl_->counts_[Section::QUESTION().getCode()]);
  608. s += ", ANSWER: " +
  609. lexical_cast<string>(impl_->counts_[Section::ANSWER().getCode()]);
  610. s += ", AUTHORITY: " +
  611. lexical_cast<string>(impl_->counts_[Section::AUTHORITY().getCode()]);
  612. unsigned int arcount = impl_->counts_[Section::ADDITIONAL().getCode()];
  613. RRsetPtr edns_rrset;
  614. if (!getHeaderFlag(MessageFlag::QR()) && impl_->remote_edns_ != NULL) {
  615. edns_rrset = impl_->remote_edns_;
  616. ++arcount;
  617. } else if (getHeaderFlag(MessageFlag::QR()) && impl_->local_edns_ != NULL) {
  618. edns_rrset = impl_->local_edns_;
  619. ++arcount;
  620. }
  621. s += ", ADDITIONAL: " + lexical_cast<string>(arcount) + "\n";
  622. if (edns_rrset != NULL) {
  623. s += "\n;; OPT PSEUDOSECTION:\n";
  624. s += "; EDNS: version: ";
  625. s += lexical_cast<string>(
  626. (edns_rrset->getTTL().getValue() & 0x00ff0000) >> 16);
  627. s += ", flags:";
  628. if ((edns_rrset->getTTL().getValue() & 0x8000) != 0) {
  629. s += " do";
  630. }
  631. uint32_t mbz = edns_rrset->getTTL().getValue() & ~0x8000 & 0xffff;
  632. if (mbz != 0) {
  633. s += "; MBZ: " + lexical_cast<string>(mbz) + ", udp: ";
  634. } else {
  635. s += "; udp: " +
  636. lexical_cast<string>(edns_rrset->getClass().getCode());
  637. }
  638. s += "\n";
  639. }
  640. if (!impl_->questions_.empty()) {
  641. s += "\n;; " +
  642. string(sectiontext[Section::QUESTION().getCode()]) + " SECTION:\n";
  643. for_each(impl_->questions_.begin(), impl_->questions_.end(),
  644. SectionFormatter<QuestionPtr>(Section::QUESTION(), s));
  645. }
  646. if (!impl_->rrsets_[sectionCodeToId(Section::ANSWER())].empty()) {
  647. s += "\n;; " +
  648. string(sectiontext[Section::ANSWER().getCode()]) + " SECTION:\n";
  649. for_each(impl_->rrsets_[sectionCodeToId(Section::ANSWER())].begin(),
  650. impl_->rrsets_[sectionCodeToId(Section::ANSWER())].end(),
  651. SectionFormatter<RRsetPtr>(Section::ANSWER(), s));
  652. }
  653. if (!impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].empty()) {
  654. s += "\n;; " +
  655. string(sectiontext[Section::AUTHORITY().getCode()]) + " SECTION:\n";
  656. for_each(impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].begin(),
  657. impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].end(),
  658. SectionFormatter<RRsetPtr>(Section::AUTHORITY(), s));
  659. }
  660. if (!impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].empty()) {
  661. s += "\n;; " +
  662. string(sectiontext[Section::ADDITIONAL().getCode()]) +
  663. " SECTION:\n";
  664. for_each(impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].begin(),
  665. impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].end(),
  666. SectionFormatter<RRsetPtr>(Section::ADDITIONAL(), s));
  667. }
  668. return (s);
  669. }
  670. void
  671. Message::clear(Mode mode)
  672. {
  673. impl_->init();
  674. impl_->mode_ = mode;
  675. }
  676. void
  677. Message::makeResponse()
  678. {
  679. if (impl_->mode_ != Message::PARSE) {
  680. isc_throw(InvalidMessageOperation,
  681. "makeResponse() is performed in non-parse mode");
  682. }
  683. impl_->dnssec_ok_ = false;
  684. impl_->remote_udpsize_ = impl_->udpsize_;
  685. impl_->local_edns_ = RRsetPtr();
  686. impl_->udpsize_ = DEFAULT_MAX_UDPSIZE;
  687. impl_->flags_ &= MESSAGE_REPLYPRESERVE;
  688. setHeaderFlag(MessageFlag::QR());
  689. impl_->mode_ = Message::RENDER;
  690. impl_->rrsets_[sectionCodeToId(Section::ANSWER())].clear();
  691. impl_->counts_[Section::ANSWER().getCode()] = 0;
  692. impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].clear();
  693. impl_->counts_[Section::AUTHORITY().getCode()] = 0;
  694. impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].clear();
  695. impl_->counts_[Section::ADDITIONAL().getCode()] = 0;
  696. }
  697. ///
  698. /// Template version of Section Iterator
  699. ///
  700. template <typename T>
  701. struct SectionIteratorImpl {
  702. SectionIteratorImpl(const typename vector<T>::const_iterator& it) :
  703. it_(it) {}
  704. typename vector<T>::const_iterator it_;
  705. };
  706. template <typename T>
  707. SectionIterator<T>::SectionIterator(const SectionIteratorImpl<T>& impl)
  708. {
  709. impl_ = new SectionIteratorImpl<T>(impl.it_);
  710. }
  711. template <typename T>
  712. SectionIterator<T>::~SectionIterator()
  713. {
  714. delete impl_;
  715. }
  716. template <typename T>
  717. SectionIterator<T>::SectionIterator(const SectionIterator<T>& source) :
  718. impl_(new SectionIteratorImpl<T>(source.impl_->it_))
  719. {}
  720. template <typename T>
  721. void
  722. SectionIterator<T>::operator=(const SectionIterator<T>& source)
  723. {
  724. if (impl_ == source.impl_) {
  725. return;
  726. }
  727. SectionIteratorImpl<T>* newimpl =
  728. new SectionIteratorImpl<T>(source.impl_->it_);
  729. delete impl_;
  730. impl_ = newimpl;
  731. }
  732. template <typename T>
  733. SectionIterator<T>&
  734. SectionIterator<T>::operator++()
  735. {
  736. ++(impl_->it_);
  737. return (*this);
  738. }
  739. template <typename T>
  740. SectionIterator<T>
  741. SectionIterator<T>::operator++(int)
  742. {
  743. SectionIterator<T> tmp(*this);
  744. ++(*this);
  745. return (tmp);
  746. }
  747. template <typename T>
  748. const T&
  749. SectionIterator<T>::operator*() const
  750. {
  751. return (*(impl_->it_));
  752. }
  753. template <typename T>
  754. const T*
  755. SectionIterator<T>::operator->() const
  756. {
  757. return (impl_->it_.operator->());
  758. }
  759. template <typename T>
  760. bool
  761. SectionIterator<T>::operator!=(const SectionIterator<T>& other) const
  762. {
  763. return (impl_->it_ != other.impl_->it_);
  764. }
  765. ///
  766. /// We need to explicitly instantiate these template classes because these
  767. /// are public classes but defined in this implementation file.
  768. ///
  769. template class SectionIterator<QuestionPtr>;
  770. template class SectionIterator<RRsetPtr>;
  771. namespace {
  772. typedef SectionIteratorImpl<QuestionPtr> QuestionIteratorImpl;
  773. typedef SectionIteratorImpl<RRsetPtr> RRsetIteratorImpl;
  774. }
  775. ///
  776. /// Question iterator
  777. ///
  778. const QuestionIterator
  779. Message::beginQuestion() const
  780. {
  781. return (QuestionIterator(QuestionIteratorImpl(impl_->questions_.begin())));
  782. }
  783. const QuestionIterator
  784. Message::endQuestion() const
  785. {
  786. return (QuestionIterator(QuestionIteratorImpl(impl_->questions_.end())));
  787. }
  788. ///
  789. /// RRsets iterators
  790. ///
  791. const SectionIterator<RRsetPtr>
  792. Message::beginSection(const Section& section) const
  793. {
  794. if (section == Section::QUESTION()) {
  795. isc_throw(InvalidMessageSection, "");
  796. }
  797. return (RRsetIterator(
  798. RRsetIteratorImpl(
  799. impl_->rrsets_[sectionCodeToId(section)].begin())));
  800. }
  801. const SectionIterator<RRsetPtr>
  802. Message::endSection(const Section& section) const
  803. {
  804. if (section == Section::QUESTION()) {
  805. isc_throw(InvalidMessageSection, "");
  806. }
  807. return (RRsetIterator(
  808. RRsetIteratorImpl(
  809. impl_->rrsets_[sectionCodeToId(section)].end())));
  810. }
  811. ostream&
  812. operator<<(ostream& os, const Opcode& opcode)
  813. {
  814. return (os << opcode.toText());
  815. }
  816. ostream&
  817. operator<<(ostream& os, const Rcode& rcode)
  818. {
  819. return (os << rcode.toText());
  820. }
  821. ostream&
  822. operator<<(ostream& os, const Message& message)
  823. {
  824. return (os << message.toText());
  825. }
  826. } // end of namespace dns
  827. } // end of namespace isc