Coverage Report

Created: 2023-03-26 07:18

/src/pdns/pdns/dnsdist.hh
Line
Count
Source (jump to first uncovered line)
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
 */
22
#pragma once
23
#include "config.h"
24
#include "ext/luawrapper/include/LuaContext.hpp"
25
26
#include <memory>
27
#include <mutex>
28
#include <string>
29
#include <thread>
30
#include <time.h>
31
#include <unistd.h>
32
#include <unordered_map>
33
34
#include <boost/variant.hpp>
35
36
#include "circular_buffer.hh"
37
#include "dnscrypt.hh"
38
#include "dnsdist-cache.hh"
39
#include "dnsdist-dynbpf.hh"
40
#include "dnsdist-idstate.hh"
41
#include "dnsdist-lbpolicies.hh"
42
#include "dnsdist-protocols.hh"
43
#include "dnsname.hh"
44
#include "doh.hh"
45
#include "ednsoptions.hh"
46
#include "iputils.hh"
47
#include "misc.hh"
48
#include "mplexer.hh"
49
#include "noinitvector.hh"
50
#include "sholder.hh"
51
#include "tcpiohandler.hh"
52
#include "uuid-utils.hh"
53
#include "proxy-protocol.hh"
54
#include "stat_t.hh"
55
56
uint64_t uptimeOfProcess(const std::string& str);
57
58
extern uint16_t g_ECSSourcePrefixV4;
59
extern uint16_t g_ECSSourcePrefixV6;
60
extern bool g_ECSOverride;
61
62
using QTag = std::unordered_map<string, string>;
63
64
class IncomingTCPConnectionState;
65
66
struct ClientState;
67
68
struct DNSQuestion
69
{
70
  DNSQuestion(InternalQueryState& ids_, PacketBuffer& data_):
71
0
    data(data_), ids(ids_), ecsPrefixLength(ids.origRemote.sin4.sin_family == AF_INET ? g_ECSSourcePrefixV4 : g_ECSSourcePrefixV6), ecsOverride(g_ECSOverride) {
72
0
  }
73
  DNSQuestion(const DNSQuestion&) = delete;
74
  DNSQuestion& operator=(const DNSQuestion&) = delete;
75
  DNSQuestion(DNSQuestion&&) = default;
76
0
  virtual ~DNSQuestion() = default;
77
78
  std::string getTrailingData() const;
79
  bool setTrailingData(const std::string&);
80
  const PacketBuffer& getData() const
81
0
  {
82
0
    return data;
83
0
  }
84
  PacketBuffer& getMutableData()
85
0
  {
86
0
    return data;
87
0
  }
88
89
  dnsheader* getHeader()
90
0
  {
91
0
    if (data.size() < sizeof(dnsheader)) {
92
0
      throw std::runtime_error("Trying to access the dnsheader of a too small (" + std::to_string(data.size()) + ") DNSQuestion buffer");
93
0
    }
94
0
    return reinterpret_cast<dnsheader*>(&data.at(0));
95
0
  }
96
97
  const dnsheader* getHeader() const
98
0
  {
99
0
    if (data.size() < sizeof(dnsheader)) {
100
0
      throw std::runtime_error("Trying to access the dnsheader of a too small (" + std::to_string(data.size()) + ") DNSQuestion buffer");
101
0
    }
102
0
    return reinterpret_cast<const dnsheader*>(&data.at(0));
103
0
  }
104
105
  bool hasRoomFor(size_t more) const
106
0
  {
107
0
    return data.size() <= getMaximumSize() && (getMaximumSize() - data.size()) >= more;
108
0
  }
109
110
  size_t getMaximumSize() const
111
0
  {
112
0
    if (overTCP()) {
113
0
      return std::numeric_limits<uint16_t>::max();
114
0
    }
115
0
    return 4096;
116
0
  }
117
118
  dnsdist::Protocol getProtocol() const
119
0
  {
120
0
    return ids.protocol;
121
0
  }
122
123
  bool overTCP() const
124
0
  {
125
0
    return !(ids.protocol == dnsdist::Protocol::DoUDP || ids.protocol == dnsdist::Protocol::DNSCryptUDP);
126
0
  }
127
128
0
  void setTag(std::string&& key, std::string&& value) {
129
0
    if (!ids.qTag) {
130
0
      ids.qTag = std::make_unique<QTag>();
131
0
    }
132
0
    ids.qTag->insert_or_assign(std::move(key), std::move(value));
133
0
  }
134
135
0
  void setTag(const std::string& key, const std::string& value) {
136
0
    if (!ids.qTag) {
137
0
      ids.qTag = std::make_unique<QTag>();
138
0
    }
139
0
    ids.qTag->insert_or_assign(key, value);
140
0
  }
141
142
  const struct timespec& getQueryRealTime() const
143
0
  {
144
0
    return ids.queryRealTime.d_start;
145
0
  }
146
147
  bool isAsynchronous() const
148
0
  {
149
0
    return asynchronous;
150
0
  }
151
152
  std::shared_ptr<IncomingTCPConnectionState> getIncomingTCPState() const
153
0
  {
154
0
    return d_incomingTCPState;
155
0
  }
156
157
  ClientState* getFrontend() const
158
0
  {
159
0
    return ids.cs;
160
0
  }
161
162
protected:
163
  PacketBuffer& data;
164
165
public:
166
  InternalQueryState& ids;
167
  std::unique_ptr<Netmask> ecs{nullptr};
168
  std::string sni; /* Server Name Indication, if any (DoT or DoH) */
169
  mutable std::unique_ptr<EDNSOptionViewMap> ednsOptions; /* this needs to be mutable because it is parsed just in time, when DNSQuestion is read-only */
170
  std::shared_ptr<IncomingTCPConnectionState> d_incomingTCPState{nullptr};
171
  std::unique_ptr<std::vector<ProxyProtocolValue>> proxyProtocolValues{nullptr};
172
  uint16_t ecsPrefixLength;
173
  uint8_t ednsRCode{0};
174
  bool ecsOverride;
175
  bool useECS{true};
176
  bool addXPF{true};
177
  bool asynchronous{false};
178
};
179
180
struct DownstreamState;
181
182
struct DNSResponse : DNSQuestion
183
{
184
  DNSResponse(InternalQueryState& ids_, PacketBuffer& data_, const std::shared_ptr<DownstreamState>& downstream):
185
0
    DNSQuestion(ids_, data_), d_downstream(downstream) { }
186
  DNSResponse(const DNSResponse&) = delete;
187
  DNSResponse& operator=(const DNSResponse&) = delete;
188
  DNSResponse(DNSResponse&&) = default;
189
190
  const std::shared_ptr<DownstreamState>& d_downstream;
191
};
192
193
/* so what could you do:
194
   drop,
195
   fake up nxdomain,
196
   provide actual answer,
197
   allow & and stop processing,
198
   continue processing,
199
   modify header:    (servfail|refused|notimp), set TC=1,
200
   send to pool */
