]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnsdist.hh
documentation of blockFilter was out of date
[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>
ecbe9133 13#include "sholder.hh"
11e1e08b 14#include "dnscrypt.hh"
886e2cf2 15#include "dnsdist-cache.hh"
85c7ca75 16#include "gettime.hh"
1ea747c0 17
d8c19b98
RG
18#ifdef HAVE_PROTOBUF
19#include <boost/uuid/uuid.hpp>
20#include <boost/uuid/uuid_generators.hpp>
21#endif
22
42fae326 23void* carbonDumpThread();
61d1b966 24uint64_t uptimeOfProcess(const std::string& str);
bd1c631b 25
78ffa782 26struct DynBlock
27{
28 DynBlock& operator=(const DynBlock& rhs)
29 {
30 reason=rhs.reason;
31 until=rhs.until;
32 blocks.store(rhs.blocks);
33 return *this;
34 }
35
36 string reason;
37 struct timespec until;
38 mutable std::atomic<unsigned int> blocks;
39};
40
41extern GlobalStateHolder<NetmaskTree<DynBlock>> g_dynblockNMG;
f758857a 42
43extern vector<pair<struct timeval, std::string> > g_confDelta;
44
e48090d1 45struct DNSDistStats
46{
6ad8b29a 47 using stat_t=std::atomic<uint64_t>; // aww yiss ;-)
e48090d1 48 stat_t responses{0};
49 stat_t servfailResponses{0};
50 stat_t queries{0};
e73ec7d3 51 stat_t nonCompliantQueries{0};
d08b1cdf 52 stat_t nonCompliantResponses{0};
643a182a 53 stat_t rdQueries{0};
2efd427d 54 stat_t emptyQueries{0};
e48090d1 55 stat_t aclDrops{0};
56 stat_t blockFilter{0};
bd1c631b 57 stat_t dynBlocked{0};
e48090d1 58 stat_t ruleDrop{0};
59 stat_t ruleNXDomain{0};
60 stat_t selfAnswered{0};
61 stat_t downstreamTimeouts{0};
62 stat_t downstreamSendErrors{0};
6ad8b29a 63 stat_t truncFail{0};
b8bc7e61 64 stat_t noPolicy{0};
886e2cf2
RG
65 stat_t cacheHits{0};
66 stat_t cacheMisses{0};
42fae326 67 stat_t latency0_1{0}, latency1_10{0}, latency10_50{0}, latency50_100{0}, latency100_1000{0}, latencySlow{0};
e48090d1 68
e16fd59c 69 double latencyAvg100{0}, latencyAvg1000{0}, latencyAvg10000{0}, latencyAvg1000000{0};
a1a787dc 70 typedef std::function<uint64_t(const std::string&)> statfunction_t;
71 typedef boost::variant<stat_t*, double*, statfunction_t> entry_t;
e16fd59c 72 std::vector<std::pair<std::string, entry_t>> entries{
42fae326 73 {"responses", &responses}, {"servfail-responses", &servfailResponses},
74 {"queries", &queries}, {"acl-drops", &aclDrops},
75 {"block-filter", &blockFilter}, {"rule-drop", &ruleDrop},
76 {"rule-nxdomain", &ruleNXDomain}, {"self-answered", &selfAnswered},
77 {"downstream-timeouts", &downstreamTimeouts}, {"downstream-send-errors", &downstreamSendErrors},
78 {"trunc-failures", &truncFail}, {"no-policy", &noPolicy},
79 {"latency0-1", &latency0_1}, {"latency1-10", &latency1_10},
80 {"latency10-50", &latency10_50}, {"latency50-100", &latency50_100},
e16fd59c 81 {"latency100-1000", &latency100_1000}, {"latency-slow", &latencySlow},
82 {"latency-avg100", &latencyAvg100}, {"latency-avg1000", &latencyAvg1000},
a1a787dc 83 {"latency-avg10000", &latencyAvg10000}, {"latency-avg1000000", &latencyAvg1000000},
61d1b966 84 {"uptime", uptimeOfProcess},
a9b6db56 85 {"real-memory-usage", getRealMemoryUsage},
a2aa00ed 86 {"noncompliant-queries", &nonCompliantQueries},
d08b1cdf 87 {"noncompliant-responses", &nonCompliantResponses},
643a182a 88 {"rdqueries", &rdQueries},
2efd427d 89 {"empty-queries", &emptyQueries},
886e2cf2
RG
90 {"cache-hits", &cacheHits},
91 {"cache-misses", &cacheMisses},
4f99f3d3
RG
92 {"cpu-user-msec", getCPUTimeUser},
93 {"cpu-sys-msec", getCPUTimeSystem},
bd1c631b 94 {"fd-usage", getOpenFileDescriptors}, {"dyn-blocked", &dynBlocked},
95 {"dyn-block-nmg-size", [](const std::string&) { return g_dynblockNMG.getLocal()->size(); }}
42fae326 96 };
e48090d1 97};
98
e16fd59c 99
e48090d1 100extern struct DNSDistStats g_stats;
101
638184e9 102
df111b53 103struct StopWatch
104{
df111b53 105 struct timespec d_start{0,0};
106 void start() {
85c7ca75 107 if(gettime(&d_start) < 0)
df111b53 108 unixDie("Getting timestamp");
109
110 }
111
112 double udiff() const {
113 struct timespec now;
85c7ca75 114 if(gettime(&now) < 0)
df111b53 115 unixDie("Getting timestamp");
116
117 return 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0;
118 }
119
120 double udiffAndSet() {
121 struct timespec now;
85c7ca75 122 if(gettime(&now) < 0)
df111b53 123 unixDie("Getting timestamp");
124
125 auto ret= 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0;
126 d_start = now;
127 return ret;
128 }
129
130};
131
132class QPSLimiter
133{
134public:
135 QPSLimiter()
136 {
137 }
138
139 QPSLimiter(unsigned int rate, unsigned int burst) : d_rate(rate), d_burst(burst), d_tokens(burst)
140 {
141 d_passthrough=false;
142 d_prev.start();
143 }
144
145 unsigned int getRate() const
146 {
147 return d_passthrough? 0 : d_rate;
148 }
149
150 int getPassed() const
151 {
152 return d_passed;
153 }
154 int getBlocked() const
155 {
156 return d_blocked;
157 }
158
ecbe9133 159 bool check() const // this is not quite fair
df111b53 160 {
161 if(d_passthrough)
162 return true;
163 auto delta = d_prev.udiffAndSet();
164
165 d_tokens += 1.0*d_rate * (delta/1000000.0);
166
167 if(d_tokens > d_burst)
168 d_tokens = d_burst;
169
170 bool ret=false;
171 if(d_tokens >= 1.0) { // we need this because burst=1 is weird otherwise
172 ret=true;
173 --d_tokens;
174 d_passed++;
175 }
176 else
177 d_blocked++;
178
179 return ret;
180 }
181private:
182 bool d_passthrough{true};
183 unsigned int d_rate;
184 unsigned int d_burst;
ecbe9133 185 mutable double d_tokens;
186 mutable StopWatch d_prev;
187 mutable unsigned int d_passed{0};
188 mutable unsigned int d_blocked{0};
df111b53 189};
190
df111b53 191struct IDState
192{
c9ba8478 193 IDState() : origFD(-1), delayMsec(0) { origDest.sin4.sin_family = 0;}
df111b53 194 IDState(const IDState& orig)
195 {
196 origFD = orig.origFD;
197 origID = orig.origID;
198 origRemote = orig.origRemote;
549d63c9 199 origDest = orig.origDest;
7b3865cd 200 delayMsec = orig.delayMsec;
df111b53 201 age.store(orig.age.load());
202 }
203
2bf26975 204 int origFD; // set to <0 to indicate this state is empty // 4
205
206 ComboAddress origRemote; // 28
549d63c9 207 ComboAddress origDest; // 28
2bf26975 208 StopWatch sentTime; // 16
209 DNSName qname; // 80
11e1e08b
RG
210#ifdef HAVE_DNSCRYPT
211 std::shared_ptr<DnsCryptQuery> dnsCryptQuery{0};
d8c19b98
RG
212#endif
213#ifdef HAVE_PROTOBUF
214 boost::uuids::uuid uniqueId;
11e1e08b 215#endif
886e2cf2
RG
216 std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
217 uint32_t cacheKey; // 8
2bf26975 218 std::atomic<uint16_t> age; // 4
219 uint16_t qtype; // 2
886e2cf2 220 uint16_t qclass; // 2
2bf26975 221 uint16_t origID; // 2
aeb36780 222 uint16_t origFlags; // 2
7b3865cd 223 int delayMsec;
ca404e94 224 bool ednsAdded{false};
ff73f02b 225 bool ecsAdded{false};
886e2cf2 226 bool skipCache{false};
df111b53 227};
228
229struct Rings {
230 Rings()
231 {
df111b53 232 queryRing.set_capacity(10000);
233 respRing.set_capacity(10000);
0e41337b 234 pthread_rwlock_init(&queryLock, 0);
df111b53 235 }
0ba5eecf 236 struct Query
237 {
238 struct timespec when;
239 ComboAddress requestor;
240 DNSName name;
03ebf8b2 241 uint16_t size;
0ba5eecf 242 uint16_t qtype;
3fcaeeac 243 struct dnsheader dh;
0ba5eecf 244 };
245 boost::circular_buffer<Query> queryRing;
df111b53 246 struct Response
247 {
80a216c9 248 struct timespec when;
249 ComboAddress requestor;
df111b53 250 DNSName name;
251 uint16_t qtype;
df111b53 252 unsigned int usec;
80a216c9 253 unsigned int size;
3fcaeeac 254 struct dnsheader dh;
2d11d1b2 255 ComboAddress ds; // who handled it
df111b53 256 };
257 boost::circular_buffer<Response> respRing;
258 std::mutex respMutex;
0e41337b 259 pthread_rwlock_t queryLock;
03ebf8b2 260
7fc00937 261 std::unordered_map<int, vector<boost::variant<string,double> > > getTopBandwidth(unsigned int numentries);
a683e8bd 262 size_t numDistinctRequestors();
df111b53 263};
264
0e41337b 265extern Rings g_rings;
df111b53 266
8a5d5053 267struct ClientState
268{
269 ComboAddress local;
11e1e08b
RG
270#ifdef HAVE_DNSCRYPT
271 DnsCryptContext* dnscryptCtx{0};
272#endif
963bef8d 273 std::atomic<uint64_t> queries{0};
a36ce055
RG
274 int udpFD{-1};
275 int tcpFD{-1};
8a5d5053 276};
277
278class TCPClientCollection {
279 std::vector<int> d_tcpclientthreads;
a9bf3ec4 280 std::atomic<uint64_t> d_pos{0};
8a5d5053 281public:
a9bf3ec4 282 std::atomic<uint64_t> d_queued{0}, d_numthreads{0};
6c1ca990 283 uint64_t d_maxthreads{0};
8a5d5053 284
a9bf3ec4 285 TCPClientCollection(size_t maxThreads)
8a5d5053 286 {
6c1ca990 287 d_maxthreads = maxThreads;
a9bf3ec4 288 d_tcpclientthreads.reserve(maxThreads);
8a5d5053 289 }
290
a9bf3ec4 291 int getThread()
8a5d5053 292 {
6c1ca990 293 uint64_t pos = d_pos++;
8a5d5053 294 ++d_queued;
295 return d_tcpclientthreads[pos % d_numthreads];
296 }
297 void addTCPClientThread();
298};
299
a9bf3ec4 300extern std::shared_ptr<TCPClientCollection> g_tcpclientthreads;
8a5d5053 301
df111b53 302struct DownstreamState
303{
fbe2a2e0
RG
304 DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf);
305 DownstreamState(const ComboAddress& remote_): DownstreamState(remote_, ComboAddress(), 0) {}
6a62c0e3
RG
306 ~DownstreamState()
307 {
308 if (fd >= 0)
309 close(fd);
310 }
df111b53 311
f99e3aaf 312 int fd{-1};
df111b53 313 std::thread tid;
314 ComboAddress remote;
315 QPSLimiter qps;
316 vector<IDState> idStates;
fbe2a2e0
RG
317 ComboAddress sourceAddr;
318 DNSName checkName{"a.root-servers.net."};
319 QType checkType{QType::A};
df111b53 320 std::atomic<uint64_t> idOffset{0};
321 std::atomic<uint64_t> sendErrors{0};
322 std::atomic<uint64_t> outstanding{0};
323 std::atomic<uint64_t> reuseds{0};
324 std::atomic<uint64_t> queries{0};
325 struct {
326 std::atomic<uint64_t> sendErrors{0};
327 std::atomic<uint64_t> reuseds{0};
328 std::atomic<uint64_t> queries{0};
329 } prev;
18eeccc9 330 string name;
df111b53 331 double queryLoad{0.0};
332 double dropRate{0.0};
333 double latencyUsec{0.0};
334 int order{1};
335 int weight{1};
3f6d07a4
RG
336 int tcpRecvTimeout{30};
337 int tcpSendTimeout{30};
fbe2a2e0 338 unsigned int sourceItf{0};
3f6d07a4 339 uint16_t retries{5};
9e87dcb8
RG
340 uint8_t currentCheckFailures{0};
341 uint8_t maxCheckFailures{1};
df111b53 342 StopWatch sw;
343 set<string> pools;
344 enum class Availability { Up, Down, Auto} availability{Availability::Auto};
fbe2a2e0 345 bool mustResolve{false};
df111b53 346 bool upStatus{false};
ca404e94 347 bool useECS{false};
df111b53 348 bool isUp() const
349 {
350 if(availability == Availability::Down)
351 return false;
352 if(availability == Availability::Up)
353 return true;
354 return upStatus;
355 }
356 void setUp() { availability = Availability::Up; }
357 void setDown() { availability = Availability::Down; }
358 void setAuto() { availability = Availability::Auto; }
18eeccc9
RG
359 string getName() const {
360 if (name.empty()) {
361 return remote.toStringWithPort();
362 }
363 return name;
364 }
a7940c06 365 string getNameWithAddr() const {
366 if (name.empty()) {
367 return remote.toStringWithPort();
368 }
369 return name + " (" + remote.toStringWithPort()+ ")";
370 }
371
df111b53 372};
373using servers_t =vector<std::shared_ptr<DownstreamState>>;
df111b53 374
497a6e3a
RG
375struct DNSQuestion
376{
d8c19b98 377 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 378
d8c19b98
RG
379#ifdef HAVE_PROTOBUF
380 boost::uuids::uuid uniqueId;
381#endif
497a6e3a
RG
382 const DNSName* qname;
383 const uint16_t qtype;
cec47783 384 const uint16_t qclass;
497a6e3a
RG
385 const ComboAddress* local;
386 const ComboAddress* remote;
387 struct dnsheader* dh;
388 size_t size;
389 uint16_t len;
390 const bool tcp;
886e2cf2 391 bool skipCache{false};
497a6e3a
RG
392};
393
e91084ce 394typedef std::function<bool(const DNSQuestion*)> blockfilter_t;
da4e7813 395template <class T> using NumberedVector = std::vector<std::pair<unsigned int, T> >;
396
397void* responderThread(std::shared_ptr<DownstreamState> state);
398extern std::mutex g_luamutex;
399extern LuaContext g_lua;
400extern std::string g_outputBuffer; // locking for this is ok, as locked by g_luamutex
401
0940e4eb 402class DNSRule
403{
404public:
497a6e3a 405 virtual bool matches(const DNSQuestion* dq) const =0;
0940e4eb 406 virtual string toString() const = 0;
407 mutable std::atomic<uint64_t> d_matches{0};
408};
409
410/* so what could you do:
411 drop,
412 fake up nxdomain,
413 provide actual answer,
414 allow & and stop processing,
415 continue processing,
416 modify header: (servfail|refused|notimp), set TC=1,
417 send to pool */
418
419class DNSAction
420{
421public:
7b3865cd 422 enum class Action { Drop, Nxdomain, Spoof, Allow, HeaderModify, Pool, Delay, None};
497a6e3a 423 virtual Action operator()(DNSQuestion*, string* ruleresult) const =0;
0940e4eb 424 virtual string toString() const = 0;
cf6874ba 425 virtual std::unordered_map<string, double> getStats() const
426 {
427 return {{}};
428 }
0940e4eb 429};
430
8146444b
RG
431class DNSResponseAction
432{
433public:
434 enum class Action { None };
435 virtual Action operator()(DNSQuestion*, string* ruleresult) const =0;
436 virtual string toString() const = 0;
437};
438
da4e7813 439using NumberedServerVector = NumberedVector<shared_ptr<DownstreamState>>;
497a6e3a 440typedef std::function<shared_ptr<DownstreamState>(const NumberedServerVector& servers, const DNSQuestion*)> policyfunc_t;
df111b53 441
442struct ServerPolicy
443{
444 string name;
70a57b05 445 policyfunc_t policy;
df111b53 446};
447
886e2cf2
RG
448struct ServerPool
449{
450 const std::shared_ptr<DNSDistPacketCache> getCache() const { return packetCache; };
451
452 NumberedVector<shared_ptr<DownstreamState>> servers;
453 std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
454};
455using pools_t=map<std::string,std::shared_ptr<ServerPool>>;
456void addServerToPool(pools_t& pools, const string& poolName, std::shared_ptr<DownstreamState> server);
457void removeServerFromPool(pools_t& pools, const string& poolName, std::shared_ptr<DownstreamState> server);
458
42fae326 459struct CarbonConfig
460{
d617b22c 461 ComboAddress server;
42fae326 462 std::string ourname;
d617b22c 463 unsigned int interval;
42fae326 464};
465
ca404e94
RG
466enum ednsHeaderFlags {
467 EDNS_HEADER_FLAG_NONE = 0,
468 EDNS_HEADER_FLAG_DO = 32768
469};
470
d617b22c 471extern GlobalStateHolder<vector<CarbonConfig> > g_carbon;
ecbe9133 472extern GlobalStateHolder<ServerPolicy> g_policy;
473extern GlobalStateHolder<servers_t> g_dstates;
886e2cf2 474extern GlobalStateHolder<pools_t> g_pools;
0940e4eb 475extern GlobalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSAction> > > > g_rulactions;
8146444b 476extern GlobalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > > g_resprulactions;
638184e9 477extern GlobalStateHolder<NetmaskGroup> g_ACL;
2e72cc0e 478
ecbe9133 479extern ComboAddress g_serverControl; // not changed during runtime
480
4c34246d 481extern std::vector<std::tuple<ComboAddress, bool, bool>> g_locals; // not changed at runtime (we hope XXX)
963bef8d 482extern vector<ClientState*> g_frontends;
ecbe9133 483extern std::string g_key; // in theory needs locking
6ad8b29a 484extern bool g_truncateTC;
b29edbee 485extern bool g_fixupCase;
3f6d07a4
RG
486extern int g_tcpRecvTimeout;
487extern int g_tcpSendTimeout;
e41f8165
RG
488extern uint16_t g_maxOutstanding;
489extern std::atomic<bool> g_configurationDone;
6c1ca990
RG
490extern uint64_t g_maxTCPClientThreads;
491extern uint64_t g_maxTCPQueuedConnections;
886e2cf2 492extern std::atomic<uint16_t> g_cacheCleaningDelay;
ca404e94
RG
493extern uint16_t g_ECSSourcePrefixV4;
494extern uint16_t g_ECSSourcePrefixV6;
495extern bool g_ECSOverride;
9e87dcb8 496extern bool g_verboseHealthChecks;
1ea747c0 497extern uint32_t g_staleCacheEntriesTTL;
ca404e94 498
ecbe9133 499struct dnsheader;
500
501void controlThread(int fd, ComboAddress local);
839f3021 502vector<std::function<void(void)>> setupLua(bool client, const std::string& config);
886e2cf2
RG
503std::shared_ptr<ServerPool> getPool(const pools_t& pools, const std::string& poolName);
504std::shared_ptr<ServerPool> createPoolIfNotExists(pools_t& pools, const string& poolName);
505const NumberedServerVector& getDownstreamCandidates(const pools_t& pools, const std::string& poolName);
da4e7813 506
497a6e3a 507std::shared_ptr<DownstreamState> firstAvailable(const NumberedServerVector& servers, const DNSQuestion* dq);
ecbe9133 508
497a6e3a
RG
509std::shared_ptr<DownstreamState> leastOutstanding(const NumberedServerVector& servers, const DNSQuestion* dq);
510std::shared_ptr<DownstreamState> wrandom(const NumberedServerVector& servers, const DNSQuestion* dq);
511std::shared_ptr<DownstreamState> whashed(const NumberedServerVector& servers, const DNSQuestion* dq);
512std::shared_ptr<DownstreamState> roundrobin(const NumberedServerVector& servers, const DNSQuestion* dq);
520eb5a0 513int getEDNSZ(const char* packet, unsigned int len);
6ca7a40a 514void spoofResponseFromString(DNSQuestion& dq, const string& spoofContent);
ca404e94 515uint16_t getEDNSOptionCode(const char * packet, size_t len);
002decab 516void dnsdistWebserverThread(int sock, const ComboAddress& local, const string& password, const string& apiKey, const boost::optional<std::map<std::string, std::string> >&);
6885d4bf 517bool getMsgLen32(int fd, uint32_t* len);
518bool putMsgLen32(int fd, uint32_t len);
d8d85a30 519void* tcpAcceptorThread(void* p);
80a216c9 520
886e2cf2 521void moreLua(bool client);
ffb07158 522void doClient(ComboAddress server, const std::string& command);
523void doConsole();
524void controlClientThread(int fd, ComboAddress client);
525extern "C" {
526char** my_completion( const char * text , int start, int end);
527}
f758857a 528void setLuaNoSideEffect(); // if nothing has been declared, set that there are no side effects
529void setLuaSideEffect(); // set to report a side effect, cancelling all _no_ side effect calls
530bool getLuaNoSideEffect(); // set if there were only explicit declarations of _no_ side effect
531void resetLuaSideEffect(); // reset to indeterminate state
11e1e08b 532
fcffc585 533bool responseContentMatches(const char* response, const uint16_t responseLen, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& remote);
8146444b
RG
534bool processQuery(LocalStateHolder<NetmaskTree<DynBlock> >& localDynBlock, 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);
535bool processResponse(LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSResponseAction> > > >& localRespRulactions, DNSQuestion& dq);
ff73f02b 536bool 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 537void restoreFlags(struct dnsheader* dh, uint16_t origFlags);
fcffc585 538
11e1e08b 539#ifdef HAVE_DNSCRYPT
4c34246d 540extern std::vector<std::tuple<ComboAddress,DnsCryptContext,bool>> g_dnsCryptLocals;
11e1e08b
RG
541
542int handleDnsCryptQuery(DnsCryptContext* ctx, char* packet, uint16_t len, std::shared_ptr<DnsCryptQuery>& query, uint16_t* decryptedQueryLen, bool tcp, std::vector<uint8_t>& reponse);
0f72fd5c 543bool encryptResponse(char* response, uint16_t* responseLen, size_t responseSize, bool tcp, std::shared_ptr<DnsCryptQuery> dnsCryptQuery);
11e1e08b 544#endif