]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnsdist.hh
dnsdist: Don't reuse Proxy Protocol-enabled TCP connections to backends
[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"
cbf4e13a 25
df111b53 26#include <atomic>
df111b53 27#include <mutex>
cbf4e13a 28#include <string>
df111b53 29#include <thread>
cbf4e13a 30#include <time.h>
bffca8b9 31#include <unistd.h>
cbf4e13a
RG
32#include <unordered_map>
33
cbf4e13a
RG
34#include <boost/variant.hpp>
35
f12666f2 36#include "capabilities.hh"
9f6a31ff 37#include "circular_buffer.hh"
11e1e08b 38#include "dnscrypt.hh"
886e2cf2 39#include "dnsdist-cache.hh"
87b515ed 40#include "dnsdist-dynbpf.hh"
b6e26895 41#include "dnsdist-lbpolicies.hh"
cbf4e13a 42#include "dnsname.hh"
fbf14b03 43#include "doh.hh"
cbf4e13a
RG
44#include "ednsoptions.hh"
45#include "gettime.hh"
46#include "iputils.hh"
47#include "misc.hh"
48#include "mplexer.hh"
49#include "sholder.hh"
a227f47d 50#include "tcpiohandler.hh"
d61aa945 51#include "uuid-utils.hh"
bde73d5b 52#include "proxy-protocol.hh"
d8c19b98 53
9b73b71c 54void carbonDumpThread();
61d1b966 55uint64_t uptimeOfProcess(const std::string& str);
bd1c631b 56
7b925432
RG
57extern uint16_t g_ECSSourcePrefixV4;
58extern uint16_t g_ECSSourcePrefixV6;
59extern bool g_ECSOverride;
26a6373d 60
15fac047
CH
61typedef std::unordered_map<string, string> QTag;
62
7b925432
RG
63struct DNSQuestion
64{
e7c732b8 65 DNSQuestion(const DNSName* name, uint16_t type, uint16_t class_, unsigned int consumed_, const ComboAddress* lc, const ComboAddress* rem, struct dnsheader* header, size_t bufferSize, uint16_t queryLen, bool isTcp, const struct timespec* queryTime_):
4ab01344
RG
66 qname(name), local(lc), remote(rem), dh(header), queryTime(queryTime_), size(bufferSize), consumed(consumed_), tempFailureTTL(boost::none), qtype(type), qclass(class_), len(queryLen), ecsPrefixLength(rem->sin4.sin_family == AF_INET ? g_ECSSourcePrefixV4 : g_ECSSourcePrefixV6), tcp(isTcp), ecsOverride(g_ECSOverride) {
67 const uint16_t* flags = getFlagsFromDNSHeader(dh);
68 origFlags = *flags;
69 }
dd1a3034
RG
70 DNSQuestion(const DNSQuestion&) = delete;
71 DNSQuestion& operator=(const DNSQuestion&) = delete;
72 DNSQuestion(DNSQuestion&&) = default;
7b925432 73
0ed8f0fa
RG
74 std::string getTrailingData() const;
75 bool setTrailingData(const std::string&);
76
7b925432 77#ifdef HAVE_PROTOBUF
ec48a28d 78 boost::optional<boost::uuids::uuid> uniqueId;
7b925432 79#endif
bd14f087 80 Netmask ecs;
4ab01344 81 boost::optional<Netmask> subnet;
046bac5c 82 std::string sni; /* Server Name Indication, if any (DoT or DoH) */
2a28db86 83 std::string poolname;
4ab01344
RG
84 const DNSName* qname{nullptr};
85 const ComboAddress* local{nullptr};
86 const ComboAddress* remote{nullptr};
15fac047 87 std::shared_ptr<QTag> qTag{nullptr};
bde73d5b 88 std::unique_ptr<std::vector<ProxyProtocolValue>> proxyProtocolValues{nullptr};
cbf4e13a 89 std::shared_ptr<std::map<uint16_t, EDNSOptionView> > ednsOptions;
4ab01344
RG
90 std::shared_ptr<DNSCryptQuery> dnsCryptQuery{nullptr};
91 std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
92 struct dnsheader* dh{nullptr};
93 const struct timespec* queryTime{nullptr};
fbf14b03 94 struct DOHUnit* du{nullptr};
7b925432 95 size_t size;
e7c732b8 96 unsigned int consumed{0};
4ab01344
RG
97 int delayMsec{0};
98 boost::optional<uint32_t> tempFailureTTL;
99 uint32_t cacheKeyNoECS;
100 uint32_t cacheKey;
101 const uint16_t qtype;
102 const uint16_t qclass;
7b925432
RG
103 uint16_t len;
104 uint16_t ecsPrefixLength;
4ab01344 105 uint16_t origFlags;
1ecbd15e 106 uint8_t ednsRCode{0};
7b925432
RG
107 const bool tcp;
108 bool skipCache{false};
109 bool ecsOverride;
5b8255ba 110 bool useECS{true};
5cc8371b 111 bool addXPF{true};
bd14f087 112 bool ecsSet{false};
4ab01344
RG
113 bool ecsAdded{false};
114 bool ednsAdded{false};
115 bool useZeroScope{false};
116 bool dnssecOK{false};
7b925432
RG
117};
118
119struct DNSResponse : DNSQuestion
120{
dd026b9c
RG
121 DNSResponse(const DNSName* name, uint16_t type, uint16_t class_, unsigned int consumed_, const ComboAddress* lc, const ComboAddress* rem, struct dnsheader* header, size_t bufferSize, uint16_t responseLen, bool isTcp, const struct timespec* queryTime_):
122 DNSQuestion(name, type, class_, consumed_, lc, rem, header, bufferSize, responseLen, isTcp, queryTime_) { }
dd1a3034
RG
123 DNSResponse(const DNSResponse&) = delete;
124 DNSResponse& operator=(const DNSResponse&) = delete;
125 DNSResponse(DNSResponse&&) = default;
7b925432
RG
126};
127
5c30ec69
LM
128/* so what could you do:
129 drop,
130 fake up nxdomain,
131 provide actual answer,
132 allow & and stop processing,
133 continue processing,
7b925432
RG
134 modify header: (servfail|refused|notimp), set TC=1,
135 send to pool */
136
137class DNSAction
138{
139public:
202c4ab9 140 enum class Action { Drop, Nxdomain, Refused, Spoof, Allow, HeaderModify, Pool, Delay, Truncate, ServFail, None, NoOp, NoRecurse, SpoofRaw };
b718792f
RG
141 static std::string typeToString(const Action& action)
142 {
143 switch(action) {
144 case Action::Drop:
145 return "Drop";
146 case Action::Nxdomain:
147 return "Send NXDomain";
148 case Action::Refused:
149 return "Send Refused";
150 case Action::Spoof:
151 return "Spoof an answer";
202c4ab9
RG
152 case Action::SpoofRaw:
153 return "Spoof an answer from raw bytes";
b718792f
RG
154 case Action::Allow:
155 return "Allow";
156 case Action::HeaderModify:
157 return "Modify the header";
158 case Action::Pool:
159 return "Route to a pool";
160 case Action::Delay:
161 return "Delay";
162 case Action::Truncate:
163 return "Truncate over UDP";
164 case Action::ServFail:
165 return "Send ServFail";
166 case Action::None:
477c86a0 167 case Action::NoOp:
b718792f 168 return "Do nothing";
3d60b39a 169 case Action::NoRecurse:
170 return "Set rd=0";
b718792f
RG
171 }
172
173 return "Unknown";
174 }
175
7b925432 176 virtual Action operator()(DNSQuestion*, string* ruleresult) const =0;
205f2081
RG
177 virtual ~DNSAction()
178 {
179 }
7b925432 180 virtual string toString() const = 0;
b8019cf7 181 virtual std::map<string, double> getStats() const
7b925432
RG
182 {
183 return {{}};
184 }
185};
186
187class DNSResponseAction
188{
189public:
5f23eb98 190 enum class Action { Allow, Delay, Drop, HeaderModify, ServFail, None };
7b925432 191 virtual Action operator()(DNSResponse*, string* ruleresult) const =0;
205f2081
RG
192 virtual ~DNSResponseAction()
193 {
194 }
7b925432
RG
195 virtual string toString() const = 0;
196};
197
78ffa782 198struct DynBlock
199{
1d3ba133 200 DynBlock(): action(DNSAction::Action::None), warning(false)
5708a729
RG
201 {
202 }
203
1d3ba133 204 DynBlock(const std::string& reason_, const struct timespec& until_, const DNSName& domain_, DNSAction::Action action_): reason(reason_), until(until_), domain(domain_), action(action_), warning(false)
5708a729
RG
205 {
206 }
207
1d3ba133 208 DynBlock(const DynBlock& rhs): reason(rhs.reason), until(rhs.until), domain(rhs.domain), action(rhs.action), warning(rhs.warning)
5708a729
RG
209 {
210 blocks.store(rhs.blocks);
211 }
212
78ffa782 213 DynBlock& operator=(const DynBlock& rhs)
214 {
215 reason=rhs.reason;
216 until=rhs.until;
71c94675 217 domain=rhs.domain;
7b925432 218 action=rhs.action;
78ffa782 219 blocks.store(rhs.blocks);
1d3ba133 220 warning=rhs.warning;
78ffa782 221 return *this;
222 }
71c94675 223
78ffa782 224 string reason;
225 struct timespec until;
71c94675 226 DNSName domain;
7b925432 227 DNSAction::Action action;
78ffa782 228 mutable std::atomic<unsigned int> blocks;
1d3ba133 229 bool warning;
78ffa782 230};
231
232extern GlobalStateHolder<NetmaskTree<DynBlock>> g_dynblockNMG;
f758857a 233
234extern vector<pair<struct timeval, std::string> > g_confDelta;
235
eb0335ff
MC
236extern uint64_t getLatencyCount(const std::string&);
237
e48090d1 238struct DNSDistStats
239{
6ad8b29a 240 using stat_t=std::atomic<uint64_t>; // aww yiss ;-)
e48090d1 241 stat_t responses{0};
242 stat_t servfailResponses{0};
243 stat_t queries{0};
61d10a4d
MH
244 stat_t frontendNXDomain{0};
245 stat_t frontendServFail{0};
246 stat_t frontendNoError{0};
e73ec7d3 247 stat_t nonCompliantQueries{0};
d08b1cdf 248 stat_t nonCompliantResponses{0};
643a182a 249 stat_t rdQueries{0};
2efd427d 250 stat_t emptyQueries{0};
e48090d1 251 stat_t aclDrops{0};
bd1c631b 252 stat_t dynBlocked{0};
e48090d1 253 stat_t ruleDrop{0};
254 stat_t ruleNXDomain{0};
dd46e5e3 255 stat_t ruleRefused{0};
5f23eb98 256 stat_t ruleServFail{0};
e48090d1 257 stat_t selfAnswered{0};
258 stat_t downstreamTimeouts{0};
259 stat_t downstreamSendErrors{0};
6ad8b29a 260 stat_t truncFail{0};
b8bc7e61 261 stat_t noPolicy{0};
886e2cf2
RG
262 stat_t cacheHits{0};
263 stat_t cacheMisses{0};
eb0335ff 264 stat_t latency0_1{0}, latency1_10{0}, latency10_50{0}, latency50_100{0}, latency100_1000{0}, latencySlow{0}, latencySum{0};
f29758cc 265 stat_t securityStatus{0};
5c30ec69 266
e16fd59c 267 double latencyAvg100{0}, latencyAvg1000{0}, latencyAvg10000{0}, latencyAvg1000000{0};
a1a787dc 268 typedef std::function<uint64_t(const std::string&)> statfunction_t;
72f58a53 269 typedef boost::variant<stat_t*, double*, statfunction_t> entry_t;
e16fd59c 270 std::vector<std::pair<std::string, entry_t>> entries{
dd46e5e3
RG
271 {"responses", &responses},
272 {"servfail-responses", &servfailResponses},
273 {"queries", &queries},
61d10a4d
MH
274 {"frontend-nxdomain", &frontendNXDomain},
275 {"frontend-servfail", &frontendServFail},
276 {"frontend-noerror", &frontendNoError},
dd46e5e3 277 {"acl-drops", &aclDrops},
dd46e5e3
RG
278 {"rule-drop", &ruleDrop},
279 {"rule-nxdomain", &ruleNXDomain},
280 {"rule-refused", &ruleRefused},
5f23eb98 281 {"rule-servfail", &ruleServFail},
dd46e5e3
RG
282 {"self-answered", &selfAnswered},
283 {"downstream-timeouts", &downstreamTimeouts},
5c30ec69 284 {"downstream-send-errors", &downstreamSendErrors},
dd46e5e3
RG
285 {"trunc-failures", &truncFail},
286 {"no-policy", &noPolicy},
287 {"latency0-1", &latency0_1},
288 {"latency1-10", &latency1_10},
289 {"latency10-50", &latency10_50},
290 {"latency50-100", &latency50_100},
291 {"latency100-1000", &latency100_1000},
292 {"latency-slow", &latencySlow},
293 {"latency-avg100", &latencyAvg100},
294 {"latency-avg1000", &latencyAvg1000},
295 {"latency-avg10000", &latencyAvg10000},
296 {"latency-avg1000000", &latencyAvg1000000},
61d1b966 297 {"uptime", uptimeOfProcess},
a9b6db56 298 {"real-memory-usage", getRealMemoryUsage},
330dcb5c 299 {"special-memory-usage", getSpecialMemoryUsage},
0d394f35
RG
300 {"udp-in-errors", boost::bind(udpErrorStats, "udp-in-errors")},
301 {"udp-noport-errors", boost::bind(udpErrorStats, "udp-noport-errors")},
302 {"udp-recvbuf-errors", boost::bind(udpErrorStats, "udp-recvbuf-errors")},
303 {"udp-sndbuf-errors", boost::bind(udpErrorStats, "udp-sndbuf-errors")},
a2aa00ed 304 {"noncompliant-queries", &nonCompliantQueries},
d08b1cdf 305 {"noncompliant-responses", &nonCompliantResponses},
643a182a 306 {"rdqueries", &rdQueries},
2efd427d 307 {"empty-queries", &emptyQueries},
886e2cf2
RG
308 {"cache-hits", &cacheHits},
309 {"cache-misses", &cacheMisses},
0d394f35
RG
310 {"cpu-iowait", getCPUIOWait},
311 {"cpu-steal", getCPUSteal},
4f99f3d3 312 {"cpu-sys-msec", getCPUTimeSystem},
0d394f35 313 {"cpu-user-msec", getCPUTimeUser},
dd46e5e3 314 {"fd-usage", getOpenFileDescriptors},
5c30ec69 315 {"dyn-blocked", &dynBlocked},
f29758cc 316 {"dyn-block-nmg-size", [](const std::string&) { return g_dynblockNMG.getLocal()->size(); }},
eb0335ff
MC
317 {"security-status", &securityStatus},
318 // Latency histogram
319 {"latency-sum", &latencySum},
320 {"latency-count", getLatencyCount},
42fae326 321 };
e48090d1 322};
323
324extern struct DNSDistStats g_stats;
f653b8df 325void doLatencyStats(double udiff);
e48090d1 326
638184e9 327
df111b53 328struct StopWatch
329{
58307a85
RG
330 StopWatch(bool realTime=false): d_needRealTime(realTime)
331 {
332 }
df111b53 333 struct timespec d_start{0,0};
58307a85
RG
334 bool d_needRealTime{false};
335
5c30ec69 336 void start() {
58307a85 337 if(gettime(&d_start, d_needRealTime) < 0)
df111b53 338 unixDie("Getting timestamp");
5c30ec69 339
df111b53 340 }
cf48b0ce
RG
341
342 void set(const struct timespec& from) {
343 d_start = from;
344 }
5c30ec69 345
df111b53 346 double udiff() const {
347 struct timespec now;
58307a85 348 if(gettime(&now, d_needRealTime) < 0)
df111b53 349 unixDie("Getting timestamp");
5c30ec69 350
df111b53 351 return 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0;
352 }
353
354 double udiffAndSet() {
355 struct timespec now;
58307a85 356 if(gettime(&now, d_needRealTime) < 0)
df111b53 357 unixDie("Getting timestamp");
5c30ec69 358
df111b53 359 auto ret= 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0;
360 d_start = now;
361 return ret;
362 }
363
364};
365
67ce0bdd 366class BasicQPSLimiter
df111b53 367{
368public:
67ce0bdd 369 BasicQPSLimiter()
df111b53 370 {
371 }
372
2d29e6b7 373 BasicQPSLimiter(unsigned int burst): d_tokens(burst)
67ce0bdd
RG
374 {
375 d_prev.start();
376 }
377
378 bool check(unsigned int rate, unsigned int burst) const // this is not quite fair
379 {
380 auto delta = d_prev.udiffAndSet();
381
1a1787b6 382 if(delta > 0.0) // time, frequently, does go backwards..
383 d_tokens += 1.0 * rate * (delta/1000000.0);
67ce0bdd
RG
384
385 if(d_tokens > burst) {
386 d_tokens = burst;
387 }
388
389 bool ret=false;
390 if(d_tokens >= 1.0) { // we need this because burst=1 is weird otherwise
391 ret=true;
392 --d_tokens;
393 }
394
395 return ret;
396 }
397
398 bool seenSince(const struct timespec& cutOff) const
399 {
400 return cutOff < d_prev.d_start;
401 }
402
403protected:
404 mutable StopWatch d_prev;
405 mutable double d_tokens;
406};
407
408class QPSLimiter : public BasicQPSLimiter
409{
410public:
411 QPSLimiter(): BasicQPSLimiter()
412 {
413 }
414
2d29e6b7 415 QPSLimiter(unsigned int rate, unsigned int burst): BasicQPSLimiter(burst), d_rate(rate), d_burst(burst), d_passthrough(false)
df111b53 416 {
df111b53 417 d_prev.start();
418 }
419
420 unsigned int getRate() const
421 {
67ce0bdd 422 return d_passthrough ? 0 : d_rate;
df111b53 423 }
424
425 int getPassed() const
426 {
427 return d_passed;
428 }
67ce0bdd 429
df111b53 430 int getBlocked() const
431 {
432 return d_blocked;
433 }
434
ecbe9133 435 bool check() const // this is not quite fair
df111b53 436 {
67ce0bdd 437 if (d_passthrough) {
df111b53 438 return true;
67ce0bdd 439 }
df111b53 440
67ce0bdd
RG
441 bool ret = BasicQPSLimiter::check(d_rate, d_burst);
442 if (ret) {
df111b53 443 d_passed++;
444 }
67ce0bdd 445 else {
df111b53 446 d_blocked++;
67ce0bdd 447 }
df111b53 448
5c30ec69 449 return ret;
df111b53 450 }
451private:
ecbe9133 452 mutable unsigned int d_passed{0};
453 mutable unsigned int d_blocked{0};
67ce0bdd
RG
454 unsigned int d_rate;
455 unsigned int d_burst;
456 bool d_passthrough{true};
df111b53 457};
458
b5b93e0b
RG
459struct ClientState;
460
df111b53 461struct IDState
462{
a9489723 463 IDState(): sentTime(true), delayMsec(0), tempFailureTTL(boost::none) { origDest.sin4.sin_family = 0;}
71b86bd8 464 IDState(const IDState& orig): origRemote(orig.origRemote), origDest(orig.origDest), age(orig.age)
df111b53 465 {
a9489723
RG
466 usageIndicator.store(orig.usageIndicator.load());
467 origFD = orig.origFD;
df111b53 468 origID = orig.origID;
7b3865cd 469 delayMsec = orig.delayMsec;
acb8f5d5 470 tempFailureTTL = orig.tempFailureTTL;
df111b53 471 }
472
311f19d5 473 static const int64_t unusedIndicator = -1;
2bf26975 474
311f19d5
RG
475 static bool isInUse(int64_t usageIndicator)
476 {
477 return usageIndicator != unusedIndicator;
478 }
479
480 bool isInUse() const
481 {
482 return usageIndicator != unusedIndicator;
483 }
484
485 /* return true if the value has been successfully replaced meaning that
486 no-one updated the usage indicator in the meantime */
487 bool tryMarkUnused(int64_t expectedUsageIndicator)
488 {
489 return usageIndicator.compare_exchange_strong(expectedUsageIndicator, unusedIndicator);
490 }
491
492 /* mark as unused no matter what, return true if the state was in use before */
493 bool markAsUsed()
494 {
495 auto currentGeneration = generation++;
496 return markAsUsed(currentGeneration);
497 }
498
499 /* mark as unused no matter what, return true if the state was in use before */
500 bool markAsUsed(int64_t currentGeneration)
501 {
502 int64_t oldUsage = usageIndicator.exchange(currentGeneration);
503 return oldUsage != unusedIndicator;
504 }
505
a9489723 506 /* We use this value to detect whether this state is in use.
9bd1a882
RG
507 For performance reasons we don't want to use a lock here, but that means
508 we need to be very careful when modifying this value. Modifications happen
509 from:
510 - one of the UDP or DoH 'client' threads receiving a query, selecting a backend
511 then picking one of the states associated to this backend (via the idOffset).
a9489723 512 Most of the time this state should not be in use and usageIndicator is -1, but we
9bd1a882
RG
513 might not yet have received a response for the query previously associated to this
514 state, meaning that we will 'reuse' this state and erase the existing state.
515 If we ever receive a response for this state, it will be discarded. This is
516 mostly fine for UDP except that we still need to be careful in order to miss
517 the 'outstanding' counters, which should only be increased when we are picking
518 an empty state, and not when reusing ;
519 For DoH, though, we have dynamically allocated a DOHUnit object that needs to
520 be freed, as well as internal objects internals to libh2o.
521 - one of the UDP receiver threads receiving a response from a backend, picking
522 the corresponding state and sending the response to the client ;
523 - the 'healthcheck' thread scanning the states to actively discover timeouts,
524 mostly to keep some counters like the 'outstanding' one sane.
a9489723
RG
525 We previously based that logic on the origFD (FD on which the query was received,
526 and therefore from where the response should be sent) but this suffered from an
527 ABA problem since it was quite likely that a UDP 'client thread' would reset it to the
528 same value since we only have so much incoming sockets:
529 - 1/ 'client' thread gets a query and set origFD to its FD, say 5 ;
530 - 2/ 'receiver' thread gets a response, read the value of origFD to 5, check that the qname,
531 qtype and qclass match
532 - 3/ during that time the 'client' thread reuses the state, setting again origFD to 5 ;
533 - 4/ the 'receiver' thread uses compare_exchange_strong() to only replace the value if it's still
534 5, except it's not the same 5 anymore and it overrides a fresh state.
535 We now use a 32-bit unsigned counter instead, which is incremented every time the state is set,
536 wrapping around if necessary, and we set an atomic signed 64-bit value, so that we still have -1
537 when the state is unused and the value of our counter otherwise.
9bd1a882 538 */
311f19d5
RG
539 std::atomic<int64_t> usageIndicator{unusedIndicator}; // set to unusedIndicator to indicate this state is empty // 8
540 std::atomic<uint32_t> generation{0}; // increased every time a state is used, to be able to detect an ABA issue // 4
2bf26975 541 ComboAddress origRemote; // 28
549d63c9 542 ComboAddress origDest; // 28
2bf26975 543 StopWatch sentTime; // 16
544 DNSName qname; // 80
43234e76 545 std::shared_ptr<DNSCryptQuery> dnsCryptQuery{nullptr};
d8c19b98 546#ifdef HAVE_PROTOBUF
ec48a28d 547 boost::optional<boost::uuids::uuid> uniqueId;
11e1e08b 548#endif
78e3ac9e 549 boost::optional<Netmask> subnet{boost::none};
886e2cf2 550 std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
a76b0d63 551 std::shared_ptr<QTag> qTag{nullptr};
b5b93e0b 552 const ClientState* cs{nullptr};
fbf14b03 553 DOHUnit* du{nullptr};
9837850d 554 uint32_t cacheKey; // 4
555 uint32_t cacheKeyNoECS; // 4
71b86bd8 556 uint16_t age; // 4
2bf26975 557 uint16_t qtype; // 2
886e2cf2 558 uint16_t qclass; // 2
2bf26975 559 uint16_t origID; // 2
aeb36780 560 uint16_t origFlags; // 2
a9489723 561 int origFD{-1};
7b3865cd 562 int delayMsec;
acb8f5d5 563 boost::optional<uint32_t> tempFailureTTL;
ca404e94 564 bool ednsAdded{false};
ff73f02b 565 bool ecsAdded{false};
886e2cf2 566 bool skipCache{false};
7cea4e39 567 bool destHarvested{false}; // if true, origDest holds the original dest addr, otherwise the listening addr
d7728daf 568 bool dnssecOK{false};
389d903a 569 bool useZeroScope;
df111b53 570};
571
786e4d8c 572typedef std::unordered_map<string, unsigned int> QueryCountRecords;
dd1a3034 573typedef std::function<std::tuple<bool, string>(const DNSQuestion* dq)> QueryCountFilter;
786e4d8c
RS
574struct QueryCount {
575 QueryCount()
576 {
43234e76 577 pthread_rwlock_init(&queryLock, nullptr);
786e4d8c 578 }
040793d4
OM
579 ~QueryCount()
580 {
581 pthread_rwlock_destroy(&queryLock);
582 }
786e4d8c
RS
583 QueryCountRecords records;
584 QueryCountFilter filter;
585 pthread_rwlock_t queryLock;
586 bool enabled{false};
587};
588
589extern QueryCount g_qcount;
590
8a5d5053 591struct ClientState
592{
8274967b 593 ClientState(const ComboAddress& local_, bool isTCP_, bool doReusePort, int fastOpenQueue, const std::string& itfName, const std::set<int>& cpus_): cpus(cpus_), local(local_), interface(itfName), fastOpenQueueSize(fastOpenQueue), tcp(isTCP_), reuseport(doReusePort)
6e9fd124
RG
594 {
595 }
596
f0e4dcba 597 std::set<int> cpus;
8a5d5053 598 ComboAddress local;
43234e76 599 std::shared_ptr<DNSCryptContext> dnscryptCtx{nullptr};
6e9fd124 600 std::shared_ptr<TLSFrontend> tlsFrontend{nullptr};
fbf14b03 601 std::shared_ptr<DOHFrontend> dohFrontend{nullptr};
6e9fd124 602 std::string interface;
963bef8d 603 std::atomic<uint64_t> queries{0};
7fc95193 604 mutable std::atomic<uint64_t> responses{0};
a6e9e107
RG
605 std::atomic<uint64_t> tcpDiedReadingQuery{0};
606 std::atomic<uint64_t> tcpDiedSendingResponse{0};
607 std::atomic<uint64_t> tcpGaveUp{0};
608 std::atomic<uint64_t> tcpClientTimeouts{0};
609 std::atomic<uint64_t> tcpDownstreamTimeouts{0};
cff9aa03 610 std::atomic<uint64_t> tcpCurrentConnections{0};
846b63bb
RG
611 std::atomic<uint64_t> tlsNewSessions{0}; // A new TLS session has been negotiated, no resumption
612 std::atomic<uint64_t> tlsResumptions{0}; // A TLS session has been resumed, either via session id or via a TLS ticket
b608e6c6
RG
613 std::atomic<uint64_t> tlsUnknownTicketKey{0}; // A TLS ticket has been presented but we don't have the associated key (might have expired)
614 std::atomic<uint64_t> tlsInactiveTicketKey{0}; // A TLS ticket has been successfully resumed but the key is no longer active, we should issue a new one
bb3954f0
RG
615 std::atomic<uint64_t> tls10queries{0}; // valid DNS queries received via TLSv1.0
616 std::atomic<uint64_t> tls11queries{0}; // valid DNS queries received via TLSv1.1
617 std::atomic<uint64_t> tls12queries{0}; // valid DNS queries received via TLSv1.2
618 std::atomic<uint64_t> tls13queries{0}; // valid DNS queries received via TLSv1.3
619 std::atomic<uint64_t> tlsUnknownqueries{0}; // valid DNS queries received via unknown TLS version
cff9aa03
RG
620 std::atomic<double> tcpAvgQueriesPerConnection{0.0};
621 /* in ms */
622 std::atomic<double> tcpAvgConnectionDuration{0.0};
a36ce055
RG
623 int udpFD{-1};
624 int tcpFD{-1};
6e9fd124 625 int fastOpenQueueSize{0};
b5b93e0b 626 bool muted{false};
6e9fd124
RG
627 bool tcp;
628 bool reuseport;
629 bool ready{false};
8429ad04
RG
630
631 int getSocket() const
632 {
633 return udpFD != -1 ? udpFD : tcpFD;
634 }
635
3a2ca389
RG
636 bool isUDP() const
637 {
638 return udpFD != -1;
639 }
640
641 bool isTCP() const
642 {
643 return udpFD == -1;
644 }
645
f34fdcc5
RG
646 bool hasTLS() const
647 {
648 return tlsFrontend != nullptr || dohFrontend != nullptr;
649 }
650
ba7ec340
RG
651 std::string getType() const
652 {
653 std::string result = udpFD != -1 ? "UDP" : "TCP";
654
fbf14b03
RG
655 if (dohFrontend) {
656 result += " (DNS over HTTPS)";
657 }
658 else if (tlsFrontend) {
ba7ec340
RG
659 result += " (DNS over TLS)";
660 }
661 else if (dnscryptCtx) {
662 result += " (DNSCrypt)";
663 }
664
665 return result;
666 }
667
8429ad04
RG
668#ifdef HAVE_EBPF
669 shared_ptr<BPFFilter> d_filter;
670
671 void detachFilter()
672 {
673 if (d_filter) {
674 d_filter->removeSocket(getSocket());
675 d_filter = nullptr;
676 }
677 }
678
679 void attachFilter(shared_ptr<BPFFilter> bpf)
680 {
681 detachFilter();
682
683 bpf->addSocket(getSocket());
684 d_filter = bpf;
685 }
686#endif /* HAVE_EBPF */
cff9aa03 687
dd026b9c 688 void updateTCPMetrics(size_t nbQueries, uint64_t durationMs)
cff9aa03 689 {
dd026b9c 690 tcpAvgQueriesPerConnection = (99.0 * tcpAvgQueriesPerConnection / 100.0) + (nbQueries / 100.0);
cff9aa03
RG
691 tcpAvgConnectionDuration = (99.0 * tcpAvgConnectionDuration / 100.0) + (durationMs / 100.0);
692 }
8a5d5053 693};
694
695class TCPClientCollection {
696 std::vector<int> d_tcpclientthreads;
ded1985a 697 std::atomic<uint64_t> d_numthreads{0};
a9bf3ec4 698 std::atomic<uint64_t> d_pos{0};
ded1985a 699 std::atomic<uint64_t> d_queued{0};
73402775 700 const uint64_t d_maxthreads{0};
ded1985a 701 std::mutex d_mutex;
edbda1ad 702 int d_singlePipe[2];
73402775 703 const bool d_useSinglePipe;
ded1985a 704public:
8a5d5053 705
b79e4996
RG
706 TCPClientCollection(size_t maxThreads, bool useSinglePipe=false): d_maxthreads(maxThreads), d_singlePipe{-1,-1}, d_useSinglePipe(useSinglePipe)
707
8a5d5053 708 {
a9bf3ec4 709 d_tcpclientthreads.reserve(maxThreads);
edbda1ad
RG
710
711 if (d_useSinglePipe) {
712 if (pipe(d_singlePipe) < 0) {
c52b8cb6
OM
713 int err = errno;
714 throw std::runtime_error("Error creating the TCP single communication pipe: " + stringerror(err));
edbda1ad 715 }
3b07fd1b
RG
716
717 if (!setNonBlocking(d_singlePipe[0])) {
718 int err = errno;
719 close(d_singlePipe[0]);
720 close(d_singlePipe[1]);
c52b8cb6 721 throw std::runtime_error("Error setting the TCP single communication pipe non-blocking: " + stringerror(err));
3b07fd1b
RG
722 }
723
edbda1ad
RG
724 if (!setNonBlocking(d_singlePipe[1])) {
725 int err = errno;
726 close(d_singlePipe[0]);
727 close(d_singlePipe[1]);
c52b8cb6 728 throw std::runtime_error("Error setting the TCP single communication pipe non-blocking: " + stringerror(err));
edbda1ad
RG
729 }
730 }
8a5d5053 731 }
a9bf3ec4 732 int getThread()
8a5d5053 733 {
6c1ca990 734 uint64_t pos = d_pos++;
8a5d5053 735 ++d_queued;
736 return d_tcpclientthreads[pos % d_numthreads];
737 }
ded1985a
RG
738 bool hasReachedMaxThreads() const
739 {
740 return d_numthreads >= d_maxthreads;
741 }
742 uint64_t getThreadsCount() const
743 {
744 return d_numthreads;
745 }
746 uint64_t getQueuedCount() const
747 {
748 return d_queued;
749 }
750 void decrementQueuedCount()
751 {
752 --d_queued;
753 }
8a5d5053 754 void addTCPClientThread();
755};
756
1f7646c2 757extern std::unique_ptr<TCPClientCollection> g_tcpclientthreads;
8a5d5053 758
df111b53 759struct DownstreamState
760{
1720247e 761 typedef std::function<std::tuple<DNSName, uint16_t, uint16_t>(const DNSName&, uint16_t, uint16_t, dnsheader*)> checkfunc_t;
98650fde 762
203b5348
RG
763 DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf, const std::string& sourceItfName, size_t numberOfSockets, bool connect);
764 DownstreamState(const ComboAddress& remote_): DownstreamState(remote_, ComboAddress(), 0, std::string(), 1, true) {}
6a62c0e3
RG
765 ~DownstreamState()
766 {
5bdbb83d 767 for (auto& fd : sockets) {
150105a2
RG
768 if (fd >= 0) {
769 close(fd);
770 fd = -1;
771 }
772 }
040793d4 773 pthread_rwlock_destroy(&d_lock);
6a62c0e3 774 }
1720247e 775 boost::uuids::uuid id;
50033a8e 776 std::vector<unsigned int> hashes;
d58e616a 777 mutable pthread_rwlock_t d_lock;
5bdbb83d 778 std::vector<int> sockets;
70b0d0e2 779 const std::string sourceItfName;
5bdbb83d 780 std::mutex socketsLock;
5d7e6765 781 std::mutex connectLock;
5bdbb83d 782 std::unique_ptr<FDMultiplexer> mplexer{nullptr};
df111b53 783 std::thread tid;
a2353842 784 const ComboAddress remote;
df111b53 785 QPSLimiter qps;
786 vector<IDState> idStates;
73402775 787 const ComboAddress sourceAddr;
98650fde 788 checkfunc_t checkFunction;
fbe2a2e0
RG
789 DNSName checkName{"a.root-servers.net."};
790 QType checkType{QType::A};
de9f7157 791 uint16_t checkClass{QClass::IN};
df111b53 792 std::atomic<uint64_t> idOffset{0};
793 std::atomic<uint64_t> sendErrors{0};
794 std::atomic<uint64_t> outstanding{0};
795 std::atomic<uint64_t> reuseds{0};
796 std::atomic<uint64_t> queries{0};
7fc95193 797 std::atomic<uint64_t> responses{0};
df111b53 798 struct {
799 std::atomic<uint64_t> sendErrors{0};
800 std::atomic<uint64_t> reuseds{0};
801 std::atomic<uint64_t> queries{0};
802 } prev;
a6e9e107
RG
803 std::atomic<uint64_t> tcpDiedSendingQuery{0};
804 std::atomic<uint64_t> tcpDiedReadingResponse{0};
805 std::atomic<uint64_t> tcpGaveUp{0};
806 std::atomic<uint64_t> tcpReadTimeouts{0};
807 std::atomic<uint64_t> tcpWriteTimeouts{0};
cff9aa03
RG
808 std::atomic<uint64_t> tcpCurrentConnections{0};
809 std::atomic<double> tcpAvgQueriesPerConnection{0.0};
810 /* in ms */
811 std::atomic<double> tcpAvgConnectionDuration{0.0};
5bdbb83d 812 size_t socketsOffset{0};
df111b53 813 double queryLoad{0.0};
814 double dropRate{0.0};
815 double latencyUsec{0.0};
816 int order{1};
817 int weight{1};
b40cffe7 818 int tcpConnectTimeout{5};
3f6d07a4
RG
819 int tcpRecvTimeout{30};
820 int tcpSendTimeout{30};
7c9bf18d 821 unsigned int checkInterval{1};
822 unsigned int lastCheck{0};
73402775 823 const unsigned int sourceItf{0};
3f6d07a4 824 uint16_t retries{5};
c85f69a8 825 uint16_t xpfRRCode{0};
b7e6f4a1 826 uint16_t checkTimeout{1000}; /* in milliseconds */
9e87dcb8 827 uint8_t currentCheckFailures{0};
853faf61 828 uint8_t consecutiveSuccessfulChecks{0};
9e87dcb8 829 uint8_t maxCheckFailures{1};
1b633bec 830 uint8_t minRiseSuccesses{1};
df111b53 831 StopWatch sw;
832 set<string> pools;
833 enum class Availability { Up, Down, Auto} availability{Availability::Auto};
fbe2a2e0 834 bool mustResolve{false};
df111b53 835 bool upStatus{false};
ca404e94 836 bool useECS{false};
bde73d5b 837 bool useProxyProtocol{false};
21830638 838 bool setCD{false};
49c33a6c 839 bool disableZeroScope{false};
7565f4e6 840 std::atomic<bool> connected{false};
5d7e6765 841 std::atomic_flag threadStarted;
284d460c 842 bool tcpFastOpen{false};
5602f131 843 bool ipBindAddrNoPort{true};
5d7e6765 844
df111b53 845 bool isUp() const
846 {
847 if(availability == Availability::Down)
848 return false;
849 if(availability == Availability::Up)
850 return true;
851 return upStatus;
852 }
853 void setUp() { availability = Availability::Up; }
854 void setDown() { availability = Availability::Down; }
855 void setAuto() { availability = Availability::Auto; }
508543b4 856 const string& getName() const {
18eeccc9
RG
857 return name;
858 }
508543b4 859 const string& getNameWithAddr() const {
be05aa91
RG
860 return nameWithAddr;
861 }
862 void setName(const std::string& newName)
863 {
864 name = newName;
77c369f8 865 nameWithAddr = newName.empty() ? remote.toStringWithPort() : (name + " (" + remote.toStringWithPort()+ ")");
a7940c06 866 }
be05aa91 867
9f4eb5cc
RG
868 string getStatus() const
869 {
870 string status;
871 if(availability == DownstreamState::Availability::Up)
872 status = "UP";
873 else if(availability == DownstreamState::Availability::Down)
874 status = "DOWN";
875 else
876 status = (upStatus ? "up" : "down");
877 return status;
878 }
5d7e6765 879 bool reconnect();
f2caf657
CHB
880 void hash();
881 void setId(const boost::uuids::uuid& newId);
882 void setWeight(int newWeight);
cff9aa03 883
dd026b9c 884 void updateTCPMetrics(size_t nbQueries, uint64_t durationMs)
cff9aa03 885 {
dd026b9c 886 tcpAvgQueriesPerConnection = (99.0 * tcpAvgQueriesPerConnection / 100.0) + (nbQueries / 100.0);
cff9aa03
RG
887 tcpAvgConnectionDuration = (99.0 * tcpAvgConnectionDuration / 100.0) + (durationMs / 100.0);
888 }
be05aa91
RG
889private:
890 std::string name;
891 std::string nameWithAddr;
df111b53 892};
893using servers_t =vector<std::shared_ptr<DownstreamState>>;
df111b53 894
9b73b71c 895void responderThread(std::shared_ptr<DownstreamState> state);
da4e7813 896extern std::mutex g_luamutex;
897extern LuaContext g_lua;
898extern std::string g_outputBuffer; // locking for this is ok, as locked by g_luamutex
899
0940e4eb 900class DNSRule
901{
902public:
205f2081
RG
903 virtual ~DNSRule ()
904 {
905 }
497a6e3a 906 virtual bool matches(const DNSQuestion* dq) const =0;
0940e4eb 907 virtual string toString() const = 0;
908 mutable std::atomic<uint64_t> d_matches{0};
909};
910
886e2cf2
RG
911struct ServerPool
912{
a1b1a29d
RG
913 ServerPool()
914 {
915 pthread_rwlock_init(&d_lock, nullptr);
916 }
040793d4
OM
917 ~ServerPool()
918 {
919 pthread_rwlock_destroy(&d_lock);
920 }
a1b1a29d 921
886e2cf2
RG
922 const std::shared_ptr<DNSDistPacketCache> getCache() const { return packetCache; };
923
7e687744
RG
924 bool getECS() const
925 {
926 return d_useECS;
927 }
928
929 void setECS(bool useECS)
930 {
931 d_useECS = useECS;
932 }
933
886e2cf2 934 std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
b9f8a6c8 935 std::shared_ptr<ServerPolicy> policy{nullptr};
5c30ec69 936
a1b1a29d
RG
937 size_t countServers(bool upOnly)
938 {
939 size_t count = 0;
940 ReadLock rl(&d_lock);
941 for (const auto& server : d_servers) {
942 if (!upOnly || std::get<1>(server)->isUp() ) {
943 count++;
c1b81381
RG
944 }
945 }
a1b1a29d
RG
946 return count;
947 }
948
be05aa91 949 ServerPolicy::NumberedServerVector getServers()
a1b1a29d 950 {
be05aa91 951 ServerPolicy::NumberedServerVector result;
a1b1a29d
RG
952 {
953 ReadLock rl(&d_lock);
954 result = d_servers;
955 }
956 return result;
957 }
958
959 void addServer(shared_ptr<DownstreamState>& server)
960 {
961 WriteLock wl(&d_lock);
962 unsigned int count = (unsigned int) d_servers.size();
963 d_servers.push_back(make_pair(++count, server));
964 /* we need to reorder based on the server 'order' */
965 std::stable_sort(d_servers.begin(), d_servers.end(), [](const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& a, const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& b) {
966 return a.second->order < b.second->order;
967 });
968 /* and now we need to renumber for Lua (custom policies) */
969 size_t idx = 1;
970 for (auto& serv : d_servers) {
971 serv.first = idx++;
972 }
973 }
974
975 void removeServer(shared_ptr<DownstreamState>& server)
976 {
977 WriteLock wl(&d_lock);
978 size_t idx = 1;
979 bool found = false;
980 for (auto it = d_servers.begin(); it != d_servers.end();) {
981 if (found) {
982 /* we need to renumber the servers placed
983 after the removed one, for Lua (custom policies) */
984 it->first = idx++;
985 it++;
986 }
987 else if (it->second == server) {
988 it = d_servers.erase(it);
989 found = true;
990 } else {
991 idx++;
992 it++;
993 }
994 }
995 }
996
997private:
be05aa91 998 ServerPolicy::NumberedServerVector d_servers;
a1b1a29d 999 pthread_rwlock_t d_lock;
7e687744 1000 bool d_useECS{false};
886e2cf2 1001};
886e2cf2 1002
42fae326 1003struct CarbonConfig
1004{
d617b22c 1005 ComboAddress server;
813b0ba9 1006 std::string namespace_name;
42fae326 1007 std::string ourname;
813b0ba9 1008 std::string instance_name;
d617b22c 1009 unsigned int interval;
42fae326 1010};
1011
ca404e94
RG
1012enum ednsHeaderFlags {
1013 EDNS_HEADER_FLAG_NONE = 0,
1014 EDNS_HEADER_FLAG_DO = 32768
1015};
1016
4d5959e6
RG
1017struct DNSDistRuleAction
1018{
1019 std::shared_ptr<DNSRule> d_rule;
1020 std::shared_ptr<DNSAction> d_action;
1021 boost::uuids::uuid d_id;
f8a222ac 1022 uint64_t d_creationOrder;
4d5959e6
RG
1023};
1024
1025struct DNSDistResponseRuleAction
1026{
1027 std::shared_ptr<DNSRule> d_rule;
1028 std::shared_ptr<DNSResponseAction> d_action;
1029 boost::uuids::uuid d_id;
f8a222ac 1030 uint64_t d_creationOrder;
4d5959e6
RG
1031};
1032
71c94675 1033extern GlobalStateHolder<SuffixMatchTree<DynBlock>> g_dynblockSMT;
dd46e5e3 1034extern DNSAction::Action g_dynBlockAction;
71c94675 1035
d617b22c 1036extern GlobalStateHolder<vector<CarbonConfig> > g_carbon;
ecbe9133 1037extern GlobalStateHolder<ServerPolicy> g_policy;
1038extern GlobalStateHolder<servers_t> g_dstates;
886e2cf2 1039extern GlobalStateHolder<pools_t> g_pools;
4d5959e6
RG
1040extern GlobalStateHolder<vector<DNSDistRuleAction> > g_rulactions;
1041extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_resprulactions;
1042extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_cachehitresprulactions;
2d4783a8 1043extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_selfansweredresprulactions;
638184e9 1044extern GlobalStateHolder<NetmaskGroup> g_ACL;
2e72cc0e 1045
ecbe9133 1046extern ComboAddress g_serverControl; // not changed during runtime
1047
a227f47d 1048extern std::vector<shared_ptr<TLSFrontend>> g_tlslocals;
fbf14b03 1049extern std::vector<shared_ptr<DOHFrontend>> g_dohlocals;
6e9fd124 1050extern std::vector<std::unique_ptr<ClientState>> g_frontends;
6ad8b29a 1051extern bool g_truncateTC;
b29edbee 1052extern bool g_fixupCase;
3f6d07a4
RG
1053extern int g_tcpRecvTimeout;
1054extern int g_tcpSendTimeout;
e0b5e49d 1055extern int g_udpTimeout;
e41f8165
RG
1056extern uint16_t g_maxOutstanding;
1057extern std::atomic<bool> g_configurationDone;
6c1ca990
RG
1058extern uint64_t g_maxTCPClientThreads;
1059extern uint64_t g_maxTCPQueuedConnections;
9396d955
RG
1060extern size_t g_maxTCPQueriesPerConn;
1061extern size_t g_maxTCPConnectionDuration;
1062extern size_t g_maxTCPConnectionsPerClient;
886e2cf2 1063extern std::atomic<uint16_t> g_cacheCleaningDelay;
f65ea0c2 1064extern std::atomic<uint16_t> g_cacheCleaningPercentage;
1ea747c0 1065extern uint32_t g_staleCacheEntriesTTL;
56d68fad
RG
1066extern bool g_apiReadWrite;
1067extern std::string g_apiConfigDirectory;
26a3cdb7 1068extern bool g_servFailOnNoPolicy;
edbda1ad 1069extern bool g_useTCPSinglePipe;
cff9aa03 1070extern uint16_t g_downstreamTCPCleanupInterval;
0beaa5c8 1071extern size_t g_udpVectorSize;
53c57da7 1072extern bool g_preserveTrailingData;
0dffe9e3 1073extern bool g_allowEmptyResponse;
ca404e94 1074
87b515ed
RG
1075#ifdef HAVE_EBPF
1076extern shared_ptr<BPFFilter> g_defaultBPFFilter;
8429ad04 1077extern std::vector<std::shared_ptr<DynBPFFilter> > g_dynBPFFilters;
87b515ed
RG
1078#endif /* HAVE_EBPF */
1079
0beaa5c8
RG
1080struct LocalHolders
1081{
2d4783a8 1082 LocalHolders(): acl(g_ACL.getLocal()), policy(g_policy.getLocal()), rulactions(g_rulactions.getLocal()), cacheHitRespRulactions(g_cachehitresprulactions.getLocal()), selfAnsweredRespRulactions(g_selfansweredresprulactions.getLocal()), servers(g_dstates.getLocal()), dynNMGBlock(g_dynblockNMG.getLocal()), dynSMTBlock(g_dynblockSMT.getLocal()), pools(g_pools.getLocal())
0beaa5c8
RG
1083 {
1084 }
1085
1086 LocalStateHolder<NetmaskGroup> acl;
1087 LocalStateHolder<ServerPolicy> policy;
4d5959e6
RG
1088 LocalStateHolder<vector<DNSDistRuleAction> > rulactions;
1089 LocalStateHolder<vector<DNSDistResponseRuleAction> > cacheHitRespRulactions;
2d4783a8 1090 LocalStateHolder<vector<DNSDistResponseRuleAction> > selfAnsweredRespRulactions;
0beaa5c8
RG
1091 LocalStateHolder<servers_t> servers;
1092 LocalStateHolder<NetmaskTree<DynBlock> > dynNMGBlock;
1093 LocalStateHolder<SuffixMatchTree<DynBlock> > dynSMTBlock;
1094 LocalStateHolder<pools_t> pools;
1095};
1096
ecbe9133 1097struct dnsheader;
1098
1099void controlThread(int fd, ComboAddress local);
b6e26895 1100vector<std::function<void(void)>> setupLua(bool client, const std::string& config);
e7c732b8 1101
80dbd7d2
CHB
1102struct WebserverConfig
1103{
1104 std::string password;
1105 std::string apiKey;
1106 boost::optional<std::map<std::string, std::string> > customHeaders;
1107 std::mutex lock;
1108};
1109
32c97b56
CHB
1110void setWebserverAPIKey(const boost::optional<std::string> apiKey);
1111void setWebserverPassword(const std::string& password);
1112void setWebserverCustomHeaders(const boost::optional<std::map<std::string, std::string> > customHeaders);
1113
80dbd7d2 1114void dnsdistWebserverThread(int sock, const ComboAddress& local);
9b73b71c 1115void tcpAcceptorThread(void* p);
fbf14b03
RG
1116#ifdef HAVE_DNS_OVER_HTTPS
1117void dohThread(ClientState* cs);
1118#endif /* HAVE_DNS_OVER_HTTPS */
80a216c9 1119
f758857a 1120void setLuaNoSideEffect(); // if nothing has been declared, set that there are no side effects
1121void setLuaSideEffect(); // set to report a side effect, cancelling all _no_ side effect calls
1122bool getLuaNoSideEffect(); // set if there were only explicit declarations of _no_ side effect
1123void resetLuaSideEffect(); // reset to indeterminate state
11e1e08b 1124
e7c732b8 1125bool responseContentMatches(const char* response, const uint16_t responseLen, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& remote, unsigned int& consumed);
3e425868 1126bool processResponse(char** response, uint16_t* responseLen, size_t* responseSize, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRulactions, DNSResponse& dr, size_t addRoom, std::vector<uint8_t>& rewrittenResponse, bool muted);
2a28db86 1127bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::string& ruleresult, bool& drop);
4ab01344 1128
0beaa5c8 1129bool checkQueryHeaders(const struct dnsheader* dh);
fcffc585 1130
6e9fd124 1131extern std::vector<std::shared_ptr<DNSCryptContext>> g_dnsCryptLocals;
43234e76 1132int handleDNSCryptQuery(char* packet, uint16_t len, std::shared_ptr<DNSCryptQuery> query, uint16_t* decryptedQueryLen, bool tcp, time_t now, std::vector<uint8_t>& response);
4ab01344 1133boost::optional<std::vector<uint8_t>> checkDNSCryptQuery(const ClientState& cs, const char* query, uint16_t& len, std::shared_ptr<DNSCryptQuery>& dnsCryptQuery, time_t now, bool tcp);
9f4eb5cc 1134
18f707fa 1135bool addXPF(DNSQuestion& dq, uint16_t optionCode);
5cc8371b 1136
555970c9
RG
1137uint16_t getRandomDNSID();
1138
9f4eb5cc
RG
1139#include "dnsdist-snmp.hh"
1140
1141extern bool g_snmpEnabled;
1142extern bool g_snmpTrapsEnabled;
1143extern DNSDistSNMPAgent* g_snmpAgent;
e7c732b8
RG
1144extern bool g_addEDNSToSelfGeneratedResponses;
1145
83fe2c55 1146extern std::set<std::string> g_capabilitiesToRetain;
8179b6d6
RG
1147static const uint16_t s_udpIncomingBufferSize{1500}; // don't accept UDP queries larger than this value
1148static const size_t s_maxPacketCacheEntrySize{4096}; // don't cache responses larger than this value
4ab01344 1149
3e425868
RG
1150enum class ProcessQueryResult { Drop, SendAnswer, PassToBackend };
1151ProcessQueryResult processQuery(DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr<DownstreamState>& selectedBackend);
4ab01344 1152
d0ae6360
RG
1153DNSResponse makeDNSResponseFromIDState(IDState& ids, struct dnsheader* dh, size_t bufferSize, uint16_t responseLen, bool isTCP);
1154void setIDStateFromDNSQuestion(IDState& ids, DNSQuestion& dq, DNSName&& qname);
fbf14b03
RG
1155
1156int pickBackendSocketForSending(std::shared_ptr<DownstreamState>& state);
1157ssize_t udpClientSendRequestToBackend(const std::shared_ptr<DownstreamState>& ss, const int sd, const char* request, const size_t requestLen, bool healthCheck=false);