query.h 8.7 KB

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