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