]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/recursordist/syncres.hh
rec: CVE-2023-50387 and CVE-2023-50868
[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 static unsigned int s_ecscachelimitttl;
524 static unsigned int s_maxvalidationsperq;
525 static unsigned int s_maxnsec3iterationsperq;
526 static uint8_t s_ecsipv4limit;
527 static uint8_t s_ecsipv6limit;
528 static uint8_t s_ecsipv4cachelimit;
529 static uint8_t s_ecsipv6cachelimit;
530 static bool s_ecsipv4nevercache;
531 static bool s_ecsipv6nevercache;
532
533 static bool s_doIPv4;
534 static bool s_doIPv6;
535 static bool s_noEDNSPing;
536 static bool s_noEDNS;
537 static bool s_rootNXTrust;
538 static bool s_qnameminimization;
539 static HardenNXD s_hardenNXD;
540 static unsigned int s_refresh_ttlperc;
541 static unsigned int s_locked_ttlperc;
542 static int s_tcp_fast_open;
543 static bool s_tcp_fast_open_connect;
544 static bool s_dot_to_port_853;
545 static unsigned int s_max_busy_dot_probes;
546 static unsigned int s_max_CNAMES_followed;
547 static unsigned int s_max_minimize_count;
548 static unsigned int s_minimize_one_label;
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;
553 static bool s_save_parent_ns_set;
554 static bool s_addExtendedResolutionDNSErrors;
555
556 std::unordered_map<std::string, bool> d_discardedPolicies;
557 DNSFilterEngine::Policy d_appliedPolicy;
558 std::unordered_set<std::string> d_policyTags;
559 boost::optional<string> d_routingTag;
560 ComboAddress d_fromAuthIP;
561 RecEventTrace d_eventTrace;
562 std::shared_ptr<Logr::Logger> d_slog = g_slog->withName("syncres");
563 boost::optional<EDNSExtendedError> d_extendedError;
564
565 unsigned int d_authzonequeries;
566 unsigned int d_outqueries;
567 unsigned int d_tcpoutqueries;
568 unsigned int d_dotoutqueries;
569 unsigned int d_throttledqueries;
570 unsigned int d_timeouts;
571 unsigned int d_unreachables;
572 unsigned int d_totUsec;
573 unsigned int d_maxdepth{0};
574 // Initialized ony once, as opposed to d_now which gets updated after outgoing requests
575 struct timeval d_fixednow;
576
577 private:
578 ComboAddress d_requestor;
579 ComboAddress d_cacheRemote;
580
581 static NetmaskGroup s_ednslocalsubnets;
582 static NetmaskGroup s_ednsremotesubnets;
583 static SuffixMatchNode s_ednsdomains;
584 static EDNSSubnetOpts s_ecsScopeZero;
585 static LogMode s_lm;
586 static std::unique_ptr<NetmaskGroup> s_dontQuery;
587 const static std::unordered_set<QType> s_redirectionQTypes;
588
589 struct GetBestNSAnswer
590 {
591 DNSName qname;
592 set<pair<DNSName, DNSName>> bestns;
593 uint8_t qtype;
594 bool operator<(const GetBestNSAnswer& bestAnswer) const
595 {
596 return std::tie(qtype, qname, bestns) < std::tie(bestAnswer.qtype, bestAnswer.qname, bestAnswer.bestns);
597 }
598 };
599
600 using zonesStates_t = std::map<DNSName, vState>;
601 enum StopAtDelegation
602 {
603 DontStop,
604 Stop,
605 Stopped
606 };
607
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);
610 bool addAdditionals(QType qtype, vector<DNSRecord>& ret, unsigned int depth);
611
612 void updateQueryCounts(const string& prefix, const DNSName& qname, const ComboAddress& address, bool doTCP, bool doDoT);
613 static bool doDoTtoAuth(const DNSName& nameServer);
614 int doResolveAt(NsSet& nameservers, DNSName auth, bool flawedNSSet, const DNSName& qname, QType qtype, vector<DNSRecord>& ret,
615 unsigned int depth, const string& prefix, set<GetBestNSAnswer>& beenthere, Context& context, StopAtDelegation* stopAtDelegation,
616 std::map<DNSName, std::vector<ComboAddress>>* fallback);
617 void ednsStats(boost::optional<Netmask>& ednsmask, const DNSName& qname, const string& prefix);
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);
620
621 int doResolve(const DNSName& qname, QType qtype, vector<DNSRecord>& ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, Context& context);
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);
623 bool doOOBResolve(const AuthDomain& domain, const DNSName& qname, QType qtype, vector<DNSRecord>& ret, int& res);
624 bool doOOBResolve(const DNSName& qname, QType qtype, vector<DNSRecord>& ret, unsigned int depth, const string& prefix, int& res);
625 static bool isRecursiveForwardOrAuth(const DNSName& qname);
626 static bool isForwardOrAuth(const DNSName& qname);
627 static domainmap_t::const_iterator getBestAuthZone(DNSName* qname);
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);
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);
632
633 vector<std::pair<DNSName, float>> shuffleInSpeedOrder(const DNSName& qname, NsSet& nameservers, const string& prefix);
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);
636 void selectNSOnSpeed(const DNSName& qname, const string& prefix, vector<ComboAddress>& ret);
637 vector<ComboAddress> getAddrs(const DNSName& qname, unsigned int depth, const string& prefix, set<GetBestNSAnswer>& beenthere, bool cacheOnly, unsigned int& addressQueriesForNS);
638
639 bool nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers);
640 bool nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress&);
641 void checkMaxQperQ(const DNSName& qname) const;
642 bool throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, QType qtype, bool pierceDontQuery);
643
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);
645
646 void sanitizeRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, const DNSName& auth, bool wasForwarded, bool rdQuery);
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 */
649 void fixupAnswer(const std::string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, const DNSName& auth, bool wasForwarded, bool rdQuery);
650 void rememberParentSetIfNeeded(const DNSName& domain, const vector<DNSRecord>& newRecords, unsigned int depth, const string& prefix);
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);
653
654 bool doSpecialNamesResolve(const DNSName& qname, QType qtype, QClass qclass, vector<DNSRecord>& ret);
655
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;
657
658 boost::optional<Netmask> getEDNSSubnetMask(const DNSName& name, const ComboAddress& rem);
659
660 static bool validationEnabled();
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;
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);
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);
665 vState getDNSKeys(const DNSName& signer, skeyset_t& keys, bool& servFailOccurred, unsigned int depth, const string& prefix);
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;
672 void initZoneCutsFromTA(const DNSName& from, const string& prefix);
673 size_t countSupportedDS(const dsmap_t& dsmap, const string& prefix);
674
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);
676
677 void handlePolicyHit(const std::string& prefix, const DNSName& qname, QType qtype, vector<DNSRecord>& ret, bool& done, int& rcode, unsigned int depth);
678 unsigned int getAdjustedRecursionBound() const;
679
680 void setUpdatingRootNS()
681 {
682 d_updatingRootNS = true;
683 }
684
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
695 zonesStates_t d_cutStates;
696 ostringstream d_trace;
697 shared_ptr<RecursorLua4> d_pdl;
698 boost::optional<Netmask> d_outgoingECSNetwork;
699 std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>> d_outgoingProtobufServers;
700 std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>> d_frameStreamServers;
701 boost::optional<const boost::uuids::uuid&> d_initialRequestId;
702 pdns::validation::ValidationContext d_validationContext;
703 asyncresolve_t d_asyncResolve{nullptr};
704 // d_now is initialized in the constructor and updates after outgoing requests in lwres.cc:asyncresolve
705 struct timeval d_now;
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;
709 string d_prefix;
710 vState d_queryValidationState{vState::Indeterminate};
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 */
715 bool d_cacheonly;
716 bool d_doDNSSEC;
717 bool d_DNSSECValidationRequested{false};
718 bool d_doEDNS0{true};
719 bool d_requireAuthData{true};
720 bool d_updatingRootNS{false};
721 bool d_wantsRPZ{true};
722 bool d_wasOutOfBand{false};
723 bool d_wasVariable{false};
724 bool d_qNameMinimization{false};
725 bool d_qNameMinimizationFallbackMode{false};
726 bool d_queryReceivedOverTCP{false};
727 bool d_followCNAME{true};
728 bool d_refresh{false};
729 bool d_serveStale{false};
730
731 LogMode d_lm;
732 };
733
734 /* external functions, opaque to us */
735 LWResult::Result asendtcp(const PacketBuffer& data, shared_ptr<TCPIOHandler>&);
736 LWResult::Result arecvtcp(PacketBuffer& data, size_t len, shared_ptr<TCPIOHandler>&, bool incompleteOkay);
737
738 enum TCPAction : uint8_t
739 {
740 DoingRead,
741 DoingWrite
742 };
743
744 struct PacketID
745 {
746 PacketID()
747 {
748 remote.reset();
749 }
750
751 ComboAddress remote; // this is the remote
752 DNSName domain; // this is the question
753
754 PacketBuffer inMSG; // they'll go here
755 PacketBuffer outMSG; // the outgoing message that needs to be sent
756
757 using chain_t = set<uint16_t>;
758 mutable chain_t chain;
759 shared_ptr<TCPIOHandler> tcphandler{nullptr};
760 string::size_type inPos{0}; // how far are we along in the inMSG
761 size_t inWanted{0}; // if this is set, we'll read until inWanted bytes are read
762 string::size_type outPos{0}; // how far we are along in the outMSG
763 mutable uint32_t nearMisses{0}; // number of near misses - host correct, id wrong
764 int fd{-1};
765 int tcpsock{0}; // or wait for an event on a TCP fd
766 mutable bool closed{false}; // Processing already started, don't accept new chained ids
767 bool inIncompleteOkay{false};
768 uint16_t id{0}; // wait for a specific id/remote pair
769 uint16_t type{0}; // and this is its type
770 TCPAction highState{TCPAction::DoingRead};
771 IOState lowState{IOState::NeedRead};
772
773 bool operator<(const PacketID& /* b */) const
774 {
775 // We don't want explicit PacketID compare here, but always via predicate classes below
776 assert(0); // NOLINT: lib
777 }
778 };
779
780 inline ostream& operator<<(ostream& ostr, const PacketID& pid)
781 {
782 return ostr << "PacketID(id=" << pid.id << ",remote=" << pid.remote.toString() << ",type=" << pid.type << ",tcpsock=" << pid.tcpsock << ",fd=" << pid.fd << ',' << pid.domain << ')';
783 }
784
785 inline ostream& operator<<(ostream& ostr, const shared_ptr<PacketID>& pid)
786 {
787 return ostr << *pid;
788 }
789
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 */
795 struct PacketIDCompare
796 {
797 bool operator()(const std::shared_ptr<PacketID>& lhs, const std::shared_ptr<PacketID>& rhs) const
798 {
799 if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) < std::tie(rhs->remote, rhs->tcpsock, rhs->type)) {
800 return true;
801 }
802 if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) > std::tie(rhs->remote, rhs->tcpsock, rhs->type)) {
803 return false;
804 }
805
806 return std::tie(lhs->domain, lhs->fd, lhs->id) < std::tie(rhs->domain, rhs->fd, rhs->id);
807 }
808 };
809
810 struct PacketIDBirthdayCompare
811 {
812 bool operator()(const std::shared_ptr<PacketID>& lhs, const std::shared_ptr<PacketID>& rhs) const
813 {
814 if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) < std::tie(rhs->remote, rhs->tcpsock, rhs->type)) {
815 return true;
816 }
817 if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) > std::tie(rhs->remote, rhs->tcpsock, rhs->type)) {
818 return false;
819 }
820 return lhs->domain < rhs->domain;
821 }
822 };
823 extern std::unique_ptr<MemRecursorCache> g_recCache;
824
825 extern rec::GlobalCounters g_Counters;
826 extern thread_local rec::TCounters t_Counters;
827
828 //! represents a running TCP/IP client session
829 class TCPConnection
830 {
831 public:
832 TCPConnection(int fileDesc, const ComboAddress& addr);
833 ~TCPConnection();
834 TCPConnection(const TCPConnection&) = delete;
835 TCPConnection& operator=(const TCPConnection&) = delete;
836 TCPConnection(TCPConnection&&) = delete;
837 TCPConnection& operator=(TCPConnection&&) = delete;
838
839 [[nodiscard]] int getFD() const
840 {
841 return d_fd;
842 }
843 void setDropOnIdle()
844 {
845 d_dropOnIdle = true;
846 }
847 [[nodiscard]] bool isDropOnIdle() const
848 {
849 return d_dropOnIdle;
850 }
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
856 std::vector<ProxyProtocolValue> proxyProtocolValues;
857 std::string data;
858 ComboAddress d_remote;
859 ComboAddress d_source;
860 ComboAddress d_destination;
861 ComboAddress d_mappedSource;
862 size_t queriesCount{0};
863 size_t proxyProtocolGot{0};
864 ssize_t proxyProtocolNeed{0};
865 enum stateenum
866 {
867 PROXYPROTOCOLHEADER,
868 BYTE0,
869 BYTE1,
870 GETQUESTION,
871 DONE
872 } state{BYTE0};
873 uint16_t qlen{0};
874 uint16_t bytesread{0};
875 uint16_t d_requestsInFlight{0}; // number of mthreads spawned for this connection
876
877 private:
878 int d_fd;
879 static std::atomic<uint32_t> s_currentConnections; //!< total number of current TCP connections
880 bool d_dropOnIdle{false};
881 };
882
883 class ImmediateServFailException
884 {
885 public:
886 ImmediateServFailException(string reason_) :
887 reason(std::move(reason_)){};
888
889 string reason; //! Print this to tell the user what went wrong
890 };
891
892 class PolicyHitException
893 {
894 };
895
896 class ImmediateQueryDropException
897 {
898 };
899
900 class SendTruncatedAnswerException
901 {
902 };
903
904 using addrringbuf_t = boost::circular_buffer<ComboAddress>;
905 extern thread_local std::unique_ptr<addrringbuf_t> t_servfailremotes, t_largeanswerremotes, t_remotes, t_bogusremotes, t_timeouts;
906
907 extern thread_local std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t>>> t_queryring, t_servfailqueryring, t_bogusqueryring;
908 extern thread_local std::shared_ptr<NetmaskGroup> t_allowFrom;
909 extern thread_local std::shared_ptr<NetmaskGroup> t_allowNotifyFrom;
910 extern unsigned int g_networkTimeoutMsec;
911 extern uint16_t g_outgoingEDNSBufsize;
912 extern std::atomic<uint32_t> g_maxCacheEntries, g_maxPacketCacheEntries;
913 extern bool g_lowercaseOutgoing;
914
915 std::string reloadZoneConfiguration(bool yaml);
916 using pipefunc_t = std::function<void*()>;
917 void broadcastFunction(const pipefunc_t& func);
918 void distributeAsyncFunction(const std::string& packet, const pipefunc_t& func);
919
920 int directResolve(const DNSName& qname, QType qtype, QClass qclass, vector<DNSRecord>& ret, const shared_ptr<RecursorLua4>& pdl, Logr::log_t);
921 int directResolve(const DNSName& qname, QType qtype, QClass qclass, vector<DNSRecord>& ret, const shared_ptr<RecursorLua4>& pdl, bool qnamemin, Logr::log_t);
922 int followCNAMERecords(std::vector<DNSRecord>& ret, QType qtype, int rcode);
923 int getFakeAAAARecords(const DNSName& qname, ComboAddress prefix, vector<DNSRecord>& ret);
924 int getFakePTRRecords(const DNSName& qname, vector<DNSRecord>& ret);
925
926 template <class T>
927 T broadcastAccFunction(const std::function<T*()>& func);
928
929 using notifyset_t = std::unordered_set<DNSName>;
930 std::tuple<std::shared_ptr<SyncRes::domainmap_t>, std::shared_ptr<notifyset_t>> parseZoneConfiguration(bool yaml);
931 void* pleaseSupplantAllowNotifyFor(std::shared_ptr<notifyset_t> allowNotifyFor);
932
933 uint64_t* pleaseGetNsSpeedsSize();
934 uint64_t* pleaseGetFailedServersSize();
935 uint64_t* pleaseGetConcurrentQueries();
936 uint64_t* pleaseGetThrottleSize();
937 void doCarbonDump(void*);
938 bool primeHints(time_t now = time(nullptr));
939
940 using timebuf_t = std::array<char, 64>;
941 const char* isoDateTimeMillis(const struct timeval& tval, timebuf_t& buf);
942
943 struct WipeCacheResult
944 {
945 int record_count = 0;
946 int negative_record_count = 0;
947 int packet_count = 0;
948 };
949
950 struct WipeCacheResult wipeCaches(const DNSName& canon, bool subtree, uint16_t qtype);
951
952 extern __thread struct timeval g_now;
953
954 struct ThreadTimes
955 {
956 uint64_t msec{0};
957 vector<uint64_t> times;
958 ThreadTimes& operator+=(const ThreadTimes& rhs)
959 {
960 times.push_back(rhs.msec);
961 return *this;
962 }
963 };