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 "config.h"
24 #include "ext/luawrapper/include/LuaContext.hpp"
25 
26 #include <mutex>
27 #include <string>
28 #include <thread>
29 #include <time.h>
30 #include <unistd.h>
31 #include <unordered_map>
32 
33 #include <boost/variant.hpp>
34 
35 #include "capabilities.hh"
36 #include "circular_buffer.hh"
37 #include "dnscrypt.hh"
38 #include "dnsdist-cache.hh"
39 #include "dnsdist-dynbpf.hh"
40 #include "dnsdist-lbpolicies.hh"
41 #include "dnsname.hh"
42 #include "doh.hh"
43 #include "ednsoptions.hh"
44 #include "gettime.hh"
45 #include "iputils.hh"
46 #include "misc.hh"
47 #include "mplexer.hh"
48 #include "noinitvector.hh"
49 #include "sholder.hh"
50 #include "tcpiohandler.hh"
51 #include "uuid-utils.hh"
52 #include "proxy-protocol.hh"
53 #include "stat_t.hh"
54 
55 void carbonDumpThread();
56 uint64_t uptimeOfProcess(const std::string& str);
57 
58 extern uint16_t g_ECSSourcePrefixV4;
59 extern uint16_t g_ECSSourcePrefixV6;
60 extern bool g_ECSOverride;
61 
62 using QTag = std::unordered_map<string, string>;
63 
64 struct DNSQuestion
65 {
DNSQuestionDNSQuestion66   DNSQuestion(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, PacketBuffer& data_, bool isTcp, const struct timespec* queryTime_):
67     data(data_), qname(name), local(lc), remote(rem), queryTime(queryTime_), tempFailureTTL(boost::none), qtype(type), qclass(class_), ecsPrefixLength(rem->sin4.sin_family == AF_INET ? g_ECSSourcePrefixV4 : g_ECSSourcePrefixV6), tcp(isTcp), ecsOverride(g_ECSOverride) {
68     const uint16_t* flags = getFlagsFromDNSHeader(getHeader());
69     origFlags = *flags;
70   }
71   DNSQuestion(const DNSQuestion&) = delete;
72   DNSQuestion& operator=(const DNSQuestion&) = delete;
73   DNSQuestion(DNSQuestion&&) = default;
74 
75   std::string getTrailingData() const;
76   bool setTrailingData(const std::string&);
getDataDNSQuestion77   const PacketBuffer& getData() const
78   {
79     return data;
80   }
getMutableDataDNSQuestion81   PacketBuffer& getMutableData()
82   {
83     return data;
84   }
85 
getHeaderDNSQuestion86   dnsheader* getHeader()
87   {
88     if (data.size() < sizeof(dnsheader)) {
89       throw std::runtime_error("Trying to access the dnsheader of a too small (" + std::to_string(data.size()) + ") DNSQuestion buffer");
90     }
91     return reinterpret_cast<dnsheader*>(&data.at(0));
92   }
93 
getHeaderDNSQuestion94   const dnsheader* getHeader() const
95   {
96     if (data.size() < sizeof(dnsheader)) {
97       throw std::runtime_error("Trying to access the dnsheader of a too small (" + std::to_string(data.size()) + ") DNSQuestion buffer");
98     }
99     return reinterpret_cast<const dnsheader*>(&data.at(0));
100   }
101 
hasRoomForDNSQuestion102   bool hasRoomFor(size_t more) const
103   {
104     return data.size() <= getMaximumSize() && (getMaximumSize() - data.size()) >= more;
105   }
106 
getMaximumSizeDNSQuestion107   size_t getMaximumSize() const
108   {
109     if (tcp) {
110       return std::numeric_limits<uint16_t>::max();
111     }
112     return 4096;
113   }
114 
115 protected:
116     PacketBuffer& data;
117 
118 public:
119   boost::optional<boost::uuids::uuid> uniqueId;
120   Netmask ecs;
121   boost::optional<Netmask> subnet;
122   std::string sni; /* Server Name Indication, if any (DoT or DoH) */
123   std::string poolname;
124   const DNSName* qname{nullptr};
125   const ComboAddress* local{nullptr};
126   const ComboAddress* remote{nullptr};
127   /* this is the address dnsdist received the packet on,
128      which might not match local when support for incoming proxy protocol
129      is enabled */
130   const ComboAddress* hopLocal{nullptr};  /* the address dnsdist received the packet from, see above */
131   const ComboAddress* hopRemote{nullptr};
132   std::shared_ptr<QTag> qTag{nullptr};
133   std::unique_ptr<std::vector<ProxyProtocolValue>> proxyProtocolValues{nullptr};
134   mutable std::shared_ptr<std::map<uint16_t, EDNSOptionView> > ednsOptions;
135   std::shared_ptr<DNSCryptQuery> dnsCryptQuery{nullptr};
136   std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
137   const struct timespec* queryTime{nullptr};
138   struct DOHUnit* du{nullptr};
139   int delayMsec{0};
140   boost::optional<uint32_t> tempFailureTTL;
141   uint32_t cacheKeyNoECS{0};
142   uint32_t cacheKey{0};
143   const uint16_t qtype;
144   const uint16_t qclass;
145   uint16_t ecsPrefixLength;
146   uint16_t origFlags;
147   uint16_t cacheFlags; /* DNS flags as sent to the backend */
148   uint8_t ednsRCode{0};
149   const bool tcp;
150   bool skipCache{false};
151   bool ecsOverride;
152   bool useECS{true};
153   bool addXPF{true};
154   bool ecsSet{false};
155   bool ecsAdded{false};
156   bool ednsAdded{false};
157   bool useZeroScope{false};
158   bool dnssecOK{false};
159 };
160 
161 struct DNSResponse : DNSQuestion
162 {
DNSResponseDNSResponse163   DNSResponse(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, PacketBuffer& data_, bool isTcp, const struct timespec* queryTime_):
164     DNSQuestion(name, type, class_, lc, rem, data_, isTcp, queryTime_) { }
165   DNSResponse(const DNSResponse&) = delete;
166   DNSResponse& operator=(const DNSResponse&) = delete;
167   DNSResponse(DNSResponse&&) = default;
168 };
169 
170 /* so what could you do:
171    drop,
172    fake up nxdomain,
173    provide actual answer,
174    allow & and stop processing,
175    continue processing,
176    modify header:    (servfail|refused|notimp), set TC=1,
177    send to pool */
178 
179 class DNSAction
180 {
181 public:
182   enum class Action { Drop, Nxdomain, Refused, Spoof, Allow, HeaderModify, Pool, Delay, Truncate, ServFail, None, NoOp, NoRecurse, SpoofRaw };
typeToString(const Action & action)183   static std::string typeToString(const Action& action)
184   {
185     switch(action) {
186     case Action::Drop:
187       return "Drop";
188     case Action::Nxdomain:
189       return "Send NXDomain";
190     case Action::Refused:
191       return "Send Refused";
192     case Action::Spoof:
193       return "Spoof an answer";
194     case Action::SpoofRaw:
195       return "Spoof an answer from raw bytes";
196     case Action::Allow:
197       return "Allow";
198     case Action::HeaderModify:
199       return "Modify the header";
200     case Action::Pool:
201       return "Route to a pool";
202     case Action::Delay:
203       return "Delay";
204     case Action::Truncate:
205       return "Truncate over UDP";
206     case Action::ServFail:
207       return "Send ServFail";
208     case Action::None:
209     case Action::NoOp:
210       return "Do nothing";
211     case Action::NoRecurse:
212       return "Set rd=0";
213     }
214 
215     return "Unknown";
216   }
217 
218   virtual Action operator()(DNSQuestion*, string* ruleresult) const =0;
~DNSAction()219   virtual ~DNSAction()
220   {
221   }
222   virtual string toString() const = 0;
getStats() const223   virtual std::map<string, double> getStats() const
224   {
225     return {{}};
226   }
227 };
228 
229 class DNSResponseAction
230 {
231 public:
232   enum class Action : uint8_t { Allow, Delay, Drop, HeaderModify, ServFail, None };
233   virtual Action operator()(DNSResponse*, string* ruleresult) const =0;
~DNSResponseAction()234   virtual ~DNSResponseAction()
235   {
236   }
237   virtual string toString() const = 0;
238 };
239 
240 struct DynBlock
241 {
DynBlockDynBlock242   DynBlock(): action(DNSAction::Action::None), warning(false)
243   {
244     until.tv_sec = 0;
245     until.tv_nsec = 0;
246   }
247 
DynBlockDynBlock248   DynBlock(const std::string& reason_, const struct timespec& until_, const DNSName& domain_, DNSAction::Action action_): reason(reason_), domain(domain_), until(until_), action(action_), warning(false)
249   {
250   }
251 
DynBlockDynBlock252   DynBlock(const DynBlock& rhs): reason(rhs.reason), domain(rhs.domain), until(rhs.until), action(rhs.action), warning(rhs.warning), bpf(rhs.bpf)
253   {
254     blocks.store(rhs.blocks);
255   }
256 
DynBlockDynBlock257   DynBlock(DynBlock&& rhs): reason(std::move(rhs.reason)), domain(std::move(rhs.domain)), until(rhs.until), action(rhs.action), warning(rhs.warning), bpf(rhs.bpf)
258   {
259     blocks.store(rhs.blocks);
260   }
261 
operator =DynBlock262   DynBlock& operator=(const DynBlock& rhs)
263   {
264     reason = rhs.reason;
265     until = rhs.until;
266     domain = rhs.domain;
267     action = rhs.action;
268     blocks.store(rhs.blocks);
269     warning = rhs.warning;
270     bpf = rhs.bpf;
271     return *this;
272   }
273 
operator =DynBlock274   DynBlock& operator=(DynBlock&& rhs)
275   {
276     reason = std::move(rhs.reason);
277     until = rhs.until;
278     domain = std::move(rhs.domain);
279     action = rhs.action;
280     blocks.store(rhs.blocks);
281     warning = rhs.warning;
282     bpf = rhs.bpf;
283     return *this;
284   }
285 
286   string reason;
287   DNSName domain;
288   struct timespec until;
289   mutable std::atomic<unsigned int> blocks;
290   DNSAction::Action action{DNSAction::Action::None};
291   bool warning{false};
292   bool bpf{false};
293 };
294 
295 extern GlobalStateHolder<NetmaskTree<DynBlock>> g_dynblockNMG;
296 
297 extern vector<pair<struct timeval, std::string> > g_confDelta;
298 
299 extern uint64_t getLatencyCount(const std::string&);
300 
301 using pdns::stat_t;
302 
303 struct DNSDistStats
304 {
305   stat_t responses{0};
306   stat_t servfailResponses{0};
307   stat_t queries{0};
308   stat_t frontendNXDomain{0};
309   stat_t frontendServFail{0};
310   stat_t frontendNoError{0};
311   stat_t nonCompliantQueries{0};
312   stat_t nonCompliantResponses{0};
313   stat_t rdQueries{0};
314   stat_t emptyQueries{0};
315   stat_t aclDrops{0};
316   stat_t dynBlocked{0};
317   stat_t ruleDrop{0};
318   stat_t ruleNXDomain{0};
319   stat_t ruleRefused{0};
320   stat_t ruleServFail{0};
321   stat_t ruleTruncated{0};
322   stat_t selfAnswered{0};
323   stat_t downstreamTimeouts{0};
324   stat_t downstreamSendErrors{0};
325   stat_t truncFail{0};
326   stat_t noPolicy{0};
327   stat_t cacheHits{0};
328   stat_t cacheMisses{0};
329   stat_t latency0_1{0}, latency1_10{0}, latency10_50{0}, latency50_100{0}, latency100_1000{0}, latencySlow{0}, latencySum{0};
330   stat_t securityStatus{0};
331   stat_t dohQueryPipeFull{0};
332   stat_t dohResponsePipeFull{0};
333   stat_t proxyProtocolInvalid{0};
334 
335   double latencyAvg100{0}, latencyAvg1000{0}, latencyAvg10000{0}, latencyAvg1000000{0};
336   typedef std::function<uint64_t(const std::string&)> statfunction_t;
337   typedef boost::variant<stat_t*, double*, statfunction_t> entry_t;
338   std::vector<std::pair<std::string, entry_t>> entries{
339     {"responses", &responses},
340     {"servfail-responses", &servfailResponses},
341     {"queries", &queries},
342     {"frontend-nxdomain", &frontendNXDomain},
343     {"frontend-servfail", &frontendServFail},
344     {"frontend-noerror", &frontendNoError},
345     {"acl-drops", &aclDrops},
346     {"rule-drop", &ruleDrop},
347     {"rule-nxdomain", &ruleNXDomain},
348     {"rule-refused", &ruleRefused},
349     {"rule-servfail", &ruleServFail},
350     {"rule-truncated", &ruleTruncated},
351     {"self-answered", &selfAnswered},
352     {"downstream-timeouts", &downstreamTimeouts},
353     {"downstream-send-errors", &downstreamSendErrors},
354     {"trunc-failures", &truncFail},
355     {"no-policy", &noPolicy},
356     {"latency0-1", &latency0_1},
357     {"latency1-10", &latency1_10},
358     {"latency10-50", &latency10_50},
359     {"latency50-100", &latency50_100},
360     {"latency100-1000", &latency100_1000},
361     {"latency-slow", &latencySlow},
362     {"latency-avg100", &latencyAvg100},
363     {"latency-avg1000", &latencyAvg1000},
364     {"latency-avg10000", &latencyAvg10000},
365     {"latency-avg1000000", &latencyAvg1000000},
366     {"uptime", uptimeOfProcess},
367     {"real-memory-usage", getRealMemoryUsage},
368     {"special-memory-usage", getSpecialMemoryUsage},
369     {"udp-in-errors", boost::bind(udpErrorStats, "udp-in-errors")},
370     {"udp-noport-errors", boost::bind(udpErrorStats, "udp-noport-errors")},
371     {"udp-recvbuf-errors", boost::bind(udpErrorStats, "udp-recvbuf-errors")},
372     {"udp-sndbuf-errors", boost::bind(udpErrorStats, "udp-sndbuf-errors")},
373     {"tcp-listen-overflows", std::bind(tcpErrorStats, "ListenOverflows")},
374     {"noncompliant-queries", &nonCompliantQueries},
375     {"noncompliant-responses", &nonCompliantResponses},
376     {"proxy-protocol-invalid", &proxyProtocolInvalid},
377     {"rdqueries", &rdQueries},
378     {"empty-queries", &emptyQueries},
379     {"cache-hits", &cacheHits},
380     {"cache-misses", &cacheMisses},
381     {"cpu-iowait", getCPUIOWait},
382     {"cpu-steal", getCPUSteal},
383     {"cpu-sys-msec", getCPUTimeSystem},
384     {"cpu-user-msec", getCPUTimeUser},
385     {"fd-usage", getOpenFileDescriptors},
386     {"dyn-blocked", &dynBlocked},
__anond93cc1860102DNSDistStats387     {"dyn-block-nmg-size", [](const std::string&) { return g_dynblockNMG.getLocal()->size(); }},
388     {"security-status", &securityStatus},
389     {"doh-query-pipe-full", &dohQueryPipeFull},
390     {"doh-response-pipe-full", &dohResponsePipeFull},
391     // Latency histogram
392     {"latency-sum", &latencySum},
393     {"latency-count", getLatencyCount},
394   };
395 };
396 
397 extern struct DNSDistStats g_stats;
398 void doLatencyStats(double udiff);
399 
400 
401 struct StopWatch
402 {
StopWatchStopWatch403   StopWatch(bool realTime=false): d_needRealTime(realTime)
404   {
405   }
406   struct timespec d_start{0,0};
407   bool d_needRealTime{false};
408 
startStopWatch409   void start() {
410     if(gettime(&d_start, d_needRealTime) < 0)
411       unixDie("Getting timestamp");
412 
413   }
414 
setStopWatch415   void set(const struct timespec& from) {
416     d_start = from;
417   }
418 
udiffStopWatch419   double udiff() const {
420     struct timespec now;
421     if(gettime(&now, d_needRealTime) < 0)
422       unixDie("Getting timestamp");
423 
424     return 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0;
425   }
426 
udiffAndSetStopWatch427   double udiffAndSet() {
428     struct timespec now;
429     if(gettime(&now, d_needRealTime) < 0)
430       unixDie("Getting timestamp");
431 
432     auto ret= 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0;
433     d_start = now;
434     return ret;
435   }
436 
437 };
438 
439 class BasicQPSLimiter
440 {
441 public:
BasicQPSLimiter()442   BasicQPSLimiter()
443   {
444   }
445 
BasicQPSLimiter(unsigned int burst)446   BasicQPSLimiter(unsigned int burst): d_tokens(burst)
447   {
448     d_prev.start();
449   }
450 
~BasicQPSLimiter()451   virtual ~BasicQPSLimiter()
452   {
453   }
454 
check(unsigned int rate,unsigned int burst) const455   bool check(unsigned int rate, unsigned int burst) const // this is not quite fair
456   {
457     if (checkOnly(rate, burst)) {
458       addHit();
459       return true;
460     }
461 
462     return false;
463   }
464 
checkOnly(unsigned int rate,unsigned int burst) const465   bool checkOnly(unsigned int rate, unsigned int burst) const // this is not quite fair
466   {
467     auto delta = d_prev.udiffAndSet();
468 
469     if (delta > 0.0) { // time, frequently, does go backwards..
470       d_tokens += 1.0 * rate * (delta/1000000.0);
471     }
472 
473     if (d_tokens > burst) {
474       d_tokens = burst;
475     }
476 
477     bool ret = false;
478     if (d_tokens >= 1.0) { // we need this because burst=1 is weird otherwise
479       ret = true;
480     }
481 
482     return ret;
483   }
484 
addHit() const485   virtual void addHit() const
486   {
487     --d_tokens;
488   }
489 
seenSince(const struct timespec & cutOff) const490   bool seenSince(const struct timespec& cutOff) const
491   {
492     return cutOff < d_prev.d_start;
493   }
494 
495 protected:
496   mutable StopWatch d_prev;
497   mutable double d_tokens{0.0};
498 };
499 
500 class QPSLimiter : public BasicQPSLimiter
501 {
502 public:
QPSLimiter()503   QPSLimiter(): BasicQPSLimiter()
504   {
505   }
506 
QPSLimiter(unsigned int rate,unsigned int burst)507   QPSLimiter(unsigned int rate, unsigned int burst): BasicQPSLimiter(burst), d_rate(rate), d_burst(burst), d_passthrough(false)
508   {
509     d_prev.start();
510   }
511 
getRate() const512   unsigned int getRate() const
513   {
514     return d_passthrough ? 0 : d_rate;
515   }
516 
check() const517   bool check() const // this is not quite fair
518   {
519     if (d_passthrough) {
520       return true;
521     }
522 
523     return BasicQPSLimiter::check(d_rate, d_burst);
524   }
525 
checkOnly() const526   bool checkOnly() const
527   {
528     if (d_passthrough) {
529       return true;
530     }
531 
532     return BasicQPSLimiter::checkOnly(d_rate, d_burst);
533   }
534 
addHit() const535   void addHit() const override
536   {
537     if (!d_passthrough) {
538       --d_tokens;
539     }
540   }
541 
542 private:
543   unsigned int d_rate{0};
544   unsigned int d_burst{0};
545   bool d_passthrough{true};
546 };
547 
548 struct ClientState;
549 
550 /* g++ defines __SANITIZE_THREAD__
551    clang++ supports the nice __has_feature(thread_sanitizer),
552    let's merge them */
553 #if defined(__has_feature)
554 #if __has_feature(thread_sanitizer)
555 #define __SANITIZE_THREAD__ 1
556 #endif
557 #endif
558 
559 struct IDState
560 {
IDStateIDState561   IDState(): sentTime(true), delayMsec(0), tempFailureTTL(boost::none) { origDest.sin4.sin_family = 0;}
562   IDState(const IDState& orig) = delete;
IDStateIDState563   IDState(IDState&& rhs): origRemote(rhs.origRemote), origDest(rhs.origDest), sentTime(rhs.sentTime), qname(std::move(rhs.qname)), dnsCryptQuery(std::move(rhs.dnsCryptQuery)), subnet(rhs.subnet), packetCache(std::move(rhs.packetCache)), qTag(std::move(rhs.qTag)), cs(rhs.cs), du(std::move(rhs.du)), cacheKey(rhs.cacheKey), cacheKeyNoECS(rhs.cacheKeyNoECS), qtype(rhs.qtype), qclass(rhs.qclass), origID(rhs.origID), origFlags(rhs.origFlags), cacheFlags(rhs.cacheFlags), origFD(rhs.origFD), delayMsec(rhs.delayMsec), tempFailureTTL(rhs.tempFailureTTL), ednsAdded(rhs.ednsAdded), ecsAdded(rhs.ecsAdded), skipCache(rhs.skipCache), destHarvested(rhs.destHarvested), dnssecOK(rhs.dnssecOK), useZeroScope(rhs.useZeroScope)
564   {
565     if (rhs.isInUse()) {
566       throw std::runtime_error("Trying to move an in-use IDState");
567     }
568 
569     uniqueId = std::move(rhs.uniqueId);
570 #ifdef __SANITIZE_THREAD__
571     age.store(rhs.age.load());
572 #else
573     age = rhs.age;
574 #endif
575   }
576 
operator =IDState577   IDState& operator=(IDState&& rhs)
578   {
579     if (isInUse()) {
580       throw std::runtime_error("Trying to overwrite an in-use IDState");
581     }
582 
583     if (rhs.isInUse()) {
584       throw std::runtime_error("Trying to move an in-use IDState");
585     }
586 
587     origRemote = rhs.origRemote;
588     origDest = rhs.origDest;
589     sentTime = rhs.sentTime;
590     qname = std::move(rhs.qname);
591     dnsCryptQuery = std::move(rhs.dnsCryptQuery);
592     subnet = rhs.subnet;
593     packetCache = std::move(rhs.packetCache);
594     qTag = std::move(rhs.qTag);
595     cs = rhs.cs;
596     du = std::move(rhs.du);
597     cacheKey = rhs.cacheKey;
598     cacheKeyNoECS = rhs.cacheKeyNoECS;
599     qtype = rhs.qtype;
600     qclass = rhs.qclass;
601     origID = rhs.origID;
602     origFlags = rhs.origFlags;
603     cacheFlags = rhs.cacheFlags;
604     origFD = rhs.origFD;
605     delayMsec = rhs.delayMsec;
606     tempFailureTTL = rhs.tempFailureTTL;
607     ednsAdded = rhs.ednsAdded;
608     ecsAdded = rhs.ecsAdded;
609     skipCache = rhs.skipCache;
610     destHarvested = rhs.destHarvested;
611     dnssecOK = rhs.dnssecOK;
612     useZeroScope = rhs.useZeroScope;
613 #ifdef __SANITIZE_THREAD__
614     age.store(rhs.age.load());
615 #else
616     age = rhs.age;
617 #endif
618     uniqueId = std::move(rhs.uniqueId);
619 
620     return *this;
621   }
622 
623   static const int64_t unusedIndicator = -1;
624 
isInUseIDState625   static bool isInUse(int64_t usageIndicator)
626   {
627     return usageIndicator != unusedIndicator;
628   }
629 
isInUseIDState630   bool isInUse() const
631   {
632     return usageIndicator != unusedIndicator;
633   }
634 
635   /* return true if the value has been successfully replaced meaning that
636      no-one updated the usage indicator in the meantime */
tryMarkUnusedIDState637   bool tryMarkUnused(int64_t expectedUsageIndicator)
638   {
639     return usageIndicator.compare_exchange_strong(expectedUsageIndicator, unusedIndicator);
640   }
641 
642   /* mark as unused no matter what, return true if the state was in use before */
markAsUsedIDState643   bool markAsUsed()
644   {
645     auto currentGeneration = generation++;
646     return markAsUsed(currentGeneration);
647   }
648 
649   /* mark as unused no matter what, return true if the state was in use before */
markAsUsedIDState650   bool markAsUsed(int64_t currentGeneration)
651   {
652     int64_t oldUsage = usageIndicator.exchange(currentGeneration);
653     return oldUsage != unusedIndicator;
654   }
655 
656   /* We use this value to detect whether this state is in use.
657      For performance reasons we don't want to use a lock here, but that means
658      we need to be very careful when modifying this value. Modifications happen
659      from:
660      - one of the UDP or DoH 'client' threads receiving a query, selecting a backend
661        then picking one of the states associated to this backend (via the idOffset).
662        Most of the time this state should not be in use and usageIndicator is -1, but we
663        might not yet have received a response for the query previously associated to this
664        state, meaning that we will 'reuse' this state and erase the existing state.
665        If we ever receive a response for this state, it will be discarded. This is
666        mostly fine for UDP except that we still need to be careful in order to miss
667        the 'outstanding' counters, which should only be increased when we are picking
668        an empty state, and not when reusing ;
669        For DoH, though, we have dynamically allocated a DOHUnit object that needs to
670        be freed, as well as internal objects internals to libh2o.
671      - one of the UDP receiver threads receiving a response from a backend, picking
672        the corresponding state and sending the response to the client ;
673      - the 'healthcheck' thread scanning the states to actively discover timeouts,
674        mostly to keep some counters like the 'outstanding' one sane.
675      We previously based that logic on the origFD (FD on which the query was received,
676      and therefore from where the response should be sent) but this suffered from an
677      ABA problem since it was quite likely that a UDP 'client thread' would reset it to the
678      same value since we only have so much incoming sockets:
679      - 1/ 'client' thread gets a query and set origFD to its FD, say 5 ;
680      - 2/ 'receiver' thread gets a response, read the value of origFD to 5, check that the qname,
681        qtype and qclass match
682      - 3/ during that time the 'client' thread reuses the state, setting again origFD to 5 ;
683      - 4/ the 'receiver' thread uses compare_exchange_strong() to only replace the value if it's still
684        5, except it's not the same 5 anymore and it overrides a fresh state.
685      We now use a 32-bit unsigned counter instead, which is incremented every time the state is set,
686      wrapping around if necessary, and we set an atomic signed 64-bit value, so that we still have -1
687      when the state is unused and the value of our counter otherwise.
688   */
689   std::atomic<int64_t> usageIndicator{unusedIndicator};  // set to unusedIndicator to indicate this state is empty   // 8
690   std::atomic<uint32_t> generation{0}; // increased every time a state is used, to be able to detect an ABA issue    // 4
691   ComboAddress origRemote;                                    // 28
692   ComboAddress origDest;                                      // 28
693   ComboAddress hopRemote;
694   ComboAddress hopLocal;
695   StopWatch sentTime;                                         // 16
696   DNSName qname;                                              // 80
697   std::shared_ptr<DNSCryptQuery> dnsCryptQuery{nullptr};
698   boost::optional<boost::uuids::uuid> uniqueId;
699   boost::optional<Netmask> subnet{boost::none};
700   std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
701   std::shared_ptr<QTag> qTag{nullptr};
702   const ClientState* cs{nullptr};
703   DOHUnit* du{nullptr};
704   uint32_t cacheKey{0};                                       // 4
705   uint32_t cacheKeyNoECS{0};                                  // 4
706 #ifdef __SANITIZE_THREAD__
707   std::atomic<uint16_t> age{0};
708 #else
709   uint16_t age{0};                                            // 4
710 #endif
711   uint16_t qtype{0};                                          // 2
712   uint16_t qclass{0};                                         // 2
713   uint16_t origID{0};                                         // 2
714   uint16_t origFlags{0};                                      // 2
715   uint16_t cacheFlags{0}; // DNS flags as sent to the backend // 2
716   int origFD{-1};
717   int delayMsec{0};
718   boost::optional<uint32_t> tempFailureTTL;
719   bool ednsAdded{false};
720   bool ecsAdded{false};
721   bool skipCache{false};
722   bool destHarvested{false}; // if true, origDest holds the original dest addr, otherwise the listening addr
723   bool dnssecOK{false};
724   bool useZeroScope{false};
725 };
726 
727 typedef std::unordered_map<string, unsigned int> QueryCountRecords;
728 typedef std::function<std::tuple<bool, string>(const DNSQuestion* dq)> QueryCountFilter;
729 struct QueryCount {
QueryCountQueryCount730   QueryCount()
731   {
732   }
~QueryCountQueryCount733   ~QueryCount()
734   {
735   }
736   QueryCountRecords records;
737   QueryCountFilter filter;
738   ReadWriteLock queryLock;
739   bool enabled{false};
740 };
741 
742 extern QueryCount g_qcount;
743 
744 struct ClientState
745 {
ClientStateClientState746   ClientState(const ComboAddress& local_, bool isTCP_, bool doReusePort, int fastOpenQueue, const std::string& itfName, const std::set<int>& cpus_): cpus(cpus_), local(local_), interface(itfName), fastOpenQueueSize(fastOpenQueue), tcp(isTCP_), reuseport(doReusePort)
747   {
748   }
749 
750   std::set<int> cpus;
751   ComboAddress local;
752   std::shared_ptr<DNSCryptContext> dnscryptCtx{nullptr};
753   std::shared_ptr<TLSFrontend> tlsFrontend{nullptr};
754   std::shared_ptr<DOHFrontend> dohFrontend{nullptr};
755   std::string interface;
756   stat_t queries{0};
757   mutable stat_t responses{0};
758   stat_t tcpDiedReadingQuery{0};
759   stat_t tcpDiedSendingResponse{0};
760   stat_t tcpGaveUp{0};
761   stat_t tcpClientTimeouts{0};
762   stat_t tcpDownstreamTimeouts{0};
763   /* current number of connections to this frontend */
764   stat_t tcpCurrentConnections{0};
765   /* maximum number of concurrent connections to this frontend reached */
766   stat_t tcpMaxConcurrentConnections{0};
767   stat_t tlsNewSessions{0}; // A new TLS session has been negotiated, no resumption
768   stat_t tlsResumptions{0}; // A TLS session has been resumed, either via session id or via a TLS ticket
769   stat_t tlsUnknownTicketKey{0}; // A TLS ticket has been presented but we don't have the associated key (might have expired)
770   stat_t tlsInactiveTicketKey{0}; // A TLS ticket has been successfully resumed but the key is no longer active, we should issue a new one
771   stat_t tls10queries{0};   // valid DNS queries received via TLSv1.0
772   stat_t tls11queries{0};   // valid DNS queries received via TLSv1.1
773   stat_t tls12queries{0};   // valid DNS queries received via TLSv1.2
774   stat_t tls13queries{0};   // valid DNS queries received via TLSv1.3
775   stat_t tlsUnknownqueries{0};   // valid DNS queries received via unknown TLS version
776   pdns::stat_t_trait<double> tcpAvgQueriesPerConnection{0.0};
777   /* in ms */
778   pdns::stat_t_trait<double> tcpAvgConnectionDuration{0.0};
779   size_t d_maxInFlightQueriesPerConn{1};
780   size_t d_tcpConcurrentConnectionsLimit{0};
781   int udpFD{-1};
782   int tcpFD{-1};
783   int tcpListenQueueSize{SOMAXCONN};
784   int fastOpenQueueSize{0};
785   bool muted{false};
786   bool tcp;
787   bool reuseport;
788   bool ready{false};
789 
getSocketClientState790   int getSocket() const
791   {
792     return udpFD != -1 ? udpFD : tcpFD;
793   }
794 
isUDPClientState795   bool isUDP() const
796   {
797     return udpFD != -1;
798   }
799 
isTCPClientState800   bool isTCP() const
801   {
802     return udpFD == -1;
803   }
804 
hasTLSClientState805   bool hasTLS() const
806   {
807     return tlsFrontend != nullptr || dohFrontend != nullptr;
808   }
809 
getTypeClientState810   std::string getType() const
811   {
812     std::string result = udpFD != -1 ? "UDP" : "TCP";
813 
814     if (dohFrontend) {
815       result += " (DNS over HTTPS)";
816     }
817     else if (tlsFrontend) {
818       result += " (DNS over TLS)";
819     }
820     else if (dnscryptCtx) {
821       result += " (DNSCrypt)";
822     }
823 
824     return result;
825   }
826 
827   shared_ptr<BPFFilter> d_filter;
828 
detachFilterClientState829   void detachFilter()
830   {
831     if (d_filter) {
832       d_filter->removeSocket(getSocket());
833       d_filter = nullptr;
834     }
835   }
836 
attachFilterClientState837   void attachFilter(shared_ptr<BPFFilter> bpf)
838   {
839     detachFilter();
840 
841     bpf->addSocket(getSocket());
842     d_filter = bpf;
843   }
844 
updateTCPMetricsClientState845   void updateTCPMetrics(size_t nbQueries, uint64_t durationMs)
846   {
847     tcpAvgQueriesPerConnection = (99.0 * tcpAvgQueriesPerConnection / 100.0) + (nbQueries / 100.0);
848     tcpAvgConnectionDuration = (99.0 * tcpAvgConnectionDuration / 100.0) + (durationMs / 100.0);
849   }
850 };
851 
852 class TCPClientCollection {
853   std::vector<int> d_tcpclientthreads;
854   stat_t d_numthreads{0};
855   stat_t d_pos{0};
856   stat_t d_queued{0};
857   const uint64_t d_maxthreads{0};
858   std::mutex d_mutex;
859   int d_singlePipe[2];
860   const bool d_useSinglePipe;
861 public:
862 
863   TCPClientCollection(size_t maxThreads, bool useSinglePipe=false);
getThread()864   int getThread()
865   {
866     if (d_numthreads == 0) {
867       throw std::runtime_error("No TCP worker thread yet");
868     }
869 
870     uint64_t pos = d_pos++;
871     ++d_queued;
872     return d_tcpclientthreads.at(pos % d_numthreads);
873   }
hasReachedMaxThreads() const874   bool hasReachedMaxThreads() const
875   {
876     return d_numthreads >= d_maxthreads;
877   }
getThreadsCount() const878   uint64_t getThreadsCount() const
879   {
880     return d_numthreads;
881   }
getQueuedCount() const882   uint64_t getQueuedCount() const
883   {
884     return d_queued;
885   }
decrementQueuedCount()886   void decrementQueuedCount()
887   {
888     --d_queued;
889   }
890   void addTCPClientThread();
891 };
892 
893 extern std::unique_ptr<TCPClientCollection> g_tcpclientthreads;
894 
895 struct DownstreamState
896 {
897    typedef std::function<std::tuple<DNSName, uint16_t, uint16_t>(const DNSName&, uint16_t, uint16_t, dnsheader*)> checkfunc_t;
898 
899   DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf, const std::string& sourceItfName, size_t numberOfSockets, bool connect);
DownstreamStateDownstreamState900   DownstreamState(const ComboAddress& remote_): DownstreamState(remote_, ComboAddress(), 0, std::string(), 1, true) {}
901   ~DownstreamState();
902 
903   boost::uuids::uuid id;
904   std::vector<unsigned int> hashes;
905   mutable ReadWriteLock d_lock;
906   std::vector<int> sockets;
907   const std::string sourceItfName;
908   std::mutex socketsLock;
909   std::mutex connectLock;
910   std::unique_ptr<FDMultiplexer> mplexer{nullptr};
911   std::shared_ptr<TLSCtx> d_tlsCtx{nullptr};
912   std::thread tid;
913   const ComboAddress remote;
914   QPSLimiter qps;
915   vector<IDState> idStates;
916   const ComboAddress sourceAddr;
917   checkfunc_t checkFunction;
918   DNSName checkName{"a.root-servers.net."};
919   QType checkType{QType::A};
920   uint16_t checkClass{QClass::IN};
921   std::atomic<uint64_t> idOffset{0};
922   stat_t sendErrors{0};
923   stat_t outstanding{0};
924   stat_t reuseds{0};
925   stat_t queries{0};
926   stat_t responses{0};
927   struct {
928     stat_t sendErrors{0};
929     stat_t reuseds{0};
930     stat_t queries{0};
931   } prev;
932   stat_t tcpDiedSendingQuery{0};
933   stat_t tcpDiedReadingResponse{0};
934   stat_t tcpGaveUp{0};
935   stat_t tcpReadTimeouts{0};
936   stat_t tcpWriteTimeouts{0};
937   stat_t tcpConnectTimeouts{0};
938   /* current number of connections to this backend */
939   stat_t tcpCurrentConnections{0};
940   /* maximum number of concurrent connections to this backend reached */
941   stat_t tcpMaxConcurrentConnections{0};
942   stat_t tcpReusedConnections{0};
943   stat_t tcpNewConnections{0};
944   pdns::stat_t_trait<double> tcpAvgQueriesPerConnection{0.0};
945   /* in ms */
946   pdns::stat_t_trait<double> tcpAvgConnectionDuration{0.0};
947   size_t socketsOffset{0};
948   size_t d_maxInFlightQueriesPerConn{1};
949   size_t d_tcpConcurrentConnectionsLimit{0};
950   pdns::stat_t_trait<double> queryLoad{0.0};
951   pdns::stat_t_trait<double> dropRate{0.0};
952   double latencyUsec{0.0};
953   int order{1};
954   int weight{1};
955   int tcpConnectTimeout{5};
956   int tcpRecvTimeout{30};
957   int tcpSendTimeout{30};
958   unsigned int checkInterval{1};
959   unsigned int lastCheck{0};
960   const unsigned int sourceItf{0};
961   uint16_t retries{5};
962   uint16_t xpfRRCode{0};
963   uint16_t checkTimeout{1000}; /* in milliseconds */
964   uint8_t currentCheckFailures{0};
965   uint8_t consecutiveSuccessfulChecks{0};
966   uint8_t maxCheckFailures{1};
967   uint8_t minRiseSuccesses{1};
968   StopWatch sw;
969   set<string> pools;
970   enum class Availability { Up, Down, Auto} availability{Availability::Auto};
971   bool mustResolve{false};
972   bool upStatus{false};
973   bool useECS{false};
974   bool useProxyProtocol{false};
975   bool setCD{false};
976   bool disableZeroScope{false};
977   std::atomic<bool> connected{false};
978   std::atomic_flag threadStarted;
979   bool tcpFastOpen{false};
980   bool ipBindAddrNoPort{true};
981   bool reconnectOnUp{false};
982 
isUpDownstreamState983   bool isUp() const
984   {
985     if(availability == Availability::Down)
986       return false;
987     if(availability == Availability::Up)
988       return true;
989     return upStatus;
990   }
setUpDownstreamState991   void setUp() { availability = Availability::Up; }
setDownDownstreamState992   void setDown() { availability = Availability::Down; }
setAutoDownstreamState993   void setAuto() { availability = Availability::Auto; }
getNameDownstreamState994   const string& getName() const {
995     return name;
996   }
getNameWithAddrDownstreamState997   const string& getNameWithAddr() const {
998     return nameWithAddr;
999   }
setNameDownstreamState1000   void setName(const std::string& newName)
1001   {
1002     name = newName;
1003     nameWithAddr = newName.empty() ? remote.toStringWithPort() : (name + " (" + remote.toStringWithPort()+ ")");
1004   }
1005 
getStatusDownstreamState1006   string getStatus() const
1007   {
1008     string status;
1009     if(availability == DownstreamState::Availability::Up)
1010       status = "UP";
1011     else if(availability == DownstreamState::Availability::Down)
1012       status = "DOWN";
1013     else
1014       status = (upStatus ? "up" : "down");
1015     return status;
1016   }
1017   bool reconnect();
1018   void hash();
1019   void setId(const boost::uuids::uuid& newId);
1020   void setWeight(int newWeight);
1021   void stop();
isStoppedDownstreamState1022   bool isStopped() const
1023   {
1024     return d_stopped;
1025   }
1026 
updateTCPMetricsDownstreamState1027   void updateTCPMetrics(size_t nbQueries, uint64_t durationMs)
1028   {
1029     tcpAvgQueriesPerConnection = (99.0 * tcpAvgQueriesPerConnection / 100.0) + (nbQueries / 100.0);
1030     tcpAvgConnectionDuration = (99.0 * tcpAvgConnectionDuration / 100.0) + (durationMs / 100.0);
1031   }
1032 
incQueriesCountDownstreamState1033   void incQueriesCount()
1034   {
1035     ++queries;
1036     qps.addHit();
1037   }
1038 
1039 private:
1040   std::string name;
1041   std::string nameWithAddr;
1042   bool d_stopped{false};
1043 };
1044 using servers_t =vector<std::shared_ptr<DownstreamState>>;
1045 
1046 void responderThread(std::shared_ptr<DownstreamState> state);
1047 extern std::mutex g_luamutex;
1048 extern LuaContext g_lua;
1049 extern std::string g_outputBuffer; // locking for this is ok, as locked by g_luamutex
1050 
1051 class DNSRule
1052 {
1053 public:
~DNSRule()1054   virtual ~DNSRule ()
1055   {
1056   }
1057   virtual bool matches(const DNSQuestion* dq) const =0;
1058   virtual string toString() const = 0;
1059   mutable stat_t d_matches{0};
1060 };
1061 
1062 struct ServerPool
1063 {
ServerPoolServerPool1064   ServerPool(): d_servers(std::make_shared<ServerPolicy::NumberedServerVector>())
1065   {
1066   }
1067 
~ServerPoolServerPool1068   ~ServerPool()
1069   {
1070   }
1071 
getCacheServerPool1072   const std::shared_ptr<DNSDistPacketCache> getCache() const { return packetCache; };
1073 
getECSServerPool1074   bool getECS() const
1075   {
1076     return d_useECS;
1077   }
1078 
setECSServerPool1079   void setECS(bool useECS)
1080   {
1081     d_useECS = useECS;
1082   }
1083 
1084   std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
1085   std::shared_ptr<ServerPolicy> policy{nullptr};
1086 
countServersServerPool1087   size_t countServers(bool upOnly)
1088   {
1089     size_t count = 0;
1090     ReadLock rl(&d_lock);
1091     for (const auto& server : *d_servers) {
1092       if (!upOnly || std::get<1>(server)->isUp() ) {
1093         count++;
1094       }
1095     }
1096     return count;
1097   }
1098 
getServersServerPool1099   const std::shared_ptr<ServerPolicy::NumberedServerVector> getServers()
1100   {
1101     std::shared_ptr<ServerPolicy::NumberedServerVector> result;
1102     {
1103       ReadLock rl(&d_lock);
1104       result = d_servers;
1105     }
1106     return result;
1107   }
1108 
addServerServerPool1109   void addServer(shared_ptr<DownstreamState>& server)
1110   {
1111     WriteLock wl(&d_lock);
1112     /* we can't update the content of the shared pointer directly even when holding the lock,
1113        as other threads might hold a copy. We can however update the pointer as long as we hold the lock. */
1114     unsigned int count = static_cast<unsigned int>(d_servers->size());
1115     auto newServers = std::make_shared<ServerPolicy::NumberedServerVector>(*d_servers);
1116     newServers->push_back(make_pair(++count, server));
1117     /* we need to reorder based on the server 'order' */
1118     std::stable_sort(newServers->begin(), newServers->end(), [](const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& a, const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& b) {
1119       return a.second->order < b.second->order;
1120     });
1121     /* and now we need to renumber for Lua (custom policies) */
1122     size_t idx = 1;
1123     for (auto& serv : *newServers) {
1124       serv.first = idx++;
1125     }
1126     d_servers = newServers;
1127   }
1128 
removeServerServerPool1129   void removeServer(shared_ptr<DownstreamState>& server)
1130   {
1131     WriteLock wl(&d_lock);
1132     /* we can't update the content of the shared pointer directly even when holding the lock,
1133        as other threads might hold a copy. We can however update the pointer as long as we hold the lock. */
1134     auto newServers = std::make_shared<ServerPolicy::NumberedServerVector>(*d_servers);
1135     size_t idx = 1;
1136     bool found = false;
1137     for (auto it = newServers->begin(); it != newServers->end();) {
1138       if (found) {
1139         /* we need to renumber the servers placed
1140            after the removed one, for Lua (custom policies) */
1141         it->first = idx++;
1142         it++;
1143       }
1144       else if (it->second == server) {
1145         it = newServers->erase(it);
1146         found = true;
1147       } else {
1148         idx++;
1149         it++;
1150       }
1151     }
1152     d_servers = newServers;
1153   }
1154 
1155 private:
1156   std::shared_ptr<ServerPolicy::NumberedServerVector> d_servers;
1157   ReadWriteLock d_lock;
1158   bool d_useECS{false};
1159 };
1160 
1161 struct CarbonConfig
1162 {
1163   ComboAddress server;
1164   std::string namespace_name;
1165   std::string ourname;
1166   std::string instance_name;
1167   unsigned int interval;
1168 };
1169 
1170 enum ednsHeaderFlags {
1171   EDNS_HEADER_FLAG_NONE = 0,
1172   EDNS_HEADER_FLAG_DO = 32768
1173 };
1174 
1175 struct DNSDistRuleAction
1176 {
1177   std::shared_ptr<DNSRule> d_rule;
1178   std::shared_ptr<DNSAction> d_action;
1179   std::string d_name;
1180   boost::uuids::uuid d_id;
1181   uint64_t d_creationOrder;
1182 };
1183 
1184 struct DNSDistResponseRuleAction
1185 {
1186   std::shared_ptr<DNSRule> d_rule;
1187   std::shared_ptr<DNSResponseAction> d_action;
1188   std::string d_name;
1189   boost::uuids::uuid d_id;
1190   uint64_t d_creationOrder;
1191 };
1192 
1193 extern GlobalStateHolder<SuffixMatchTree<DynBlock>> g_dynblockSMT;
1194 extern DNSAction::Action g_dynBlockAction;
1195 
1196 extern GlobalStateHolder<vector<CarbonConfig> > g_carbon;
1197 extern GlobalStateHolder<ServerPolicy> g_policy;
1198 extern GlobalStateHolder<servers_t> g_dstates;
1199 extern GlobalStateHolder<pools_t> g_pools;
1200 extern GlobalStateHolder<vector<DNSDistRuleAction> > g_ruleactions;
1201 extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_respruleactions;
1202 extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_cachehitrespruleactions;
1203 extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_selfansweredrespruleactions;
1204 extern GlobalStateHolder<NetmaskGroup> g_ACL;
1205 
1206 extern ComboAddress g_serverControl; // not changed during runtime
1207 
1208 extern std::vector<shared_ptr<TLSFrontend>> g_tlslocals;
1209 extern std::vector<shared_ptr<DOHFrontend>> g_dohlocals;
1210 extern std::vector<std::unique_ptr<ClientState>> g_frontends;
1211 extern bool g_truncateTC;
1212 extern bool g_fixupCase;
1213 extern int g_tcpRecvTimeout;
1214 extern int g_tcpSendTimeout;
1215 extern int g_udpTimeout;
1216 extern uint16_t g_maxOutstanding;
1217 extern std::atomic<bool> g_configurationDone;
1218 extern boost::optional<uint64_t> g_maxTCPClientThreads;
1219 extern uint64_t g_maxTCPQueuedConnections;
1220 extern size_t g_maxTCPQueriesPerConn;
1221 extern size_t g_maxTCPConnectionDuration;
1222 extern size_t g_maxTCPConnectionsPerClient;
1223 extern size_t g_tcpInternalPipeBufferSize;
1224 extern pdns::stat16_t g_cacheCleaningDelay;
1225 extern pdns::stat16_t g_cacheCleaningPercentage;
1226 extern uint32_t g_staleCacheEntriesTTL;
1227 extern bool g_apiReadWrite;
1228 extern std::string g_apiConfigDirectory;
1229 extern bool g_servFailOnNoPolicy;
1230 extern bool g_useTCPSinglePipe;
1231 extern uint16_t g_downstreamTCPCleanupInterval;
1232 extern size_t g_udpVectorSize;
1233 extern bool g_allowEmptyResponse;
1234 
1235 extern shared_ptr<BPFFilter> g_defaultBPFFilter;
1236 extern std::vector<std::shared_ptr<DynBPFFilter> > g_dynBPFFilters;
1237 
1238 struct LocalHolders
1239 {
LocalHoldersLocalHolders1240   LocalHolders(): acl(g_ACL.getLocal()), policy(g_policy.getLocal()), ruleactions(g_ruleactions.getLocal()), cacheHitRespRuleactions(g_cachehitrespruleactions.getLocal()), selfAnsweredRespRuleactions(g_selfansweredrespruleactions.getLocal()), servers(g_dstates.getLocal()), dynNMGBlock(g_dynblockNMG.getLocal()), dynSMTBlock(g_dynblockSMT.getLocal()), pools(g_pools.getLocal())
1241   {
1242   }
1243 
1244   LocalStateHolder<NetmaskGroup> acl;
1245   LocalStateHolder<ServerPolicy> policy;
1246   LocalStateHolder<vector<DNSDistRuleAction> > ruleactions;
1247   LocalStateHolder<vector<DNSDistResponseRuleAction> > cacheHitRespRuleactions;
1248   LocalStateHolder<vector<DNSDistResponseRuleAction> > selfAnsweredRespRuleactions;
1249   LocalStateHolder<servers_t> servers;
1250   LocalStateHolder<NetmaskTree<DynBlock> > dynNMGBlock;
1251   LocalStateHolder<SuffixMatchTree<DynBlock> > dynSMTBlock;
1252   LocalStateHolder<pools_t> pools;
1253 };
1254 
1255 vector<std::function<void(void)>> setupLua(bool client, const std::string& config);
1256 
1257 void tcpAcceptorThread(ClientState* p);
1258 void setMaxCachedTCPConnectionsPerDownstream(size_t max);
1259 
1260 #ifdef HAVE_DNS_OVER_HTTPS
1261 void dohThread(ClientState* cs);
1262 #endif /* HAVE_DNS_OVER_HTTPS */
1263 
1264 void setLuaNoSideEffect(); // if nothing has been declared, set that there are no side effects
1265 void setLuaSideEffect();   // set to report a side effect, cancelling all _no_ side effect calls
1266 bool getLuaNoSideEffect(); // set if there were only explicit declarations of _no_ side effect
1267 void resetLuaSideEffect(); // reset to indeterminate state
1268 
1269 bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& remote, unsigned int& qnameWireLength);
1270 bool processResponse(PacketBuffer& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRuleActions, DNSResponse& dr, bool muted);
1271 bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::string& ruleresult, bool& drop);
1272 
1273 bool checkQueryHeaders(const struct dnsheader* dh);
1274 
1275 extern std::vector<std::shared_ptr<DNSCryptContext>> g_dnsCryptLocals;
1276 int handleDNSCryptQuery(PacketBuffer& packet, std::shared_ptr<DNSCryptQuery>& query, bool tcp, time_t now, PacketBuffer& response);
1277 bool checkDNSCryptQuery(const ClientState& cs, PacketBuffer& query, std::shared_ptr<DNSCryptQuery>& dnsCryptQuery, time_t now, bool tcp);
1278 
1279 uint16_t getRandomDNSID();
1280 
1281 #include "dnsdist-snmp.hh"
1282 
1283 extern bool g_snmpEnabled;
1284 extern bool g_snmpTrapsEnabled;
1285 extern DNSDistSNMPAgent* g_snmpAgent;
1286 extern bool g_addEDNSToSelfGeneratedResponses;
1287 
1288 extern std::set<std::string> g_capabilitiesToRetain;
1289 static const uint16_t s_udpIncomingBufferSize{1500}; // don't accept UDP queries larger than this value
1290 static const size_t s_maxPacketCacheEntrySize{4096}; // don't cache responses larger than this value
1291 
1292 enum class ProcessQueryResult { Drop, SendAnswer, PassToBackend };
1293 ProcessQueryResult processQuery(DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr<DownstreamState>& selectedBackend);
1294 
1295 DNSResponse makeDNSResponseFromIDState(IDState& ids, PacketBuffer& data, bool isTCP);
1296 void setIDStateFromDNSQuestion(IDState& ids, DNSQuestion& dq, DNSName&& qname);
1297 
1298 int pickBackendSocketForSending(std::shared_ptr<DownstreamState>& state);
1299 ssize_t udpClientSendRequestToBackend(const std::shared_ptr<DownstreamState>& ss, const int sd, const PacketBuffer& request, bool healthCheck = false);
1300