message.cc 30 KB

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