]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/recursordist/syncres.hh
rec: CVE-2023-50387 and CVE-2023-50868
[thirdparty/pdns.git] / pdns / recursordist / 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>
d6d5dea7 38#include <boost/utility.hpp>
9f6a31ff 39#include "circular_buffer.hh"
1d5b3ce6 40#include "sstuff.hh"
9fdf67d5 41#include "recursor_cache.hh"
1d5b3ce6 42#include "mtasker.hh"
a9af3782 43#include "iputils.hh"
e46b0f2f 44#include "validate-recursor.hh"
b40562da 45#include "ednssubnet.hh"
644dd1da 46#include "filterpo.hh"
39ce10b2 47#include "negcache.hh"
5216ddcc 48#include "proxy-protocol.hh"
559b6c93 49#include "sholder.hh"
a71665e5 50#include "histogram.hh"
bd468718 51#include "stat_t.hh"
2a17f6c6 52#include "tcpiohandler.hh"
0f14442c 53#include "rec-eventtrace.hh"
2ed8065e 54#include "logr.hh"
7d3d2f4f 55#include "rec-tcounters.hh"
3e5667f9 56#include "ednsextendederror.hh"
644dd1da 57
20642494 58#ifdef HAVE_CONFIG_H
4898a348 59#include "config.h"
20642494
PL
60#endif
61
4898a348 62#include <boost/uuid/uuid.hpp>
b9fa43e0
OM
63#ifdef HAVE_FSTRM
64#include "fstrm_logger.hh"
65#endif /* HAVE_FSTRM */
4898a348 66
2b20e918 67extern GlobalStateHolder<SuffixMatchNode> g_xdnssec;
559b6c93
PL
68extern GlobalStateHolder<SuffixMatchNode> g_dontThrottleNames;
69extern GlobalStateHolder<NetmaskGroup> g_dontThrottleNetmasks;
b4ae1398 70extern GlobalStateHolder<SuffixMatchNode> g_DoTToAuthNames;
559b6c93 71
c21f8271
OM
72enum class AdditionalMode : uint8_t; // defined in rec-lua-conf.hh
73
a3e7b735 74class RecursorLua4;
620db2c8 75
f688bbaa 76using NsSet = std::unordered_map<DNSName, pair<vector<ComboAddress>, bool>>;
49f076e8 77
ccfadb6c 78extern std::unique_ptr<NegCache> g_negCache;
a0c1d047 79
bb4bdbaf 80class SyncRes : public boost::noncopyable
00a19ff7
BH
81{
82public:
f8f66c91
OM
83 enum LogMode
84 {
85 LogNone,
86 Log,
87 Store
88 };
32b3e0ef 89 using asyncresolve_t = std::function<LWResult::Result(const ComboAddress&, const DNSName&, int, bool, bool, int, struct timeval*, boost::optional<Netmask>&, const ResolveContext&, LWResult*, bool*)>;
77499b05 90
f8f66c91
OM
91 enum class HardenNXD
92 {
93 No,
94 DNSSEC,
95 Yes
96 };
76e368a3 97
718c531d
OM
98 struct Context
99 {
100 boost::optional<EDNSExtendedError> extendedError;
101 vState state{vState::Indeterminate};
102 };
103
f688bbaa 104 vState getDSRecords(const DNSName& zone, dsmap_t& dsMap, bool onlyTA, unsigned int depth, const string& prefix, bool bogusOnNXD = true, bool* foundCut = nullptr);
1e332f68 105
3337c2f7 106 class AuthDomain
a712cb56 107 {
3337c2f7 108 public:
f688bbaa 109 using records_t = multi_index_container<
a712cb56 110 DNSRecord,
f8f66c91 111 indexed_by<
a712cb56 112 ordered_non_unique<
f8f66c91
OM
113 composite_key<DNSRecord,
114 member<DNSRecord, DNSName, &DNSRecord::d_name>,
115 member<DNSRecord, uint16_t, &DNSRecord::d_type>>,
f688bbaa 116 composite_key_compare<std::less<>, std::less<>>>>>;
3337c2f7 117
a712cb56 118 records_t d_records;
3337c2f7
RG
119 vector<ComboAddress> d_servers;
120 DNSName d_name;
121 bool d_rdForward{false};
122
487a76b7
FM
123 bool operator==(const AuthDomain& rhs) const;
124
f8f66c91
OM
125 [[nodiscard]] std::string print(const std::string& indent = "",
126 const std::string& indentLevel = " ") const;
08326ab9 127
f4e0e6ff 128 int getRecords(const DNSName& qname, QType qtype, std::vector<DNSRecord>& records) const;
f688bbaa 129 [[nodiscard]] bool isAuth() const
3337c2f7
RG
130 {
131 return d_servers.empty();
132 }
f688bbaa 133 [[nodiscard]] bool isForward() const
3337c2f7
RG
134 {
135 return !isAuth();
136 }
f688bbaa 137 [[nodiscard]] bool shouldRecurse() const
3337c2f7
RG
138 {
139 return d_rdForward;
140 }
f688bbaa 141 [[nodiscard]] const DNSName& getName() const
3337c2f7
RG
142 {
143 return d_name;
144 }
145
146 private:
147 void addSOA(std::vector<DNSRecord>& records) const;
a712cb56
RG
148 };
149
f688bbaa 150 using domainmap_t = std::unordered_map<DNSName, AuthDomain>;
b9715061 151
f8f66c91
OM
152 struct ThreadLocalStorage
153 {
a712cb56
RG
154 std::shared_ptr<domainmap_t> domainmap;
155 };
156
f688bbaa 157 static void setDefaultLogMode(LogMode logmode)
9065eb05 158 {
f688bbaa 159 s_lm = logmode;
9065eb05 160 }
3a016e92 161
10971f78 162 OptLog LogObject(const string& prefix);
3a016e92 163
f688bbaa
OM
164 static uint64_t doEDNSDump(int fileDesc);
165 static uint64_t doDumpNSSpeeds(int fileDesc);
166 static uint64_t doDumpThrottleMap(int fileDesc);
167 static uint64_t doDumpFailedServers(int fileDesc);
168 static uint64_t doDumpNonResolvingNS(int fileDesc);
169 static uint64_t doDumpSavedParentNSSets(int fileDesc);
170 static uint64_t doDumpDoTProbeMap(int fileDesc);
4e45e5bc 171
d61b8a01 172 static int getRootNS(struct timeval now, asyncresolve_t asyncCallback, unsigned int depth, Logr::log_t);
9065eb05
RG
173 static void addDontQuery(const std::string& mask)
174 {
f688bbaa 175 if (!s_dontQuery) {
2bbc9eb0 176 s_dontQuery = std::make_unique<NetmaskGroup>();
f688bbaa 177 }
9065eb05
RG
178 s_dontQuery->addMask(mask);
179 }
180 static void addDontQuery(const Netmask& mask)
181 {
f688bbaa 182 if (!s_dontQuery) {
2bbc9eb0 183 s_dontQuery = std::make_unique<NetmaskGroup>();
f688bbaa 184 }
9065eb05
RG
185 s_dontQuery->addMask(mask);
186 }
187 static void clearDontQuery()
188 {
189 s_dontQuery = nullptr;
190 }
3d324e00 191 static void parseEDNSSubnetAllowlist(const std::string& alist);
2fe3354d
CH
192 static void parseEDNSSubnetAddFor(const std::string& subnetlist);
193 static void addEDNSLocalSubnet(const std::string& subnet)
9065eb05 194 {
2fe3354d
CH
195 s_ednslocalsubnets.addMask(subnet);
196 }
197 static void addEDNSRemoteSubnet(const std::string& subnet)
198 {
199 s_ednsremotesubnets.addMask(subnet);
9065eb05
RG
200 }
201 static void addEDNSDomain(const DNSName& domain)
202 {
203 s_ednsdomains.add(domain);
204 }
2fe3354d 205 static void clearEDNSLocalSubnets()
9065eb05 206 {
2fe3354d
CH
207 s_ednslocalsubnets.clear();
208 }
209 static void clearEDNSRemoteSubnets()
210 {
211 s_ednsremotesubnets.clear();
9065eb05
RG
212 }
213 static void clearEDNSDomains()
214 {
215 s_ednsdomains = SuffixMatchNode();
216 }
03d26a97
OM
217
218 static void pruneNSSpeeds(time_t limit);
219 static uint64_t getNSSpeedsSize();
f688bbaa 220 static void submitNSSpeed(const DNSName& server, const ComboAddress& address, int usec, const struct timeval& now);
03d26a97 221 static void clearNSSpeeds();
f688bbaa 222 static float getNSSpeed(const DNSName& server, const ComboAddress& address);
03d26a97 223
f8f66c91
OM
224 struct EDNSStatus
225 {
226 EDNSStatus(const ComboAddress& arg) :
227 address(arg) {}
f6001854 228 ComboAddress address;
3a016e92 229 time_t ttd{0};
f8f66c91
OM
230 enum EDNSMode : uint8_t
231 {
232 EDNSOK = 0,
233 EDNSIGNORANT = 1,
234 NOEDNS = 2
235 } mode{EDNSOK};
a712cb56 236
f688bbaa 237 [[nodiscard]] std::string toString() const
f6001854 238 {
f8f66c91 239 const std::array<std::string, 3> modes = {"OK", "Ignorant", "No"};
f688bbaa
OM
240 auto umode = static_cast<unsigned int>(mode);
241 if (umode >= modes.size()) {
f6001854
OM
242 return "?";
243 }
f688bbaa 244 return modes.at(umode);
f6001854
OM
245 }
246 };
247
248 static EDNSStatus::EDNSMode getEDNSStatus(const ComboAddress& server);
249 static uint64_t getEDNSStatusesSize();
250 static void clearEDNSStatuses();
251 static void pruneEDNSStatuses(time_t cutoff);
4d064b36
OM
252
253 static uint64_t getThrottledServersSize();
e0d0cce7 254 static void pruneThrottledServers(time_t now);
4d064b36 255 static void clearThrottle();
e0d0cce7 256 static bool isThrottled(time_t now, const ComboAddress& server, const DNSName& target, QType qtype);
4d064b36
OM
257 static bool isThrottled(time_t now, const ComboAddress& server);
258 static void doThrottle(time_t now, const ComboAddress& server, time_t duration, unsigned int tries);
0e05dc93 259 static void doThrottle(time_t now, const ComboAddress& server, const DNSName& name, QType qtype, time_t duration, unsigned int tries);
314600f6 260 static void unThrottle(const ComboAddress& server, const DNSName& qname, QType qtype);
465c6d66
OM
261
262 static uint64_t getFailedServersSize();
263 static void clearFailedServers();
264 static void pruneFailedServers(time_t cutoff);
265 static unsigned long getServerFailsCount(const ComboAddress& server);
266
267 static void clearNonResolvingNS();
268 static uint64_t getNonResolvingNSSize();
269 static void pruneNonResolving(time_t cutoff);
d2b4d7ad
OM
270
271 static void clearSaveParentsNSSets();
272 static size_t getSaveParentsNSSetsSize();
273 static void pruneSaveParentsNSSets(time_t now);
274
a66fd34f
OM
275 static void pruneDoTProbeMap(time_t cutoff);
276
a712cb56
RG
277 static void setDomainMap(std::shared_ptr<domainmap_t> newMap)
278 {
645b217b 279 t_sstorage.domainmap = std::move(newMap);
a712cb56 280 }
f688bbaa 281 static std::shared_ptr<domainmap_t> getDomainMap()
a712cb56
RG
282 {
283 return t_sstorage.domainmap;
284 }
9065eb05 285
8a3a3822
RG
286 static void setECSScopeZeroAddress(const Netmask& scopeZeroMask)
287 {
288 s_ecsScopeZero.source = scopeZeroMask;
289 }
290
c9783016
RG
291 static void clearECSStats()
292 {
293 s_ecsqueries.store(0);
294 s_ecsresponses.store(0);
295
296 for (size_t idx = 0; idx < 32; idx++) {
297 SyncRes::s_ecsResponsesBySubnetSize4[idx].store(0);
298 }
299
300 for (size_t idx = 0; idx < 128; idx++) {
301 SyncRes::s_ecsResponsesBySubnetSize6[idx].store(0);
302 }
303 }
304
9065eb05 305 explicit SyncRes(const struct timeval& now);
30ee601a 306
f8f66c91 307 int beginResolve(const DNSName& qname, QType qtype, QClass qclass, vector<DNSRecord>& ret, unsigned int depth = 0);
378437c9 308 bool tryDoT(const DNSName& qname, QType qtype, const DNSName& nsName, ComboAddress address, time_t);
d8f3508b 309
cb273be5 310 void setId(int threadid)
c836dc19 311 {
cb273be5
OM
312 if (doLog()) {
313 d_prefix = "[" + std::to_string(threadid) + "] ";
314 }
315 }
316
317 void setId(const string& prefix)
c836dc19 318 {
cb273be5
OM
319 if (doLog()) {
320 d_prefix = "[" + prefix + "] ";
321 }
c836dc19 322 }
3ddb9247 323
f688bbaa 324 void setLogMode(LogMode logmode)
77499b05 325 {
f688bbaa 326 d_lm = logmode;
77499b05
BH
327 }
328
69cbdef9 329 bool doLog() const
c836dc19 330 {
3ddb9247 331 return d_lm != LogNone;
c836dc19 332 }
77499b05 333
116d1288 334 bool setCacheOnly(bool state = true)
c836dc19 335 {
116d1288
OM
336 bool old = d_cacheonly;
337 d_cacheonly = state;
338 return old;
339 }
340
87c4554a
OM
341 bool setRefreshAlmostExpired(bool doit)
342 {
343 auto old = d_refresh;
344 d_refresh = doit;
345 return old;
346 }
347
e2307ada 348 bool setQNameMinimization(bool state = true)
116d1288 349 {
e2307ada
OM
350 auto old = d_qNameMinimization;
351 d_qNameMinimization = state;
352 return old;
c836dc19 353 }
2188dcc3 354
52f994cd
OM
355 bool setQMFallbackMode(bool state = true)
356 {
f943cd2f
OM
357 auto old = d_qNameMinimizationFallbackMode;
358 d_qNameMinimizationFallbackMode = state;
52f994cd
OM
359 return old;
360 }
361
362 bool getQMFallbackMode() const
363 {
f943cd2f 364 return d_qNameMinimizationFallbackMode;
52f994cd 365 }
f943cd2f 366
f8f66c91 367 void setDoEDNS0(bool state = true)
2188dcc3 368 {
f8f66c91 369 d_doEDNS0 = state;
2188dcc3
BH
370 }
371
f8f66c91 372 void setDoDNSSEC(bool state = true)
30ee601a 373 {
f8f66c91 374 d_doDNSSEC = state;
30ee601a
RG
375 }
376
f8f66c91 377 void setDNSSECValidationRequested(bool requested = true)
0c43f455
RG
378 {
379 d_DNSSECValidationRequested = requested;
380 }
381
382 bool isDNSSECValidationRequested() const
383 {
384 return d_DNSSECValidationRequested;
385 }
386
e1636f82
RG
387 bool shouldValidate() const
388 {
389 return d_DNSSECValidationRequested && !d_wasOutOfBand;
390 }
391
f8f66c91 392 void setWantsRPZ(bool state = true)
30ee601a 393 {
f8f66c91 394 d_wantsRPZ = state;
30ee601a
RG
395 }
396
397 bool getWantsRPZ() const
398 {
399 return d_wantsRPZ;
400 }
401
77499b05
BH
402 string getTrace() const
403 {
404 return d_trace.str();
405 }
406
116d1288
OM
407 bool getQNameMinimization() const
408 {
409 return d_qNameMinimization;
410 }
411
a3e7b735 412 void setLuaEngine(shared_ptr<RecursorLua4> pdl)
3457a2a0 413 {
645b217b 414 d_pdl = std::move(pdl);
3457a2a0 415 }
416
3762e821 417 bool wasVariable() const
418 {
419 return d_wasVariable;
420 }
3457a2a0 421
9fc36e90
PL
422 bool wasOutOfBand() const
423 {
424 return d_wasOutOfBand;
425 }
426
30ee601a
RG
427 struct timeval getNow() const
428 {
429 return d_now;
430 }
431
44c4fc7a 432 // For debugging purposes
f688bbaa 433 void setNow(const struct timeval& tval)
44c4fc7a 434 {
f688bbaa 435 d_now = tval;
44c4fc7a
OM
436 }
437
f688bbaa 438 void setQuerySource(const ComboAddress& requestor, const boost::optional<const EDNSSubnetOpts&>& incomingECS);
edabff75 439 void setQuerySource(const Netmask& netmask);
30ee601a 440
f688bbaa 441 void setInitialRequestId(const boost::optional<const boost::uuids::uuid&>& initialRequestId)
30ee601a
RG
442 {
443 d_initialRequestId = initialRequestId;
444 }
63341e8d 445
3fe06137 446 void setOutgoingProtobufServers(std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>>& servers)
63341e8d 447 {
b773359c 448 d_outgoingProtobufServers = servers;
63341e8d 449 }
30ee601a 450
b9fa43e0 451#ifdef HAVE_FSTRM
10ba6d01 452 void setFrameStreamServers(std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& servers)
b9fa43e0
OM
453 {
454 d_frameStreamServers = servers;
455 }
456#endif /* HAVE_FSTRM */
457
30ee601a
RG
458 void setAsyncCallback(asyncresolve_t func)
459 {
645b217b 460 d_asyncResolve = std::move(func);
30ee601a 461 }
3ddb9247 462
4d2be65d
RG
463 vState getValidationState() const
464 {
465 return d_queryValidationState;
466 }
467
d4f08082
RG
468 void setQueryReceivedOverTCP(bool tcp)
469 {
470 d_queryReceivedOverTCP = tcp;
471 }
472
cfbcc0f3
OM
473 static bool isUnsupported(QType qtype)
474 {
e7cc83fd
OM
475 auto qcode = qtype.getCode();
476 // rfc6895 section 3.1, note ANY is 255 and falls outside the range
477 if (qcode >= QType::rfc6895MetaLowerBound && qcode <= QType::rfc6895MetaUpperBound) {
478 return true;
479 }
480 switch (qcode) {
cfbcc0f3 481 // Internal types
e7cc83fd 482 case QType::ENT: // aka TYPE0
cfbcc0f3 483 case QType::ADDR:
e7cc83fd 484 // RFC
bca5ab3a 485 case QType::rfc6895Reserved:
e7cc83fd
OM
486 // Other
487 case QType::RRSIG:
2cdafbde 488 case QType::NSEC3: // We use the same logic as for an auth: NSEC is queryable, NSEC3 not
e7cc83fd 489 case QType::OPT:
cfbcc0f3
OM
490 return true;
491 }
492 return false;
493 }
494
fa5f61e9
OM
495 static bool answerIsNOData(uint16_t requestedType, int rcode, const std::vector<DNSRecord>& records);
496
a712cb56
RG
497 static thread_local ThreadLocalStorage t_sstorage;
498
bd468718
RG
499 static pdns::stat_t s_ecsqueries;
500 static pdns::stat_t s_ecsresponses;
501 static std::map<uint8_t, pdns::stat_t> s_ecsResponsesBySubnetSize4;
502 static std::map<uint8_t, pdns::stat_t> s_ecsResponsesBySubnetSize6;
9065eb05 503
9065eb05
RG
504 static string s_serverID;
505 static unsigned int s_minimumTTL;
5cf4b2e7 506 static unsigned int s_minimumECSTTL;
9065eb05 507 static unsigned int s_maxqperq;
a49b0b40 508 static unsigned int s_maxnsperresolve;
86f95f85 509 static unsigned int s_maxnsaddressqperq;
9065eb05
RG
510 static unsigned int s_maxtotusec;
511 static unsigned int s_maxdepth;
a9af3782 512 static unsigned int s_maxnegttl;
b9473937 513 static unsigned int s_maxbogusttl;
c3e753c7 514 static unsigned int s_maxcachettl;
1051f8a9
BH
515 static unsigned int s_packetcachettl;
516 static unsigned int s_packetcacheservfailttl;
91505918 517 static unsigned int s_packetcachenegativettl;
628e2c7b
PA
518 static unsigned int s_serverdownmaxfails;
519 static unsigned int s_serverdownthrottletime;
e329b582
O
520 static unsigned int s_nonresolvingnsmaxfails;
521 static unsigned int s_nonresolvingnsthrottletime;
5fba6d59 522 static unsigned int s_unthrottle_n;
e7861cc4 523 static unsigned int s_ecscachelimitttl;
15e973d6
OM
524 static unsigned int s_maxvalidationsperq;
525 static unsigned int s_maxnsec3iterationsperq;
e9f9b8ec
RG
526 static uint8_t s_ecsipv4limit;
527 static uint8_t s_ecsipv6limit;
fd8898fb 528 static uint8_t s_ecsipv4cachelimit;
529 static uint8_t s_ecsipv6cachelimit;
66535fce
O
530 static bool s_ecsipv4nevercache;
531 static bool s_ecsipv6nevercache;
532
7b1d1a7d 533 static bool s_doIPv4;
9065eb05
RG
534 static bool s_doIPv6;
535 static bool s_noEDNSPing;
536 static bool s_noEDNS;
537 static bool s_rootNXTrust;
116d1288 538 static bool s_qnameminimization;
d40a915b 539 static HardenNXD s_hardenNXD;
87c4554a 540 static unsigned int s_refresh_ttlperc;
55badaf8 541 static unsigned int s_locked_ttlperc;
2bc7ddac 542 static int s_tcp_fast_open;
bffc1e7c 543 static bool s_tcp_fast_open_connect;
7c36f101 544 static bool s_dot_to_port_853;
78deedda 545 static unsigned int s_max_busy_dot_probes;
47571866 546 static unsigned int s_max_CNAMES_followed;
c88611d6 547 static unsigned int s_max_minimize_count;
3f15edc8 548 static unsigned int s_minimize_one_label;
0416940b
O
549
550 static const int event_trace_to_pb = 1;
551 static const int event_trace_to_log = 2;
552 static int s_event_trace_enabled;
1bb24087 553 static bool s_save_parent_ns_set;
3e5667f9 554 static bool s_addExtendedResolutionDNSErrors;
84d4747e 555
f8f66c91 556 std::unordered_map<std::string, bool> d_discardedPolicies;
a712cb56 557 DNSFilterEngine::Policy d_appliedPolicy;
b502d522 558 std::unordered_set<std::string> d_policyTags;
d6fd3cb8 559 boost::optional<string> d_routingTag;
e76b8a0d 560 ComboAddress d_fromAuthIP;
0f14442c 561 RecEventTrace d_eventTrace;
ab26d8d5 562 std::shared_ptr<Logr::Logger> d_slog = g_slog->withName("syncres");
3e5667f9 563 boost::optional<EDNSExtendedError> d_extendedError;
d6fd3cb8 564
f7b8cffa 565 unsigned int d_authzonequeries;
a712cb56
RG
566 unsigned int d_outqueries;
567 unsigned int d_tcpoutqueries;
7c36f101 568 unsigned int d_dotoutqueries;
a712cb56
RG
569 unsigned int d_throttledqueries;
570 unsigned int d_timeouts;
571 unsigned int d_unreachables;
572 unsigned int d_totUsec;
992fc809 573 unsigned int d_maxdepth{0};
f3493699 574 // Initialized ony once, as opposed to d_now which gets updated after outgoing requests
f688bbaa 575 struct timeval d_fixednow;
49a699c4 576
00a19ff7 577private:
2fe3354d
CH
578 ComboAddress d_requestor;
579 ComboAddress d_cacheRemote;
a712cb56 580
2fe3354d
CH
581 static NetmaskGroup s_ednslocalsubnets;
582 static NetmaskGroup s_ednsremotesubnets;
9065eb05 583 static SuffixMatchNode s_ednsdomains;
8a3a3822 584 static EDNSSubnetOpts s_ecsScopeZero;
9065eb05
RG
585 static LogMode s_lm;
586 static std::unique_ptr<NetmaskGroup> s_dontQuery;
f4e0e6ff 587 const static std::unordered_set<QType> s_redirectionQTypes;
9065eb05
RG
588
589 struct GetBestNSAnswer
590 {
591 DNSName qname;
f8f66c91 592 set<pair<DNSName, DNSName>> bestns;
6493dfc0 593 uint8_t qtype;
f688bbaa 594 bool operator<(const GetBestNSAnswer& bestAnswer) const
9065eb05 595 {
f688bbaa 596 return std::tie(qtype, qname, bestns) < std::tie(bestAnswer.qtype, bestAnswer.qname, bestAnswer.bestns);
9065eb05
RG
597 }
598 };
599
f688bbaa 600 using zonesStates_t = std::map<DNSName, vState>;
f8f66c91
OM
601 enum StopAtDelegation
602 {
603 DontStop,
604 Stop,
605 Stopped
606 };
70b3fe7a 607
f688bbaa
OM
608 void resolveAdditionals(const DNSName& qname, QType qtype, AdditionalMode mode, std::vector<DNSRecord>& additionals, unsigned int depth, bool& additionalsNotInCache);
609 void addAdditionals(QType qtype, const vector<DNSRecord>& start, vector<DNSRecord>& additionals, std::set<std::pair<DNSName, QType>>& uniqueCalls, std::set<std::tuple<DNSName, QType, QType>>& uniqueResults, unsigned int depth, unsigned int additionaldepth, bool& additionalsNotInCache);
f8f66c91 610 bool addAdditionals(QType qtype, vector<DNSRecord>& ret, unsigned int depth);
76e368a3 611
0fd1030f 612 void updateQueryCounts(const string& prefix, const DNSName& qname, const ComboAddress& address, bool doTCP, bool doDoT);
f688bbaa 613 static bool doDoTtoAuth(const DNSName& nameServer);
f8f66c91 614 int doResolveAt(NsSet& nameservers, DNSName auth, bool flawedNSSet, const DNSName& qname, QType qtype, vector<DNSRecord>& ret,
192c0a72 615 unsigned int depth, const string& prefix, set<GetBestNSAnswer>& beenthere, Context& context, StopAtDelegation* stopAtDelegation,
6af46497 616 std::map<DNSName, std::vector<ComboAddress>>* fallback);
328c3547 617 void ednsStats(boost::optional<Netmask>& ednsmask, const DNSName& qname, const string& prefix);
f688bbaa
OM
618 bool doResolveAtThisIP(const std::string& prefix, const DNSName& qname, QType qtype, LWResult& lwr, boost::optional<Netmask>& ednsmask, const DNSName& auth, bool sendRDQuery, bool wasForwarded, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool doDoT, bool& truncated, bool& spoofed, boost::optional<EDNSExtendedError>& extendedError, bool dontThrottle = false);
619 bool processAnswer(unsigned int depth, const string& prefix, LWResult& lwr, const DNSName& qname, 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, const ComboAddress& remoteIP);
f8f66c91 620
718c531d 621 int doResolve(const DNSName& qname, QType qtype, vector<DNSRecord>& ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, Context& context);
f688bbaa 622 int doResolveNoQNameMinimization(const DNSName& qname, QType qtype, vector<DNSRecord>& ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, Context& context, bool* fromCache = nullptr, StopAtDelegation* stopAtDelegation = nullptr);
f8f66c91 623 bool doOOBResolve(const AuthDomain& domain, const DNSName& qname, QType qtype, vector<DNSRecord>& ret, int& res);
192c0a72 624 bool doOOBResolve(const DNSName& qname, QType qtype, vector<DNSRecord>& ret, unsigned int depth, const string& prefix, int& res);
f688bbaa
OM
625 static bool isRecursiveForwardOrAuth(const DNSName& qname);
626 static bool isForwardOrAuth(const DNSName& qname);
627 static domainmap_t::const_iterator getBestAuthZone(DNSName* qname);
e3f3c9a4 628 bool doCNAMECacheCheck(const DNSName& qname, QType qtype, vector<DNSRecord>& ret, unsigned int depth, const string& prefix, int& res, Context& context, bool wasAuthZone, bool wasForwardRecurse, bool checkForDups);
192c0a72
OM
629 bool doCacheCheck(const DNSName& qname, const DNSName& authname, bool wasForwardedOrAuthZone, bool wasAuthZone, bool wasForwardRecurse, QType qtype, vector<DNSRecord>& ret, unsigned int depth, const string& prefix, int& res, Context& context);
630 void getBestNSFromCache(const DNSName& qname, QType qtype, vector<DNSRecord>& bestns, bool* flawedNSSet, unsigned int depth, const string& prefix, set<GetBestNSAnswer>& beenthere, const boost::optional<DNSName>& cutOffDomain = boost::none);
631 DNSName getBestNSNamesFromCache(const DNSName& qname, QType qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, const string& prefix, set<GetBestNSAnswer>& beenthere);
c5c066bf 632
baaa61a1 633 vector<std::pair<DNSName, float>> shuffleInSpeedOrder(const DNSName& qname, NsSet& nameservers, const string& prefix);
f688bbaa
OM
634 vector<ComboAddress> shuffleForwardSpeed(const DNSName& qname, const vector<ComboAddress>& rnameservers, const string& prefix, bool wasRd);
635 static bool moreSpecificThan(const DNSName& lhs, const DNSName& rhs);
328c3547 636 void selectNSOnSpeed(const DNSName& qname, const string& prefix, vector<ComboAddress>& ret);
192c0a72 637 vector<ComboAddress> getAddrs(const DNSName& qname, unsigned int depth, const string& prefix, set<GetBestNSAnswer>& beenthere, bool cacheOnly, unsigned int& addressQueriesForNS);
26ca3513 638
69cbdef9
RG
639 bool nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers);
640 bool nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress&);
c75d28f2 641 void checkMaxQperQ(const DNSName& qname) const;
22165a18 642 bool throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, QType qtype, bool pierceDontQuery);
26ca3513 643
f688bbaa 644 vector<ComboAddress> retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, vector<std::pair<DNSName, float>>::const_iterator& tns, unsigned int depth, set<GetBestNSAnswer>& beenthere, const vector<std::pair<DNSName, float>>& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet, bool cacheOnly, unsigned int& nretrieveAddressesForNS);
7155c3e5 645
f688bbaa 646 void sanitizeRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, const DNSName& auth, bool wasForwarded, bool rdQuery);
f8f66c91
OM
647 /* This function will check whether the answer should have the AA bit set, and will set if it should be set and isn't.
648 This is unfortunately needed to deal with very crappy so-called DNS servers */
f688bbaa 649 void fixupAnswer(const std::string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, const DNSName& auth, bool wasForwarded, bool rdQuery);
cb273be5 650 void rememberParentSetIfNeeded(const DNSName& domain, const vector<DNSRecord>& newRecords, unsigned int depth, const string& prefix);
f688bbaa
OM
651 RCode::rcodes_ updateCacheFromRecords(unsigned int depth, const string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, const DNSName& auth, bool wasForwarded, const boost::optional<Netmask>&, vState& state, bool& needWildcardProof, bool& gatherWildcardProof, unsigned int& wildcardLabelsCount, bool sendRDQuery, const ComboAddress& remoteIP);
652 bool processRecords(const std::string& prefix, const DNSName& qname, QType qtype, const DNSName& auth, LWResult& lwr, bool sendRDQuery, vector<DNSRecord>& ret, set<DNSName>& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic, vState& state, bool needWildcardProof, bool gatherwildcardProof, unsigned int wildcardLabelsCount, int& rcode, bool& negIndicHasSignatures, unsigned int depth);
26ca3513 653
f688bbaa 654 bool doSpecialNamesResolve(const DNSName& qname, QType qtype, QClass qclass, vector<DNSRecord>& ret);
db50a7f4 655
e8cf6180 656 LWResult::Result asyncresolveWrapper(const ComboAddress& address, bool ednsMANDATORY, const DNSName& domain, const DNSName& auth, int type, bool doTCP, bool sendRDQuery, struct timeval* now, boost::optional<Netmask>& srcmask, LWResult* res, bool* chained, const DNSName& nsName) const;
30ee601a 657
f688bbaa 658 boost::optional<Netmask> getEDNSSubnetMask(const DNSName& name, const ComboAddress& rem);
e9f9b8ec 659
f688bbaa 660 static bool validationEnabled();
d06dcda4 661 uint32_t computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, uint32_t signaturesTTL, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs) const;
f688bbaa
OM
662 void updateValidationState(const DNSName& qname, vState& state, vState stateUpdate, const string& prefix);
663 vState validateRecordsWithSigs(unsigned int depth, const string& prefix, const DNSName& qname, QType qtype, const DNSName& name, QType type, const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures);
d06dcda4 664 vState validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, unsigned int depth, const string& prefix);
cb273be5 665 vState getDNSKeys(const DNSName& signer, skeyset_t& keys, bool& servFailOccurred, unsigned int depth, const string& prefix);
f688bbaa
OM
666 dState getDenialValidationState(const NegCache::NegCacheEntry& negEntry, dState expectedState, bool referralToUnsigned, const string& prefix);
667 void updateDenialValidationState(const DNSName& qname, vState& neValidationState, const DNSName& neName, vState& state, dState denialState, dState expectedState, bool isDS, unsigned int depth, const string& prefix);
668 void computeNegCacheValidationStatus(const NegCache::NegCacheEntry& negEntry, const DNSName& qname, QType qtype, int res, vState& state, unsigned int depth, const string& prefix);
669 vState getTA(const DNSName& zone, dsmap_t& dsMap, const string& prefix);
670 vState getValidationStatus(const DNSName& name, bool wouldBeValid, bool typeIsDS, unsigned int depth, const string& prefix);
671 void updateValidationStatusInCache(const DNSName& qname, QType qtype, bool aaFlag, vState newState) const;
10971f78
OM
672 void initZoneCutsFromTA(const DNSName& from, const string& prefix);
673 size_t countSupportedDS(const dsmap_t& dsmap, const string& prefix);
4d2be65d 674
07e812c7 675 void handleNewTarget(const std::string& prefix, const DNSName& qname, const DNSName& newtarget, QType qtype, std::vector<DNSRecord>& ret, int& rcode, unsigned int depth, const std::vector<DNSRecord>& recordsFromAnswer, vState& state);
d4f08082 676
22165a18 677 void handlePolicyHit(const std::string& prefix, const DNSName& qname, QType qtype, vector<DNSRecord>& ret, bool& done, int& rcode, unsigned int depth);
07e812c7 678 unsigned int getAdjustedRecursionBound() const;
d4f08082 679
0b29b9c5
RG
680 void setUpdatingRootNS()
681 {
682 d_updatingRootNS = true;
683 }
684
0498b0b6
OM
685 std::string getPrefix(unsigned int depth) const
686 {
687 if (!doLog()) {
688 return "";
689 }
690 auto prefix = d_prefix;
691 prefix.append(depth, ' ');
692 return prefix;
693 }
694
51b6b728 695 zonesStates_t d_cutStates;
77499b05 696 ostringstream d_trace;
a3e7b735 697 shared_ptr<RecursorLua4> d_pdl;
2fe3354d 698 boost::optional<Netmask> d_outgoingECSNetwork;
2bbc9eb0
RP
699 std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>> d_outgoingProtobufServers;
700 std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>> d_frameStreamServers;
30ee601a 701 boost::optional<const boost::uuids::uuid&> d_initialRequestId;
15e973d6 702 pdns::validation::ValidationContext d_validationContext;
30ee601a 703 asyncresolve_t d_asyncResolve{nullptr};
f3493699 704 // d_now is initialized in the constructor and updates after outgoing requests in lwres.cc:asyncresolve
30ee601a 705 struct timeval d_now;
f08b5933
RG
706 /* if the client is asking for a DS that does not exist, we need to provide the SOA along with the NSEC(3) proof
707 and we might not have it if we picked up the proof from a delegation */
708 DNSName d_externalDSQuery;
c836dc19 709 string d_prefix;
98307d0f 710 vState d_queryValidationState{vState::Indeterminate};
b88526ce
PL
711
712 /* When d_cacheonly is set to true, we will only check the cache.
713 * This is set when the RD bit is unset in the incoming query
714 */
c836dc19 715 bool d_cacheonly;
30ee601a 716 bool d_doDNSSEC;
0c43f455 717 bool d_DNSSECValidationRequested{false};
30ee601a 718 bool d_doEDNS0{true};
24bb9b58 719 bool d_requireAuthData{true};
0b29b9c5 720 bool d_updatingRootNS{false};
30ee601a
RG
721 bool d_wantsRPZ{true};
722 bool d_wasOutOfBand{false};
723 bool d_wasVariable{false};
116d1288 724 bool d_qNameMinimization{false};
f943cd2f 725 bool d_qNameMinimizationFallbackMode{false};
d4f08082 726 bool d_queryReceivedOverTCP{false};
7373cea8 727 bool d_followCNAME{true};
87c4554a 728 bool d_refresh{false};
6af46497 729 bool d_serveStale{false};
f8f66c91 730
77499b05 731 LogMode d_lm;
00a19ff7 732};
ac0e821b 733
a9af3782 734/* external functions, opaque to us */
66242d00
O
735LWResult::Result asendtcp(const PacketBuffer& data, shared_ptr<TCPIOHandler>&);
736LWResult::Result arecvtcp(PacketBuffer& data, size_t len, shared_ptr<TCPIOHandler>&, bool incompleteOkay);
1d5b3ce6 737
f8f66c91
OM
738enum TCPAction : uint8_t
739{
740 DoingRead,
741 DoingWrite
742};
4bcf780e 743
1d5b3ce6
BH
744struct PacketID
745{
3bf2e213 746 PacketID()
67770277 747 {
d38e2ba9 748 remote.reset();
67770277 749 }
1d5b3ce6 750
f8f66c91
OM
751 ComboAddress remote; // this is the remote
752 DNSName domain; // this is the question
1d5b3ce6 753
2a17f6c6
O
754 PacketBuffer inMSG; // they'll go here
755 PacketBuffer outMSG; // the outgoing message that needs to be sent
1d5b3ce6 756
f688bbaa 757 using chain_t = set<uint16_t>;
96f81a93 758 mutable chain_t chain;
66242d00 759 shared_ptr<TCPIOHandler> tcphandler{nullptr};
f8f66c91 760 string::size_type inPos{0}; // how far are we along in the inMSG
ea844a86 761 size_t inWanted{0}; // if this is set, we'll read until inWanted bytes are read
f8f66c91 762 string::size_type outPos{0}; // how far we are along in the outMSG
3bf2e213
O
763 mutable uint32_t nearMisses{0}; // number of near misses - host correct, id wrong
764 int fd{-1};
f8f66c91 765 int tcpsock{0}; // or wait for an event on a TCP fd
3bf2e213
O
766 mutable bool closed{false}; // Processing already started, don't accept new chained ids
767 bool inIncompleteOkay{false};
f8f66c91
OM
768 uint16_t id{0}; // wait for a specific id/remote pair
769 uint16_t type{0}; // and this is its type
f9bb1d3f
OM
770 TCPAction highState{TCPAction::DoingRead};
771 IOState lowState{IOState::NeedRead};
35ce8576 772
8b428a6b 773 bool operator<(const PacketID& /* b */) const
1d5b3ce6 774 {
2d4ccdf5 775 // We don't want explicit PacketID compare here, but always via predicate classes below
f688bbaa 776 assert(0); // NOLINT: lib
1d5b3ce6
BH
777 }
778};
779
f688bbaa 780inline ostream& operator<<(ostream& ostr, const PacketID& pid)
96f81a93 781{
f688bbaa 782 return ostr << "PacketID(id=" << pid.id << ",remote=" << pid.remote.toString() << ",type=" << pid.type << ",tcpsock=" << pid.tcpsock << ",fd=" << pid.fd << ',' << pid.domain << ')';
a2eef000
O
783}
784
f688bbaa 785inline ostream& operator<<(ostream& ostr, const shared_ptr<PacketID>& pid)
a2eef000 786{
f688bbaa 787 return ostr << *pid;
a2eef000
O
788}
789
2d4ccdf5
O
790/*
791 * The two compare predicates below must be consistent!
792 * PacketIDBirthdayCompare can omit minor fields, but not change the or skip fields
793 * order! See boost docs on CompatibleCompare.
794 */
0662c2d3 795struct PacketIDCompare
a2eef000 796{
f688bbaa 797 bool operator()(const std::shared_ptr<PacketID>& lhs, const std::shared_ptr<PacketID>& rhs) const
0662c2d3 798 {
f688bbaa 799 if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) < std::tie(rhs->remote, rhs->tcpsock, rhs->type)) {
0662c2d3
O
800 return true;
801 }
f688bbaa 802 if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) > std::tie(rhs->remote, rhs->tcpsock, rhs->type)) {
0662c2d3
O
803 return false;
804 }
805
f688bbaa 806 return std::tie(lhs->domain, lhs->fd, lhs->id) < std::tie(rhs->domain, rhs->fd, rhs->id);
0662c2d3
O
807 }
808};
a2eef000
O
809
810struct PacketIDBirthdayCompare
811{
f688bbaa 812 bool operator()(const std::shared_ptr<PacketID>& lhs, const std::shared_ptr<PacketID>& rhs) const
96f81a93 813 {
f688bbaa 814 if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) < std::tie(rhs->remote, rhs->tcpsock, rhs->type)) {
96f81a93 815 return true;
3bf2e213 816 }
f688bbaa 817 if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) > std::tie(rhs->remote, rhs->tcpsock, rhs->type)) {
96f81a93 818 return false;
3bf2e213 819 }
f688bbaa 820 return lhs->domain < rhs->domain;
96f81a93
BH
821 }
822};
ccfadb6c 823extern std::unique_ptr<MemRecursorCache> g_recCache;
1d5b3ce6 824
7d3d2f4f
OM
825extern rec::GlobalCounters g_Counters;
826extern thread_local rec::TCounters t_Counters;
827
0e408828 828//! represents a running TCP/IP client session
f688bbaa 829class TCPConnection
0e408828 830{
50a5ef72 831public:
c0db60c3 832 TCPConnection(int fileDesc, const ComboAddress& addr);
cd989c87 833 ~TCPConnection();
f688bbaa
OM
834 TCPConnection(const TCPConnection&) = delete;
835 TCPConnection& operator=(const TCPConnection&) = delete;
836 TCPConnection(TCPConnection&&) = delete;
837 TCPConnection& operator=(TCPConnection&&) = delete;
3ddb9247 838
f688bbaa 839 [[nodiscard]] int getFD() const
cd989c87
BH
840 {
841 return d_fd;
842 }
6b425e61
O
843 void setDropOnIdle()
844 {
845 d_dropOnIdle = true;
846 }
f688bbaa 847 [[nodiscard]] bool isDropOnIdle() const
6b425e61
O
848 {
849 return d_dropOnIdle;
850 }
f688bbaa
OM
851
852 // The max number of concurrent TCP requests we're willing to process
853 static uint16_t s_maxInFlight;
854 static unsigned int getCurrentConnections() { return s_currentConnections; }
855
5216ddcc 856 std::vector<ProxyProtocolValue> proxyProtocolValues;
2749c3fe 857 std::string data;
f688bbaa 858 ComboAddress d_remote;
5216ddcc
RG
859 ComboAddress d_source;
860 ComboAddress d_destination;
e81063e5 861 ComboAddress d_mappedSource;
2749c3fe 862 size_t queriesCount{0};
5216ddcc
RG
863 size_t proxyProtocolGot{0};
864 ssize_t proxyProtocolNeed{0};
f8f66c91
OM
865 enum stateenum
866 {
867 PROXYPROTOCOLHEADER,
868 BYTE0,
869 BYTE1,
870 GETQUESTION,
871 DONE
872 } state{BYTE0};
b841314c
RG
873 uint16_t qlen{0};
874 uint16_t bytesread{0};
b5b94beb 875 uint16_t d_requestsInFlight{0}; // number of mthreads spawned for this connection
f8f66c91 876
50a5ef72 877private:
f688bbaa 878 int d_fd;
7db617e1 879 static std::atomic<uint32_t> s_currentConnections; //!< total number of current TCP connections
6b425e61 880 bool d_dropOnIdle{false};
0e408828
BH
881};
882
44971ca0
PD
883class ImmediateServFailException
884{
885public:
645b217b
OM
886 ImmediateServFailException(string reason_) :
887 reason(std::move(reason_)){};
44971ca0
PD
888
889 string reason; //! Print this to tell the user what went wrong
890};
0e408828 891
124dd1d4
RG
892class PolicyHitException
893{
894};
895
d4f08082
RG
896class ImmediateQueryDropException
897{
898};
899
900class SendTruncatedAnswerException
901{
902};
903
f688bbaa 904using addrringbuf_t = boost::circular_buffer<ComboAddress>;
621ccf89 905extern thread_local std::unique_ptr<addrringbuf_t> t_servfailremotes, t_largeanswerremotes, t_remotes, t_bogusremotes, t_timeouts;
a9af3782 906
f8f66c91 907extern thread_local std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t>>> t_queryring, t_servfailqueryring, t_bogusqueryring;
f26bf547 908extern thread_local std::shared_ptr<NetmaskGroup> t_allowFrom;
35189b7d 909extern thread_local std::shared_ptr<NetmaskGroup> t_allowNotifyFrom;
a512e3d1 910extern unsigned int g_networkTimeoutMsec;
b33c2462 911extern uint16_t g_outgoingEDNSBufsize;
a6f7f5fe 912extern std::atomic<uint32_t> g_maxCacheEntries, g_maxPacketCacheEntries;
c1c29961 913extern bool g_lowercaseOutgoing;
12ce523e 914
9883d3f9 915std::string reloadZoneConfiguration(bool yaml);
f42b7625 916using pipefunc_t = std::function<void*()>;
b4e76a18 917void broadcastFunction(const pipefunc_t& func);
e8e12e8c 918void distributeAsyncFunction(const std::string& packet, const pipefunc_t& func);
3427fa8a 919
645b217b
OM
920int directResolve(const DNSName& qname, QType qtype, QClass qclass, vector<DNSRecord>& ret, const shared_ptr<RecursorLua4>& pdl, Logr::log_t);
921int directResolve(const DNSName& qname, QType qtype, QClass qclass, vector<DNSRecord>& ret, const shared_ptr<RecursorLua4>& pdl, bool qnamemin, Logr::log_t);
e8e12e8c 922int followCNAMERecords(std::vector<DNSRecord>& ret, QType qtype, int rcode);
ef3ee606
RG
923int getFakeAAAARecords(const DNSName& qname, ComboAddress prefix, vector<DNSRecord>& ret);
924int getFakePTRRecords(const DNSName& qname, vector<DNSRecord>& ret);
3427fa8a 925
f8f66c91
OM
926template <class T>
927T broadcastAccFunction(const std::function<T*()>& func);
3427fa8a 928
f688bbaa 929using notifyset_t = std::unordered_set<DNSName>;
9883d3f9 930std::tuple<std::shared_ptr<SyncRes::domainmap_t>, std::shared_ptr<notifyset_t>> parseZoneConfiguration(bool yaml);
ebe2aeb8 931void* pleaseSupplantAllowNotifyFor(std::shared_ptr<notifyset_t> allowNotifyFor);
35189b7d 932
13034931 933uint64_t* pleaseGetNsSpeedsSize();
60e5208a 934uint64_t* pleaseGetFailedServersSize();
13034931
BH
935uint64_t* pleaseGetConcurrentQueries();
936uint64_t* pleaseGetThrottleSize();
2c78bd57 937void doCarbonDump(void*);
1d52e318 938bool primeHints(time_t now = time(nullptr));
f688bbaa
OM
939
940using timebuf_t = std::array<char, 64>;
941const char* isoDateTimeMillis(const struct timeval& tval, timebuf_t& buf);
795215f2 942
f6329e6e
KF
943struct WipeCacheResult
944{
945 int record_count = 0;
946 int negative_record_count = 0;
947 int packet_count = 0;
948};
949
950struct WipeCacheResult wipeCaches(const DNSName& canon, bool subtree, uint16_t qtype);
951
f703f766 952extern __thread struct timeval g_now;
5ac6d761 953
954struct ThreadTimes
955{
f9bb1d3f 956 uint64_t msec{0};
5ac6d761 957 vector<uint64_t> times;
958 ThreadTimes& operator+=(const ThreadTimes& rhs)
959 {
960 times.push_back(rhs.msec);
961 return *this;
962 }
963};