resolver_cache.cc 7.1 KB

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