]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsdist.hh
Merge pull request #4354 from rgacogne/rec-delegation-only
[thirdparty/pdns.git] / pdns / dnsdist.hh
1 #pragma once
2 #include "config.h"
3 #include "ext/luawrapper/include/LuaContext.hpp"
4 #include <time.h>
5 #include "misc.hh"
6 #include "iputils.hh"
7 #include "dnsname.hh"
8 #include <atomic>
9 #include <boost/circular_buffer.hpp>
10 #include <boost/variant.hpp>
11 #include <mutex>
12 #include <thread>
13 #include <unistd.h>
14 #include "sholder.hh"
15 #include "dnscrypt.hh"
16 #include "dnsdist-cache.hh"
17 #include "gettime.hh"
18 #include "dnsdist-dynbpf.hh"
19 #include "bpf-filter.hh"
20
21 #ifdef HAVE_PROTOBUF
22 #include <boost/uuid/uuid.hpp>
23 #include <boost/uuid/uuid_generators.hpp>
24 #endif
25
26 void* carbonDumpThread();
27 uint64_t uptimeOfProcess(const std::string& str);
28
29 struct DynBlock
30 {
31 DynBlock& operator=(const DynBlock& rhs)
32 {
33 reason=rhs.reason;
34 until=rhs.until;
35 domain=rhs.domain;
36 blocks.store(rhs.blocks);
37 return *this;
38 }
39
40 string reason;
41 struct timespec until;
42 DNSName domain;
43 mutable std::atomic<unsigned int> blocks;
44 };
45
46 extern GlobalStateHolder<NetmaskTree<DynBlock>> g_dynblockNMG;
47
48 extern vector<pair<struct timeval, std::string> > g_confDelta;
49
50 struct DNSDistStats
51 {
52 using stat_t=std::atomic<uint64_t>; // aww yiss ;-)
53 stat_t responses{0};
54 stat_t servfailResponses{0};
55 stat_t queries{0};
56 stat_t nonCompliantQueries{0};
57 stat_t nonCompliantResponses{0};
58 stat_t rdQueries{0};
59 stat_t emptyQueries{0};
60 stat_t aclDrops{0};
61 stat_t blockFilter{0};
62 stat_t dynBlocked{0};
63 stat_t ruleDrop{0};
64 stat_t ruleNXDomain{0};
65 stat_t selfAnswered{0};
66 stat_t downstreamTimeouts{0};
67 stat_t downstreamSendErrors{0};
68 stat_t truncFail{0};
69 stat_t noPolicy{0};
70 stat_t cacheHits{0};
71 stat_t cacheMisses{0};
72 stat_t latency0_1{0}, latency1_10{0}, latency10_50{0}, latency50_100{0}, latency100_1000{0}, latencySlow{0};
73
74 double latencyAvg100{0}, latencyAvg1000{0}, latencyAvg10000{0}, latencyAvg1000000{0};
75 typedef std::function<uint64_t(const std::string&)> statfunction_t;
76 typedef boost::variant<stat_t*, double*, statfunction_t> entry_t;
77 std::vector<std::pair<std::string, entry_t>> entries{
78 {"responses", &responses}, {"servfail-responses", &servfailResponses},
79 {"queries", &queries}, {"acl-drops", &aclDrops},
80 {"block-filter", &blockFilter}, {"rule-drop", &ruleDrop},
81 {"rule-nxdomain", &ruleNXDomain}, {"self-answered", &selfAnswered},
82 {"downstream-timeouts", &downstreamTimeouts}, {"downstream-send-errors", &downstreamSendErrors},
83 {"trunc-failures", &truncFail}, {"no-policy", &noPolicy},
84 {"latency0-1", &latency0_1}, {"latency1-10", &latency1_10},
85 {"latency10-50", &latency10_50}, {"latency50-100", &latency50_100},
86 {"latency100-1000", &latency100_1000}, {"latency-slow", &latencySlow},
87 {"latency-avg100", &latencyAvg100}, {"latency-avg1000", &latencyAvg1000},
88 {"latency-avg10000", &latencyAvg10000}, {"latency-avg1000000", &latencyAvg1000000},
89 {"uptime", uptimeOfProcess},
90 {"real-memory-usage", getRealMemoryUsage},
91 {"noncompliant-queries", &nonCompliantQueries},
92 {"noncompliant-responses", &nonCompliantResponses},
93 {"rdqueries", &rdQueries},
94 {"empty-queries", &emptyQueries},
95 {"cache-hits", &cacheHits},
96 {"cache-misses", &cacheMisses},
97 {"cpu-user-msec", getCPUTimeUser},
98 {"cpu-sys-msec", getCPUTimeSystem},
99 {"fd-usage", getOpenFileDescriptors}, {"dyn-blocked", &dynBlocked},
100 {"dyn-block-nmg-size", [](const std::string&) { return g_dynblockNMG.getLocal()->size(); }}
101 };
102 };
103
104
105 extern struct DNSDistStats g_stats;
106
107
108 struct StopWatch
109 {
110 StopWatch(bool realTime=false): d_needRealTime(realTime)
111 {
112 }
113 struct timespec d_start{0,0};
114 bool d_needRealTime{false};
115
116 void start() {
117 if(gettime(&d_start, d_needRealTime) < 0)
118 unixDie("Getting timestamp");
119
120 }
121
122 double udiff() const {
123 struct timespec now;
124 if(gettime(&now, d_needRealTime) < 0)
125 unixDie("Getting timestamp");
126
127 return 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0;
128 }
129
130 double udiffAndSet() {
131 struct timespec now;
132 if(gettime(&now, d_needRealTime) < 0)
133 unixDie("Getting timestamp");
134
135 auto ret= 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0;
136 d_start = now;
137 return ret;
138 }
139
140 };
141
142 class QPSLimiter
143 {
144 public:
145 QPSLimiter()
146 {
147 }
148
149 QPSLimiter(unsigned int rate, unsigned int burst) : d_rate(rate), d_burst(burst), d_tokens(burst)
150 {
151 d_passthrough=false;
152 d_prev.start();
153 }
154
155 unsigned int getRate() const
156 {
157 return d_passthrough? 0 : d_rate;
158 }
159
160 int getPassed() const
161 {
162 return d_passed;
163 }
164 int getBlocked() const
165 {
166 return d_blocked;
167 }
168
169 bool check() const // this is not quite fair
170 {
171 if(d_passthrough)
172 return true;
173 auto delta = d_prev.udiffAndSet();
174
175 d_tokens += 1.0*d_rate * (delta/1000000.0);
176
177 if(d_tokens > d_burst)
178 d_tokens = d_burst;
179
180 bool ret=false;
181 if(d_tokens >= 1.0) { // we need this because burst=1 is weird otherwise
182 ret=true;
183 --d_tokens;
184 d_passed++;
185 }
186 else
187 d_blocked++;
188
189 return ret;
190 }
191 private:
192 bool d_passthrough{true};
193 unsigned int d_rate;
194 unsigned int d_burst;
195 mutable double d_tokens;
196 mutable StopWatch d_prev;
197 mutable unsigned int d_passed{0};
198 mutable unsigned int d_blocked{0};
199 };
200
201 struct IDState
202 {
203 IDState() : origFD(-1), sentTime(true), delayMsec(0) { origDest.sin4.sin_family = 0;}
204 IDState(const IDState& orig)
205 {
206 origFD = orig.origFD;
207 origID = orig.origID;
208 origRemote = orig.origRemote;
209 origDest = orig.origDest;
210 delayMsec = orig.delayMsec;
211 age.store(orig.age.load());
212 }
213
214 int origFD; // set to <0 to indicate this state is empty // 4
215
216 ComboAddress origRemote; // 28
217 ComboAddress origDest; // 28
218 StopWatch sentTime; // 16
219 DNSName qname; // 80
220 #ifdef HAVE_DNSCRYPT
221 std::shared_ptr<DnsCryptQuery> dnsCryptQuery{0};
222 #endif
223 #ifdef HAVE_PROTOBUF
224 boost::uuids::uuid uniqueId;
225 #endif
226 std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
227 uint32_t cacheKey; // 8
228 std::atomic<uint16_t> age; // 4
229 uint16_t qtype; // 2
230 uint16_t qclass; // 2
231 uint16_t origID; // 2
232 uint16_t origFlags; // 2
233 int delayMsec;
234 bool ednsAdded{false};
235 bool ecsAdded{false};
236 bool skipCache{false};
237 };
238
239 struct Rings {
240 Rings()
241 {
242 queryRing.set_capacity(10000);
243 respRing.set_capacity(10000);
244 pthread_rwlock_init(&queryLock, 0);
245 }
246 struct Query
247 {
248 struct timespec when;
249 ComboAddress requestor;
250 DNSName name;
251 uint16_t size;
252 uint16_t qtype;
253 struct dnsheader dh;
254 };
255 boost::circular_buffer<Query> queryRing;
256 struct Response
257 {
258 struct timespec when;
259 ComboAddress requestor;
260 DNSName name;
261 uint16_t qtype;
262 unsigned int usec;
263 unsigned int size;
264 struct dnsheader dh;
265 ComboAddress ds; // who handled it
266 };
267 boost::circular_buffer<Response> respRing;
268 std::mutex respMutex;
269 pthread_rwlock_t queryLock;
270
271 std::unordered_map<int, vector<boost::variant<string,double> > > getTopBandwidth(unsigned int numentries);
272 size_t numDistinctRequestors();
273 };
274
275 extern Rings g_rings;
276
277 typedef std::unordered_map<string, unsigned int> QueryCountRecords;
278 typedef std::function<std::tuple<bool, string>(DNSQuestion dq)> QueryCountFilter;
279 struct QueryCount {
280 QueryCount()
281 {
282 pthread_rwlock_init(&queryLock, 0);
283 }
284 QueryCountRecords records;
285 QueryCountFilter filter;
286 pthread_rwlock_t queryLock;
287 bool enabled{false};
288 };
289
290 extern QueryCount g_qcount;
291
292 struct ClientState
293 {
294 ComboAddress local;
295 #ifdef HAVE_DNSCRYPT
296 DnsCryptContext* dnscryptCtx{0};
297 #endif
298 std::atomic<uint64_t> queries{0};
299 int udpFD{-1};
300 int tcpFD{-1};
301
302 int getSocket() const
303 {
304 return udpFD != -1 ? udpFD : tcpFD;
305 }
306
307 #ifdef HAVE_EBPF
308 shared_ptr<BPFFilter> d_filter;
309
310 void detachFilter()
311 {
312 if (d_filter) {
313 d_filter->removeSocket(getSocket());
314 d_filter = nullptr;
315 }
316 }
317
318 void attachFilter(shared_ptr<BPFFilter> bpf)
319 {
320 detachFilter();
321
322 bpf->addSocket(getSocket());
323 d_filter = bpf;
324 }
325 #endif /* HAVE_EBPF */
326 };
327
328 class TCPClientCollection {
329 std::vector<int> d_tcpclientthreads;
330 std::atomic<uint64_t> d_pos{0};
331 public:
332 std::atomic<uint64_t> d_queued{0}, d_numthreads{0};
333 uint64_t d_maxthreads{0};
334
335 TCPClientCollection(size_t maxThreads)
336 {
337 d_maxthreads = maxThreads;
338 d_tcpclientthreads.reserve(maxThreads);
339 }
340
341 int getThread()
342 {
343 uint64_t pos = d_pos++;
344 ++d_queued;
345 return d_tcpclientthreads[pos % d_numthreads];
346 }
347 void addTCPClientThread();
348 };
349
350 extern std::shared_ptr<TCPClientCollection> g_tcpclientthreads;
351
352 struct DownstreamState
353 {
354 DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf);
355 DownstreamState(const ComboAddress& remote_): DownstreamState(remote_, ComboAddress(), 0) {}
356 ~DownstreamState()
357 {
358 if (fd >= 0)
359 close(fd);
360 }
361
362 int fd{-1};
363 std::thread tid;
364 ComboAddress remote;
365 QPSLimiter qps;
366 vector<IDState> idStates;
367 ComboAddress sourceAddr;
368 DNSName checkName{"a.root-servers.net."};
369 QType checkType{QType::A};
370 std::atomic<uint64_t> idOffset{0};
371 std::atomic<uint64_t> sendErrors{0};
372 std::atomic<uint64_t> outstanding{0};
373 std::atomic<uint64_t> reuseds{0};
374 std::atomic<uint64_t> queries{0};
375 struct {
376 std::atomic<uint64_t> sendErrors{0};
377 std::atomic<uint64_t> reuseds{0};
378 std::atomic<uint64_t> queries{0};
379 } prev;
380 string name;
381 double queryLoad{0.0};
382 double dropRate{0.0};
383 double latencyUsec{0.0};
384 int order{1};
385 int weight{1};
386 int tcpRecvTimeout{30};
387 int tcpSendTimeout{30};
388 unsigned int sourceItf{0};
389 uint16_t retries{5};
390 uint8_t currentCheckFailures{0};
391 uint8_t maxCheckFailures{1};
392 StopWatch sw;
393 set<string> pools;
394 enum class Availability { Up, Down, Auto} availability{Availability::Auto};
395 bool mustResolve{false};
396 bool upStatus{false};
397 bool useECS{false};
398 bool setCD{false};
399 bool isUp() const
400 {
401 if(availability == Availability::Down)
402 return false;
403 if(availability == Availability::Up)
404 return true;
405 return upStatus;
406 }
407 void setUp() { availability = Availability::Up; }
408 void setDown() { availability = Availability::Down; }
409 void setAuto() { availability = Availability::Auto; }
410 string getName() const {
411 if (name.empty()) {
412 return remote.toStringWithPort();
413 }
414 return name;
415 }
416 string getNameWithAddr() const {
417 if (name.empty()) {
418 return remote.toStringWithPort();
419 }
420 return name + " (" + remote.toStringWithPort()+ ")";
421 }
422
423 };
424 using servers_t =vector<std::shared_ptr<DownstreamState>>;
425
426 struct DNSQuestion
427 {
428 DNSQuestion(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, struct dnsheader* header, size_t bufferSize, uint16_t queryLen, bool isTcp): qname(name), qtype(type), qclass(class_), local(lc), remote(rem), dh(header), size(bufferSize), len(queryLen), tcp(isTcp) { }
429
430 #ifdef HAVE_PROTOBUF
431 boost::uuids::uuid uniqueId;
432 #endif
433 const DNSName* qname;
434 const uint16_t qtype;
435 const uint16_t qclass;
436 const ComboAddress* local;
437 const ComboAddress* remote;
438 struct dnsheader* dh;
439 size_t size;
440 uint16_t len;
441 const bool tcp;
442 bool skipCache{false};
443 };
444
445 struct DNSResponse : DNSQuestion
446 {
447 DNSResponse(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, struct dnsheader* header, size_t bufferSize, uint16_t queryLen, bool isTcp, const struct timespec* queryTime_): DNSQuestion(name, type, class_, lc, rem, header, bufferSize, queryLen, isTcp), queryTime(queryTime_) { }
448
449 const struct timespec* queryTime;
450 };
451
452 typedef std::function<bool(const DNSQuestion*)> blockfilter_t;
453 template <class T> using NumberedVector = std::vector<std::pair<unsigned int, T> >;
454
455 void* responderThread(std::shared_ptr<DownstreamState> state);
456 extern std::mutex g_luamutex;
457 extern LuaContext g_lua;
458 extern std::string g_outputBuffer; // locking for this is ok, as locked by g_luamutex
459
460 class DNSRule
461 {
462 public:
463 virtual bool matches(const DNSQuestion* dq) const =0;
464 virtual string toString() const = 0;
465 mutable std::atomic<uint64_t> d_matches{0};
466 };
467
468 /* so what could you do:
469 drop,
470 fake up nxdomain,
471 provide actual answer,
472 allow & and stop processing,
473 continue processing,
474 modify header: (servfail|refused|notimp), set TC=1,
475 send to pool */
476
477 class DNSAction
478 {
479 public:
480 enum class Action { Drop, Nxdomain, Spoof, Allow, HeaderModify, Pool, Delay, None};
481 virtual Action operator()(DNSQuestion*, string* ruleresult) const =0;
482 virtual string toString() const = 0;
483 virtual std::unordered_map<string, double> getStats() const
484 {
485 return {{}};
486 }
487 };
488
489 class DNSResponseAction
490 {
491 public:
492 enum class Action { Allow, Delay, Drop, HeaderModify, None };
493 virtual Action operator()(DNSResponse*, string* ruleresult) const =0;
494 virtual string toString() const = 0;
495 };
496
497 using NumberedServerVector = NumberedVector<shared_ptr<DownstreamState>>;
498 typedef std::function<shared_ptr<DownstreamState>(const NumberedServerVector& servers, const DNSQuestion*)> policyfunc_t;
499
500 struct ServerPolicy
501 {
502 string name;
503 policyfunc_t policy;
504 };
505
506 struct ServerPool
507 {
508 const std::shared_ptr<DNSDistPacketCache> getCache() const { return packetCache; };
509
510 NumberedVector<shared_ptr<DownstreamState>> servers;
511 std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
512 };
513 using pools_t=map<std::string,std::shared_ptr<ServerPool>>;
514 void addServerToPool(pools_t& pools, const string& poolName, std::shared_ptr<DownstreamState> server);
515 void removeServerFromPool(pools_t& pools, const string& poolName, std::shared_ptr<DownstreamState> server);
516
517 struct CarbonConfig
518 {
519 ComboAddress server;
520 std::string ourname;
521 unsigned int interval;
522 };
523
524 enum ednsHeaderFlags {
525 EDNS_HEADER_FLAG_NONE = 0,
526 EDNS_HEADER_FLAG_DO = 32768
527 };
528
529 /* Quest in life: serve as a rapid block list. If you add a DNSName to a root SuffixMatchNode,
530 anything part of that domain will return 'true' in check */
531 template<typename T>
532 struct SuffixMatchTree
533 {
534 SuffixMatchTree(const std::string& name_="", bool endNode_=false) : name(name_), endNode(endNode_)
535 {}
536
537 SuffixMatchTree(const SuffixMatchTree& rhs)
538 {
539 name = rhs.name;
540 d_human = rhs.d_human;
541 children = rhs.children;
542 endNode = rhs.endNode;
543 d_value = rhs.d_value;
544 }
545 std::string name;
546 std::string d_human;
547 mutable std::set<SuffixMatchTree> children;
548 mutable bool endNode;
549 mutable T d_value;
550 bool operator<(const SuffixMatchTree& rhs) const
551 {
552 return strcasecmp(name.c_str(), rhs.name.c_str()) < 0;
553 }
554 typedef SuffixMatchTree value_type;
555
556 template<typename V>
557 void visit(const V& v) const {
558 for(const auto& c : children)
559 c.visit(v);
560 if(endNode)
561 v(*this);
562 }
563
564 void add(const DNSName& name, const T& t)
565 {
566 add(name.getRawLabels(), t);
567 }
568
569 void add(std::vector<std::string> labels, const T& value) const
570 {
571 if(labels.empty()) { // this allows insertion of the root
572 endNode=true;
573 d_value=value;
574 }
575 else if(labels.size()==1) {
576 SuffixMatchTree newChild(*labels.begin(), true);
577 newChild.d_value=value;
578 children.insert(newChild);
579 }
580 else {
581 SuffixMatchTree newnode(*labels.rbegin(), false);
582 auto res=children.insert(newnode);
583 if(!res.second) {
584 children.erase(newnode);
585 res=children.insert(newnode);
586 }
587 labels.pop_back();
588 res.first->add(labels, value);
589 }
590 }
591
592 T* lookup(const DNSName& name) const
593 {
594 if(children.empty()) { // speed up empty set
595 if(endNode)
596 return &d_value;
597 return 0;
598 }
599 return lookup(name.getRawLabels());
600 }
601
602 T* lookup(std::vector<std::string> labels) const
603 {
604 if(labels.empty()) { // optimization
605 if(endNode)
606 return &d_value;
607 return 0;
608 }
609
610 SuffixMatchTree smn(*labels.rbegin());
611 auto child = children.find(smn);
612 if(child == children.end()) {
613 if(endNode)
614 return &d_value;
615 return 0;
616 }
617 labels.pop_back();
618 return child->lookup(labels);
619 }
620
621 };
622
623 extern GlobalStateHolder<SuffixMatchTree<DynBlock>> g_dynblockSMT;
624
625 extern GlobalStateHolder<vector<CarbonConfig> > g_carbon;
626 extern GlobalStateHolder<ServerPolicy> g_policy;
627 extern GlobalStateHolder<servers_t> g_dstates;
628 extern GlobalStateHolder<pools_t> g_pools;
629 extern GlobalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSAction> > > > g_rulactions;
630 extern GlobalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > > g_resprulactions;
631 extern GlobalStateHolder<NetmaskGroup> g_ACL;
632
633 extern ComboAddress g_serverControl; // not changed during runtime
634
635 extern std::vector<std::tuple<ComboAddress, bool, bool, int>> g_locals; // not changed at runtime (we hope XXX)
636 extern vector<ClientState*> g_frontends;
637 extern std::string g_key; // in theory needs locking
638 extern bool g_truncateTC;
639 extern bool g_fixupCase;
640 extern int g_tcpRecvTimeout;
641 extern int g_tcpSendTimeout;
642 extern uint16_t g_maxOutstanding;
643 extern std::atomic<bool> g_configurationDone;
644 extern uint64_t g_maxTCPClientThreads;
645 extern uint64_t g_maxTCPQueuedConnections;
646 extern std::atomic<uint16_t> g_cacheCleaningDelay;
647 extern uint16_t g_ECSSourcePrefixV4;
648 extern uint16_t g_ECSSourcePrefixV6;
649 extern bool g_ECSOverride;
650 extern bool g_verboseHealthChecks;
651 extern uint32_t g_staleCacheEntriesTTL;
652
653 struct ConsoleKeyword {
654 std::string name;
655 bool function;
656 std::string parameters;
657 std::string description;
658 std::string toString() const
659 {
660 std::string res(name);
661 if (function) {
662 res += "(" + parameters + ")";
663 }
664 res += ": ";
665 res += description;
666 return res;
667 }
668 };
669 extern const std::vector<ConsoleKeyword> g_consoleKeywords;
670
671 #ifdef HAVE_EBPF
672 extern shared_ptr<BPFFilter> g_defaultBPFFilter;
673 extern std::vector<std::shared_ptr<DynBPFFilter> > g_dynBPFFilters;
674 #endif /* HAVE_EBPF */
675
676 struct dnsheader;
677
678 void controlThread(int fd, ComboAddress local);
679 vector<std::function<void(void)>> setupLua(bool client, const std::string& config);
680 std::shared_ptr<ServerPool> getPool(const pools_t& pools, const std::string& poolName);
681 std::shared_ptr<ServerPool> createPoolIfNotExists(pools_t& pools, const string& poolName);
682 const NumberedServerVector& getDownstreamCandidates(const pools_t& pools, const std::string& poolName);
683
684 std::shared_ptr<DownstreamState> firstAvailable(const NumberedServerVector& servers, const DNSQuestion* dq);
685
686 std::shared_ptr<DownstreamState> leastOutstanding(const NumberedServerVector& servers, const DNSQuestion* dq);
687 std::shared_ptr<DownstreamState> wrandom(const NumberedServerVector& servers, const DNSQuestion* dq);
688 std::shared_ptr<DownstreamState> whashed(const NumberedServerVector& servers, const DNSQuestion* dq);
689 std::shared_ptr<DownstreamState> roundrobin(const NumberedServerVector& servers, const DNSQuestion* dq);
690 int getEDNSZ(const char* packet, unsigned int len);
691 void spoofResponseFromString(DNSQuestion& dq, const string& spoofContent);
692 uint16_t getEDNSOptionCode(const char * packet, size_t len);
693 void dnsdistWebserverThread(int sock, const ComboAddress& local, const string& password, const string& apiKey, const boost::optional<std::map<std::string, std::string> >&);
694 bool getMsgLen32(int fd, uint32_t* len);
695 bool putMsgLen32(int fd, uint32_t len);
696 void* tcpAcceptorThread(void* p);
697
698 void moreLua(bool client);
699 void doClient(ComboAddress server, const std::string& command);
700 void doConsole();
701 void controlClientThread(int fd, ComboAddress client);
702 extern "C" {
703 char** my_completion( const char * text , int start, int end);
704 }
705 void setLuaNoSideEffect(); // if nothing has been declared, set that there are no side effects
706 void setLuaSideEffect(); // set to report a side effect, cancelling all _no_ side effect calls
707 bool getLuaNoSideEffect(); // set if there were only explicit declarations of _no_ side effect
708 void resetLuaSideEffect(); // reset to indeterminate state
709
710 bool responseContentMatches(const char* response, const uint16_t responseLen, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& remote);
711 bool processQuery(LocalStateHolder<NetmaskTree<DynBlock> >& localDynBlockNMG,
712 LocalStateHolder<SuffixMatchTree<DynBlock> >& localDynBlockSMT, LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSAction> > > >& localRulactions, blockfilter_t blockFilter, DNSQuestion& dq, string& poolname, int* delayMsec, const struct timespec& now);
713 bool processResponse(LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > >& localRespRulactions, DNSResponse& dr, int* delayMsec);
714 bool fixUpResponse(char** response, uint16_t* responseLen, size_t* responseSize, const DNSName& qname, uint16_t origFlags, bool ednsAdded, bool ecsAdded, std::vector<uint8_t>& rewrittenResponse, uint16_t addRoom);
715 void restoreFlags(struct dnsheader* dh, uint16_t origFlags);
716
717 #ifdef HAVE_DNSCRYPT
718 extern std::vector<std::tuple<ComboAddress,DnsCryptContext,bool,int>> g_dnsCryptLocals;
719
720 int handleDnsCryptQuery(DnsCryptContext* ctx, char* packet, uint16_t len, std::shared_ptr<DnsCryptQuery>& query, uint16_t* decryptedQueryLen, bool tcp, std::vector<uint8_t>& reponse);
721 bool encryptResponse(char* response, uint16_t* responseLen, size_t responseSize, bool tcp, std::shared_ptr<DnsCryptQuery> dnsCryptQuery);
722 #endif