]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/recursordist/rec-main.hh
updated KSK and ZSK Rollover procedures, small fixes in Algorithm Rollover procedure
[thirdparty/pdns.git] / pdns / recursordist / rec-main.hh
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
23 #pragma once
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "logger.hh"
30 #include "lua-recursor4.hh"
31 #include "mplexer.hh"
32 #include "namespaces.hh"
33 #include "rec-lua-conf.hh"
34 #include "rec-protozero.hh"
35 #include "syncres.hh"
36 #include "rec-snmp.hh"
37 #include "rec_channel.hh"
38 #include "threadname.hh"
39
40 #ifdef NOD_ENABLED
41 #include "nod.hh"
42 #endif /* NOD_ENABLED */
43
44 #ifdef HAVE_BOOST_CONTAINER_FLAT_SET_HPP
45 #include <boost/container/flat_set.hpp>
46 #endif
47
48 //! used to send information to a newborn mthread
49 struct DNSComboWriter
50 {
51 DNSComboWriter(const std::string& query, const struct timeval& now, shared_ptr<RecursorLua4> luaContext) :
52 d_mdp(true, query), d_now(now), d_query(query), d_luaContext(luaContext)
53 {
54 }
55
56 DNSComboWriter(const std::string& query, const struct timeval& now, std::unordered_set<std::string>&& policyTags, shared_ptr<RecursorLua4> luaContext, LuaContext::LuaObject&& data, std::vector<DNSRecord>&& records) :
57 d_mdp(true, query), d_now(now), d_query(query), d_policyTags(std::move(policyTags)), d_records(std::move(records)), d_luaContext(luaContext), d_data(std::move(data))
58 {
59 }
60
61 void setRemote(const ComboAddress& sa)
62 {
63 d_remote = sa;
64 }
65
66 void setSource(const ComboAddress& sa)
67 {
68 d_source = sa;
69 }
70
71 void setLocal(const ComboAddress& sa)
72 {
73 d_local = sa;
74 }
75
76 void setDestination(const ComboAddress& sa)
77 {
78 d_destination = sa;
79 }
80
81 void setSocket(int sock)
82 {
83 d_socket = sock;
84 }
85
86 string getRemote() const
87 {
88 if (d_source == d_remote) {
89 return d_source.toStringWithPort();
90 }
91 return d_source.toStringWithPort() + " (proxied by " + d_remote.toStringWithPort() + ")";
92 }
93
94 std::vector<ProxyProtocolValue> d_proxyProtocolValues;
95 MOADNSParser d_mdp;
96 struct timeval d_now;
97 /* Remote client, might differ from d_source
98 in case of XPF, in which case d_source holds
99 the IP of the client and d_remote of the proxy
100 */
101 ComboAddress d_remote;
102 ComboAddress d_source;
103 /* Destination address, might differ from
104 d_destination in case of XPF, in which case
105 d_destination holds the IP of the proxy and
106 d_local holds our own. */
107 ComboAddress d_local;
108 ComboAddress d_destination;
109 RecEventTrace d_eventTrace;
110 boost::uuids::uuid d_uuid;
111 string d_requestorId;
112 string d_deviceId;
113 string d_deviceName;
114 struct timeval d_kernelTimestamp
115 {
116 0, 0
117 };
118 std::string d_query;
119 std::unordered_set<std::string> d_policyTags;
120 std::string d_routingTag;
121 std::vector<DNSRecord> d_records;
122
123 // d_data is tied to this LuaContext so we need to keep it alive and use it, not a newer one, as long as d_data exists
124 shared_ptr<RecursorLua4> d_luaContext;
125 LuaContext::LuaObject d_data;
126
127 EDNSSubnetOpts d_ednssubnet;
128 shared_ptr<TCPConnection> d_tcpConnection;
129 boost::optional<uint16_t> d_extendedErrorCode{boost::none};
130 string d_extendedErrorExtra;
131 boost::optional<int> d_rcode{boost::none};
132 int d_socket{-1};
133 unsigned int d_tag{0};
134 uint32_t d_qhash{0};
135 uint32_t d_ttlCap{std::numeric_limits<uint32_t>::max()};
136 bool d_variable{false};
137 bool d_ecsFound{false};
138 bool d_ecsParsed{false};
139 bool d_followCNAMERecords{false};
140 bool d_logResponse{false};
141 bool d_tcp{false};
142 bool d_responsePaddingDisabled{false};
143 std::map<std::string, RecursorLua4::MetaValue> d_meta;
144 };
145
146 extern thread_local unique_ptr<FDMultiplexer> t_fdm;
147 extern uint16_t g_minUdpSourcePort;
148 extern uint16_t g_maxUdpSourcePort;
149
150 // you can ask this class for a UDP socket to send a query from
151 // this socket is not yours, don't even think about deleting it
152 // but after you call 'returnSocket' on it, don't assume anything anymore
153 class UDPClientSocks
154 {
155 unsigned int d_numsocks;
156
157 public:
158 UDPClientSocks() :
159 d_numsocks(0)
160 {
161 }
162
163 LWResult::Result getSocket(const ComboAddress& toaddr, int* fd);
164
165 // return a socket to the pool, or simply erase it
166 void returnSocket(int fd);
167
168 private:
169 // returns -1 for errors which might go away, throws for ones that won't
170 static int makeClientSocket(int family);
171 };
172
173 enum class PaddingMode
174 {
175 Always,
176 PaddedQueries
177 };
178
179 typedef MTasker<std::shared_ptr<PacketID>, PacketBuffer, PacketIDCompare> MT_t;
180 extern thread_local std::unique_ptr<MT_t> MT; // the big MTasker
181
182 extern bool g_logCommonErrors;
183 extern size_t g_proxyProtocolMaximumSize;
184 extern std::atomic<bool> g_quiet;
185 extern NetmaskGroup g_XPFAcl;
186 extern thread_local std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>> t_protobufServers;
187 extern thread_local std::shared_ptr<RecursorLua4> t_pdl;
188 extern bool g_gettagNeedsEDNSOptions;
189 extern NetmaskGroup g_paddingFrom;
190 extern unsigned int g_paddingTag;
191 extern PaddingMode g_paddingMode;
192 extern thread_local std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>> t_outgoingProtobufServers;
193 extern unsigned int g_maxMThreads;
194 extern bool g_reusePort;
195 extern bool g_anyToTcp;
196 extern size_t g_tcpMaxQueriesPerConn;
197 extern unsigned int g_maxTCPPerClient;
198 extern int g_tcpTimeout;
199 extern uint16_t g_udpTruncationThreshold;
200 extern double g_balancingFactor;
201 extern size_t g_maxUDPQueriesPerRound;
202 extern bool g_useKernelTimestamp;
203 extern thread_local std::shared_ptr<NetmaskGroup> t_allowFrom;
204 extern thread_local std::shared_ptr<NetmaskGroup> t_allowNotifyFrom;
205 extern thread_local std::shared_ptr<notifyset_t> t_allowNotifyFor;
206 extern thread_local std::unique_ptr<UDPClientSocks> t_udpclientsocks;
207 extern bool g_useIncomingECS;
208 extern boost::optional<ComboAddress> g_dns64Prefix;
209 extern DNSName g_dns64PrefixReverse;
210 extern uint64_t g_latencyStatSize;
211 extern bool g_addExtendedResolutionDNSErrors;
212 extern uint16_t g_xpfRRCode;
213 extern NetmaskGroup g_proxyProtocolACL;
214 extern std::atomic<bool> g_statsWanted;
215 extern uint32_t g_disthashseed;
216 extern int g_argc;
217 extern char** g_argv;
218 extern std::shared_ptr<SyncRes::domainmap_t> g_initialDomainMap; // new threads needs this to be setup
219 extern std::shared_ptr<NetmaskGroup> g_initialAllowFrom; // new thread needs to be setup with this
220 extern std::shared_ptr<NetmaskGroup> g_initialAllowNotifyFrom; // new threads need this to be setup
221 extern std::shared_ptr<notifyset_t> g_initialAllowNotifyFor; // new threads need this to be setup
222 extern thread_local std::shared_ptr<Regex> t_traceRegex;
223 extern string g_programname;
224 extern string g_pidfname;
225 extern RecursorControlChannel g_rcc; // only active in the handler thread
226
227 #ifdef NOD_ENABLED
228 extern bool g_nodEnabled;
229 extern DNSName g_nodLookupDomain;
230 extern bool g_nodLog;
231 extern SuffixMatchNode g_nodDomainWL;
232 extern std::string g_nod_pbtag;
233 extern bool g_udrEnabled;
234 extern bool g_udrLog;
235 extern std::string g_udr_pbtag;
236 extern thread_local std::shared_ptr<nod::NODDB> t_nodDBp;
237 extern thread_local std::shared_ptr<nod::UniqueResponseDB> t_udrDBp;
238 #endif
239
240 #ifdef HAVE_FSTRM
241 extern thread_local std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>> t_frameStreamServers;
242 extern thread_local uint64_t t_frameStreamServersGeneration;
243 #endif /* HAVE_FSTRM */
244
245 #ifdef HAVE_BOOST_CONTAINER_FLAT_SET_HPP
246 extern boost::container::flat_set<uint16_t> g_avoidUdpSourcePorts;
247 #else
248 extern std::set<uint16_t> g_avoidUdpSourcePorts;
249 #endif
250
251 /* without reuseport, all listeners share the same sockets */
252 typedef vector<pair<int, boost::function<void(int, boost::any&)>>> deferredAdd_t;
253 extern deferredAdd_t g_deferredAdds;
254
255 typedef map<ComboAddress, uint32_t, ComboAddress::addressOnlyLessThan> tcpClientCounts_t;
256 extern thread_local std::unique_ptr<tcpClientCounts_t> t_tcpClientCounts;
257
258 inline MT_t* getMT()
259 {
260 return MT ? MT.get() : nullptr;
261 }
262
263 /* this function is called with both a string and a vector<uint8_t> representing a packet */
264 template <class T>
265 static bool sendResponseOverTCP(const std::unique_ptr<DNSComboWriter>& dc, const T& packet)
266 {
267 uint8_t buf[2];
268 buf[0] = packet.size() / 256;
269 buf[1] = packet.size() % 256;
270
271 Utility::iovec iov[2];
272 iov[0].iov_base = (void*)buf;
273 iov[0].iov_len = 2;
274 iov[1].iov_base = (void*)&*packet.begin();
275 iov[1].iov_len = packet.size();
276
277 int wret = Utility::writev(dc->d_socket, iov, 2);
278 bool hadError = true;
279
280 if (wret == 0) {
281 g_log << Logger::Warning << "EOF writing TCP answer to " << dc->getRemote() << endl;
282 }
283 else if (wret < 0) {
284 int err = errno;
285 g_log << Logger::Warning << "Error writing TCP answer to " << dc->getRemote() << ": " << strerror(err) << endl;
286 }
287 else if ((unsigned int)wret != 2 + packet.size()) {
288 g_log << Logger::Warning << "Oops, partial answer sent to " << dc->getRemote() << " for " << dc->d_mdp.d_qname << " (size=" << (2 + packet.size()) << ", sent " << wret << ")" << endl;
289 }
290 else {
291 hadError = false;
292 }
293
294 return hadError;
295 }
296
297 // For communicating with our threads effectively readonly after
298 // startup.
299 // First we have the handler thread, t_id == 0 (some other helper
300 // threads like SNMP might have t_id == 0 as well) then the
301 // distributor threads if any and finally the workers
302 struct RecThreadInfo
303 {
304 struct ThreadPipeSet
305 {
306 int writeToThread{-1};
307 int readToThread{-1};
308 int writeFromThread{-1};
309 int readFromThread{-1};
310 int writeQueriesToThread{-1}; // this one is non-blocking
311 int readQueriesToThread{-1};
312 };
313
314 public:
315 static RecThreadInfo& self()
316 {
317 return s_threadInfos.at(t_id);
318 }
319
320 static RecThreadInfo& info(unsigned int i)
321 {
322 return s_threadInfos.at(i);
323 }
324
325 static vector<RecThreadInfo>& infos()
326 {
327 return s_threadInfos;
328 }
329
330 bool isDistributor() const
331 {
332 if (t_id == 0) {
333 return false;
334 }
335 return s_weDistributeQueries && listener;
336 }
337
338 bool isHandler() const
339 {
340 if (t_id == 0) {
341 return true;
342 }
343 return handler;
344 }
345
346 bool isWorker() const
347 {
348 return worker;
349 }
350
351 bool isListener() const
352 {
353 return listener;
354 }
355
356 bool isTaskThread() const
357 {
358 return taskThread;
359 }
360
361 void setHandler()
362 {
363 handler = true;
364 }
365
366 void setWorker()
367 {
368 worker = true;
369 }
370
371 void setListener(bool flag = true)
372 {
373 listener = flag;
374 }
375
376 void setTaskThread()
377 {
378 taskThread = true;
379 }
380
381 static unsigned int id()
382 {
383 return t_id;
384 }
385
386 static void setThreadId(unsigned int id)
387 {
388 t_id = id;
389 }
390
391 std::string getName() const
392 {
393 return name;
394 }
395
396 static unsigned int numHandlers()
397 {
398 return 1;
399 }
400
401 static unsigned int numTaskThreads()
402 {
403 return 1;
404 }
405
406 static unsigned int numWorkers()
407 {
408 return s_numWorkerThreads;
409 }
410
411 static unsigned int numDistributors()
412 {
413 return s_numDistributorThreads;
414 }
415
416 static bool weDistributeQueries()
417 {
418 return s_weDistributeQueries;
419 }
420
421 static void setWeDistributeQueries(bool flag)
422 {
423 s_weDistributeQueries = flag;
424 }
425
426 static void setNumWorkerThreads(unsigned int n)
427 {
428 s_numWorkerThreads = n;
429 }
430
431 static void setNumDistributorThreads(unsigned int n)
432 {
433 s_numDistributorThreads = n;
434 }
435
436 static unsigned int numRecursorThreads()
437 {
438 return numHandlers() + numDistributors() + numWorkers() + numTaskThreads();
439 }
440
441 static int runThreads();
442 static void makeThreadPipes();
443
444 void setExitCode(int e)
445 {
446 exitCode = e;
447 }
448
449 // FD corresponding to TCP sockets this thread is listening on.
450 // These FDs are also in deferredAdds when we have one socket per
451 // listener, and in g_deferredAdds instead.
452 std::set<int> tcpSockets;
453 // FD corresponding to listening sockets if we have one socket per
454 // listener (with reuseport), otherwise all listeners share the
455 // same FD and g_deferredAdds is then used instead
456 deferredAdd_t deferredAdds;
457
458 struct ThreadPipeSet pipes;
459 MT_t* mt{nullptr};
460 uint64_t numberOfDistributedQueries{0};
461
462 private:
463 void start(unsigned int id, const string& name, const std::map<unsigned int, std::set<int>>& cpusMap);
464
465 std::string name;
466 std::thread thread;
467 int exitCode{0};
468
469 // handle the web server, carbon, statistics and the control channel
470 bool handler{false};
471 // accept incoming queries (and distributes them to the workers if pdns-distributes-queries is set)
472 bool listener{false};
473 // process queries
474 bool worker{false};
475 // run async tasks: from TastQueue and ZoneToCache
476 bool taskThread{false};
477
478 static thread_local unsigned int t_id;
479 static std::vector<RecThreadInfo> s_threadInfos;
480 static bool s_weDistributeQueries; // if true, 1 or more threads listen on the incoming query sockets and distribute them to workers
481 static unsigned int s_numDistributorThreads;
482 static unsigned int s_numWorkerThreads;
483 };
484
485 struct ThreadMSG
486 {
487 pipefunc_t func;
488 bool wantAnswer;
489 };
490
491 PacketBuffer GenUDPQueryResponse(const ComboAddress& dest, const string& query);
492 bool checkProtobufExport(LocalStateHolder<LuaConfigItems>& luaconfsLocal);
493 bool checkOutgoingProtobufExport(LocalStateHolder<LuaConfigItems>& luaconfsLocal);
494 bool checkFrameStreamExport(LocalStateHolder<LuaConfigItems>& luaconfsLocal);
495 void getQNameAndSubnet(const std::string& question, DNSName* dnsname, uint16_t* qtype, uint16_t* qclass,
496 bool& foundECS, EDNSSubnetOpts* ednssubnet, EDNSOptionViewMap* options,
497 bool& foundXPF, ComboAddress* xpfSource, ComboAddress* xpfDest);
498 void protobufLogQuery(LocalStateHolder<LuaConfigItems>& luaconfsLocal, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const Netmask& ednssubnet, bool tcp, uint16_t id, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::unordered_set<std::string>& policyTags, const std::string& requestorId, const std::string& deviceId, const std::string& deviceName, const std::map<std::string, RecursorLua4::MetaValue>& meta);
499 bool isAllowNotifyForZone(DNSName qname);
500 bool checkForCacheHit(bool qnameParsed, unsigned int tag, const string& data,
501 DNSName& qname, uint16_t& qtype, uint16_t& qclass,
502 const struct timeval& now,
503 string& response, uint32_t& qhash,
504 RecursorPacketCache::OptPBData& pbData, bool tcp, const ComboAddress& source);
505 void protobufLogResponse(pdns::ProtoZero::RecMessage& message);
506 void protobufLogResponse(const struct dnsheader* dh, LocalStateHolder<LuaConfigItems>& luaconfsLocal,
507 const RecursorPacketCache::OptPBData& pbData, const struct timeval& tv,
508 bool tcp, const ComboAddress& source, const ComboAddress& destination,
509 const EDNSSubnetOpts& ednssubnet,
510 const boost::uuids::uuid& uniqueId, const string& requestorId, const string& deviceId,
511 const string& deviceName, const std::map<std::string, RecursorLua4::MetaValue>& meta,
512 const RecEventTrace& eventTrace);
513 void requestWipeCaches(const DNSName& canon);
514 void startDoResolve(void* p);
515 bool expectProxyProtocol(const ComboAddress& from);
516 void finishTCPReply(std::unique_ptr<DNSComboWriter>& dc, bool hadError, bool updateInFlight);
517 void checkFastOpenSysctl(bool active);
518 void checkTFOconnect();
519 void makeTCPServerSockets(deferredAdd_t& deferredAdds, std::set<int>& tcpSockets);
520 void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t&);
521
522 void makeUDPServerSockets(deferredAdd_t& deferredAdds);
523
524 #define LOCAL_NETS "127.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fc00::/7, fe80::/10"
525 #define LOCAL_NETS_INVERSE "!127.0.0.0/8, !10.0.0.0/8, !100.64.0.0/10, !169.254.0.0/16, !192.168.0.0/16, !172.16.0.0/12, !::1/128, !fc00::/7, !fe80::/10"
526 // Bad Nets taken from both:
527 // http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
528 // and
529 // http://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
530 // where such a network may not be considered a valid destination
531 #define BAD_NETS "0.0.0.0/8, 192.0.0.0/24, 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24, 240.0.0.0/4, ::/96, ::ffff:0:0/96, 100::/64, 2001:db8::/32"
532 #define DONT_QUERY LOCAL_NETS ", " BAD_NETS