]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/syncres.hh
rec: Get rid of `SyncRes::d_nocache`, prevent root refresh loop
[thirdparty/pdns.git] / pdns / syncres.hh
CommitLineData
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>
59#include <boost/uuid/uuid_generators.hpp>
60#endif
61
a3e7b735 62class RecursorLua4;
620db2c8 63
fa1b87ff
PL
64typedef map<
65 DNSName,
66 pair<
67 vector<ComboAddress>,
68 bool
69 >
70> NsSet;
49f076e8 71
bb4bdbaf 72template<class Thing> class Throttle : public boost::noncopyable
49f076e8
BH
73{
74public:
75 Throttle()
76 {
77 d_limit=3;
78 d_ttl=60;
79 d_last_clean=time(0);
80 }
87da00e7 81 bool shouldThrottle(time_t now, const Thing& t)
49f076e8 82 {
cd7bf56b 83 if(now > d_last_clean + 300 ) {
bb4bdbaf 84
49f076e8 85 d_last_clean=now;
594c2ee7 86 for(typename cont_t::iterator i=d_cont.begin();i!=d_cont.end();) {
4957a608
BH
87 if( i->second.ttd < now) {
88 d_cont.erase(i++);
89 }
90 else
91 ++i;
594c2ee7 92 }
49f076e8
BH
93 }
94
49f076e8
BH
95 typename cont_t::iterator i=d_cont.find(t);
96 if(i==d_cont.end())
97 return false;
ccb07d93 98 if(now > i->second.ttd || i->second.count == 0) {
49f076e8 99 d_cont.erase(i);
139c2911 100 return false;
49f076e8 101 }
ccb07d93 102 i->second.count--;
014c60c3
BH
103
104 return true; // still listed, still blocked
49f076e8 105 }
3ddb9247 106 void throttle(time_t now, const Thing& t, time_t ttl=0, unsigned int tries=0)
49f076e8
BH
107 {
108 typename cont_t::iterator i=d_cont.find(t);
87da00e7 109 entry e={ now+(ttl ? ttl : d_ttl), tries ? tries : d_limit};
49f076e8 110
c214232f 111 if(i==d_cont.end()) {
49f076e8 112 d_cont[t]=e;
3ddb9247
PD
113 }
114 else if(i->second.ttd > e.ttd || (i->second.count) < e.count)
c214232f 115 d_cont[t]=e;
8a5602d4 116 }
3ddb9247 117
30ee601a 118 unsigned int size() const
8a5602d4 119 {
705f31ae 120 return (unsigned int)d_cont.size();
49f076e8 121 }
30ee601a
RG
122
123 void clear()
124 {
125 d_cont.clear();
126 }
49f076e8 127private:
b747bce8
AT
128 unsigned int d_limit;
129 time_t d_ttl;
49f076e8 130 time_t d_last_clean;
3ddb9247 131 struct entry
49f076e8
BH
132 {
133 time_t ttd;
b747bce8 134 unsigned int count;
49f076e8
BH
135 };
136 typedef map<Thing,entry> cont_t;
137 cont_t d_cont;
138};
139
140
eefd15f9 141/** Class that implements a decaying EWMA.
36c5ee42 142 This class keeps an exponentially weighted moving average which, additionally, decays over time.
eefd15f9
BH
143 The decaying is only done on get.
144*/
145class DecayingEwma
146{
147public:
3ddb9247 148 DecayingEwma() : d_val(0.0)
71dea98d
BH
149 {
150 d_needinit=true;
118dcc93 151 d_last.tv_sec = d_last.tv_usec = 0;
71dea98d 152 d_lastget=d_last;
36c5ee42 153 }
d6d5dea7 154
71dea98d 155 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 156 {
71dea98d 157 }
d6d5dea7 158
a712cb56 159 void submit(int val, const struct timeval* tv)
71dea98d 160 {
a712cb56 161 struct timeval now=*tv;
71dea98d
BH
162
163 if(d_needinit) {
164 d_last=now;
21f0f88b 165 d_lastget=now;
71dea98d 166 d_needinit=false;
21f0f88b 167 d_val = val;
71dea98d 168 }
21f0f88b
BH
169 else {
170 float diff= makeFloat(d_last - now);
71dea98d 171
21f0f88b
BH
172 d_last=now;
173 double factor=exp(diff)/2.0; // might be '0.5', or 0.0001
3ddb9247 174 d_val=(float)((1-factor)*val+ (float)factor*d_val);
21f0f88b 175 }
eefd15f9 176 }
d6d5dea7 177
a712cb56 178 double get(const struct timeval* tv)
71dea98d 179 {
a712cb56 180 struct timeval now=*tv;
71dea98d 181 float diff=makeFloat(d_lastget-now);
36c5ee42 182 d_lastget=now;
705f31ae 183 float factor=exp(diff/60.0f); // is 1.0 or less
eefd15f9
BH
184 return d_val*=factor;
185 }
186
30ee601a 187 double peek(void) const
a82ce718
PD
188 {
189 return d_val;
190 }
191
996c89cc 192 bool stale(time_t limit) const
9fdf67d5 193 {
71dea98d 194 return limit > d_lastget.tv_sec;
9fdf67d5
BH
195 }
196
eefd15f9 197private:
71dea98d
BH
198 struct timeval d_last; // stores time
199 struct timeval d_lastget; // stores time
200 float d_val;
201 bool d_needinit;
202};
203
628e2c7b
PA
204template<class Thing> class Counters : public boost::noncopyable
205{
206public:
207 Counters()
208 {
209 }
30ee601a 210 unsigned long value(const Thing& t) const
628e2c7b 211 {
30ee601a 212 typename cont_t::const_iterator i=d_cont.find(t);
628e2c7b
PA
213
214 if(i==d_cont.end()) {
215 return 0;
216 }
217 return (unsigned long)i->second;
218 }
219 unsigned long incr(const Thing& t)
220 {
221 typename cont_t::iterator i=d_cont.find(t);
222
223 if(i==d_cont.end()) {
224 d_cont[t]=1;
225 return 1;
226 }
227 else {
228 if (i->second < std::numeric_limits<unsigned long>::max())
229 i->second++;
230 return (unsigned long)i->second;
231 }
232 }
233 unsigned long decr(const Thing& t)
234 {
235 typename cont_t::iterator i=d_cont.find(t);
236
237 if(i!=d_cont.end() && --i->second == 0) {
238 d_cont.erase(i);
239 return 0;
240 } else
241 return (unsigned long)i->second;
242 }
243 void clear(const Thing& t)
244 {
245 typename cont_t::iterator i=d_cont.find(t);
246
247 if(i!=d_cont.end()) {
248 d_cont.erase(i);
249 }
250 }
30ee601a
RG
251 void clear()
252 {
253 d_cont.clear();
254 }
255 size_t size() const
406f46f9 256 {
257 return d_cont.size();
258 }
628e2c7b
PA
259private:
260 typedef map<Thing,unsigned long> cont_t;
261 cont_t d_cont;
262};
263
71dea98d 264
bb4bdbaf 265class SyncRes : public boost::noncopyable
00a19ff7
BH
266{
267public:
3ddb9247 268 enum LogMode { LogNone, Log, Store};
9065eb05 269 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, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult *lwr)> asyncresolve_t;
77499b05 270
a712cb56
RG
271 struct EDNSStatus
272 {
273 EDNSStatus() : mode(UNKNOWN), modeSetAt(0) {}
274 enum EDNSMode { UNKNOWN=0, EDNSOK=1, EDNSIGNORANT=2, NOEDNS=3 } mode;
275 time_t modeSetAt;
276 };
277
278 //! This represents a number of decaying Ewmas, used to store performance per nameserver-name.
279 /** Modelled to work mostly like the underlying DecayingEwma. After you've called get,
280 d_best is filled out with the best address for this collection */
281 struct DecayingEwmaCollection
282 {
283 void submit(const ComboAddress& remote, int usecs, const struct timeval* now)
284 {
285 collection_t::iterator pos;
286 for(pos=d_collection.begin(); pos != d_collection.end(); ++pos)
287 if(pos->first==remote)
288 break;
289 if(pos!=d_collection.end()) {
290 pos->second.submit(usecs, now);
291 }
292 else {
293 DecayingEwma de;
294 de.submit(usecs, now);
295 d_collection.push_back(make_pair(remote, de));
296 }
297 }
298
299 double get(const struct timeval* now)
300 {
301 if(d_collection.empty())
302 return 0;
303 double ret=std::numeric_limits<double>::max();
304 double tmp;
305 for(collection_t::iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos) {
306 if((tmp=pos->second.get(now)) < ret) {
307 ret=tmp;
308 d_best=pos->first;
309 }
310 }
311
312 return ret;
313 }
314
315 bool stale(time_t limit) const
316 {
317 for(collection_t::const_iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos)
318 if(!pos->second.stale(limit))
319 return false;
320 return true;
321 }
322
323 typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
324 collection_t d_collection;
325 ComboAddress d_best;
326 };
327
328 typedef map<DNSName, DecayingEwmaCollection> nsspeeds_t;
329 typedef map<ComboAddress, EDNSStatus> ednsstatus_t;
330
331 struct AuthDomain
332 {
333 vector<ComboAddress> d_servers;
334 bool d_rdForward;
335 typedef multi_index_container <
336 DNSRecord,
337 indexed_by <
338 ordered_non_unique<
339 composite_key< DNSRecord,
340 member<DNSRecord, DNSName, &DNSRecord::d_name>,
341 member<DNSRecord, uint16_t, &DNSRecord::d_type>
342 >,
343 composite_key_compare<std::less<DNSName>, std::less<uint16_t> >
344 >
345 >
346 > records_t;
347 records_t d_records;
348 };
349
350 typedef map<DNSName, AuthDomain> domainmap_t;
351 typedef Throttle<boost::tuple<ComboAddress,DNSName,uint16_t> > throttle_t;
352 typedef Counters<ComboAddress> fails_t;
353
354 struct ThreadLocalStorage {
355 NegCache negcache;
356 nsspeeds_t nsSpeeds;
357 throttle_t throttle;
358 ednsstatus_t ednsstatus;
359 fails_t fails;
360 std::shared_ptr<domainmap_t> domainmap;
361 };
362
9065eb05
RG
363 static void setDefaultLogMode(LogMode lm)
364 {
365 s_lm = lm;
366 }
367 static void doEDNSDumpAndClose(int fd);
368 static uint64_t doDumpNSSpeeds(int fd);
369 static int getRootNS(struct timeval now, asyncresolve_t asyncCallback);
370 static void clearDelegationOnly()
371 {
372 s_delegationOnly.clear();
373 }
374 static void addDelegationOnly(const DNSName& name)
375 {
376 s_delegationOnly.insert(name);
377 }
378 static void addDontQuery(const std::string& mask)
379 {
380 if (!s_dontQuery)
381 s_dontQuery = std::unique_ptr<NetmaskGroup>(new NetmaskGroup());
bb4bdbaf 382
9065eb05
RG
383 s_dontQuery->addMask(mask);
384 }
385 static void addDontQuery(const Netmask& mask)
386 {
387 if (!s_dontQuery)
388 s_dontQuery = std::unique_ptr<NetmaskGroup>(new NetmaskGroup());
389
390 s_dontQuery->addMask(mask);
391 }
392 static void clearDontQuery()
393 {
394 s_dontQuery = nullptr;
395 }
396 static void parseEDNSSubnetWhitelist(const std::string& wlist);
397 static void addEDNSSubnet(const Netmask& subnet)
398 {
399 s_ednssubnets.addMask(subnet);
400 }
401 static void addEDNSDomain(const DNSName& domain)
402 {
403 s_ednsdomains.add(domain);
404 }
405 static void clearEDNSSubnets()
406 {
407 s_ednssubnets.clear();
408 }
409 static void clearEDNSDomains()
410 {
411 s_ednsdomains = SuffixMatchNode();
412 }
a712cb56
RG
413 static void pruneNSSpeeds(time_t limit)
414 {
415 for(auto i = t_sstorage.nsSpeeds.begin(), end = t_sstorage.nsSpeeds.end(); i != end; ) {
416 if(i->second.stale(limit)) {
417 i = t_sstorage.nsSpeeds.erase(i);
418 }
419 else {
420 ++i;
421 }
422 }
423 }
424 static uint64_t getNSSpeedsSize()
425 {
426 return t_sstorage.nsSpeeds.size();
427 }
428 static void submitNSSpeed(const DNSName& server, const ComboAddress& ca, uint32_t usec, const struct timeval* now)
429 {
430 t_sstorage.nsSpeeds[server].submit(ca, usec, now);
431 }
432 static void clearNSSpeeds()
433 {
434 t_sstorage.nsSpeeds.clear();
435 }
436 static EDNSStatus::EDNSMode getEDNSStatus(const ComboAddress& server)
437 {
438 const auto& it = t_sstorage.ednsstatus.find(server);
439 if (it == t_sstorage.ednsstatus.end())
440 return EDNSStatus::UNKNOWN;
441
442 return it->second.mode;
443 }
444 static uint64_t getEDNSStatusesSize()
445 {
446 return t_sstorage.ednsstatus.size();
447 }
448 static void clearEDNSStatuses()
449 {
450 t_sstorage.ednsstatus.clear();
451 }
452 static uint64_t getThrottledServersSize()
453 {
454 return t_sstorage.throttle.size();
455 }
456 static void clearThrottle()
457 {
458 t_sstorage.throttle.clear();
459 }
460 static bool isThrottled(time_t now, const ComboAddress& server, const DNSName& target, uint16_t qtype)
461 {
462 return t_sstorage.throttle.shouldThrottle(now, boost::make_tuple(server, target, qtype));
463 }
464 static bool isThrottled(time_t now, const ComboAddress& server)
465 {
466 return t_sstorage.throttle.shouldThrottle(now, boost::make_tuple(server, "", 0));
467 }
468 static void doThrottle(time_t now, const ComboAddress& server, time_t duration, unsigned int tries)
469 {
470 t_sstorage.throttle.throttle(now, boost::make_tuple(server, "", 0), duration, tries);
471 }
472 static uint64_t getFailedServersSize()
473 {
474 return t_sstorage.fails.size();
475 }
476 static void clearFailedServers()
477 {
478 t_sstorage.fails.clear();
479 }
480 static unsigned long getServerFailsCount(const ComboAddress& server)
481 {
482 return t_sstorage.fails.value(server);
483 }
484
485 static void clearNegCache()
486 {
487 t_sstorage.negcache.clear();
488 }
489
490 static uint64_t getNegCacheSize()
491 {
492 return t_sstorage.negcache.size();
493 }
494
495 static void pruneNegCache(unsigned int maxEntries)
496 {
497 t_sstorage.negcache.prune(maxEntries);
498 }
499
500 static uint64_t wipeNegCache(const DNSName& name, bool subtree = false)
501 {
502 return t_sstorage.negcache.wipe(name, subtree);
503 }
504
505 static void setDomainMap(std::shared_ptr<domainmap_t> newMap)
506 {
507 t_sstorage.domainmap = newMap;
508 }
509
510 static const std::shared_ptr<domainmap_t> getDomainMap()
511 {
512 return t_sstorage.domainmap;
513 }
9065eb05
RG
514
515 explicit SyncRes(const struct timeval& now);
30ee601a 516
e325f20c 517 int beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret);
c836dc19
BH
518 void setId(int id)
519 {
77499b05 520 if(doLog())
9fdf67d5 521 d_prefix="["+itoa(id)+"] ";
c836dc19 522 }
3ddb9247
PD
523
524 void setLogMode(LogMode lm)
77499b05
BH
525 {
526 d_lm = lm;
527 }
528
69cbdef9 529 bool doLog() const
c836dc19 530 {
3ddb9247 531 return d_lm != LogNone;
c836dc19 532 }
77499b05 533
c836dc19
BH
534 void setCacheOnly(bool state=true)
535 {
536 d_cacheonly=state;
537 }
2188dcc3
BH
538
539 void setDoEDNS0(bool state=true)
540 {
541 d_doEDNS0=state;
542 }
543
30ee601a
RG
544 void setDoDNSSEC(bool state=true)
545 {
546 d_doDNSSEC=state;
547 }
548
549 void setWantsRPZ(bool state=true)
550 {
551 d_wantsRPZ=state;
552 }
553
554 bool getWantsRPZ() const
555 {
556 return d_wantsRPZ;
557 }
558
559 void setIncomingECSFound(bool state=true)
560 {
561 d_incomingECSFound=state;
562 }
563
77499b05
BH
564 string getTrace() const
565 {
566 return d_trace.str();
567 }
568
a3e7b735 569 void setLuaEngine(shared_ptr<RecursorLua4> pdl)
3457a2a0 570 {
571 d_pdl = pdl;
572 }
573
3762e821 574 bool wasVariable() const
575 {
576 return d_wasVariable;
577 }
3457a2a0 578
9fc36e90
PL
579 bool wasOutOfBand() const
580 {
581 return d_wasOutOfBand;
582 }
583
30ee601a
RG
584 struct timeval getNow() const
585 {
586 return d_now;
587 }
588
a672e9de
PL
589 void setSkipCNAMECheck(bool skip = false)
590 {
591 d_skipCNAMECheck = skip;
592 }
593
30ee601a
RG
594 void setIncomingECS(boost::optional<const EDNSSubnetOpts&> incomingECS)
595 {
596 d_incomingECS = incomingECS;
597 }
598
599#ifdef HAVE_PROTOBUF
600 void setInitialRequestId(boost::optional<const boost::uuids::uuid&> initialRequestId)
601 {
602 d_initialRequestId = initialRequestId;
603 }
604#endif
605
606 void setAsyncCallback(asyncresolve_t func)
607 {
608 d_asyncResolve = func;
609 }
3ddb9247 610
a712cb56
RG
611 static thread_local ThreadLocalStorage t_sstorage;
612
aebb81e4 613 static std::atomic<uint64_t> s_queries;
614 static std::atomic<uint64_t> s_outgoingtimeouts;
615 static std::atomic<uint64_t> s_outgoing4timeouts;
616 static std::atomic<uint64_t> s_outgoing6timeouts;
617 static std::atomic<uint64_t> s_throttledqueries;
618 static std::atomic<uint64_t> s_dontqueries;
619 static std::atomic<uint64_t> s_outqueries;
620 static std::atomic<uint64_t> s_tcpoutqueries;
621 static std::atomic<uint64_t> s_nodelegated;
622 static std::atomic<uint64_t> s_unreachables;
9065eb05 623
9065eb05
RG
624 static string s_serverID;
625 static unsigned int s_minimumTTL;
626 static unsigned int s_maxqperq;
627 static unsigned int s_maxtotusec;
628 static unsigned int s_maxdepth;
a9af3782 629 static unsigned int s_maxnegttl;
c3e753c7 630 static unsigned int s_maxcachettl;
1051f8a9
BH
631 static unsigned int s_packetcachettl;
632 static unsigned int s_packetcacheservfailttl;
628e2c7b
PA
633 static unsigned int s_serverdownmaxfails;
634 static unsigned int s_serverdownthrottletime;
e9f9b8ec
RG
635 static uint8_t s_ecsipv4limit;
636 static uint8_t s_ecsipv6limit;
9065eb05
RG
637 static bool s_doIPv6;
638 static bool s_noEDNSPing;
639 static bool s_noEDNS;
640 static bool s_rootNXTrust;
1051f8a9 641 static bool s_nopacketcache;
3ddb9247 642
a712cb56
RG
643 std::unordered_map<std::string,bool> d_discardedPolicies;
644 DNSFilterEngine::Policy d_appliedPolicy;
645 unsigned int d_outqueries;
646 unsigned int d_tcpoutqueries;
647 unsigned int d_throttledqueries;
648 unsigned int d_timeouts;
649 unsigned int d_unreachables;
650 unsigned int d_totUsec;
651 ComboAddress d_requestor;
49a699c4 652
00a19ff7 653private:
a712cb56 654
9065eb05
RG
655 static std::unordered_set<DNSName> s_delegationOnly;
656 static NetmaskGroup s_ednssubnets;
657 static SuffixMatchNode s_ednsdomains;
658 static LogMode s_lm;
659 static std::unique_ptr<NetmaskGroup> s_dontQuery;
660
661 struct GetBestNSAnswer
662 {
663 DNSName qname;
664 set<pair<DNSName,DNSName> > bestns;
665 uint8_t qtype; // only A and AAAA anyhow
666 bool operator<(const GetBestNSAnswer &b) const
667 {
668 return boost::tie(qname, qtype, bestns) <
669 boost::tie(b.qname, b.qtype, b.bestns);
670 }
671 };
672
fa1b87ff 673 int doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret,
7c3398aa 674 unsigned int depth, set<GetBestNSAnswer>&beenthere);
6dfff36f
RG
675 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);
676 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);
677
7c3398aa
RG
678 int doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere);
679 bool doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res);
69cbdef9 680 domainmap_t::const_iterator getBestAuthZone(DNSName* qname) const;
7c3398aa
RG
681 bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res);
682 bool doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res);
683 void getBestNSFromCache(const DNSName &qname, const QType &qtype, vector<DNSRecord>&bestns, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>& beenthere);
684 DNSName getBestNSNamesFromCache(const DNSName &qname, const QType &qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>&beenthere);
c5c066bf 685
fa1b87ff 686 inline vector<DNSName> shuffleInSpeedOrder(NsSet &nameservers, const string &prefix);
69cbdef9 687 bool moreSpecificThan(const DNSName& a, const DNSName &b) const;
7c3398aa 688 vector<ComboAddress> getAddrs(const DNSName &qname, unsigned int depth, set<GetBestNSAnswer>& beenthere);
26ca3513 689
69cbdef9
RG
690 bool nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers);
691 bool nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress&);
26ca3513
RG
692 bool throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery);
693
694 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);
6dfff36f
RG
695 RCode::rcodes_ updateCacheFromRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, const DNSName& auth, bool wasForwarded, const boost::optional<Netmask>);
696 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);
26ca3513 697
6dfff36f 698 bool doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector<DNSRecord> &ret);
db50a7f4 699
30ee601a
RG
700 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) const;
701
e9f9b8ec
RG
702 boost::optional<Netmask> getEDNSSubnetMask(const ComboAddress& local, const DNSName&dn, const ComboAddress& rem);
703
0b29b9c5
RG
704 void setUpdatingRootNS()
705 {
706 d_updatingRootNS = true;
707 }
708
709
77499b05 710 ostringstream d_trace;
a3e7b735 711 shared_ptr<RecursorLua4> d_pdl;
30ee601a
RG
712 boost::optional<const EDNSSubnetOpts&> d_incomingECS;
713#ifdef HAVE_PROTOBUF
714 boost::optional<const boost::uuids::uuid&> d_initialRequestId;
715#endif
716 asyncresolve_t d_asyncResolve{nullptr};
717 struct timeval d_now;
c836dc19 718 string d_prefix;
b88526ce
PL
719
720 /* When d_cacheonly is set to true, we will only check the cache.
721 * This is set when the RD bit is unset in the incoming query
722 */
c836dc19 723 bool d_cacheonly;
30ee601a
RG
724 bool d_doDNSSEC;
725 bool d_doEDNS0{true};
726 bool d_incomingECSFound{false};
727 bool d_skipCNAMECheck{false};
0b29b9c5 728 bool d_updatingRootNS{false};
30ee601a
RG
729 bool d_wantsRPZ{true};
730 bool d_wasOutOfBand{false};
731 bool d_wasVariable{false};
57769f13 732
77499b05 733 LogMode d_lm;
00a19ff7 734};
ac0e821b 735
5c633640 736class Socket;
a9af3782 737/* external functions, opaque to us */
5c633640 738int asendtcp(const string& data, Socket* sock);
a683e8bd 739int arecvtcp(string& data, size_t len, Socket* sock, bool incompleteOkay);
1d5b3ce6
BH
740
741
742struct PacketID
743{
825fa717 744 PacketID() : id(0), type(0), sock(0), inNeeded(0), inIncompleteOkay(false), outPos(0), nearMisses(0), fd(-1)
67770277
BH
745 {
746 memset(&remote, 0, sizeof(remote));
747 }
1d5b3ce6
BH
748
749 uint16_t id; // wait for a specific id/remote pair
91ffe057 750 uint16_t type; // and this is its type
996c89cc 751 ComboAddress remote; // this is the remote
3ddb9247 752 DNSName domain; // this is the question
1d5b3ce6
BH
753
754 Socket* sock; // or wait for an event on a TCP fd
1d5b3ce6 755 string inMSG; // they'll go here
a683e8bd 756 size_t inNeeded; // if this is set, we'll read until inNeeded bytes are read
825fa717 757 bool inIncompleteOkay;
1d5b3ce6
BH
758
759 string outMSG; // the outgoing message that needs to be sent
760 string::size_type outPos; // how far we are along in the outMSG
761
96f81a93
BH
762 typedef set<uint16_t > chain_t;
763 mutable chain_t chain;
91ffe057 764 mutable uint32_t nearMisses; // number of near misses - host correct, id wrong
4ef015cd 765 int fd;
35ce8576 766
1d5b3ce6
BH
767 bool operator<(const PacketID& b) const
768 {
769 int ourSock= sock ? sock->getHandle() : 0;
770 int bSock = b.sock ? b.sock->getHandle() : 0;
787e5eab 771 if( tie(remote, ourSock, type) < tie(b.remote, bSock, b.type))
0d5f0a9f 772 return true;
787e5eab 773 if( tie(remote, ourSock, type) > tie(b.remote, bSock, b.type))
0d5f0a9f
BH
774 return false;
775
c5c066bf 776 return tie(domain, fd, id) < tie(b.domain, b.fd, b.id);
1d5b3ce6
BH
777 }
778};
779
3ddb9247 780struct PacketIDBirthdayCompare: public std::binary_function<PacketID, PacketID, bool>
96f81a93
BH
781{
782 bool operator()(const PacketID& a, const PacketID& b) const
783 {
784 int ourSock= a.sock ? a.sock->getHandle() : 0;
785 int bSock = b.sock ? b.sock->getHandle() : 0;
787e5eab 786 if( tie(a.remote, ourSock, a.type) < tie(b.remote, bSock, b.type))
96f81a93 787 return true;
787e5eab 788 if( tie(a.remote, ourSock, a.type) > tie(b.remote, bSock, b.type))
96f81a93
BH
789 return false;
790
72849e12 791 return a.domain < b.domain;
96f81a93
BH
792 }
793};
f26bf547
RG
794extern thread_local std::unique_ptr<MemRecursorCache> t_RC;
795extern thread_local std::unique_ptr<RecursorPacketCache> t_packetCache;
d2392145 796typedef MTasker<PacketID,string> MT_t;
f26bf547 797extern thread_local std::unique_ptr<MT_t> MT;
1d5b3ce6
BH
798
799struct RecursorStats
800{
aebb81e4 801 std::atomic<uint64_t> servFails;
802 std::atomic<uint64_t> nxDomains;
803 std::atomic<uint64_t> noErrors;
804 std::atomic<uint64_t> answers0_1, answers1_10, answers10_100, answers100_1000, answersSlow;
805 std::atomic<uint64_t> auth4Answers0_1, auth4Answers1_10, auth4Answers10_100, auth4Answers100_1000, auth4AnswersSlow;
806 std::atomic<uint64_t> auth6Answers0_1, auth6Answers1_10, auth6Answers10_100, auth6Answers100_1000, auth6AnswersSlow;
08f3f638 807 double avgLatencyUsec;
aebb81e4 808 std::atomic<uint64_t> qcounter; // not increased for unauth packets
809 std::atomic<uint64_t> ipv6qcounter;
810 std::atomic<uint64_t> tcpqcounter;
811 std::atomic<uint64_t> unauthorizedUDP; // when this is increased, qcounter isn't
812 std::atomic<uint64_t> unauthorizedTCP; // when this is increased, qcounter isn't
813 std::atomic<uint64_t> policyDrops;
814 std::atomic<uint64_t> tcpClientOverflow;
815 std::atomic<uint64_t> clientParseError;
816 std::atomic<uint64_t> serverParseError;
817 std::atomic<uint64_t> tooOldDrops;
818 std::atomic<uint64_t> unexpectedCount;
819 std::atomic<uint64_t> caseMismatchCount;
820 std::atomic<uint64_t> spoofCount;
821 std::atomic<uint64_t> resourceLimits;
822 std::atomic<uint64_t> overCapacityDrops;
823 std::atomic<uint64_t> ipv6queries;
824 std::atomic<uint64_t> chainResends;
825 std::atomic<uint64_t> nsSetInvalidations;
826 std::atomic<uint64_t> ednsPingMatches;
827 std::atomic<uint64_t> ednsPingMismatches;
828 std::atomic<uint64_t> noPingOutQueries, noEdnsOutQueries;
829 std::atomic<uint64_t> packetCacheHits;
830 std::atomic<uint64_t> noPacketError;
831 std::atomic<uint64_t> ignoredCount;
5e3de507 832 time_t startupTime;
aebb81e4 833 std::atomic<uint64_t> dnssecQueries;
ec6eacbc 834 unsigned int maxMThreadStackUsage;
849fe8d2
PL
835 std::atomic<uint64_t> dnssecValidations; // should be the sum of all dnssecResult* stats
836 std::map<vState, std::atomic<uint64_t> > dnssecResults;
7a25883a 837 std::map<DNSFilterEngine::PolicyKind, std::atomic<uint64_t> > policyResults;
b3b5459d 838};
996c89cc 839
0e408828 840//! represents a running TCP/IP client session
cd989c87 841class TCPConnection : public boost::noncopyable
0e408828 842{
50a5ef72 843public:
cd989c87
BH
844 TCPConnection(int fd, const ComboAddress& addr);
845 ~TCPConnection();
3ddb9247 846
30ee601a 847 int getFD() const
cd989c87
BH
848 {
849 return d_fd;
850 }
b841314c
RG
851 enum stateenum {BYTE0, BYTE1, GETQUESTION, DONE} state{BYTE0};
852 uint16_t qlen{0};
853 uint16_t bytesread{0};
cd989c87
BH
854 const ComboAddress d_remote;
855 char data[65535]; // damn
fde296a3 856 size_t queriesCount{0};
0e408828 857
50a5ef72 858 static unsigned int getCurrentConnections() { return s_currentConnections; }
50a5ef72 859private:
cd989c87 860 const int d_fd;
1bc9e6bd 861 static AtomicCounter s_currentConnections; //!< total number of current TCP connections
0e408828
BH
862};
863
44971ca0
PD
864class ImmediateServFailException
865{
866public:
867 ImmediateServFailException(string r){reason=r;};
868
869 string reason; //! Print this to tell the user what went wrong
870};
0e408828 871
f635ed7b 872#if (__GNUC__ == 4 && __GNUC_MINOR__ == 2)
873typedef boost::circular_buffer<SComboAddress> addrringbuf_t;
874#else
875typedef boost::circular_buffer<ComboAddress> addrringbuf_t;
876#endif
f26bf547 877extern thread_local std::unique_ptr<addrringbuf_t> t_servfailremotes, t_largeanswerremotes, t_remotes;
a9af3782 878
f26bf547
RG
879extern thread_local std::unique_ptr<boost::circular_buffer<pair<DNSName,uint16_t> > > t_queryring, t_servfailqueryring;
880extern thread_local std::shared_ptr<NetmaskGroup> t_allowFrom;
674cf0f6 881string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end);
77499b05 882string doTraceRegex(vector<string>::const_iterator begin, vector<string>::const_iterator end);
18af64a8 883void parseACLs();
1d5b3ce6 884extern RecursorStats g_stats;
c3828c03 885extern unsigned int g_numThreads;
b33c2462 886extern uint16_t g_outgoingEDNSBufsize;
12ce523e 887
888
ee1ada80 889std::string reloadAuthAndForwards();
c1d73d94 890ComboAddress parseIPAndPort(const std::string& input, uint16_t port);
1652a63e 891ComboAddress getQueryLocalAddress(int family, uint16_t port);
3427fa8a 892typedef boost::function<void*(void)> pipefunc_t;
49a699c4 893void broadcastFunction(const pipefunc_t& func, bool skipSelf = false);
8171ab83 894void distributeAsyncFunction(const std::string& question, const pipefunc_t& func);
3427fa8a 895
e325f20c 896int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret);
3427fa8a 897
13034931 898template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool skipSelf=false);
3427fa8a 899
9065eb05 900std::shared_ptr<SyncRes::domainmap_t> parseAuthAndForwards();
13034931
BH
901uint64_t* pleaseGetNsSpeedsSize();
902uint64_t* pleaseGetCacheSize();
903uint64_t* pleaseGetNegCacheSize();
904uint64_t* pleaseGetCacheHits();
905uint64_t* pleaseGetCacheMisses();
906uint64_t* pleaseGetConcurrentQueries();
907uint64_t* pleaseGetThrottleSize();
16beeaa4
BH
908uint64_t* pleaseGetPacketCacheHits();
909uint64_t* pleaseGetPacketCacheSize();
86f3ca51 910uint64_t* pleaseWipeCache(const DNSName& canon, bool subtree=false);
911uint64_t* pleaseWipePacketCache(const DNSName& canon, bool subtree);
912uint64_t* pleaseWipeAndCountNegCache(const DNSName& canon, bool subtree=false);
2c78bd57 913void doCarbonDump(void*);
9065eb05 914void primeHints(void);
795215f2 915
f703f766 916extern __thread struct timeval g_now;
f3d6a5c5 917
4898a348 918#ifdef HAVE_PROTOBUF
f26bf547 919extern thread_local std::unique_ptr<boost::uuids::random_generator> t_uuidGenerator;
4898a348 920#endif