201
202
class DNSAction
203
{
204
public:
205
  enum class Action : uint8_t { Drop, Nxdomain, Refused, Spoof, Allow, HeaderModify, Pool, Delay, Truncate, ServFail, None, NoOp, NoRecurse, SpoofRaw, SpoofPacket };
206
  static std::string typeToString(const Action& action)
207
0
  {
208
0
    switch(action) {
209
0
    case Action::Drop:
210
0
      return "Drop";
211
0
    case Action::Nxdomain:
212
0
      return "Send NXDomain";
213
0
    case Action::Refused:
214
0
      return "Send Refused";
215
0
    case Action::Spoof:
216
0
      return "Spoof an answer";
217
0
    case Action::SpoofPacket:
218
0
      return "Spoof a raw answer from bytes";
219
0
    case Action::SpoofRaw:
220
0
      return "Spoof an answer from raw bytes";
221
0
    case Action::Allow:
222
0
      return "Allow";
223
0
    case Action::HeaderModify:
224
0
      return "Modify the header";
225
0
    case Action::Pool:
226
0
      return "Route to a pool";
227
0
    case Action::Delay:
228
0
      return "Delay";
229
0
    case Action::Truncate:
230
0
      return "Truncate over UDP";
231
0
    case Action::ServFail:
232
0
      return "Send ServFail";
233
0
    case Action::None:
234
0
    case Action::NoOp:
235
0
      return "Do nothing";
236
0
    case Action::NoRecurse:
237
0
      return "Set rd=0";
238
0
    }
239
0
240
0
    return "Unknown";
241
0
  }
242
243
  virtual Action operator()(DNSQuestion*, string* ruleresult) const =0;
244
  virtual ~DNSAction()
245
0
  {
246
0
  }
247
  virtual string toString() const = 0;
248
  virtual std::map<string, double> getStats() const
249
0
  {
250
0
    return {{}};
251
0
  }
252
  virtual void reload()
253
0
  {
254
0
  }
255
};
256
257
class DNSResponseAction
258
{
259
public:
260
  enum class Action : uint8_t { Allow, Delay, Drop, HeaderModify, ServFail, None };
261
  virtual Action operator()(DNSResponse*, string* ruleresult) const =0;
262
  virtual ~DNSResponseAction()
263
0
  {
264
0
  }
265
  virtual string toString() const = 0;
266
  virtual void reload()
267
0
  {
268
0
  }
269
};
270
271
struct DynBlock
272
{
273
  DynBlock(): action(DNSAction::Action::None), warning(false)
274
0
  {
275
0
    until.tv_sec = 0;
276
0
    until.tv_nsec = 0;
277
0
  }
278
279
  DynBlock(const std::string& reason_, const struct timespec& until_, const DNSName& domain_, DNSAction::Action action_): reason(reason_), domain(domain_), until(until_), action(action_), warning(false)
280
0
  {
281
0
  }
282
283
  DynBlock(const DynBlock& rhs): reason(rhs.reason), domain(rhs.domain), until(rhs.until), action(rhs.action), warning(rhs.warning), bpf(rhs.bpf)
284
0
  {
285
0
    blocks.store(rhs.blocks);
286
0
  }
287
288
  DynBlock(DynBlock&& rhs): reason(std::move(rhs.reason)), domain(std::move(rhs.domain)), until(rhs.until), action(rhs.action), warning(rhs.warning), bpf(rhs.bpf)
289
0
  {
290
0
    blocks.store(rhs.blocks);
291
0
  }
292
293
  DynBlock& operator=(const DynBlock& rhs)
294
0
  {
295
0
    reason = rhs.reason;
296
0
    until = rhs.until;
297
0
    domain = rhs.domain;
298
0
    action = rhs.action;
299
0
    blocks.store(rhs.blocks);
300
0
    warning = rhs.warning;
301
0
    bpf = rhs.bpf;
302
0
    return *this;
303
0
  }
304
305
  DynBlock& operator=(DynBlock&& rhs)
306
0
  {
307
0
    reason = std::move(rhs.reason);
308
0
    until = rhs.until;
309
0
    domain = std::move(rhs.domain);
310
0
    action = rhs.action;
311
0
    blocks.store(rhs.blocks);
312
0
    warning = rhs.warning;
313
0
    bpf = rhs.bpf;
314
0
    return *this;
315
0
  }
316
317
  string reason;
318
  DNSName domain;
319
  struct timespec until;
320
  mutable std::atomic<unsigned int> blocks;
321
  DNSAction::Action action{DNSAction::Action::None};
322
  bool warning{false};
323
  bool bpf{false};
324
};
325
326
extern GlobalStateHolder<NetmaskTree<DynBlock, AddressAndPortRange>> g_dynblockNMG;
327
328
extern vector<pair<struct timeval, std::string> > g_confDelta;
329
330
using pdns::stat_t;
331
332
struct DNSDistStats
333
{
334
  stat_t responses{0};
335
  stat_t servfailResponses{0};
336
  stat_t queries{0};
337
  stat_t frontendNXDomain{0};
338
  stat_t frontendServFail{0};
339
  stat_t frontendNoError{0};
340
  stat_t nonCompliantQueries{0};
341
  stat_t nonCompliantResponses{0};
342
  stat_t rdQueries{0};
343
  stat_t emptyQueries{0};
344
  stat_t aclDrops{0};
345
  stat_t dynBlocked{0};
346
  stat_t ruleDrop{0};
347
  stat_t ruleNXDomain{0};
348
  stat_t ruleRefused{0};
349
  stat_t ruleServFail{0};
350
  stat_t ruleTruncated{0};
351
  stat_t selfAnswered{0};
352
  stat_t downstreamTimeouts{0};
353
  stat_t downstreamSendErrors{0};
354
  stat_t truncFail{0};
355
  stat_t noPolicy{0};
356
  stat_t cacheHits{0};
357
  stat_t cacheMisses{0};
358
  stat_t latency0_1{0}, latency1_10{0}, latency10_50{0}, latency50_100{0}, latency100_1000{0}, latencySlow{0}, latencySum{0}, latencyCount{0};
359
  stat_t securityStatus{0};
360
  stat_t dohQueryPipeFull{0};
361
  stat_t dohResponsePipeFull{0};
362
  stat_t outgoingDoHQueryPipeFull{0};
363
  stat_t proxyProtocolInvalid{0};
364
  stat_t tcpQueryPipeFull{0};
365
  stat_t tcpCrossProtocolQueryPipeFull{0};
366
  stat_t tcpCrossProtocolResponsePipeFull{0};
367
  double latencyAvg100{0}, latencyAvg1000{0}, latencyAvg10000{0}, latencyAvg1000000{0};
368
  double latencyTCPAvg100{0}, latencyTCPAvg1000{0}, latencyTCPAvg10000{0}, latencyTCPAvg1000000{0};
369
  double latencyDoTAvg100{0}, latencyDoTAvg1000{0}, latencyDoTAvg10000{0}, latencyDoTAvg1000000{0};
370
  double latencyDoHAvg100{0}, latencyDoHAvg1000{0}, latencyDoHAvg10000{0}, latencyDoHAvg1000000{0};
371
  typedef std::function<uint64_t(const std::string&)> statfunction_t;
372
  typedef boost::variant<stat_t*, pdns::stat_t_trait<double>*, double*, statfunction_t> entry_t;
373
374
  std::vector<std::pair<std::string, entry_t>> entries{
375
    {"responses", &responses},
376
    {"servfail-responses", &servfailResponses},
377
    {"queries", &queries},
378
    {"frontend-nxdomain", &frontendNXDomain},
379
    {"frontend-servfail", &frontendServFail},
380
    {"frontend-noerror", &frontendNoError},
381
    {"acl-drops", &aclDrops},
382
    {"rule-drop", &ruleDrop},
383
    {"rule-nxdomain", &ruleNXDomain},
384
    {"rule-refused", &ruleRefused},
385
    {"rule-servfail", &ruleServFail},
386
    {"rule-truncated", &ruleTruncated},
387
    {"self-answered", &selfAnswered},
388
    {"downstream-timeouts", &downstreamTimeouts},
389
    {"downstream-send-errors", &downstreamSendErrors},
390
    {"trunc-failures", &truncFail},
391
    {"no-policy", &noPolicy},
392
    {"latency0-1", &latency0_1},
393
    {"latency1-10", &latency1_10},
394
    {"latency10-50", &latency10_50},
395
    {"latency50-100", &latency50_100},
396
    {"latency100-1000", &latency100_1000},
397
    {"latency-slow", &latencySlow},
398
    {"latency-avg100", &latencyAvg100},
399
    {"latency-avg1000", &latencyAvg1000},
400
    {"latency-avg10000", &latencyAvg10000},
401
    {"latency-avg1000000", &latencyAvg1000000},
402
    {"latency-tcp-avg100", &latencyTCPAvg100},
403
    {"latency-tcp-avg1000", &latencyTCPAvg1000},
404
    {"latency-tcp-avg10000", &latencyTCPAvg10000},
405
    {"latency-tcp-avg1000000", &latencyTCPAvg1000000},
406
    {"latency-dot-avg100", &latencyDoTAvg100},
407
    {"latency-dot-avg1000", &latencyDoTAvg1000},
408
    {"latency-dot-avg10000", &latencyDoTAvg10000},
409
    {"latency-dot-avg1000000", &latencyDoTAvg1000000},
410
    {"latency-doh-avg100", &latencyDoHAvg100},
411
    {"latency-doh-avg1000", &latencyDoHAvg1000},
412
    {"latency-doh-avg10000", &latencyDoHAvg10000},
413
    {"latency-doh-avg1000000", &latencyDoHAvg1000000},
414
    {"uptime", uptimeOfProcess},
415
    {"real-memory-usage", getRealMemoryUsage},
416
    {"special-memory-usage", getSpecialMemoryUsage},
417
    {"udp-in-errors", std::bind(udpErrorStats, "udp-in-errors")},
418
    {"udp-noport-errors", std::bind(udpErrorStats, "udp-noport-errors")},
419
    {"udp-recvbuf-errors", std::bind(udpErrorStats, "udp-recvbuf-errors")},
420
    {"udp-sndbuf-errors", std::bind(udpErrorStats, "udp-sndbuf-errors")},
421
    {"udp-in-csum-errors", std::bind(udpErrorStats, "udp-in-csum-errors")},
422
    {"udp6-in-errors", std::bind(udp6ErrorStats, "udp6-in-errors")},
423
    {"udp6-recvbuf-errors", std::bind(udp6ErrorStats, "udp6-recvbuf-errors")},
424
    {"udp6-sndbuf-errors", std::bind(udp6ErrorStats, "udp6-sndbuf-errors")},
425
    {"udp6-noport-errors", std::bind(udp6ErrorStats, "udp6-noport-errors")},
426
    {"udp6-in-csum-errors", std::bind(udp6ErrorStats, "udp6-in-csum-errors")},
427
    {"tcp-listen-overflows", std::bind(tcpErrorStats, "ListenOverflows")},
428
    {"noncompliant-queries", &nonCompliantQueries},
429
    {"noncompliant-responses", &nonCompliantResponses},
430
    {"proxy-protocol-invalid", &proxyProtocolInvalid},
431
    {"rdqueries", &rdQueries},
432
    {"empty-queries", &emptyQueries},
433
    {"cache-hits", &cacheHits},
434
    {"cache-misses", &cacheMisses},
435
    {"cpu-iowait", getCPUIOWait},
436
    {"cpu-steal", getCPUSteal},
437
    {"cpu-sys-msec", getCPUTimeSystem},
438
    {"cpu-user-msec", getCPUTimeUser},
439
    {"fd-usage", getOpenFileDescriptors},
440
    {"dyn-blocked", &dynBlocked},
441
    {"dyn-block-nmg-size", [](const std::string&) { return g_dynblockNMG.getLocal()->size(); }},
442
    {"security-status", &securityStatus},
443
    {"doh-query-pipe-full", &dohQueryPipeFull},
444
    {"doh-response-pipe-full", &dohResponsePipeFull},
445
    {"outgoing-doh-query-pipe-full", &outgoingDoHQueryPipeFull},
446
    {"tcp-query-pipe-full", &tcpQueryPipeFull},
447
    {"tcp-cross-protocol-query-pipe-full", &tcpCrossProtocolQueryPipeFull},
448
    {"tcp-cross-protocol-response-pipe-full", &tcpCrossProtocolResponsePipeFull},
449
    // Latency histogram
450
    {"latency-sum", &latencySum},
451
    {"latency-count", &latencyCount},
452
  };
453
  std::map<std::string, stat_t, std::less<>> customCounters;
454
  std::map<std::string, pdns::stat_t_trait<double>, std::less<>> customGauges;
455
};
456
457
extern struct DNSDistStats g_stats;
458
459
class BasicQPSLimiter
460
{
461
public:
462
  BasicQPSLimiter()
463
0
  {
464
0
  }
465
466
  BasicQPSLimiter(unsigned int burst): d_tokens(burst)
467
0
  {
468
0
    d_prev.start();
469
0
  }
470
471
  virtual ~BasicQPSLimiter()
472
0
  {
473
0
  }
474
475
  bool check(unsigned int rate, unsigned int burst) const // this is not quite fair
476
0
  {
477
0
    if (checkOnly(rate, burst)) {
478
0
      addHit();
479
0
      return true;
480
0
    }
481
0
482
0
    return false;
483
0
  }
484
485
  bool checkOnly(unsigned int rate, unsigned int burst) const // this is not quite fair
486
0
  {
487
0
    auto delta = d_prev.udiffAndSet();
488
0
489
0
    if (delta > 0.0) { // time, frequently, does go backwards..
490
0
      d_tokens += 1.0 * rate * (delta/1000000.0);
491
0
    }
492
0
493
0
    if (d_tokens > burst) {
494
0
      d_tokens = burst;
495
0
    }
496
0
497
0
    bool ret = false;
498
0
    if (d_tokens >= 1.0) { // we need this because burst=1 is weird otherwise
499
0
      ret = true;
500
0
    }
501
0
502
0
    return ret;
503
0
  }
504
505
  virtual void addHit() const
506
0
  {
507
0
    --d_tokens;
508
0
  }
509
510
  bool seenSince(const struct timespec& cutOff) const
511
0
  {
512
0
    return cutOff < d_prev.d_start;
513
0
  }
514
515
protected:
516
  mutable StopWatch d_prev;
517
  mutable double d_tokens{0.0};
518
};
519
520
class QPSLimiter : public BasicQPSLimiter
521
{
522
public:
523
  QPSLimiter(): BasicQPSLimiter()
524
0
  {
525
0
  }
526
527
  QPSLimiter(unsigned int rate, unsigned int burst): BasicQPSLimiter(burst), d_rate(rate), d_burst(burst), d_passthrough(false)
528
0
  {
529
0
    d_prev.start();
530
0
  }
531
532
  unsigned int getRate() const
533
0
  {
534
0
    return d_passthrough ? 0 : d_rate;
535
0
  }
536
537
  bool check() const // this is not quite fair
538
0
  {
539
0
    if (d_passthrough) {
540
0
      return true;
541
0
    }
542
0
543
0
    return BasicQPSLimiter::check(d_rate, d_burst);
544
0
  }
545
546
  bool checkOnly() const
547
0
  {
548
0
    if (d_passthrough) {
549
0
      return true;
550
0
    }
551
0
552
0
    return BasicQPSLimiter::checkOnly(d_rate, d_burst);
553
0
  }
554
555
  void addHit() const override
556
0
  {
557
0
    if (!d_passthrough) {
558
0
      --d_tokens;
559
0
    }
560
0
  }
561
562
private:
563
  unsigned int d_rate{0};
564
  unsigned int d_burst{0};
565
  bool d_passthrough{true};
566
};
567
568
typedef std::unordered_map<string, unsigned int> QueryCountRecords;
569
typedef std::function<std::tuple<bool, string>(const DNSQuestion* dq)> QueryCountFilter;
570
struct QueryCount {
571
  QueryCount()
572
0
  {
573
0
  }
574
  ~QueryCount()
575
0
  {
576
0
  }
577
  SharedLockGuarded<QueryCountRecords> records;
578
  QueryCountFilter filter;
579
  bool enabled{false};
580
};
581
582
extern QueryCount g_qcount;
583
584
struct ClientState
585
{
586
  ClientState(const ComboAddress& local_, bool isTCP_, bool doReusePort, int fastOpenQueue, const std::string& itfName, const std::set<int>& cpus_): cpus(cpus_), interface(itfName), local(local_), fastOpenQueueSize(fastOpenQueue), tcp(isTCP_), reuseport(doReusePort)
587
0
  {
588
0
  }
589
590
  stat_t queries{0};
591
  stat_t nonCompliantQueries{0};
592
  mutable stat_t responses{0};
593
  mutable stat_t tcpDiedReadingQuery{0};
594
  mutable stat_t tcpDiedSendingResponse{0};
595
  mutable stat_t tcpGaveUp{0};
596
  mutable stat_t tcpClientTimeouts{0};
597
  mutable stat_t tcpDownstreamTimeouts{0};
598
  /* current number of connections to this frontend */
599
  mutable stat_t tcpCurrentConnections{0};
600
  /* maximum number of concurrent connections to this frontend reached */
601
  mutable stat_t tcpMaxConcurrentConnections{0};
602
  stat_t tlsNewSessions{0}; // A new TLS session has been negotiated, no resumption
603
  stat_t tlsResumptions{0}; // A TLS session has been resumed, either via session id or via a TLS ticket
604
  stat_t tlsUnknownTicketKey{0}; // A TLS ticket has been presented but we don't have the associated key (might have expired)
605
  stat_t tlsInactiveTicketKey{0}; // A TLS ticket has been successfully resumed but the key is no longer active, we should issue a new one
606
  stat_t tls10queries{0};   // valid DNS queries received via TLSv1.0
607
  stat_t tls11queries{0};   // valid DNS queries received via TLSv1.1
608
  stat_t tls12queries{0};   // valid DNS queries received via TLSv1.2
609
  stat_t tls13queries{0};   // valid DNS queries received via TLSv1.3
610
  stat_t tlsUnknownqueries{0};   // valid DNS queries received via unknown TLS version
611
  pdns::stat_t_trait<double> tcpAvgQueriesPerConnection{0.0};
612
  /* in ms */
613
  pdns::stat_t_trait<double> tcpAvgConnectionDuration{0.0};
614
  std::set<int> cpus;
615
  std::string interface;
616
  ComboAddress local;
617
  std::vector<std::pair<ComboAddress, int>> d_additionalAddresses;
618
  std::shared_ptr<DNSCryptContext> dnscryptCtx{nullptr};
619
  std::shared_ptr<TLSFrontend> tlsFrontend{nullptr};
620
  std::shared_ptr<DOHFrontend> dohFrontend{nullptr};
621
  std::shared_ptr<BPFFilter> d_filter{nullptr};
622
  size_t d_maxInFlightQueriesPerConn{1};
623
  size_t d_tcpConcurrentConnectionsLimit{0};
624
  int udpFD{-1};
625
  int tcpFD{-1};
626
  int tcpListenQueueSize{SOMAXCONN};
627
  int fastOpenQueueSize{0};
628
  bool muted{false};
629
  bool tcp;
630
  bool reuseport;
631
  bool ready{false};
632
633
  int getSocket() const
634
0
  {
635
0
    return udpFD != -1 ? udpFD : tcpFD;
636
0
  }
637
638
  bool isUDP() const
639
0
  {
640
0
    return udpFD != -1;
641
0
  }
642
643
  bool isTCP() const
644
0
  {
645
0
    return udpFD == -1;
646
0
  }
647
648
  bool isDoH() const
649
0
  {
650
0
    return dohFrontend != nullptr;
651
0
  }
652
653
  bool hasTLS() const
654
0
  {
655
0
    return tlsFrontend != nullptr || (dohFrontend != nullptr && dohFrontend->isHTTPS());
656
0
  }
657
658
  dnsdist::Protocol getProtocol() const
659
0
  {
660
0
    if (dnscryptCtx) {
661
0
      if (udpFD != -1) {
662
0
        return dnsdist::Protocol::DNSCryptUDP;
663
0
      }
664
0
      return dnsdist::Protocol::DNSCryptTCP;
665
0
    }
666
0
    if (isDoH()) {
667
0
      return dnsdist::Protocol::DoH;
668
0
    }
669
0
    else if (hasTLS()) {
670
0
      return dnsdist::Protocol::DoT;
671
0
    }
672
0
    else if (udpFD != -1) {
673
0
      return dnsdist::Protocol::DoUDP;
674
0
    }
675
0
    else {
676
0
      return dnsdist::Protocol::DoTCP;
677
0
    }
678
0
  }
679
680
  std::string getType() const
681
0
  {
682
0
    std::string result = udpFD != -1 ? "UDP" : "TCP";
683
0
684
0
    if (dohFrontend) {
685
0
      if (dohFrontend->isHTTPS()) {
686
0
        result += " (DNS over HTTPS)";
687
0
      }
688
0
      else {
689
0
        result += " (DNS over HTTP)";
690
0
      }
691
0
    }
692
0
    else if (tlsFrontend) {
693
0
      result += " (DNS over TLS)";
694
0
    }
695
0
    else if (dnscryptCtx) {
696
0
      result += " (DNSCrypt)";
697
0
    }
698
0
699
0
    return result;
700
0
  }
701
702
  void detachFilter(int socket)
703
0
  {
704
0
    if (d_filter) {
705
0
      d_filter->removeSocket(socket);
706
0
      d_filter = nullptr;
707
0
    }
708
0
  }
709
710
  void attachFilter(shared_ptr<BPFFilter> bpf, int socket)
711
0
  {
712
0
    detachFilter(socket);
713
0
714
0
    bpf->addSocket(socket);
715
0
    d_filter = bpf;
716
0
  }
717
718
  void detachFilter()
719
0
  {
720
0
    if (d_filter) {
721
0
      detachFilter(getSocket());
722
0
      for (const auto& [addr, socket] : d_additionalAddresses) {
723
0
        (void) addr;
724
0
        if (socket != -1) {
725
0
          detachFilter(socket);
726
0
        }
727
0
      }
728
0
729
0
      d_filter = nullptr;
730
0
    }
731
0
  }
732
733
  void attachFilter(shared_ptr<BPFFilter> bpf)
734
0
  {
735
0
    detachFilter();
736
0
737
0
    bpf->addSocket(getSocket());
738
0
    for (const auto& [addr, socket] : d_additionalAddresses) {
739
0
      (void) addr;
740
0
      if (socket != -1) {
741
0
        bpf->addSocket(socket);
742
0
      }
743
0
    }
744
0
    d_filter = bpf;
745
0
  }
746
747
  void updateTCPMetrics(size_t nbQueries, uint64_t durationMs)
748
0
  {
749
0
    tcpAvgQueriesPerConnection = (99.0 * tcpAvgQueriesPerConnection / 100.0) + (nbQueries / 100.0);
750
0
    tcpAvgConnectionDuration = (99.0 * tcpAvgConnectionDuration / 100.0) + (durationMs / 100.0);
751
0
  }
752
};
753
754
struct CrossProtocolQuery;
755
756
struct DownstreamState: public std::enable_shared_from_this<DownstreamState>
757
{
758
  DownstreamState(const DownstreamState&) = delete;
759
  DownstreamState(DownstreamState&&) = delete;
760
  DownstreamState& operator=(const DownstreamState&) = delete;
761
  DownstreamState& operator=(DownstreamState&&) = delete;
762
763
  typedef std::function<std::tuple<DNSName, uint16_t, uint16_t>(const DNSName&, uint16_t, uint16_t, dnsheader*)> checkfunc_t;
764
  enum class Availability : uint8_t { Up, Down, Auto, Lazy };
765
  enum class LazyHealthCheckMode : uint8_t { TimeoutOnly, TimeoutOrServFail };
766
767
  struct Config
768
  {
769
    Config()
770
0
    {
771
0
    }
772
    Config(const ComboAddress& remote_): remote(remote_)
773
0
    {
774
0
    }
775
776
    TLSContextParameters d_tlsParams;
777
    set<string> pools;
778
    std::set<int> d_cpus;
779
    checkfunc_t checkFunction;
780
    std::optional<boost::uuids::uuid> id;
781
    DNSName checkName{"a.root-servers.net."};
782
    ComboAddress remote;
783
    ComboAddress sourceAddr;
784
    std::string sourceItfName;
785
    std::string d_tlsSubjectName;
786
    std::string d_dohPath;
787
    std::string name;
788
    std::string nameWithAddr;
789
    size_t d_numberOfSockets{1};
790
    size_t d_maxInFlightQueriesPerConn{1};
791
    size_t d_tcpConcurrentConnectionsLimit{0};
792
    int order{1};
793
    int d_weight{1};
794
    int tcpConnectTimeout{5};
795
    int tcpRecvTimeout{30};
796
    int tcpSendTimeout{30};
797
    int d_qpsLimit{0};
798
    unsigned int checkInterval{1};
799
    unsigned int sourceItf{0};
800
    QType checkType{QType::A};
801
    uint16_t checkClass{QClass::IN};
802
    uint16_t d_retries{5};
803
    uint16_t xpfRRCode{0};
804
    uint16_t checkTimeout{1000}; /* in milliseconds */
805
    uint16_t d_lazyHealthCheckSampleSize{100};
806
    uint16_t d_lazyHealthCheckMinSampleCount{1};
807
    uint16_t d_lazyHealthCheckFailedInterval{30};
808
    uint16_t d_lazyHealthCheckMaxBackOff{3600};
809
    uint8_t d_lazyHealthCheckThreshold{20};
810
    LazyHealthCheckMode d_lazyHealthCheckMode{LazyHealthCheckMode::TimeoutOrServFail};
811
    uint8_t maxCheckFailures{1};
812
    uint8_t minRiseSuccesses{1};
813
    Availability availability{Availability::Auto};
814
    bool d_tlsSubjectIsAddr{false};
815
    bool mustResolve{false};
816
    bool useECS{false};
817
    bool useProxyProtocol{false};
818
    bool setCD{false};
819
    bool disableZeroScope{false};
820
    bool tcpFastOpen{false};
821
    bool ipBindAddrNoPort{true};
822
    bool reconnectOnUp{false};
823
    bool d_tcpCheck{false};
824
    bool d_tcpOnly{false};
825
    bool d_addXForwardedHeaders{false}; // for DoH backends
826
    bool d_lazyHealthCheckUseExponentialBackOff{false};
827
    bool d_upgradeToLazyHealthChecks{false};
828
  };
829
830
  DownstreamState(DownstreamState::Config&& config, std::shared_ptr<TLSCtx> tlsCtx, bool connect);
831
  DownstreamState(const ComboAddress& remote): DownstreamState(DownstreamState::Config(remote), nullptr, false)
832
0
  {
833
0
  }
834
835
  ~DownstreamState();
836
837
  Config d_config;
838
  stat_t sendErrors{0};
839
  stat_t outstanding{0};
840
  stat_t reuseds{0};
841
  stat_t queries{0};
842
  stat_t responses{0};
843
  stat_t nonCompliantResponses{0};
844
  struct {
845
    stat_t sendErrors{0};
846
    stat_t reuseds{0};
847
    stat_t queries{0};
848
  } prev;
849
  stat_t tcpDiedSendingQuery{0};
850
  stat_t tcpDiedReadingResponse{0};
851
  stat_t tcpGaveUp{0};
852
  stat_t tcpReadTimeouts{0};
853
  stat_t tcpWriteTimeouts{0};
854
  stat_t tcpConnectTimeouts{0};
855
  /* current number of connections to this backend */
856
  stat_t tcpCurrentConnections{0};
857
  /* maximum number of concurrent connections to this backend reached */
858
  stat_t tcpMaxConcurrentConnections{0};
859
  /* number of times we had to enforce the maximum concurrent connections limit */
860
  stat_t tcpTooManyConcurrentConnections{0};
861
  stat_t tcpReusedConnections{0};
862
  stat_t tcpNewConnections{0};
863
  stat_t tlsResumptions{0};
864
  pdns::stat_t_trait<double> tcpAvgQueriesPerConnection{0.0};
865
  /* in ms */
866
  pdns::stat_t_trait<double> tcpAvgConnectionDuration{0.0};
867
  pdns::stat_t_trait<double> queryLoad{0.0};
868
  pdns::stat_t_trait<double> dropRate{0.0};
869
870
  SharedLockGuarded<std::vector<unsigned int>> hashes;
871
  LockGuarded<std::unique_ptr<FDMultiplexer>> mplexer{nullptr};
872
private:
873
  LockGuarded<std::map<uint16_t, IDState>> d_idStatesMap;
874
  vector<IDState> idStates;
875
876
  struct LazyHealthCheckStats
877
  {
878
    boost::circular_buffer<bool> d_lastResults;
879
    time_t d_nextCheck{0};
880
    enum class LazyStatus: uint8_t { Healthy = 0, PotentialFailure, Failed };
881
    LazyStatus d_status{LazyStatus::Healthy};
882
  };
883
  LockGuarded<LazyHealthCheckStats> d_lazyHealthCheckStats;
884
885
public:
886
  std::shared_ptr<TLSCtx> d_tlsCtx{nullptr};
887
  std::vector<int> sockets;
888
  StopWatch sw;
889
  QPSLimiter qps;
890
  std::atomic<uint64_t> idOffset{0};
891
  size_t socketsOffset{0};
892
  double latencyUsec{0.0};
893
  double latencyUsecTCP{0.0};
894
  unsigned int d_nextCheck{0};
895
  uint16_t currentCheckFailures{0};
896
  uint8_t consecutiveSuccessfulChecks{0};
897
  std::atomic<bool> hashesComputed{false};
898
  std::atomic<bool> connected{false};
899
  bool upStatus{false};
900
901
private:
902
  void connectUDPSockets();
903
904
  std::thread tid;
905
  std::mutex connectLock;
906
  std::atomic_flag threadStarted;
907
  bool d_stopped{false};
908
public:
909
910
  void start();
911
912
  bool isUp() const
913
0
  {
914
0
    if (d_config.availability == Availability::Down) {
915
0
      return false;
916
0
    }
917
0
    else if (d_config.availability == Availability::Up) {
918
0
      return true;
919
0
    }
920
0
    return upStatus;
921
0
  }
922
923
0
  void setUp() {
924
0
    d_config.availability = Availability::Up;
925
0
  }
926
927
  void setUpStatus(bool newStatus)
928
0
  {
929
0
    upStatus = newStatus;
930
0
    if (!upStatus) {
931
0
      latencyUsec = 0.0;
932
0
      latencyUsecTCP = 0.0;
933
0
    }
934
0
  }
935
  void setDown()
936
0
  {
937
0
    d_config.availability = Availability::Down;
938
0
    latencyUsec = 0.0;
939
0
    latencyUsecTCP = 0.0;
940
0
  }
941
0
  void setAuto() {
942
0
    d_config.availability = Availability::Auto;
943
0
  }
944
0
  void setLazyAuto() {
945
0
    d_config.availability = Availability::Lazy;
946
0
    d_lazyHealthCheckStats.lock()->d_lastResults.set_capacity(d_config.d_lazyHealthCheckSampleSize);
947
0
  }
948
  bool healthCheckRequired(std::optional<time_t> currentTime = std::nullopt);
949
950
0
  const string& getName() const {
951
0
    return d_config.name;
952
0
  }
953
0
  const string& getNameWithAddr() const {
954
0
    return d_config.nameWithAddr;
955
0
  }
956
  void setName(const std::string& newName)
957
0
  {
958
0
    d_config.name = newName;
959
0
    d_config.nameWithAddr = newName.empty() ? d_config.remote.toStringWithPort() : (d_config.name + " (" + d_config.remote.toStringWithPort()+ ")");
960
0
  }
961
962
  string getStatus() const
963
0
  {
964
0
    string status;
965
0
    if (d_config.availability == DownstreamState::Availability::Up) {
966
0
      status = "UP";
967
0
    }
968
0
    else if (d_config.availability == DownstreamState::Availability::Down) {
969
0
      status = "DOWN";
970
0
    }
971
0
    else {
972
0
      status = (upStatus ? "up" : "down");
973
0
    }
974
0
    return status;
975
0
  }
976
977
  bool reconnect();
978
  void hash();
979
  void setId(const boost::uuids::uuid& newId);
980
  void setWeight(int newWeight);
981
  void stop();
982
  bool isStopped() const
983
0
  {
984
0
    return d_stopped;
985
0
  }
986
  const boost::uuids::uuid& getID() const
987
0
  {
988
0
    return *d_config.id;
989
0
  }
990
991
  void updateTCPMetrics(size_t nbQueries, uint64_t durationMs)
992
0
  {
993
0
    tcpAvgQueriesPerConnection = (99.0 * tcpAvgQueriesPerConnection / 100.0) + (nbQueries / 100.0);
994
0
    tcpAvgConnectionDuration = (99.0 * tcpAvgConnectionDuration / 100.0) + (durationMs / 100.0);
995
0
  }
996
997
  void updateTCPLatency(double udiff)
998
0
  {
999
0
    latencyUsecTCP = (127.0 * latencyUsecTCP / 128.0) + udiff / 128.0;
1000
0
  }
1001
1002
  void incQueriesCount()
1003
0
  {
1004
0
    ++queries;
1005
0
    qps.addHit();
1006
0
  }
1007
1008
  void incCurrentConnectionsCount();
1009
1010
  bool doHealthcheckOverTCP() const
1011
0
  {
1012
0
    return d_config.d_tcpOnly || d_config.d_tcpCheck || d_tlsCtx != nullptr;
1013
0
  }
1014
1015
  bool isTCPOnly() const
1016
0
  {
1017
0
    return d_config.d_tcpOnly || d_tlsCtx != nullptr;
1018
0
  }
1019
1020
  bool isDoH() const
1021
0
  {
1022
0
    return !d_config.d_dohPath.empty();
1023
0
  }
1024
1025
  bool passCrossProtocolQuery(std::unique_ptr<CrossProtocolQuery>&& cpq);
1026
  int pickSocketForSending();
1027
  void pickSocketsReadyForReceiving(std::vector<int>& ready);
1028
  void handleUDPTimeouts();
1029
  void reportTimeoutOrError();
1030
  void reportResponse(uint8_t rcode);
1031
  void submitHealthCheckResult(bool initial, bool newState);
1032
  time_t getNextLazyHealthCheck();
1033
  uint16_t saveState(InternalQueryState&&);
1034
  void restoreState(uint16_t id, InternalQueryState&&);
1035
  std::optional<InternalQueryState> getState(uint16_t id);
1036
1037
  dnsdist::Protocol getProtocol() const
1038
0
  {
1039
0
    if (isDoH()) {
1040
0
      return dnsdist::Protocol::DoH;
1041
0
    }
1042
0
    if (d_tlsCtx != nullptr) {
1043
0
      return dnsdist::Protocol::DoT;
1044
0
    }
1045
0
    if (isTCPOnly()) {
1046
0
      return dnsdist::Protocol::DoTCP;
1047
0
    }
1048
0
    return dnsdist::Protocol::DoUDP;
1049
0
  }
1050
1051
  double getRelevantLatencyUsec() const
1052
0
  {
1053
0
    if (isTCPOnly()) {
1054
0
      return latencyUsecTCP;
1055
0
    }
1056
0
    return latencyUsec;
1057
0
  }
1058
1059
  static int s_udpTimeout;
1060
  static bool s_randomizeSockets;
1061
  static bool s_randomizeIDs;
1062
private:
1063
  void handleUDPTimeout(IDState& ids);
1064
  void updateNextLazyHealthCheck(LazyHealthCheckStats& stats, bool checkScheduled, std::optional<time_t> currentTime = std::nullopt);
1065
};
1066
using servers_t = vector<std::shared_ptr<DownstreamState>>;
1067
1068
void responderThread(std::shared_ptr<DownstreamState> state);
1069
extern LockGuarded<LuaContext> g_lua;
1070
extern std::string g_outputBuffer; // locking for this is ok, as locked by g_luamutex
1071
1072
class DNSRule
1073
{
1074
public:
1075
  virtual ~DNSRule ()
1076
0
  {
1077
0
  }
1078
  virtual bool matches(const DNSQuestion* dq) const =0;
1079
  virtual string toString() const = 0;
1080
  mutable stat_t d_matches{0};
1081
};
1082
1083
struct ServerPool
1084
{
1085
  ServerPool(): d_servers(std::make_shared<const ServerPolicy::NumberedServerVector>())
1086
0
  {
1087
0
  }
1088
1089
  ~ServerPool()
1090
0
  {
1091
0
  }
1092
1093
0
  const std::shared_ptr<DNSDistPacketCache> getCache() const { return packetCache; };
1094
1095
  bool getECS() const
1096
0
  {
1097
0
    return d_useECS;
1098
0
  }
1099
1100
  void setECS(bool useECS)
1101
0
  {
1102
0
    d_useECS = useECS;
1103
0
  }
1104
1105
  std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
1106
  std::shared_ptr<ServerPolicy> policy{nullptr};
1107
1108
  size_t poolLoad();
1109
  size_t countServers(bool upOnly);
1110
  const std::shared_ptr<const ServerPolicy::NumberedServerVector> getServers();
1111
  void addServer(shared_ptr<DownstreamState>& server);
1112
  void removeServer(shared_ptr<DownstreamState>& server);
1113
1114
private:
1115
  SharedLockGuarded<std::shared_ptr<const ServerPolicy::NumberedServerVector>> d_servers;
1116
  bool d_useECS{false};
1117
};
1118
1119
enum ednsHeaderFlags {
1120
  EDNS_HEADER_FLAG_NONE = 0,
1121
  EDNS_HEADER_FLAG_DO = 32768
1122
};
1123
1124
struct DNSDistRuleAction
1125
{
1126
  std::shared_ptr<DNSRule> d_rule;
1127
  std::shared_ptr<DNSAction> d_action;
1128
  std::string d_name;
1129
  boost::uuids::uuid d_id;
1130
  uint64_t d_creationOrder;
1131
};
1132
1133
struct DNSDistResponseRuleAction
1134
{
1135
  std::shared_ptr<DNSRule> d_rule;
1136
  std::shared_ptr<DNSResponseAction> d_action;
1137
  std::string d_name;
1138
  boost::uuids::uuid d_id;
1139
  uint64_t d_creationOrder;
1140
};
1141
1142
extern GlobalStateHolder<SuffixMatchTree<DynBlock>> g_dynblockSMT;
1143
extern DNSAction::Action g_dynBlockAction;
1144
1145
extern GlobalStateHolder<ServerPolicy> g_policy;
1146
extern GlobalStateHolder<servers_t> g_dstates;
1147
extern GlobalStateHolder<pools_t> g_pools;
1148
extern GlobalStateHolder<vector<DNSDistRuleAction> > g_ruleactions;
1149
extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_respruleactions;
1150
extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_cachehitrespruleactions;
1151
extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_selfansweredrespruleactions;
1152
extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_cacheInsertedRespRuleActions;
1153
extern GlobalStateHolder<NetmaskGroup> g_ACL;
1154
1155
extern ComboAddress g_serverControl; // not changed during runtime
1156
1157
extern std::vector<shared_ptr<TLSFrontend>> g_tlslocals;
1158
extern std::vector<shared_ptr<DOHFrontend>> g_dohlocals;
1159
extern std::vector<std::unique_ptr<ClientState>> g_frontends;
1160
extern bool g_truncateTC;
1161
extern bool g_fixupCase;
1162
extern int g_tcpRecvTimeout;
1163
extern int g_tcpSendTimeout;
1164
extern uint16_t g_maxOutstanding;
1165
extern std::atomic<bool> g_configurationDone;
1166
extern boost::optional<uint64_t> g_maxTCPClientThreads;
1167
extern uint64_t g_maxTCPQueuedConnections;
1168
extern size_t g_maxTCPQueriesPerConn;
1169
extern size_t g_maxTCPConnectionDuration;
1170
extern size_t g_tcpInternalPipeBufferSize;
1171
extern pdns::stat16_t g_cacheCleaningDelay;
1172
extern pdns::stat16_t g_cacheCleaningPercentage;
1173
extern uint32_t g_staleCacheEntriesTTL;
1174
extern bool g_apiReadWrite;
1175
extern std::string g_apiConfigDirectory;
1176
extern bool g_servFailOnNoPolicy;
1177
extern size_t g_udpVectorSize;
1178
extern bool g_allowEmptyResponse;
1179
extern uint32_t g_socketUDPSendBuffer;
1180
extern uint32_t g_socketUDPRecvBuffer;
1181
1182
extern shared_ptr<BPFFilter> g_defaultBPFFilter;
1183
extern std::vector<std::shared_ptr<DynBPFFilter> > g_dynBPFFilters;
1184
1185
struct LocalHolders
1186
{
1187
  LocalHolders(): acl(g_ACL.getLocal()), policy(g_policy.getLocal()), ruleactions(g_ruleactions.getLocal()), cacheHitRespRuleactions(g_cachehitrespruleactions.getLocal()), cacheInsertedRespRuleActions(g_cacheInsertedRespRuleActions.getLocal()), selfAnsweredRespRuleactions(g_selfansweredrespruleactions.getLocal()), servers(g_dstates.getLocal()), dynNMGBlock(g_dynblockNMG.getLocal()), dynSMTBlock(g_dynblockSMT.getLocal()), pools(g_pools.getLocal())
1188
0
  {
1189
0
  }
1190
1191
  LocalStateHolder<NetmaskGroup> acl;
1192
  LocalStateHolder<ServerPolicy> policy;
1193
  LocalStateHolder<vector<DNSDistRuleAction> > ruleactions;
1194
  LocalStateHolder<vector<DNSDistResponseRuleAction> > cacheHitRespRuleactions;
1195
  LocalStateHolder<vector<DNSDistResponseRuleAction> > cacheInsertedRespRuleActions;
1196
  LocalStateHolder<vector<DNSDistResponseRuleAction> > selfAnsweredRespRuleactions;
1197
  LocalStateHolder<servers_t> servers;
1198
  LocalStateHolder<NetmaskTree<DynBlock, AddressAndPortRange> > dynNMGBlock;
1199
  LocalStateHolder<SuffixMatchTree<DynBlock> > dynSMTBlock;
1200
  LocalStateHolder<pools_t> pools;
1201
};
1202
1203
void tcpAcceptorThread(std::vector<ClientState*> states);
1204
1205
#ifdef HAVE_DNS_OVER_HTTPS
1206
void dohThread(ClientState* cs);
1207
#endif /* HAVE_DNS_OVER_HTTPS */
1208
1209
void setLuaNoSideEffect(); // if nothing has been declared, set that there are no side effects
1210
void setLuaSideEffect();   // set to report a side effect, cancelling all _no_ side effect calls
1211
bool getLuaNoSideEffect(); // set if there were only explicit declarations of _no_ side effect
1212
void resetLuaSideEffect(); // reset to indeterminate state
1213
1214
bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const std::shared_ptr<DownstreamState>& remote, unsigned int& qnameWireLength);
1215
1216
bool checkQueryHeaders(const struct dnsheader* dh, ClientState& cs);
1217
1218
extern std::vector<std::shared_ptr<DNSCryptContext>> g_dnsCryptLocals;
1219
int handleDNSCryptQuery(PacketBuffer& packet, DNSCryptQuery& query, bool tcp, time_t now, PacketBuffer& response);
1220
bool checkDNSCryptQuery(const ClientState& cs, PacketBuffer& query, std::unique_ptr<DNSCryptQuery>& dnsCryptQuery, time_t now, bool tcp);
1221
1222
#include "dnsdist-snmp.hh"
1223
1224
extern bool g_snmpEnabled;
1225
extern bool g_snmpTrapsEnabled;
1226
extern DNSDistSNMPAgent* g_snmpAgent;
1227
extern bool g_addEDNSToSelfGeneratedResponses;
1228
1229
extern std::set<std::string> g_capabilitiesToRetain;
1230
static const uint16_t s_udpIncomingBufferSize{1500}; // don't accept UDP queries larger than this value
1231
static const size_t s_maxPacketCacheEntrySize{4096}; // don't cache responses larger than this value
1232
1233
enum class ProcessQueryResult : uint8_t { Drop, SendAnswer, PassToBackend, Asynchronous };
1234
ProcessQueryResult processQuery(DNSQuestion& dq, LocalHolders& holders, std::shared_ptr<DownstreamState>& selectedBackend);
1235
ProcessQueryResult processQueryAfterRules(DNSQuestion& dq, LocalHolders& holders, std::shared_ptr<DownstreamState>& selectedBackend);
1236
bool processResponse(PacketBuffer& response, const std::vector<DNSDistResponseRuleAction>& respRuleActions, const std::vector<DNSDistResponseRuleAction>& insertedRespRuleActions, DNSResponse& dr, bool muted);
1237
bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::string& ruleresult, bool& drop);
1238
bool processResponseAfterRules(PacketBuffer& response, const std::vector<DNSDistResponseRuleAction>& cacheInsertedRespRuleActions, DNSResponse& dr, bool muted);
1239
1240
bool assignOutgoingUDPQueryToBackend(std::shared_ptr<DownstreamState>& ds, uint16_t queryID, DNSQuestion& dq, PacketBuffer& query, ComboAddress& dest);
1241
1242
ssize_t udpClientSendRequestToBackend(const std::shared_ptr<DownstreamState>& ss, const int sd, const PacketBuffer& request, bool healthCheck = false);
1243
bool sendUDPResponse(int origFD, const PacketBuffer& response, const int delayMsec, const ComboAddress& origDest, const ComboAddress& origRemote);
1244
void handleResponseSent(const DNSName& qname, const QType& qtype, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol outgoingProtocol, dnsdist::Protocol incomingProtocol, bool fromBackend);
1245
void handleResponseSent(const InternalQueryState& ids, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol outgoingProtocol, bool fromBackend);