resolver_cache.cc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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. #include <config.h>
  15. #include "resolver_cache.h"
  16. #include "dns/message.h"
  17. #include "rrset_cache.h"
  18. #include "logger.h"
  19. #include <string>
  20. #include <algorithm>
  21. using namespace isc::dns;
  22. using namespace std;
  23. namespace isc {
  24. namespace cache {
  25. ResolverClassCache::ResolverClassCache(const RRClass& cache_class) :
  26. cache_class_(cache_class)
  27. {
  28. LOG_DEBUG(logger, DBG_TRACE_BASIC, CACHE_RESOLVER_INIT).arg(cache_class);
  29. local_zone_data_ = LocalZoneDataPtr(new LocalZoneData(cache_class_.getCode()));
  30. rrsets_cache_ = RRsetCachePtr(new RRsetCache(RRSET_CACHE_DEFAULT_SIZE,
  31. cache_class_.getCode()));
  32. // SOA rrset cache from negative response
  33. negative_soa_cache_ = RRsetCachePtr(new RRsetCache(NEGATIVE_RRSET_CACHE_DEFAULT_SIZE,
  34. cache_class_.getCode()));
  35. messages_cache_ = MessageCachePtr(new MessageCache(rrsets_cache_,
  36. MESSAGE_CACHE_DEFAULT_SIZE,
  37. cache_class_.getCode(),
  38. negative_soa_cache_));
  39. }
  40. ResolverClassCache::ResolverClassCache(const CacheSizeInfo& cache_info) :
  41. cache_class_(cache_info.cclass)
  42. {
  43. LOG_DEBUG(logger, DBG_TRACE_BASIC, CACHE_RESOLVER_INIT_INFO).
  44. arg(cache_class_);
  45. uint16_t klass = cache_class_.getCode();
  46. // TODO We should find one way to load local zone data.
  47. local_zone_data_ = LocalZoneDataPtr(new LocalZoneData(klass));
  48. rrsets_cache_ = RRsetCachePtr(new
  49. RRsetCache(cache_info.rrset_cache_size, klass));
  50. // SOA rrset cache from negative response
  51. negative_soa_cache_ = RRsetCachePtr(new RRsetCache(cache_info.rrset_cache_size,
  52. klass));
  53. messages_cache_ = MessageCachePtr(new MessageCache(rrsets_cache_,
  54. cache_info.message_cache_size,
  55. klass, negative_soa_cache_));
  56. }
  57. const RRClass&
  58. ResolverClassCache::getClass() const {
  59. return (cache_class_);
  60. }
  61. bool
  62. ResolverClassCache::lookup(const isc::dns::Name& qname,
  63. const isc::dns::RRType& qtype,
  64. isc::dns::Message& response) const
  65. {
  66. LOG_DEBUG(logger, DBG_TRACE_DATA, CACHE_RESOLVER_LOOKUP_MSG).
  67. arg(qname).arg(qtype);
  68. // message response should has question section already.
  69. if (response.beginQuestion() == response.endQuestion()) {
  70. LOG_ERROR(logger, CACHE_RESOLVER_NO_QUESTION).arg(qname).arg(qtype);
  71. isc_throw(MessageNoQuestionSection, "Message has no question section");
  72. }
  73. // First, query in local zone, if the rrset(qname, qtype, qclass) can be
  74. // found in local zone, generated reply message with only the rrset in
  75. // answer section.
  76. RRsetPtr rrset_ptr = local_zone_data_->lookup(qname, qtype);
  77. if (rrset_ptr) {
  78. LOG_DEBUG(logger, DBG_TRACE_DATA, CACHE_RESOLVER_LOCAL_MSG).
  79. arg(qname).arg(qtype);
  80. response.addRRset(Message::SECTION_ANSWER, rrset_ptr);
  81. return (true);
  82. }
  83. // Search in class-specific message cache.
  84. return (messages_cache_->lookup(qname, qtype, response));
  85. }
  86. isc::dns::RRsetPtr
  87. ResolverClassCache::lookup(const isc::dns::Name& qname,
  88. const isc::dns::RRType& qtype) const
  89. {
  90. LOG_DEBUG(logger, DBG_TRACE_DATA, CACHE_RESOLVER_LOOKUP_RRSET).
  91. arg(qname).arg(qtype);
  92. // Algorithm:
  93. // 1. Search in local zone data first,
  94. // 2. Then do search in rrsets_cache_.
  95. RRsetPtr rrset_ptr = local_zone_data_->lookup(qname, qtype);
  96. if (rrset_ptr) {
  97. LOG_DEBUG(logger, DBG_TRACE_DATA, CACHE_RESOLVER_LOCAL_RRSET).
  98. arg(qname).arg(qtype);
  99. return (rrset_ptr);
  100. } else {
  101. RRsetEntryPtr rrset_entry = rrsets_cache_->lookup(qname, qtype);
  102. if (rrset_entry) {
  103. return (rrset_entry->getRRset());
  104. } else {
  105. return (RRsetPtr());
  106. }
  107. }
  108. }
  109. bool
  110. ResolverClassCache::update(const isc::dns::Message& msg) {
  111. LOG_DEBUG(logger, DBG_TRACE_DATA, CACHE_RESOLVER_UPDATE_MSG).
  112. arg((*msg.beginQuestion())->getName()).
  113. arg((*msg.beginQuestion())->getType()).
  114. arg((*msg.beginQuestion())->getClass());
  115. return (messages_cache_->update(msg));
  116. }
  117. bool
  118. ResolverClassCache::updateRRsetCache(const isc::dns::ConstRRsetPtr& rrset_ptr,
  119. RRsetCachePtr rrset_cache_ptr)
  120. {
  121. RRsetTrustLevel level;
  122. if (rrset_ptr->getType() == RRType::A() ||
  123. rrset_ptr->getType() == RRType::AAAA()) {
  124. level = RRSET_TRUST_PRIM_GLUE;
  125. } else {
  126. level = RRSET_TRUST_PRIM_ZONE_NONGLUE;
  127. }
  128. rrset_cache_ptr->update((*rrset_ptr.get()), level);
  129. return (true);
  130. }
  131. bool
  132. ResolverClassCache::update(const isc::dns::ConstRRsetPtr& rrset_ptr) {
  133. LOG_DEBUG(logger, DBG_TRACE_DATA, CACHE_RESOLVER_UPDATE_RRSET).
  134. arg(rrset_ptr->getName()).arg(rrset_ptr->getType()).
  135. arg(rrset_ptr->getClass());
  136. // First update local zone, then update rrset cache.
  137. local_zone_data_->update((*rrset_ptr.get()));
  138. updateRRsetCache(rrset_ptr, rrsets_cache_);
  139. return (true);
  140. }
  141. ResolverCache::ResolverCache()
  142. {
  143. class_caches_.push_back(new ResolverClassCache(RRClass::IN()));
  144. }
  145. ResolverCache::ResolverCache(std::vector<CacheSizeInfo> caches_info)
  146. {
  147. for (std::vector<CacheSizeInfo>::size_type i = 0;
  148. i < caches_info.size(); ++i) {
  149. class_caches_.push_back(new ResolverClassCache(caches_info[i]));
  150. }
  151. }
  152. ResolverCache::~ResolverCache()
  153. {
  154. for (std::vector<ResolverClassCache*>::size_type i = 0;
  155. i < class_caches_.size(); ++i) {
  156. delete class_caches_[i];
  157. }
  158. }
  159. bool
  160. ResolverCache::lookup(const isc::dns::Name& qname,
  161. const isc::dns::RRType& qtype,
  162. const isc::dns::RRClass& qclass,
  163. isc::dns::Message& response) const
  164. {
  165. ResolverClassCache* cc = getClassCache(qclass);
  166. if (cc) {
  167. return (cc->lookup(qname, qtype, response));
  168. } else {
  169. LOG_DEBUG(logger, DBG_TRACE_DATA, CACHE_RESOLVER_UNKNOWN_CLASS_MSG).
  170. arg(qclass);
  171. return (false);
  172. }
  173. }
  174. isc::dns::RRsetPtr
  175. ResolverCache::lookup(const isc::dns::Name& qname,
  176. const isc::dns::RRType& qtype,
  177. const isc::dns::RRClass& qclass) const
  178. {
  179. ResolverClassCache* cc = getClassCache(qclass);
  180. if (cc) {
  181. return (cc->lookup(qname, qtype));
  182. } else {
  183. LOG_DEBUG(logger, DBG_TRACE_DATA, CACHE_RESOLVER_UNKNOWN_CLASS_RRSET).
  184. arg(qclass);
  185. return (RRsetPtr());
  186. }
  187. }
  188. isc::dns::RRsetPtr
  189. ResolverCache::lookupDeepestNS(const isc::dns::Name& qname,
  190. const isc::dns::RRClass& qclass) const
  191. {
  192. LOG_DEBUG(logger, DBG_TRACE_DATA, CACHE_RESOLVER_DEEPEST).arg(qname).
  193. arg(qclass);
  194. isc::dns::RRType qtype = RRType::NS();
  195. ResolverClassCache* cc = getClassCache(qclass);
  196. if (cc) {
  197. unsigned int count = qname.getLabelCount();
  198. unsigned int level = 0;
  199. while(level < count) {
  200. Name close_name = qname.split(level);
  201. RRsetPtr rrset_ptr = cc->lookup(close_name, qtype);
  202. if (rrset_ptr) {
  203. return (rrset_ptr);
  204. } else {
  205. ++level;
  206. }
  207. }
  208. }
  209. return (RRsetPtr());
  210. }
  211. bool
  212. ResolverCache::update(const isc::dns::Message& msg) {
  213. QuestionIterator iter = msg.beginQuestion();
  214. ResolverClassCache* cc = getClassCache((*iter)->getClass());
  215. if (cc) {
  216. return (cc->update(msg));
  217. } else {
  218. LOG_DEBUG(logger, DBG_TRACE_DATA,
  219. CACHE_RESOLVER_UPDATE_UNKNOWN_CLASS_MSG).
  220. arg((*msg.beginQuestion())->getClass());
  221. return (false);
  222. }
  223. }
  224. bool
  225. ResolverCache::update(const isc::dns::ConstRRsetPtr& rrset_ptr) {
  226. ResolverClassCache* cc = getClassCache(rrset_ptr->getClass());
  227. if (cc) {
  228. return (cc->update(rrset_ptr));
  229. } else {
  230. LOG_DEBUG(logger, DBG_TRACE_DATA,
  231. CACHE_RESOLVER_UPDATE_UNKNOWN_CLASS_RRSET).
  232. arg(rrset_ptr->getClass());
  233. return (false);
  234. }
  235. }
  236. ResolverClassCache*
  237. ResolverCache::getClassCache(const isc::dns::RRClass& cache_class) const {
  238. for (std::vector<ResolverClassCache*>::size_type i = 0;
  239. i < class_caches_.size(); ++i) {
  240. if (class_caches_[i]->getClass() == cache_class) {
  241. return (class_caches_[i]);
  242. }
  243. }
  244. return (NULL);
  245. }
  246. } // namespace cache
  247. } // namespace isc