]>
Commit | Line | Data |
---|---|---|
12471842 PL |
1 | /* |
2 | * This file is part of PowerDNS or dnsdist. | |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
32cdc494 | 22 | #pragma once |
00a19ff7 | 23 | #include <string> |
aebb81e4 | 24 | #include <atomic> |
3897b9e1 | 25 | #include "utility.hh" |
00a19ff7 BH |
26 | #include "dns.hh" |
27 | #include "qtype.hh" | |
28 | #include <vector> | |
29 | #include <set> | |
9ea28e46 | 30 | #include <unordered_set> |
00a19ff7 | 31 | #include <map> |
eefd15f9 BH |
32 | #include <cmath> |
33 | #include <iostream> | |
34 | #include <utility> | |
c836dc19 | 35 | #include "misc.hh" |
00a19ff7 | 36 | #include "lwres.hh" |
4898a348 | 37 | #include <boost/optional.hpp> |
92011b8f | 38 | #include <boost/circular_buffer.hpp> |
d6d5dea7 | 39 | #include <boost/utility.hpp> |
1d5b3ce6 | 40 | #include "sstuff.hh" |
9fdf67d5 | 41 | #include "recursor_cache.hh" |
16beeaa4 | 42 | #include "recpacketcache.hh" |
1d5b3ce6 | 43 | #include <boost/tuple/tuple.hpp> |
71dea98d | 44 | #include <boost/optional.hpp> |
1d5b3ce6 BH |
45 | #include <boost/tuple/tuple_comparison.hpp> |
46 | #include "mtasker.hh" | |
a9af3782 | 47 | #include "iputils.hh" |
849fe8d2 | 48 | #include "validate.hh" |
b40562da | 49 | #include "ednssubnet.hh" |
644dd1da | 50 | #include "filterpo.hh" |
39ce10b2 | 51 | #include "negcache.hh" |
644dd1da | 52 | |
20642494 | 53 | #ifdef HAVE_CONFIG_H |
4898a348 | 54 | #include "config.h" |
20642494 PL |
55 | #endif |
56 | ||
4898a348 RG |
57 | #ifdef HAVE_PROTOBUF |
58 | #include <boost/uuid/uuid.hpp> | |
4898a348 RG |
59 | #endif |
60 | ||
a3e7b735 | 61 | class RecursorLua4; |
620db2c8 | 62 | |
fa1b87ff PL |
63 | typedef map< |
64 | DNSName, | |
65 | pair< | |
66 | vector<ComboAddress>, | |
67 | bool | |
68 | > | |
69 | > NsSet; | |
49f076e8 | 70 | |
bb4bdbaf | 71 | template<class Thing> class Throttle : public boost::noncopyable |
49f076e8 BH |
72 | { |
73 | public: | |
3cbe2773 | 74 | Throttle() : d_limit(3), d_ttl(60), d_last_clean(time(nullptr)) |
49f076e8 | 75 | { |
49f076e8 | 76 | } |
96e2f64f | 77 | |
78 | struct entry | |
79 | { | |
80 | time_t ttd; | |
81 | unsigned int count; | |
82 | }; | |
83 | typedef map<Thing,entry> cont_t; | |
84 | ||
87da00e7 | 85 | bool shouldThrottle(time_t now, const Thing& t) |
49f076e8 | 86 | { |
cd7bf56b | 87 | if(now > d_last_clean + 300 ) { |
bb4bdbaf | 88 | |
49f076e8 | 89 | d_last_clean=now; |
594c2ee7 | 90 | for(typename cont_t::iterator i=d_cont.begin();i!=d_cont.end();) { |
4957a608 BH |
91 | if( i->second.ttd < now) { |
92 | d_cont.erase(i++); | |
93 | } | |
94 | else | |
95 | ++i; | |
594c2ee7 | 96 | } |
49f076e8 BH |
97 | } |
98 | ||
49f076e8 BH |
99 | typename cont_t::iterator i=d_cont.find(t); |
100 | if(i==d_cont.end()) | |
101 | return false; | |
ccb07d93 | 102 | if(now > i->second.ttd || i->second.count == 0) { |
49f076e8 | 103 | d_cont.erase(i); |
139c2911 | 104 | return false; |
49f076e8 | 105 | } |
ccb07d93 | 106 | i->second.count--; |
014c60c3 BH |
107 | |
108 | return true; // still listed, still blocked | |
49f076e8 | 109 | } |
3ddb9247 | 110 | void throttle(time_t now, const Thing& t, time_t ttl=0, unsigned int tries=0) |
49f076e8 BH |
111 | { |
112 | typename cont_t::iterator i=d_cont.find(t); | |
87da00e7 | 113 | entry e={ now+(ttl ? ttl : d_ttl), tries ? tries : d_limit}; |
49f076e8 | 114 | |
c214232f | 115 | if(i==d_cont.end()) { |
49f076e8 | 116 | d_cont[t]=e; |
3ddb9247 PD |
117 | } |
118 | else if(i->second.ttd > e.ttd || (i->second.count) < e.count) | |
c214232f | 119 | d_cont[t]=e; |
8a5602d4 | 120 | } |
3ddb9247 | 121 | |
30ee601a | 122 | unsigned int size() const |
8a5602d4 | 123 | { |
705f31ae | 124 | return (unsigned int)d_cont.size(); |
49f076e8 | 125 | } |
30ee601a | 126 | |
96e2f64f | 127 | const cont_t& getThrottleMap() const |
128 | { | |
129 | return d_cont; | |
c1e20fba | 130 | } |
131 | ||
30ee601a RG |
132 | void clear() |
133 | { | |
134 | d_cont.clear(); | |
135 | } | |
c1e20fba | 136 | |
49f076e8 | 137 | private: |
b747bce8 AT |
138 | unsigned int d_limit; |
139 | time_t d_ttl; | |
49f076e8 | 140 | time_t d_last_clean; |
49f076e8 BH |
141 | cont_t d_cont; |
142 | }; | |
143 | ||
144 | ||
eefd15f9 | 145 | /** Class that implements a decaying EWMA. |
36c5ee42 | 146 | This class keeps an exponentially weighted moving average which, additionally, decays over time. |
eefd15f9 BH |
147 | The decaying is only done on get. |
148 | */ | |
149 | class DecayingEwma | |
150 | { | |
151 | public: | |
3ddb9247 | 152 | DecayingEwma() : d_val(0.0) |
71dea98d BH |
153 | { |
154 | d_needinit=true; | |
118dcc93 | 155 | d_last.tv_sec = d_last.tv_usec = 0; |
71dea98d | 156 | d_lastget=d_last; |
36c5ee42 | 157 | } |
d6d5dea7 | 158 | |
71dea98d | 159 | DecayingEwma(const DecayingEwma& orig) : d_last(orig.d_last), d_lastget(orig.d_lastget), d_val(orig.d_val), d_needinit(orig.d_needinit) |
eefd15f9 | 160 | { |
71dea98d | 161 | } |
d6d5dea7 | 162 | |
a712cb56 | 163 | void submit(int val, const struct timeval* tv) |
71dea98d | 164 | { |
a712cb56 | 165 | struct timeval now=*tv; |
71dea98d BH |
166 | |
167 | if(d_needinit) { | |
168 | d_last=now; | |
21f0f88b | 169 | d_lastget=now; |
71dea98d | 170 | d_needinit=false; |
21f0f88b | 171 | d_val = val; |
71dea98d | 172 | } |
21f0f88b BH |
173 | else { |
174 | float diff= makeFloat(d_last - now); | |
71dea98d | 175 | |
21f0f88b BH |
176 | d_last=now; |
177 | double factor=exp(diff)/2.0; // might be '0.5', or 0.0001 | |
3ddb9247 | 178 | d_val=(float)((1-factor)*val+ (float)factor*d_val); |
21f0f88b | 179 | } |
eefd15f9 | 180 | } |
d6d5dea7 | 181 | |
a712cb56 | 182 | double get(const struct timeval* tv) |
71dea98d | 183 | { |
a712cb56 | 184 | struct timeval now=*tv; |
71dea98d | 185 | float diff=makeFloat(d_lastget-now); |
36c5ee42 | 186 | d_lastget=now; |
705f31ae | 187 | float factor=exp(diff/60.0f); // is 1.0 or less |
eefd15f9 BH |
188 | return d_val*=factor; |
189 | } | |
190 | ||
30ee601a | 191 | double peek(void) const |
a82ce718 PD |
192 | { |
193 | return d_val; | |
194 | } | |
195 | ||
996c89cc | 196 | bool stale(time_t limit) const |
9fdf67d5 | 197 | { |
71dea98d | 198 | return limit > d_lastget.tv_sec; |
9fdf67d5 BH |
199 | } |
200 | ||
eefd15f9 | 201 | private: |
71dea98d BH |
202 | struct timeval d_last; // stores time |
203 | struct timeval d_lastget; // stores time | |
204 | float d_val; | |
205 | bool d_needinit; | |
206 | }; | |
207 | ||
628e2c7b PA |
208 | template<class Thing> class Counters : public boost::noncopyable |
209 | { | |
210 | public: | |
211 | Counters() | |
212 | { | |
213 | } | |
30ee601a | 214 | unsigned long value(const Thing& t) const |
628e2c7b | 215 | { |
30ee601a | 216 | typename cont_t::const_iterator i=d_cont.find(t); |
628e2c7b PA |
217 | |
218 | if(i==d_cont.end()) { | |
219 | return 0; | |
220 | } | |
221 | return (unsigned long)i->second; | |
222 | } | |
223 | unsigned long incr(const Thing& t) | |
224 | { | |
225 | typename cont_t::iterator i=d_cont.find(t); | |
226 | ||
227 | if(i==d_cont.end()) { | |
228 | d_cont[t]=1; | |
229 | return 1; | |
230 | } | |
231 | else { | |
232 | if (i->second < std::numeric_limits<unsigned long>::max()) | |
233 | i->second++; | |
234 | return (unsigned long)i->second; | |
235 | } | |
236 | } | |
237 | unsigned long decr(const Thing& t) | |
238 | { | |
239 | typename cont_t::iterator i=d_cont.find(t); | |
240 | ||
241 | if(i!=d_cont.end() && --i->second == 0) { | |
242 | d_cont.erase(i); | |
243 | return 0; | |
244 | } else | |
245 | return (unsigned long)i->second; | |
246 | } | |
247 | void clear(const Thing& t) | |
248 | { | |
249 | typename cont_t::iterator i=d_cont.find(t); | |
250 | ||
251 | if(i!=d_cont.end()) { | |
252 | d_cont.erase(i); | |
253 | } | |
254 | } | |
30ee601a RG |
255 | void clear() |
256 | { | |
257 | d_cont.clear(); | |
258 | } | |
259 | size_t size() const | |
406f46f9 | 260 | { |
261 | return d_cont.size(); | |
262 | } | |
628e2c7b PA |
263 | private: |
264 | typedef map<Thing,unsigned long> cont_t; | |
265 | cont_t d_cont; | |
266 | }; | |
267 | ||
71dea98d | 268 | |
bb4bdbaf | 269 | class SyncRes : public boost::noncopyable |
00a19ff7 BH |
270 | { |
271 | public: | |
3ddb9247 | 272 | enum LogMode { LogNone, Log, Store}; |
0bd2e252 | 273 | typedef std::function<int(const ComboAddress& ip, const DNSName& qdomain, int qtype, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult *lwr, bool* chained)> asyncresolve_t; |
77499b05 | 274 | |
a712cb56 RG |
275 | struct EDNSStatus |
276 | { | |
277 | EDNSStatus() : mode(UNKNOWN), modeSetAt(0) {} | |
278 | enum EDNSMode { UNKNOWN=0, EDNSOK=1, EDNSIGNORANT=2, NOEDNS=3 } mode; | |
279 | time_t modeSetAt; | |
280 | }; | |
281 | ||
282 | //! This represents a number of decaying Ewmas, used to store performance per nameserver-name. | |
283 | /** Modelled to work mostly like the underlying DecayingEwma. After you've called get, | |
284 | d_best is filled out with the best address for this collection */ | |
285 | struct DecayingEwmaCollection | |
286 | { | |
287 | void submit(const ComboAddress& remote, int usecs, const struct timeval* now) | |
288 | { | |
0e4675a9 | 289 | d_collection[remote].submit(usecs, now); |
a712cb56 RG |
290 | } |
291 | ||
292 | double get(const struct timeval* now) | |
293 | { | |
294 | if(d_collection.empty()) | |
295 | return 0; | |
296 | double ret=std::numeric_limits<double>::max(); | |
297 | double tmp; | |
0e4675a9 RG |
298 | for (auto& entry : d_collection) { |
299 | if((tmp = entry.second.get(now)) < ret) { | |
a712cb56 | 300 | ret=tmp; |
0e4675a9 | 301 | d_best=entry.first; |
a712cb56 RG |
302 | } |
303 | } | |
304 | ||
305 | return ret; | |
306 | } | |
307 | ||
308 | bool stale(time_t limit) const | |
309 | { | |
0e4675a9 RG |
310 | for(const auto& entry : d_collection) |
311 | if(!entry.second.stale(limit)) | |
a712cb56 RG |
312 | return false; |
313 | return true; | |
314 | } | |
315 | ||
0e4675a9 RG |
316 | void purge(const std::map<ComboAddress, double>& keep) |
317 | { | |
318 | for (auto iter = d_collection.begin(); iter != d_collection.end(); ) { | |
319 | if (keep.find(iter->first) != keep.end()) { | |
320 | ++iter; | |
321 | } | |
322 | else { | |
323 | iter = d_collection.erase(iter); | |
324 | } | |
325 | } | |
326 | } | |
327 | ||
328 | typedef std::map<ComboAddress, DecayingEwma> collection_t; | |
a712cb56 RG |
329 | collection_t d_collection; |
330 | ComboAddress d_best; | |
331 | }; | |
332 | ||
333 | typedef map<DNSName, DecayingEwmaCollection> nsspeeds_t; | |
334 | typedef map<ComboAddress, EDNSStatus> ednsstatus_t; | |
335 | ||
1e332f68 PL |
336 | vState getDSRecords(const DNSName& zone, dsmap_t& ds, bool onlyTA, unsigned int depth, bool bogusOnNXD=true, bool* foundCut=nullptr); |
337 | ||
3337c2f7 | 338 | class AuthDomain |
a712cb56 | 339 | { |
3337c2f7 | 340 | public: |
a712cb56 RG |
341 | typedef multi_index_container < |
342 | DNSRecord, | |
343 | indexed_by < | |
344 | ordered_non_unique< | |
345 | composite_key< DNSRecord, | |
346 | member<DNSRecord, DNSName, &DNSRecord::d_name>, | |
347 | member<DNSRecord, uint16_t, &DNSRecord::d_type> | |
348 | >, | |
349 | composite_key_compare<std::less<DNSName>, std::less<uint16_t> > | |
350 | > | |
351 | > | |
352 | > records_t; | |
3337c2f7 | 353 | |
a712cb56 | 354 | records_t d_records; |
3337c2f7 RG |
355 | vector<ComboAddress> d_servers; |
356 | DNSName d_name; | |
357 | bool d_rdForward{false}; | |
358 | ||
359 | int getRecords(const DNSName& qname, uint16_t qtype, std::vector<DNSRecord>& records) const; | |
360 | bool isAuth() const | |
361 | { | |
362 | return d_servers.empty(); | |
363 | } | |
364 | bool isForward() const | |
365 | { | |
366 | return !isAuth(); | |
367 | } | |
368 | bool shouldRecurse() const | |
369 | { | |
370 | return d_rdForward; | |
371 | } | |
372 | const DNSName& getName() const | |
373 | { | |
374 | return d_name; | |
375 | } | |
376 | ||
377 | private: | |
378 | void addSOA(std::vector<DNSRecord>& records) const; | |
a712cb56 RG |
379 | }; |
380 | ||
381 | typedef map<DNSName, AuthDomain> domainmap_t; | |
382 | typedef Throttle<boost::tuple<ComboAddress,DNSName,uint16_t> > throttle_t; | |
383 | typedef Counters<ComboAddress> fails_t; | |
384 | ||
385 | struct ThreadLocalStorage { | |
386 | NegCache negcache; | |
387 | nsspeeds_t nsSpeeds; | |
388 | throttle_t throttle; | |
389 | ednsstatus_t ednsstatus; | |
390 | fails_t fails; | |
391 | std::shared_ptr<domainmap_t> domainmap; | |
392 | }; | |
393 | ||
9065eb05 RG |
394 | static void setDefaultLogMode(LogMode lm) |
395 | { | |
396 | s_lm = lm; | |
397 | } | |
addde5c1 | 398 | static uint64_t doEDNSDump(int fd); |
9065eb05 | 399 | static uint64_t doDumpNSSpeeds(int fd); |
c1e20fba | 400 | static uint64_t doDumpThrottleMap(int fd); |
9065eb05 RG |
401 | static int getRootNS(struct timeval now, asyncresolve_t asyncCallback); |
402 | static void clearDelegationOnly() | |
403 | { | |
404 | s_delegationOnly.clear(); | |
405 | } | |
406 | static void addDelegationOnly(const DNSName& name) | |
407 | { | |
408 | s_delegationOnly.insert(name); | |
409 | } | |
410 | static void addDontQuery(const std::string& mask) | |
411 | { | |
412 | if (!s_dontQuery) | |
413 | s_dontQuery = std::unique_ptr<NetmaskGroup>(new NetmaskGroup()); | |
bb4bdbaf | 414 | |
9065eb05 RG |
415 | s_dontQuery->addMask(mask); |
416 | } | |
417 | static void addDontQuery(const Netmask& mask) | |
418 | { | |
419 | if (!s_dontQuery) | |
420 | s_dontQuery = std::unique_ptr<NetmaskGroup>(new NetmaskGroup()); | |
421 | ||
422 | s_dontQuery->addMask(mask); | |
423 | } | |
424 | static void clearDontQuery() | |
425 | { | |
426 | s_dontQuery = nullptr; | |
427 | } | |
428 | static void parseEDNSSubnetWhitelist(const std::string& wlist); | |
2fe3354d CH |
429 | static void parseEDNSSubnetAddFor(const std::string& subnetlist); |
430 | static void addEDNSLocalSubnet(const std::string& subnet) | |
9065eb05 | 431 | { |
2fe3354d CH |
432 | s_ednslocalsubnets.addMask(subnet); |
433 | } | |
434 | static void addEDNSRemoteSubnet(const std::string& subnet) | |
435 | { | |
436 | s_ednsremotesubnets.addMask(subnet); | |
9065eb05 RG |
437 | } |
438 | static void addEDNSDomain(const DNSName& domain) | |
439 | { | |
440 | s_ednsdomains.add(domain); | |
441 | } | |
2fe3354d | 442 | static void clearEDNSLocalSubnets() |
9065eb05 | 443 | { |
2fe3354d CH |
444 | s_ednslocalsubnets.clear(); |
445 | } | |
446 | static void clearEDNSRemoteSubnets() | |
447 | { | |
448 | s_ednsremotesubnets.clear(); | |
9065eb05 RG |
449 | } |
450 | static void clearEDNSDomains() | |
451 | { | |
452 | s_ednsdomains = SuffixMatchNode(); | |
453 | } | |
a712cb56 RG |
454 | static void pruneNSSpeeds(time_t limit) |
455 | { | |
456 | for(auto i = t_sstorage.nsSpeeds.begin(), end = t_sstorage.nsSpeeds.end(); i != end; ) { | |
457 | if(i->second.stale(limit)) { | |
458 | i = t_sstorage.nsSpeeds.erase(i); | |
459 | } | |
460 | else { | |
461 | ++i; | |
462 | } | |
463 | } | |
464 | } | |
465 | static uint64_t getNSSpeedsSize() | |
466 | { | |
467 | return t_sstorage.nsSpeeds.size(); | |
468 | } | |
469 | static void submitNSSpeed(const DNSName& server, const ComboAddress& ca, uint32_t usec, const struct timeval* now) | |
470 | { | |
471 | t_sstorage.nsSpeeds[server].submit(ca, usec, now); | |
472 | } | |
473 | static void clearNSSpeeds() | |
474 | { | |
475 | t_sstorage.nsSpeeds.clear(); | |
476 | } | |
477 | static EDNSStatus::EDNSMode getEDNSStatus(const ComboAddress& server) | |
478 | { | |
479 | const auto& it = t_sstorage.ednsstatus.find(server); | |
480 | if (it == t_sstorage.ednsstatus.end()) | |
481 | return EDNSStatus::UNKNOWN; | |
482 | ||
483 | return it->second.mode; | |
484 | } | |
485 | static uint64_t getEDNSStatusesSize() | |
486 | { | |
487 | return t_sstorage.ednsstatus.size(); | |
488 | } | |
489 | static void clearEDNSStatuses() | |
490 | { | |
491 | t_sstorage.ednsstatus.clear(); | |
492 | } | |
493 | static uint64_t getThrottledServersSize() | |
494 | { | |
495 | return t_sstorage.throttle.size(); | |
496 | } | |
497 | static void clearThrottle() | |
498 | { | |
499 | t_sstorage.throttle.clear(); | |
500 | } | |
501 | static bool isThrottled(time_t now, const ComboAddress& server, const DNSName& target, uint16_t qtype) | |
502 | { | |
503 | return t_sstorage.throttle.shouldThrottle(now, boost::make_tuple(server, target, qtype)); | |
504 | } | |
505 | static bool isThrottled(time_t now, const ComboAddress& server) | |
506 | { | |
507 | return t_sstorage.throttle.shouldThrottle(now, boost::make_tuple(server, "", 0)); | |
508 | } | |
509 | static void doThrottle(time_t now, const ComboAddress& server, time_t duration, unsigned int tries) | |
510 | { | |
511 | t_sstorage.throttle.throttle(now, boost::make_tuple(server, "", 0), duration, tries); | |
512 | } | |
513 | static uint64_t getFailedServersSize() | |
514 | { | |
515 | return t_sstorage.fails.size(); | |
516 | } | |
517 | static void clearFailedServers() | |
518 | { | |
519 | t_sstorage.fails.clear(); | |
520 | } | |
521 | static unsigned long getServerFailsCount(const ComboAddress& server) | |
522 | { | |
523 | return t_sstorage.fails.value(server); | |
524 | } | |
525 | ||
526 | static void clearNegCache() | |
527 | { | |
528 | t_sstorage.negcache.clear(); | |
529 | } | |
530 | ||
531 | static uint64_t getNegCacheSize() | |
532 | { | |
533 | return t_sstorage.negcache.size(); | |
534 | } | |
535 | ||
536 | static void pruneNegCache(unsigned int maxEntries) | |
537 | { | |
538 | t_sstorage.negcache.prune(maxEntries); | |
539 | } | |
540 | ||
541 | static uint64_t wipeNegCache(const DNSName& name, bool subtree = false) | |
542 | { | |
543 | return t_sstorage.negcache.wipe(name, subtree); | |
544 | } | |
545 | ||
546 | static void setDomainMap(std::shared_ptr<domainmap_t> newMap) | |
547 | { | |
548 | t_sstorage.domainmap = newMap; | |
549 | } | |
550 | ||
551 | static const std::shared_ptr<domainmap_t> getDomainMap() | |
552 | { | |
553 | return t_sstorage.domainmap; | |
554 | } | |
9065eb05 | 555 | |
8a3a3822 RG |
556 | static void setECSScopeZeroAddress(const Netmask& scopeZeroMask) |
557 | { | |
558 | s_ecsScopeZero.source = scopeZeroMask; | |
559 | } | |
560 | ||
c9783016 RG |
561 | static void clearECSStats() |
562 | { | |
563 | s_ecsqueries.store(0); | |
564 | s_ecsresponses.store(0); | |
565 | ||
566 | for (size_t idx = 0; idx < 32; idx++) { | |
567 | SyncRes::s_ecsResponsesBySubnetSize4[idx].store(0); | |
568 | } | |
569 | ||
570 | for (size_t idx = 0; idx < 128; idx++) { | |
571 | SyncRes::s_ecsResponsesBySubnetSize6[idx].store(0); | |
572 | } | |
573 | } | |
574 | ||
9065eb05 | 575 | explicit SyncRes(const struct timeval& now); |
30ee601a | 576 | |
e325f20c | 577 | int beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret); |
c836dc19 BH |
578 | void setId(int id) |
579 | { | |
77499b05 | 580 | if(doLog()) |
9fdf67d5 | 581 | d_prefix="["+itoa(id)+"] "; |
c836dc19 | 582 | } |
3ddb9247 PD |
583 | |
584 | void setLogMode(LogMode lm) | |
77499b05 BH |
585 | { |
586 | d_lm = lm; | |
587 | } | |
588 | ||
69cbdef9 | 589 | bool doLog() const |
c836dc19 | 590 | { |
3ddb9247 | 591 | return d_lm != LogNone; |
c836dc19 | 592 | } |
77499b05 | 593 | |
c836dc19 BH |
594 | void setCacheOnly(bool state=true) |
595 | { | |
596 | d_cacheonly=state; | |
597 | } | |
2188dcc3 BH |
598 | |
599 | void setDoEDNS0(bool state=true) | |
600 | { | |
601 | d_doEDNS0=state; | |
602 | } | |
603 | ||
30ee601a RG |
604 | void setDoDNSSEC(bool state=true) |
605 | { | |
606 | d_doDNSSEC=state; | |
607 | } | |
608 | ||
0c43f455 RG |
609 | void setDNSSECValidationRequested(bool requested=true) |
610 | { | |
611 | d_DNSSECValidationRequested = requested; | |
612 | } | |
613 | ||
614 | bool isDNSSECValidationRequested() const | |
615 | { | |
616 | return d_DNSSECValidationRequested; | |
617 | } | |
618 | ||
e1636f82 RG |
619 | bool shouldValidate() const |
620 | { | |
621 | return d_DNSSECValidationRequested && !d_wasOutOfBand; | |
622 | } | |
623 | ||
30ee601a RG |
624 | void setWantsRPZ(bool state=true) |
625 | { | |
626 | d_wantsRPZ=state; | |
627 | } | |
628 | ||
629 | bool getWantsRPZ() const | |
630 | { | |
631 | return d_wantsRPZ; | |
632 | } | |
633 | ||
77499b05 BH |
634 | string getTrace() const |
635 | { | |
636 | return d_trace.str(); | |
637 | } | |
638 | ||
a3e7b735 | 639 | void setLuaEngine(shared_ptr<RecursorLua4> pdl) |
3457a2a0 | 640 | { |
641 | d_pdl = pdl; | |
642 | } | |
643 | ||
3762e821 | 644 | bool wasVariable() const |
645 | { | |
646 | return d_wasVariable; | |
647 | } | |
3457a2a0 | 648 | |
9fc36e90 PL |
649 | bool wasOutOfBand() const |
650 | { | |
651 | return d_wasOutOfBand; | |
652 | } | |
653 | ||
30ee601a RG |
654 | struct timeval getNow() const |
655 | { | |
656 | return d_now; | |
657 | } | |
658 | ||
a672e9de PL |
659 | void setSkipCNAMECheck(bool skip = false) |
660 | { | |
661 | d_skipCNAMECheck = skip; | |
662 | } | |
663 | ||
2fe3354d | 664 | void setQuerySource(const ComboAddress& requestor, boost::optional<const EDNSSubnetOpts&> incomingECS); |
30ee601a RG |
665 | |
666 | #ifdef HAVE_PROTOBUF | |
667 | void setInitialRequestId(boost::optional<const boost::uuids::uuid&> initialRequestId) | |
668 | { | |
669 | d_initialRequestId = initialRequestId; | |
670 | } | |
63341e8d | 671 | |
3fe06137 | 672 | void setOutgoingProtobufServers(std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>>& servers) |
63341e8d | 673 | { |
b773359c | 674 | d_outgoingProtobufServers = servers; |
63341e8d | 675 | } |
30ee601a RG |
676 | #endif |
677 | ||
678 | void setAsyncCallback(asyncresolve_t func) | |
679 | { | |
680 | d_asyncResolve = func; | |
681 | } | |
3ddb9247 | 682 | |
4d2be65d RG |
683 | vState getValidationState() const |
684 | { | |
685 | return d_queryValidationState; | |
686 | } | |
687 | ||
a712cb56 RG |
688 | static thread_local ThreadLocalStorage t_sstorage; |
689 | ||
aebb81e4 | 690 | static std::atomic<uint64_t> s_queries; |
691 | static std::atomic<uint64_t> s_outgoingtimeouts; | |
692 | static std::atomic<uint64_t> s_outgoing4timeouts; | |
693 | static std::atomic<uint64_t> s_outgoing6timeouts; | |
694 | static std::atomic<uint64_t> s_throttledqueries; | |
695 | static std::atomic<uint64_t> s_dontqueries; | |
e9a628a2 | 696 | static std::atomic<uint64_t> s_authzonequeries; |
aebb81e4 | 697 | static std::atomic<uint64_t> s_outqueries; |
698 | static std::atomic<uint64_t> s_tcpoutqueries; | |
699 | static std::atomic<uint64_t> s_nodelegated; | |
700 | static std::atomic<uint64_t> s_unreachables; | |
d6923beb | 701 | static std::atomic<uint64_t> s_ecsqueries; |
702 | static std::atomic<uint64_t> s_ecsresponses; | |
c9783016 RG |
703 | static std::map<uint8_t, std::atomic<uint64_t>> s_ecsResponsesBySubnetSize4; |
704 | static std::map<uint8_t, std::atomic<uint64_t>> s_ecsResponsesBySubnetSize6; | |
9065eb05 | 705 | |
9065eb05 RG |
706 | static string s_serverID; |
707 | static unsigned int s_minimumTTL; | |
5cf4b2e7 | 708 | static unsigned int s_minimumECSTTL; |
9065eb05 RG |
709 | static unsigned int s_maxqperq; |
710 | static unsigned int s_maxtotusec; | |
711 | static unsigned int s_maxdepth; | |
a9af3782 | 712 | static unsigned int s_maxnegttl; |
b9473937 | 713 | static unsigned int s_maxbogusttl; |
c3e753c7 | 714 | static unsigned int s_maxcachettl; |
1051f8a9 BH |
715 | static unsigned int s_packetcachettl; |
716 | static unsigned int s_packetcacheservfailttl; | |
628e2c7b PA |
717 | static unsigned int s_serverdownmaxfails; |
718 | static unsigned int s_serverdownthrottletime; | |
e7861cc4 | 719 | static unsigned int s_ecscachelimitttl; |
e9f9b8ec RG |
720 | static uint8_t s_ecsipv4limit; |
721 | static uint8_t s_ecsipv6limit; | |
fd8898fb | 722 | static uint8_t s_ecsipv4cachelimit; |
723 | static uint8_t s_ecsipv6cachelimit; | |
9065eb05 RG |
724 | static bool s_doIPv6; |
725 | static bool s_noEDNSPing; | |
726 | static bool s_noEDNS; | |
727 | static bool s_rootNXTrust; | |
1051f8a9 | 728 | static bool s_nopacketcache; |
3ddb9247 | 729 | |
a712cb56 RG |
730 | std::unordered_map<std::string,bool> d_discardedPolicies; |
731 | DNSFilterEngine::Policy d_appliedPolicy; | |
f7b8cffa | 732 | unsigned int d_authzonequeries; |
a712cb56 RG |
733 | unsigned int d_outqueries; |
734 | unsigned int d_tcpoutqueries; | |
735 | unsigned int d_throttledqueries; | |
736 | unsigned int d_timeouts; | |
737 | unsigned int d_unreachables; | |
738 | unsigned int d_totUsec; | |
49a699c4 | 739 | |
00a19ff7 | 740 | private: |
2fe3354d CH |
741 | ComboAddress d_requestor; |
742 | ComboAddress d_cacheRemote; | |
a712cb56 | 743 | |
9065eb05 | 744 | static std::unordered_set<DNSName> s_delegationOnly; |
2fe3354d CH |
745 | static NetmaskGroup s_ednslocalsubnets; |
746 | static NetmaskGroup s_ednsremotesubnets; | |
9065eb05 | 747 | static SuffixMatchNode s_ednsdomains; |
8a3a3822 | 748 | static EDNSSubnetOpts s_ecsScopeZero; |
9065eb05 RG |
749 | static LogMode s_lm; |
750 | static std::unique_ptr<NetmaskGroup> s_dontQuery; | |
751 | ||
752 | struct GetBestNSAnswer | |
753 | { | |
754 | DNSName qname; | |
755 | set<pair<DNSName,DNSName> > bestns; | |
756 | uint8_t qtype; // only A and AAAA anyhow | |
757 | bool operator<(const GetBestNSAnswer &b) const | |
758 | { | |
759 | return boost::tie(qname, qtype, bestns) < | |
760 | boost::tie(b.qname, b.qtype, b.bestns); | |
761 | } | |
762 | }; | |
763 | ||
70b3fe7a RG |
764 | typedef std::map<DNSName,vState> zonesStates_t; |
765 | ||
fa1b87ff | 766 | int doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, |
51b6b728 | 767 | unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state); |
6dfff36f | 768 | bool doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType& qtype, LWResult& lwr, boost::optional<Netmask>& ednsmask, const DNSName& auth, bool const sendRDQuery, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool* truncated); |
51b6b728 | 769 | bool processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector<DNSRecord>& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state); |
6dfff36f | 770 | |
51b6b728 | 771 | int doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, vState& state); |
f7b8cffa | 772 | bool doOOBResolve(const AuthDomain& domain, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int& res); |
7c3398aa | 773 | bool doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res); |
69cbdef9 | 774 | domainmap_t::const_iterator getBestAuthZone(DNSName* qname) const; |
ad797d94 RG |
775 | bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state, bool wasAuthZone, bool wasForwardRecurse); |
776 | bool doCacheCheck(const DNSName &qname, const DNSName& authname, bool wasForwardedOrAuthZone, bool wasAuthZone, bool wasForwardRecurse, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state); | |
7c3398aa RG |
777 | void getBestNSFromCache(const DNSName &qname, const QType &qtype, vector<DNSRecord>&bestns, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>& beenthere); |
778 | DNSName getBestNSNamesFromCache(const DNSName &qname, const QType &qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>&beenthere); | |
c5c066bf | 779 | |
fa1b87ff | 780 | inline vector<DNSName> shuffleInSpeedOrder(NsSet &nameservers, const string &prefix); |
cc11d7f4 | 781 | inline vector<ComboAddress> shuffleForwardSpeed(const vector<ComboAddress> &rnameservers, const string &prefix, const bool wasRd); |
69cbdef9 | 782 | bool moreSpecificThan(const DNSName& a, const DNSName &b) const; |
b4c8789a | 783 | vector<ComboAddress> getAddrs(const DNSName &qname, unsigned int depth, set<GetBestNSAnswer>& beenthere, bool cacheOnly); |
26ca3513 | 784 | |
69cbdef9 RG |
785 | bool nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers); |
786 | bool nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress&); | |
26ca3513 RG |
787 | bool throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery); |
788 | ||
b4c8789a | 789 | vector<ComboAddress> retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, vector<DNSName >::const_iterator& tns, const unsigned int depth, set<GetBestNSAnswer>& beenthere, const vector<DNSName >& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet, bool cacheOnly); |
7155c3e5 RG |
790 | |
791 | void sanitizeRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, const QType& qtype, const DNSName& auth, bool wasForwarded, bool rdQuery); | |
792 | RCode::rcodes_ updateCacheFromRecords(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, const DNSName& auth, bool wasForwarded, const boost::optional<Netmask>, vState& state, bool& needWildcardProof, unsigned int& wildcardLabelsCount, bool sendRDQuery); | |
e4894ce0 | 793 | bool processRecords(const std::string& prefix, const DNSName& qname, const QType& qtype, const DNSName& auth, LWResult& lwr, const bool sendRDQuery, vector<DNSRecord>& ret, set<DNSName>& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic, vState& state, const bool needWildcardProof, const unsigned int wildcardLabelsCount); |
26ca3513 | 794 | |
6dfff36f | 795 | bool doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector<DNSRecord> &ret); |
db50a7f4 | 796 | |
deca7d8f | 797 | int asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, struct timeval* now, boost::optional<Netmask>& srcmask, LWResult* res, bool* chained) const; |
30ee601a | 798 | |
2fe3354d | 799 | boost::optional<Netmask> getEDNSSubnetMask(const DNSName&dn, const ComboAddress& rem); |
e9f9b8ec | 800 | |
4d2be65d | 801 | bool validationEnabled() const; |
4d2be65d RG |
802 | uint32_t computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL) const; |
803 | void updateValidationState(vState& state, const vState stateUpdate); | |
51b6b728 RG |
804 | vState validateRecordsWithSigs(unsigned int depth, const DNSName& qname, const QType& qtype, const DNSName& name, const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures); |
805 | vState validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, unsigned int depth); | |
51b6b728 | 806 | vState getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int depth); |
28364e4b RG |
807 | dState getDenialValidationState(const NegCache::NegCacheEntry& ne, const vState state, const dState expectedState, bool referralToUnsigned); |
808 | void updateDenialValidationState(vState& neValidationState, const DNSName& neName, vState& state, const dState denialState, const dState expectedState, bool allowOptOut); | |
809 | void computeNegCacheValidationStatus(const NegCache::NegCacheEntry* ne, const DNSName& qname, const QType& qtype, const int res, vState& state, unsigned int depth); | |
4d2be65d | 810 | vState getTA(const DNSName& zone, dsmap_t& ds); |
0735b60f | 811 | bool haveExactValidationStatus(const DNSName& domain); |
5374b03b | 812 | vState getValidationStatus(const DNSName& subdomain, bool allowIndeterminate=true); |
b9473937 | 813 | void updateValidationStatusInCache(const DNSName &qname, const QType& qt, bool aa, vState newState) const; |
70b3fe7a | 814 | |
c405e222 | 815 | bool lookForCut(const DNSName& qname, unsigned int depth, const vState existingState, vState& newState); |
51b6b728 | 816 | void computeZoneCuts(const DNSName& begin, const DNSName& end, unsigned int depth); |
4d2be65d | 817 | |
0b29b9c5 RG |
818 | void setUpdatingRootNS() |
819 | { | |
820 | d_updatingRootNS = true; | |
821 | } | |
822 | ||
51b6b728 | 823 | zonesStates_t d_cutStates; |
77499b05 | 824 | ostringstream d_trace; |
a3e7b735 | 825 | shared_ptr<RecursorLua4> d_pdl; |
2fe3354d | 826 | boost::optional<Netmask> d_outgoingECSNetwork; |
3fe06137 | 827 | std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>> d_outgoingProtobufServers{nullptr}; |
30ee601a RG |
828 | #ifdef HAVE_PROTOBUF |
829 | boost::optional<const boost::uuids::uuid&> d_initialRequestId; | |
830 | #endif | |
831 | asyncresolve_t d_asyncResolve{nullptr}; | |
832 | struct timeval d_now; | |
c836dc19 | 833 | string d_prefix; |
4d2be65d | 834 | vState d_queryValidationState{Indeterminate}; |
b88526ce PL |
835 | |
836 | /* When d_cacheonly is set to true, we will only check the cache. | |
837 | * This is set when the RD bit is unset in the incoming query | |
838 | */ | |
c836dc19 | 839 | bool d_cacheonly; |
30ee601a | 840 | bool d_doDNSSEC; |
0c43f455 | 841 | bool d_DNSSECValidationRequested{false}; |
30ee601a | 842 | bool d_doEDNS0{true}; |
24bb9b58 | 843 | bool d_requireAuthData{true}; |
30ee601a | 844 | bool d_skipCNAMECheck{false}; |
0b29b9c5 | 845 | bool d_updatingRootNS{false}; |
30ee601a RG |
846 | bool d_wantsRPZ{true}; |
847 | bool d_wasOutOfBand{false}; | |
848 | bool d_wasVariable{false}; | |
57769f13 | 849 | |
77499b05 | 850 | LogMode d_lm; |
00a19ff7 | 851 | }; |
ac0e821b | 852 | |
5c633640 | 853 | class Socket; |
a9af3782 | 854 | /* external functions, opaque to us */ |
5c633640 | 855 | int asendtcp(const string& data, Socket* sock); |
a683e8bd | 856 | int arecvtcp(string& data, size_t len, Socket* sock, bool incompleteOkay); |
1d5b3ce6 BH |
857 | |
858 | ||
859 | struct PacketID | |
860 | { | |
825fa717 | 861 | PacketID() : id(0), type(0), sock(0), inNeeded(0), inIncompleteOkay(false), outPos(0), nearMisses(0), fd(-1) |
67770277 | 862 | { |
d38e2ba9 | 863 | remote.reset(); |
67770277 | 864 | } |
1d5b3ce6 BH |
865 | |
866 | uint16_t id; // wait for a specific id/remote pair | |
91ffe057 | 867 | uint16_t type; // and this is its type |
996c89cc | 868 | ComboAddress remote; // this is the remote |
3ddb9247 | 869 | DNSName domain; // this is the question |
1d5b3ce6 BH |
870 | |
871 | Socket* sock; // or wait for an event on a TCP fd | |
1d5b3ce6 | 872 | string inMSG; // they'll go here |
a683e8bd | 873 | size_t inNeeded; // if this is set, we'll read until inNeeded bytes are read |
825fa717 | 874 | bool inIncompleteOkay; |
1d5b3ce6 BH |
875 | |
876 | string outMSG; // the outgoing message that needs to be sent | |
877 | string::size_type outPos; // how far we are along in the outMSG | |
878 | ||
96f81a93 BH |
879 | typedef set<uint16_t > chain_t; |
880 | mutable chain_t chain; | |
91ffe057 | 881 | mutable uint32_t nearMisses; // number of near misses - host correct, id wrong |
4ef015cd | 882 | int fd; |
35ce8576 | 883 | |
1d5b3ce6 BH |
884 | bool operator<(const PacketID& b) const |
885 | { | |
886 | int ourSock= sock ? sock->getHandle() : 0; | |
887 | int bSock = b.sock ? b.sock->getHandle() : 0; | |
787e5eab | 888 | if( tie(remote, ourSock, type) < tie(b.remote, bSock, b.type)) |
0d5f0a9f | 889 | return true; |
787e5eab | 890 | if( tie(remote, ourSock, type) > tie(b.remote, bSock, b.type)) |
0d5f0a9f BH |
891 | return false; |
892 | ||
c5c066bf | 893 | return tie(domain, fd, id) < tie(b.domain, b.fd, b.id); |
1d5b3ce6 BH |
894 | } |
895 | }; | |
896 | ||
3ddb9247 | 897 | struct PacketIDBirthdayCompare: public std::binary_function<PacketID, PacketID, bool> |
96f81a93 BH |
898 | { |
899 | bool operator()(const PacketID& a, const PacketID& b) const | |
900 | { | |
901 | int ourSock= a.sock ? a.sock->getHandle() : 0; | |
902 | int bSock = b.sock ? b.sock->getHandle() : 0; | |
787e5eab | 903 | if( tie(a.remote, ourSock, a.type) < tie(b.remote, bSock, b.type)) |
96f81a93 | 904 | return true; |
787e5eab | 905 | if( tie(a.remote, ourSock, a.type) > tie(b.remote, bSock, b.type)) |
96f81a93 BH |
906 | return false; |
907 | ||
72849e12 | 908 | return a.domain < b.domain; |
96f81a93 BH |
909 | } |
910 | }; | |
f26bf547 RG |
911 | extern thread_local std::unique_ptr<MemRecursorCache> t_RC; |
912 | extern thread_local std::unique_ptr<RecursorPacketCache> t_packetCache; | |
d2392145 | 913 | typedef MTasker<PacketID,string> MT_t; |
f165a1f4 | 914 | MT_t* getMT(); |
1d5b3ce6 BH |
915 | |
916 | struct RecursorStats | |
917 | { | |
aebb81e4 | 918 | std::atomic<uint64_t> servFails; |
919 | std::atomic<uint64_t> nxDomains; | |
920 | std::atomic<uint64_t> noErrors; | |
921 | std::atomic<uint64_t> answers0_1, answers1_10, answers10_100, answers100_1000, answersSlow; | |
922 | std::atomic<uint64_t> auth4Answers0_1, auth4Answers1_10, auth4Answers10_100, auth4Answers100_1000, auth4AnswersSlow; | |
923 | std::atomic<uint64_t> auth6Answers0_1, auth6Answers1_10, auth6Answers10_100, auth6Answers100_1000, auth6AnswersSlow; | |
19178da9 | 924 | std::atomic<uint64_t> ourtime0_1, ourtime1_2, ourtime2_4, ourtime4_8, ourtime8_16, ourtime16_32, ourtimeSlow; |
925 | double avgLatencyUsec{0}; | |
926 | double avgLatencyOursUsec{0}; | |
aebb81e4 | 927 | std::atomic<uint64_t> qcounter; // not increased for unauth packets |
928 | std::atomic<uint64_t> ipv6qcounter; | |
929 | std::atomic<uint64_t> tcpqcounter; | |
930 | std::atomic<uint64_t> unauthorizedUDP; // when this is increased, qcounter isn't | |
931 | std::atomic<uint64_t> unauthorizedTCP; // when this is increased, qcounter isn't | |
932 | std::atomic<uint64_t> policyDrops; | |
933 | std::atomic<uint64_t> tcpClientOverflow; | |
934 | std::atomic<uint64_t> clientParseError; | |
935 | std::atomic<uint64_t> serverParseError; | |
936 | std::atomic<uint64_t> tooOldDrops; | |
ba892c7f | 937 | std::atomic<uint64_t> truncatedDrops; |
cf8cda18 | 938 | std::atomic<uint64_t> queryPipeFullDrops; |
aebb81e4 | 939 | std::atomic<uint64_t> unexpectedCount; |
940 | std::atomic<uint64_t> caseMismatchCount; | |
941 | std::atomic<uint64_t> spoofCount; | |
942 | std::atomic<uint64_t> resourceLimits; | |
943 | std::atomic<uint64_t> overCapacityDrops; | |
944 | std::atomic<uint64_t> ipv6queries; | |
945 | std::atomic<uint64_t> chainResends; | |
946 | std::atomic<uint64_t> nsSetInvalidations; | |
947 | std::atomic<uint64_t> ednsPingMatches; | |
948 | std::atomic<uint64_t> ednsPingMismatches; | |
949 | std::atomic<uint64_t> noPingOutQueries, noEdnsOutQueries; | |
950 | std::atomic<uint64_t> packetCacheHits; | |
951 | std::atomic<uint64_t> noPacketError; | |
952 | std::atomic<uint64_t> ignoredCount; | |
c0f9be19 | 953 | std::atomic<uint64_t> emptyQueriesCount; |
5e3de507 | 954 | time_t startupTime; |
aebb81e4 | 955 | std::atomic<uint64_t> dnssecQueries; |
88c33dca RG |
956 | std::atomic<uint64_t> dnssecAuthenticDataQueries; |
957 | std::atomic<uint64_t> dnssecCheckDisabledQueries; | |
49dc532e | 958 | std::atomic<uint64_t> variableResponses; |
ec6eacbc | 959 | unsigned int maxMThreadStackUsage; |
849fe8d2 PL |
960 | std::atomic<uint64_t> dnssecValidations; // should be the sum of all dnssecResult* stats |
961 | std::map<vState, std::atomic<uint64_t> > dnssecResults; | |
7a25883a | 962 | std::map<DNSFilterEngine::PolicyKind, std::atomic<uint64_t> > policyResults; |
596bf482 | 963 | std::atomic<uint64_t> rebalancedQueries{0}; |
b3b5459d | 964 | }; |
996c89cc | 965 | |
0e408828 | 966 | //! represents a running TCP/IP client session |
cd989c87 | 967 | class TCPConnection : public boost::noncopyable |
0e408828 | 968 | { |
50a5ef72 | 969 | public: |
cd989c87 BH |
970 | TCPConnection(int fd, const ComboAddress& addr); |
971 | ~TCPConnection(); | |
3ddb9247 | 972 | |
30ee601a | 973 | int getFD() const |
cd989c87 BH |
974 | { |
975 | return d_fd; | |
976 | } | |
2749c3fe RG |
977 | |
978 | std::string data; | |
979 | const ComboAddress d_remote; | |
980 | size_t queriesCount{0}; | |
b841314c RG |
981 | enum stateenum {BYTE0, BYTE1, GETQUESTION, DONE} state{BYTE0}; |
982 | uint16_t qlen{0}; | |
983 | uint16_t bytesread{0}; | |
0e408828 | 984 | |
50a5ef72 | 985 | static unsigned int getCurrentConnections() { return s_currentConnections; } |
50a5ef72 | 986 | private: |
cd989c87 | 987 | const int d_fd; |
1bc9e6bd | 988 | static AtomicCounter s_currentConnections; //!< total number of current TCP connections |
0e408828 BH |
989 | }; |
990 | ||
44971ca0 PD |
991 | class ImmediateServFailException |
992 | { | |
993 | public: | |
8a70e507 | 994 | ImmediateServFailException(string r) : reason(r) {}; |
44971ca0 PD |
995 | |
996 | string reason; //! Print this to tell the user what went wrong | |
997 | }; | |
0e408828 | 998 | |
f635ed7b | 999 | typedef boost::circular_buffer<ComboAddress> addrringbuf_t; |
621ccf89 | 1000 | extern thread_local std::unique_ptr<addrringbuf_t> t_servfailremotes, t_largeanswerremotes, t_remotes, t_bogusremotes, t_timeouts; |
a9af3782 | 1001 | |
66f2e6ad | 1002 | extern thread_local std::unique_ptr<boost::circular_buffer<pair<DNSName,uint16_t> > > t_queryring, t_servfailqueryring, t_bogusqueryring; |
f26bf547 | 1003 | extern thread_local std::shared_ptr<NetmaskGroup> t_allowFrom; |
674cf0f6 | 1004 | string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end); |
77499b05 | 1005 | string doTraceRegex(vector<string>::const_iterator begin, vector<string>::const_iterator end); |
18af64a8 | 1006 | void parseACLs(); |
1d5b3ce6 | 1007 | extern RecursorStats g_stats; |
a512e3d1 | 1008 | extern unsigned int g_networkTimeoutMsec; |
c3828c03 | 1009 | extern unsigned int g_numThreads; |
b33c2462 | 1010 | extern uint16_t g_outgoingEDNSBufsize; |
a6f7f5fe | 1011 | extern std::atomic<uint32_t> g_maxCacheEntries, g_maxPacketCacheEntries; |
c1c29961 | 1012 | extern bool g_lowercaseOutgoing; |
12ce523e | 1013 | |
1014 | ||
ee1ada80 | 1015 | std::string reloadAuthAndForwards(); |
c1d73d94 | 1016 | ComboAddress parseIPAndPort(const std::string& input, uint16_t port); |
1652a63e | 1017 | ComboAddress getQueryLocalAddress(int family, uint16_t port); |
3427fa8a | 1018 | typedef boost::function<void*(void)> pipefunc_t; |
b4e76a18 | 1019 | void broadcastFunction(const pipefunc_t& func); |
8171ab83 | 1020 | void distributeAsyncFunction(const std::string& question, const pipefunc_t& func); |
3427fa8a | 1021 | |
e325f20c | 1022 | int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret); |
3427fa8a | 1023 | |
b4e76a18 | 1024 | template<class T> T broadcastAccFunction(const boost::function<T*()>& func); |
3427fa8a | 1025 | |
9065eb05 | 1026 | std::shared_ptr<SyncRes::domainmap_t> parseAuthAndForwards(); |
13034931 BH |
1027 | uint64_t* pleaseGetNsSpeedsSize(); |
1028 | uint64_t* pleaseGetCacheSize(); | |
1029 | uint64_t* pleaseGetNegCacheSize(); | |
1030 | uint64_t* pleaseGetCacheHits(); | |
1031 | uint64_t* pleaseGetCacheMisses(); | |
1032 | uint64_t* pleaseGetConcurrentQueries(); | |
1033 | uint64_t* pleaseGetThrottleSize(); | |
16beeaa4 BH |
1034 | uint64_t* pleaseGetPacketCacheHits(); |
1035 | uint64_t* pleaseGetPacketCacheSize(); | |
86f3ca51 | 1036 | uint64_t* pleaseWipeCache(const DNSName& canon, bool subtree=false); |
1037 | uint64_t* pleaseWipePacketCache(const DNSName& canon, bool subtree); | |
1038 | uint64_t* pleaseWipeAndCountNegCache(const DNSName& canon, bool subtree=false); | |
2c78bd57 | 1039 | void doCarbonDump(void*); |
9065eb05 | 1040 | void primeHints(void); |
795215f2 | 1041 | |
f703f766 | 1042 | extern __thread struct timeval g_now; |
5ac6d761 | 1043 | |
1044 | struct ThreadTimes | |
1045 | { | |
1046 | uint64_t msec; | |
1047 | vector<uint64_t> times; | |
1048 | ThreadTimes& operator+=(const ThreadTimes& rhs) | |
1049 | { | |
1050 | times.push_back(rhs.msec); | |
1051 | return *this; | |
1052 | } | |
1053 | }; |