2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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.
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.
30 #include <unordered_set>
37 #include <boost/optional.hpp>
38 #include <boost/utility.hpp>
39 #include "circular_buffer.hh"
41 #include "recursor_cache.hh"
44 #include "validate-recursor.hh"
45 #include "ednssubnet.hh"
46 #include "filterpo.hh"
47 #include "negcache.hh"
48 #include "proxy-protocol.hh"
50 #include "histogram.hh"
52 #include "tcpiohandler.hh"
53 #include "rec-eventtrace.hh"
55 #include "rec-tcounters.hh"
56 #include "ednsextendederror.hh"
62 #include <boost/uuid/uuid.hpp>
64 #include "fstrm_logger.hh"
65 #endif /* HAVE_FSTRM */
67 extern GlobalStateHolder<SuffixMatchNode> g_xdnssec;
68 extern GlobalStateHolder<SuffixMatchNode> g_dontThrottleNames;
69 extern GlobalStateHolder<NetmaskGroup> g_dontThrottleNetmasks;
70 extern GlobalStateHolder<SuffixMatchNode> g_DoTToAuthNames;
72 enum class AdditionalMode : uint8_t; // defined in rec-lua-conf.hh
76 using NsSet = std::unordered_map<DNSName, pair<vector<ComboAddress>, bool>>;
78 extern std::unique_ptr<NegCache> g_negCache;
80 class SyncRes : public boost::noncopyable
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*)>;
100 boost::optional<EDNSExtendedError> extendedError;
101 vState state{vState::Indeterminate};
104 vState getDSRecords(const DNSName& zone, dsmap_t& dsMap, bool onlyTA, unsigned int depth, const string& prefix, bool bogusOnNXD = true, bool* foundCut = nullptr);
109 using records_t = multi_index_container<
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<>>>>>;
119 vector<ComboAddress> d_servers;
121 bool d_rdForward{false};
123 bool operator==(const AuthDomain& rhs) const;
125 [[nodiscard]] std::string print(const std::string& indent = "",
126 const std::string& indentLevel = " ") const;
128 int getRecords(const DNSName& qname, QType qtype, std::vector<DNSRecord>& records) const;
129 [[nodiscard]] bool isAuth() const
131 return d_servers.empty();
133 [[nodiscard]] bool isForward() const
137 [[nodiscard]] bool shouldRecurse() const
141 [[nodiscard]] const DNSName& getName() const
147 void addSOA(std::vector<DNSRecord>& records) const;
150 using domainmap_t = std::unordered_map<DNSName, AuthDomain>;
152 struct ThreadLocalStorage
154 std::shared_ptr<domainmap_t> domainmap;
157 static void setDefaultLogMode(LogMode logmode)
162 OptLog LogObject(const string& prefix);
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);
172 static int getRootNS(struct timeval now, asyncresolve_t asyncCallback, unsigned int depth, Logr::log_t);
173 static void addDontQuery(const std::string& mask)
176 s_dontQuery = std::make_unique<NetmaskGroup>();
178 s_dontQuery->addMask(mask);
180 static void addDontQuery(const Netmask& mask)
183 s_dontQuery = std::make_unique<NetmaskGroup>();
185 s_dontQuery->addMask(mask);
187 static void clearDontQuery()
189 s_dontQuery = nullptr;
191 static void parseEDNSSubnetAllowlist(const std::string& alist);
192 static void parseEDNSSubnetAddFor(const std::string& subnetlist);
193 static void addEDNSLocalSubnet(const std::string& subnet)
195 s_ednslocalsubnets.addMask(subnet);
197 static void addEDNSRemoteSubnet(const std::string& subnet)
199 s_ednsremotesubnets.addMask(subnet);
201 static void addEDNSDomain(const DNSName& domain)
203 s_ednsdomains.add(domain);
205 static void clearEDNSLocalSubnets()
207 s_ednslocalsubnets.clear();
209 static void clearEDNSRemoteSubnets()
211 s_ednsremotesubnets.clear();
213 static void clearEDNSDomains()
215 s_ednsdomains = SuffixMatchNode();
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);
226 EDNSStatus(const ComboAddress& arg) :
228 ComboAddress address;
230 enum EDNSMode : uint8_t
237 [[nodiscard]] std::string toString() const
239 const std::array<std::string, 3> modes = {"OK", "Ignorant", "No"};
240 auto umode = static_cast<unsigned int>(mode);
241 if (umode >= modes.size()) {
244 return modes.at(umode);
248 static EDNSStatus::EDNSMode getEDNSStatus(const ComboAddress& server);
249 static uint64_t getEDNSStatusesSize();
250 static void clearEDNSStatuses();
251 static void pruneEDNSStatuses(time_t cutoff);
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);
262 static uint64_t getFailedServersSize();
263 static void clearFailedServers();
264 static void pruneFailedServers(time_t cutoff);
265 static unsigned long getServerFailsCount(const ComboAddress& server);
267 static void clearNonResolvingNS();
268 static uint64_t getNonResolvingNSSize();
269 static void pruneNonResolving(time_t cutoff);
271 static void clearSaveParentsNSSets();
272 static size_t getSaveParentsNSSetsSize();
273 static void pruneSaveParentsNSSets(time_t now);
275 static void pruneDoTProbeMap(time_t cutoff);
277 static void setDomainMap(std::shared_ptr<domainmap_t> newMap)
279 t_sstorage.domainmap = std::move(newMap);
281 static std::shared_ptr<domainmap_t> getDomainMap()
283 return t_sstorage.domainmap;
286 static void setECSScopeZeroAddress(const Netmask& scopeZeroMask)
288 s_ecsScopeZero.source = scopeZeroMask;
291 static void clearECSStats()
293 s_ecsqueries.store(0);
294 s_ecsresponses.store(0);
296 for (size_t idx = 0; idx < 32; idx++) {
297 SyncRes::s_ecsResponsesBySubnetSize4[idx].store(0);
300 for (size_t idx = 0; idx < 128; idx++) {
301 SyncRes::s_ecsResponsesBySubnetSize6[idx].store(0);
305 explicit SyncRes(const struct timeval& now);
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);
310 void setId(int threadid)
313 d_prefix = "[" + std::to_string(threadid) + "] ";
317 void setId(const string& prefix)
320 d_prefix = "[" + prefix + "] ";
324 void setLogMode(LogMode logmode)
331 return d_lm != LogNone;
334 bool setCacheOnly(bool state = true)
336 bool old = d_cacheonly;
341 bool setRefreshAlmostExpired(bool doit)
343 auto old = d_refresh;
348 bool setQNameMinimization(bool state = true)
350 auto old = d_qNameMinimization;
351 d_qNameMinimization = state;
355 bool setQMFallbackMode(bool state = true)
357 auto old = d_qNameMinimizationFallbackMode;
358 d_qNameMinimizationFallbackMode = state;
362 bool getQMFallbackMode() const
364 return d_qNameMinimizationFallbackMode;
367 void setDoEDNS0(bool state = true)
372 void setDoDNSSEC(bool state = true)
377 void setDNSSECValidationRequested(bool requested = true)
379 d_DNSSECValidationRequested = requested;
382 bool isDNSSECValidationRequested() const
384 return d_DNSSECValidationRequested;
387 bool shouldValidate() const
389 return d_DNSSECValidationRequested && !d_wasOutOfBand;
392 void setWantsRPZ(bool state = true)
397 bool getWantsRPZ() const
402 string getTrace() const
404 return d_trace.str();
407 bool getQNameMinimization() const
409 return d_qNameMinimization;
412 void setLuaEngine(shared_ptr<RecursorLua4> pdl)
414 d_pdl = std::move(pdl);
417 bool wasVariable() const
419 return d_wasVariable;
422 bool wasOutOfBand() const
424 return d_wasOutOfBand;
427 struct timeval getNow() const
432 // For debugging purposes
433 void setNow(const struct timeval& tval)
438 void setQuerySource(const ComboAddress& requestor, const boost::optional<const EDNSSubnetOpts&>& incomingECS);
439 void setQuerySource(const Netmask& netmask);
441 void setInitialRequestId(const boost::optional<const boost::uuids::uuid&>& initialRequestId)
443 d_initialRequestId = initialRequestId;
446 void setOutgoingProtobufServers(std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>>& servers)
448 d_outgoingProtobufServers = servers;
452 void setFrameStreamServers(std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& servers)
454 d_frameStreamServers = servers;
456 #endif /* HAVE_FSTRM */
458 void setAsyncCallback(asyncresolve_t func)
460 d_asyncResolve = std::move(func);
463 vState getValidationState() const
465 return d_queryValidationState;
468 void setQueryReceivedOverTCP(bool tcp)
470 d_queryReceivedOverTCP = tcp;
473 static bool isUnsupported(QType qtype)
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) {
482 case QType::ENT: // aka TYPE0
485 case QType::rfc6895Reserved:
488 case QType::NSEC3: // We use the same logic as for an auth: NSEC is queryable, NSEC3 not
495 static bool answerIsNOData(uint16_t requestedType, int rcode, const std::vector<DNSRecord>& records);
497 static thread_local ThreadLocalStorage t_sstorage;
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;
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;
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;
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;
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;
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;
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;
577 ComboAddress d_requestor;
578 ComboAddress d_cacheRemote;
580 static NetmaskGroup s_ednslocalsubnets;
581 static NetmaskGroup s_ednsremotesubnets;
582 static SuffixMatchNode s_ednsdomains;
583 static EDNSSubnetOpts s_ecsScopeZero;
585 static std::unique_ptr<NetmaskGroup> s_dontQuery;
586 const static std::unordered_set<QType> s_redirectionQTypes;
588 struct GetBestNSAnswer
591 set<pair<DNSName, DNSName>> bestns;
593 bool operator<(const GetBestNSAnswer& bestAnswer) const
595 return std::tie(qtype, qname, bestns) < std::tie(bestAnswer.qtype, bestAnswer.qname, bestAnswer.bestns);
599 using zonesStates_t = std::map<DNSName, vState>;
600 enum StopAtDelegation
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);
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);
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);
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);
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);
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);
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);
653 bool doSpecialNamesResolve(const DNSName& qname, QType qtype, QClass qclass, vector<DNSRecord>& ret);
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;
657 boost::optional<Netmask> getEDNSSubnetMask(const DNSName& name, const ComboAddress& rem);
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);
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);
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;
679 void setUpdatingRootNS()
681 d_updatingRootNS = true;
684 std::string getPrefix(unsigned int depth) const
689 auto prefix = d_prefix;
690 prefix.append(depth, ' ');
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;
708 vState d_queryValidationState{vState::Indeterminate};
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
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};
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);
736 enum TCPAction : uint8_t
749 ComboAddress remote; // this is the remote
750 DNSName domain; // this is the question
752 PacketBuffer inMSG; // they'll go here
753 PacketBuffer outMSG; // the outgoing message that needs to be sent
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
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};
771 bool operator<(const PacketID& /* b */) const
773 // We don't want explicit PacketID compare here, but always via predicate classes below
774 assert(0); // NOLINT: lib
778 inline ostream& operator<<(ostream& ostr, const PacketID& pid)
780 return ostr << "PacketID(id=" << pid.id << ",remote=" << pid.remote.toString() << ",type=" << pid.type << ",tcpsock=" << pid.tcpsock << ",fd=" << pid.fd << ',' << pid.domain << ')';
783 inline ostream& operator<<(ostream& ostr, const shared_ptr<PacketID>& pid)
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.
793 struct PacketIDCompare
795 bool operator()(const std::shared_ptr<PacketID>& lhs, const std::shared_ptr<PacketID>& rhs) const
797 if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) < std::tie(rhs->remote, rhs->tcpsock, rhs->type)) {
800 if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) > std::tie(rhs->remote, rhs->tcpsock, rhs->type)) {
804 return std::tie(lhs->domain, lhs->fd, lhs->id) < std::tie(rhs->domain, rhs->fd, rhs->id);
808 struct PacketIDBirthdayCompare
810 bool operator()(const std::shared_ptr<PacketID>& lhs, const std::shared_ptr<PacketID>& rhs) const
812 if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) < std::tie(rhs->remote, rhs->tcpsock, rhs->type)) {
815 if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) > std::tie(rhs->remote, rhs->tcpsock, rhs->type)) {
818 return lhs->domain < rhs->domain;
821 extern std::unique_ptr<MemRecursorCache> g_recCache;
823 extern rec::GlobalCounters g_Counters;
824 extern thread_local rec::TCounters t_Counters;
826 //! represents a running TCP/IP client session
830 TCPConnection(int fileDesc, const ComboAddress& addr);
832 TCPConnection(const TCPConnection&) = delete;
833 TCPConnection& operator=(const TCPConnection&) = delete;
834 TCPConnection(TCPConnection&&) = delete;
835 TCPConnection& operator=(TCPConnection&&) = delete;
837 [[nodiscard]] int getFD() const
845 [[nodiscard]] bool isDropOnIdle() const
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; }
854 std::vector<ProxyProtocolValue> proxyProtocolValues;
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};
872 uint16_t bytesread{0};
873 uint16_t d_requestsInFlight{0}; // number of mthreads spawned for this connection
877 static std::atomic<uint32_t> s_currentConnections; //!< total number of current TCP connections
878 bool d_dropOnIdle{false};
881 class ImmediateServFailException
884 ImmediateServFailException(string reason_) :
885 reason(std::move(reason_)){};
887 string reason; //! Print this to tell the user what went wrong
890 class PolicyHitException
894 class ImmediateQueryDropException
898 class SendTruncatedAnswerException
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;
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;
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);
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);
925 T broadcastAccFunction(const std::function<T*()>& func);
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);
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));
938 using timebuf_t = std::array<char, 64>;
939 const char* isoDateTimeMillis(const struct timeval& tval, timebuf_t& buf);
941 struct WipeCacheResult
943 int record_count = 0;
944 int negative_record_count = 0;
945 int packet_count = 0;
948 struct WipeCacheResult wipeCaches(const DNSName& canon, bool subtree, uint16_t qtype);
950 extern __thread struct timeval g_now;
955 vector<uint64_t> times;
956 ThreadTimes& operator+=(const ThreadTimes& rhs)
958 times.push_back(rhs.msec);