]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/pdns_recursor.cc
Merge pull request #7517 from Habbie/mysqlthreadcloser
[thirdparty/pdns.git] / pdns / pdns_recursor.cc
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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <netdb.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #ifdef HAVE_BOOST_CONTAINER_FLAT_SET_HPP
30 #include <boost/container/flat_set.hpp>
31 #endif
32 #include "ws-recursor.hh"
33 #include <thread>
34 #include "threadname.hh"
35 #include "recpacketcache.hh"
36 #include "utility.hh"
37 #include "dns_random.hh"
38 #ifdef HAVE_LIBSODIUM
39 #include <sodium.h>
40 #endif
41 #include "opensslsigners.hh"
42 #include <iostream>
43 #include <errno.h>
44 #include <boost/static_assert.hpp>
45 #include <map>
46 #include <set>
47 #include "recursor_cache.hh"
48 #include "cachecleaner.hh"
49 #include <stdio.h>
50 #include <signal.h>
51 #include <stdlib.h>
52 #include "misc.hh"
53 #include "mtasker.hh"
54 #include <utility>
55 #include "arguments.hh"
56 #include "syncres.hh"
57 #include <fcntl.h>
58 #include <fstream>
59 #include "sortlist.hh"
60 #include "sstuff.hh"
61 #include <boost/tuple/tuple.hpp>
62 #include <boost/tuple/tuple_comparison.hpp>
63 #include <boost/shared_array.hpp>
64 #include <boost/function.hpp>
65 #include <boost/algorithm/string.hpp>
66 #ifdef MALLOC_TRACE
67 #include "malloctrace.hh"
68 #endif
69 #include <netinet/tcp.h>
70 #include "capabilities.hh"
71 #include "dnsparser.hh"
72 #include "dnswriter.hh"
73 #include "dnsrecords.hh"
74 #include "zoneparser-tng.hh"
75 #include "rec_channel.hh"
76 #include "logger.hh"
77 #include "iputils.hh"
78 #include "mplexer.hh"
79 #include "config.h"
80 #include "lua-recursor4.hh"
81 #include "version.hh"
82 #include "responsestats.hh"
83 #include "secpoll-recursor.hh"
84 #include "dnsname.hh"
85 #include "filterpo.hh"
86 #include "rpzloader.hh"
87 #include "validate-recursor.hh"
88 #include "rec-lua-conf.hh"
89 #include "ednsoptions.hh"
90 #include "gettime.hh"
91 #include "pubsuffix.hh"
92 #ifdef NOD_ENABLED
93 #include "nod.hh"
94 #endif /* NOD_ENABLED */
95
96 #include "rec-protobuf.hh"
97 #include "rec-snmp.hh"
98
99 #ifdef HAVE_SYSTEMD
100 #include <systemd/sd-daemon.h>
101 #endif
102
103 #include "namespaces.hh"
104
105 #ifdef HAVE_PROTOBUF
106 #include "uuid-utils.hh"
107 #endif
108
109 #include "xpf.hh"
110
111 typedef map<ComboAddress, uint32_t, ComboAddress::addressOnlyLessThan> tcpClientCounts_t;
112
113 static thread_local std::shared_ptr<RecursorLua4> t_pdl;
114 static thread_local unsigned int t_id = 0;
115 static thread_local std::shared_ptr<Regex> t_traceRegex;
116 static thread_local std::unique_ptr<tcpClientCounts_t> t_tcpClientCounts;
117 #ifdef HAVE_PROTOBUF
118 static thread_local std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>> t_protobufServers{nullptr};
119 static thread_local uint64_t t_protobufServersGeneration;
120 static thread_local std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>> t_outgoingProtobufServers{nullptr};
121 static thread_local uint64_t t_outgoingProtobufServersGeneration;
122 #endif /* HAVE_PROTOBUF */
123
124 thread_local std::unique_ptr<MT_t> MT; // the big MTasker
125 thread_local std::unique_ptr<MemRecursorCache> t_RC;
126 thread_local std::unique_ptr<RecursorPacketCache> t_packetCache;
127 thread_local FDMultiplexer* t_fdm{nullptr};
128 thread_local std::unique_ptr<addrringbuf_t> t_remotes, t_servfailremotes, t_largeanswerremotes, t_bogusremotes;
129 thread_local std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t> > > t_queryring, t_servfailqueryring, t_bogusqueryring;
130 thread_local std::shared_ptr<NetmaskGroup> t_allowFrom;
131 #ifdef NOD_ENABLED
132 thread_local std::shared_ptr<nod::NODDB> t_nodDBp;
133 thread_local std::shared_ptr<nod::UniqueResponseDB> t_udrDBp;
134 #endif /* NOD_ENABLED */
135 __thread struct timeval g_now; // timestamp, updated (too) frequently
136
137 typedef vector<pair<int, function< void(int, any&) > > > deferredAdd_t;
138
139 // for communicating with our threads
140 // effectively readonly after startup
141 struct RecThreadInfo
142 {
143 struct ThreadPipeSet
144 {
145 int writeToThread{-1};
146 int readToThread{-1};
147 int writeFromThread{-1};
148 int readFromThread{-1};
149 int writeQueriesToThread{-1}; // this one is non-blocking
150 int readQueriesToThread{-1};
151 };
152
153 /* FD corresponding to TCP sockets this thread is listening
154 on.
155 These FDs are also in deferredAdds when we have one
156 socket per listener, and in g_deferredAdds instead. */
157 std::set<int> tcpSockets;
158 /* FD corresponding to listening sockets if we have one socket per
159 listener (with reuseport), otherwise all listeners share the
160 same FD and g_deferredAdds is then used instead */
161 deferredAdd_t deferredAdds;
162 struct ThreadPipeSet pipes;
163 std::thread thread;
164 /* handle the web server, carbon, statistics and the control channel */
165 bool isHandler{false};
166 /* accept incoming queries (and distributes them to the workers if pdns-distributes-queries is set) */
167 bool isListener{false};
168 /* process queries */
169 bool isWorker{false};
170 };
171
172 /* first we have the handler thread, t_id == 0 (some other
173 helper threads like SNMP might have t_id == 0 as well)
174 then the distributor threads if any
175 and finally the workers */
176 static std::vector<RecThreadInfo> s_threadInfos;
177 /* without reuseport, all listeners share the same sockets */
178 static deferredAdd_t g_deferredAdds;
179
180 typedef vector<int> tcpListenSockets_t;
181 typedef map<int, ComboAddress> listenSocketsAddresses_t; // is shared across all threads right now
182
183 static const ComboAddress g_local4("0.0.0.0"), g_local6("::");
184 static listenSocketsAddresses_t g_listenSocketsAddresses; // is shared across all threads right now
185 static set<int> g_fromtosockets; // listen sockets that use 'sendfromto()' mechanism
186 static vector<ComboAddress> g_localQueryAddresses4, g_localQueryAddresses6;
187 static AtomicCounter counter;
188 static std::shared_ptr<SyncRes::domainmap_t> g_initialDomainMap; // new threads needs this to be setup
189 static std::shared_ptr<NetmaskGroup> g_initialAllowFrom; // new thread needs to be setup with this
190 static NetmaskGroup g_XPFAcl;
191 static size_t g_tcpMaxQueriesPerConn;
192 static size_t s_maxUDPQueriesPerRound;
193 static uint64_t g_latencyStatSize;
194 static uint32_t g_disthashseed;
195 static unsigned int g_maxTCPPerClient;
196 static unsigned int g_maxMThreads;
197 static unsigned int g_numDistributorThreads;
198 static unsigned int g_numWorkerThreads;
199 static int g_tcpTimeout;
200 static uint16_t g_udpTruncationThreshold;
201 static uint16_t g_xpfRRCode{0};
202 static std::atomic<bool> statsWanted;
203 static std::atomic<bool> g_quiet;
204 static bool g_logCommonErrors;
205 static bool g_anyToTcp;
206 static bool g_weDistributeQueries; // if true, 1 or more threads listen on the incoming query sockets and distribute them to workers
207 static bool g_reusePort{false};
208 static bool g_gettagNeedsEDNSOptions{false};
209 static time_t g_statisticsInterval;
210 static bool g_useIncomingECS;
211 std::atomic<uint32_t> g_maxCacheEntries, g_maxPacketCacheEntries;
212 #ifdef NOD_ENABLED
213 static bool g_nodEnabled;
214 static DNSName g_nodLookupDomain;
215 static bool g_nodLog;
216 static SuffixMatchNode g_nodDomainWL;
217 static std::string g_nod_pbtag;
218 static bool g_udrEnabled;
219 static bool g_udrLog;
220 static std::string g_udr_pbtag;
221 #endif /* NOD_ENABLED */
222 #ifdef HAVE_BOOST_CONTAINER_FLAT_SET_HPP
223 static boost::container::flat_set<uint16_t> s_avoidUdpSourcePorts;
224 #else
225 static std::set<uint16_t> s_avoidUdpSourcePorts;
226 #endif
227 static uint16_t s_minUdpSourcePort;
228 static uint16_t s_maxUdpSourcePort;
229
230 RecursorControlChannel s_rcc; // only active in the handler thread
231 RecursorStats g_stats;
232 string s_programname="pdns_recursor";
233 string s_pidfname;
234 bool g_lowercaseOutgoing;
235 unsigned int g_networkTimeoutMsec;
236 unsigned int g_numThreads;
237 uint16_t g_outgoingEDNSBufsize;
238 bool g_logRPZChanges{false};
239
240 #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"
241 #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"
242 // Bad Nets taken from both:
243 // http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
244 // and
245 // http://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
246 // where such a network may not be considered a valid destination
247 #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"
248 #define DONT_QUERY LOCAL_NETS ", " BAD_NETS
249
250 //! used to send information to a newborn mthread
251 struct DNSComboWriter {
252 DNSComboWriter(const std::string& query, const struct timeval& now): d_mdp(true, query), d_now(now), d_query(query)
253 {
254 }
255
256 DNSComboWriter(const std::string& query, const struct timeval& now, std::vector<std::string>&& policyTags, LuaContext::LuaObject&& data): d_mdp(true, query), d_now(now), d_query(query), d_policyTags(std::move(policyTags)), d_data(std::move(data))
257 {
258 }
259
260 void setRemote(const ComboAddress& sa)
261 {
262 d_remote=sa;
263 }
264
265 void setSource(const ComboAddress& sa)
266 {
267 d_source=sa;
268 }
269
270 void setLocal(const ComboAddress& sa)
271 {
272 d_local=sa;
273 }
274
275 void setDestination(const ComboAddress& sa)
276 {
277 d_destination=sa;
278 }
279
280 void setSocket(int sock)
281 {
282 d_socket=sock;
283 }
284
285 string getRemote() const
286 {
287 if (d_source == d_remote) {
288 return d_source.toStringWithPort();
289 }
290 return d_source.toStringWithPort() + " (proxied by " + d_remote.toStringWithPort() + ")";
291 }
292
293 MOADNSParser d_mdp;
294 struct timeval d_now;
295 /* Remote client, might differ from d_source
296 in case of XPF, in which case d_source holds
297 the IP of the client and d_remote of the proxy
298 */
299 ComboAddress d_remote;
300 ComboAddress d_source;
301 /* Destination address, might differ from
302 d_destination in case of XPF, in which case
303 d_destination holds the IP of the proxy and
304 d_local holds our own. */
305 ComboAddress d_local;
306 ComboAddress d_destination;
307 #ifdef HAVE_PROTOBUF
308 boost::uuids::uuid d_uuid;
309 string d_requestorId;
310 string d_deviceId;
311 #endif
312 std::string d_query;
313 std::vector<std::string> d_policyTags;
314 LuaContext::LuaObject d_data;
315 EDNSSubnetOpts d_ednssubnet;
316 shared_ptr<TCPConnection> d_tcpConnection;
317 int d_socket;
318 unsigned int d_tag{0};
319 uint32_t d_qhash{0};
320 uint32_t d_ttlCap{std::numeric_limits<uint32_t>::max()};
321 uint16_t d_ecsBegin{0};
322 uint16_t d_ecsEnd{0};
323 bool d_variable{false};
324 bool d_ecsFound{false};
325 bool d_ecsParsed{false};
326 bool d_tcp;
327 };
328
329 MT_t* getMT()
330 {
331 return MT ? MT.get() : nullptr;
332 }
333
334 ArgvMap &arg()
335 {
336 static ArgvMap theArg;
337 return theArg;
338 }
339
340 unsigned int getRecursorThreadId()
341 {
342 return t_id;
343 }
344
345 int getMTaskerTID()
346 {
347 return MT->getTid();
348 }
349
350 static bool isDistributorThread()
351 {
352 if (t_id == 0) {
353 return false;
354 }
355
356 return g_weDistributeQueries && s_threadInfos.at(t_id).isListener;
357 }
358
359 static bool isHandlerThread()
360 {
361 if (t_id == 0) {
362 return true;
363 }
364
365 return s_threadInfos.at(t_id).isHandler;
366 }
367
368 static void handleTCPClientWritable(int fd, FDMultiplexer::funcparam_t& var);
369
370 // -1 is error, 0 is timeout, 1 is success
371 int asendtcp(const string& data, Socket* sock)
372 {
373 PacketID pident;
374 pident.sock=sock;
375 pident.outMSG=data;
376
377 t_fdm->addWriteFD(sock->getHandle(), handleTCPClientWritable, pident);
378 string packet;
379
380 int ret=MT->waitEvent(pident, &packet, g_networkTimeoutMsec);
381
382 if(!ret || ret==-1) { // timeout
383 t_fdm->removeWriteFD(sock->getHandle());
384 }
385 else if(packet.size() !=data.size()) { // main loop tells us what it sent out, or empty in case of an error
386 return -1;
387 }
388 return ret;
389 }
390
391 static void handleTCPClientReadable(int fd, FDMultiplexer::funcparam_t& var);
392
393 // -1 is error, 0 is timeout, 1 is success
394 int arecvtcp(string& data, size_t len, Socket* sock, bool incompleteOkay)
395 {
396 data.clear();
397 PacketID pident;
398 pident.sock=sock;
399 pident.inNeeded=len;
400 pident.inIncompleteOkay=incompleteOkay;
401 t_fdm->addReadFD(sock->getHandle(), handleTCPClientReadable, pident);
402
403 int ret=MT->waitEvent(pident,&data, g_networkTimeoutMsec);
404 if(!ret || ret==-1) { // timeout
405 t_fdm->removeReadFD(sock->getHandle());
406 }
407 else if(data.empty()) {// error, EOF or other
408 return -1;
409 }
410
411 return ret;
412 }
413
414 static void handleGenUDPQueryResponse(int fd, FDMultiplexer::funcparam_t& var)
415 {
416 PacketID pident=*any_cast<PacketID>(&var);
417 char resp[512];
418 ComboAddress fromaddr;
419 socklen_t addrlen=sizeof(fromaddr);
420
421 ssize_t ret=recvfrom(fd, resp, sizeof(resp), 0, (sockaddr *)&fromaddr, &addrlen);
422 if (fromaddr != pident.remote) {
423 g_log<<Logger::Notice<<"Response received from the wrong remote host ("<<fromaddr.toStringWithPort()<<" instead of "<<pident.remote.toStringWithPort()<<"), discarding"<<endl;
424
425 }
426
427 t_fdm->removeReadFD(fd);
428 if(ret >= 0) {
429 string data(resp, (size_t) ret);
430 MT->sendEvent(pident, &data);
431 }
432 else {
433 string empty;
434 MT->sendEvent(pident, &empty);
435 // cerr<<"Had some kind of error: "<<ret<<", "<<strerror(errno)<<endl;
436 }
437 }
438 string GenUDPQueryResponse(const ComboAddress& dest, const string& query)
439 {
440 Socket s(dest.sin4.sin_family, SOCK_DGRAM);
441 s.setNonBlocking();
442 ComboAddress local = getQueryLocalAddress(dest.sin4.sin_family, 0);
443
444 s.bind(local);
445 s.connect(dest);
446 s.send(query);
447
448 PacketID pident;
449 pident.sock=&s;
450 pident.remote=dest;
451 pident.type=0;
452 t_fdm->addReadFD(s.getHandle(), handleGenUDPQueryResponse, pident);
453
454 string data;
455
456 int ret=MT->waitEvent(pident,&data, g_networkTimeoutMsec);
457
458 if(!ret || ret==-1) { // timeout
459 t_fdm->removeReadFD(s.getHandle());
460 }
461 else if(data.empty()) {// error, EOF or other
462 // we could special case this
463 return data;
464 }
465 return data;
466 }
467
468 //! pick a random query local address
469 ComboAddress getQueryLocalAddress(int family, uint16_t port)
470 {
471 ComboAddress ret;
472 if(family==AF_INET) {
473 if(g_localQueryAddresses4.empty())
474 ret = g_local4;
475 else
476 ret = g_localQueryAddresses4[dns_random(g_localQueryAddresses4.size())];
477 ret.sin4.sin_port = htons(port);
478 }
479 else {
480 if(g_localQueryAddresses6.empty())
481 ret = g_local6;
482 else
483 ret = g_localQueryAddresses6[dns_random(g_localQueryAddresses6.size())];
484
485 ret.sin6.sin6_port = htons(port);
486 }
487 return ret;
488 }
489
490 static void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t&);
491
492 static void setSocketBuffer(int fd, int optname, uint32_t size)
493 {
494 uint32_t psize=0;
495 socklen_t len=sizeof(psize);
496
497 if(!getsockopt(fd, SOL_SOCKET, optname, (char*)&psize, &len) && psize > size) {
498 g_log<<Logger::Error<<"Not decreasing socket buffer size from "<<psize<<" to "<<size<<endl;
499 return;
500 }
501
502 if (setsockopt(fd, SOL_SOCKET, optname, (char*)&size, sizeof(size)) < 0 )
503 g_log<<Logger::Error<<"Unable to raise socket buffer size to "<<size<<": "<<strerror(errno)<<endl;
504 }
505
506
507 static void setSocketReceiveBuffer(int fd, uint32_t size)
508 {
509 setSocketBuffer(fd, SO_RCVBUF, size);
510 }
511
512 static void setSocketSendBuffer(int fd, uint32_t size)
513 {
514 setSocketBuffer(fd, SO_SNDBUF, size);
515 }
516
517
518 // you can ask this class for a UDP socket to send a query from
519 // this socket is not yours, don't even think about deleting it
520 // but after you call 'returnSocket' on it, don't assume anything anymore
521 class UDPClientSocks
522 {
523 unsigned int d_numsocks;
524 public:
525 UDPClientSocks() : d_numsocks(0)
526 {
527 }
528
529 typedef set<int> socks_t;
530 socks_t d_socks;
531
532 // returning -2 means: temporary OS error (ie, out of files), -1 means error related to remote
533 int getSocket(const ComboAddress& toaddr, int* fd)
534 {
535 *fd=makeClientSocket(toaddr.sin4.sin_family);
536 if(*fd < 0) // temporary error - receive exception otherwise
537 return -2;
538
539 if(connect(*fd, (struct sockaddr*)(&toaddr), toaddr.getSocklen()) < 0) {
540 int err = errno;
541 // returnSocket(*fd);
542 try {
543 closesocket(*fd);
544 }
545 catch(const PDNSException& e) {
546 g_log<<Logger::Error<<"Error closing UDP socket after connect() failed: "<<e.reason<<endl;
547 }
548
549 if(err==ENETUNREACH) // Seth "My Interfaces Are Like A Yo Yo" Arnold special
550 return -2;
551 return -1;
552 }
553
554 d_socks.insert(*fd);
555 d_numsocks++;
556 return 0;
557 }
558
559 void returnSocket(int fd)
560 {
561 socks_t::iterator i=d_socks.find(fd);
562 if(i==d_socks.end()) {
563 throw PDNSException("Trying to return a socket (fd="+std::to_string(fd)+") not in the pool");
564 }
565 returnSocketLocked(i);
566 }
567
568 // return a socket to the pool, or simply erase it
569 void returnSocketLocked(socks_t::iterator& i)
570 {
571 if(i==d_socks.end()) {
572 throw PDNSException("Trying to return a socket not in the pool");
573 }
574 try {
575 t_fdm->removeReadFD(*i);
576 }
577 catch(FDMultiplexerException& e) {
578 // we sometimes return a socket that has not yet been assigned to t_fdm
579 }
580 try {
581 closesocket(*i);
582 }
583 catch(const PDNSException& e) {
584 g_log<<Logger::Error<<"Error closing returned UDP socket: "<<e.reason<<endl;
585 }
586
587 d_socks.erase(i++);
588 --d_numsocks;
589 }
590
591 // returns -1 for errors which might go away, throws for ones that won't
592 static int makeClientSocket(int family)
593 {
594 int ret=socket(family, SOCK_DGRAM, 0 ); // turns out that setting CLO_EXEC and NONBLOCK from here is not a performance win on Linux (oddly enough)
595
596 if(ret < 0 && errno==EMFILE) // this is not a catastrophic error
597 return ret;
598
599 if(ret<0)
600 throw PDNSException("Making a socket for resolver (family = "+std::to_string(family)+"): "+stringerror());
601
602 // setCloseOnExec(ret); // we're not going to exec
603
604 int tries=10;
605 ComboAddress sin;
606 while(--tries) {
607 uint16_t port;
608
609 if(tries==1) // fall back to kernel 'random'
610 port = 0;
611 else {
612 do {
613 port = s_minUdpSourcePort + dns_random(s_maxUdpSourcePort - s_minUdpSourcePort + 1);
614 }
615 while (s_avoidUdpSourcePorts.count(port));
616 }
617
618 sin=getQueryLocalAddress(family, port); // does htons for us
619
620 if (::bind(ret, (struct sockaddr *)&sin, sin.getSocklen()) >= 0)
621 break;
622 }
623 if(!tries)
624 throw PDNSException("Resolver binding to local query client socket on "+sin.toString()+": "+stringerror());
625
626 setReceiveSocketErrors(ret, family);
627 setNonBlocking(ret);
628 return ret;
629 }
630 };
631
632 static thread_local std::unique_ptr<UDPClientSocks> t_udpclientsocks;
633
634 /* these two functions are used by LWRes */
635 // -2 is OS error, -1 is error that depends on the remote, > 0 is success
636 int asendto(const char *data, size_t len, int flags,
637 const ComboAddress& toaddr, uint16_t id, const DNSName& domain, uint16_t qtype, int* fd)
638 {
639
640 PacketID pident;
641 pident.domain = domain;
642 pident.remote = toaddr;
643 pident.type = qtype;
644
645 // see if there is an existing outstanding request we can chain on to, using partial equivalence function
646 pair<MT_t::waiters_t::iterator, MT_t::waiters_t::iterator> chain=MT->d_waiters.equal_range(pident, PacketIDBirthdayCompare());
647
648 for(; chain.first != chain.second; chain.first++) {
649 if(chain.first->key.fd > -1) { // don't chain onto existing chained waiter!
650 /*
651 cerr<<"Orig: "<<pident.domain<<", "<<pident.remote.toString()<<", id="<<id<<endl;
652 cerr<<"Had hit: "<< chain.first->key.domain<<", "<<chain.first->key.remote.toString()<<", id="<<chain.first->key.id
653 <<", count="<<chain.first->key.chain.size()<<", origfd: "<<chain.first->key.fd<<endl;
654 */
655 chain.first->key.chain.insert(id); // we can chain
656 *fd=-1; // gets used in waitEvent / sendEvent later on
657 return 1;
658 }
659 }
660
661 int ret=t_udpclientsocks->getSocket(toaddr, fd);
662 if(ret < 0)
663 return ret;
664
665 pident.fd=*fd;
666 pident.id=id;
667
668 t_fdm->addReadFD(*fd, handleUDPServerResponse, pident);
669 ret = send(*fd, data, len, 0);
670
671 int tmp = errno;
672
673 if(ret < 0)
674 t_udpclientsocks->returnSocket(*fd);
675
676 errno = tmp; // this is for logging purposes only
677 return ret;
678 }
679
680 // -1 is error, 0 is timeout, 1 is success
681 int arecvfrom(std::string& packet, int flags, const ComboAddress& fromaddr, size_t *d_len,
682 uint16_t id, const DNSName& domain, uint16_t qtype, int fd, struct timeval* now)
683 {
684 static optional<unsigned int> nearMissLimit;
685 if(!nearMissLimit)
686 nearMissLimit=::arg().asNum("spoof-nearmiss-max");
687
688 PacketID pident;
689 pident.fd=fd;
690 pident.id=id;
691 pident.domain=domain;
692 pident.type = qtype;
693 pident.remote=fromaddr;
694
695 int ret=MT->waitEvent(pident, &packet, g_networkTimeoutMsec, now);
696
697 if(ret > 0) {
698 if(packet.empty()) // means "error"
699 return -1;
700
701 *d_len=packet.size();
702
703 if(*nearMissLimit && pident.nearMisses > *nearMissLimit) {
704 g_log<<Logger::Error<<"Too many ("<<pident.nearMisses<<" > "<<*nearMissLimit<<") bogus answers for '"<<domain<<"' from "<<fromaddr.toString()<<", assuming spoof attempt."<<endl;
705 g_stats.spoofCount++;
706 return -1;
707 }
708 }
709 else {
710 if(fd >= 0)
711 t_udpclientsocks->returnSocket(fd);
712 }
713 return ret;
714 }
715
716 static void writePid(void)
717 {
718 if(!::arg().mustDo("write-pid"))
719 return;
720 ofstream of(s_pidfname.c_str(), std::ios_base::app);
721 if(of)
722 of<< Utility::getpid() <<endl;
723 else
724 g_log<<Logger::Error<<"Writing pid for "<<Utility::getpid()<<" to "<<s_pidfname<<" failed: "<<strerror(errno)<<endl;
725 }
726
727 TCPConnection::TCPConnection(int fd, const ComboAddress& addr) : data(2, 0), d_remote(addr), d_fd(fd)
728 {
729 ++s_currentConnections;
730 (*t_tcpClientCounts)[d_remote]++;
731 }
732
733 TCPConnection::~TCPConnection()
734 {
735 try {
736 if(closesocket(d_fd) < 0)
737 g_log<<Logger::Error<<"Error closing socket for TCPConnection"<<endl;
738 }
739 catch(const PDNSException& e) {
740 g_log<<Logger::Error<<"Error closing TCPConnection socket: "<<e.reason<<endl;
741 }
742
743 if(t_tcpClientCounts->count(d_remote) && !(*t_tcpClientCounts)[d_remote]--)
744 t_tcpClientCounts->erase(d_remote);
745 --s_currentConnections;
746 }
747
748 AtomicCounter TCPConnection::s_currentConnections;
749
750 static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var);
751
752 // the idea is, only do things that depend on the *response* here. Incoming accounting is on incoming.
753 static void updateResponseStats(int res, const ComboAddress& remote, unsigned int packetsize, const DNSName* query, uint16_t qtype)
754 {
755 if(packetsize > 1000 && t_largeanswerremotes)
756 t_largeanswerremotes->push_back(remote);
757 switch(res) {
758 case RCode::ServFail:
759 if(t_servfailremotes) {
760 t_servfailremotes->push_back(remote);
761 if(query && t_servfailqueryring) // packet cache
762 t_servfailqueryring->push_back(make_pair(*query, qtype));
763 }
764 g_stats.servFails++;
765 break;
766 case RCode::NXDomain:
767 g_stats.nxDomains++;
768 break;
769 case RCode::NoError:
770 g_stats.noErrors++;
771 break;
772 }
773 }
774
775 static string makeLoginfo(const std::unique_ptr<DNSComboWriter>& dc)
776 try
777 {
778 return "("+dc->d_mdp.d_qname.toLogString()+"/"+DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)+" from "+(dc->getRemote())+")";
779 }
780 catch(...)
781 {
782 return "Exception making error message for exception";
783 }
784
785 #ifdef HAVE_PROTOBUF
786 static void protobufLogQuery(uint8_t maskV4, uint8_t maskV6, 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::vector<std::string>& policyTags, const std::string& requestorId, const std::string& deviceId)
787 {
788 if (!t_protobufServers) {
789 return;
790 }
791
792 Netmask requestorNM(remote, remote.sin4.sin_family == AF_INET ? maskV4 : maskV6);
793 const ComboAddress& requestor = requestorNM.getMaskedNetwork();
794 RecProtoBufMessage message(DNSProtoBufMessage::Query, uniqueId, &requestor, &local, qname, qtype, qclass, id, tcp, len);
795 message.setServerIdentity(SyncRes::s_serverID);
796 message.setEDNSSubnet(ednssubnet, ednssubnet.isIpv4() ? maskV4 : maskV6);
797 message.setRequestorId(requestorId);
798 message.setDeviceId(deviceId);
799
800 if (!policyTags.empty()) {
801 message.setPolicyTags(policyTags);
802 }
803
804 // cerr <<message.toDebugString()<<endl;
805 std::string str;
806 message.serialize(str);
807
808 for (auto& server : *t_protobufServers) {
809 server->queueData(str);
810 }
811 }
812
813 static void protobufLogResponse(const RecProtoBufMessage& message)
814 {
815 if (!t_protobufServers) {
816 return;
817 }
818
819 // cerr <<message.toDebugString()<<endl;
820 std::string str;
821 message.serialize(str);
822
823 for (auto& server : *t_protobufServers) {
824 server->queueData(str);
825 }
826 }
827 #endif
828
829 /**
830 * Chases the CNAME provided by the PolicyCustom RPZ policy.
831 *
832 * @param spoofed: The DNSRecord that was created by the policy, should already be added to ret
833 * @param qtype: The QType of the original query
834 * @param sr: A SyncRes
835 * @param res: An integer that will contain the RCODE of the lookup we do
836 * @param ret: A vector of DNSRecords where the result of the CNAME chase should be appended to
837 */
838 static void handleRPZCustom(const DNSRecord& spoofed, const QType& qtype, SyncRes& sr, int& res, vector<DNSRecord>& ret)
839 {
840 if (spoofed.d_type == QType::CNAME) {
841 bool oldWantsRPZ = sr.getWantsRPZ();
842 sr.setWantsRPZ(false);
843 vector<DNSRecord> ans;
844 res = sr.beginResolve(DNSName(spoofed.d_content->getZoneRepresentation()), qtype, QClass::IN, ans);
845 for (const auto& rec : ans) {
846 if(rec.d_place == DNSResourceRecord::ANSWER) {
847 ret.push_back(rec);
848 }
849 }
850 // Reset the RPZ state of the SyncRes
851 sr.setWantsRPZ(oldWantsRPZ);
852 }
853 }
854
855 static bool addRecordToPacket(DNSPacketWriter& pw, const DNSRecord& rec, uint32_t& minTTL, uint32_t ttlCap, const uint16_t maxAnswerSize)
856 {
857 pw.startRecord(rec.d_name, rec.d_type, (rec.d_ttl > ttlCap ? ttlCap : rec.d_ttl), rec.d_class, rec.d_place);
858
859 if(rec.d_type != QType::OPT) // their TTL ain't real
860 minTTL = min(minTTL, rec.d_ttl);
861
862 rec.d_content->toPacket(pw);
863 if(pw.size() > static_cast<size_t>(maxAnswerSize)) {
864 pw.rollback();
865 if(rec.d_place != DNSResourceRecord::ADDITIONAL) {
866 pw.getHeader()->tc=1;
867 pw.truncate();
868 }
869 return false;
870 }
871
872 return true;
873 }
874
875 #ifdef HAVE_PROTOBUF
876 static std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>> startProtobufServers(const ProtobufExportConfig& config)
877 {
878 auto result = std::make_shared<std::vector<std::unique_ptr<RemoteLogger>>>();
879
880 for (const auto& server : config.servers) {
881 try {
882 result->emplace_back(new RemoteLogger(server, config.timeout, 100*config.maxQueuedEntries, config.reconnectWaitTime, config.asyncConnect));
883 }
884 catch(const std::exception& e) {
885 g_log<<Logger::Error<<"Error while starting protobuf logger to '"<<server<<": "<<e.what()<<endl;
886 }
887 catch(const PDNSException& e) {
888 g_log<<Logger::Error<<"Error while starting protobuf logger to '"<<server<<": "<<e.reason<<endl;
889 }
890 }
891
892 return result;
893 }
894
895 static bool checkProtobufExport(LocalStateHolder<LuaConfigItems>& luaconfsLocal)
896 {
897 if (!luaconfsLocal->protobufExportConfig.enabled) {
898 if (t_protobufServers) {
899 for (auto& server : *t_protobufServers) {
900 server->stop();
901 }
902 t_protobufServers.reset();
903 }
904
905 return false;
906 }
907
908 /* if the server was not running, or if it was running according to a
909 previous configuration */
910 if (!t_protobufServers ||
911 t_protobufServersGeneration < luaconfsLocal->generation) {
912
913 if (t_protobufServers) {
914 for (auto& server : *t_protobufServers) {
915 server->stop();
916 }
917 }
918 t_protobufServers.reset();
919
920 t_protobufServers = startProtobufServers(luaconfsLocal->protobufExportConfig);
921 t_protobufServersGeneration = luaconfsLocal->generation;
922 }
923
924 return true;
925 }
926
927 static bool checkOutgoingProtobufExport(LocalStateHolder<LuaConfigItems>& luaconfsLocal)
928 {
929 if (!luaconfsLocal->outgoingProtobufExportConfig.enabled) {
930 if (t_outgoingProtobufServers) {
931 for (auto& server : *t_outgoingProtobufServers) {
932 server->stop();
933 }
934 }
935 t_outgoingProtobufServers.reset();
936
937 return false;
938 }
939
940 /* if the server was not running, or if it was running according to a
941 previous configuration */
942 if (!t_outgoingProtobufServers ||
943 t_outgoingProtobufServersGeneration < luaconfsLocal->generation) {
944
945 if (t_outgoingProtobufServers) {
946 for (auto& server : *t_outgoingProtobufServers) {
947 server->stop();
948 }
949 }
950 t_outgoingProtobufServers.reset();
951
952 t_outgoingProtobufServers = startProtobufServers(luaconfsLocal->outgoingProtobufExportConfig);
953 t_outgoingProtobufServersGeneration = luaconfsLocal->generation;
954 }
955
956 return true;
957 }
958 #endif /* HAVE_PROTOBUF */
959
960 #ifdef NOD_ENABLED
961 static bool nodCheckNewDomain(const DNSName& dname)
962 {
963 static const QType qt(QType::A);
964 static const uint16_t qc(QClass::IN);
965 bool ret = false;
966 // First check the (sub)domain isn't whitelisted for NOD purposes
967 if (!g_nodDomainWL.check(dname)) {
968 // Now check the NODDB (note this is probablistic so can have FNs/FPs)
969 if (t_nodDBp && t_nodDBp->isNewDomain(dname)) {
970 if (g_nodLog) {
971 // This should probably log to a dedicated log file
972 g_log<<Logger::Notice<<"Newly observed domain nod="<<dname.toLogString()<<endl;
973 }
974 if (!(g_nodLookupDomain.isRoot())) {
975 // Send a DNS A query to <domain>.g_nodLookupDomain
976 DNSName qname = dname;
977 vector<DNSRecord> dummy;
978 qname += g_nodLookupDomain;
979 directResolve(qname, qt, qc, dummy);
980 }
981 ret = true;
982 }
983 }
984 return ret;
985 }
986
987 static void nodAddDomain(const DNSName& dname)
988 {
989 // Don't bother adding domains on the nod whitelist
990 if (!g_nodDomainWL.check(dname)) {
991 if (t_nodDBp) {
992 // This keeps the nod info up to date
993 t_nodDBp->addDomain(dname);
994 }
995 }
996 }
997
998 static bool udrCheckUniqueDNSRecord(const DNSName& dname, uint16_t qtype, const DNSRecord& record)
999 {
1000 bool ret = false;
1001 if (record.d_place == DNSResourceRecord::ANSWER ||
1002 record.d_place == DNSResourceRecord::ADDITIONAL) {
1003 // Create a string that represent a triplet of (qname, qtype and RR[type, name, content])
1004 std::stringstream ss;
1005 ss << dname.toDNSStringLC() << ":" << qtype << ":" << qtype << ":" << record.d_type << ":" << record.d_name.toDNSStringLC() << ":" << record.d_content->getZoneRepresentation();
1006 if (t_udrDBp && t_udrDBp->isUniqueResponse(ss.str())) {
1007 if (g_udrLog) {
1008 // This should also probably log to a dedicated file.
1009 g_log<<Logger::Notice<<"Unique response observed: qname="<<dname.toLogString()<<" qtype="<<QType(qtype).getName()<< " rrtype=" << QType(record.d_type).getName() << " rrname=" << record.d_name.toLogString() << " rrcontent=" << record.d_content->getZoneRepresentation() << endl;
1010 }
1011 ret = true;
1012 }
1013 }
1014 return ret;
1015 }
1016 #endif /* NOD_ENABLED */
1017
1018 static void startDoResolve(void *p)
1019 {
1020 auto dc=std::unique_ptr<DNSComboWriter>(reinterpret_cast<DNSComboWriter*>(p));
1021 try {
1022 if (t_queryring)
1023 t_queryring->push_back(make_pair(dc->d_mdp.d_qname, dc->d_mdp.d_qtype));
1024
1025 uint16_t maxanswersize = dc->d_tcp ? 65535 : min(static_cast<uint16_t>(512), g_udpTruncationThreshold);
1026 EDNSOpts edo;
1027 std::vector<pair<uint16_t, string> > ednsOpts;
1028 bool variableAnswer = dc->d_variable;
1029 bool haveEDNS=false;
1030 #ifdef NOD_ENABLED
1031 bool hasUDR = false;
1032 #endif /* NOD_ENABLED */
1033 DNSPacketWriter::optvect_t returnedEdnsOptions; // Here we stuff all the options for the return packet
1034 uint8_t ednsExtRCode = 0;
1035 if(getEDNSOpts(dc->d_mdp, &edo)) {
1036 haveEDNS=true;
1037 if (edo.d_version != 0) {
1038 ednsExtRCode = ERCode::BADVERS;
1039 }
1040
1041 if(!dc->d_tcp) {
1042 /* rfc6891 6.2.3:
1043 "Values lower than 512 MUST be treated as equal to 512."
1044 */
1045 maxanswersize = min(static_cast<uint16_t>(edo.d_packetsize >= 512 ? edo.d_packetsize : 512), g_udpTruncationThreshold);
1046 }
1047 ednsOpts = edo.d_options;
1048 maxanswersize -= 11; // EDNS header size
1049
1050 for (const auto& o : edo.d_options) {
1051 if (o.first == EDNSOptionCode::ECS && g_useIncomingECS && !dc->d_ecsParsed) {
1052 dc->d_ecsFound = getEDNSSubnetOptsFromString(o.second, &dc->d_ednssubnet);
1053 } else if (o.first == EDNSOptionCode::NSID) {
1054 const static string mode_server_id = ::arg()["server-id"];
1055 if(mode_server_id != "disabled" && !mode_server_id.empty() &&
1056 maxanswersize > (2 + 2 + mode_server_id.size())) {
1057 returnedEdnsOptions.push_back(make_pair(EDNSOptionCode::NSID, mode_server_id));
1058 variableAnswer = true; // Can't packetcache an answer with NSID
1059 // Option Code and Option Length are both 2
1060 maxanswersize -= 2 + 2 + mode_server_id.size();
1061 }
1062 }
1063 }
1064 }
1065 /* perhaps there was no EDNS or no ECS but by now we looked */
1066 dc->d_ecsParsed = true;
1067 vector<DNSRecord> ret;
1068 vector<uint8_t> packet;
1069
1070 auto luaconfsLocal = g_luaconfs.getLocal();
1071 // Used to tell syncres later on if we should apply NSDNAME and NSIP RPZ triggers for this query
1072 bool wantsRPZ(true);
1073 boost::optional<RecProtoBufMessage> pbMessage(boost::none);
1074 bool logResponse = false;
1075 #ifdef HAVE_PROTOBUF
1076 if (checkProtobufExport(luaconfsLocal)) {
1077 logResponse = t_protobufServers && luaconfsLocal->protobufExportConfig.logResponses;
1078 Netmask requestorNM(dc->d_source, dc->d_source.sin4.sin_family == AF_INET ? luaconfsLocal->protobufMaskV4 : luaconfsLocal->protobufMaskV6);
1079 const ComboAddress& requestor = requestorNM.getMaskedNetwork();
1080 pbMessage = RecProtoBufMessage(RecProtoBufMessage::Response, dc->d_uuid, &requestor, &dc->d_destination, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass, dc->d_mdp.d_header.id, dc->d_tcp, 0);
1081 pbMessage->setServerIdentity(SyncRes::s_serverID);
1082 pbMessage->setEDNSSubnet(dc->d_ednssubnet.source, dc->d_ednssubnet.source.isIpv4() ? luaconfsLocal->protobufMaskV4 : luaconfsLocal->protobufMaskV6);
1083 }
1084 #endif /* HAVE_PROTOBUF */
1085
1086 DNSPacketWriter pw(packet, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass);
1087
1088 pw.getHeader()->aa=0;
1089 pw.getHeader()->ra=1;
1090 pw.getHeader()->qr=1;
1091 pw.getHeader()->tc=0;
1092 pw.getHeader()->id=dc->d_mdp.d_header.id;
1093 pw.getHeader()->rd=dc->d_mdp.d_header.rd;
1094 pw.getHeader()->cd=dc->d_mdp.d_header.cd;
1095
1096 /* This is the lowest TTL seen in the records of the response,
1097 so we can't cache it for longer than this value.
1098 If we have a TTL cap, this value can't be larger than the
1099 cap no matter what. */
1100 uint32_t minTTL = dc->d_ttlCap;
1101
1102 SyncRes sr(dc->d_now);
1103
1104 bool DNSSECOK=false;
1105 if(t_pdl) {
1106 sr.setLuaEngine(t_pdl);
1107 }
1108 if(g_dnssecmode != DNSSECMode::Off) {
1109 sr.setDoDNSSEC(true);
1110
1111 // Does the requestor want DNSSEC records?
1112 if(edo.d_extFlags & EDNSOpts::DNSSECOK) {
1113 DNSSECOK=true;
1114 g_stats.dnssecQueries++;
1115 }
1116 if (dc->d_mdp.d_header.cd) {
1117 /* Per rfc6840 section 5.9, "When processing a request with
1118 the Checking Disabled (CD) bit set, a resolver SHOULD attempt
1119 to return all response data, even data that has failed DNSSEC
1120 validation. */
1121 ++g_stats.dnssecCheckDisabledQueries;
1122 }
1123 if (dc->d_mdp.d_header.ad) {
1124 /* Per rfc6840 section 5.7, "the AD bit in a query as a signal
1125 indicating that the requester understands and is interested in the
1126 value of the AD bit in the response. This allows a requester to
1127 indicate that it understands the AD bit without also requesting
1128 DNSSEC data via the DO bit. */
1129 ++g_stats.dnssecAuthenticDataQueries;
1130 }
1131 } else {
1132 // Ignore the client-set CD flag
1133 pw.getHeader()->cd=0;
1134 }
1135 sr.setDNSSECValidationRequested(g_dnssecmode == DNSSECMode::ValidateAll || g_dnssecmode==DNSSECMode::ValidateForLog || ((dc->d_mdp.d_header.ad || DNSSECOK) && g_dnssecmode==DNSSECMode::Process));
1136
1137 #ifdef HAVE_PROTOBUF
1138 sr.setInitialRequestId(dc->d_uuid);
1139 sr.setOutgoingProtobufServers(t_outgoingProtobufServers);
1140 #endif
1141
1142 sr.setQuerySource(dc->d_remote, g_useIncomingECS && !dc->d_ednssubnet.source.empty() ? boost::optional<const EDNSSubnetOpts&>(dc->d_ednssubnet) : boost::none);
1143
1144 bool tracedQuery=false; // we could consider letting Lua know about this too
1145 bool shouldNotValidate = false;
1146
1147 /* preresolve expects res (dq.rcode) to be set to RCode::NoError by default */
1148 int res = RCode::NoError;
1149 DNSFilterEngine::Policy appliedPolicy;
1150 std::vector<DNSRecord> spoofed;
1151 RecursorLua4::DNSQuestion dq(dc->d_source, dc->d_destination, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_tcp, variableAnswer, wantsRPZ, logResponse);
1152 dq.ednsFlags = &edo.d_extFlags;
1153 dq.ednsOptions = &ednsOpts;
1154 dq.tag = dc->d_tag;
1155 dq.discardedPolicies = &sr.d_discardedPolicies;
1156 dq.policyTags = &dc->d_policyTags;
1157 dq.appliedPolicy = &appliedPolicy;
1158 dq.currentRecords = &ret;
1159 dq.dh = &dc->d_mdp.d_header;
1160 dq.data = dc->d_data;
1161 #ifdef HAVE_PROTOBUF
1162 dq.requestorId = dc->d_requestorId;
1163 dq.deviceId = dc->d_deviceId;
1164 #endif
1165
1166 if(ednsExtRCode != 0) {
1167 goto sendit;
1168 }
1169
1170 if(dc->d_mdp.d_qtype==QType::ANY && !dc->d_tcp && g_anyToTcp) {
1171 pw.getHeader()->tc = 1;
1172 res = 0;
1173 variableAnswer = true;
1174 goto sendit;
1175 }
1176
1177 if(t_traceRegex && t_traceRegex->match(dc->d_mdp.d_qname.toString())) {
1178 sr.setLogMode(SyncRes::Store);
1179 tracedQuery=true;
1180 }
1181
1182
1183 if(!g_quiet || tracedQuery) {
1184 g_log<<Logger::Warning<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] " << (dc->d_tcp ? "TCP " : "") << "question for '"<<dc->d_mdp.d_qname<<"|"
1185 <<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)<<"' from "<<dc->getRemote();
1186 if(!dc->d_ednssubnet.source.empty()) {
1187 g_log<<" (ecs "<<dc->d_ednssubnet.source.toString()<<")";
1188 }
1189 g_log<<endl;
1190 }
1191
1192 sr.setId(MT->getTid());
1193 if(!dc->d_mdp.d_header.rd)
1194 sr.setCacheOnly();
1195
1196 if (t_pdl) {
1197 t_pdl->prerpz(dq, res);
1198 }
1199
1200 // Check if the query has a policy attached to it
1201 if (wantsRPZ) {
1202 appliedPolicy = luaconfsLocal->dfe.getQueryPolicy(dc->d_mdp.d_qname, dc->d_source, sr.d_discardedPolicies);
1203 }
1204
1205 // if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve
1206 if(!t_pdl || !t_pdl->preresolve(dq, res)) {
1207
1208 sr.setWantsRPZ(wantsRPZ);
1209 if(wantsRPZ) {
1210 switch(appliedPolicy.d_kind) {
1211 case DNSFilterEngine::PolicyKind::NoAction:
1212 break;
1213 case DNSFilterEngine::PolicyKind::Drop:
1214 g_stats.policyDrops++;
1215 g_stats.policyResults[appliedPolicy.d_kind]++;
1216 return;
1217 case DNSFilterEngine::PolicyKind::NXDOMAIN:
1218 g_stats.policyResults[appliedPolicy.d_kind]++;
1219 res=RCode::NXDomain;
1220 goto haveAnswer;
1221 case DNSFilterEngine::PolicyKind::NODATA:
1222 g_stats.policyResults[appliedPolicy.d_kind]++;
1223 res=RCode::NoError;
1224 goto haveAnswer;
1225 case DNSFilterEngine::PolicyKind::Custom:
1226 g_stats.policyResults[appliedPolicy.d_kind]++;
1227 res=RCode::NoError;
1228 spoofed=appliedPolicy.getCustomRecords(dc->d_mdp.d_qname, dc->d_mdp.d_qtype);
1229 for (const auto& dr : spoofed) {
1230 ret.push_back(dr);
1231 handleRPZCustom(dr, QType(dc->d_mdp.d_qtype), sr, res, ret);
1232 }
1233 goto haveAnswer;
1234 case DNSFilterEngine::PolicyKind::Truncate:
1235 if(!dc->d_tcp) {
1236 g_stats.policyResults[appliedPolicy.d_kind]++;
1237 res=RCode::NoError;
1238 pw.getHeader()->tc=1;
1239 goto haveAnswer;
1240 }
1241 break;
1242 }
1243 }
1244
1245 // Query got not handled for QNAME Policy reasons, now actually go out to find an answer
1246 try {
1247 res = sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret);
1248 shouldNotValidate = sr.wasOutOfBand();
1249 }
1250 catch(ImmediateServFailException &e) {
1251 if(g_logCommonErrors)
1252 g_log<<Logger::Notice<<"Sending SERVFAIL to "<<dc->getRemote()<<" during resolve of '"<<dc->d_mdp.d_qname<<"' because: "<<e.reason<<endl;
1253 res = RCode::ServFail;
1254 }
1255
1256 dq.validationState = sr.getValidationState();
1257
1258 // During lookup, an NSDNAME or NSIP trigger was hit in RPZ
1259 if (res == -2) { // XXX This block should be macro'd, it is repeated post-resolve.
1260 appliedPolicy = sr.d_appliedPolicy;
1261 g_stats.policyResults[appliedPolicy.d_kind]++;
1262 switch(appliedPolicy.d_kind) {
1263 case DNSFilterEngine::PolicyKind::NoAction: // This can never happen
1264 throw PDNSException("NoAction policy returned while a NSDNAME or NSIP trigger was hit");
1265 case DNSFilterEngine::PolicyKind::Drop:
1266 g_stats.policyDrops++;
1267 return;
1268 case DNSFilterEngine::PolicyKind::NXDOMAIN:
1269 ret.clear();
1270 res=RCode::NXDomain;
1271 goto haveAnswer;
1272
1273 case DNSFilterEngine::PolicyKind::NODATA:
1274 ret.clear();
1275 res=RCode::NoError;
1276 goto haveAnswer;
1277
1278 case DNSFilterEngine::PolicyKind::Truncate:
1279 if(!dc->d_tcp) {
1280 ret.clear();
1281 res=RCode::NoError;
1282 pw.getHeader()->tc=1;
1283 goto haveAnswer;
1284 }
1285 break;
1286
1287 case DNSFilterEngine::PolicyKind::Custom:
1288 ret.clear();
1289 res=RCode::NoError;
1290 spoofed=appliedPolicy.getCustomRecords(dc->d_mdp.d_qname, dc->d_mdp.d_qtype);
1291 for (const auto& dr : spoofed) {
1292 ret.push_back(dr);
1293 handleRPZCustom(dr, QType(dc->d_mdp.d_qtype), sr, res, ret);
1294 }
1295 goto haveAnswer;
1296 }
1297 }
1298
1299 if (wantsRPZ) {
1300 appliedPolicy = luaconfsLocal->dfe.getPostPolicy(ret, sr.d_discardedPolicies);
1301 }
1302
1303 if(t_pdl) {
1304 if(res == RCode::NoError) {
1305 auto i=ret.cbegin();
1306 for(; i!= ret.cend(); ++i)
1307 if(i->d_type == dc->d_mdp.d_qtype && i->d_place == DNSResourceRecord::ANSWER)
1308 break;
1309 if(i == ret.cend() && t_pdl->nodata(dq, res))
1310 shouldNotValidate = true;
1311
1312 }
1313 else if(res == RCode::NXDomain && t_pdl->nxdomain(dq, res))
1314 shouldNotValidate = true;
1315
1316 if(t_pdl->postresolve(dq, res))
1317 shouldNotValidate = true;
1318 }
1319
1320 if (wantsRPZ) { //XXX This block is repeated, see above
1321 g_stats.policyResults[appliedPolicy.d_kind]++;
1322 switch(appliedPolicy.d_kind) {
1323 case DNSFilterEngine::PolicyKind::NoAction:
1324 break;
1325 case DNSFilterEngine::PolicyKind::Drop:
1326 g_stats.policyDrops++;
1327 return;
1328 case DNSFilterEngine::PolicyKind::NXDOMAIN:
1329 ret.clear();
1330 res=RCode::NXDomain;
1331 goto haveAnswer;
1332
1333 case DNSFilterEngine::PolicyKind::NODATA:
1334 ret.clear();
1335 res=RCode::NoError;
1336 goto haveAnswer;
1337
1338 case DNSFilterEngine::PolicyKind::Truncate:
1339 if(!dc->d_tcp) {
1340 ret.clear();
1341 res=RCode::NoError;
1342 pw.getHeader()->tc=1;
1343 goto haveAnswer;
1344 }
1345 break;
1346
1347 case DNSFilterEngine::PolicyKind::Custom:
1348 ret.clear();
1349 res=RCode::NoError;
1350 spoofed=appliedPolicy.getCustomRecords(dc->d_mdp.d_qname, dc->d_mdp.d_qtype);
1351 for (const auto& dr : spoofed) {
1352 ret.push_back(dr);
1353 handleRPZCustom(dr, QType(dc->d_mdp.d_qtype), sr, res, ret);
1354 }
1355 goto haveAnswer;
1356 }
1357 }
1358 }
1359 haveAnswer:;
1360 if(res == PolicyDecision::DROP) {
1361 g_stats.policyDrops++;
1362 return;
1363 }
1364 if(tracedQuery || res == -1 || res == RCode::ServFail || pw.getHeader()->rcode == RCode::ServFail)
1365 {
1366 string trace(sr.getTrace());
1367 if(!trace.empty()) {
1368 vector<string> lines;
1369 boost::split(lines, trace, boost::is_any_of("\n"));
1370 for(const string& line : lines) {
1371 if(!line.empty())
1372 g_log<<Logger::Warning<< line << endl;
1373 }
1374 }
1375 }
1376
1377 if(res == -1) {
1378 pw.getHeader()->rcode=RCode::ServFail;
1379 // no commit here, because no record
1380 g_stats.servFails++;
1381 }
1382 else {
1383 pw.getHeader()->rcode=res;
1384
1385 // Does the validation mode or query demand validation?
1386 if(!shouldNotValidate && sr.isDNSSECValidationRequested()) {
1387 try {
1388 if(sr.doLog()) {
1389 g_log<<Logger::Warning<<"Starting validation of answer to "<<dc->d_mdp.d_qname<<"|"<<QType(dc->d_mdp.d_qtype).getName()<<" for "<<dc->getRemote()<<endl;
1390 }
1391
1392 auto state = sr.getValidationState();
1393
1394 if(state == Secure) {
1395 if(sr.doLog()) {
1396 g_log<<Logger::Warning<<"Answer to "<<dc->d_mdp.d_qname<<"|"<<QType(dc->d_mdp.d_qtype).getName()<<" for "<<dc->getRemote()<<" validates correctly"<<endl;
1397 }
1398
1399 // Is the query source interested in the value of the ad-bit?
1400 if (dc->d_mdp.d_header.ad || DNSSECOK)
1401 pw.getHeader()->ad=1;
1402 }
1403 else if(state == Insecure) {
1404 if(sr.doLog()) {
1405 g_log<<Logger::Warning<<"Answer to "<<dc->d_mdp.d_qname<<"|"<<QType(dc->d_mdp.d_qtype).getName()<<" for "<<dc->getRemote()<<" validates as Insecure"<<endl;
1406 }
1407
1408 pw.getHeader()->ad=0;
1409 }
1410 else if(state == Bogus) {
1411 if(t_bogusremotes)
1412 t_bogusremotes->push_back(dc->d_source);
1413 if(t_bogusqueryring)
1414 t_bogusqueryring->push_back(make_pair(dc->d_mdp.d_qname, dc->d_mdp.d_qtype));
1415 if(g_dnssecLogBogus || sr.doLog() || g_dnssecmode == DNSSECMode::ValidateForLog) {
1416 g_log<<Logger::Warning<<"Answer to "<<dc->d_mdp.d_qname<<"|"<<QType(dc->d_mdp.d_qtype).getName()<<" for "<<dc->getRemote()<<" validates as Bogus"<<endl;
1417 }
1418
1419 // Does the query or validation mode sending out a SERVFAIL on validation errors?
1420 if(!pw.getHeader()->cd && (g_dnssecmode == DNSSECMode::ValidateAll || dc->d_mdp.d_header.ad || DNSSECOK)) {
1421 if(sr.doLog()) {
1422 g_log<<Logger::Warning<<"Sending out SERVFAIL for "<<dc->d_mdp.d_qname<<"|"<<QType(dc->d_mdp.d_qtype).getName()<<" because recursor or query demands it for Bogus results"<<endl;
1423 }
1424
1425 pw.getHeader()->rcode=RCode::ServFail;
1426 goto sendit;
1427 } else {
1428 if(sr.doLog()) {
1429 g_log<<Logger::Warning<<"Not sending out SERVFAIL for "<<dc->d_mdp.d_qname<<"|"<<QType(dc->d_mdp.d_qtype).getName()<<" Bogus validation since neither config nor query demands this"<<endl;
1430 }
1431 }
1432 }
1433 }
1434 catch(ImmediateServFailException &e) {
1435 if(g_logCommonErrors)
1436 g_log<<Logger::Notice<<"Sending SERVFAIL to "<<dc->getRemote()<<" during validation of '"<<dc->d_mdp.d_qname<<"|"<<QType(dc->d_mdp.d_qtype).getName()<<"' because: "<<e.reason<<endl;
1437 pw.getHeader()->rcode=RCode::ServFail;
1438 goto sendit;
1439 }
1440 }
1441
1442 if(ret.size()) {
1443 orderAndShuffle(ret);
1444 if(auto sl = luaconfsLocal->sortlist.getOrderCmp(dc->d_source)) {
1445 stable_sort(ret.begin(), ret.end(), *sl);
1446 variableAnswer=true;
1447 }
1448 }
1449
1450 bool needCommit = false;
1451 for(auto i=ret.cbegin(); i!=ret.cend(); ++i) {
1452 if( ! DNSSECOK &&
1453 ( i->d_type == QType::NSEC3 ||
1454 (
1455 ( i->d_type == QType::RRSIG || i->d_type==QType::NSEC ) &&
1456 (
1457 ( dc->d_mdp.d_qtype != i->d_type && dc->d_mdp.d_qtype != QType::ANY ) ||
1458 i->d_place != DNSResourceRecord::ANSWER
1459 )
1460 )
1461 )
1462 ) {
1463 continue;
1464 }
1465
1466 if (!addRecordToPacket(pw, *i, minTTL, dc->d_ttlCap, maxanswersize)) {
1467 needCommit = false;
1468 break;
1469 }
1470 needCommit = true;
1471
1472 #ifdef NOD_ENABLED
1473 bool udr = false;
1474 if (g_udrEnabled) {
1475 udr = udrCheckUniqueDNSRecord(dc->d_mdp.d_qname, dc->d_mdp.d_qtype, *i);
1476 if (!hasUDR && udr)
1477 hasUDR = true;
1478 }
1479 #endif /* NOD ENABLED */
1480
1481 #ifdef HAVE_PROTOBUF
1482 if (t_protobufServers) {
1483 #ifdef NOD_ENABLED
1484 pbMessage->addRR(*i, luaconfsLocal->protobufExportConfig.exportTypes, udr);
1485 #else
1486 pbMessage->addRR(*i, luaconfsLocal->protobufExportConfig.exportTypes);
1487 #endif /* NOD_ENABLED */
1488 }
1489 #endif
1490 }
1491 if(needCommit)
1492 pw.commit();
1493 }
1494 sendit:;
1495
1496 if(g_useIncomingECS && dc->d_ecsFound && !sr.wasVariable() && !variableAnswer) {
1497 // cerr<<"Stuffing in a 0 scope because answer is static"<<endl;
1498 EDNSSubnetOpts eo;
1499 eo.source = dc->d_ednssubnet.source;
1500 ComboAddress sa;
1501 sa.reset();
1502 sa.sin4.sin_family = eo.source.getNetwork().sin4.sin_family;
1503 eo.scope = Netmask(sa, 0);
1504
1505 returnedEdnsOptions.push_back(make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(eo)));
1506 }
1507
1508 if (haveEDNS) {
1509 /* we try to add the EDNS OPT RR even for truncated answers,
1510 as rfc6891 states:
1511 "The minimal response MUST be the DNS header, question section, and an
1512 OPT record. This MUST also occur when a truncated response (using
1513 the DNS header's TC bit) is returned."
1514 */
1515 pw.addOpt(512, ednsExtRCode, DNSSECOK ? EDNSOpts::DNSSECOK : 0, returnedEdnsOptions);
1516 pw.commit();
1517 }
1518
1519 g_rs.submitResponse(dc->d_mdp.d_qtype, packet.size(), !dc->d_tcp);
1520 updateResponseStats(res, dc->d_source, packet.size(), &dc->d_mdp.d_qname, dc->d_mdp.d_qtype);
1521 #ifdef NOD_ENABLED
1522 bool nod = false;
1523 if (g_nodEnabled) {
1524 if (nodCheckNewDomain(dc->d_mdp.d_qname))
1525 nod = true;
1526 }
1527 #endif /* NOD_ENABLED */
1528 #ifdef HAVE_PROTOBUF
1529 if (t_protobufServers && logResponse && !(luaconfsLocal->protobufExportConfig.taggedOnly && (!appliedPolicy.d_name || appliedPolicy.d_name->empty()) && dc->d_policyTags.empty())) {
1530 pbMessage->setBytes(packet.size());
1531 pbMessage->setResponseCode(pw.getHeader()->rcode);
1532 if (appliedPolicy.d_name) {
1533 pbMessage->setAppliedPolicy(*appliedPolicy.d_name);
1534 pbMessage->setAppliedPolicyType(appliedPolicy.d_type);
1535 }
1536 pbMessage->setPolicyTags(dc->d_policyTags);
1537 pbMessage->setQueryTime(dc->d_now.tv_sec, dc->d_now.tv_usec);
1538 pbMessage->setRequestorId(dq.requestorId);
1539 pbMessage->setDeviceId(dq.deviceId);
1540 #ifdef NOD_ENABLED
1541 if (g_nodEnabled) {
1542 if (nod) {
1543 pbMessage->setNOD(true);
1544 pbMessage->addPolicyTag(g_nod_pbtag);
1545 }
1546 if (hasUDR) {
1547 pbMessage->addPolicyTag(g_udr_pbtag);
1548 }
1549 }
1550 #endif /* NOD_ENABLED */
1551 protobufLogResponse(*pbMessage);
1552 #ifdef NOD_ENABLED
1553 if (g_nodEnabled) {
1554 pbMessage->setNOD(false);
1555 pbMessage->clearUDR();
1556 if (nod)
1557 pbMessage->removePolicyTag(g_nod_pbtag);
1558 if (hasUDR)
1559 pbMessage->removePolicyTag(g_udr_pbtag);
1560 }
1561 #endif /* NOD_ENABLED */
1562 }
1563 #endif
1564 if(!dc->d_tcp) {
1565 struct msghdr msgh;
1566 struct iovec iov;
1567 char cbuf[256];
1568 fillMSGHdr(&msgh, &iov, cbuf, 0, (char*)&*packet.begin(), packet.size(), &dc->d_remote);
1569 msgh.msg_control=NULL;
1570
1571 if(g_fromtosockets.count(dc->d_socket)) {
1572 addCMsgSrcAddr(&msgh, cbuf, &dc->d_local, 0);
1573 }
1574 if(sendmsg(dc->d_socket, &msgh, 0) < 0 && g_logCommonErrors)
1575 g_log<<Logger::Warning<<"Sending UDP reply to client "<<dc->getRemote()<<" failed with: "<<strerror(errno)<<endl;
1576
1577 if(variableAnswer || sr.wasVariable()) {
1578 g_stats.variableResponses++;
1579 }
1580 if(!SyncRes::s_nopacketcache && !variableAnswer && !sr.wasVariable() ) {
1581 t_packetCache->insertResponsePacket(dc->d_tag, dc->d_qhash, std::move(dc->d_query), dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass,
1582 string((const char*)&*packet.begin(), packet.size()),
1583 g_now.tv_sec,
1584 pw.getHeader()->rcode == RCode::ServFail ? SyncRes::s_packetcacheservfailttl :
1585 min(minTTL,SyncRes::s_packetcachettl),
1586 dq.validationState,
1587 dc->d_ecsBegin,
1588 dc->d_ecsEnd,
1589 std::move(pbMessage));
1590 }
1591 // else cerr<<"Not putting in packet cache: "<<sr.wasVariable()<<endl;
1592 }
1593 else {
1594 char buf[2];
1595 buf[0]=packet.size()/256;
1596 buf[1]=packet.size()%256;
1597
1598 Utility::iovec iov[2];
1599
1600 iov[0].iov_base=(void*)buf; iov[0].iov_len=2;
1601 iov[1].iov_base=(void*)&*packet.begin(); iov[1].iov_len = packet.size();
1602
1603 int wret=Utility::writev(dc->d_socket, iov, 2);
1604 bool hadError=true;
1605
1606 if(wret == 0)
1607 g_log<<Logger::Error<<"EOF writing TCP answer to "<<dc->getRemote()<<endl;
1608 else if(wret < 0 )
1609 g_log<<Logger::Error<<"Error writing TCP answer to "<<dc->getRemote()<<": "<< strerror(errno) <<endl;
1610 else if((unsigned int)wret != 2 + packet.size())
1611 g_log<<Logger::Error<<"Oops, partial answer sent to "<<dc->getRemote()<<" for "<<dc->d_mdp.d_qname<<" (size="<< (2 + packet.size()) <<", sent "<<wret<<")"<<endl;
1612 else
1613 hadError=false;
1614
1615 // update tcp connection status, either by closing or moving to 'BYTE0'
1616
1617 if(hadError) {
1618 // no need to remove us from FDM, we weren't there
1619 dc->d_socket = -1;
1620 }
1621 else {
1622 dc->d_tcpConnection->queriesCount++;
1623 if (g_tcpMaxQueriesPerConn && dc->d_tcpConnection->queriesCount >= g_tcpMaxQueriesPerConn) {
1624 dc->d_socket = -1;
1625 }
1626 else {
1627 dc->d_tcpConnection->state=TCPConnection::BYTE0;
1628 Utility::gettimeofday(&g_now, 0); // needs to be updated
1629 t_fdm->addReadFD(dc->d_socket, handleRunningTCPQuestion, dc->d_tcpConnection);
1630 t_fdm->setReadTTD(dc->d_socket, g_now, g_tcpTimeout);
1631 }
1632 }
1633 }
1634 float spent=makeFloat(sr.getNow()-dc->d_now);
1635 if(!g_quiet) {
1636 g_log<<Logger::Error<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] answer to "<<(dc->d_mdp.d_header.rd?"":"non-rd ")<<"question '"<<dc->d_mdp.d_qname<<"|"<<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype);
1637 g_log<<"': "<<ntohs(pw.getHeader()->ancount)<<" answers, "<<ntohs(pw.getHeader()->arcount)<<" additional, took "<<sr.d_outqueries<<" packets, "<<
1638 sr.d_totUsec/1000.0<<" netw ms, "<< spent*1000.0<<" tot ms, "<<
1639 sr.d_throttledqueries<<" throttled, "<<sr.d_timeouts<<" timeouts, "<<sr.d_tcpoutqueries<<" tcp connections, rcode="<< res;
1640
1641 if(!shouldNotValidate && sr.isDNSSECValidationRequested()) {
1642 g_log<< ", dnssec="<<vStates[sr.getValidationState()];
1643 }
1644
1645 g_log<<endl;
1646
1647 }
1648
1649 if (sr.d_outqueries || sr.d_authzonequeries) {
1650 t_RC->cacheMisses++;
1651 }
1652 else {
1653 t_RC->cacheHits++;
1654 }
1655
1656 if(spent < 0.001)
1657 g_stats.answers0_1++;
1658 else if(spent < 0.010)
1659 g_stats.answers1_10++;
1660 else if(spent < 0.1)
1661 g_stats.answers10_100++;
1662 else if(spent < 1.0)
1663 g_stats.answers100_1000++;
1664 else
1665 g_stats.answersSlow++;
1666
1667 uint64_t newLat=(uint64_t)(spent*1000000);
1668 newLat = min(newLat,(uint64_t)(((uint64_t) g_networkTimeoutMsec)*1000)); // outliers of several minutes exist..
1669 g_stats.avgLatencyUsec=(1-1.0/g_latencyStatSize)*g_stats.avgLatencyUsec + (float)newLat/g_latencyStatSize;
1670 // no worries, we do this for packet cache hits elsewhere
1671
1672 auto ourtime = 1000.0*spent-sr.d_totUsec/1000.0; // in msec
1673 if(ourtime < 1)
1674 g_stats.ourtime0_1++;
1675 else if(ourtime < 2)
1676 g_stats.ourtime1_2++;
1677 else if(ourtime < 4)
1678 g_stats.ourtime2_4++;
1679 else if(ourtime < 8)
1680 g_stats.ourtime4_8++;
1681 else if(ourtime < 16)
1682 g_stats.ourtime8_16++;
1683 else if(ourtime < 32)
1684 g_stats.ourtime16_32++;
1685 else {
1686 // cerr<<"SLOW: "<<ourtime<<"ms -> "<<dc->d_mdp.d_qname<<"|"<<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)<<endl;
1687 g_stats.ourtimeSlow++;
1688 }
1689 if(ourtime >= 0.0) {
1690 newLat=ourtime*1000; // usec
1691 g_stats.avgLatencyOursUsec=(1-1.0/g_latencyStatSize)*g_stats.avgLatencyOursUsec + (float)newLat/g_latencyStatSize;
1692 }
1693 // cout<<dc->d_mdp.d_qname<<"\t"<<MT->getUsec()<<"\t"<<sr.d_outqueries<<endl;
1694 }
1695 catch(PDNSException &ae) {
1696 g_log<<Logger::Error<<"startDoResolve problem "<<makeLoginfo(dc)<<": "<<ae.reason<<endl;
1697 }
1698 catch(const MOADNSException &mde) {
1699 g_log<<Logger::Error<<"DNS parser error "<<makeLoginfo(dc) <<": "<<dc->d_mdp.d_qname<<", "<<mde.what()<<endl;
1700 }
1701 catch(std::exception& e) {
1702 g_log<<Logger::Error<<"STL error "<< makeLoginfo(dc)<<": "<<e.what();
1703
1704 // Luawrapper nests the exception from Lua, so we unnest it here
1705 try {
1706 std::rethrow_if_nested(e);
1707 } catch(const std::exception& ne) {
1708 g_log<<". Extra info: "<<ne.what();
1709 } catch(...) {}
1710
1711 g_log<<endl;
1712 }
1713 catch(...) {
1714 g_log<<Logger::Error<<"Any other exception in a resolver context "<< makeLoginfo(dc) <<endl;
1715 }
1716
1717 g_stats.maxMThreadStackUsage = max(MT->getMaxStackUsage(), g_stats.maxMThreadStackUsage);
1718 }
1719
1720 static void makeControlChannelSocket(int processNum=-1)
1721 {
1722 string sockname=::arg()["socket-dir"]+"/"+s_programname;
1723 if(processNum >= 0)
1724 sockname += "."+std::to_string(processNum);
1725 sockname+=".controlsocket";
1726 s_rcc.listen(sockname);
1727
1728 int sockowner = -1;
1729 int sockgroup = -1;
1730
1731 if (!::arg().isEmpty("socket-group"))
1732 sockgroup=::arg().asGid("socket-group");
1733 if (!::arg().isEmpty("socket-owner"))
1734 sockowner=::arg().asUid("socket-owner");
1735
1736 if (sockgroup > -1 || sockowner > -1) {
1737 if(chown(sockname.c_str(), sockowner, sockgroup) < 0) {
1738 unixDie("Failed to chown control socket");
1739 }
1740 }
1741
1742 // do mode change if socket-mode is given
1743 if(!::arg().isEmpty("socket-mode")) {
1744 mode_t sockmode=::arg().asMode("socket-mode");
1745 if(chmod(sockname.c_str(), sockmode) < 0) {
1746 unixDie("Failed to chmod control socket");
1747 }
1748 }
1749 }
1750
1751 static void getQNameAndSubnet(const std::string& question, DNSName* dnsname, uint16_t* qtype, uint16_t* qclass,
1752 bool& foundECS, EDNSSubnetOpts* ednssubnet, EDNSOptionViewMap* options,
1753 bool& foundXPF, ComboAddress* xpfSource, ComboAddress* xpfDest)
1754 {
1755 const bool lookForXPF = xpfSource != nullptr && g_xpfRRCode != 0;
1756 const bool lookForECS = ednssubnet != nullptr;
1757 const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(question.c_str());
1758 size_t questionLen = question.length();
1759 unsigned int consumed=0;
1760 *dnsname=DNSName(question.c_str(), questionLen, sizeof(dnsheader), false, qtype, qclass, &consumed);
1761
1762 size_t pos= sizeof(dnsheader)+consumed+4;
1763 const size_t headerSize = /* root */ 1 + sizeof(dnsrecordheader);
1764 const uint16_t arcount = ntohs(dh->arcount);
1765
1766 for (uint16_t arpos = 0; arpos < arcount && questionLen > (pos + headerSize) && ((lookForECS && !foundECS) || (lookForXPF && !foundXPF)); arpos++) {
1767 if (question.at(pos) != 0) {
1768 /* not an OPT or a XPF, bye. */
1769 return;
1770 }
1771
1772 pos += 1;
1773 const dnsrecordheader* drh = reinterpret_cast<const dnsrecordheader*>(&question.at(pos));
1774 pos += sizeof(dnsrecordheader);
1775
1776 if (pos >= questionLen) {
1777 return;
1778 }
1779
1780 /* OPT root label (1) followed by type (2) */
1781 if(lookForECS && ntohs(drh->d_type) == QType::OPT) {
1782 if (!options) {
1783 char* ecsStart = nullptr;
1784 size_t ecsLen = 0;
1785 /* we need to pass the record len */
1786 int res = getEDNSOption(const_cast<char*>(reinterpret_cast<const char*>(&question.at(pos - sizeof(drh->d_clen)))), questionLen - pos + sizeof(drh->d_clen), EDNSOptionCode::ECS, &ecsStart, &ecsLen);
1787 if (res == 0 && ecsLen > 4) {
1788 EDNSSubnetOpts eso;
1789 if(getEDNSSubnetOptsFromString(ecsStart + 4, ecsLen - 4, &eso)) {
1790 *ednssubnet=eso;
1791 foundECS = true;
1792 }
1793 }
1794 }
1795 else {
1796 /* we need to pass the record len */
1797 int res = getEDNSOptions(reinterpret_cast<const char*>(&question.at(pos -sizeof(drh->d_clen))), questionLen - pos + (sizeof(drh->d_clen)), *options);
1798 if (res == 0) {
1799 const auto& it = options->find(EDNSOptionCode::ECS);
1800 if (it != options->end() && !it->second.values.empty() && it->second.values.at(0).content != nullptr && it->second.values.at(0).size > 0) {
1801 EDNSSubnetOpts eso;
1802 if(getEDNSSubnetOptsFromString(it->second.values.at(0).content, it->second.values.at(0).size, &eso)) {
1803 *ednssubnet=eso;
1804 foundECS = true;
1805 }
1806 }
1807 }
1808 }
1809 }
1810 else if (lookForXPF && ntohs(drh->d_type) == g_xpfRRCode && ntohs(drh->d_class) == QClass::IN && drh->d_ttl == 0) {
1811 if ((questionLen - pos) < ntohs(drh->d_clen)) {
1812 return;
1813 }
1814
1815 foundXPF = parseXPFPayload(reinterpret_cast<const char*>(&question.at(pos)), ntohs(drh->d_clen), *xpfSource, xpfDest);
1816 }
1817
1818 pos += ntohs(drh->d_clen);
1819 }
1820 }
1821
1822 static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)
1823 {
1824 shared_ptr<TCPConnection> conn=any_cast<shared_ptr<TCPConnection> >(var);
1825
1826 if(conn->state==TCPConnection::BYTE0) {
1827 ssize_t bytes=recv(conn->getFD(), &conn->data[0], 2, 0);
1828 if(bytes==1)
1829 conn->state=TCPConnection::BYTE1;
1830 if(bytes==2) {
1831 conn->qlen=(((unsigned char)conn->data[0]) << 8)+ (unsigned char)conn->data[1];
1832 conn->data.resize(conn->qlen);
1833 conn->bytesread=0;
1834 conn->state=TCPConnection::GETQUESTION;
1835 }
1836 if(!bytes || bytes < 0) {
1837 t_fdm->removeReadFD(fd);
1838 return;
1839 }
1840 }
1841 else if(conn->state==TCPConnection::BYTE1) {
1842 ssize_t bytes=recv(conn->getFD(), &conn->data[1], 1, 0);
1843 if(bytes==1) {
1844 conn->state=TCPConnection::GETQUESTION;
1845 conn->qlen=(((unsigned char)conn->data[0]) << 8)+ (unsigned char)conn->data[1];
1846 conn->data.resize(conn->qlen);
1847 conn->bytesread=0;
1848 }
1849 if(!bytes || bytes < 0) {
1850 if(g_logCommonErrors)
1851 g_log<<Logger::Error<<"TCP client "<< conn->d_remote.toStringWithPort() <<" disconnected after first byte"<<endl;
1852 t_fdm->removeReadFD(fd);
1853 return;
1854 }
1855 }
1856 else if(conn->state==TCPConnection::GETQUESTION) {
1857 ssize_t bytes=recv(conn->getFD(), &conn->data[conn->bytesread], conn->qlen - conn->bytesread, 0);
1858 if(!bytes || bytes < 0 || bytes > std::numeric_limits<std::uint16_t>::max()) {
1859 if(g_logCommonErrors) {
1860 g_log<<Logger::Error<<"TCP client "<< conn->d_remote.toStringWithPort() <<" disconnected while reading question body"<<endl;
1861 }
1862 t_fdm->removeReadFD(fd);
1863 return;
1864 }
1865 conn->bytesread+=(uint16_t)bytes;
1866 if(conn->bytesread==conn->qlen) {
1867 t_fdm->removeReadFD(fd); // should no longer awake ourselves when there is data to read
1868
1869 std::unique_ptr<DNSComboWriter> dc;
1870 try {
1871 dc=std::unique_ptr<DNSComboWriter>(new DNSComboWriter(conn->data, g_now));
1872 }
1873 catch(const MOADNSException &mde) {
1874 g_stats.clientParseError++;
1875 if(g_logCommonErrors)
1876 g_log<<Logger::Error<<"Unable to parse packet from TCP client "<< conn->d_remote.toStringWithPort() <<endl;
1877 return;
1878 }
1879 dc->d_tcpConnection = conn; // carry the torch
1880 dc->setSocket(conn->getFD()); // this is the only time a copy is made of the actual fd
1881 dc->d_tcp=true;
1882 dc->setRemote(conn->d_remote);
1883 dc->setSource(conn->d_remote);
1884 ComboAddress dest;
1885 dest.reset();
1886 dest.sin4.sin_family = conn->d_remote.sin4.sin_family;
1887 socklen_t len = dest.getSocklen();
1888 getsockname(conn->getFD(), (sockaddr*)&dest, &len); // if this fails, we're ok with it
1889 dc->setLocal(dest);
1890 dc->setDestination(dest);
1891 DNSName qname;
1892 uint16_t qtype=0;
1893 uint16_t qclass=0;
1894 bool needECS = false;
1895 bool needXPF = g_XPFAcl.match(conn->d_remote);
1896 string requestorId;
1897 string deviceId;
1898 bool logQuery = false;
1899 #ifdef HAVE_PROTOBUF
1900 auto luaconfsLocal = g_luaconfs.getLocal();
1901 if (checkProtobufExport(luaconfsLocal)) {
1902 needECS = true;
1903 }
1904 logQuery = t_protobufServers && luaconfsLocal->protobufExportConfig.logQueries;
1905 #endif
1906
1907 if(needECS || needXPF || (t_pdl && (t_pdl->d_gettag_ffi || t_pdl->d_gettag))) {
1908
1909 try {
1910 EDNSOptionViewMap ednsOptions;
1911 bool xpfFound = false;
1912 dc->d_ecsParsed = true;
1913 dc->d_ecsFound = false;
1914 getQNameAndSubnet(conn->data, &qname, &qtype, &qclass,
1915 dc->d_ecsFound, &dc->d_ednssubnet, g_gettagNeedsEDNSOptions ? &ednsOptions : nullptr,
1916 xpfFound, needXPF ? &dc->d_source : nullptr, needXPF ? &dc->d_destination : nullptr);
1917
1918 if(t_pdl) {
1919 try {
1920 if (t_pdl->d_gettag_ffi) {
1921 dc->d_tag = t_pdl->gettag_ffi(dc->d_source, dc->d_ednssubnet.source, dc->d_destination, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptions, true, requestorId, deviceId, dc->d_ttlCap, dc->d_variable, logQuery);
1922 }
1923 else if (t_pdl->d_gettag) {
1924 dc->d_tag = t_pdl->gettag(dc->d_source, dc->d_ednssubnet.source, dc->d_destination, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptions, true, requestorId, deviceId);
1925 }
1926 }
1927 catch(const std::exception& e) {
1928 if(g_logCommonErrors)
1929 g_log<<Logger::Warning<<"Error parsing a query packet qname='"<<qname<<"' for tag determination, setting tag=0: "<<e.what()<<endl;
1930 }
1931 }
1932 }
1933 catch(const std::exception& e)
1934 {
1935 if(g_logCommonErrors)
1936 g_log<<Logger::Warning<<"Error parsing a query packet for tag determination, setting tag=0: "<<e.what()<<endl;
1937 }
1938 }
1939
1940 const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(&conn->data[0]);
1941
1942 #ifdef HAVE_PROTOBUF
1943 if(t_protobufServers || t_outgoingProtobufServers) {
1944 dc->d_requestorId = requestorId;
1945 dc->d_deviceId = deviceId;
1946 dc->d_uuid = getUniqueID();
1947 }
1948
1949 if(t_protobufServers) {
1950 try {
1951
1952 if (logQuery && !(luaconfsLocal->protobufExportConfig.taggedOnly && dc->d_policyTags.empty())) {
1953 protobufLogQuery(luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, dc->d_uuid, dc->d_source, dc->d_destination, dc->d_ednssubnet.source, true, dh->id, conn->qlen, qname, qtype, qclass, dc->d_policyTags, dc->d_requestorId, dc->d_deviceId);
1954 }
1955 }
1956 catch(std::exception& e) {
1957 if(g_logCommonErrors)
1958 g_log<<Logger::Warning<<"Error parsing a TCP query packet for edns subnet: "<<e.what()<<endl;
1959 }
1960 }
1961 #endif
1962 if(t_pdl) {
1963 if(t_pdl->ipfilter(dc->d_source, dc->d_destination, *dh)) {
1964 if(!g_quiet)
1965 g_log<<Logger::Notice<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] DROPPED TCP question from "<<dc->d_source.toStringWithPort()<<(dc->d_source != dc->d_remote ? " (via "+dc->d_remote.toStringWithPort()+")" : "")<<" based on policy"<<endl;
1966 g_stats.policyDrops++;
1967 return;
1968 }
1969 }
1970
1971 if(dc->d_mdp.d_header.qr) {
1972 g_stats.ignoredCount++;
1973 if(g_logCommonErrors) {
1974 g_log<<Logger::Error<<"Ignoring answer from TCP client "<< dc->getRemote() <<" on server socket!"<<endl;
1975 }
1976 return;
1977 }
1978 if(dc->d_mdp.d_header.opcode) {
1979 g_stats.ignoredCount++;
1980 if(g_logCommonErrors) {
1981 g_log<<Logger::Error<<"Ignoring non-query opcode from TCP client "<< dc->getRemote() <<" on server socket!"<<endl;
1982 }
1983 return;
1984 }
1985 else if (dh->qdcount == 0) {
1986 g_stats.emptyQueriesCount++;
1987 if(g_logCommonErrors) {
1988 g_log<<Logger::Error<<"Ignoring empty (qdcount == 0) query from "<< dc->getRemote() <<" on server socket!"<<endl;
1989 }
1990 return;
1991 }
1992 else {
1993 ++g_stats.qcounter;
1994 ++g_stats.tcpqcounter;
1995 MT->makeThread(startDoResolve, dc.release()); // deletes dc, will set state to BYTE0 again
1996 return;
1997 }
1998 }
1999 }
2000 }
2001
2002 //! Handle new incoming TCP connection
2003 static void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t& )
2004 {
2005 ComboAddress addr;
2006 socklen_t addrlen=sizeof(addr);
2007 int newsock=accept(fd, (struct sockaddr*)&addr, &addrlen);
2008 if(newsock>=0) {
2009 if(MT->numProcesses() > g_maxMThreads) {
2010 g_stats.overCapacityDrops++;
2011 try {
2012 closesocket(newsock);
2013 }
2014 catch(const PDNSException& e) {
2015 g_log<<Logger::Error<<"Error closing TCP socket after an over capacity drop: "<<e.reason<<endl;
2016 }
2017 return;
2018 }
2019
2020 if(t_remotes)
2021 t_remotes->push_back(addr);
2022 if(t_allowFrom && !t_allowFrom->match(&addr)) {
2023 if(!g_quiet)
2024 g_log<<Logger::Error<<"["<<MT->getTid()<<"] dropping TCP query from "<<addr.toString()<<", address not matched by allow-from"<<endl;
2025
2026 g_stats.unauthorizedTCP++;
2027 try {
2028 closesocket(newsock);
2029 }
2030 catch(const PDNSException& e) {
2031 g_log<<Logger::Error<<"Error closing TCP socket after an ACL drop: "<<e.reason<<endl;
2032 }
2033 return;
2034 }
2035 if(g_maxTCPPerClient && t_tcpClientCounts->count(addr) && (*t_tcpClientCounts)[addr] >= g_maxTCPPerClient) {
2036 g_stats.tcpClientOverflow++;
2037 try {
2038 closesocket(newsock); // don't call TCPConnection::closeAndCleanup here - did not enter it in the counts yet!
2039 }
2040 catch(const PDNSException& e) {
2041 g_log<<Logger::Error<<"Error closing TCP socket after an overflow drop: "<<e.reason<<endl;
2042 }
2043 return;
2044 }
2045
2046 setNonBlocking(newsock);
2047 std::shared_ptr<TCPConnection> tc = std::make_shared<TCPConnection>(newsock, addr);
2048 tc->state=TCPConnection::BYTE0;
2049
2050 t_fdm->addReadFD(tc->getFD(), handleRunningTCPQuestion, tc);
2051
2052 struct timeval now;
2053 Utility::gettimeofday(&now, 0);
2054 t_fdm->setReadTTD(tc->getFD(), now, g_tcpTimeout);
2055 }
2056 }
2057
2058 static string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fromaddr, const ComboAddress& destaddr, struct timeval tv, int fd)
2059 {
2060 gettimeofday(&g_now, 0);
2061 struct timeval diff = g_now - tv;
2062 double delta=(diff.tv_sec*1000 + diff.tv_usec/1000.0);
2063
2064 if(tv.tv_sec && delta > 1000.0) {
2065 g_stats.tooOldDrops++;
2066 return 0;
2067 }
2068
2069 ++g_stats.qcounter;
2070 if(fromaddr.sin4.sin_family==AF_INET6)
2071 g_stats.ipv6qcounter++;
2072
2073 string response;
2074 const struct dnsheader* dh = (struct dnsheader*)question.c_str();
2075 unsigned int ctag=0;
2076 uint32_t qhash = 0;
2077 bool needECS = false;
2078 bool needXPF = g_XPFAcl.match(fromaddr);
2079 std::vector<std::string> policyTags;
2080 LuaContext::LuaObject data;
2081 ComboAddress source = fromaddr;
2082 ComboAddress destination = destaddr;
2083 string requestorId;
2084 string deviceId;
2085 bool logQuery = false;
2086 #ifdef HAVE_PROTOBUF
2087 boost::uuids::uuid uniqueId;
2088 auto luaconfsLocal = g_luaconfs.getLocal();
2089 if (checkProtobufExport(luaconfsLocal)) {
2090 uniqueId = getUniqueID();
2091 needECS = true;
2092 } else if (checkOutgoingProtobufExport(luaconfsLocal)) {
2093 uniqueId = getUniqueID();
2094 }
2095 logQuery = t_protobufServers && luaconfsLocal->protobufExportConfig.logQueries;
2096 bool logResponse = t_protobufServers && luaconfsLocal->protobufExportConfig.logResponses;
2097 #endif
2098 EDNSSubnetOpts ednssubnet;
2099 bool ecsFound = false;
2100 bool ecsParsed = false;
2101 uint16_t ecsBegin = 0;
2102 uint16_t ecsEnd = 0;
2103 uint32_t ttlCap = std::numeric_limits<uint32_t>::max();
2104 bool variable = false;
2105 try {
2106 DNSName qname;
2107 uint16_t qtype=0;
2108 uint16_t qclass=0;
2109 uint32_t age;
2110 bool qnameParsed=false;
2111 #ifdef MALLOC_TRACE
2112 /*
2113 static uint64_t last=0;
2114 if(!last)
2115 g_mtracer->clearAllocators();
2116 cout<<g_mtracer->getAllocs()-last<<" "<<g_mtracer->getNumOut()<<" -- BEGIN TRACE"<<endl;
2117 last=g_mtracer->getAllocs();
2118 cout<<g_mtracer->topAllocatorsString()<<endl;
2119 g_mtracer->clearAllocators();
2120 */
2121 #endif
2122
2123 if(needECS || needXPF || (t_pdl && (t_pdl->d_gettag || t_pdl->d_gettag_ffi))) {
2124 try {
2125 EDNSOptionViewMap ednsOptions;
2126 bool xpfFound = false;
2127
2128 ecsFound = false;
2129
2130 getQNameAndSubnet(question, &qname, &qtype, &qclass,
2131 ecsFound, &ednssubnet, g_gettagNeedsEDNSOptions ? &ednsOptions : nullptr,
2132 xpfFound, needXPF ? &source : nullptr, needXPF ? &destination : nullptr);
2133
2134 qnameParsed = true;
2135 ecsParsed = true;
2136
2137 if(t_pdl) {
2138 try {
2139 if (t_pdl->d_gettag_ffi) {
2140 ctag = t_pdl->gettag_ffi(source, ednssubnet.source, destination, qname, qtype, &policyTags, data, ednsOptions, false, requestorId, deviceId, ttlCap, variable, logQuery);
2141 }
2142 else if (t_pdl->d_gettag) {
2143 ctag = t_pdl->gettag(source, ednssubnet.source, destination, qname, qtype, &policyTags, data, ednsOptions, false, requestorId, deviceId);
2144 }
2145 }
2146 catch(const std::exception& e) {
2147 if(g_logCommonErrors)
2148 g_log<<Logger::Warning<<"Error parsing a query packet qname='"<<qname<<"' for tag determination, setting tag=0: "<<e.what()<<endl;
2149 }
2150 }
2151 }
2152 catch(const std::exception& e)
2153 {
2154 if(g_logCommonErrors)
2155 g_log<<Logger::Warning<<"Error parsing a query packet for tag determination, setting tag=0: "<<e.what()<<endl;
2156 }
2157 }
2158
2159 bool cacheHit = false;
2160 boost::optional<RecProtoBufMessage> pbMessage(boost::none);
2161 #ifdef HAVE_PROTOBUF
2162 if (t_protobufServers) {
2163 pbMessage = RecProtoBufMessage(DNSProtoBufMessage::DNSProtoBufMessageType::Response);
2164 pbMessage->setServerIdentity(SyncRes::s_serverID);
2165 if (logQuery && !(luaconfsLocal->protobufExportConfig.taggedOnly && policyTags.empty())) {
2166 protobufLogQuery(luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, uniqueId, source, destination, ednssubnet.source, false, dh->id, question.size(), qname, qtype, qclass, policyTags, requestorId, deviceId);
2167 }
2168 }
2169 #endif /* HAVE_PROTOBUF */
2170
2171 /* It might seem like a good idea to skip the packet cache lookup if we know that the answer is not cacheable,
2172 but it means that the hash would not be computed. If some script decides at a later time to mark back the answer
2173 as cacheable we would cache it with a wrong tag, so better safe than sorry. */
2174 vState valState;
2175 if (qnameParsed) {
2176 cacheHit = (!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(ctag, question, qname, qtype, qclass, g_now.tv_sec, &response, &age, &valState, &qhash, &ecsBegin, &ecsEnd, pbMessage ? &(*pbMessage) : nullptr));
2177 }
2178 else {
2179 cacheHit = (!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(ctag, question, qname, &qtype, &qclass, g_now.tv_sec, &response, &age, &valState, &qhash, &ecsBegin, &ecsEnd, pbMessage ? &(*pbMessage) : nullptr));
2180 }
2181
2182 if (cacheHit) {
2183 if(valState == Bogus) {
2184 if(t_bogusremotes)
2185 t_bogusremotes->push_back(source);
2186 if(t_bogusqueryring)
2187 t_bogusqueryring->push_back(make_pair(qname, qtype));
2188 }
2189
2190 #ifdef HAVE_PROTOBUF
2191 if(t_protobufServers && logResponse && !(luaconfsLocal->protobufExportConfig.taggedOnly && pbMessage->getAppliedPolicy().empty() && pbMessage->getPolicyTags().empty())) {
2192 Netmask requestorNM(source, source.sin4.sin_family == AF_INET ? luaconfsLocal->protobufMaskV4 : luaconfsLocal->protobufMaskV6);
2193 const ComboAddress& requestor = requestorNM.getMaskedNetwork();
2194 pbMessage->update(uniqueId, &requestor, &destination, false, dh->id);
2195 pbMessage->setEDNSSubnet(ednssubnet.source, ednssubnet.source.isIpv4() ? luaconfsLocal->protobufMaskV4 : luaconfsLocal->protobufMaskV6);
2196 pbMessage->setQueryTime(g_now.tv_sec, g_now.tv_usec);
2197 pbMessage->setRequestorId(requestorId);
2198 pbMessage->setDeviceId(deviceId);
2199 protobufLogResponse(*pbMessage);
2200 }
2201 #endif /* HAVE_PROTOBUF */
2202 if(!g_quiet)
2203 g_log<<Logger::Notice<<t_id<< " question answered from packet cache tag="<<ctag<<" from "<<source.toStringWithPort()<<(source != fromaddr ? " (via "+fromaddr.toStringWithPort()+")" : "")<<endl;
2204
2205 g_stats.packetCacheHits++;
2206 SyncRes::s_queries++;
2207 ageDNSPacket(response, age);
2208 struct msghdr msgh;
2209 struct iovec iov;
2210 char cbuf[256];
2211 fillMSGHdr(&msgh, &iov, cbuf, 0, (char*)response.c_str(), response.length(), const_cast<ComboAddress*>(&fromaddr));
2212 msgh.msg_control=NULL;
2213
2214 if(g_fromtosockets.count(fd)) {
2215 addCMsgSrcAddr(&msgh, cbuf, &destaddr, 0);
2216 }
2217 if(sendmsg(fd, &msgh, 0) < 0 && g_logCommonErrors)
2218 g_log<<Logger::Warning<<"Sending UDP reply to client "<<source.toStringWithPort()<<(source != fromaddr ? " (via "+fromaddr.toStringWithPort()+")" : "")<<" failed with: "<<strerror(errno)<<endl;
2219
2220 if(response.length() >= sizeof(struct dnsheader)) {
2221 struct dnsheader tmpdh;
2222 memcpy(&tmpdh, response.c_str(), sizeof(tmpdh));
2223 updateResponseStats(tmpdh.rcode, source, response.length(), 0, 0);
2224 }
2225 g_stats.avgLatencyUsec=(1-1.0/g_latencyStatSize)*g_stats.avgLatencyUsec + 0.0; // we assume 0 usec
2226 g_stats.avgLatencyOursUsec=(1-1.0/g_latencyStatSize)*g_stats.avgLatencyOursUsec + 0.0; // we assume 0 usec
2227 return 0;
2228 }
2229 }
2230 catch(std::exception& e) {
2231 g_log<<Logger::Error<<"Error processing or aging answer packet: "<<e.what()<<endl;
2232 return 0;
2233 }
2234
2235 if(t_pdl) {
2236 if(t_pdl->ipfilter(source, destination, *dh)) {
2237 if(!g_quiet)
2238 g_log<<Logger::Notice<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] DROPPED question from "<<source.toStringWithPort()<<(source != fromaddr ? " (via "+fromaddr.toStringWithPort()+")" : "")<<" based on policy"<<endl;
2239 g_stats.policyDrops++;
2240 return 0;
2241 }
2242 }
2243
2244 if(MT->numProcesses() > g_maxMThreads) {
2245 if(!g_quiet)
2246 g_log<<Logger::Notice<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] DROPPED question from "<<source.toStringWithPort()<<(source != fromaddr ? " (via "+fromaddr.toStringWithPort()+")" : "")<<", over capacity"<<endl;
2247
2248 g_stats.overCapacityDrops++;
2249 return 0;
2250 }
2251
2252 auto dc = std::unique_ptr<DNSComboWriter>(new DNSComboWriter(question, g_now, std::move(policyTags), std::move(data)));
2253 dc->setSocket(fd);
2254 dc->d_tag=ctag;
2255 dc->d_qhash=qhash;
2256 dc->setRemote(fromaddr);
2257 dc->setSource(source);
2258 dc->setLocal(destaddr);
2259 dc->setDestination(destination);
2260 dc->d_tcp=false;
2261 dc->d_ecsFound = ecsFound;
2262 dc->d_ecsParsed = ecsParsed;
2263 dc->d_ecsBegin = ecsBegin;
2264 dc->d_ecsEnd = ecsEnd;
2265 dc->d_ednssubnet = ednssubnet;
2266 dc->d_ttlCap = ttlCap;
2267 dc->d_variable = variable;
2268 #ifdef HAVE_PROTOBUF
2269 if (t_protobufServers || t_outgoingProtobufServers) {
2270 dc->d_uuid = std::move(uniqueId);
2271 }
2272 dc->d_requestorId = requestorId;
2273 dc->d_deviceId = deviceId;
2274 #endif
2275
2276 MT->makeThread(startDoResolve, (void*) dc.release()); // deletes dc
2277 return 0;
2278 }
2279
2280
2281 static void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
2282 {
2283 ssize_t len;
2284 static const size_t maxIncomingQuerySize = 512;
2285 static thread_local std::string data;
2286 ComboAddress fromaddr;
2287 struct msghdr msgh;
2288 struct iovec iov;
2289 char cbuf[256];
2290 bool firstQuery = true;
2291
2292 for(size_t queriesCounter = 0; queriesCounter < s_maxUDPQueriesPerRound; queriesCounter++) {
2293 data.resize(maxIncomingQuerySize);
2294 fromaddr.sin6.sin6_family=AF_INET6; // this makes sure fromaddr is big enough
2295 fillMSGHdr(&msgh, &iov, cbuf, sizeof(cbuf), &data[0], data.size(), &fromaddr);
2296
2297 if((len=recvmsg(fd, &msgh, 0)) >= 0) {
2298
2299 firstQuery = false;
2300
2301 if (static_cast<size_t>(len) < sizeof(dnsheader)) {
2302 g_stats.ignoredCount++;
2303 if (!g_quiet) {
2304 g_log<<Logger::Error<<"Ignoring too-short ("<<std::to_string(len)<<") query from "<<fromaddr.toString()<<endl;
2305 }
2306 return;
2307 }
2308
2309 if (msgh.msg_flags & MSG_TRUNC) {
2310 g_stats.truncatedDrops++;
2311 if (!g_quiet) {
2312 g_log<<Logger::Error<<"Ignoring truncated query from "<<fromaddr.toString()<<endl;
2313 }
2314 return;
2315 }
2316
2317 if(t_remotes) {
2318 t_remotes->push_back(fromaddr);
2319 }
2320
2321 if(t_allowFrom && !t_allowFrom->match(&fromaddr)) {
2322 if(!g_quiet) {
2323 g_log<<Logger::Error<<"["<<MT->getTid()<<"] dropping UDP query from "<<fromaddr.toString()<<", address not matched by allow-from"<<endl;
2324 }
2325
2326 g_stats.unauthorizedUDP++;
2327 return;
2328 }
2329 BOOST_STATIC_ASSERT(offsetof(sockaddr_in, sin_port) == offsetof(sockaddr_in6, sin6_port));
2330 if(!fromaddr.sin4.sin_port) { // also works for IPv6
2331 if(!g_quiet) {
2332 g_log<<Logger::Error<<"["<<MT->getTid()<<"] dropping UDP query from "<<fromaddr.toStringWithPort()<<", can't deal with port 0"<<endl;
2333 }
2334
2335 g_stats.clientParseError++; // not quite the best place to put it, but needs to go somewhere
2336 return;
2337 }
2338
2339 try {
2340 data.resize(static_cast<size_t>(len));
2341 dnsheader* dh=(dnsheader*)&data[0];
2342
2343 if(dh->qr) {
2344 g_stats.ignoredCount++;
2345 if(g_logCommonErrors) {
2346 g_log<<Logger::Error<<"Ignoring answer from "<<fromaddr.toString()<<" on server socket!"<<endl;
2347 }
2348 }
2349 else if(dh->opcode) {
2350 g_stats.ignoredCount++;
2351 if(g_logCommonErrors) {
2352 g_log<<Logger::Error<<"Ignoring non-query opcode "<<dh->opcode<<" from "<<fromaddr.toString()<<" on server socket!"<<endl;
2353 }
2354 }
2355 else if (dh->qdcount == 0) {
2356 g_stats.emptyQueriesCount++;
2357 if(g_logCommonErrors) {
2358 g_log<<Logger::Error<<"Ignoring empty (qdcount == 0) query from "<<fromaddr.toString()<<" on server socket!"<<endl;
2359 }
2360 }
2361 else {
2362 struct timeval tv={0,0};
2363 HarvestTimestamp(&msgh, &tv);
2364 ComboAddress dest;
2365 dest.reset(); // this makes sure we ignore this address if not returned by recvmsg above
2366 auto loc = rplookup(g_listenSocketsAddresses, fd);
2367 if(HarvestDestinationAddress(&msgh, &dest)) {
2368 // but.. need to get port too
2369 if(loc) {
2370 dest.sin4.sin_port = loc->sin4.sin_port;
2371 }
2372 }
2373 else {
2374 if(loc) {
2375 dest = *loc;
2376 }
2377 else {
2378 dest.sin4.sin_family = fromaddr.sin4.sin_family;
2379 socklen_t slen = dest.getSocklen();
2380 getsockname(fd, (sockaddr*)&dest, &slen); // if this fails, we're ok with it
2381 }
2382 }
2383
2384 if(g_weDistributeQueries) {
2385 distributeAsyncFunction(data, boost::bind(doProcessUDPQuestion, data, fromaddr, dest, tv, fd));
2386 }
2387 else {
2388 doProcessUDPQuestion(data, fromaddr, dest, tv, fd);
2389 }
2390 }
2391 }
2392 catch(const MOADNSException &mde) {
2393 g_stats.clientParseError++;
2394 if(g_logCommonErrors) {
2395 g_log<<Logger::Error<<"Unable to parse packet from remote UDP client "<<fromaddr.toString() <<": "<<mde.what()<<endl;
2396 }
2397 }
2398 catch(const std::runtime_error& e) {
2399 g_stats.clientParseError++;
2400 if(g_logCommonErrors) {
2401 g_log<<Logger::Error<<"Unable to parse packet from remote UDP client "<<fromaddr.toString() <<": "<<e.what()<<endl;
2402 }
2403 }
2404 }
2405 else {
2406 // cerr<<t_id<<" had error: "<<stringerror()<<endl;
2407 if(firstQuery && errno == EAGAIN) {
2408 g_stats.noPacketError++;
2409 }
2410
2411 break;
2412 }
2413 }
2414 }
2415
2416 static void makeTCPServerSockets(deferredAdd_t& deferredAdds, std::set<int>& tcpSockets)
2417 {
2418 int fd;
2419 vector<string>locals;
2420 stringtok(locals,::arg()["local-address"]," ,");
2421
2422 if(locals.empty())
2423 throw PDNSException("No local address specified");
2424
2425 for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
2426 ServiceTuple st;
2427 st.port=::arg().asNum("local-port");
2428 parseService(*i, st);
2429
2430 ComboAddress sin;
2431
2432 sin.reset();
2433 sin.sin4.sin_family = AF_INET;
2434 if(!IpToU32(st.host, (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
2435 sin.sin6.sin6_family = AF_INET6;
2436 if(makeIPv6sockaddr(st.host, &sin.sin6) < 0)
2437 throw PDNSException("Unable to resolve local address for TCP server on '"+ st.host +"'");
2438 }
2439
2440 fd=socket(sin.sin6.sin6_family, SOCK_STREAM, 0);
2441 if(fd<0)
2442 throw PDNSException("Making a TCP server socket for resolver: "+stringerror());
2443
2444 setCloseOnExec(fd);
2445
2446 int tmp=1;
2447 if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof tmp)<0) {
2448 g_log<<Logger::Error<<"Setsockopt failed for TCP listening socket"<<endl;
2449 exit(1);
2450 }
2451 if(sin.sin6.sin6_family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &tmp, sizeof(tmp)) < 0) {
2452 g_log<<Logger::Error<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<strerror(errno)<<endl;
2453 }
2454
2455 #ifdef TCP_DEFER_ACCEPT
2456 if(setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &tmp, sizeof tmp) >= 0) {
2457 if(i==locals.begin())
2458 g_log<<Logger::Info<<"Enabled TCP data-ready filter for (slight) DoS protection"<<endl;
2459 }
2460 #endif
2461
2462 if( ::arg().mustDo("non-local-bind") )
2463 Utility::setBindAny(AF_INET, fd);
2464
2465 #ifdef SO_REUSEPORT
2466 if(g_reusePort) {
2467 if(setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &tmp, sizeof(tmp)) < 0)
2468 throw PDNSException("SO_REUSEPORT: "+stringerror());
2469 }
2470 #endif
2471
2472 if (::arg().asNum("tcp-fast-open") > 0) {
2473 #ifdef TCP_FASTOPEN
2474 int fastOpenQueueSize = ::arg().asNum("tcp-fast-open");
2475 if (setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &fastOpenQueueSize, sizeof fastOpenQueueSize) < 0) {
2476 g_log<<Logger::Error<<"Failed to enable TCP Fast Open for listening socket: "<<strerror(errno)<<endl;
2477 }
2478 #else
2479 g_log<<Logger::Warning<<"TCP Fast Open configured but not supported for listening socket"<<endl;
2480 #endif
2481 }
2482
2483 sin.sin4.sin_port = htons(st.port);
2484 socklen_t socklen=sin.sin4.sin_family==AF_INET ? sizeof(sin.sin4) : sizeof(sin.sin6);
2485 if (::bind(fd, (struct sockaddr *)&sin, socklen )<0)
2486 throw PDNSException("Binding TCP server socket for "+ st.host +": "+stringerror());
2487
2488 setNonBlocking(fd);
2489 setSocketSendBuffer(fd, 65000);
2490 listen(fd, 128);
2491 deferredAdds.push_back(make_pair(fd, handleNewTCPQuestion));
2492 tcpSockets.insert(fd);
2493
2494 // we don't need to update g_listenSocketsAddresses since it doesn't work for TCP/IP:
2495 // - fd is not that which we know here, but returned from accept()
2496 if(sin.sin4.sin_family == AF_INET)
2497 g_log<<Logger::Info<<"Listening for TCP queries on "<< sin.toString() <<":"<<st.port<<endl;
2498 else
2499 g_log<<Logger::Info<<"Listening for TCP queries on ["<< sin.toString() <<"]:"<<st.port<<endl;
2500 }
2501 }
2502
2503 static void makeUDPServerSockets(deferredAdd_t& deferredAdds)
2504 {
2505 int one=1;
2506 vector<string>locals;
2507 stringtok(locals,::arg()["local-address"]," ,");
2508
2509 if(locals.empty())
2510 throw PDNSException("No local address specified");
2511
2512 for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
2513 ServiceTuple st;
2514 st.port=::arg().asNum("local-port");
2515 parseService(*i, st);
2516
2517 ComboAddress sin;
2518
2519 sin.reset();
2520 sin.sin4.sin_family = AF_INET;
2521 if(!IpToU32(st.host.c_str() , (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
2522 sin.sin6.sin6_family = AF_INET6;
2523 if(makeIPv6sockaddr(st.host, &sin.sin6) < 0)
2524 throw PDNSException("Unable to resolve local address for UDP server on '"+ st.host +"'");
2525 }
2526
2527 int fd=socket(sin.sin4.sin_family, SOCK_DGRAM, 0);
2528 if(fd < 0) {
2529 throw PDNSException("Making a UDP server socket for resolver: "+netstringerror());
2530 }
2531 if (!setSocketTimestamps(fd))
2532 g_log<<Logger::Warning<<"Unable to enable timestamp reporting for socket"<<endl;
2533
2534 if(IsAnyAddress(sin)) {
2535 if(sin.sin4.sin_family == AF_INET)
2536 if(!setsockopt(fd, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one))) // linux supports this, so why not - might fail on other systems
2537 g_fromtosockets.insert(fd);
2538 #ifdef IPV6_RECVPKTINFO
2539 if(sin.sin4.sin_family == AF_INET6)
2540 if(!setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)))
2541 g_fromtosockets.insert(fd);
2542 #endif
2543 if(sin.sin6.sin6_family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)) < 0) {
2544 g_log<<Logger::Error<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<strerror(errno)<<endl;
2545 }
2546 }
2547 if( ::arg().mustDo("non-local-bind") )
2548 Utility::setBindAny(AF_INET6, fd);
2549
2550 setCloseOnExec(fd);
2551
2552 setSocketReceiveBuffer(fd, 250000);
2553 sin.sin4.sin_port = htons(st.port);
2554
2555
2556 #ifdef SO_REUSEPORT
2557 if(g_reusePort) {
2558 if(setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
2559 throw PDNSException("SO_REUSEPORT: "+stringerror());
2560 }
2561 #endif
2562 socklen_t socklen=sin.getSocklen();
2563 if (::bind(fd, (struct sockaddr *)&sin, socklen)<0)
2564 throw PDNSException("Resolver binding to server socket on port "+ std::to_string(st.port) +" for "+ st.host+": "+stringerror());
2565
2566 setNonBlocking(fd);
2567
2568 deferredAdds.push_back(make_pair(fd, handleNewUDPQuestion));
2569 g_listenSocketsAddresses[fd]=sin; // this is written to only from the startup thread, not from the workers
2570 if(sin.sin4.sin_family == AF_INET)
2571 g_log<<Logger::Info<<"Listening for UDP queries on "<< sin.toString() <<":"<<st.port<<endl;
2572 else
2573 g_log<<Logger::Info<<"Listening for UDP queries on ["<< sin.toString() <<"]:"<<st.port<<endl;
2574 }
2575 }
2576
2577 static void daemonize(void)
2578 {
2579 if(fork())
2580 exit(0); // bye bye
2581
2582 setsid();
2583
2584 int i=open("/dev/null",O_RDWR); /* open stdin */
2585 if(i < 0)
2586 g_log<<Logger::Critical<<"Unable to open /dev/null: "<<stringerror()<<endl;
2587 else {
2588 dup2(i,0); /* stdin */
2589 dup2(i,1); /* stderr */
2590 dup2(i,2); /* stderr */
2591 close(i);
2592 }
2593 }
2594
2595 static void usr1Handler(int)
2596 {
2597 statsWanted=true;
2598 }
2599
2600 static void usr2Handler(int)
2601 {
2602 g_quiet= !g_quiet;
2603 SyncRes::setDefaultLogMode(g_quiet ? SyncRes::LogNone : SyncRes::Log);
2604 ::arg().set("quiet")=g_quiet ? "" : "no";
2605 }
2606
2607 static void doStats(void)
2608 {
2609 static time_t lastOutputTime;
2610 static uint64_t lastQueryCount;
2611
2612 uint64_t cacheHits = broadcastAccFunction<uint64_t>(pleaseGetCacheHits);
2613 uint64_t cacheMisses = broadcastAccFunction<uint64_t>(pleaseGetCacheMisses);
2614
2615 if(g_stats.qcounter && (cacheHits + cacheMisses) && SyncRes::s_queries && SyncRes::s_outqueries) {
2616 g_log<<Logger::Notice<<"stats: "<<g_stats.qcounter<<" questions, "<<
2617 broadcastAccFunction<uint64_t>(pleaseGetCacheSize)<< " cache entries, "<<
2618 broadcastAccFunction<uint64_t>(pleaseGetNegCacheSize)<<" negative entries, "<<
2619 (int)((cacheHits*100.0)/(cacheHits+cacheMisses))<<"% cache hits"<<endl;
2620
2621 g_log<<Logger::Notice<<"stats: throttle map: "
2622 << broadcastAccFunction<uint64_t>(pleaseGetThrottleSize) <<", ns speeds: "
2623 << broadcastAccFunction<uint64_t>(pleaseGetNsSpeedsSize)<<endl;
2624 g_log<<Logger::Notice<<"stats: outpacket/query ratio "<<(int)(SyncRes::s_outqueries*100.0/SyncRes::s_queries)<<"%";
2625 g_log<<Logger::Notice<<", "<<(int)(SyncRes::s_throttledqueries*100.0/(SyncRes::s_outqueries+SyncRes::s_throttledqueries))<<"% throttled, "
2626 <<SyncRes::s_nodelegated<<" no-delegation drops"<<endl;
2627 g_log<<Logger::Notice<<"stats: "<<SyncRes::s_tcpoutqueries<<" outgoing tcp connections, "<<
2628 broadcastAccFunction<uint64_t>(pleaseGetConcurrentQueries)<<" queries running, "<<SyncRes::s_outgoingtimeouts<<" outgoing timeouts"<<endl;
2629
2630 //g_log<<Logger::Notice<<"stats: "<<g_stats.ednsPingMatches<<" ping matches, "<<g_stats.ednsPingMismatches<<" mismatches, "<<
2631 //g_stats.noPingOutQueries<<" outqueries w/o ping, "<< g_stats.noEdnsOutQueries<<" w/o EDNS"<<endl;
2632
2633 g_log<<Logger::Notice<<"stats: " << broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize) <<
2634 " packet cache entries, "<<(int)(100.0*broadcastAccFunction<uint64_t>(pleaseGetPacketCacheHits)/SyncRes::s_queries) << "% packet cache hits"<<endl;
2635
2636 time_t now = time(0);
2637 if(lastOutputTime && lastQueryCount && now != lastOutputTime) {
2638 g_log<<Logger::Notice<<"stats: "<< (SyncRes::s_queries - lastQueryCount) / (now - lastOutputTime) <<" qps (average over "<< (now - lastOutputTime) << " seconds)"<<endl;
2639 }
2640 lastOutputTime = now;
2641 lastQueryCount = SyncRes::s_queries;
2642 }
2643 else if(statsWanted)
2644 g_log<<Logger::Notice<<"stats: no stats yet!"<<endl;
2645
2646 statsWanted=false;
2647 }
2648
2649 static void houseKeeping(void *)
2650 {
2651 static thread_local time_t last_rootupdate, last_prune, last_secpoll, last_trustAnchorUpdate{0};
2652 static thread_local int cleanCounter=0;
2653 static thread_local bool s_running; // houseKeeping can get suspended in secpoll, and be restarted, which makes us do duplicate work
2654 auto luaconfsLocal = g_luaconfs.getLocal();
2655
2656 if (last_trustAnchorUpdate == 0 && !luaconfsLocal->trustAnchorFileInfo.fname.empty() && luaconfsLocal->trustAnchorFileInfo.interval != 0) {
2657 // Loading the Lua config file already "refreshed" the TAs
2658 last_trustAnchorUpdate = g_now.tv_sec + luaconfsLocal->trustAnchorFileInfo.interval * 3600;
2659 }
2660
2661 try {
2662 if(s_running)
2663 return;
2664 s_running=true;
2665
2666 struct timeval now;
2667 Utility::gettimeofday(&now, 0);
2668
2669 if(now.tv_sec - last_prune > (time_t)(5 + t_id)) {
2670 DTime dt;
2671 dt.setTimeval(now);
2672 t_RC->doPrune(g_maxCacheEntries / g_numThreads); // this function is local to a thread, so fine anyhow
2673 t_packetCache->doPruneTo(g_maxPacketCacheEntries / g_numWorkerThreads);
2674
2675 SyncRes::pruneNegCache(g_maxCacheEntries / (g_numWorkerThreads * 10));
2676
2677 if(!((cleanCounter++)%40)) { // this is a full scan!
2678 time_t limit=now.tv_sec-300;
2679 SyncRes::pruneNSSpeeds(limit);
2680 }
2681 last_prune=time(0);
2682 }
2683
2684 if(now.tv_sec - last_rootupdate > 7200) {
2685 int res = SyncRes::getRootNS(g_now, nullptr);
2686 if (!res)
2687 last_rootupdate=now.tv_sec;
2688 }
2689
2690 if(isHandlerThread()) {
2691
2692 if(now.tv_sec - last_secpoll >= 3600) {
2693 try {
2694 doSecPoll(&last_secpoll);
2695 }
2696 catch(std::exception& e)
2697 {
2698 g_log<<Logger::Error<<"Exception while performing security poll: "<<e.what()<<endl;
2699 }
2700 catch(PDNSException& e)
2701 {
2702 g_log<<Logger::Error<<"Exception while performing security poll: "<<e.reason<<endl;
2703 }
2704 catch(ImmediateServFailException &e)
2705 {
2706 g_log<<Logger::Error<<"Exception while performing security poll: "<<e.reason<<endl;
2707 }
2708 catch(...)
2709 {
2710 g_log<<Logger::Error<<"Exception while performing security poll"<<endl;
2711 }
2712 }
2713
2714 if (!luaconfsLocal->trustAnchorFileInfo.fname.empty() && luaconfsLocal->trustAnchorFileInfo.interval != 0 &&
2715 g_now.tv_sec - last_trustAnchorUpdate >= (luaconfsLocal->trustAnchorFileInfo.interval * 3600)) {
2716 g_log<<Logger::Debug<<"Refreshing Trust Anchors from file"<<endl;
2717 try {
2718 map<DNSName, dsmap_t> dsAnchors;
2719 if (updateTrustAnchorsFromFile(luaconfsLocal->trustAnchorFileInfo.fname, dsAnchors)) {
2720 g_luaconfs.modify([&dsAnchors](LuaConfigItems& lci) {
2721 lci.dsAnchors = dsAnchors;
2722 });
2723 }
2724 last_trustAnchorUpdate = now.tv_sec;
2725 } catch (const PDNSException &pe) {
2726 g_log<<Logger::Error<<"Unable to update Trust Anchors: "<<pe.reason<<endl;
2727 }
2728 }
2729 s_running=false;
2730 }
2731 }
2732 catch(PDNSException& ae)
2733 {
2734 s_running=false;
2735 g_log<<Logger::Error<<"Fatal error in housekeeping thread: "<<ae.reason<<endl;
2736 throw;
2737 }
2738 }
2739
2740 static void makeThreadPipes()
2741 {
2742 /* thread 0 is the handler / SNMP, we start at 1 */
2743 for(unsigned int n = 1; n <= (g_numWorkerThreads + g_numDistributorThreads); ++n) {
2744 auto& threadInfos = s_threadInfos.at(n);
2745
2746 int fd[2];
2747 if(pipe(fd) < 0)
2748 unixDie("Creating pipe for inter-thread communications");
2749
2750 threadInfos.pipes.readToThread = fd[0];
2751 threadInfos.pipes.writeToThread = fd[1];
2752
2753 if(pipe(fd) < 0)
2754 unixDie("Creating pipe for inter-thread communications");
2755
2756 threadInfos.pipes.readFromThread = fd[0];
2757 threadInfos.pipes.writeFromThread = fd[1];
2758
2759 if(pipe(fd) < 0)
2760 unixDie("Creating pipe for inter-thread communications");
2761
2762 threadInfos.pipes.readQueriesToThread = fd[0];
2763 threadInfos.pipes.writeQueriesToThread = fd[1];
2764
2765 if (!setNonBlocking(threadInfos.pipes.writeQueriesToThread)) {
2766 unixDie("Making pipe for inter-thread communications non-blocking");
2767 }
2768 }
2769 }
2770
2771 struct ThreadMSG
2772 {
2773 pipefunc_t func;
2774 bool wantAnswer;
2775 };
2776
2777 void broadcastFunction(const pipefunc_t& func)
2778 {
2779 /* This function might be called by the worker with t_id 0 during startup
2780 for the initialization of ACLs and domain maps. After that it should only
2781 be called by the handler. */
2782
2783 if (s_threadInfos.empty() && isHandlerThread()) {
2784 /* the handler and distributors will call themselves below, but
2785 during startup we get called while s_threadInfos has not been
2786 populated yet to update the ACL or domain maps, so we need to
2787 handle that case.
2788 */
2789 func();
2790 }
2791
2792 unsigned int n = 0;
2793 for (const auto& threadInfo : s_threadInfos) {
2794 if(n++ == t_id) {
2795 func(); // don't write to ourselves!
2796 continue;
2797 }
2798
2799 ThreadMSG* tmsg = new ThreadMSG();
2800 tmsg->func = func;
2801 tmsg->wantAnswer = true;
2802 if(write(threadInfo.pipes.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) {
2803 delete tmsg;
2804
2805 unixDie("write to thread pipe returned wrong size or error");
2806 }
2807
2808 string* resp = nullptr;
2809 if(read(threadInfo.pipes.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
2810 unixDie("read from thread pipe returned wrong size or error");
2811
2812 if(resp) {
2813 delete resp;
2814 resp = nullptr;
2815 }
2816 }
2817 }
2818
2819 static bool trySendingQueryToWorker(unsigned int target, ThreadMSG* tmsg)
2820 {
2821 const auto& targetInfo = s_threadInfos[target];
2822 if(!targetInfo.isWorker) {
2823 g_log<<Logger::Error<<"distributeAsyncFunction() tried to assign a query to a non-worker thread"<<endl;
2824 exit(1);
2825 }
2826
2827 const auto& tps = targetInfo.pipes;
2828
2829 ssize_t written = write(tps.writeQueriesToThread, &tmsg, sizeof(tmsg));
2830 if (written > 0) {
2831 if (static_cast<size_t>(written) != sizeof(tmsg)) {
2832 delete tmsg;
2833 unixDie("write to thread pipe returned wrong size or error");
2834 }
2835 }
2836 else {
2837 int error = errno;
2838 if (error == EAGAIN || error == EWOULDBLOCK) {
2839 return false;
2840 } else {
2841 delete tmsg;
2842 unixDie("write to thread pipe returned wrong size or error:" + std::to_string(error));
2843 }
2844 }
2845
2846 return true;
2847 }
2848
2849 // This function is only called by the distributor threads, when pdns-distributes-queries is set
2850 void distributeAsyncFunction(const string& packet, const pipefunc_t& func)
2851 {
2852 if (!isDistributorThread()) {
2853 g_log<<Logger::Error<<"distributeAsyncFunction() has been called by a worker ("<<t_id<<")"<<endl;
2854 exit(1);
2855 }
2856
2857 unsigned int hash = hashQuestion(packet.c_str(), packet.length(), g_disthashseed);
2858 unsigned int target = /* skip handler */ 1 + g_numDistributorThreads + (hash % g_numWorkerThreads);
2859
2860 ThreadMSG* tmsg = new ThreadMSG();
2861 tmsg->func = func;
2862 tmsg->wantAnswer = false;
2863
2864 if (!trySendingQueryToWorker(target, tmsg)) {
2865 /* if this function failed but did not raise an exception, it means that the pipe
2866 was full, let's try another one */
2867 unsigned int newTarget = 0;
2868 do {
2869 newTarget = /* skip handler */ 1 + g_numDistributorThreads + dns_random(g_numWorkerThreads);
2870 } while (newTarget == target);
2871
2872 if (!trySendingQueryToWorker(newTarget, tmsg)) {
2873 g_stats.queryPipeFullDrops++;
2874 delete tmsg;
2875 }
2876 }
2877 }
2878
2879 static void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var)
2880 {
2881 ThreadMSG* tmsg = nullptr;
2882
2883 if(read(fd, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) { // fd == readToThread || fd == readQueriesToThread
2884 unixDie("read from thread pipe returned wrong size or error");
2885 }
2886
2887 void *resp=0;
2888 try {
2889 resp = tmsg->func();
2890 }
2891 catch(std::exception& e) {
2892 if(g_logCommonErrors)
2893 g_log<<Logger::Error<<"PIPE function we executed created exception: "<<e.what()<<endl; // but what if they wanted an answer.. we send 0
2894 }
2895 catch(PDNSException& e) {
2896 if(g_logCommonErrors)
2897 g_log<<Logger::Error<<"PIPE function we executed created PDNS exception: "<<e.reason<<endl; // but what if they wanted an answer.. we send 0
2898 }
2899 if(tmsg->wantAnswer) {
2900 const auto& threadInfo = s_threadInfos.at(t_id);
2901 if(write(threadInfo.pipes.writeFromThread, &resp, sizeof(resp)) != sizeof(resp)) {
2902 delete tmsg;
2903 unixDie("write to thread pipe returned wrong size or error");
2904 }
2905 }
2906
2907 delete tmsg;
2908 }
2909
2910 template<class T> void *voider(const boost::function<T*()>& func)
2911 {
2912 return func();
2913 }
2914
2915 vector<ComboAddress>& operator+=(vector<ComboAddress>&a, const vector<ComboAddress>& b)
2916 {
2917 a.insert(a.end(), b.begin(), b.end());
2918 return a;
2919 }
2920
2921 vector<pair<string, uint16_t> >& operator+=(vector<pair<string, uint16_t> >&a, const vector<pair<string, uint16_t> >& b)
2922 {
2923 a.insert(a.end(), b.begin(), b.end());
2924 return a;
2925 }
2926
2927 vector<pair<DNSName, uint16_t> >& operator+=(vector<pair<DNSName, uint16_t> >&a, const vector<pair<DNSName, uint16_t> >& b)
2928 {
2929 a.insert(a.end(), b.begin(), b.end());
2930 return a;
2931 }
2932
2933
2934 /*
2935 This function should only be called by the handler to gather metrics, wipe the cache,
2936 reload the Lua script (not the Lua config) or change the current trace regex,
2937 and by the SNMP thread to gather metrics. */
2938 template<class T> T broadcastAccFunction(const boost::function<T*()>& func)
2939 {
2940 if (!isHandlerThread()) {
2941 g_log<<Logger::Error<<"broadcastAccFunction has been called by a worker ("<<t_id<<")"<<endl;
2942 exit(1);
2943 }
2944
2945 unsigned int n = 0;
2946 T ret=T();
2947 for (const auto& threadInfo : s_threadInfos) {
2948 if (n++ == t_id) {
2949 continue;
2950 }
2951
2952 const auto& tps = threadInfo.pipes;
2953 ThreadMSG* tmsg = new ThreadMSG();
2954 tmsg->func = boost::bind(voider<T>, func);
2955 tmsg->wantAnswer = true;
2956
2957 if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) {
2958 delete tmsg;
2959 unixDie("write to thread pipe returned wrong size or error");
2960 }
2961
2962 T* resp = nullptr;
2963 if(read(tps.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
2964 unixDie("read from thread pipe returned wrong size or error");
2965
2966 if(resp) {
2967 ret += *resp;
2968 delete resp;
2969 resp = nullptr;
2970 }
2971 }
2972 return ret;
2973 }
2974
2975 template string broadcastAccFunction(const boost::function<string*()>& fun); // explicit instantiation
2976 template uint64_t broadcastAccFunction(const boost::function<uint64_t*()>& fun); // explicit instantiation
2977 template vector<ComboAddress> broadcastAccFunction(const boost::function<vector<ComboAddress> *()>& fun); // explicit instantiation
2978 template vector<pair<DNSName,uint16_t> > broadcastAccFunction(const boost::function<vector<pair<DNSName, uint16_t> > *()>& fun); // explicit instantiation
2979
2980 static void handleRCC(int fd, FDMultiplexer::funcparam_t& var)
2981 {
2982 string remote;
2983 string msg=s_rcc.recv(&remote);
2984 RecursorControlParser rcp;
2985 RecursorControlParser::func_t* command;
2986
2987 string answer=rcp.getAnswer(msg, &command);
2988
2989 // If we are inside a chroot, we need to strip
2990 if (!arg()["chroot"].empty()) {
2991 size_t len = arg()["chroot"].length();
2992 remote = remote.substr(len);
2993 }
2994
2995 try {
2996 s_rcc.send(answer, &remote);
2997 command();
2998 }
2999 catch(std::exception& e) {
3000 g_log<<Logger::Error<<"Error dealing with control socket request: "<<e.what()<<endl;
3001 }
3002 catch(PDNSException& ae) {
3003 g_log<<Logger::Error<<"Error dealing with control socket request: "<<ae.reason<<endl;
3004 }
3005 }
3006
3007 static void handleTCPClientReadable(int fd, FDMultiplexer::funcparam_t& var)
3008 {
3009 PacketID* pident=any_cast<PacketID>(&var);
3010 // cerr<<"handleTCPClientReadable called for fd "<<fd<<", pident->inNeeded: "<<pident->inNeeded<<", "<<pident->sock->getHandle()<<endl;
3011
3012 shared_array<char> buffer(new char[pident->inNeeded]);
3013
3014 ssize_t ret=recv(fd, buffer.get(), pident->inNeeded,0);
3015 if(ret > 0) {
3016 pident->inMSG.append(&buffer[0], &buffer[ret]);
3017 pident->inNeeded-=(size_t)ret;
3018 if(!pident->inNeeded || pident->inIncompleteOkay) {
3019 // cerr<<"Got entire load of "<<pident->inMSG.size()<<" bytes"<<endl;
3020 PacketID pid=*pident;
3021 string msg=pident->inMSG;
3022
3023 t_fdm->removeReadFD(fd);
3024 MT->sendEvent(pid, &msg);
3025 }
3026 else {
3027 // cerr<<"Still have "<<pident->inNeeded<<" left to go"<<endl;
3028 }
3029 }
3030 else {
3031 PacketID tmp=*pident;
3032 t_fdm->removeReadFD(fd); // pident might now be invalid (it isn't, but still)
3033 string empty;
3034 MT->sendEvent(tmp, &empty); // this conveys error status
3035 }
3036 }
3037
3038 static void handleTCPClientWritable(int fd, FDMultiplexer::funcparam_t& var)
3039 {
3040 PacketID* pid=any_cast<PacketID>(&var);
3041 ssize_t ret=send(fd, pid->outMSG.c_str() + pid->outPos, pid->outMSG.size() - pid->outPos,0);
3042 if(ret > 0) {
3043 pid->outPos+=(ssize_t)ret;
3044 if(pid->outPos==pid->outMSG.size()) {
3045 PacketID tmp=*pid;
3046 t_fdm->removeWriteFD(fd);
3047 MT->sendEvent(tmp, &tmp.outMSG); // send back what we sent to convey everything is ok
3048 }
3049 }
3050 else { // error or EOF
3051 PacketID tmp(*pid);
3052 t_fdm->removeWriteFD(fd);
3053 string sent;
3054 MT->sendEvent(tmp, &sent); // we convey error status by sending empty string
3055 }
3056 }
3057
3058 // resend event to everybody chained onto it
3059 static void doResends(MT_t::waiters_t::iterator& iter, PacketID resend, const string& content)
3060 {
3061 if(iter->key.chain.empty())
3062 return;
3063 // cerr<<"doResends called!\n";
3064 for(PacketID::chain_t::iterator i=iter->key.chain.begin(); i != iter->key.chain.end() ; ++i) {
3065 resend.fd=-1;
3066 resend.id=*i;
3067 // cerr<<"\tResending "<<content.size()<<" bytes for fd="<<resend.fd<<" and id="<<resend.id<<endl;
3068
3069 MT->sendEvent(resend, &content);
3070 g_stats.chainResends++;
3071 }
3072 }
3073
3074 static void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t& var)
3075 {
3076 PacketID pid=any_cast<PacketID>(var);
3077 ssize_t len;
3078 std::string packet;
3079 packet.resize(g_outgoingEDNSBufsize);
3080 ComboAddress fromaddr;
3081 socklen_t addrlen=sizeof(fromaddr);
3082
3083 len=recvfrom(fd, &packet.at(0), packet.size(), 0, (sockaddr *)&fromaddr, &addrlen);
3084
3085 if(len < (ssize_t) sizeof(dnsheader)) {
3086 if(len < 0)
3087 ; // cerr<<"Error on fd "<<fd<<": "<<stringerror()<<"\n";
3088 else {
3089 g_stats.serverParseError++;
3090 if(g_logCommonErrors)
3091 g_log<<Logger::Error<<"Unable to parse packet from remote UDP server "<< fromaddr.toString() <<
3092 ": packet smaller than DNS header"<<endl;
3093 }
3094
3095 t_udpclientsocks->returnSocket(fd);
3096 string empty;
3097
3098 MT_t::waiters_t::iterator iter=MT->d_waiters.find(pid);
3099 if(iter != MT->d_waiters.end())
3100 doResends(iter, pid, empty);
3101
3102 MT->sendEvent(pid, &empty); // this denotes error (does lookup again.. at least L1 will be hot)
3103 return;
3104 }
3105
3106 packet.resize(len);
3107 dnsheader dh;
3108 memcpy(&dh, &packet.at(0), sizeof(dh));
3109
3110 PacketID pident;
3111 pident.remote=fromaddr;
3112 pident.id=dh.id;
3113 pident.fd=fd;
3114
3115 if(!dh.qr && g_logCommonErrors) {
3116 g_log<<Logger::Notice<<"Not taking data from question on outgoing socket from "<< fromaddr.toStringWithPort() <<endl;
3117 }
3118
3119 if(!dh.qdcount || // UPC, Nominum, very old BIND on FormErr, NSD
3120 !dh.qr) { // one weird server
3121 pident.domain.clear();
3122 pident.type = 0;
3123 }
3124 else {
3125 try {
3126 if(len > 12)
3127 pident.domain=DNSName(&packet.at(0), len, 12, false, &pident.type); // don't copy this from above - we need to do the actual read
3128 }
3129 catch(std::exception& e) {
3130 g_stats.serverParseError++; // won't be fed to lwres.cc, so we have to increment
3131 g_log<<Logger::Warning<<"Error in packet from remote nameserver "<< fromaddr.toStringWithPort() << ": "<<e.what() << endl;
3132 return;
3133 }
3134 }
3135
3136 MT_t::waiters_t::iterator iter=MT->d_waiters.find(pident);
3137 if(iter != MT->d_waiters.end()) {
3138 doResends(iter, pident, packet);
3139 }
3140
3141 retryWithName:
3142
3143 if(!MT->sendEvent(pident, &packet)) {
3144 // we do a full scan for outstanding queries on unexpected answers. not too bad since we only accept them on the right port number, which is hard enough to guess
3145 for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
3146 if(pident.fd==mthread->key.fd && mthread->key.remote==pident.remote && mthread->key.type == pident.type &&
3147 pident.domain == mthread->key.domain) {
3148 mthread->key.nearMisses++;
3149 }
3150
3151 // be a bit paranoid here since we're weakening our matching
3152 if(pident.domain.empty() && !mthread->key.domain.empty() && !pident.type && mthread->key.type &&
3153 pident.id == mthread->key.id && mthread->key.remote == pident.remote) {
3154 // cerr<<"Empty response, rest matches though, sending to a waiter"<<endl;
3155 pident.domain = mthread->key.domain;
3156 pident.type = mthread->key.type;
3157 goto retryWithName; // note that this only passes on an error, lwres will still reject the packet
3158 }
3159 }
3160 g_stats.unexpectedCount++; // if we made it here, it really is an unexpected answer
3161 if(g_logCommonErrors) {
3162 g_log<<Logger::Warning<<"Discarding unexpected packet from "<<fromaddr.toStringWithPort()<<": "<< (pident.domain.empty() ? "<empty>" : pident.domain.toString())<<", "<<pident.type<<", "<<MT->d_waiters.size()<<" waiters"<<endl;
3163 }
3164 }
3165 else if(fd >= 0) {
3166 t_udpclientsocks->returnSocket(fd);
3167 }
3168 }
3169
3170 FDMultiplexer* getMultiplexer()
3171 {
3172 FDMultiplexer* ret;
3173 for(const auto& i : FDMultiplexer::getMultiplexerMap()) {
3174 try {
3175 ret=i.second();
3176 return ret;
3177 }
3178 catch(FDMultiplexerException &fe) {
3179 g_log<<Logger::Error<<"Non-fatal error initializing possible multiplexer ("<<fe.what()<<"), falling back"<<endl;
3180 }
3181 catch(...) {
3182 g_log<<Logger::Error<<"Non-fatal error initializing possible multiplexer"<<endl;
3183 }
3184 }
3185 g_log<<Logger::Error<<"No working multiplexer found!"<<endl;
3186 exit(1);
3187 }
3188
3189
3190 static string* doReloadLuaScript()
3191 {
3192 string fname= ::arg()["lua-dns-script"];
3193 try {
3194 if(fname.empty()) {
3195 t_pdl.reset();
3196 g_log<<Logger::Info<<t_id<<" Unloaded current lua script"<<endl;
3197 return new string("unloaded\n");
3198 }
3199 else {
3200 t_pdl = std::make_shared<RecursorLua4>();
3201 t_pdl->loadFile(fname);
3202 }
3203 }
3204 catch(std::exception& e) {
3205 g_log<<Logger::Error<<t_id<<" Retaining current script, error from '"<<fname<<"': "<< e.what() <<endl;
3206 return new string("retaining current script, error from '"+fname+"': "+e.what()+"\n");
3207 }
3208
3209 g_log<<Logger::Warning<<t_id<<" (Re)loaded lua script from '"<<fname<<"'"<<endl;
3210 return new string("(re)loaded '"+fname+"'\n");
3211 }
3212
3213 string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end)
3214 {
3215 if(begin != end)
3216 ::arg().set("lua-dns-script") = *begin;
3217
3218 return broadcastAccFunction<string>(doReloadLuaScript);
3219 }
3220
3221 static string* pleaseUseNewTraceRegex(const std::string& newRegex)
3222 try
3223 {
3224 if(newRegex.empty()) {
3225 t_traceRegex.reset();
3226 return new string("unset\n");
3227 }
3228 else {
3229 t_traceRegex = std::make_shared<Regex>(newRegex);
3230 return new string("ok\n");
3231 }
3232 }
3233 catch(PDNSException& ae)
3234 {
3235 return new string(ae.reason+"\n");
3236 }
3237
3238 string doTraceRegex(vector<string>::const_iterator begin, vector<string>::const_iterator end)
3239 {
3240 return broadcastAccFunction<string>(boost::bind(pleaseUseNewTraceRegex, begin!=end ? *begin : ""));
3241 }
3242
3243 static void checkLinuxIPv6Limits()
3244 {
3245 #ifdef __linux__
3246 string line;
3247 if(readFileIfThere("/proc/sys/net/ipv6/route/max_size", &line)) {
3248 int lim=std::stoi(line);
3249 if(lim < 16384) {
3250 g_log<<Logger::Error<<"If using IPv6, please raise sysctl net.ipv6.route.max_size, currently set to "<<lim<<" which is < 16384"<<endl;
3251 }
3252 }
3253 #endif
3254 }
3255 static void checkOrFixFDS()
3256 {
3257 unsigned int availFDs=getFilenumLimit();
3258 unsigned int wantFDs = g_maxMThreads * g_numWorkerThreads +25; // even healthier margin then before
3259
3260 if(wantFDs > availFDs) {
3261 unsigned int hardlimit= getFilenumLimit(true);
3262 if(hardlimit >= wantFDs) {
3263 setFilenumLimit(wantFDs);
3264 g_log<<Logger::Warning<<"Raised soft limit on number of filedescriptors to "<<wantFDs<<" to match max-mthreads and threads settings"<<endl;
3265 }
3266 else {
3267 int newval = (hardlimit - 25) / g_numWorkerThreads;
3268 g_log<<Logger::Warning<<"Insufficient number of filedescriptors available for max-mthreads*threads setting! ("<<hardlimit<<" < "<<wantFDs<<"), reducing max-mthreads to "<<newval<<endl;
3269 g_maxMThreads = newval;
3270 setFilenumLimit(hardlimit);
3271 }
3272 }
3273 }
3274
3275 static void* recursorThread(unsigned int tid, const string& threadName);
3276
3277 static void* pleaseSupplantACLs(std::shared_ptr<NetmaskGroup> ng)
3278 {
3279 t_allowFrom = ng;
3280 return nullptr;
3281 }
3282
3283 int g_argc;
3284 char** g_argv;
3285
3286 void parseACLs()
3287 {
3288 static bool l_initialized;
3289
3290 if(l_initialized) { // only reload configuration file on second call
3291 string configname=::arg()["config-dir"]+"/recursor.conf";
3292 if(::arg()["config-name"]!="") {
3293 configname=::arg()["config-dir"]+"/recursor-"+::arg()["config-name"]+".conf";
3294 }
3295 cleanSlashes(configname);
3296
3297 if(!::arg().preParseFile(configname.c_str(), "allow-from-file"))
3298 throw runtime_error("Unable to re-parse configuration file '"+configname+"'");
3299 ::arg().preParseFile(configname.c_str(), "allow-from", LOCAL_NETS);
3300 ::arg().preParseFile(configname.c_str(), "include-dir");
3301 ::arg().preParse(g_argc, g_argv, "include-dir");
3302
3303 // then process includes
3304 std::vector<std::string> extraConfigs;
3305 ::arg().gatherIncludes(extraConfigs);
3306
3307 for(const std::string& fn : extraConfigs) {
3308 if(!::arg().preParseFile(fn.c_str(), "allow-from-file", ::arg()["allow-from-file"]))
3309 throw runtime_error("Unable to re-parse configuration file include '"+fn+"'");
3310 if(!::arg().preParseFile(fn.c_str(), "allow-from", ::arg()["allow-from"]))
3311 throw runtime_error("Unable to re-parse configuration file include '"+fn+"'");
3312 }
3313
3314 ::arg().preParse(g_argc, g_argv, "allow-from-file");
3315 ::arg().preParse(g_argc, g_argv, "allow-from");
3316 }
3317
3318 std::shared_ptr<NetmaskGroup> oldAllowFrom = t_allowFrom;
3319 std::shared_ptr<NetmaskGroup> allowFrom = std::make_shared<NetmaskGroup>();
3320
3321 if(!::arg()["allow-from-file"].empty()) {
3322 string line;
3323 ifstream ifs(::arg()["allow-from-file"].c_str());
3324 if(!ifs) {
3325 throw runtime_error("Could not open '"+::arg()["allow-from-file"]+"': "+stringerror());
3326 }
3327
3328 string::size_type pos;
3329 while(getline(ifs,line)) {
3330 pos=line.find('#');
3331 if(pos!=string::npos)
3332 line.resize(pos);
3333 trim(line);
3334 if(line.empty())
3335 continue;
3336
3337 allowFrom->addMask(line);
3338 }
3339 g_log<<Logger::Warning<<"Done parsing " << allowFrom->size() <<" allow-from ranges from file '"<<::arg()["allow-from-file"]<<"' - overriding 'allow-from' setting"<<endl;
3340 }
3341 else if(!::arg()["allow-from"].empty()) {
3342 vector<string> ips;
3343 stringtok(ips, ::arg()["allow-from"], ", ");
3344
3345 g_log<<Logger::Warning<<"Only allowing queries from: ";
3346 for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
3347 allowFrom->addMask(*i);
3348 if(i!=ips.begin())
3349 g_log<<Logger::Warning<<", ";
3350 g_log<<Logger::Warning<<*i;
3351 }
3352 g_log<<Logger::Warning<<endl;
3353 }
3354 else {
3355 if(::arg()["local-address"]!="127.0.0.1" && ::arg().asNum("local-port")==53)
3356 g_log<<Logger::Warning<<"WARNING: Allowing queries from all IP addresses - this can be a security risk!"<<endl;
3357 allowFrom = nullptr;
3358 }
3359
3360 g_initialAllowFrom = allowFrom;
3361 broadcastFunction(boost::bind(pleaseSupplantACLs, allowFrom));
3362 oldAllowFrom = nullptr;
3363
3364 l_initialized = true;
3365 }
3366
3367
3368 static void setupDelegationOnly()
3369 {
3370 vector<string> parts;
3371 stringtok(parts, ::arg()["delegation-only"], ", \t");
3372 for(const auto& p : parts) {
3373 SyncRes::addDelegationOnly(DNSName(p));
3374 }
3375 }
3376
3377 static std::map<unsigned int, std::set<int> > parseCPUMap()
3378 {
3379 std::map<unsigned int, std::set<int> > result;
3380
3381 const std::string value = ::arg()["cpu-map"];
3382
3383 if (!value.empty() && !isSettingThreadCPUAffinitySupported()) {
3384 g_log<<Logger::Warning<<"CPU mapping requested but not supported, skipping"<<endl;
3385 return result;
3386 }
3387
3388 std::vector<std::string> parts;
3389
3390 stringtok(parts, value, " \t");
3391
3392 for(const auto& part : parts) {
3393 if (part.find('=') == string::npos)
3394 continue;
3395
3396 try {
3397 auto headers = splitField(part, '=');
3398 trim(headers.first);
3399 trim(headers.second);
3400
3401 unsigned int threadId = pdns_stou(headers.first);
3402 std::vector<std::string> cpus;
3403
3404 stringtok(cpus, headers.second, ",");
3405
3406 for(const auto& cpu : cpus) {
3407 int cpuId = std::stoi(cpu);
3408
3409 result[threadId].insert(cpuId);
3410 }
3411 }
3412 catch(const std::exception& e) {
3413 g_log<<Logger::Error<<"Error parsing cpu-map entry '"<<part<<"': "<<e.what()<<endl;
3414 }
3415 }
3416
3417 return result;
3418 }
3419
3420 static void setCPUMap(const std::map<unsigned int, std::set<int> >& cpusMap, unsigned int n, pthread_t tid)
3421 {
3422 const auto& cpuMapping = cpusMap.find(n);
3423 if (cpuMapping != cpusMap.cend()) {
3424 int rc = mapThreadToCPUList(tid, cpuMapping->second);
3425 if (rc == 0) {
3426 g_log<<Logger::Info<<"CPU affinity for worker "<<n<<" has been set to CPU map:";
3427 for (const auto cpu : cpuMapping->second) {
3428 g_log<<Logger::Info<<" "<<cpu;
3429 }
3430 g_log<<Logger::Info<<endl;
3431 }
3432 else {
3433 g_log<<Logger::Warning<<"Error setting CPU affinity for worker "<<n<<" to CPU map:";
3434 for (const auto cpu : cpuMapping->second) {
3435 g_log<<Logger::Info<<" "<<cpu;
3436 }
3437 g_log<<Logger::Info<<strerror(rc)<<endl;
3438 }
3439 }
3440 }
3441
3442 #ifdef NOD_ENABLED
3443 static void setupNODThread()
3444 {
3445 if (g_nodEnabled) {
3446 uint32_t num_cells = ::arg().asNum("new-domain-db-size");
3447 t_nodDBp = std::make_shared<nod::NODDB>(num_cells);
3448 try {
3449 t_nodDBp->setCacheDir(::arg()["new-domain-history-dir"]);
3450 }
3451 catch (const PDNSException& e) {
3452 g_log<<Logger::Error<<"new-domain-history-dir (" << ::arg()["new-domain-history-dir"] << ") is not readable or does not exist"<<endl;
3453 _exit(1);
3454 }
3455 if (!t_nodDBp->init()) {
3456 g_log<<Logger::Error<<"Could not initialize domain tracking"<<endl;
3457 _exit(1);
3458 }
3459 std::thread t(nod::NODDB::startHousekeepingThread, t_nodDBp, std::this_thread::get_id());
3460 t.detach();
3461 g_nod_pbtag = ::arg()["new-domain-pb-tag"];
3462 }
3463 if (g_udrEnabled) {
3464 uint32_t num_cells = ::arg().asNum("unique-response-db-size");
3465 t_udrDBp = std::make_shared<nod::UniqueResponseDB>(num_cells);
3466 try {
3467 t_udrDBp->setCacheDir(::arg()["unique-response-history-dir"]);
3468 }
3469 catch (const PDNSException& e) {
3470 g_log<<Logger::Error<<"unique-response-history-dir (" << ::arg()["unique-response-history-dir"] << ") is not readable or does not exist"<<endl;
3471 _exit(1);
3472 }
3473 if (!t_udrDBp->init()) {
3474 g_log<<Logger::Error<<"Could not initialize unique response tracking"<<endl;
3475 _exit(1);
3476 }
3477 std::thread t(nod::UniqueResponseDB::startHousekeepingThread, t_udrDBp, std::this_thread::get_id());
3478 t.detach();
3479 g_udr_pbtag = ::arg()["unique-response-pb-tag"];
3480 }
3481 }
3482
3483 void parseNODWhitelist(const std::string& wlist)
3484 {
3485 vector<string> parts;
3486 stringtok(parts, wlist, ",; ");
3487 for(const auto& a : parts) {
3488 g_nodDomainWL.add(DNSName(a));
3489 }
3490 }
3491
3492 static void setupNODGlobal()
3493 {
3494 // Setup NOD subsystem
3495 g_nodEnabled = ::arg().mustDo("new-domain-tracking");
3496 g_nodLookupDomain = DNSName(::arg()["new-domain-lookup"]);
3497 g_nodLog = ::arg().mustDo("new-domain-log");
3498 parseNODWhitelist(::arg()["new-domain-whitelist"]);
3499
3500 // Setup Unique DNS Response subsystem
3501 g_udrEnabled = ::arg().mustDo("unique-response-tracking");
3502 g_udrLog = ::arg().mustDo("unique-response-log");
3503 }
3504 #endif /* NOD_ENABLED */
3505
3506 static int serviceMain(int argc, char*argv[])
3507 {
3508 g_log.setName(s_programname);
3509 g_log.disableSyslog(::arg().mustDo("disable-syslog"));
3510 g_log.setTimestamps(::arg().mustDo("log-timestamp"));
3511
3512 if(!::arg()["logging-facility"].empty()) {
3513 int val=logFacilityToLOG(::arg().asNum("logging-facility") );
3514 if(val >= 0)
3515 g_log.setFacility(val);
3516 else
3517 g_log<<Logger::Error<<"Unknown logging facility "<<::arg().asNum("logging-facility") <<endl;
3518 }
3519
3520 showProductVersion();
3521
3522 g_disthashseed=dns_random(0xffffffff);
3523
3524 checkLinuxIPv6Limits();
3525 try {
3526 vector<string> addrs;
3527 if(!::arg()["query-local-address6"].empty()) {
3528 SyncRes::s_doIPv6=true;
3529 g_log<<Logger::Warning<<"Enabling IPv6 transport for outgoing queries"<<endl;
3530
3531 stringtok(addrs, ::arg()["query-local-address6"], ", ;");
3532 for(const string& addr : addrs) {
3533 g_localQueryAddresses6.push_back(ComboAddress(addr));
3534 }
3535 }
3536 else {
3537 g_log<<Logger::Warning<<"NOT using IPv6 for outgoing queries - set 'query-local-address6=::' to enable"<<endl;
3538 }
3539 addrs.clear();
3540 stringtok(addrs, ::arg()["query-local-address"], ", ;");
3541 for(const string& addr : addrs) {
3542 g_localQueryAddresses4.push_back(ComboAddress(addr));
3543 }
3544 }
3545 catch(std::exception& e) {
3546 g_log<<Logger::Error<<"Assigning local query addresses: "<<e.what();
3547 exit(99);
3548 }
3549
3550 // keep this ABOVE loadRecursorLuaConfig!
3551 if(::arg()["dnssec"]=="off")
3552 g_dnssecmode=DNSSECMode::Off;
3553 else if(::arg()["dnssec"]=="process-no-validate")
3554 g_dnssecmode=DNSSECMode::ProcessNoValidate;
3555 else if(::arg()["dnssec"]=="process")
3556 g_dnssecmode=DNSSECMode::Process;
3557 else if(::arg()["dnssec"]=="validate")
3558 g_dnssecmode=DNSSECMode::ValidateAll;
3559 else if(::arg()["dnssec"]=="log-fail")
3560 g_dnssecmode=DNSSECMode::ValidateForLog;
3561 else {
3562 g_log<<Logger::Error<<"Unknown DNSSEC mode "<<::arg()["dnssec"]<<endl;
3563 exit(1);
3564 }
3565
3566 g_signatureInceptionSkew = ::arg().asNum("signature-inception-skew");
3567 if (g_signatureInceptionSkew < 0) {
3568 g_log<<Logger::Error<<"A negative value for 'signature-inception-skew' is not allowed"<<endl;
3569 exit(1);
3570 }
3571
3572 g_dnssecLogBogus = ::arg().mustDo("dnssec-log-bogus");
3573 g_maxNSEC3Iterations = ::arg().asNum("nsec3-max-iterations");
3574
3575 g_maxCacheEntries = ::arg().asNum("max-cache-entries");
3576 g_maxPacketCacheEntries = ::arg().asNum("max-packetcache-entries");
3577
3578 luaConfigDelayedThreads delayedLuaThreads;
3579 try {
3580 loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads);
3581 }
3582 catch (PDNSException &e) {
3583 g_log<<Logger::Error<<"Cannot load Lua configuration: "<<e.reason<<endl;
3584 exit(1);
3585 }
3586
3587 parseACLs();
3588 initPublicSuffixList(::arg()["public-suffix-list-file"]);
3589
3590 if(!::arg()["dont-query"].empty()) {
3591 vector<string> ips;
3592 stringtok(ips, ::arg()["dont-query"], ", ");
3593 ips.push_back("0.0.0.0");
3594 ips.push_back("::");
3595
3596 g_log<<Logger::Warning<<"Will not send queries to: ";
3597 for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
3598 SyncRes::addDontQuery(*i);
3599 if(i!=ips.begin())
3600 g_log<<Logger::Warning<<", ";
3601 g_log<<Logger::Warning<<*i;
3602 }
3603 g_log<<Logger::Warning<<endl;
3604 }
3605
3606 g_quiet=::arg().mustDo("quiet");
3607
3608 /* this needs to be done before parseACLs(), which call broadcastFunction() */
3609 g_weDistributeQueries = ::arg().mustDo("pdns-distributes-queries");
3610 if(g_weDistributeQueries) {
3611 g_log<<Logger::Warning<<"PowerDNS Recursor itself will distribute queries over threads"<<endl;
3612 }
3613
3614 setupDelegationOnly();
3615 g_outgoingEDNSBufsize=::arg().asNum("edns-outgoing-bufsize");
3616
3617 if(::arg()["trace"]=="fail") {
3618 SyncRes::setDefaultLogMode(SyncRes::Store);
3619 }
3620 else if(::arg().mustDo("trace")) {
3621 SyncRes::setDefaultLogMode(SyncRes::Log);
3622 ::arg().set("quiet")="no";
3623 g_quiet=false;
3624 g_dnssecLOG=true;
3625 }
3626 string myHostname = getHostname();
3627 if (myHostname == "UNKNOWN"){
3628 g_log<<Logger::Warning<<"Unable to get the hostname, NSID and id.server values will be empty"<<endl;
3629 myHostname = "";
3630 }
3631
3632 SyncRes::s_minimumTTL = ::arg().asNum("minimum-ttl-override");
3633
3634 SyncRes::s_nopacketcache = ::arg().mustDo("disable-packetcache");
3635
3636 SyncRes::s_maxnegttl=::arg().asNum("max-negative-ttl");
3637 SyncRes::s_maxbogusttl=::arg().asNum("max-cache-bogus-ttl");
3638 SyncRes::s_maxcachettl=max(::arg().asNum("max-cache-ttl"), 15);
3639 SyncRes::s_packetcachettl=::arg().asNum("packetcache-ttl");
3640 // Cap the packetcache-servfail-ttl to the packetcache-ttl
3641 uint32_t packetCacheServFailTTL = ::arg().asNum("packetcache-servfail-ttl");
3642 SyncRes::s_packetcacheservfailttl=(packetCacheServFailTTL > SyncRes::s_packetcachettl) ? SyncRes::s_packetcachettl : packetCacheServFailTTL;
3643 SyncRes::s_serverdownmaxfails=::arg().asNum("server-down-max-fails");
3644 SyncRes::s_serverdownthrottletime=::arg().asNum("server-down-throttle-time");
3645 SyncRes::s_serverID=::arg()["server-id"];
3646 SyncRes::s_maxqperq=::arg().asNum("max-qperq");
3647 SyncRes::s_maxtotusec=1000*::arg().asNum("max-total-msec");
3648 SyncRes::s_maxdepth=::arg().asNum("max-recursion-depth");
3649 SyncRes::s_rootNXTrust = ::arg().mustDo( "root-nx-trust");
3650 if(SyncRes::s_serverID.empty()) {
3651 SyncRes::s_serverID = myHostname;
3652 }
3653
3654 SyncRes::s_ecsipv4limit = ::arg().asNum("ecs-ipv4-bits");
3655 SyncRes::s_ecsipv6limit = ::arg().asNum("ecs-ipv6-bits");
3656 SyncRes::clearECSStats();
3657
3658 if (!::arg().isEmpty("ecs-scope-zero-address")) {
3659 ComboAddress scopeZero(::arg()["ecs-scope-zero-address"]);
3660 SyncRes::setECSScopeZeroAddress(Netmask(scopeZero, scopeZero.isIPv4() ? 32 : 128));
3661 }
3662 else {
3663 bool found = false;
3664 for (const auto& addr : g_localQueryAddresses4) {
3665 if (!IsAnyAddress(addr)) {
3666 SyncRes::setECSScopeZeroAddress(Netmask(addr, 32));
3667 found = true;
3668 break;
3669 }
3670 }
3671 if (!found) {
3672 for (const auto& addr : g_localQueryAddresses6) {
3673 if (!IsAnyAddress(addr)) {
3674 SyncRes::setECSScopeZeroAddress(Netmask(addr, 128));
3675 found = true;
3676 break;
3677 }
3678 }
3679 if (!found) {
3680 SyncRes::setECSScopeZeroAddress(Netmask("127.0.0.1/32"));
3681 }
3682 }
3683 }
3684
3685 SyncRes::parseEDNSSubnetWhitelist(::arg()["edns-subnet-whitelist"]);
3686 SyncRes::parseEDNSSubnetAddFor(::arg()["ecs-add-for"]);
3687 g_useIncomingECS = ::arg().mustDo("use-incoming-edns-subnet");
3688
3689 g_XPFAcl.toMasks(::arg()["xpf-allow-from"]);
3690 g_xpfRRCode = ::arg().asNum("xpf-rr-code");
3691
3692 g_networkTimeoutMsec = ::arg().asNum("network-timeout");
3693
3694 g_initialDomainMap = parseAuthAndForwards();
3695
3696 g_latencyStatSize=::arg().asNum("latency-statistic-size");
3697
3698 g_logCommonErrors=::arg().mustDo("log-common-errors");
3699 g_logRPZChanges = ::arg().mustDo("log-rpz-changes");
3700
3701 g_anyToTcp = ::arg().mustDo("any-to-tcp");
3702 g_udpTruncationThreshold = ::arg().asNum("udp-truncation-threshold");
3703
3704 g_lowercaseOutgoing = ::arg().mustDo("lowercase-outgoing");
3705
3706 g_numDistributorThreads = ::arg().asNum("distributor-threads");
3707 g_numWorkerThreads = ::arg().asNum("threads");
3708 if (g_numWorkerThreads < 1) {
3709 g_log<<Logger::Warning<<"Asked to run with 0 threads, raising to 1 instead"<<endl;
3710 g_numWorkerThreads = 1;
3711 }
3712
3713 g_numThreads = g_numDistributorThreads + g_numWorkerThreads;
3714 g_maxMThreads = ::arg().asNum("max-mthreads");
3715
3716 g_gettagNeedsEDNSOptions = ::arg().mustDo("gettag-needs-edns-options");
3717
3718 g_statisticsInterval = ::arg().asNum("statistics-interval");
3719
3720 #ifdef SO_REUSEPORT
3721 g_reusePort = ::arg().mustDo("reuseport");
3722 #endif
3723
3724 s_threadInfos.resize(g_numDistributorThreads + g_numWorkerThreads + /* handler */ 1);
3725
3726 if (g_reusePort) {
3727 if (g_weDistributeQueries) {
3728 /* first thread is the handler, then distributors */
3729 for (unsigned int threadId = 1; threadId <= g_numDistributorThreads; threadId++) {
3730 auto& deferredAdds = s_threadInfos.at(threadId).deferredAdds;
3731 auto& tcpSockets = s_threadInfos.at(threadId).tcpSockets;
3732 makeUDPServerSockets(deferredAdds);
3733 makeTCPServerSockets(deferredAdds, tcpSockets);
3734 }
3735 }
3736 else {
3737 /* first thread is the handler, there is no distributor here and workers are accepting queries */
3738 for (unsigned int threadId = 1; threadId <= g_numWorkerThreads; threadId++) {
3739 auto& deferredAdds = s_threadInfos.at(threadId).deferredAdds;
3740 auto& tcpSockets = s_threadInfos.at(threadId).tcpSockets;
3741 makeUDPServerSockets(deferredAdds);
3742 makeTCPServerSockets(deferredAdds, tcpSockets);
3743 }
3744 }
3745 }
3746 else {
3747 std::set<int> tcpSockets;
3748 /* we don't have reuseport so we can only open one socket per
3749 listening addr:port and everyone will listen on it */
3750 makeUDPServerSockets(g_deferredAdds);
3751 makeTCPServerSockets(g_deferredAdds, tcpSockets);
3752
3753 /* every listener (so distributor if g_weDistributeQueries, workers otherwise)
3754 needs to listen to the shared sockets */
3755 if (g_weDistributeQueries) {
3756 /* first thread is the handler, then distributors */
3757 for (unsigned int threadId = 1; threadId <= g_numDistributorThreads; threadId++) {
3758 s_threadInfos.at(threadId).tcpSockets = tcpSockets;
3759 }
3760 }
3761 else {
3762 /* first thread is the handler, there is no distributor here and workers are accepting queries */
3763 for (unsigned int threadId = 1; threadId <= g_numWorkerThreads; threadId++) {
3764 s_threadInfos.at(threadId).tcpSockets = tcpSockets;
3765 }
3766 }
3767 }
3768
3769 #ifdef NOD_ENABLED
3770 // Setup newly observed domain globals
3771 setupNODGlobal();
3772 #endif /* NOD_ENABLED */
3773
3774 int forks;
3775 for(forks = 0; forks < ::arg().asNum("processes") - 1; ++forks) {
3776 if(!fork()) // we are child
3777 break;
3778 }
3779
3780 if(::arg().mustDo("daemon")) {
3781 g_log<<Logger::Warning<<"Calling daemonize, going to background"<<endl;
3782 g_log.toConsole(Logger::Critical);
3783 daemonize();
3784 }
3785 signal(SIGUSR1,usr1Handler);
3786 signal(SIGUSR2,usr2Handler);
3787 signal(SIGPIPE,SIG_IGN);
3788
3789 checkOrFixFDS();
3790
3791 #ifdef HAVE_LIBSODIUM
3792 if (sodium_init() == -1) {
3793 g_log<<Logger::Error<<"Unable to initialize sodium crypto library"<<endl;
3794 exit(99);
3795 }
3796 #endif
3797
3798 openssl_thread_setup();
3799 openssl_seed();
3800 /* setup rng before chroot */
3801 dns_random_init();
3802
3803 if(::arg()["server-id"].empty()) {
3804 ::arg().set("server-id") = myHostname;
3805 }
3806
3807 int newgid=0;
3808 if(!::arg()["setgid"].empty())
3809 newgid=Utility::makeGidNumeric(::arg()["setgid"]);
3810 int newuid=0;
3811 if(!::arg()["setuid"].empty())
3812 newuid=Utility::makeUidNumeric(::arg()["setuid"]);
3813
3814 Utility::dropGroupPrivs(newuid, newgid);
3815
3816 if (!::arg()["chroot"].empty()) {
3817 #ifdef HAVE_SYSTEMD
3818 char *ns;
3819 ns = getenv("NOTIFY_SOCKET");
3820 if (ns != nullptr) {
3821 g_log<<Logger::Error<<"Unable to chroot when running from systemd. Please disable chroot= or set the 'Type' for this service to 'simple'"<<endl;
3822 exit(1);
3823 }
3824 #endif
3825 if (chroot(::arg()["chroot"].c_str())<0 || chdir("/") < 0) {
3826 g_log<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror (errno)<<", exiting"<<endl;
3827 exit(1);
3828 }
3829 else
3830 g_log<<Logger::Info<<"Chrooted to '"<<::arg()["chroot"]<<"'"<<endl;
3831 }
3832
3833 s_pidfname=::arg()["socket-dir"]+"/"+s_programname+".pid";
3834 if(!s_pidfname.empty())
3835 unlink(s_pidfname.c_str()); // remove possible old pid file
3836 writePid();
3837
3838 makeControlChannelSocket( ::arg().asNum("processes") > 1 ? forks : -1);
3839
3840 Utility::dropUserPrivs(newuid);
3841 try {
3842 /* we might still have capabilities remaining, for example if we have been started as root
3843 without --setuid (please don't do that) or as an unprivileged user with ambient capabilities
3844 like CAP_NET_BIND_SERVICE.
3845 */
3846 dropCapabilities();
3847 }
3848 catch(const std::exception& e) {
3849 g_log<<Logger::Warning<<e.what()<<endl;
3850 }
3851
3852 startLuaConfigDelayedThreads(delayedLuaThreads, g_luaconfs.getCopy().generation);
3853
3854 makeThreadPipes();
3855
3856 g_tcpTimeout=::arg().asNum("client-tcp-timeout");
3857 g_maxTCPPerClient=::arg().asNum("max-tcp-per-client");
3858 g_tcpMaxQueriesPerConn=::arg().asNum("max-tcp-queries-per-connection");
3859 s_maxUDPQueriesPerRound=::arg().asNum("max-udp-queries-per-round");
3860
3861 blacklistStats(StatComponent::API, ::arg()["stats-api-blacklist"]);
3862 blacklistStats(StatComponent::Carbon, ::arg()["stats-carbon-blacklist"]);
3863 blacklistStats(StatComponent::RecControl, ::arg()["stats-rec-control-blacklist"]);
3864 blacklistStats(StatComponent::SNMP, ::arg()["stats-snmp-blacklist"]);
3865
3866 if (::arg().mustDo("snmp-agent")) {
3867 g_snmpAgent = std::make_shared<RecursorSNMPAgent>("recursor", ::arg()["snmp-master-socket"]);
3868 g_snmpAgent->run();
3869 }
3870
3871 int port = ::arg().asNum("udp-source-port-min");
3872 if(port < 1024 || port > 65535){
3873 g_log<<Logger::Error<<"Unable to launch, udp-source-port-min is not a valid port number"<<endl;
3874 exit(99); // this isn't going to fix itself either
3875 }
3876 s_minUdpSourcePort = port;
3877 port = ::arg().asNum("udp-source-port-max");
3878 if(port < 1024 || port > 65535 || port < s_minUdpSourcePort){
3879 g_log<<Logger::Error<<"Unable to launch, udp-source-port-max is not a valid port number or is smaller than udp-source-port-min"<<endl;
3880 exit(99); // this isn't going to fix itself either
3881 }
3882 s_maxUdpSourcePort = port;
3883 std::vector<string> parts {};
3884 stringtok(parts, ::arg()["udp-source-port-avoid"], ", ");
3885 for (const auto &part : parts)
3886 {
3887 port = std::stoi(part);
3888 if(port < 1024 || port > 65535){
3889 g_log<<Logger::Error<<"Unable to launch, udp-source-port-avoid contains an invalid port number: "<<part<<endl;
3890 exit(99); // this isn't going to fix itself either
3891 }
3892 s_avoidUdpSourcePorts.insert(port);
3893 }
3894
3895 unsigned int currentThreadId = 1;
3896 const auto cpusMap = parseCPUMap();
3897
3898 if(g_numThreads == 1) {
3899 g_log<<Logger::Warning<<"Operating unthreaded"<<endl;
3900 #ifdef HAVE_SYSTEMD
3901 sd_notify(0, "READY=1");
3902 #endif
3903
3904 /* This thread handles the web server, carbon, statistics and the control channel */
3905 auto& handlerInfos = s_threadInfos.at(0);
3906 handlerInfos.isHandler = true;
3907 handlerInfos.thread = std::thread(recursorThread, 0, "main");
3908
3909 setCPUMap(cpusMap, currentThreadId, pthread_self());
3910
3911 auto& infos = s_threadInfos.at(currentThreadId);
3912 infos.isListener = true;
3913 infos.isWorker = true;
3914 recursorThread(currentThreadId++, "worker");
3915 }
3916 else {
3917
3918 if (g_weDistributeQueries) {
3919 g_log<<Logger::Warning<<"Launching "<< g_numDistributorThreads <<" distributor threads"<<endl;
3920 for(unsigned int n=0; n < g_numDistributorThreads; ++n) {
3921 auto& infos = s_threadInfos.at(currentThreadId);
3922 infos.isListener = true;
3923 infos.thread = std::thread(recursorThread, currentThreadId++, "distr");
3924
3925 setCPUMap(cpusMap, currentThreadId, infos.thread.native_handle());
3926 }
3927 }
3928
3929 g_log<<Logger::Warning<<"Launching "<< g_numWorkerThreads <<" worker threads"<<endl;
3930
3931 for(unsigned int n=0; n < g_numWorkerThreads; ++n) {
3932 auto& infos = s_threadInfos.at(currentThreadId);
3933 infos.isListener = g_weDistributeQueries ? false : true;
3934 infos.isWorker = true;
3935 infos.thread = std::thread(recursorThread, currentThreadId++, "worker");
3936
3937 setCPUMap(cpusMap, currentThreadId, infos.thread.native_handle());
3938 }
3939
3940 #ifdef HAVE_SYSTEMD
3941 sd_notify(0, "READY=1");
3942 #endif
3943
3944 /* This thread handles the web server, carbon, statistics and the control channel */
3945 auto& infos = s_threadInfos.at(0);
3946 infos.isHandler = true;
3947 infos.thread = std::thread(recursorThread, 0, "web+stat");
3948
3949 s_threadInfos.at(0).thread.join();
3950 }
3951 return 0;
3952 }
3953
3954 static void* recursorThread(unsigned int n, const string& threadName)
3955 try
3956 {
3957 t_id=n;
3958 auto& threadInfo = s_threadInfos.at(t_id);
3959
3960 static string threadPrefix = "pdns-r/";
3961 setThreadName(threadPrefix + threadName);
3962
3963 SyncRes tmp(g_now); // make sure it allocates tsstorage before we do anything, like primeHints or so..
3964 SyncRes::setDomainMap(g_initialDomainMap);
3965 t_allowFrom = g_initialAllowFrom;
3966 t_udpclientsocks = std::unique_ptr<UDPClientSocks>(new UDPClientSocks());
3967 t_tcpClientCounts = std::unique_ptr<tcpClientCounts_t>(new tcpClientCounts_t());
3968 primeHints();
3969
3970 t_packetCache = std::unique_ptr<RecursorPacketCache>(new RecursorPacketCache());
3971
3972 g_log<<Logger::Warning<<"Done priming cache with root hints"<<endl;
3973
3974 #ifdef NOD_ENABLED
3975 if (threadInfo.isWorker)
3976 setupNODThread();
3977 #endif /* NOD_ENABLED */
3978
3979 /* the listener threads handle TCP queries */
3980 if(threadInfo.isWorker || threadInfo.isListener) {
3981 try {
3982 if(!::arg()["lua-dns-script"].empty()) {
3983 t_pdl = std::make_shared<RecursorLua4>();
3984 t_pdl->loadFile(::arg()["lua-dns-script"]);
3985 g_log<<Logger::Warning<<"Loaded 'lua' script from '"<<::arg()["lua-dns-script"]<<"'"<<endl;
3986 }
3987 }
3988 catch(std::exception &e) {
3989 g_log<<Logger::Error<<"Failed to load 'lua' script from '"<<::arg()["lua-dns-script"]<<"': "<<e.what()<<endl;
3990 _exit(99);
3991 }
3992 }
3993
3994 unsigned int ringsize=::arg().asNum("stats-ringbuffer-entries") / g_numWorkerThreads;
3995 if(ringsize) {
3996 t_remotes = std::unique_ptr<addrringbuf_t>(new addrringbuf_t());
3997 if(g_weDistributeQueries)
3998 t_remotes->set_capacity(::arg().asNum("stats-ringbuffer-entries") / g_numDistributorThreads);
3999 else
4000 t_remotes->set_capacity(ringsize);
4001 t_servfailremotes = std::unique_ptr<addrringbuf_t>(new addrringbuf_t());
4002 t_servfailremotes->set_capacity(ringsize);
4003 t_bogusremotes = std::unique_ptr<addrringbuf_t>(new addrringbuf_t());
4004 t_bogusremotes->set_capacity(ringsize);
4005 t_largeanswerremotes = std::unique_ptr<addrringbuf_t>(new addrringbuf_t());
4006 t_largeanswerremotes->set_capacity(ringsize);
4007 t_timeouts = std::unique_ptr<addrringbuf_t>(new addrringbuf_t());
4008 t_timeouts->set_capacity(ringsize);
4009
4010 t_queryring = std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t> > >(new boost::circular_buffer<pair<DNSName, uint16_t> >());
4011 t_queryring->set_capacity(ringsize);
4012 t_servfailqueryring = std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t> > >(new boost::circular_buffer<pair<DNSName, uint16_t> >());
4013 t_servfailqueryring->set_capacity(ringsize);
4014 t_bogusqueryring = std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t> > >(new boost::circular_buffer<pair<DNSName, uint16_t> >());
4015 t_bogusqueryring->set_capacity(ringsize);
4016 }
4017
4018 MT=std::unique_ptr<MTasker<PacketID,string> >(new MTasker<PacketID,string>(::arg().asNum("stack-size")));
4019
4020 #ifdef HAVE_PROTOBUF
4021 /* start protobuf export threads if needed */
4022 auto luaconfsLocal = g_luaconfs.getLocal();
4023 checkProtobufExport(luaconfsLocal);
4024 checkOutgoingProtobufExport(luaconfsLocal);
4025 #endif /* HAVE_PROTOBUF */
4026
4027 PacketID pident;
4028
4029 t_fdm=getMultiplexer();
4030
4031 if(threadInfo.isHandler) {
4032 if(::arg().mustDo("webserver")) {
4033 g_log<<Logger::Warning << "Enabling web server" << endl;
4034 try {
4035 new RecursorWebServer(t_fdm);
4036 }
4037 catch(PDNSException &e) {
4038 g_log<<Logger::Error<<"Exception: "<<e.reason<<endl;
4039 exit(99);
4040 }
4041 }
4042 g_log<<Logger::Info<<"Enabled '"<< t_fdm->getName() << "' multiplexer"<<endl;
4043 }
4044 else {
4045
4046 t_fdm->addReadFD(threadInfo.pipes.readToThread, handlePipeRequest);
4047 t_fdm->addReadFD(threadInfo.pipes.readQueriesToThread, handlePipeRequest);
4048
4049 if (threadInfo.isListener) {
4050 if (g_reusePort) {
4051 /* then every listener has its own FDs */
4052 for(const auto deferred : threadInfo.deferredAdds) {
4053 t_fdm->addReadFD(deferred.first, deferred.second);
4054 }
4055 }
4056 else {
4057 /* otherwise all listeners are listening on the same ones */
4058 for(const auto deferred : g_deferredAdds) {
4059 t_fdm->addReadFD(deferred.first, deferred.second);
4060 }
4061 }
4062 }
4063 }
4064
4065 registerAllStats();
4066
4067 if(threadInfo.isHandler) {
4068 t_fdm->addReadFD(s_rcc.d_fd, handleRCC); // control channel
4069 }
4070
4071 unsigned int maxTcpClients=::arg().asNum("max-tcp-clients");
4072
4073 bool listenOnTCP(true);
4074
4075 time_t last_stat = 0;
4076 time_t last_carbon=0, last_lua_maintenance=0;
4077 time_t carbonInterval=::arg().asNum("carbon-interval");
4078 time_t luaMaintenanceInterval=::arg().asNum("lua-maintenance-interval");
4079 counter.store(0); // used to periodically execute certain tasks
4080 for(;;) {
4081 while(MT->schedule(&g_now)); // MTasker letting the mthreads do their thing
4082
4083 if(!(counter%500)) {
4084 MT->makeThread(houseKeeping, 0);
4085 }
4086
4087 if(!(counter%55)) {
4088 typedef vector<pair<int, FDMultiplexer::funcparam_t> > expired_t;
4089 expired_t expired=t_fdm->getTimeouts(g_now);
4090
4091 for(expired_t::iterator i=expired.begin() ; i != expired.end(); ++i) {
4092 shared_ptr<TCPConnection> conn=any_cast<shared_ptr<TCPConnection> >(i->second);
4093 if(g_logCommonErrors)
4094 g_log<<Logger::Warning<<"Timeout from remote TCP client "<< conn->d_remote.toStringWithPort() <<endl;
4095 t_fdm->removeReadFD(i->first);
4096 }
4097 }
4098
4099 counter++;
4100
4101 if(threadInfo.isHandler) {
4102 if(statsWanted || (g_statisticsInterval > 0 && (g_now.tv_sec - last_stat) >= g_statisticsInterval)) {
4103 doStats();
4104 last_stat = g_now.tv_sec;
4105 }
4106
4107 Utility::gettimeofday(&g_now, 0);
4108
4109 if((g_now.tv_sec - last_carbon) >= carbonInterval) {
4110 MT->makeThread(doCarbonDump, 0);
4111 last_carbon = g_now.tv_sec;
4112 }
4113 }
4114 if (t_pdl != nullptr) {
4115 // lua-dns-script directive is present, call the maintenance callback if needed
4116 /* remember that the listener threads handle TCP queries */
4117 if (threadInfo.isWorker || threadInfo.isListener) {
4118 // Only on threads processing queries
4119 if(g_now.tv_sec - last_lua_maintenance >= luaMaintenanceInterval) {
4120 t_pdl->maintenance();
4121 last_lua_maintenance = g_now.tv_sec;
4122 }
4123 }
4124 }
4125
4126 t_fdm->run(&g_now);
4127 // 'run' updates g_now for us
4128
4129 if(threadInfo.isListener) {
4130 if(listenOnTCP) {
4131 if(TCPConnection::getCurrentConnections() > maxTcpClients) { // shutdown, too many connections
4132 for(const auto fd : threadInfo.tcpSockets) {
4133 t_fdm->removeReadFD(fd);
4134 }
4135 listenOnTCP=false;
4136 }
4137 }
4138 else {
4139 if(TCPConnection::getCurrentConnections() <= maxTcpClients) { // reenable
4140 for(const auto fd : threadInfo.tcpSockets) {
4141 t_fdm->addReadFD(fd, handleNewTCPQuestion);
4142 }
4143 listenOnTCP=true;
4144 }
4145 }
4146 }
4147 }
4148 }
4149 catch(PDNSException &ae) {
4150 g_log<<Logger::Error<<"Exception: "<<ae.reason<<endl;
4151 return 0;
4152 }
4153 catch(std::exception &e) {
4154 g_log<<Logger::Error<<"STL Exception: "<<e.what()<<endl;
4155 return 0;
4156 }
4157 catch(...) {
4158 g_log<<Logger::Error<<"any other exception in main: "<<endl;
4159 return 0;
4160 }
4161
4162
4163 int main(int argc, char **argv)
4164 {
4165 g_argc = argc;
4166 g_argv = argv;
4167 g_stats.startupTime=time(0);
4168 Utility::srandom();
4169 versionSetProduct(ProductRecursor);
4170 reportBasicTypes();
4171 reportOtherTypes();
4172
4173 int ret = EXIT_SUCCESS;
4174
4175 try {
4176 ::arg().set("stack-size","stack size per mthread")="200000";
4177 ::arg().set("soa-minimum-ttl","Don't change")="0";
4178 ::arg().set("no-shuffle","Don't change")="off";
4179 ::arg().set("local-port","port to listen on")="53";
4180 ::arg().set("local-address","IP addresses to listen on, separated by spaces or commas. Also accepts ports.")="127.0.0.1";
4181 ::arg().setSwitch("non-local-bind", "Enable binding to non-local addresses by using FREEBIND / BINDANY socket options")="no";
4182 ::arg().set("trace","if we should output heaps of logging. set to 'fail' to only log failing domains")="off";
4183 ::arg().set("dnssec", "DNSSEC mode: off/process-no-validate (default)/process/log-fail/validate")="process-no-validate";
4184 ::arg().set("dnssec-log-bogus", "Log DNSSEC bogus validations")="no";
4185 ::arg().set("signature-inception-skew", "Allow the signature inception to be off by this number of seconds")="60";
4186 ::arg().set("daemon","Operate as a daemon")="no";
4187 ::arg().setSwitch("write-pid","Write a PID file")="yes";
4188 ::arg().set("loglevel","Amount of logging. Higher is more. Do not set below 3")="6";
4189 ::arg().set("disable-syslog","Disable logging to syslog, useful when running inside a supervisor that logs stdout")="no";
4190 ::arg().set("log-timestamp","Print timestamps in log lines, useful to disable when running with a tool that timestamps stdout already")="yes";
4191 ::arg().set("log-common-errors","If we should log rather common errors")="no";
4192 ::arg().set("chroot","switch to chroot jail")="";
4193 ::arg().set("setgid","If set, change group id to this gid for more security")="";
4194 ::arg().set("setuid","If set, change user id to this uid for more security")="";
4195 ::arg().set("network-timeout", "Wait this number of milliseconds for network i/o")="1500";
4196 ::arg().set("threads", "Launch this number of threads")="2";
4197 ::arg().set("distributor-threads", "Launch this number of distributor threads, distributing queries to other threads")="0";
4198 ::arg().set("processes", "Launch this number of processes (EXPERIMENTAL, DO NOT CHANGE)")="1"; // if we un-experimental this, need to fix openssl rand seeding for multiple PIDs!
4199 ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
4200 ::arg().set("api-config-dir", "Directory where REST API stores config and zones") = "";
4201 ::arg().set("api-key", "Static pre-shared authentication key for access to the REST API") = "";
4202 ::arg().setSwitch("webserver", "Start a webserver (for REST API)") = "no";
4203 ::arg().set("webserver-address", "IP Address of webserver to listen on") = "127.0.0.1";
4204 ::arg().set("webserver-port", "Port of webserver to listen on") = "8082";
4205 ::arg().set("webserver-password", "Password required for accessing the webserver") = "";
4206 ::arg().set("webserver-allow-from","Webserver access is only allowed from these subnets")="127.0.0.1,::1";
4207 ::arg().set("carbon-ourname", "If set, overrides our reported hostname for carbon stats")="";
4208 ::arg().set("carbon-server", "If set, send metrics in carbon (graphite) format to this server IP address")="";
4209 ::arg().set("carbon-interval", "Number of seconds between carbon (graphite) updates")="30";
4210 ::arg().set("carbon-namespace", "If set overwrites the first part of the carbon string")="pdns";
4211 ::arg().set("carbon-instance", "If set overwrites the the instance name default")="recursor";
4212
4213 ::arg().set("statistics-interval", "Number of seconds between printing of recursor statistics, 0 to disable")="1800";
4214 ::arg().set("quiet","Suppress logging of questions and answers")="";
4215 ::arg().set("logging-facility","Facility to log messages as. 0 corresponds to local0")="";
4216 ::arg().set("config-dir","Location of configuration directory (recursor.conf)")=SYSCONFDIR;
4217 ::arg().set("socket-owner","Owner of socket")="";
4218 ::arg().set("socket-group","Group of socket")="";
4219 ::arg().set("socket-mode", "Permissions for socket")="";
4220
4221 ::arg().set("socket-dir",string("Where the controlsocket will live, ")+LOCALSTATEDIR+" when unset and not chrooted" )="";
4222 ::arg().set("delegation-only","Which domains we only accept delegations from")="";
4223 ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
4224 ::arg().set("query-local-address6","Source IPv6 address for sending queries. IF UNSET, IPv6 WILL NOT BE USED FOR OUTGOING QUERIES")="";
4225 ::arg().set("client-tcp-timeout","Timeout in seconds when talking to TCP clients")="2";
4226 ::arg().set("max-mthreads", "Maximum number of simultaneous Mtasker threads")="2048";
4227 ::arg().set("max-tcp-clients","Maximum number of simultaneous TCP clients")="128";
4228 ::arg().set("server-down-max-fails","Maximum number of consecutive timeouts (and unreachables) to mark a server as down ( 0 => disabled )")="64";
4229 ::arg().set("server-down-throttle-time","Number of seconds to throttle all queries to a server after being marked as down")="60";
4230 ::arg().set("hint-file", "If set, load root hints from this file")="";
4231 ::arg().set("max-cache-entries", "If set, maximum number of entries in the main cache")="1000000";
4232 ::arg().set("max-negative-ttl", "maximum number of seconds to keep a negative cached entry in memory")="3600";
4233 ::arg().set("max-cache-bogus-ttl", "maximum number of seconds to keep a Bogus (positive or negative) cached entry in memory")="3600";
4234 ::arg().set("max-cache-ttl", "maximum number of seconds to keep a cached entry in memory")="86400";
4235 ::arg().set("packetcache-ttl", "maximum number of seconds to keep a cached entry in packetcache")="3600";
4236 ::arg().set("max-packetcache-entries", "maximum number of entries to keep in the packetcache")="500000";
4237 ::arg().set("packetcache-servfail-ttl", "maximum number of seconds to keep a cached servfail entry in packetcache")="60";
4238 ::arg().set("server-id", "Returned when queried for 'id.server' TXT or NSID, defaults to hostname, set custom or 'disabled'")="";
4239 ::arg().set("stats-ringbuffer-entries", "maximum number of packets to store statistics for")="10000";
4240 ::arg().set("version-string", "string reported on version.pdns or version.bind")=fullVersionString();
4241 ::arg().set("allow-from", "If set, only allow these comma separated netmasks to recurse")=LOCAL_NETS;
4242 ::arg().set("allow-from-file", "If set, load allowed netmasks from this file")="";
4243 ::arg().set("entropy-source", "If set, read entropy from this file")="/dev/urandom";
4244 ::arg().set("dont-query", "If set, do not query these netmasks for DNS data")=DONT_QUERY;
4245 ::arg().set("max-tcp-per-client", "If set, maximum number of TCP sessions per client (IP address)")="0";
4246 ::arg().set("max-tcp-queries-per-connection", "If set, maximum number of TCP queries in a TCP connection")="0";
4247 ::arg().set("spoof-nearmiss-max", "If non-zero, assume spoofing after this many near misses")="20";
4248 ::arg().set("single-socket", "If set, only use a single socket for outgoing queries")="off";
4249 ::arg().set("auth-zones", "Zones for which we have authoritative data, comma separated domain=file pairs ")="";
4250 ::arg().set("lua-config-file", "More powerful configuration options")="";
4251
4252 ::arg().set("forward-zones", "Zones for which we forward queries, comma separated domain=ip pairs")="";
4253 ::arg().set("forward-zones-recurse", "Zones for which we forward queries with recursion bit, comma separated domain=ip pairs")="";
4254 ::arg().set("forward-zones-file", "File with (+)domain=ip pairs for forwarding")="";
4255 ::arg().set("export-etc-hosts", "If we should serve up contents from /etc/hosts")="off";
4256 ::arg().set("export-etc-hosts-search-suffix", "Also serve up the contents of /etc/hosts with this suffix")="";
4257 ::arg().set("etc-hosts-file", "Path to 'hosts' file")="/etc/hosts";
4258 ::arg().set("serve-rfc1918", "If we should be authoritative for RFC 1918 private IP space")="yes";
4259 ::arg().set("lua-dns-script", "Filename containing an optional 'lua' script that will be used to modify dns answers")="";
4260 ::arg().set("lua-maintenance-interval", "Number of seconds between calls to the lua user defined maintenance() function")="1";
4261 ::arg().set("latency-statistic-size","Number of latency values to calculate the qa-latency average")="10000";
4262 ::arg().setSwitch( "disable-packetcache", "Disable packetcache" )= "no";
4263 ::arg().set("ecs-ipv4-bits", "Number of bits of IPv4 address to pass for EDNS Client Subnet")="24";
4264 ::arg().set("ecs-ipv6-bits", "Number of bits of IPv6 address to pass for EDNS Client Subnet")="56";
4265 ::arg().set("edns-subnet-whitelist", "List of netmasks and domains that we should enable EDNS subnet for")="";
4266 ::arg().set("ecs-add-for", "List of client netmasks for which EDNS Client Subnet will be added")="0.0.0.0/0, ::/0, " LOCAL_NETS_INVERSE;
4267 ::arg().set("ecs-scope-zero-address", "Address to send to whitelisted authoritative servers for incoming queries with ECS prefix-length source of 0")="";
4268 ::arg().setSwitch( "use-incoming-edns-subnet", "Pass along received EDNS Client Subnet information")="no";
4269 ::arg().setSwitch( "pdns-distributes-queries", "If PowerDNS itself should distribute queries over threads")="yes";
4270 ::arg().setSwitch( "root-nx-trust", "If set, believe that an NXDOMAIN from the root means the TLD does not exist")="yes";
4271 ::arg().setSwitch( "any-to-tcp","Answer ANY queries with tc=1, shunting to TCP" )="no";
4272 ::arg().setSwitch( "lowercase-outgoing","Force outgoing questions to lowercase")="no";
4273 ::arg().setSwitch("gettag-needs-edns-options", "If EDNS Options should be extracted before calling the gettag() hook")="no";
4274 ::arg().set("udp-truncation-threshold", "Maximum UDP response size before we truncate")="1232";
4275 ::arg().set("edns-outgoing-bufsize", "Outgoing EDNS buffer size")="1232";
4276 ::arg().set("minimum-ttl-override", "Set under adverse conditions, a minimum TTL")="0";
4277 ::arg().set("max-qperq", "Maximum outgoing queries per query")="50";
4278 ::arg().set("max-total-msec", "Maximum total wall-clock time per query in milliseconds, 0 for unlimited")="7000";
4279 ::arg().set("max-recursion-depth", "Maximum number of internal recursion calls per query, 0 for unlimited")="40";
4280 ::arg().set("max-udp-queries-per-round", "Maximum number of UDP queries processed per recvmsg() round, before returning back to normal processing")="10000";
4281
4282 ::arg().set("include-dir","Include *.conf files from this directory")="";
4283 ::arg().set("security-poll-suffix","Domain name from which to query security update notifications")="secpoll.powerdns.com.";
4284
4285 ::arg().setSwitch("reuseport","Enable SO_REUSEPORT allowing multiple recursors processes to listen to 1 address")="no";
4286
4287 ::arg().setSwitch("snmp-agent", "If set, register as an SNMP agent")="no";
4288 ::arg().set("snmp-master-socket", "If set and snmp-agent is set, the socket to use to register to the SNMP master")="";
4289
4290 std::string defaultBlacklistedStats = "cache-bytes, packetcache-bytes, special-memory-usage";
4291 for (size_t idx = 0; idx < 32; idx++) {
4292 defaultBlacklistedStats += ", ecs-v4-response-bits-" + std::to_string(idx + 1);
4293 }
4294 for (size_t idx = 0; idx < 128; idx++) {
4295 defaultBlacklistedStats += ", ecs-v6-response-bits-" + std::to_string(idx + 1);
4296 }
4297 ::arg().set("stats-api-blacklist", "List of statistics that are disabled when retrieving the complete list of statistics via the API")=defaultBlacklistedStats;
4298 ::arg().set("stats-carbon-blacklist", "List of statistics that are prevented from being exported via Carbon")=defaultBlacklistedStats;
4299 ::arg().set("stats-rec-control-blacklist", "List of statistics that are prevented from being exported via rec_control get-all")=defaultBlacklistedStats;
4300 ::arg().set("stats-snmp-blacklist", "List of statistics that are prevented from being exported via SNMP")=defaultBlacklistedStats;
4301
4302 ::arg().set("tcp-fast-open", "Enable TCP Fast Open support on the listening sockets, using the supplied numerical value as the queue size")="0";
4303 ::arg().set("nsec3-max-iterations", "Maximum number of iterations allowed for an NSEC3 record")="2500";
4304
4305 ::arg().set("cpu-map", "Thread to CPU mapping, space separated thread-id=cpu1,cpu2..cpuN pairs")="";
4306
4307 ::arg().setSwitch("log-rpz-changes", "Log additions and removals to RPZ zones at Info level")="no";
4308
4309 ::arg().set("xpf-allow-from","XPF information is only processed from these subnets")="";
4310 ::arg().set("xpf-rr-code","XPF option code to use")="0";
4311
4312 ::arg().set("udp-source-port-min", "Minimum UDP port to bind on")="1024";
4313 ::arg().set("udp-source-port-max", "Maximum UDP port to bind on")="65535";
4314 ::arg().set("udp-source-port-avoid", "List of comma separated UDP port number to avoid")="11211";
4315 ::arg().set("rng", "Specify random number generator to use. Valid values are auto,sodium,openssl,getrandom,arc4random,urandom.")="auto";
4316 ::arg().set("public-suffix-list-file", "Path to the Public Suffix List file, if any")="";
4317 #ifdef NOD_ENABLED
4318 ::arg().set("new-domain-tracking", "Track newly observed domains (i.e. never seen before).")="no";
4319 ::arg().set("new-domain-log", "Log newly observed domains.")="yes";
4320 ::arg().set("new-domain-lookup", "Perform a DNS lookup newly observed domains as a subdomain of the configured domain")="";
4321 ::arg().set("new-domain-history-dir", "Persist new domain tracking data here to persist between restarts")=string(NODCACHEDIR)+"/nod";
4322 ::arg().set("new-domain-whitelist", "List of domains (and implicitly all subdomains) which will never be considered a new domain")="";
4323 ::arg().set("new-domain-db-size", "Size of the DB used to track new domains in terms of number of cells. Defaults to 67108864")="67108864";
4324 ::arg().set("new-domain-pb-tag", "If protobuf is configured, the tag to use for messages containing newly observed domains. Defaults to 'pdns-nod'")="pdns-nod";
4325 ::arg().set("unique-response-tracking", "Track unique responses (tuple of query name, type and RR).")="no";
4326 ::arg().set("unique-response-log", "Log unique responses")="yes";
4327 ::arg().set("unique-response-history-dir", "Persist unique response tracking data here to persist between restarts")=string(NODCACHEDIR)+"/udr";
4328 ::arg().set("unique-response-db-size", "Size of the DB used to track unique responses in terms of number of cells. Defaults to 67108864")="67108864";
4329 ::arg().set("unique-response-pb-tag", "If protobuf is configured, the tag to use for messages containing unique DNS responses. Defaults to 'pdns-udr'")="pdns-udr";
4330 #endif /* NOD_ENABLED */
4331 ::arg().setCmd("help","Provide a helpful message");
4332 ::arg().setCmd("version","Print version string");
4333 ::arg().setCmd("config","Output blank configuration");
4334 g_log.toConsole(Logger::Info);
4335 ::arg().laxParse(argc,argv); // do a lax parse
4336
4337 string configname=::arg()["config-dir"]+"/recursor.conf";
4338 if(::arg()["config-name"]!="") {
4339 configname=::arg()["config-dir"]+"/recursor-"+::arg()["config-name"]+".conf";
4340 s_programname+="-"+::arg()["config-name"];
4341 }
4342 cleanSlashes(configname);
4343
4344 if(!::arg().getCommands().empty()) {
4345 cerr<<"Fatal: non-option on the command line, perhaps a '--setting=123' statement missed the '='?"<<endl;
4346 exit(99);
4347 }
4348
4349 if(::arg().mustDo("config")) {
4350 cout<<::arg().configstring()<<endl;
4351 exit(0);
4352 }
4353
4354 if(!::arg().file(configname.c_str()))
4355 g_log<<Logger::Warning<<"Unable to parse configuration file '"<<configname<<"'"<<endl;
4356
4357 ::arg().parse(argc,argv);
4358
4359 if( !::arg()["chroot"].empty() && !::arg()["api-config-dir"].empty() ) {
4360 g_log<<Logger::Error<<"Using chroot and enabling the API is not possible"<<endl;
4361 exit(EXIT_FAILURE);
4362 }
4363
4364 if (::arg()["socket-dir"].empty()) {
4365 if (::arg()["chroot"].empty())
4366 ::arg().set("socket-dir") = LOCALSTATEDIR;
4367 else
4368 ::arg().set("socket-dir") = "/";
4369 }
4370
4371 ::arg().set("delegation-only")=toLower(::arg()["delegation-only"]);
4372
4373 if(::arg().asNum("threads")==1) {
4374 if (::arg().mustDo("pdns-distributes-queries")) {
4375 g_log<<Logger::Warning<<"Only one thread, no need to distribute queries ourselves"<<endl;
4376 ::arg().set("pdns-distributes-queries")="no";
4377 }
4378 }
4379
4380 if(::arg().mustDo("pdns-distributes-queries") && ::arg().asNum("distributor-threads") <= 0) {
4381 g_log<<Logger::Warning<<"Asked to run with pdns-distributes-queries set but no distributor threads, raising to 1"<<endl;
4382 ::arg().set("distributor-threads")="1";
4383 }
4384
4385 if (!::arg().mustDo("pdns-distributes-queries")) {
4386 ::arg().set("distributor-threads")="0";
4387 }
4388
4389 if(::arg().mustDo("help")) {
4390 cout<<"syntax:"<<endl<<endl;
4391 cout<<::arg().helpstring(::arg()["help"])<<endl;
4392 exit(0);
4393 }
4394 if(::arg().mustDo("version")) {
4395 showProductVersion();
4396 showBuildConfiguration();
4397 exit(0);
4398 }
4399
4400 Logger::Urgency logUrgency = (Logger::Urgency)::arg().asNum("loglevel");
4401
4402 if (logUrgency < Logger::Error)
4403 logUrgency = Logger::Error;
4404 if(!g_quiet && logUrgency < Logger::Info) { // Logger::Info=6, Logger::Debug=7
4405 logUrgency = Logger::Info; // if you do --quiet=no, you need Info to also see the query log
4406 }
4407 g_log.setLoglevel(logUrgency);
4408 g_log.toConsole(logUrgency);
4409
4410 serviceMain(argc, argv);
4411 }
4412 catch(PDNSException &ae) {
4413 g_log<<Logger::Error<<"Exception: "<<ae.reason<<endl;
4414 ret=EXIT_FAILURE;
4415 }
4416 catch(std::exception &e) {
4417 g_log<<Logger::Error<<"STL Exception: "<<e.what()<<endl;
4418 ret=EXIT_FAILURE;
4419 }
4420 catch(...) {
4421 g_log<<Logger::Error<<"any other exception in main: "<<endl;
4422 ret=EXIT_FAILURE;
4423 }
4424
4425 return ret;
4426 }