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