]>
Commit | Line | Data |
---|---|---|
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 | */ | |
32cdc494 | 22 | #pragma once |
00a19ff7 | 23 | #include <string> |
aebb81e4 | 24 | #include <atomic> |
3897b9e1 | 25 | #include "utility.hh" |
00a19ff7 BH |
26 | #include "dns.hh" |
27 | #include "qtype.hh" | |
28 | #include <vector> | |
29 | #include <set> | |
9ea28e46 | 30 | #include <unordered_set> |
00a19ff7 | 31 | #include <map> |
eefd15f9 BH |
32 | #include <cmath> |
33 | #include <iostream> | |
34 | #include <utility> | |
c836dc19 | 35 | #include "misc.hh" |
00a19ff7 | 36 | #include "lwres.hh" |
4898a348 | 37 | #include <boost/optional.hpp> |
d6d5dea7 | 38 | #include <boost/utility.hpp> |
9f6a31ff | 39 | #include "circular_buffer.hh" |
1d5b3ce6 | 40 | #include "sstuff.hh" |
9fdf67d5 | 41 | #include "recursor_cache.hh" |
1d5b3ce6 | 42 | #include "mtasker.hh" |
a9af3782 | 43 | #include "iputils.hh" |
e46b0f2f | 44 | #include "validate-recursor.hh" |
b40562da | 45 | #include "ednssubnet.hh" |
644dd1da | 46 | #include "filterpo.hh" |
39ce10b2 | 47 | #include "negcache.hh" |
5216ddcc | 48 | #include "proxy-protocol.hh" |
559b6c93 | 49 | #include "sholder.hh" |
a71665e5 | 50 | #include "histogram.hh" |
bd468718 | 51 | #include "stat_t.hh" |
2a17f6c6 | 52 | #include "tcpiohandler.hh" |
0f14442c | 53 | #include "rec-eventtrace.hh" |
2ed8065e | 54 | #include "logr.hh" |
7d3d2f4f | 55 | #include "rec-tcounters.hh" |
3e5667f9 | 56 | #include "ednsextendederror.hh" |
644dd1da | 57 | |
20642494 | 58 | #ifdef HAVE_CONFIG_H |
4898a348 | 59 | #include "config.h" |
20642494 PL |
60 | #endif |
61 | ||
4898a348 | 62 | #include <boost/uuid/uuid.hpp> |
b9fa43e0 OM |
63 | #ifdef HAVE_FSTRM |
64 | #include "fstrm_logger.hh" | |
65 | #endif /* HAVE_FSTRM */ | |
4898a348 | 66 | |
2b20e918 | 67 | extern GlobalStateHolder<SuffixMatchNode> g_xdnssec; |
559b6c93 PL |
68 | extern GlobalStateHolder<SuffixMatchNode> g_dontThrottleNames; |
69 | extern GlobalStateHolder<NetmaskGroup> g_dontThrottleNetmasks; | |
b4ae1398 | 70 | extern GlobalStateHolder<SuffixMatchNode> g_DoTToAuthNames; |
559b6c93 | 71 | |
c21f8271 OM |
72 | enum class AdditionalMode : uint8_t; // defined in rec-lua-conf.hh |
73 | ||
a3e7b735 | 74 | class RecursorLua4; |
620db2c8 | 75 | |
f688bbaa | 76 | using NsSet = std::unordered_map<DNSName, pair<vector<ComboAddress>, bool>>; |
49f076e8 | 77 | |
ccfadb6c | 78 | extern std::unique_ptr<NegCache> g_negCache; |
a0c1d047 | 79 | |
bb4bdbaf | 80 | class SyncRes : public boost::noncopyable |
00a19ff7 BH |
81 | { |
82 | public: | |
f8f66c91 OM |
83 | enum LogMode |
84 | { | |
85 | LogNone, | |
86 | Log, | |
87 | Store | |
88 | }; | |
32b3e0ef | 89 | using asyncresolve_t = std::function<LWResult::Result(const ComboAddress&, const DNSName&, int, bool, bool, int, struct timeval*, boost::optional<Netmask>&, const ResolveContext&, LWResult*, bool*)>; |
77499b05 | 90 | |
f8f66c91 OM |
91 | enum class HardenNXD |
92 | { | |
93 | No, | |
94 | DNSSEC, | |
95 | Yes | |
96 | }; | |
76e368a3 | 97 | |
718c531d OM |
98 | struct Context |
99 | { | |
100 | boost::optional<EDNSExtendedError> extendedError; | |
101 | vState state{vState::Indeterminate}; | |
102 | }; | |
103 | ||
f688bbaa | 104 | vState getDSRecords(const DNSName& zone, dsmap_t& dsMap, bool onlyTA, unsigned int depth, const string& prefix, bool bogusOnNXD = true, bool* foundCut = nullptr); |
1e332f68 | 105 | |
3337c2f7 | 106 | class AuthDomain |
a712cb56 | 107 | { |
3337c2f7 | 108 | public: |
f688bbaa | 109 | using records_t = multi_index_container< |
a712cb56 | 110 | DNSRecord, |
f8f66c91 | 111 | indexed_by< |
a712cb56 | 112 | ordered_non_unique< |
f8f66c91 OM |
113 | composite_key<DNSRecord, |
114 | member<DNSRecord, DNSName, &DNSRecord::d_name>, | |
115 | member<DNSRecord, uint16_t, &DNSRecord::d_type>>, | |
f688bbaa | 116 | composite_key_compare<std::less<>, std::less<>>>>>; |
3337c2f7 | 117 | |
a712cb56 | 118 | records_t d_records; |
3337c2f7 RG |
119 | vector<ComboAddress> d_servers; |
120 | DNSName d_name; | |
121 | bool d_rdForward{false}; | |
122 | ||
487a76b7 FM |
123 | bool operator==(const AuthDomain& rhs) const; |
124 | ||
f8f66c91 OM |
125 | [[nodiscard]] std::string print(const std::string& indent = "", |
126 | const std::string& indentLevel = " ") const; | |
08326ab9 | 127 | |
f4e0e6ff | 128 | int getRecords(const DNSName& qname, QType qtype, std::vector<DNSRecord>& records) const; |
f688bbaa | 129 | [[nodiscard]] bool isAuth() const |
3337c2f7 RG |
130 | { |
131 | return d_servers.empty(); | |
132 | } | |
f688bbaa | 133 | [[nodiscard]] bool isForward() const |
3337c2f7 RG |
134 | { |
135 | return !isAuth(); | |
136 | } | |
f688bbaa | 137 | [[nodiscard]] bool shouldRecurse() const |
3337c2f7 RG |
138 | { |
139 | return d_rdForward; | |
140 | } | |
f688bbaa | 141 | [[nodiscard]] const DNSName& getName() const |
3337c2f7 RG |
142 | { |
143 | return d_name; | |
144 | } | |
145 | ||
146 | private: | |
147 | void addSOA(std::vector<DNSRecord>& records) const; | |
a712cb56 RG |
148 | }; |
149 | ||
f688bbaa | 150 | using domainmap_t = std::unordered_map<DNSName, AuthDomain>; |
b9715061 | 151 | |
f8f66c91 OM |
152 | struct ThreadLocalStorage |
153 | { | |
a712cb56 RG |
154 | std::shared_ptr<domainmap_t> domainmap; |
155 | }; | |
156 | ||
f688bbaa | 157 | static void setDefaultLogMode(LogMode logmode) |
9065eb05 | 158 | { |
f688bbaa | 159 | s_lm = logmode; |
9065eb05 | 160 | } |
3a016e92 | 161 | |
10971f78 | 162 | OptLog LogObject(const string& prefix); |
3a016e92 | 163 | |
f688bbaa OM |
164 | static uint64_t doEDNSDump(int fileDesc); |
165 | static uint64_t doDumpNSSpeeds(int fileDesc); | |
166 | static uint64_t doDumpThrottleMap(int fileDesc); | |
167 | static uint64_t doDumpFailedServers(int fileDesc); | |
168 | static uint64_t doDumpNonResolvingNS(int fileDesc); | |
169 | static uint64_t doDumpSavedParentNSSets(int fileDesc); | |
170 | static uint64_t doDumpDoTProbeMap(int fileDesc); | |
4e45e5bc | 171 | |
d61b8a01 | 172 | static int getRootNS(struct timeval now, asyncresolve_t asyncCallback, unsigned int depth, Logr::log_t); |
9065eb05 RG |
173 | static void addDontQuery(const std::string& mask) |
174 | { | |
f688bbaa | 175 | if (!s_dontQuery) { |
2bbc9eb0 | 176 | s_dontQuery = std::make_unique<NetmaskGroup>(); |
f688bbaa | 177 | } |
9065eb05 RG |
178 | s_dontQuery->addMask(mask); |
179 | } | |
180 | static void addDontQuery(const Netmask& mask) | |
181 | { | |
f688bbaa | 182 | if (!s_dontQuery) { |
2bbc9eb0 | 183 | s_dontQuery = std::make_unique<NetmaskGroup>(); |
f688bbaa | 184 | } |
9065eb05 RG |
185 | s_dontQuery->addMask(mask); |
186 | } | |
187 | static void clearDontQuery() | |
188 | { | |
189 | s_dontQuery = nullptr; | |
190 | } | |
3d324e00 | 191 | static void parseEDNSSubnetAllowlist(const std::string& alist); |
2fe3354d CH |
192 | static void parseEDNSSubnetAddFor(const std::string& subnetlist); |
193 | static void addEDNSLocalSubnet(const std::string& subnet) | |
9065eb05 | 194 | { |
2fe3354d CH |
195 | s_ednslocalsubnets.addMask(subnet); |
196 | } | |
197 | static void addEDNSRemoteSubnet(const std::string& subnet) | |
198 | { | |
199 | s_ednsremotesubnets.addMask(subnet); | |
9065eb05 RG |
200 | } |
201 | static void addEDNSDomain(const DNSName& domain) | |
202 | { | |
203 | s_ednsdomains.add(domain); | |
204 | } | |
2fe3354d | 205 | static void clearEDNSLocalSubnets() |
9065eb05 | 206 | { |
2fe3354d CH |
207 | s_ednslocalsubnets.clear(); |
208 | } | |
209 | static void clearEDNSRemoteSubnets() | |
210 | { | |
211 | s_ednsremotesubnets.clear(); | |
9065eb05 RG |
212 | } |
213 | static void clearEDNSDomains() | |
214 | { | |
215 | s_ednsdomains = SuffixMatchNode(); | |
216 | } | |
03d26a97 OM |
217 | |
218 | static void pruneNSSpeeds(time_t limit); | |
219 | static uint64_t getNSSpeedsSize(); | |
f688bbaa | 220 | static void submitNSSpeed(const DNSName& server, const ComboAddress& address, int usec, const struct timeval& now); |
03d26a97 | 221 | static void clearNSSpeeds(); |
f688bbaa | 222 | static float getNSSpeed(const DNSName& server, const ComboAddress& address); |
03d26a97 | 223 | |
f8f66c91 OM |
224 | struct EDNSStatus |
225 | { | |
226 | EDNSStatus(const ComboAddress& arg) : | |
227 | address(arg) {} | |
f6001854 | 228 | ComboAddress address; |
3a016e92 | 229 | time_t ttd{0}; |
f8f66c91 OM |
230 | enum EDNSMode : uint8_t |
231 | { | |
232 | EDNSOK = 0, | |
233 | EDNSIGNORANT = 1, | |
234 | NOEDNS = 2 | |
235 | } mode{EDNSOK}; | |
a712cb56 | 236 | |
f688bbaa | 237 | [[nodiscard]] std::string toString() const |
f6001854 | 238 | { |
f8f66c91 | 239 | const std::array<std::string, 3> modes = {"OK", "Ignorant", "No"}; |
f688bbaa OM |
240 | auto umode = static_cast<unsigned int>(mode); |
241 | if (umode >= modes.size()) { | |
f6001854 OM |
242 | return "?"; |
243 | } | |
f688bbaa | 244 | return modes.at(umode); |
f6001854 OM |
245 | } |
246 | }; | |
247 | ||
248 | static EDNSStatus::EDNSMode getEDNSStatus(const ComboAddress& server); | |
249 | static uint64_t getEDNSStatusesSize(); | |
250 | static void clearEDNSStatuses(); | |
251 | static void pruneEDNSStatuses(time_t cutoff); | |
4d064b36 OM |
252 | |
253 | static uint64_t getThrottledServersSize(); | |
e0d0cce7 | 254 | static void pruneThrottledServers(time_t now); |
4d064b36 | 255 | static void clearThrottle(); |
e0d0cce7 | 256 | static bool isThrottled(time_t now, const ComboAddress& server, const DNSName& target, QType qtype); |
4d064b36 OM |
257 | static bool isThrottled(time_t now, const ComboAddress& server); |
258 | static void doThrottle(time_t now, const ComboAddress& server, time_t duration, unsigned int tries); | |
0e05dc93 | 259 | static void doThrottle(time_t now, const ComboAddress& server, const DNSName& name, QType qtype, time_t duration, unsigned int tries); |
314600f6 | 260 | static void unThrottle(const ComboAddress& server, const DNSName& qname, QType qtype); |
465c6d66 OM |
261 | |
262 | static uint64_t getFailedServersSize(); | |
263 | static void clearFailedServers(); | |
264 | static void pruneFailedServers(time_t cutoff); | |
265 | static unsigned long getServerFailsCount(const ComboAddress& server); | |
266 | ||
267 | static void clearNonResolvingNS(); | |
268 | static uint64_t getNonResolvingNSSize(); | |
269 | static void pruneNonResolving(time_t cutoff); | |
d2b4d7ad OM |
270 | |
271 | static void clearSaveParentsNSSets(); | |
272 | static size_t getSaveParentsNSSetsSize(); | |
273 | static void pruneSaveParentsNSSets(time_t now); | |
274 | ||
a66fd34f OM |
275 | static void pruneDoTProbeMap(time_t cutoff); |
276 | ||
a712cb56 RG |
277 | static void setDomainMap(std::shared_ptr<domainmap_t> newMap) |
278 | { | |
645b217b | 279 | t_sstorage.domainmap = std::move(newMap); |
a712cb56 | 280 | } |
f688bbaa | 281 | static std::shared_ptr<domainmap_t> getDomainMap() |
a712cb56 RG |
282 | { |
283 | return t_sstorage.domainmap; | |
284 | } | |
9065eb05 | 285 | |
8a3a3822 RG |
286 | static void setECSScopeZeroAddress(const Netmask& scopeZeroMask) |
287 | { | |
288 | s_ecsScopeZero.source = scopeZeroMask; | |
289 | } | |
290 | ||
c9783016 RG |
291 | static void clearECSStats() |
292 | { | |
293 | s_ecsqueries.store(0); | |
294 | s_ecsresponses.store(0); | |
295 | ||
296 | for (size_t idx = 0; idx < 32; idx++) { | |
297 | SyncRes::s_ecsResponsesBySubnetSize4[idx].store(0); | |
298 | } | |
299 | ||
300 | for (size_t idx = 0; idx < 128; idx++) { | |
301 | SyncRes::s_ecsResponsesBySubnetSize6[idx].store(0); | |
302 | } | |
303 | } | |
304 | ||
9065eb05 | 305 | explicit SyncRes(const struct timeval& now); |
30ee601a | 306 | |
f8f66c91 | 307 | int beginResolve(const DNSName& qname, QType qtype, QClass qclass, vector<DNSRecord>& ret, unsigned int depth = 0); |
378437c9 | 308 | bool tryDoT(const DNSName& qname, QType qtype, const DNSName& nsName, ComboAddress address, time_t); |
d8f3508b | 309 | |
cb273be5 | 310 | void setId(int threadid) |
c836dc19 | 311 | { |
cb273be5 OM |
312 | if (doLog()) { |
313 | d_prefix = "[" + std::to_string(threadid) + "] "; | |
314 | } | |
315 | } | |
316 | ||
317 | void setId(const string& prefix) | |
c836dc19 | 318 | { |
cb273be5 OM |
319 | if (doLog()) { |
320 | d_prefix = "[" + prefix + "] "; | |
321 | } | |
c836dc19 | 322 | } |
3ddb9247 | 323 | |
f688bbaa | 324 | void setLogMode(LogMode logmode) |
77499b05 | 325 | { |
f688bbaa | 326 | d_lm = logmode; |
77499b05 BH |
327 | } |
328 | ||
69cbdef9 | 329 | bool doLog() const |
c836dc19 | 330 | { |
3ddb9247 | 331 | return d_lm != LogNone; |
c836dc19 | 332 | } |
77499b05 | 333 | |
116d1288 | 334 | bool setCacheOnly(bool state = true) |
c836dc19 | 335 | { |
116d1288 OM |
336 | bool old = d_cacheonly; |
337 | d_cacheonly = state; | |
338 | return old; | |
339 | } | |
340 | ||
87c4554a OM |
341 | bool setRefreshAlmostExpired(bool doit) |
342 | { | |
343 | auto old = d_refresh; | |
344 | d_refresh = doit; | |
345 | return old; | |
346 | } | |
347 | ||
e2307ada | 348 | bool setQNameMinimization(bool state = true) |
116d1288 | 349 | { |
e2307ada OM |
350 | auto old = d_qNameMinimization; |
351 | d_qNameMinimization = state; | |
352 | return old; | |
c836dc19 | 353 | } |
2188dcc3 | 354 | |
52f994cd OM |
355 | bool setQMFallbackMode(bool state = true) |
356 | { | |
f943cd2f OM |
357 | auto old = d_qNameMinimizationFallbackMode; |
358 | d_qNameMinimizationFallbackMode = state; | |
52f994cd OM |
359 | return old; |
360 | } | |
361 | ||
362 | bool getQMFallbackMode() const | |
363 | { | |
f943cd2f | 364 | return d_qNameMinimizationFallbackMode; |
52f994cd | 365 | } |
f943cd2f | 366 | |
f8f66c91 | 367 | void setDoEDNS0(bool state = true) |
2188dcc3 | 368 | { |
f8f66c91 | 369 | d_doEDNS0 = state; |
2188dcc3 BH |
370 | } |
371 | ||
f8f66c91 | 372 | void setDoDNSSEC(bool state = true) |
30ee601a | 373 | { |
f8f66c91 | 374 | d_doDNSSEC = state; |
30ee601a RG |
375 | } |
376 | ||
f8f66c91 | 377 | void setDNSSECValidationRequested(bool requested = true) |
0c43f455 RG |
378 | { |
379 | d_DNSSECValidationRequested = requested; | |
380 | } | |
381 | ||
382 | bool isDNSSECValidationRequested() const | |
383 | { | |
384 | return d_DNSSECValidationRequested; | |
385 | } | |
386 | ||
e1636f82 RG |
387 | bool shouldValidate() const |
388 | { | |
389 | return d_DNSSECValidationRequested && !d_wasOutOfBand; | |
390 | } | |
391 | ||
f8f66c91 | 392 | void setWantsRPZ(bool state = true) |
30ee601a | 393 | { |
f8f66c91 | 394 | d_wantsRPZ = state; |
30ee601a RG |
395 | } |
396 | ||
397 | bool getWantsRPZ() const | |
398 | { | |
399 | return d_wantsRPZ; | |
400 | } | |
401 | ||
77499b05 BH |
402 | string getTrace() const |
403 | { | |
404 | return d_trace.str(); | |
405 | } | |
406 | ||
116d1288 OM |
407 | bool getQNameMinimization() const |
408 | { | |
409 | return d_qNameMinimization; | |
410 | } | |
411 | ||
a3e7b735 | 412 | void setLuaEngine(shared_ptr<RecursorLua4> pdl) |
3457a2a0 | 413 | { |
645b217b | 414 | d_pdl = std::move(pdl); |
3457a2a0 | 415 | } |
416 | ||
3762e821 | 417 | bool wasVariable() const |
418 | { | |
419 | return d_wasVariable; | |
420 | } | |
3457a2a0 | 421 | |
9fc36e90 PL |
422 | bool wasOutOfBand() const |
423 | { | |
424 | return d_wasOutOfBand; | |
425 | } | |
426 | ||
30ee601a RG |
427 | struct timeval getNow() const |
428 | { | |
429 | return d_now; | |
430 | } | |
431 | ||
44c4fc7a | 432 | // For debugging purposes |
f688bbaa | 433 | void setNow(const struct timeval& tval) |
44c4fc7a | 434 | { |
f688bbaa | 435 | d_now = tval; |
44c4fc7a OM |
436 | } |
437 | ||
f688bbaa | 438 | void setQuerySource(const ComboAddress& requestor, const boost::optional<const EDNSSubnetOpts&>& incomingECS); |
edabff75 | 439 | void setQuerySource(const Netmask& netmask); |
30ee601a | 440 | |
f688bbaa | 441 | void setInitialRequestId(const boost::optional<const boost::uuids::uuid&>& initialRequestId) |
30ee601a RG |
442 | { |
443 | d_initialRequestId = initialRequestId; | |
444 | } | |
63341e8d | 445 | |
3fe06137 | 446 | void setOutgoingProtobufServers(std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>>& servers) |
63341e8d | 447 | { |
b773359c | 448 | d_outgoingProtobufServers = servers; |
63341e8d | 449 | } |
30ee601a | 450 | |
b9fa43e0 | 451 | #ifdef HAVE_FSTRM |
10ba6d01 | 452 | void setFrameStreamServers(std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& servers) |
b9fa43e0 OM |
453 | { |
454 | d_frameStreamServers = servers; | |
455 | } | |
456 | #endif /* HAVE_FSTRM */ | |
457 | ||
30ee601a RG |
458 | void setAsyncCallback(asyncresolve_t func) |
459 | { | |
645b217b | 460 | d_asyncResolve = std::move(func); |
30ee601a | 461 | } |
3ddb9247 | 462 | |
4d2be65d RG |
463 | vState getValidationState() const |
464 | { | |
465 | return d_queryValidationState; | |
466 | } | |
467 | ||
d4f08082 RG |
468 | void setQueryReceivedOverTCP(bool tcp) |
469 | { | |
470 | d_queryReceivedOverTCP = tcp; | |
471 | } | |
472 | ||
cfbcc0f3 OM |
473 | static bool isUnsupported(QType qtype) |
474 | { | |
e7cc83fd OM |
475 | auto qcode = qtype.getCode(); |
476 | // rfc6895 section 3.1, note ANY is 255 and falls outside the range | |
477 | if (qcode >= QType::rfc6895MetaLowerBound && qcode <= QType::rfc6895MetaUpperBound) { | |
478 | return true; | |
479 | } | |
480 | switch (qcode) { | |
cfbcc0f3 | 481 | // Internal types |
e7cc83fd | 482 | case QType::ENT: // aka TYPE0 |
cfbcc0f3 | 483 | case QType::ADDR: |
e7cc83fd | 484 | // RFC |
bca5ab3a | 485 | case QType::rfc6895Reserved: |
e7cc83fd OM |
486 | // Other |
487 | case QType::RRSIG: | |
2cdafbde | 488 | case QType::NSEC3: // We use the same logic as for an auth: NSEC is queryable, NSEC3 not |
e7cc83fd | 489 | case QType::OPT: |
cfbcc0f3 OM |
490 | return true; |
491 | } | |
492 | return false; | |
493 | } | |
494 | ||
fa5f61e9 OM |
495 | static bool answerIsNOData(uint16_t requestedType, int rcode, const std::vector<DNSRecord>& records); |
496 | ||
a712cb56 RG |
497 | static thread_local ThreadLocalStorage t_sstorage; |
498 | ||
bd468718 RG |
499 | static pdns::stat_t s_ecsqueries; |
500 | static pdns::stat_t s_ecsresponses; | |
501 | static std::map<uint8_t, pdns::stat_t> s_ecsResponsesBySubnetSize4; | |
502 | static std::map<uint8_t, pdns::stat_t> s_ecsResponsesBySubnetSize6; | |
9065eb05 | 503 | |
9065eb05 RG |
504 | static string s_serverID; |
505 | static unsigned int s_minimumTTL; | |
5cf4b2e7 | 506 | static unsigned int s_minimumECSTTL; |
9065eb05 | 507 | static unsigned int s_maxqperq; |
a49b0b40 | 508 | static unsigned int s_maxnsperresolve; |
86f95f85 | 509 | static unsigned int s_maxnsaddressqperq; |
9065eb05 RG |
510 | static unsigned int s_maxtotusec; |
511 | static unsigned int s_maxdepth; | |
a9af3782 | 512 | static unsigned int s_maxnegttl; |
b9473937 | 513 | static unsigned int s_maxbogusttl; |
c3e753c7 | 514 | static unsigned int s_maxcachettl; |
1051f8a9 BH |
515 | static unsigned int s_packetcachettl; |
516 | static unsigned int s_packetcacheservfailttl; | |
91505918 | 517 | static unsigned int s_packetcachenegativettl; |
628e2c7b PA |
518 | static unsigned int s_serverdownmaxfails; |
519 | static unsigned int s_serverdownthrottletime; | |
e329b582 O |
520 | static unsigned int s_nonresolvingnsmaxfails; |
521 | static unsigned int s_nonresolvingnsthrottletime; | |
5fba6d59 | 522 | static unsigned int s_unthrottle_n; |
e7861cc4 | 523 | static unsigned int s_ecscachelimitttl; |
15e973d6 OM |
524 | static unsigned int s_maxvalidationsperq; |
525 | static unsigned int s_maxnsec3iterationsperq; | |
e9f9b8ec RG |
526 | static uint8_t s_ecsipv4limit; |
527 | static uint8_t s_ecsipv6limit; | |
fd8898fb | 528 | static uint8_t s_ecsipv4cachelimit; |
529 | static uint8_t s_ecsipv6cachelimit; | |
66535fce O |
530 | static bool s_ecsipv4nevercache; |
531 | static bool s_ecsipv6nevercache; | |
532 | ||
7b1d1a7d | 533 | static bool s_doIPv4; |
9065eb05 RG |
534 | static bool s_doIPv6; |
535 | static bool s_noEDNSPing; | |
536 | static bool s_noEDNS; | |
537 | static bool s_rootNXTrust; | |
116d1288 | 538 | static bool s_qnameminimization; |
d40a915b | 539 | static HardenNXD s_hardenNXD; |
87c4554a | 540 | static unsigned int s_refresh_ttlperc; |
55badaf8 | 541 | static unsigned int s_locked_ttlperc; |
2bc7ddac | 542 | static int s_tcp_fast_open; |
bffc1e7c | 543 | static bool s_tcp_fast_open_connect; |
7c36f101 | 544 | static bool s_dot_to_port_853; |
78deedda | 545 | static unsigned int s_max_busy_dot_probes; |
47571866 | 546 | static unsigned int s_max_CNAMES_followed; |
c88611d6 | 547 | static unsigned int s_max_minimize_count; |
3f15edc8 | 548 | static unsigned int s_minimize_one_label; |
0416940b O |
549 | |
550 | static const int event_trace_to_pb = 1; | |
551 | static const int event_trace_to_log = 2; | |
552 | static int s_event_trace_enabled; | |
1bb24087 | 553 | static bool s_save_parent_ns_set; |
3e5667f9 | 554 | static bool s_addExtendedResolutionDNSErrors; |
84d4747e | 555 | |
f8f66c91 | 556 | std::unordered_map<std::string, bool> d_discardedPolicies; |
a712cb56 | 557 | DNSFilterEngine::Policy d_appliedPolicy; |
b502d522 | 558 | std::unordered_set<std::string> d_policyTags; |
d6fd3cb8 | 559 | boost::optional<string> d_routingTag; |
e76b8a0d | 560 | ComboAddress d_fromAuthIP; |
0f14442c | 561 | RecEventTrace d_eventTrace; |
ab26d8d5 | 562 | std::shared_ptr<Logr::Logger> d_slog = g_slog->withName("syncres"); |
3e5667f9 | 563 | boost::optional<EDNSExtendedError> d_extendedError; |
d6fd3cb8 | 564 | |
f7b8cffa | 565 | unsigned int d_authzonequeries; |
a712cb56 RG |
566 | unsigned int d_outqueries; |
567 | unsigned int d_tcpoutqueries; | |
7c36f101 | 568 | unsigned int d_dotoutqueries; |
a712cb56 RG |
569 | unsigned int d_throttledqueries; |
570 | unsigned int d_timeouts; | |
571 | unsigned int d_unreachables; | |
572 | unsigned int d_totUsec; | |
992fc809 | 573 | unsigned int d_maxdepth{0}; |
f3493699 | 574 | // Initialized ony once, as opposed to d_now which gets updated after outgoing requests |
f688bbaa | 575 | struct timeval d_fixednow; |
49a699c4 | 576 | |
00a19ff7 | 577 | private: |
2fe3354d CH |
578 | ComboAddress d_requestor; |
579 | ComboAddress d_cacheRemote; | |
a712cb56 | 580 | |
2fe3354d CH |
581 | static NetmaskGroup s_ednslocalsubnets; |
582 | static NetmaskGroup s_ednsremotesubnets; | |
9065eb05 | 583 | static SuffixMatchNode s_ednsdomains; |
8a3a3822 | 584 | static EDNSSubnetOpts s_ecsScopeZero; |
9065eb05 RG |
585 | static LogMode s_lm; |
586 | static std::unique_ptr<NetmaskGroup> s_dontQuery; | |
f4e0e6ff | 587 | const static std::unordered_set<QType> s_redirectionQTypes; |
9065eb05 RG |
588 | |
589 | struct GetBestNSAnswer | |
590 | { | |
591 | DNSName qname; | |
f8f66c91 | 592 | set<pair<DNSName, DNSName>> bestns; |
6493dfc0 | 593 | uint8_t qtype; |
f688bbaa | 594 | bool operator<(const GetBestNSAnswer& bestAnswer) const |
9065eb05 | 595 | { |
f688bbaa | 596 | return std::tie(qtype, qname, bestns) < std::tie(bestAnswer.qtype, bestAnswer.qname, bestAnswer.bestns); |
9065eb05 RG |
597 | } |
598 | }; | |
599 | ||
f688bbaa | 600 | using zonesStates_t = std::map<DNSName, vState>; |
f8f66c91 OM |
601 | enum StopAtDelegation |
602 | { | |
603 | DontStop, | |
604 | Stop, | |
605 | Stopped | |
606 | }; | |
70b3fe7a | 607 | |
f688bbaa OM |
608 | void resolveAdditionals(const DNSName& qname, QType qtype, AdditionalMode mode, std::vector<DNSRecord>& additionals, unsigned int depth, bool& additionalsNotInCache); |
609 | void addAdditionals(QType qtype, const vector<DNSRecord>& start, vector<DNSRecord>& additionals, std::set<std::pair<DNSName, QType>>& uniqueCalls, std::set<std::tuple<DNSName, QType, QType>>& uniqueResults, unsigned int depth, unsigned int additionaldepth, bool& additionalsNotInCache); | |
f8f66c91 | 610 | bool addAdditionals(QType qtype, vector<DNSRecord>& ret, unsigned int depth); |
76e368a3 | 611 | |
0fd1030f | 612 | void updateQueryCounts(const string& prefix, const DNSName& qname, const ComboAddress& address, bool doTCP, bool doDoT); |
f688bbaa | 613 | static bool doDoTtoAuth(const DNSName& nameServer); |
f8f66c91 | 614 | int doResolveAt(NsSet& nameservers, DNSName auth, bool flawedNSSet, const DNSName& qname, QType qtype, vector<DNSRecord>& ret, |
192c0a72 | 615 | unsigned int depth, const string& prefix, set<GetBestNSAnswer>& beenthere, Context& context, StopAtDelegation* stopAtDelegation, |
6af46497 | 616 | std::map<DNSName, std::vector<ComboAddress>>* fallback); |
328c3547 | 617 | void ednsStats(boost::optional<Netmask>& ednsmask, const DNSName& qname, const string& prefix); |
f688bbaa OM |
618 | bool doResolveAtThisIP(const std::string& prefix, const DNSName& qname, QType qtype, LWResult& lwr, boost::optional<Netmask>& ednsmask, const DNSName& auth, bool sendRDQuery, bool wasForwarded, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool doDoT, bool& truncated, bool& spoofed, boost::optional<EDNSExtendedError>& extendedError, bool dontThrottle = false); |
619 | bool processAnswer(unsigned int depth, const string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, DNSName& auth, bool wasForwarded, const boost::optional<Netmask>& ednsmask, bool sendRDQuery, NsSet& nameservers, std::vector<DNSRecord>& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state, const ComboAddress& remoteIP); | |
f8f66c91 | 620 | |
718c531d | 621 | int doResolve(const DNSName& qname, QType qtype, vector<DNSRecord>& ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, Context& context); |
f688bbaa | 622 | int doResolveNoQNameMinimization(const DNSName& qname, QType qtype, vector<DNSRecord>& ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, Context& context, bool* fromCache = nullptr, StopAtDelegation* stopAtDelegation = nullptr); |
f8f66c91 | 623 | bool doOOBResolve(const AuthDomain& domain, const DNSName& qname, QType qtype, vector<DNSRecord>& ret, int& res); |
192c0a72 | 624 | bool doOOBResolve(const DNSName& qname, QType qtype, vector<DNSRecord>& ret, unsigned int depth, const string& prefix, int& res); |
f688bbaa OM |
625 | static bool isRecursiveForwardOrAuth(const DNSName& qname); |
626 | static bool isForwardOrAuth(const DNSName& qname); | |
627 | static domainmap_t::const_iterator getBestAuthZone(DNSName* qname); | |
e3f3c9a4 | 628 | bool doCNAMECacheCheck(const DNSName& qname, QType qtype, vector<DNSRecord>& ret, unsigned int depth, const string& prefix, int& res, Context& context, bool wasAuthZone, bool wasForwardRecurse, bool checkForDups); |
192c0a72 OM |
629 | bool doCacheCheck(const DNSName& qname, const DNSName& authname, bool wasForwardedOrAuthZone, bool wasAuthZone, bool wasForwardRecurse, QType qtype, vector<DNSRecord>& ret, unsigned int depth, const string& prefix, int& res, Context& context); |
630 | void getBestNSFromCache(const DNSName& qname, QType qtype, vector<DNSRecord>& bestns, bool* flawedNSSet, unsigned int depth, const string& prefix, set<GetBestNSAnswer>& beenthere, const boost::optional<DNSName>& cutOffDomain = boost::none); | |
631 | DNSName getBestNSNamesFromCache(const DNSName& qname, QType qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, const string& prefix, set<GetBestNSAnswer>& beenthere); | |
c5c066bf | 632 | |
baaa61a1 | 633 | vector<std::pair<DNSName, float>> shuffleInSpeedOrder(const DNSName& qname, NsSet& nameservers, const string& prefix); |
f688bbaa OM |
634 | vector<ComboAddress> shuffleForwardSpeed(const DNSName& qname, const vector<ComboAddress>& rnameservers, const string& prefix, bool wasRd); |
635 | static bool moreSpecificThan(const DNSName& lhs, const DNSName& rhs); | |
328c3547 | 636 | void selectNSOnSpeed(const DNSName& qname, const string& prefix, vector<ComboAddress>& ret); |
192c0a72 | 637 | vector<ComboAddress> getAddrs(const DNSName& qname, unsigned int depth, const string& prefix, set<GetBestNSAnswer>& beenthere, bool cacheOnly, unsigned int& addressQueriesForNS); |
26ca3513 | 638 | |
69cbdef9 RG |
639 | bool nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers); |
640 | bool nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress&); | |
c75d28f2 | 641 | void checkMaxQperQ(const DNSName& qname) const; |
22165a18 | 642 | bool throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, QType qtype, bool pierceDontQuery); |
26ca3513 | 643 | |
f688bbaa | 644 | vector<ComboAddress> retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, vector<std::pair<DNSName, float>>::const_iterator& tns, unsigned int depth, set<GetBestNSAnswer>& beenthere, const vector<std::pair<DNSName, float>>& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet, bool cacheOnly, unsigned int& nretrieveAddressesForNS); |
7155c3e5 | 645 | |
f688bbaa | 646 | void sanitizeRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, const DNSName& auth, bool wasForwarded, bool rdQuery); |
f8f66c91 OM |
647 | /* This function will check whether the answer should have the AA bit set, and will set if it should be set and isn't. |
648 | This is unfortunately needed to deal with very crappy so-called DNS servers */ | |
f688bbaa | 649 | void fixupAnswer(const std::string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, const DNSName& auth, bool wasForwarded, bool rdQuery); |
cb273be5 | 650 | void rememberParentSetIfNeeded(const DNSName& domain, const vector<DNSRecord>& newRecords, unsigned int depth, const string& prefix); |
f688bbaa OM |
651 | RCode::rcodes_ updateCacheFromRecords(unsigned int depth, const string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, const DNSName& auth, bool wasForwarded, const boost::optional<Netmask>&, vState& state, bool& needWildcardProof, bool& gatherWildcardProof, unsigned int& wildcardLabelsCount, bool sendRDQuery, const ComboAddress& remoteIP); |
652 | bool processRecords(const std::string& prefix, const DNSName& qname, QType qtype, const DNSName& auth, LWResult& lwr, bool sendRDQuery, vector<DNSRecord>& ret, set<DNSName>& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic, vState& state, bool needWildcardProof, bool gatherwildcardProof, unsigned int wildcardLabelsCount, int& rcode, bool& negIndicHasSignatures, unsigned int depth); | |
26ca3513 | 653 | |
f688bbaa | 654 | bool doSpecialNamesResolve(const DNSName& qname, QType qtype, QClass qclass, vector<DNSRecord>& ret); |
db50a7f4 | 655 | |
e8cf6180 | 656 | LWResult::Result asyncresolveWrapper(const ComboAddress& address, bool ednsMANDATORY, const DNSName& domain, const DNSName& auth, int type, bool doTCP, bool sendRDQuery, struct timeval* now, boost::optional<Netmask>& srcmask, LWResult* res, bool* chained, const DNSName& nsName) const; |
30ee601a | 657 | |
f688bbaa | 658 | boost::optional<Netmask> getEDNSSubnetMask(const DNSName& name, const ComboAddress& rem); |
e9f9b8ec | 659 | |
f688bbaa | 660 | static bool validationEnabled(); |
d06dcda4 | 661 | uint32_t computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, uint32_t signaturesTTL, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs) const; |
f688bbaa OM |
662 | void updateValidationState(const DNSName& qname, vState& state, vState stateUpdate, const string& prefix); |
663 | vState validateRecordsWithSigs(unsigned int depth, const string& prefix, const DNSName& qname, QType qtype, const DNSName& name, QType type, const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures); | |
d06dcda4 | 664 | vState validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, unsigned int depth, const string& prefix); |
cb273be5 | 665 | vState getDNSKeys(const DNSName& signer, skeyset_t& keys, bool& servFailOccurred, unsigned int depth, const string& prefix); |
f688bbaa OM |
666 | dState getDenialValidationState(const NegCache::NegCacheEntry& negEntry, dState expectedState, bool referralToUnsigned, const string& prefix); |
667 | void updateDenialValidationState(const DNSName& qname, vState& neValidationState, const DNSName& neName, vState& state, dState denialState, dState expectedState, bool isDS, unsigned int depth, const string& prefix); | |
668 | void computeNegCacheValidationStatus(const NegCache::NegCacheEntry& negEntry, const DNSName& qname, QType qtype, int res, vState& state, unsigned int depth, const string& prefix); | |
669 | vState getTA(const DNSName& zone, dsmap_t& dsMap, const string& prefix); | |
670 | vState getValidationStatus(const DNSName& name, bool wouldBeValid, bool typeIsDS, unsigned int depth, const string& prefix); | |
671 | void updateValidationStatusInCache(const DNSName& qname, QType qtype, bool aaFlag, vState newState) const; | |
10971f78 OM |
672 | void initZoneCutsFromTA(const DNSName& from, const string& prefix); |
673 | size_t countSupportedDS(const dsmap_t& dsmap, const string& prefix); | |
4d2be65d | 674 | |
07e812c7 | 675 | void handleNewTarget(const std::string& prefix, const DNSName& qname, const DNSName& newtarget, QType qtype, std::vector<DNSRecord>& ret, int& rcode, unsigned int depth, const std::vector<DNSRecord>& recordsFromAnswer, vState& state); |
d4f08082 | 676 | |
22165a18 | 677 | void handlePolicyHit(const std::string& prefix, const DNSName& qname, QType qtype, vector<DNSRecord>& ret, bool& done, int& rcode, unsigned int depth); |
07e812c7 | 678 | unsigned int getAdjustedRecursionBound() const; |
d4f08082 | 679 | |
0b29b9c5 RG |
680 | void setUpdatingRootNS() |
681 | { | |
682 | d_updatingRootNS = true; | |
683 | } | |
684 | ||
0498b0b6 OM |
685 | std::string getPrefix(unsigned int depth) const |
686 | { | |
687 | if (!doLog()) { | |
688 | return ""; | |
689 | } | |
690 | auto prefix = d_prefix; | |
691 | prefix.append(depth, ' '); | |
692 | return prefix; | |
693 | } | |
694 | ||
51b6b728 | 695 | zonesStates_t d_cutStates; |
77499b05 | 696 | ostringstream d_trace; |
a3e7b735 | 697 | shared_ptr<RecursorLua4> d_pdl; |
2fe3354d | 698 | boost::optional<Netmask> d_outgoingECSNetwork; |
2bbc9eb0 RP |
699 | std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>> d_outgoingProtobufServers; |
700 | std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>> d_frameStreamServers; | |
30ee601a | 701 | boost::optional<const boost::uuids::uuid&> d_initialRequestId; |
15e973d6 | 702 | pdns::validation::ValidationContext d_validationContext; |
30ee601a | 703 | asyncresolve_t d_asyncResolve{nullptr}; |
f3493699 | 704 | // d_now is initialized in the constructor and updates after outgoing requests in lwres.cc:asyncresolve |
30ee601a | 705 | struct timeval d_now; |
f08b5933 RG |
706 | /* if the client is asking for a DS that does not exist, we need to provide the SOA along with the NSEC(3) proof |
707 | and we might not have it if we picked up the proof from a delegation */ | |
708 | DNSName d_externalDSQuery; | |
c836dc19 | 709 | string d_prefix; |
98307d0f | 710 | vState d_queryValidationState{vState::Indeterminate}; |
b88526ce PL |
711 | |
712 | /* When d_cacheonly is set to true, we will only check the cache. | |
713 | * This is set when the RD bit is unset in the incoming query | |
714 | */ | |
c836dc19 | 715 | bool d_cacheonly; |
30ee601a | 716 | bool d_doDNSSEC; |
0c43f455 | 717 | bool d_DNSSECValidationRequested{false}; |
30ee601a | 718 | bool d_doEDNS0{true}; |
24bb9b58 | 719 | bool d_requireAuthData{true}; |
0b29b9c5 | 720 | bool d_updatingRootNS{false}; |
30ee601a RG |
721 | bool d_wantsRPZ{true}; |
722 | bool d_wasOutOfBand{false}; | |
723 | bool d_wasVariable{false}; | |
116d1288 | 724 | bool d_qNameMinimization{false}; |
f943cd2f | 725 | bool d_qNameMinimizationFallbackMode{false}; |
d4f08082 | 726 | bool d_queryReceivedOverTCP{false}; |
7373cea8 | 727 | bool d_followCNAME{true}; |
87c4554a | 728 | bool d_refresh{false}; |
6af46497 | 729 | bool d_serveStale{false}; |
f8f66c91 | 730 | |
77499b05 | 731 | LogMode d_lm; |
00a19ff7 | 732 | }; |
ac0e821b | 733 | |
a9af3782 | 734 | /* external functions, opaque to us */ |
66242d00 O |
735 | LWResult::Result asendtcp(const PacketBuffer& data, shared_ptr<TCPIOHandler>&); |
736 | LWResult::Result arecvtcp(PacketBuffer& data, size_t len, shared_ptr<TCPIOHandler>&, bool incompleteOkay); | |
1d5b3ce6 | 737 | |
f8f66c91 OM |
738 | enum TCPAction : uint8_t |
739 | { | |
740 | DoingRead, | |
741 | DoingWrite | |
742 | }; | |
4bcf780e | 743 | |
1d5b3ce6 BH |
744 | struct PacketID |
745 | { | |
3bf2e213 | 746 | PacketID() |
67770277 | 747 | { |
d38e2ba9 | 748 | remote.reset(); |
67770277 | 749 | } |
1d5b3ce6 | 750 | |
f8f66c91 OM |
751 | ComboAddress remote; // this is the remote |
752 | DNSName domain; // this is the question | |
1d5b3ce6 | 753 | |
2a17f6c6 O |
754 | PacketBuffer inMSG; // they'll go here |
755 | PacketBuffer outMSG; // the outgoing message that needs to be sent | |
1d5b3ce6 | 756 | |
f688bbaa | 757 | using chain_t = set<uint16_t>; |
96f81a93 | 758 | mutable chain_t chain; |
66242d00 | 759 | shared_ptr<TCPIOHandler> tcphandler{nullptr}; |
f8f66c91 | 760 | string::size_type inPos{0}; // how far are we along in the inMSG |
ea844a86 | 761 | size_t inWanted{0}; // if this is set, we'll read until inWanted bytes are read |
f8f66c91 | 762 | string::size_type outPos{0}; // how far we are along in the outMSG |
3bf2e213 O |
763 | mutable uint32_t nearMisses{0}; // number of near misses - host correct, id wrong |
764 | int fd{-1}; | |
f8f66c91 | 765 | int tcpsock{0}; // or wait for an event on a TCP fd |
3bf2e213 O |
766 | mutable bool closed{false}; // Processing already started, don't accept new chained ids |
767 | bool inIncompleteOkay{false}; | |
f8f66c91 OM |
768 | uint16_t id{0}; // wait for a specific id/remote pair |
769 | uint16_t type{0}; // and this is its type | |
f9bb1d3f OM |
770 | TCPAction highState{TCPAction::DoingRead}; |
771 | IOState lowState{IOState::NeedRead}; | |
35ce8576 | 772 | |
8b428a6b | 773 | bool operator<(const PacketID& /* b */) const |
1d5b3ce6 | 774 | { |
2d4ccdf5 | 775 | // We don't want explicit PacketID compare here, but always via predicate classes below |
f688bbaa | 776 | assert(0); // NOLINT: lib |
1d5b3ce6 BH |
777 | } |
778 | }; | |
779 | ||
f688bbaa | 780 | inline ostream& operator<<(ostream& ostr, const PacketID& pid) |
96f81a93 | 781 | { |
f688bbaa | 782 | return ostr << "PacketID(id=" << pid.id << ",remote=" << pid.remote.toString() << ",type=" << pid.type << ",tcpsock=" << pid.tcpsock << ",fd=" << pid.fd << ',' << pid.domain << ')'; |
a2eef000 O |
783 | } |
784 | ||
f688bbaa | 785 | inline ostream& operator<<(ostream& ostr, const shared_ptr<PacketID>& pid) |
a2eef000 | 786 | { |
f688bbaa | 787 | return ostr << *pid; |
a2eef000 O |
788 | } |
789 | ||
2d4ccdf5 O |
790 | /* |
791 | * The two compare predicates below must be consistent! | |
792 | * PacketIDBirthdayCompare can omit minor fields, but not change the or skip fields | |
793 | * order! See boost docs on CompatibleCompare. | |
794 | */ | |
0662c2d3 | 795 | struct PacketIDCompare |
a2eef000 | 796 | { |
f688bbaa | 797 | bool operator()(const std::shared_ptr<PacketID>& lhs, const std::shared_ptr<PacketID>& rhs) const |
0662c2d3 | 798 | { |
f688bbaa | 799 | if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) < std::tie(rhs->remote, rhs->tcpsock, rhs->type)) { |
0662c2d3 O |
800 | return true; |
801 | } | |
f688bbaa | 802 | if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) > std::tie(rhs->remote, rhs->tcpsock, rhs->type)) { |
0662c2d3 O |
803 | return false; |
804 | } | |
805 | ||
f688bbaa | 806 | return std::tie(lhs->domain, lhs->fd, lhs->id) < std::tie(rhs->domain, rhs->fd, rhs->id); |
0662c2d3 O |
807 | } |
808 | }; | |
a2eef000 O |
809 | |
810 | struct PacketIDBirthdayCompare | |
811 | { | |
f688bbaa | 812 | bool operator()(const std::shared_ptr<PacketID>& lhs, const std::shared_ptr<PacketID>& rhs) const |
96f81a93 | 813 | { |
f688bbaa | 814 | if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) < std::tie(rhs->remote, rhs->tcpsock, rhs->type)) { |
96f81a93 | 815 | return true; |
3bf2e213 | 816 | } |
f688bbaa | 817 | if (std::tie(lhs->remote, lhs->tcpsock, lhs->type) > std::tie(rhs->remote, rhs->tcpsock, rhs->type)) { |
96f81a93 | 818 | return false; |
3bf2e213 | 819 | } |
f688bbaa | 820 | return lhs->domain < rhs->domain; |
96f81a93 BH |
821 | } |
822 | }; | |
ccfadb6c | 823 | extern std::unique_ptr<MemRecursorCache> g_recCache; |
1d5b3ce6 | 824 | |
7d3d2f4f OM |
825 | extern rec::GlobalCounters g_Counters; |
826 | extern thread_local rec::TCounters t_Counters; | |
827 | ||
0e408828 | 828 | //! represents a running TCP/IP client session |
f688bbaa | 829 | class TCPConnection |
0e408828 | 830 | { |
50a5ef72 | 831 | public: |
c0db60c3 | 832 | TCPConnection(int fileDesc, const ComboAddress& addr); |
cd989c87 | 833 | ~TCPConnection(); |
f688bbaa OM |
834 | TCPConnection(const TCPConnection&) = delete; |
835 | TCPConnection& operator=(const TCPConnection&) = delete; | |
836 | TCPConnection(TCPConnection&&) = delete; | |
837 | TCPConnection& operator=(TCPConnection&&) = delete; | |
3ddb9247 | 838 | |
f688bbaa | 839 | [[nodiscard]] int getFD() const |
cd989c87 BH |
840 | { |
841 | return d_fd; | |
842 | } | |
6b425e61 O |
843 | void setDropOnIdle() |
844 | { | |
845 | d_dropOnIdle = true; | |
846 | } | |
f688bbaa | 847 | [[nodiscard]] bool isDropOnIdle() const |
6b425e61 O |
848 | { |
849 | return d_dropOnIdle; | |
850 | } | |
f688bbaa OM |
851 | |
852 | // The max number of concurrent TCP requests we're willing to process | |
853 | static uint16_t s_maxInFlight; | |
854 | static unsigned int getCurrentConnections() { return s_currentConnections; } | |
855 | ||
5216ddcc | 856 | std::vector<ProxyProtocolValue> proxyProtocolValues; |
2749c3fe | 857 | std::string data; |
f688bbaa | 858 | ComboAddress d_remote; |
5216ddcc RG |
859 | ComboAddress d_source; |
860 | ComboAddress d_destination; | |
e81063e5 | 861 | ComboAddress d_mappedSource; |
2749c3fe | 862 | size_t queriesCount{0}; |
5216ddcc RG |
863 | size_t proxyProtocolGot{0}; |
864 | ssize_t proxyProtocolNeed{0}; | |
f8f66c91 OM |
865 | enum stateenum |
866 | { | |
867 | PROXYPROTOCOLHEADER, | |
868 | BYTE0, | |
869 | BYTE1, | |
870 | GETQUESTION, | |
871 | DONE | |
872 | } state{BYTE0}; | |
b841314c RG |
873 | uint16_t qlen{0}; |
874 | uint16_t bytesread{0}; | |
b5b94beb | 875 | uint16_t d_requestsInFlight{0}; // number of mthreads spawned for this connection |
f8f66c91 | 876 | |
50a5ef72 | 877 | private: |
f688bbaa | 878 | int d_fd; |
7db617e1 | 879 | static std::atomic<uint32_t> s_currentConnections; //!< total number of current TCP connections |
6b425e61 | 880 | bool d_dropOnIdle{false}; |
0e408828 BH |
881 | }; |
882 | ||
44971ca0 PD |
883 | class ImmediateServFailException |
884 | { | |
885 | public: | |
645b217b OM |
886 | ImmediateServFailException(string reason_) : |
887 | reason(std::move(reason_)){}; | |
44971ca0 PD |
888 | |
889 | string reason; //! Print this to tell the user what went wrong | |
890 | }; | |
0e408828 | 891 | |
124dd1d4 RG |
892 | class PolicyHitException |
893 | { | |
894 | }; | |
895 | ||
d4f08082 RG |
896 | class ImmediateQueryDropException |
897 | { | |
898 | }; | |
899 | ||
900 | class SendTruncatedAnswerException | |
901 | { | |
902 | }; | |
903 | ||
f688bbaa | 904 | using addrringbuf_t = boost::circular_buffer<ComboAddress>; |
621ccf89 | 905 | extern thread_local std::unique_ptr<addrringbuf_t> t_servfailremotes, t_largeanswerremotes, t_remotes, t_bogusremotes, t_timeouts; |
a9af3782 | 906 | |
f8f66c91 | 907 | extern thread_local std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t>>> t_queryring, t_servfailqueryring, t_bogusqueryring; |
f26bf547 | 908 | extern thread_local std::shared_ptr<NetmaskGroup> t_allowFrom; |
35189b7d | 909 | extern thread_local std::shared_ptr<NetmaskGroup> t_allowNotifyFrom; |
a512e3d1 | 910 | extern unsigned int g_networkTimeoutMsec; |
b33c2462 | 911 | extern uint16_t g_outgoingEDNSBufsize; |
a6f7f5fe | 912 | extern std::atomic<uint32_t> g_maxCacheEntries, g_maxPacketCacheEntries; |
c1c29961 | 913 | extern bool g_lowercaseOutgoing; |
12ce523e | 914 | |
9883d3f9 | 915 | std::string reloadZoneConfiguration(bool yaml); |
f42b7625 | 916 | using pipefunc_t = std::function<void*()>; |
b4e76a18 | 917 | void broadcastFunction(const pipefunc_t& func); |
e8e12e8c | 918 | void distributeAsyncFunction(const std::string& packet, const pipefunc_t& func); |
3427fa8a | 919 | |
645b217b OM |
920 | int directResolve(const DNSName& qname, QType qtype, QClass qclass, vector<DNSRecord>& ret, const shared_ptr<RecursorLua4>& pdl, Logr::log_t); |
921 | int directResolve(const DNSName& qname, QType qtype, QClass qclass, vector<DNSRecord>& ret, const shared_ptr<RecursorLua4>& pdl, bool qnamemin, Logr::log_t); | |
e8e12e8c | 922 | int followCNAMERecords(std::vector<DNSRecord>& ret, QType qtype, int rcode); |
ef3ee606 RG |
923 | int getFakeAAAARecords(const DNSName& qname, ComboAddress prefix, vector<DNSRecord>& ret); |
924 | int getFakePTRRecords(const DNSName& qname, vector<DNSRecord>& ret); | |
3427fa8a | 925 | |
f8f66c91 OM |
926 | template <class T> |
927 | T broadcastAccFunction(const std::function<T*()>& func); | |
3427fa8a | 928 | |
f688bbaa | 929 | using notifyset_t = std::unordered_set<DNSName>; |
9883d3f9 | 930 | std::tuple<std::shared_ptr<SyncRes::domainmap_t>, std::shared_ptr<notifyset_t>> parseZoneConfiguration(bool yaml); |
ebe2aeb8 | 931 | void* pleaseSupplantAllowNotifyFor(std::shared_ptr<notifyset_t> allowNotifyFor); |
35189b7d | 932 | |
13034931 | 933 | uint64_t* pleaseGetNsSpeedsSize(); |
60e5208a | 934 | uint64_t* pleaseGetFailedServersSize(); |
13034931 BH |
935 | uint64_t* pleaseGetConcurrentQueries(); |
936 | uint64_t* pleaseGetThrottleSize(); | |
2c78bd57 | 937 | void doCarbonDump(void*); |
1d52e318 | 938 | bool primeHints(time_t now = time(nullptr)); |
f688bbaa OM |
939 | |
940 | using timebuf_t = std::array<char, 64>; | |
941 | const char* isoDateTimeMillis(const struct timeval& tval, timebuf_t& buf); | |
795215f2 | 942 | |
f6329e6e KF |
943 | struct WipeCacheResult |
944 | { | |
945 | int record_count = 0; | |
946 | int negative_record_count = 0; | |
947 | int packet_count = 0; | |
948 | }; | |
949 | ||
950 | struct WipeCacheResult wipeCaches(const DNSName& canon, bool subtree, uint16_t qtype); | |
951 | ||
f703f766 | 952 | extern __thread struct timeval g_now; |
5ac6d761 | 953 | |
954 | struct ThreadTimes | |
955 | { | |
f9bb1d3f | 956 | uint64_t msec{0}; |
5ac6d761 | 957 | vector<uint64_t> times; |
958 | ThreadTimes& operator+=(const ThreadTimes& rhs) | |
959 | { | |
960 | times.push_back(rhs.msec); | |
961 | return *this; | |
962 | } | |
963 | }; |