message.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  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. /// \c SectionIterator is a templated class to provide standard-compatible
  77. /// iterators for Questions and RRsets for a given DNS message section.
  78. /// The template parameter is either \c QuestionPtr (for the question section)
  79. /// or \c RRsetPtr (for the answer, authority, or additional section).
  80. template <typename T>
  81. class SectionIterator : public std::iterator<std::input_iterator_tag, T> {
  82. public:
  83. SectionIterator<T>() : impl_(NULL) {}
  84. SectionIterator<T>(const SectionIteratorImpl<T>& impl);
  85. ~SectionIterator<T>();
  86. SectionIterator<T>(const SectionIterator<T>& source);
  87. void operator=(const SectionIterator<T>& source);
  88. SectionIterator<T>& operator++();
  89. SectionIterator<T> operator++(int);
  90. const T& operator*() const;
  91. const T* operator->() const;
  92. bool operator==(const SectionIterator<T>& other) const;
  93. bool operator!=(const SectionIterator<T>& other) const;
  94. private:
  95. SectionIteratorImpl<T>* impl_;
  96. };
  97. typedef SectionIterator<QuestionPtr> QuestionIterator;
  98. typedef SectionIterator<RRsetPtr> RRsetIterator;
  99. /// \brief The \c Message class encapsulates a standard DNS message.
  100. ///
  101. /// Details of the design and interfaces of this class are still in flux.
  102. /// Here are some notes about the current design.
  103. ///
  104. /// Since many realistic DNS applications deal with messages, message objects
  105. /// will be frequently used, and can be performance sensitive. To minimize
  106. /// the performance overhead of constructing and destructing the objects,
  107. /// this class is designed to be reusable. The \c clear() method is provided
  108. /// for this purpose.
  109. ///
  110. /// A \c Message class object is in either the \c PARSE or the \c RENDER mode.
  111. /// A \c PARSE mode object is intended to be used to convert wire-format
  112. /// message data into a complete \c Message object.
  113. /// A \c RENDER mode object is intended to be used to convert a \c Message
  114. /// object into wire-format data.
  115. /// Some of the method functions of this class are limited to a specific mode.
  116. /// In general, "set" type operations are only allowed for \c RENDER mode
  117. /// objects.
  118. /// The initial mode must be specified on construction, and can be changed
  119. /// through some method functions.
  120. ///
  121. /// This class uses the "pimpl" idiom, and hides detailed implementation
  122. /// through the \c impl_ pointer. Since a \c Message object is expected to
  123. /// be reused, the construction overhead of this approach should be acceptable.
  124. ///
  125. /// Open issues (among other things):
  126. /// - We may want to provide an "iterator" for all RRsets/RRs for convenience.
  127. /// This will be for applications that do not care about performance much,
  128. /// so the implementation can only be moderately efficient.
  129. /// - may want to provide a "find" method for a specified type
  130. /// of RR in the message.
  131. class Message {
  132. public:
  133. /// Constants to specify the operation mode of the \c Message.
  134. enum Mode {
  135. PARSE = 0, ///< Parse mode (handling an incoming message)
  136. RENDER = 1 ///< Render mode (building an outgoing message)
  137. };
  138. /// \brief Constants for flag bit fields of a DNS message header.
  139. ///
  140. /// Only the defined constants are valid where a header flag is required
  141. /// in this library (e.g., in \c Message::setHeaderFlag()).
  142. /// Since these are enum constants, however, invalid value could be passed
  143. /// via casting without an error at compilation time.
  144. /// It is generally the callee's responsibility to check and reject invalid
  145. /// values.
  146. /// Of course, applications shouldn't pass invalid values even if the
  147. /// callee does not perform proper validation; the result in such usage
  148. /// is undefined.
  149. ///
  150. /// In the current implementation, the defined values happen to be
  151. /// a 16-bit integer with one bit being set corresponding to the
  152. /// specified flag in the second 16 bits of the DNS Header section
  153. /// in order to make the internal implementation simpler.
  154. /// For example, \c HEADERFLAG_QR is defined to be 0x8000 as the QR
  155. /// bit is the most significant bit of the 2nd 16 bits of the header.
  156. /// However, applications should not assume this coincidence and
  157. /// must solely use the enum representations.
  158. /// Any usage based on the assumption of the underlying values is invalid
  159. /// and the result is undefined.
  160. ///
  161. /// Likewise, bit wise operations such as AND or OR on the flag values
  162. /// are invalid and are not guaranteed to work, even if it could compile
  163. /// with casting.
  164. /// For example, the following code will compile:
  165. /// \code const uint16_t combined_flags =
  166. /// static_cast<uint16_t>(Message::HEADERFLAG_AA) |
  167. /// static_cast<uint16_t>(Message::HEADERFLAG_CD);
  168. /// message->setHeaderFlag(static_cast<Message::HeaderFlag>(combined_flags));
  169. /// \endcode
  170. /// and (with the current definition) happens to work as if it were
  171. /// validly written as follows:
  172. /// \code message->setHeaderFlag(Message::HEADERFLAG_AA);
  173. /// message->setHeaderFlag(Message::HEADERFLAG_CD);
  174. /// \endcode
  175. /// But the former notation is invalid and may not work in future versions.
  176. /// We did not try to prohibit such usage at compilation time, e.g., by
  177. /// introducing a separately defined class considering the balance
  178. /// between the complexity and advantage, but hopefully the cast notation
  179. /// is sufficiently ugly to prevent proliferation of the usage.
  180. enum HeaderFlag {
  181. HEADERFLAG_QR = 0x8000, ///< Query (if cleared) or response (if set)
  182. HEADERFLAG_AA = 0x0400, ///< Authoritative answer
  183. HEADERFLAG_TC = 0x0200, ///< Truncation
  184. HEADERFLAG_RD = 0x0100, ///< Recursion desired
  185. HEADERFLAG_RA = 0x0080, ///< Recursion available
  186. HEADERFLAG_AD = 0x0020, ///< DNSSEC checking disabled (RFC4035)
  187. HEADERFLAG_CD = 0x0010 ///< Authentic %data (RFC4035)
  188. };
  189. /// \brief Constants to specify sections of a DNS message.
  190. ///
  191. /// The sections are those defined in RFC 1035 excluding the Header
  192. /// section; the fields of the Header section are accessed via specific
  193. /// methods of the \c Message class (e.g., \c getQid()).
  194. ///
  195. /// <b>Open Design Issue:</b>
  196. /// In the current implementation the values for the constants are
  197. /// sorted in the order of appearance in DNS messages, i.e.,
  198. /// from %Question to Additional.
  199. /// So, for example,
  200. /// code <code>section >= Message::SECTION_AUTHORITY</code> can be
  201. /// used to do something in or after the Authority section.
  202. /// This would be convenient, but it is not clear if it's really a good
  203. /// idea to rely on relationship between the underlying values of enum
  204. /// constants. At the moment, applications are discouraged to rely on
  205. /// this implementation detail. We will see if such usage is sufficiently
  206. /// common to officially support it.
  207. ///
  208. /// Note also that since we don't define \c operator++ for this enum,
  209. /// the following code intending to iterate over all sections will
  210. /// \b not compile:
  211. /// \code for (Section s; s <= SECTION_ADDITIONAL; ++s) { // ++s undefined
  212. /// // do something
  213. /// } \endcode
  214. /// This is intentional at this moment, and we'll see if we need to allow
  215. /// that as we have more experiences with this library.
  216. ///
  217. /// <b>Future Extension:</b> We'll probably also define constants for
  218. /// the section names used in dynamic updates in future versions.
  219. enum Section {
  220. SECTION_QUESTION = 0, ///< %Question section
  221. SECTION_ANSWER = 1, ///< Answer section
  222. SECTION_AUTHORITY = 2, ///< Authority section
  223. SECTION_ADDITIONAL = 3 ///< Additional section
  224. };
  225. ///
  226. /// \name Constructors and Destructor
  227. ///
  228. /// Note: The copy constructor and the assignment operator are
  229. /// intentionally defined as private.
  230. /// The intended use case wouldn't require copies of a \c Message object;
  231. /// once created, it would normally be expected to be reused, changing the
  232. /// mode from \c PARSE to \c RENDER, and vice versa.
  233. //@{
  234. public:
  235. /// \brief The constructor.
  236. /// The mode of the message is specified by the \c mode parameter.
  237. Message(Mode mode);
  238. /// \brief The destructor.
  239. ~Message();
  240. private:
  241. Message(const Message& source);
  242. Message& operator=(const Message& source);
  243. //@}
  244. public:
  245. /// \brief Return whether the specified header flag bit is set in the
  246. /// header section.
  247. ///
  248. /// This method is basically exception free, but if
  249. /// \c flag is not a valid constant of the \c HeaderFlag type,
  250. /// an exception of class \c InvalidParameter will be thrown.
  251. ///
  252. /// \param flag The header flag constant to test.
  253. /// \return \c true if the specified flag is set; otherwise \c false.
  254. bool getHeaderFlag(const HeaderFlag flag) const;
  255. /// \brief Set or clear the specified header flag bit in the header
  256. /// section.
  257. ///
  258. /// The optional parameter \c on indicates the operation mode,
  259. /// set or clear; if it's \c true the corresponding flag will be set;
  260. /// otherwise the flag will be cleared.
  261. /// In either case the original state of the flag does not affect the
  262. /// operation; for example, if a flag is already set and the "set"
  263. /// operation is attempted, it effectively results in no operation.
  264. ///
  265. /// The parameter \c on can be omitted, in which case a value of \c true
  266. /// (i.e., set operation) will be assumed.
  267. /// This is based on the observation that the flag would have to be set
  268. /// in the vast majority of the cases where an application needs to
  269. /// use this method.
  270. ///
  271. /// This method is only allowed in the \c RENDER mode;
  272. /// if the \c Message is in other mode, an exception of class
  273. /// InvalidMessageOperation will be thrown.
  274. ///
  275. /// If \c flag is not a valid constant of the \c HeaderFlag type,
  276. /// an exception of class \c InvalidParameter will be thrown.
  277. ///
  278. /// \param flag The header flag constant to set or clear.
  279. /// \param on If \c true the flag will be set; otherwise the flag will be
  280. /// cleared.
  281. void setHeaderFlag(const HeaderFlag flag, const bool on = true);
  282. /// \brief Return the query ID given in the header section of the message.
  283. qid_t getQid() const;
  284. /// \brief Set the query ID of the header section of the message.
  285. ///
  286. /// This method is only allowed in the \c RENDER mode;
  287. /// if the \c Message is in other mode, an exception of class
  288. /// InvalidMessageOperation will be thrown.
  289. void setQid(qid_t qid);
  290. /// \brief Return the Response Code of the message.
  291. ///
  292. /// This includes extended codes specified by an EDNS OPT RR (when
  293. /// included). In the \c PARSE mode, if the received message contains
  294. /// an EDNS OPT RR, the corresponding extended code is identified and
  295. /// returned.
  296. ///
  297. /// The message must have been properly parsed (in the case of the
  298. /// \c PARSE mode) or an \c Rcode has been set (in the case of the
  299. /// \c RENDER mode) beforehand. Otherwise, an exception of class
  300. /// \c InvalidMessageOperation will be thrown.
  301. const Rcode& getRcode() const;
  302. /// \brief Set the Response Code of the message.
  303. ///
  304. /// This method is only allowed in the \c RENDER mode;
  305. /// if the \c Message is in other mode, an exception of class
  306. /// InvalidMessageOperation will be thrown.
  307. ///
  308. /// If the specified code is an EDNS extended RCODE, an EDNS OPT RR will be
  309. /// included in the message.
  310. void setRcode(const Rcode& rcode);
  311. /// \brief Return the OPCODE given in the header section of the message.
  312. ///
  313. /// The message must have been properly parsed (in the case of the
  314. /// \c PARSE mode) or an \c Opcode has been set (in the case of the
  315. /// \c RENDER mode) beforehand. Otherwise, an exception of class
  316. /// \c InvalidMessageOperation will be thrown.
  317. const Opcode& getOpcode() const;
  318. /// \brief Set the OPCODE of the header section of the message.
  319. ///
  320. /// This method is only allowed in the \c RENDER mode;
  321. /// if the \c Message is in other mode, an exception of class
  322. /// InvalidMessageOperation will be thrown.
  323. void setOpcode(const Opcode& opcode);
  324. /// \brief Return, if any, the EDNS associated with the message.
  325. ///
  326. /// This method never throws an exception.
  327. ///
  328. /// \return A shared pointer to the EDNS. This will be a null shared
  329. /// pointer if the message is not associated with EDNS.
  330. ConstEDNSPtr getEDNS() const;
  331. /// \brief Set EDNS for the message.
  332. ///
  333. /// This method is only allowed in the \c RENDER mode;
  334. /// if the \c Message is in other mode, an exception of class
  335. /// InvalidMessageOperation will be thrown.
  336. ///
  337. /// \param edns A shared pointer to an \c EDNS object to be set in
  338. /// \c Message.
  339. void setEDNS(ConstEDNSPtr edns);
  340. /// \brief Returns the number of RRs contained in the given section.
  341. ///
  342. /// In the \c PARSE mode, the returned value may not be identical to
  343. /// the actual number of RRs of the incoming message that is parsed.
  344. /// The \c Message class handles some "meta" RRs such as EDNS OPT RR
  345. /// separately. This method doesn't include such RRs.
  346. /// Also, a future version of the parser will detect and unify duplicate
  347. /// RRs (which should be rare in practice though), in which case
  348. /// the stored RRs in the \c Message object will be fewer than the RRs
  349. /// originally contained in the incoming message.
  350. ///
  351. /// Likewise, in the \c RENDER mode, even if \c EDNS is set in the
  352. /// \c Message, this method doesn't count the corresponding OPT RR
  353. /// in the Additional section.
  354. ///
  355. /// This method is basically exception free, but if
  356. /// \c section is not a valid constant of the \c Section type,
  357. /// an exception of class \c OutOfRange will be thrown.
  358. ///
  359. /// \param section The section in the message where RRs should be
  360. /// counted.
  361. /// \return The number of RRs stored in the specified section of the
  362. /// message.
  363. unsigned int getRRCount(const Section section) const;
  364. /// \brief Return an iterator corresponding to the beginning of the
  365. /// Question section of the message.
  366. const QuestionIterator beginQuestion() const;
  367. /// \brief Return an iterator corresponding to the end of the
  368. /// Question section of the message.
  369. const QuestionIterator endQuestion() const;
  370. /// \brief Return an iterator corresponding to the beginning of the
  371. /// given section (other than Question) of the message.
  372. ///
  373. /// \c section must be a valid constant of the \c Section type;
  374. /// otherwise, an exception of class \c OutOfRange will be thrown.
  375. const RRsetIterator beginSection(const Section section) const;
  376. /// \brief Return an iterator corresponding to the end of the
  377. /// given section (other than Question) of the message.
  378. ///
  379. /// \c section must be a valid constant of the \c Section type;
  380. /// otherwise, an exception of class \c OutOfRange will be thrown.
  381. const RRsetIterator endSection(const Section section) const;
  382. /// \brief Add a (pointer like object of) Question to the message.
  383. ///
  384. /// This method is only allowed in the \c RENDER mode;
  385. /// if the \c Message is in other mode, an exception of class
  386. /// InvalidMessageOperation will be thrown.
  387. void addQuestion(QuestionPtr question);
  388. /// \brief Add a (pointer like object of) Question to the message.
  389. ///
  390. /// This version internally creates a \c QuestionPtr object from the
  391. /// given \c question and calls the other version of this method.
  392. /// So this is inherently less efficient, but is provided because this
  393. /// form may be more intuitive and may make more sense for performance
  394. /// insensitive applications.
  395. ///
  396. /// This method is only allowed in the \c RENDER mode;
  397. /// if the \c Message is in other mode, an exception of class
  398. /// InvalidMessageOperation will be thrown.
  399. void addQuestion(const Question& question);
  400. /// \brief Add a (pointer like object of) RRset to the given section
  401. /// of the message.
  402. ///
  403. /// This interface takes into account the RRSIG possibly attached to
  404. /// \c rrset. This interface design needs to be revisited later.
  405. ///
  406. /// This method is only allowed in the \c RENDER mode;
  407. /// if the \c Message is in other mode, an exception of class
  408. /// InvalidMessageOperation will be thrown.
  409. /// \c section must be a valid constant of the \c Section type;
  410. /// otherwise, an exception of class \c OutOfRange will be thrown.
  411. ///
  412. /// Note that \c addRRset() does not currently check for duplicate
  413. /// data before inserting RRsets. The caller is responsible for
  414. /// checking for these (see \c hasRRset() below).
  415. void addRRset(const Section section, RRsetPtr rrset, bool sign = false);
  416. /// \brief Determine whether the given section already has an RRset
  417. /// matching the given name, RR class and RR type.
  418. ///
  419. /// \c section must be a valid constant of the \c Section type;
  420. /// otherwise, an exception of class \c OutOfRange will be thrown.
  421. ///
  422. /// This should probably be extended to be a "find" method that returns
  423. /// a matching RRset if found.
  424. bool hasRRset(const Section section, const Name& name,
  425. const RRClass& rrclass, const RRType& rrtype);
  426. // The following methods are not currently implemented.
  427. //void removeQuestion(QuestionPtr question);
  428. //void removeRRset(const Section section, RRsetPtr rrset);
  429. // notyet:
  430. //void addRR(const Section section, const RR& rr);
  431. //void removeRR(const Section section, const RR& rr);
  432. /// \brief Clear the message content (if any) and reinitialize it in the
  433. /// specified mode.
  434. void clear(Mode mode);
  435. /// \brief Prepare for making a response from a request.
  436. ///
  437. /// This will clear the DNS header except those fields that should be kept
  438. /// for the response, and clear answer and the following sections.
  439. /// See also dns_message_reply() of BIND9.
  440. void makeResponse();
  441. /// \brief Convert the Message to a string.
  442. ///
  443. /// At least \c Opcode and \c Rcode must be validly set in the \c Message
  444. /// (as a result of parse in the \c PARSE mode or by explicitly setting
  445. /// in the \c RENDER mode); otherwise, an exception of
  446. /// class \c InvalidMessageOperation will be thrown.
  447. std::string toText() const;
  448. /// \brief Render the message in wire formant into a \c MessageRenderer
  449. /// object.
  450. ///
  451. /// This \c Message must be in the \c RENDER mode and both \c Opcode and
  452. /// \c Rcode must have been set beforehand; otherwise, an exception of
  453. /// class \c InvalidMessageOperation will be thrown.
  454. void toWire(MessageRenderer& renderer);
  455. /// \brief Parse the header section of the \c Message.
  456. void parseHeader(InputBuffer& buffer);
  457. /// \brief Parse the \c Message.
  458. void fromWire(InputBuffer& buffer);
  459. ///
  460. /// \name Protocol constants
  461. ///
  462. //@{
  463. /// \brief The default maximum size of UDP DNS messages that don't cause
  464. /// truncation.
  465. ///
  466. /// With EDNS the maximum size can be increased per message.
  467. static const uint16_t DEFAULT_MAX_UDPSIZE = 512;
  468. //@}
  469. private:
  470. MessageImpl* impl_;
  471. };
  472. /// \brief Pointer-like type pointing to a \c Message
  473. ///
  474. /// This type is expected to be used as an argument in asynchronous
  475. /// callback functions. The internal reference-counting will ensure that
  476. /// that ongoing state information will not be lost if the object
  477. /// that originated the asynchronous call falls out of scope.
  478. typedef boost::shared_ptr<Message> MessagePtr;
  479. std::ostream& operator<<(std::ostream& os, const Message& message);
  480. }
  481. }
  482. #endif // __MESSAGE_H
  483. // Local Variables:
  484. // mode: c++
  485. // End: