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