message.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  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. #ifndef __MESSAGE_H
  16. #define __MESSAGE_H 1
  17. #include <stdint.h>
  18. #include <iterator>
  19. #include <string>
  20. #include <ostream>
  21. #include <exceptions/exceptions.h>
  22. #include <dns/edns.h>
  23. #include <dns/question.h>
  24. #include <dns/rrset.h>
  25. namespace isc {
  26. namespace dns {
  27. ///
  28. /// \brief A standard DNS module exception that is thrown if a wire format
  29. /// message parser encounters a short length of data that don't even contain
  30. /// the full header section.
  31. ///
  32. class MessageTooShort : public Exception {
  33. public:
  34. MessageTooShort(const char* file, size_t line, const char* what) :
  35. isc::Exception(file, line, what) {}
  36. };
  37. ///
  38. /// \brief A standard DNS module exception that is thrown if a section iterator
  39. /// is being constructed for an incompatible section. Specifically, this
  40. /// happens RRset iterator is being constructed for a Question section.
  41. ///
  42. class InvalidMessageSection : public Exception {
  43. public:
  44. InvalidMessageSection(const char* file, size_t line, const char* what) :
  45. isc::Exception(file, line, what) {}
  46. };
  47. ///
  48. /// \brief A standard DNS module exception that is thrown if a \c Message
  49. /// class method is called that is prohibited for the current mode of
  50. /// the message.
  51. ///
  52. class InvalidMessageOperation : public Exception {
  53. public:
  54. InvalidMessageOperation(const char* file, size_t line, const char* what) :
  55. isc::Exception(file, line, what) {}
  56. };
  57. ///
  58. /// \brief A standard DNS module exception that is thrown if a UDP buffer size
  59. /// smaller than the standard default maximum (DEFAULT_MAX_UDPSIZE) is
  60. /// being specified for the message.
  61. ///
  62. class InvalidMessageUDPSize : public Exception {
  63. public:
  64. InvalidMessageUDPSize(const char* file, size_t line, const char* what) :
  65. isc::Exception(file, line, what) {}
  66. };
  67. typedef uint16_t qid_t;
  68. class InputBuffer;
  69. class MessageRenderer;
  70. class Message;
  71. class MessageImpl;
  72. class Opcode;
  73. class Rcode;
  74. template <typename T>
  75. struct SectionIteratorImpl;
  76. /// \brief The \c MessageFlag class objects represent standard flag bits
  77. /// of the header section of DNS messages.
  78. ///
  79. /// Constant objects are defined for standard flags.
  80. class MessageFlag {
  81. public:
  82. /// \brief Returns the corresponding bit of the MessageFlag.
  83. ///
  84. /// Note: this value is intended to be used for rendering or parsing
  85. /// low level wire-format data. Applications should use abstract
  86. /// interfaces. This also means the interface is not well sophisticated,
  87. /// and we should revisit the design.
  88. uint16_t getBit() const { return (flagbit_); }
  89. static const MessageFlag& QR();
  90. static const MessageFlag& AA();
  91. static const MessageFlag& TC();
  92. static const MessageFlag& RD();
  93. static const MessageFlag& RA();
  94. static const MessageFlag& AD();
  95. static const MessageFlag& CD();
  96. private:
  97. MessageFlag(uint16_t flagbit) : flagbit_(flagbit) {}
  98. uint16_t flagbit_;
  99. };
  100. inline const MessageFlag&
  101. MessageFlag::QR()
  102. {
  103. static MessageFlag f(0x8000);
  104. return (f);
  105. }
  106. inline const MessageFlag&
  107. MessageFlag::AA()
  108. {
  109. static MessageFlag f(0x0400);
  110. return (f);
  111. }
  112. inline const MessageFlag&
  113. MessageFlag::TC()
  114. {
  115. static MessageFlag f(0x0200);
  116. return (f);
  117. }
  118. inline const MessageFlag&
  119. MessageFlag::RD()
  120. {
  121. static MessageFlag f(0x0100);
  122. return (f);
  123. }
  124. inline const MessageFlag&
  125. MessageFlag::RA()
  126. {
  127. static MessageFlag f(0x0080);
  128. return (f);
  129. }
  130. inline const MessageFlag&
  131. MessageFlag::AD()
  132. {
  133. static MessageFlag f(0x0020);
  134. return (f);
  135. }
  136. inline const MessageFlag&
  137. MessageFlag::CD()
  138. {
  139. static MessageFlag f(0x0010);
  140. return (f);
  141. }
  142. /// \brief The \c Section class objects represent DNS message sections such
  143. /// as the header, question, or answer.
  144. ///
  145. /// Note: this class doesn't seem to be very useful. We should probably
  146. /// revisit this design.
  147. ///
  148. /// Note: whether or not it's represented as a class, we'll need a way
  149. /// to represent more advanced sections such as those used in dynamic updates.
  150. /// This is a TODO item.
  151. ///
  152. /// Constant objects are defined for standard flags.
  153. class Section {
  154. public:
  155. /// \brief Returns the relative position of the \c Section in DNS messages.
  156. unsigned int getCode() const { return (code_); }
  157. bool operator==(const Section& other) const
  158. { return (code_ == other.code_); }
  159. bool operator!=(const Section& other) const
  160. { return (code_ != other.code_); }
  161. static const Section& QUESTION();
  162. static const Section& ANSWER();
  163. static const Section& AUTHORITY();
  164. static const Section& ADDITIONAL();
  165. private:
  166. enum {
  167. SECTION_QUESTION = 0,
  168. SECTION_ANSWER = 1,
  169. SECTION_AUTHORITY = 2,
  170. SECTION_ADDITIONAL = 3
  171. };
  172. Section(int code) : code_(code) {}
  173. unsigned int code_;
  174. };
  175. inline const Section&
  176. Section::QUESTION()
  177. {
  178. static Section s(SECTION_QUESTION);
  179. return (s);
  180. }
  181. inline const Section&
  182. Section::ANSWER()
  183. {
  184. static Section s(SECTION_ANSWER);
  185. return (s);
  186. }
  187. inline const Section&
  188. Section::AUTHORITY()
  189. {
  190. static Section s(SECTION_AUTHORITY);
  191. return (s);
  192. }
  193. inline const Section&
  194. Section::ADDITIONAL()
  195. {
  196. static Section s(SECTION_ADDITIONAL);
  197. return (s);
  198. }
  199. /// \c SectionIterator is a templated class to provide standard-compatible
  200. /// iterators for Questions and RRsets for a given DNS message section.
  201. /// The template parameter is either \c QuestionPtr (for the question section)
  202. /// or \c RRsetPtr (for the answer, authority, or additional section).
  203. template <typename T>
  204. class SectionIterator : public std::iterator<std::input_iterator_tag, T> {
  205. public:
  206. SectionIterator<T>() : impl_(NULL) {}
  207. SectionIterator<T>(const SectionIteratorImpl<T>& impl);
  208. ~SectionIterator<T>();
  209. SectionIterator<T>(const SectionIterator<T>& source);
  210. void operator=(const SectionIterator<T>& source);
  211. SectionIterator<T>& operator++();
  212. SectionIterator<T> operator++(int);
  213. const T& operator*() const;
  214. const T* operator->() const;
  215. bool operator==(const SectionIterator<T>& other) const;
  216. bool operator!=(const SectionIterator<T>& other) const;
  217. private:
  218. SectionIteratorImpl<T>* impl_;
  219. };
  220. typedef SectionIterator<QuestionPtr> QuestionIterator;
  221. typedef SectionIterator<RRsetPtr> RRsetIterator;
  222. /// \brief The \c Message class encapsulates a standard DNS message.
  223. ///
  224. /// Details of the design and interfaces of this class are still in flux.
  225. /// Here are some notes about the current design.
  226. ///
  227. /// Since many realistic DNS applications deal with messages, message objects
  228. /// will be frequently used, and can be performance sensitive. To minimize
  229. /// the performance overhead of constructing and destructing the objects,
  230. /// this class is designed to be reusable. The \c clear() method is provided
  231. /// for this purpose.
  232. ///
  233. /// A \c Message class object is in either the \c PARSE or the \c RENDER mode.
  234. /// A \c PARSE mode object is intended to be used to convert wire-format
  235. /// message data into a complete \c Message object.
  236. /// A \c RENDER mode object is intended to be used to convert a \c Message
  237. /// object into wire-format data.
  238. /// Some of the method functions of this class are limited to a specific mode.
  239. /// In general, "set" type operations are only allowed for \c RENDER mode
  240. /// objects.
  241. /// The initial mode must be specified on construction, and can be changed
  242. /// through some method functions.
  243. ///
  244. /// This class uses the "pimpl" idiom, and hides detailed implementation
  245. /// through the \c impl_ pointer. Since a \c Message object is expected to
  246. /// be reused, the construction overhead of this approach should be acceptable.
  247. ///
  248. /// Open issues (among other things):
  249. /// - We may want to provide an "iterator" for all RRsets/RRs for convenience.
  250. /// This will be for applications that do not care about performance much,
  251. /// so the implementation can only be moderately efficient.
  252. /// - may want to provide a "find" method for a specified type
  253. /// of RR in the message.
  254. class Message {
  255. public:
  256. enum Mode {
  257. PARSE = 0,
  258. RENDER = 1
  259. };
  260. ///
  261. /// \name Constructors and Destructor
  262. ///
  263. /// Note: The copy constructor and the assignment operator are intentionally
  264. /// defined as private. The intended use case wouldn't require copies of
  265. /// a \c Message object; once created, it would normally be expected to
  266. /// be reused, changing the mode from \c PARSE to \c RENDER, and vice
  267. /// versa.
  268. //@{
  269. public:
  270. /// \brief The constructor.
  271. /// The mode of the message is specified by the \c mode parameter.
  272. Message(Mode mode);
  273. /// \brief The destructor.
  274. ~Message();
  275. private:
  276. Message(const Message& source);
  277. Message& operator=(const Message& source);
  278. //@}
  279. public:
  280. /// \brief Return whether the specified header flag bit is set in the
  281. /// header section.
  282. bool getHeaderFlag(const MessageFlag& flag) const;
  283. /// \brief Set the specified header flag bit is set in the header section.
  284. ///
  285. /// Only allowed in the \c RENDER mode.
  286. void setHeaderFlag(const MessageFlag& flag);
  287. /// \brief Clear the specified header flag bit is set in the header section.
  288. ///
  289. /// Only allowed in the \c RENDER mode.
  290. /// Note: it may make more sense to integrate this method into \c
  291. /// \c setHeaderFlag() with an additional argument.
  292. void clearHeaderFlag(const MessageFlag& flag);
  293. /// \brief Return the query ID given in the header section of the message.
  294. qid_t getQid() const;
  295. /// \brief Set the query ID of the header section of the message.
  296. ///
  297. /// Only allowed in the \c RENDER mode.
  298. void setQid(qid_t qid);
  299. /// \brief Return the Response Code of the message.
  300. ///
  301. /// This includes extended codes specified by an EDNS OPT RR (when
  302. /// included). In the \c PARSE mode, if the received message contains
  303. /// an EDNS OPT RR, the corresponding extended code is identified and
  304. /// returned.
  305. ///
  306. /// The message must have been properly parsed (in the case of the
  307. /// \c PARSE mode) or an \c Rcode has been set (in the case of the
  308. /// \c RENDER mode) beforehand. Otherwise, an exception of class
  309. /// \c InvalidMessageOperation will be thrown.
  310. const Rcode& getRcode() const;
  311. /// \brief Set the Response Code of the message.
  312. ///
  313. /// Only allowed in the \c RENDER mode.
  314. ///
  315. /// If the specified code is an EDNS extended RCODE, an EDNS OPT RR will be
  316. /// included in the message.
  317. void setRcode(const Rcode& rcode);
  318. /// \brief Return the OPCODE given in the header section of the message.
  319. ///
  320. /// The message must have been properly parsed (in the case of the
  321. /// \c PARSE mode) or an \c Opcode has been set (in the case of the
  322. /// \c RENDER mode) beforehand. Otherwise, an exception of class
  323. /// \c InvalidMessageOperation will be thrown.
  324. const Opcode& getOpcode() const;
  325. /// \brief Set the OPCODE of the header section of the message.
  326. ///
  327. /// Only allowed in the \c RENDER mode.
  328. void setOpcode(const Opcode& opcode);
  329. /// \brief Return, if any, the EDNS associated with the message.
  330. ///
  331. /// This method never throws an exception.
  332. ///
  333. /// \return A shared pointer to the EDNS. This will be a null shared
  334. /// pointer if the message is not associated with EDNS.
  335. ConstEDNSPtr getEDNS() const;
  336. /// \brief Set EDNS for the message.
  337. ///
  338. /// Only allowed in the \c RENDER mode; otherwise an exception of class
  339. /// \c InvalidMessageOperation will be thrown.
  340. ///
  341. /// \param edns A shared pointer to an \c EDNS object to be set in
  342. /// \c Message.
  343. void setEDNS(ConstEDNSPtr edns);
  344. /// \brief Returns the number of RRs contained in the given section.
  345. unsigned int getRRCount(const Section& section) const;
  346. /// \brief Return an iterator corresponding to the beginning of the
  347. /// Question section of the message.
  348. const QuestionIterator beginQuestion() const;
  349. /// \brief Return an iterator corresponding to the end of the
  350. /// Question section of the message.
  351. const QuestionIterator endQuestion() const;
  352. /// \brief Return an iterator corresponding to the beginning of the
  353. /// given section (other than Question) of the message.
  354. const RRsetIterator beginSection(const Section& section) const;
  355. /// \brief Return an iterator corresponding to the end of the
  356. /// given section (other than Question) of the message.
  357. const RRsetIterator endSection(const Section& section) const;
  358. /// \brief Add a (pointer like object of) Question to the message.
  359. ///
  360. /// Only allowed in the \c RENDER mode.
  361. void addQuestion(QuestionPtr question);
  362. /// \brief Add a (pointer like object of) Question to the message.
  363. ///
  364. /// This version internally creates a \c QuestionPtr object from the
  365. /// given \c question and calls the other version of this method.
  366. /// So this is inherently less efficient, but is provided because this
  367. /// form may be more intuitive and may make more sense for performance
  368. /// insensitive applications.
  369. ///
  370. /// Only allowed in the \c RENDER mode.
  371. void addQuestion(const Question& question);
  372. /// \brief Add a (pointer like object of) RRset to the given section
  373. /// of the message.
  374. ///
  375. /// This interface takes into account the RRSIG possibly attached to
  376. /// \c rrset. This interface design needs to be revisited later.
  377. ///
  378. /// Only allowed in the \c RENDER mode.
  379. ///
  380. /// Note that addRRset() does not currently check for duplicate
  381. /// data before inserting RRsets. The caller is responsible for
  382. /// checking for these (see hasRRset() below).
  383. void addRRset(const Section& section, RRsetPtr rrset, bool sign = false);
  384. /// \brief Determine whether the given section already has an RRset
  385. /// matching the name and type of this one
  386. bool hasRRset(const Section& section, RRsetPtr rrset);
  387. // The following methods are not currently implemented.
  388. //void removeQuestion(QuestionPtr question);
  389. //void removeRRset(const Section& section, RRsetPtr rrset);
  390. // notyet:
  391. //void addRR(const Section& section, const RR& rr);
  392. //void removeRR(const Section& section, const RR& rr);
  393. /// \brief Clear the message content (if any) and reinitialize it in the
  394. /// specified mode.
  395. void clear(Mode mode);
  396. /// \brief Prepare for making a response from a request.
  397. ///
  398. /// This will clear the DNS header except those fields that should be kept
  399. /// for the response, and clear answer and the following sections.
  400. /// See also dns_message_reply() of BIND9.
  401. void makeResponse();
  402. /// \brief Convert the Message to a string.
  403. ///
  404. /// At least \c Opcode and \c Rcode must be validly set in the \c Message
  405. /// (as a result of parse in the \c PARSE mode or by explicitly setting
  406. /// in the \c RENDER mode); otherwise, an exception of
  407. /// class \c InvalidMessageOperation will be thrown.
  408. std::string toText() const;
  409. /// \brief Render the message in wire formant into a \c MessageRenderer
  410. /// object.
  411. ///
  412. /// This \c Message must be in the \c RENDER mode and both \c Opcode and
  413. /// \c Rcode must have been set beforehand; otherwise, an exception of
  414. /// class \c InvalidMessageOperation will be thrown.
  415. void toWire(MessageRenderer& renderer);
  416. /// \brief Parse the header section of the \c Message.
  417. void parseHeader(InputBuffer& buffer);
  418. /// \brief Parse the \c Message.
  419. void fromWire(InputBuffer& buffer);
  420. ///
  421. /// \name Protocol constants
  422. ///
  423. //@{
  424. /// \brief The default maximum size of UDP DNS messages that don't cause
  425. /// truncation.
  426. ///
  427. /// With EDNS the maximum size can be increased per message.
  428. static const uint16_t DEFAULT_MAX_UDPSIZE = 512;
  429. /// \brief The highest EDNS version this implementation supports.
  430. static const uint8_t EDNS_SUPPORTED_VERSION = 0;
  431. //@}
  432. private:
  433. MessageImpl* impl_;
  434. };
  435. std::ostream& operator<<(std::ostream& os, const Message& message);
  436. }
  437. }
  438. #endif // __MESSAGE_H
  439. // Local Variables:
  440. // mode: c++
  441. // End: