]>
Commit | Line | Data |
---|---|---|
870a0fe4 AT |
1 | #ifdef HAVE_CONFIG_H |
2 | #include "config.h" | |
3 | #endif | |
6b68a4e3 RG |
4 | |
5 | #include <cinttypes> | |
6 | ||
eec1087c BH |
7 | #include "recursor_cache.hh" |
8 | #include "misc.hh" | |
9 | #include <iostream> | |
ea634573 | 10 | #include "dnsrecords.hh" |
bec87d21 | 11 | #include "arguments.hh" |
0ba0f794 | 12 | #include "syncres.hh" |
34264879 | 13 | #include "recursor_cache.hh" |
38c9ceaa | 14 | #include "cachecleaner.hh" |
61b26744 | 15 | #include "namespaces.hh" |
eec1087c | 16 | |
eec1087c BH |
17 | unsigned int MemRecursorCache::size() |
18 | { | |
705f31ae | 19 | return (unsigned int)d_cache.size(); |
43a2b29c BH |
20 | } |
21 | ||
8e42d27d | 22 | // this function is too slow to poll! |
43a2b29c BH |
23 | unsigned int MemRecursorCache::bytes() |
24 | { | |
25 | unsigned int ret=0; | |
26 | ||
27 | for(cache_t::const_iterator i=d_cache.begin(); i!=d_cache.end(); ++i) { | |
9e5ed2e4 | 28 | ret+=sizeof(struct CacheEntry); |
c5c066bf | 29 | ret+=(unsigned int)i->d_qname.toString().length(); |
e325f20c | 30 | for(auto j=i->d_records.begin(); j!= i->d_records.end(); ++j) |
31 | ret+= sizeof(*j); // XXX WRONG we don't know the stored size! j->size(); | |
43a2b29c BH |
32 | } |
33 | return ret; | |
eec1087c BH |
34 | } |
35 | ||
e74f866a RG |
36 | int32_t MemRecursorCache::handleHit(cache_t::iterator entry, const DNSName& qname, const ComboAddress& who, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, vState* state, bool* wasAuth) |
37 | { | |
38 | int32_t ttd = entry->d_ttd; | |
39 | ||
40 | if(variable && !entry->d_netmask.empty()) { | |
41 | *variable = true; | |
42 | } | |
43 | ||
44 | // cerr<<"Looking at "<<entry->d_records.size()<<" records for this name"<<endl; | |
45 | if (res) { | |
46 | for(const auto& k : entry->d_records) { | |
47 | DNSRecord dr; | |
48 | dr.d_name = qname; | |
49 | dr.d_type = entry->d_qtype; | |
50 | dr.d_class = QClass::IN; | |
51 | dr.d_content = k; | |
52 | dr.d_ttl = static_cast<uint32_t>(entry->d_ttd); | |
53 | dr.d_place = DNSResourceRecord::ANSWER; | |
54 | res->push_back(dr); | |
55 | } | |
56 | } | |
57 | ||
58 | if(signatures) { // if you do an ANY lookup you are hosed XXXX | |
59 | *signatures = entry->d_signatures; | |
60 | } | |
61 | ||
62 | if(authorityRecs) { | |
63 | *authorityRecs = entry->d_authorityRecs; | |
64 | } | |
65 | ||
66 | if (state) { | |
67 | *state = entry->d_state; | |
68 | } | |
69 | ||
70 | if (wasAuth) { | |
71 | *wasAuth = entry->d_auth; | |
72 | } | |
73 | ||
74 | moveCacheItemToBack(d_cache, entry); | |
75 | ||
76 | return ttd; | |
77 | } | |
78 | ||
b0274132 | 79 | MemRecursorCache::cache_t::const_iterator MemRecursorCache::getEntryUsingECSIndex(time_t now, const DNSName &qname, uint16_t qtype, bool requireAuth, const ComboAddress& who) |
e74f866a | 80 | { |
b0274132 RG |
81 | auto ecsIndexKey = tie(qname, qtype); |
82 | auto ecsIndex = d_ecsIndex.find(ecsIndexKey); | |
83 | if (ecsIndex != d_ecsIndex.end() && !ecsIndex->isEmpty()) { | |
e74f866a RG |
84 | /* we have netmask-specific entries, let's see if we match one */ |
85 | while (true) { | |
b0274132 | 86 | const Netmask best = ecsIndex->lookupBestMatch(who); |
e74f866a RG |
87 | if (best.empty()) { |
88 | /* we have nothing more specific for you */ | |
89 | break; | |
90 | } | |
91 | ||
92 | auto key = boost::make_tuple(qname, qtype, best); | |
93 | auto entry = d_cache.find(key); | |
94 | if (entry == d_cache.end()) { | |
b0274132 RG |
95 | /* ecsIndex is not up-to-date */ |
96 | ecsIndex->removeNetmask(best); | |
97 | if (ecsIndex->isEmpty()) { | |
98 | d_ecsIndex.erase(ecsIndex); | |
e74f866a RG |
99 | break; |
100 | } | |
101 | continue; | |
102 | } | |
103 | ||
104 | if (entry->d_ttd > now) { | |
105 | if (!requireAuth || entry->d_auth) { | |
106 | return entry; | |
107 | } | |
108 | } | |
109 | else { | |
110 | /* this netmask-specific entry has expired */ | |
111 | moveCacheItemToFront(d_cache, entry); | |
b0274132 RG |
112 | ecsIndex->removeNetmask(best); |
113 | if (ecsIndex->isEmpty()) { | |
114 | d_ecsIndex.erase(ecsIndex); | |
e74f866a RG |
115 | break; |
116 | } | |
117 | } | |
118 | } | |
119 | } | |
120 | ||
121 | /* we have nothing specific, let's see if we have a generic one */ | |
122 | auto key = boost::make_tuple(qname, qtype, Netmask()); | |
123 | auto entry = d_cache.find(key); | |
124 | if (entry != d_cache.end()) { | |
125 | if (entry->d_ttd > now) { | |
126 | if (!requireAuth || entry->d_auth) { | |
127 | return entry; | |
128 | } | |
129 | } | |
130 | else { | |
131 | moveCacheItemToFront(d_cache, entry); | |
132 | } | |
133 | } | |
134 | ||
135 | /* nothing for you, sorry */ | |
136 | return d_cache.end(); | |
137 | } | |
138 | ||
d0cd0376 | 139 | // returns -1 for no hits |
787737ae | 140 | std::pair<MemRecursorCache::cache_t::const_iterator, MemRecursorCache::cache_t::const_iterator> MemRecursorCache::getEntries(const DNSName &qname, const QType& qt) |
eec1087c | 141 | { |
e325f20c | 142 | // cerr<<"looking up "<< qname<<"|"+qt.getName()<<"\n"; |
e325f20c | 143 | if(!d_cachecachevalid || d_cachedqname!= qname) { |
b0c3b7d8 BH |
144 | // cerr<<"had cache cache miss"<<endl; |
145 | d_cachedqname=qname; | |
146 | d_cachecache=d_cache.equal_range(tie(qname)); | |
147 | d_cachecachevalid=true; | |
cf98aa40 | 148 | } |
e325f20c | 149 | // else cerr<<"had cache cache hit!"<<endl; |
748eff9f | 150 | |
787737ae RG |
151 | return d_cachecache; |
152 | } | |
153 | ||
e74f866a | 154 | bool MemRecursorCache::entryMatches(cache_t::const_iterator& entry, uint16_t qt, bool requireAuth, const ComboAddress& who) |
787737ae RG |
155 | { |
156 | if (requireAuth && !entry->d_auth) | |
157 | return false; | |
158 | ||
e74f866a RG |
159 | return ((entry->d_qtype == qt || qt == QType::ANY || |
160 | (qt == QType::ADDR && (entry->d_qtype == QType::A || entry->d_qtype == QType::AAAA))) | |
787737ae RG |
161 | && (entry->d_netmask.empty() || entry->d_netmask.match(who))); |
162 | } | |
163 | ||
164 | // returns -1 for no hits | |
165 | int32_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, bool requireAuth, vector<DNSRecord>* res, const ComboAddress& who, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, vState* state, bool* wasAuth) | |
166 | { | |
167 | time_t ttd=0; | |
168 | // cerr<<"looking up "<< qname<<"|"+qt.getName()<<"\n"; | |
e74f866a RG |
169 | if(res) { |
170 | res->clear(); | |
171 | } | |
787737ae | 172 | |
e74f866a RG |
173 | const uint16_t qtype = qt.getCode(); |
174 | /* If we don't have any netmask-specific entries at all, let's just skip this | |
175 | to be able to use the nice d_cachecache hack. */ | |
b0274132 | 176 | if (qtype != QType::ANY && !d_ecsIndex.empty()) { |
e74f866a RG |
177 | if (qtype == QType::ADDR) { |
178 | int32_t ret = -1; | |
787737ae | 179 | |
b0274132 | 180 | auto entryA = getEntryUsingECSIndex(now, qname, QType::A, requireAuth, who); |
e74f866a RG |
181 | if (entryA != d_cache.end()) { |
182 | ret = handleHit(entryA, qname, who, res, signatures, authorityRecs, variable, state, wasAuth); | |
183 | } | |
b0274132 | 184 | auto entryAAAA = getEntryUsingECSIndex(now, qname, QType::AAAA, requireAuth, who); |
e74f866a RG |
185 | if (entryAAAA != d_cache.end()) { |
186 | int32_t ttdAAAA = handleHit(entryA, qname, who, res, signatures, authorityRecs, variable, state, wasAuth); | |
187 | if (ret > 0) { | |
188 | ret = std::min(ret, ttdAAAA); | |
189 | } else { | |
190 | ret = ttdAAAA; | |
191 | } | |
192 | } | |
193 | return ret > 0 ? static_cast<int32_t>(ret-now) : ret; | |
194 | } | |
195 | else { | |
b0274132 | 196 | auto entry = getEntryUsingECSIndex(now, qname, qtype, requireAuth, who); |
e74f866a RG |
197 | if (entry != d_cache.end()) { |
198 | return static_cast<int32_t>(handleHit(entry, qname, who, res, signatures, authorityRecs, variable, state, wasAuth) - now); | |
199 | } | |
200 | return -1; | |
201 | } | |
202 | } | |
203 | ||
204 | auto entries = getEntries(qname, qt); | |
ea634573 | 205 | |
787737ae RG |
206 | if(entries.first!=entries.second) { |
207 | for(cache_t::const_iterator i=entries.first; i != entries.second; ++i) { | |
208 | ||
209 | if (i->d_ttd <= now) { | |
210 | moveCacheItemToFront(d_cache, i); | |
24bb9b58 | 211 | continue; |
787737ae | 212 | } |
24bb9b58 | 213 | |
e74f866a | 214 | if (!entryMatches(i, qtype, requireAuth, who)) |
787737ae RG |
215 | continue; |
216 | ||
e74f866a | 217 | ttd = handleHit(i, qname, who, res, signatures, authorityRecs, variable, state, wasAuth); |
787737ae RG |
218 | |
219 | if(qt.getCode()!=QType::ANY && qt.getCode()!=QType::ADDR) // normally if we have a hit, we are done | |
220 | break; | |
24bb9b58 | 221 | } |
b0d4fb45 | 222 | |
4d2be65d | 223 | // cerr<<"time left : "<<ttd - now<<", "<< (res ? res->size() : 0) <<"\n"; |
6b68a4e3 | 224 | return static_cast<int32_t>(ttd-now); |
eec1087c | 225 | } |
eec1087c BH |
226 | return -1; |
227 | } | |
34264879 | 228 | |
e325f20c | 229 | bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const vector<DNSRecord>& content, const CacheEntry& stored) |
f9f2ae96 BH |
230 | { |
231 | if(!stored.d_auth) { | |
09a6f097 | 232 | //~ cerr<<"feel free to scribble non-auth data!"<<endl; |
f9f2ae96 BH |
233 | return false; |
234 | } | |
235 | ||
236 | if(qt.getCode()!=QType::NS) { | |
09a6f097 | 237 | //~ cerr<<"Not NS record"<<endl; |
f9f2ae96 BH |
238 | return false; |
239 | } | |
240 | if(content.size()!=stored.d_records.size()) { | |
09a6f097 | 241 | //~ cerr<<"Not equal number of records"<<endl; |
f9f2ae96 BH |
242 | return false; |
243 | } | |
244 | if(stored.d_records.empty()) | |
245 | return false; | |
246 | ||
e325f20c | 247 | if(stored.d_ttd > content.begin()->d_ttl) { |
09a6f097 | 248 | //~ cerr<<"attempt to LOWER TTL - fine by us"<<endl; |
f9f2ae96 BH |
249 | return false; |
250 | } | |
251 | ||
252 | ||
74191fb7 | 253 | // cerr<<"Returning true - update attempt!\n"; |
f9f2ae96 BH |
254 | return true; |
255 | } | |
256 | ||
e74f866a | 257 | void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt, const vector<DNSRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs, bool auth, boost::optional<Netmask> ednsmask, vState state) |
eec1087c | 258 | { |
e74f866a RG |
259 | d_cachecachevalid = false; |
260 | ||
261 | auto key = boost::make_tuple(qname, qt.getCode(), ednsmask ? *ednsmask : Netmask()); | |
a072ce44 | 262 | bool isNew = false; |
e74f866a RG |
263 | cache_t::iterator stored = d_cache.find(key); |
264 | if (stored == d_cache.end()) { | |
265 | stored = d_cache.insert(CacheEntry(key, CacheEntry::records_t(), auth)).first; | |
a072ce44 | 266 | isNew = true; |
e74f866a | 267 | |
b0274132 | 268 | /* don't bother building an ecsIndex if we don't have any netmask-specific entries */ |
e74f866a | 269 | if (ednsmask && !ednsmask->empty()) { |
b0274132 RG |
270 | auto ecsIndexKey = boost::make_tuple(qname, qt.getCode()); |
271 | auto ecsIndex = d_ecsIndex.find(ecsIndexKey); | |
272 | if (ecsIndex == d_ecsIndex.end()) { | |
273 | ecsIndex = d_ecsIndex.insert(ECSIndexEntry(qname, qt.getCode())).first; | |
e74f866a | 274 | } |
b0274132 | 275 | ecsIndex->addMask(*ednsmask); |
e74f866a | 276 | } |
6c674e9a | 277 | } |
278 | ||
6b68a4e3 | 279 | time_t maxTTD=std::numeric_limits<time_t>::max(); |
d0cd0376 | 280 | CacheEntry ce=*stored; // this is a COPY |
e325f20c | 281 | ce.d_qtype=qt.getCode(); |
57769f13 | 282 | ce.d_signatures=signatures; |
2b984251 | 283 | ce.d_authorityRecs=authorityRecs; |
4d2be65d | 284 | ce.d_state=state; |
fbb356b6 | 285 | |
d0cd0376 | 286 | // cerr<<"asked to store "<< (qname.empty() ? "EMPTY" : qname.toString()) <<"|"+qt.getName()<<" -> '"; |
287 | // cerr<<(content.empty() ? string("EMPTY CONTENT") : content.begin()->d_content->getZoneRepresentation())<<"', auth="<<auth<<", ce.auth="<<ce.d_auth; | |
4d2be65d | 288 | // cerr<<", ednsmask: " << (ednsmask ? ednsmask->toString() : "none") <<endl; |
a85eb653 BH |
289 | |
290 | if(!auth && ce.d_auth) { // unauth data came in, we have some auth data, but is it fresh? | |
e325f20c | 291 | if(ce.d_ttd > now) { // we still have valid data, ignore unauth data |
bf4ab707 | 292 | // cerr<<"\tStill hold valid auth data, and the new data is unauth, return\n"; |
a85eb653 | 293 | return; |
609a76b3 BH |
294 | } |
295 | else { | |
296 | ce.d_auth = false; // new data won't be auth | |
297 | } | |
a85eb653 | 298 | } |
d0cd0376 | 299 | ce.d_records.clear(); |
300 | ||
fbb356b6 | 301 | // limit TTL of auth->auth NSset update if needed, except for root |
302 | if(ce.d_auth && auth && qt.getCode()==QType::NS && !isNew && !qname.isRoot()) { | |
303 | // cerr<<"\tLimiting TTL of auth->auth NS set replace to "<<ce.d_ttd<<endl; | |
e325f20c | 304 | maxTTD = ce.d_ttd; |
fc202159 PD |
305 | } |
306 | ||
74191fb7 | 307 | // make sure that we CAN refresh the root |
6c674e9a | 308 | if(auth && (qname.isRoot() || !attemptToRefreshNSTTL(qt, content, ce) ) ) { |
fc202159 | 309 | // cerr<<"\tGot auth data, and it was not refresh attempt of an unchanged NS set, nuking storage"<<endl; |
34264879 BH |
310 | ce.d_records.clear(); // clear non-auth data |
311 | ce.d_auth = true; | |
34264879 | 312 | } |
4d2be65d | 313 | //else cerr<<"\tNot nuking"<<endl; |
09a6f097 | 314 | |
6196f908 | 315 | |
e74f866a | 316 | for(const auto i : content) { |
6b68a4e3 RG |
317 | /* Yes, we have altered the d_ttl value by adding time(nullptr) to it |
318 | prior to calling this function, so the TTL actually holds a TTD. */ | |
e74f866a RG |
319 | ce.d_ttd=min(maxTTD, static_cast<time_t>(i.d_ttl)); // XXX this does weird things if TTLs differ in the set |
320 | // cerr<<"To store: "<<i.d_content->getZoneRepresentation()<<" with ttl/ttd "<<i.d_ttl<<", capped at: "<<maxTTD<<endl; | |
321 | ce.d_records.push_back(i.d_content); | |
376effcf | 322 | // there was code here that did things with TTL and auth. Unsure if it was good. XXX |
ea634573 | 323 | } |
bf4ab707 | 324 | |
a072ce44 RG |
325 | if (!isNew) { |
326 | moveCacheItemToBack(d_cache, stored); | |
327 | } | |
ca0b5def | 328 | d_cache.replace(stored, ce); |
eec1087c | 329 | } |
92294b60 | 330 | |
86f3ca51 | 331 | int MemRecursorCache::doWipeCache(const DNSName& name, bool sub, uint16_t qtype) |
748eff9f | 332 | { |
85c143a2 | 333 | int count=0; |
7e6139ba | 334 | d_cachecachevalid=false; |
1ef00ba1 | 335 | pair<cache_t::iterator, cache_t::iterator> range; |
1ef00ba1 | 336 | |
86f3ca51 | 337 | if(!sub) { |
b0274132 | 338 | pair<ecsIndex_t::iterator, ecsIndex_t::iterator> ecsIndexRange; |
e74f866a RG |
339 | if(qtype==0xffff) { |
340 | range = d_cache.equal_range(tie(name)); | |
b0274132 | 341 | ecsIndexRange = d_ecsIndex.equal_range(tie(name)); |
e74f866a RG |
342 | } |
343 | else { | |
86f3ca51 | 344 | range=d_cache.equal_range(tie(name, qtype)); |
b0274132 | 345 | ecsIndexRange = d_ecsIndex.equal_range(tie(name, qtype)); |
e74f866a | 346 | } |
86f3ca51 | 347 | for(cache_t::const_iterator i=range.first; i != range.second; ) { |
348 | count++; | |
349 | d_cache.erase(i++); | |
350 | } | |
b0274132 RG |
351 | for(auto i = ecsIndexRange.first; i != ecsIndexRange.second; ) { |
352 | d_ecsIndex.erase(i++); | |
e74f866a | 353 | } |
86f3ca51 | 354 | } |
355 | else { | |
356 | for(auto iter = d_cache.lower_bound(tie(name)); iter != d_cache.end(); ) { | |
357 | if(!iter->d_qname.isPartOf(name)) | |
358 | break; | |
359 | if(iter->d_qtype == qtype || qtype == 0xffff) { | |
360 | count++; | |
361 | d_cache.erase(iter++); | |
362 | } | |
363 | else | |
364 | iter++; | |
365 | } | |
b0274132 | 366 | for(auto iter = d_ecsIndex.lower_bound(tie(name)); iter != d_ecsIndex.end(); ) { |
e74f866a RG |
367 | if(!iter->d_qname.isPartOf(name)) |
368 | break; | |
369 | if(iter->d_qtype == qtype || qtype == 0xffff) { | |
b0274132 | 370 | d_ecsIndex.erase(iter++); |
e74f866a RG |
371 | } |
372 | else { | |
373 | iter++; | |
374 | } | |
375 | } | |
85c143a2 BH |
376 | } |
377 | return count; | |
748eff9f | 378 | } |
92294b60 | 379 | |
6b68a4e3 | 380 | bool MemRecursorCache::doAgeCache(time_t now, const DNSName& name, uint16_t qtype, uint32_t newTTL) |
a2b4f72f BH |
381 | { |
382 | cache_t::iterator iter = d_cache.find(tie(name, qtype)); | |
e06f9f15 | 383 | if(iter == d_cache.end()) { |
a2b4f72f | 384 | return false; |
e06f9f15 PD |
385 | } |
386 | ||
387 | CacheEntry ce = *iter; | |
6b68a4e3 | 388 | if(ce.d_ttd < now) |
a2b4f72f BH |
389 | return false; // would be dead anyhow |
390 | ||
6b68a4e3 | 391 | uint32_t maxTTL = static_cast<uint32_t>(ce.d_ttd - now); |
e06f9f15 | 392 | if(maxTTL > newTTL) { |
a2b4f72f BH |
393 | d_cachecachevalid=false; |
394 | ||
6b68a4e3 | 395 | time_t newTTD = now + newTTL; |
3ddb9247 | 396 | |
e325f20c | 397 | |
398 | if(ce.d_ttd > newTTD) // do never renew expired or older TTLs | |
399 | ce.d_ttd = newTTD; | |
400 | ||
3ddb9247 | 401 | |
a2b4f72f BH |
402 | d_cache.replace(iter, ce); |
403 | return true; | |
404 | } | |
405 | return false; | |
406 | } | |
407 | ||
e74f866a | 408 | bool MemRecursorCache::updateValidationStatus(time_t now, const DNSName &qname, const QType& qt, const ComboAddress& who, bool requireAuth, vState newState) |
787737ae RG |
409 | { |
410 | bool updated = false; | |
e74f866a | 411 | uint16_t qtype = qt.getCode(); |
b0274132 RG |
412 | if (qtype != QType::ANY && qtype != QType::ADDR && !d_ecsIndex.empty()) { |
413 | auto entry = getEntryUsingECSIndex(now, qname, qtype, requireAuth, who); | |
e74f866a RG |
414 | if (entry == d_cache.end()) { |
415 | return false; | |
416 | } | |
417 | ||
418 | entry->d_state = newState; | |
419 | return true; | |
420 | } | |
421 | ||
787737ae RG |
422 | auto entries = getEntries(qname, qt); |
423 | ||
424 | for(auto i = entries.first; i != entries.second; ++i) { | |
e74f866a | 425 | if (!entryMatches(i, qtype, requireAuth, who)) |
787737ae RG |
426 | continue; |
427 | ||
428 | i->d_state = newState; | |
429 | updated = true; | |
430 | ||
e74f866a | 431 | if(qtype != QType::ANY && qtype != QType::ADDR) // normally if we have a hit, we are done |
787737ae | 432 | break; |
787737ae RG |
433 | } |
434 | ||
435 | return updated; | |
436 | } | |
437 | ||
d7948528 | 438 | uint64_t MemRecursorCache::doDump(int fd) |
748eff9f | 439 | { |
d7948528 BH |
440 | FILE* fp=fdopen(dup(fd), "w"); |
441 | if(!fp) { // dup probably failed | |
442 | return 0; | |
748eff9f | 443 | } |
fd2d69bb | 444 | fprintf(fp, "; main record cache dump from thread follows\n;\n"); |
d23f82f7 | 445 | const auto& sidx=d_cache.get<1>(); |
bec87d21 | 446 | |
d7948528 | 447 | uint64_t count=0; |
748eff9f | 448 | time_t now=time(0); |
e74f866a RG |
449 | for(const auto i : sidx) { |
450 | for(const auto j : i.d_records) { | |
d7948528 | 451 | count++; |
4327eadf | 452 | try { |
ea9831c0 | 453 | fprintf(fp, "%s %" PRId64 " IN %s %s ; (%s) auth=%i %s\n", i.d_qname.toString().c_str(), static_cast<int64_t>(i.d_ttd - now), DNSRecordContent::NumberToType(i.d_qtype).c_str(), j->getZoneRepresentation().c_str(), vStates[i.d_state], i.d_auth, i.d_netmask.empty() ? "" : i.d_netmask.toString().c_str()); |
4327eadf BH |
454 | } |
455 | catch(...) { | |
e74f866a | 456 | fprintf(fp, "; error printing '%s'\n", i.d_qname.empty() ? "EMPTY" : i.d_qname.toString().c_str()); |
4327eadf | 457 | } |
748eff9f | 458 | } |
d50e9bc8 PL |
459 | for(const auto &sig : i.d_signatures) { |
460 | count++; | |
461 | try { | |
462 | fprintf(fp, "%s %" PRId64 " IN RRSIG %s ; %s\n", i.d_qname.toString().c_str(), static_cast<int64_t>(i.d_ttd - now), sig->getZoneRepresentation().c_str(), i.d_netmask.empty() ? "" : i.d_netmask.toString().c_str()); | |
463 | } | |
464 | catch(...) { | |
465 | fprintf(fp, "; error printing '%s'\n", i.d_qname.empty() ? "EMPTY" : i.d_qname.toString().c_str()); | |
466 | } | |
467 | } | |
748eff9f BH |
468 | } |
469 | fclose(fp); | |
d7948528 | 470 | return count; |
748eff9f | 471 | } |
43a2b29c | 472 | |
c68ae9fa | 473 | void MemRecursorCache::doPrune(unsigned int keep) |
eec1087c | 474 | { |
cf98aa40 | 475 | d_cachecachevalid=false; |
43a2b29c | 476 | |
c68ae9fa RG |
477 | pruneCollection(*this, d_cache, keep); |
478 | } | |
479 | ||
480 | void MemRecursorCache::doPrune(void) | |
481 | { | |
c3828c03 | 482 | unsigned int maxCached=::arg().asNum("max-cache-entries") / g_numThreads; |
c68ae9fa | 483 | doPrune(maxCached); |
eec1087c | 484 | } |