query.h 8.6 KB

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