message.cc 28 KB

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