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