query.h 8.2 KB

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