query.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // Copyright (C) 2010 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 __QUERY_H
  16. #define __QUERY_H
  17. #include <queue>
  18. namespace isc {
  19. namespace dns {
  20. class Name;
  21. class Message;
  22. class Section;
  23. class RRClass;
  24. class RRType;
  25. }
  26. namespace auth {
  27. // An individual task to be carried out by the query logic
  28. class QueryTask {
  29. private:
  30. /// Note: The copy constructor and the assignment operator are intentionally
  31. /// defined as private.
  32. QueryTask(const QueryTask& source);
  33. QueryTask& operator=(const QueryTask& source);
  34. public:
  35. // XXX: Members are currently public, but should probably be
  36. // moved to private and wrapped in get() functions later.
  37. // The standard query tuple: qname/qclass/qtype.
  38. // Note that qtype is ignored in the GLUE_QUERY/NOGLUE_QUERY case.
  39. const isc::dns::Name qname;
  40. const isc::dns::RRClass& qclass;
  41. const isc::dns::RRType& qtype;
  42. // The section of the reply into which the data should be
  43. // written after it has been fetched from the data source.
  44. const isc::dns::Section& section;
  45. // The op field indicates the operation to be carried out by
  46. // this query task:
  47. //
  48. // - SIMPLE_QUERY: look for a match for qname/qclass/qtype
  49. // in local data (regardless of whether it is above or below
  50. // a zone cut).
  51. //
  52. // - AUTH_QUERY: look for a match for qname/qclass/qtype, or
  53. // for qname/qclass/CNAME, or for a referral.
  54. //
  55. // - GLUE_QUERY: look for matches with qname/qclass/A
  56. // OR qname/class/AAAA in local data, regardless of
  57. // authority, for use in glue. (This can be implemented
  58. // as two successive SIMPLE_QUERY tasks, but might be
  59. // optimized by the concrete data source implementation
  60. // by turning it into a single database lookup.)
  61. //
  62. // - NOGLUE_QUERY: same as GLUE_QUERY except that answers
  63. // are rejected if they are below a zone cut.
  64. //
  65. // - REF_QUERY: look for matches for qname/qclass/NS,
  66. // qname/qclass/DS, and qname/qclass/DNAME. Used
  67. // to search for a zone cut.
  68. const enum Op {
  69. SIMPLE_QUERY,
  70. AUTH_QUERY,
  71. GLUE_QUERY,
  72. NOGLUE_QUERY,
  73. REF_QUERY,
  74. } op;
  75. // The state field indicates the state of the query; it controls
  76. // the next step after processing each query task.
  77. //
  78. // - GETANSWER: We are looking for the answer to a primary query.
  79. // (The qname of the task should exactly match the qname of the
  80. // query.) If we have no match, the query has failed.
  81. //
  82. // - GETADDITIONAL: We are filling in additional data, either
  83. // as a result of finding NS or MX records via a GETANSWER
  84. // query task, or as a result of finding NS records when
  85. // getting authority-section data.
  86. //
  87. // - FOLLOWCNAME: We are looking for the target of a CNAME RR that
  88. // was found via a previous GETANSWER query task. If we have no
  89. // match, the query is still successful.
  90. //
  91. // (NOTE: It is only necessary to set a task state when pushing
  92. // tasks onto the query task queue, which in turn is only necessary
  93. // when it's uncertain which data source will be authoritative for the
  94. // data. That's why there is no GETAUTHORITY task state; when
  95. // processing an answer, either positive or negative, the authoritative
  96. // data source will already have been discovered, and can be queried
  97. // directly.)
  98. enum State {
  99. GETANSWER,
  100. GETADDITIONAL,
  101. FOLLOWCNAME
  102. } state;
  103. // Response flags to indicate conditions encountered while
  104. // processing this task.
  105. uint32_t flags;
  106. // Constructors
  107. QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
  108. const isc::dns::RRType& t, const isc::dns::Section& sect);
  109. QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
  110. const isc::dns::RRType& t, const isc::dns::Section& sect,
  111. Op o);
  112. QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
  113. const isc::dns::RRType& t, const isc::dns::Section& sect,
  114. const State st);
  115. QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
  116. const isc::dns::RRType& t, const isc::dns::Section& sect,
  117. Op o, State st);
  118. // These are special constructors for particular query task types,
  119. // to simplify the code.
  120. //
  121. // A simple query doesn't need to specify section or state.
  122. QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
  123. const isc::dns::RRType& t, Op o);
  124. // A referral query doesn't need to specify section, state, or type.
  125. QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c, Op o);
  126. // A glue (or noglue) query doesn't need to specify type.
  127. QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
  128. const isc::dns::Section& sect, Op o, State st);
  129. ~QueryTask();
  130. };
  131. typedef boost::shared_ptr<QueryTask> QueryTaskPtr;
  132. typedef std::queue<QueryTaskPtr> QueryTaskQueue;
  133. class Query;
  134. typedef boost::shared_ptr<Query> QueryPtr;
  135. // Data Source query
  136. class Query {
  137. public:
  138. // The state of a query: pending or answered.
  139. enum Status {
  140. PENDING,
  141. ANSWERED
  142. };
  143. ///
  144. /// \name Constructors, Assignment Operator and Destructor.
  145. ///
  146. /// Note: The copy constructor and the assignment operator are intentionally
  147. /// defined as private.
  148. //@{
  149. private:
  150. Query(const Query& source);
  151. Query& operator=(const Query& source);
  152. public:
  153. // Query constructor
  154. Query(isc::dns::Message& m, bool dnssec);
  155. /// \brief The destructor.
  156. virtual ~Query();
  157. //@}
  158. // wantAdditional() == true indicates that additional-section data
  159. // should be looked up while processing this query. false indicates
  160. // that we're only interested in answer-section data
  161. bool wantAdditional() { return want_additional_; }
  162. void setWantAdditional(bool d) { want_additional_ = d; }
  163. // wantDnssec() == true indicates that DNSSEC data should be retrieved
  164. // from the data source when this query is being processed
  165. bool wantDnssec() const { return want_dnssec_; }
  166. void setWantDnssec(bool d) { want_dnssec_ = d; }
  167. const isc::dns::Name& qname() const { return *qname_; }
  168. const isc::dns::RRClass& qclass() const { return *qclass_; }
  169. const isc::dns::RRType& qtype() const { return *qtype_; }
  170. // Note: these can't be constant member functions because they expose
  171. // writable 'handles' of internal member variables. It's questionable
  172. // whether we need these accessors in the first place because the
  173. // corresponding members are public (which itself is not a good practice
  174. // but it's a different topic), but at the moment we keep them.
  175. // We should definitely revisit the design later.
  176. isc::dns::Message& message() { return *message_; }
  177. QueryTaskQueue& tasks() { return querytasks_; }
  178. Status status() const { return status_; }
  179. void setStatus(Status s) { status_ = s; }
  180. // Limit CNAME chains to 16 per query, to avoid loops
  181. inline bool tooMany() {
  182. if (++restarts_ > MAX_RESTARTS) {
  183. return (true);
  184. }
  185. return (false);
  186. }
  187. private:
  188. Status status_;
  189. const isc::dns::Name* qname_;
  190. const isc::dns::RRClass* qclass_;
  191. const isc::dns::RRType* qtype_;
  192. isc::dns::Message* message_;
  193. QueryTaskQueue querytasks_;
  194. bool want_additional_;
  195. bool want_dnssec_;
  196. static const int MAX_RESTARTS = 16;
  197. int restarts_;
  198. };
  199. }
  200. }
  201. #endif
  202. // Local Variables:
  203. // mode: c++
  204. // End: