message.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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 <sys/socket.h>
  18. #include <vector>
  19. #include <string>
  20. #include <boost/shared_ptr.hpp>
  21. #include <dns/exceptions.h>
  22. #include <dns/buffer.h>
  23. #include <dns/name.h>
  24. #include <dns/rrset.h>
  25. namespace ISC {
  26. namespace DNS {
  27. typedef uint8_t rcode_t; // we actually only need 4 bits of it
  28. typedef uint8_t opcode_t; // we actually only need 4 bits of it
  29. typedef uint16_t flags_t;
  30. typedef uint16_t qid_t;
  31. class Message;
  32. class EDNS; // see below
  33. typedef boost::shared_ptr<AbstractRRset> RRsetPtr;
  34. class RRsetsSorter {
  35. public:
  36. void sort(Message& message, section_t section) {} // dummy for now.
  37. };
  38. #define get_msgflg(flg, capflg) \
  39. bool get_ ## flg() const { return ((flags_ & FLAG_ ## capflg) != 0); }
  40. #define set_msgflg(flg, capflg) \
  41. bool set_ ## flg(bool on) { \
  42. if (on) \
  43. flags_ |= FLAG_ ## capflg; \
  44. else \
  45. flags_ &= ~FLAG_ ## capflg; \
  46. }
  47. class Message {
  48. public:
  49. Message();
  50. ~Message();
  51. qid_t get_qid() const { return (qid_); }
  52. void set_qid(qid_t qid) { qid_ = qid; }
  53. get_msgflg(rd, RD)
  54. set_msgflg(rd, RD)
  55. get_msgflg(aa, AA)
  56. set_msgflg(aa, AA)
  57. get_msgflg(qr, QR)
  58. set_msgflg(qr, QR)
  59. get_msgflg(tc, TC)
  60. set_msgflg(tc, TC)
  61. get_msgflg(ra, RA)
  62. set_msgflg(ra, RA)
  63. get_msgflg(ad, AD)
  64. set_msgflg(ad, AD)
  65. get_msgflg(cd, CD)
  66. set_msgflg(cd, CD)
  67. rcode_t get_rcode() const { return (rcode_); }
  68. void set_rcode(rcode_t rcode) { rcode_ = rcode; }
  69. opcode_t get_opcode() const { return (opcode_); }
  70. void set_opcode(opcode_t opcode) { opcode_ = opcode; }
  71. std::string to_text() const;
  72. // we don't provide accessors to QD/AN/NS/AR counters as this information
  73. // is included in the corresponding RRsets.
  74. // Open issues:
  75. // - should we handle the question section separately?
  76. // - may want to provide an "iterator" for all RRsets/RRs
  77. // - may want to provide a "find" method for a specified type
  78. // of RR in the message
  79. const std::vector<RRsetPtr>& get_section(section_t section) const
  80. { return (sections_[section]); }
  81. void add_rrset(section_t section, RRsetPtr rrset);
  82. // add_question() is redundant in that it's a special case of add_rrset,
  83. // but it'd be convenient for general purpose applications.
  84. void add_question(const Name& qname, const RRClass& qclass,
  85. const RRType& qtype);
  86. void remove_rrset(section_t section, RRsetPtr rrset);
  87. void add_rr(section_t section, const RR& rr);
  88. void remove_rr(section_t section, const RR& rr);
  89. // should we separate methods for different EDNS0-related
  90. // parameters/options? it would probably be better to have a
  91. // separate class for future extensibility.
  92. // on the other hand, considering we're going to use EDNS0 pretty
  93. // ubiquitously, perhaps we should include currently-defined EDNS0
  94. // parameters and options by default.
  95. void set_edns(EDNS* edns); // TBD
  96. const EDNS* get_edns() const; // TBD
  97. // prepare for making a response from a request. This will clear the
  98. // DNS header except those fields that should be kept for the response,
  99. // and clear answer and the following sections.
  100. // see also dns_message_reply() of BIND9.
  101. void make_response();
  102. // Render message
  103. void to_wire(); // should probably return some result code?
  104. Buffer& get_buffer()
  105. {
  106. if (buffer_ == NULL)
  107. throw DNSNoMessageBuffer();
  108. return (*buffer_);
  109. }
  110. NameCompressor& get_compressor()
  111. {
  112. if (compressor_ == NULL)
  113. throw DNSNoNameCompressor();
  114. return (*compressor_);
  115. }
  116. NameDecompressor& get_decompressor()
  117. {
  118. if (decompressor_ == NULL)
  119. throw DNSNoNameDecompressor();
  120. return (*decompressor_);
  121. }
  122. // Parse message:
  123. // This function may throw exceptions. We may revisit this design.
  124. void from_wire();
  125. public:
  126. // public protocol constants
  127. static const rcode_t RCODE_NOERROR = 0;
  128. static const rcode_t RCODE_FORMERR = 1;
  129. static const rcode_t RCODE_SERVFAIL = 2;
  130. static const rcode_t RCODE_NXDOMAIN = 3;
  131. static const rcode_t RCODE_NOTIMP = 4;
  132. static const rcode_t RCODE_REFUSED = 5;
  133. // ...more to follow
  134. static const opcode_t OPCODE_QUERY = 0;
  135. static const opcode_t OPCODE_IQUERY = 1;
  136. static const opcode_t OPCODE_STATUS = 2;
  137. static const opcode_t OPCODE_NOTIFY = 4;
  138. static const opcode_t OPCODE_UPDATE = 5;
  139. private:
  140. void initialize();
  141. void parse_question();
  142. private:
  143. // Open issues: should we rather have a header in wire-format
  144. // for efficiency?
  145. qid_t qid_;
  146. rcode_t rcode_;
  147. opcode_t opcode_;
  148. flags_t flags_;
  149. int counts_[SECTION_MAX]; // TODO: revisit this definition
  150. // TODO: revisit the type of vector items
  151. std::vector<RRsetPtr> sections_[SECTION_MAX];
  152. // tsig/sig0: TODO
  153. EDNS* edns_;
  154. Buffer* buffer_;
  155. NameCompressor* compressor_;
  156. NameDecompressor* decompressor_;
  157. RRsetsSorter* sorter_;
  158. // created internally with the default constructor. TBD: revisit this idea.
  159. Buffer* default_buffer_;
  160. NameCompressor* default_compressor_;
  161. NameDecompressor* default_decompressor_;
  162. // protocol constants
  163. static const size_t HEADERLEN = 12;
  164. static const flags_t FLAG_QR = 0x8000;
  165. static const flags_t FLAG_AA = 0x0400;
  166. static const flags_t FLAG_TC = 0x0200;
  167. static const flags_t FLAG_RD = 0x0100;
  168. static const flags_t FLAG_RA = 0x0080;
  169. static const flags_t FLAG_AD = 0x0020;
  170. static const flags_t FLAG_CD = 0x0010;
  171. static const unsigned int OPCODE_MASK = 0x7800;
  172. static const unsigned int OPCODE_SHIFT = 11;
  173. static const unsigned int RCODE_MASK = 0x000f;
  174. static const unsigned int FLAG_MASK = 0x8ff0;
  175. static const unsigned int MESSAGE_REPLYPRESERVE = (FLAG_RD | FLAG_CD);
  176. };
  177. }
  178. }
  179. #endif // __MESSAGE_H
  180. // Local Variables:
  181. // mode: c++
  182. // End: