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