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