]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/pdns_recursor.cc
Merge remote-tracking branch 'origin/master' into webserver-logging
[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 setNonBlocking(ret);
627 return ret;
628 }
629 };
630
631 static thread_local std::unique_ptr<UDPClientSocks> t_udpclientsocks;
632
633 /* these two functions are used by LWRes */
634 // -2 is OS error, -1 is error that depends on the remote, > 0 is success
635 int asendto(const char *data, size_t len, int flags,
636 const ComboAddress& toaddr, uint16_t id, const DNSName& domain, uint16_t qtype, int* fd)
637 {
638
639 PacketID pident;
640 pident.domain = domain;
641 pident.remote = toaddr;
642 pident.type = qtype;
643
644 // see if there is an existing outstanding request we can chain on to, using partial equivalence function
645 pair<MT_t::waiters_t::iterator, MT_t::waiters_t::iterator> chain=MT->d_waiters.equal_range(pident, PacketIDBirthdayCompare());
646
647 for(; chain.first != chain.second; chain.first++) {
648 if(chain.first->key.fd > -1) { // don't chain onto existing chained waiter!
649 /*
650 cerr<<"Orig: "<<pident.domain<<", "<<pident.remote.toString()<<", id="<<id<<endl;
651 cerr<<"Had hit: "<< chain.first->key.domain<<", "<<chain.first->key.remote.toString()<<", id="<<chain.first->key.id
652 <<", count="<<chain.first->key.chain.size()<<", origfd: "<<chain.first->key.fd<<endl;
653 */
654 chain.first->key.chain.insert(id); // we can chain
655 *fd=-1; // gets used in waitEvent / sendEvent later on
656 return 1;
657 }
658 }
659
660 int ret=t_udpclientsocks->getSocket(toaddr, fd);
661 if(ret < 0)
662 return ret;
663
664 pident.fd=*fd;
665 pident.id=id;
666
667 t_fdm->addReadFD(*fd, handleUDPServerResponse, pident);
668 ret = send(*fd, data, len, 0);
669
670 int tmp = errno;
671
672 if(ret < 0)
673 t_udpclientsocks->returnSocket(*fd);
674
675 errno = tmp; // this is for logging purposes only
676 return ret;
677 }
678
679 // -1 is error, 0 is timeout, 1 is success
680 int arecvfrom(std::string& packet, int flags, const ComboAddress& fromaddr, size_t *d_len,
681 uint16_t id, const DNSName& domain, uint16_t qtype, int fd, struct timeval* now)
682 {
683 static optional<unsigned int> nearMissLimit;
684 if(!nearMissLimit)
685 nearMissLimit=::arg().asNum("spoof-nearmiss-max");
686
687 PacketID pident;
688 pident.fd=fd;
689 pident.id=id;
690 pident.domain=domain;
691 pident.type = qtype;
692 pident.remote=fromaddr;
693
694 int ret=MT->waitEvent(pident, &packet, g_networkTimeoutMsec, now);
695
696 if(ret > 0) {
697 if(packet.empty()) // means "error"
698 return -1;
699
700 *d_len=packet.size();
701
702 if(*nearMissLimit && pident.nearMisses > *nearMissLimit) {
703 g_log<<Logger::Error<<"Too many ("<<pident.nearMisses<<" > "<<*nearMissLimit<<") bogus answers for '"<<domain<<"' from "<<fromaddr.toString()<<", assuming spoof attempt."<<endl;
704 g_stats.spoofCount++;
705 return -1;
706 }
707 }
708 else {
709 if(fd >= 0)
710 t_udpclientsocks->returnSocket(fd);
711 }
712 return ret;
713 }
714
715 static void writePid(void)
716 {
717 if(!::arg().mustDo("write-pid"))
718 return;
719 ofstream of(s_pidfname.c_str(), std::ios_base::app);
720 if(of)
721 of<< Utility::getpid() <<endl;
722 else
723 g_log<<Logger::Error<<"Writing pid for "<<Utility::getpid()<<" to "<<s_pidfname<<" failed: "<<strerror(errno)<<endl;
724 }
725
726 TCPConnection::TCPConnection(int fd, const ComboAddress& addr) : data(2, 0), d_remote(addr), d_fd(fd)
727 {
728 ++s_currentConnections;
729 (*t_tcpClientCounts)[d_remote]++;
730 }
731
732 TCPConnection::~TCPConnection()
733 {
734 try {
735 if(closesocket(d_fd) < 0)
736 g_log<<Logger::Error<<"Error closing socket for TCPConnection"<<endl;
737 }
738 catch(const PDNSException& e) {
739 g_log<<Logger::Error<<"Error closing TCPConnection socket: "<<e.reason<<endl;
740 }
741
742 if(t_tcpClientCounts->count(d_remote) && !(*t_tcpClientCounts)[d_remote]--)
743 t_tcpClientCounts->erase(d_remote);
744 --s_currentConnections;
745 }
746
747 AtomicCounter TCPConnection::s_currentConnections;
748
749 static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var);
750
751 // the idea is, only do things that depend on the *response* here. Incoming accounting is on incoming.
752 static void updateResponseStats(int res, const ComboAddress& remote, unsigned int packetsize, const DNSName* query, uint16_t qtype)
753 {
754 if(packetsize > 1000 && t_largeanswerremotes)
755 t_largeanswerremotes->push_back(remote);
756 switch(res) {
757 case RCode::ServFail:
758 if(t_servfailremotes) {
759 t_servfailremotes->push_back(remote);
760 if(query && t_servfailqueryring) // packet cache
761 t_servfailqueryring->push_back(make_pair(*query, qtype));
762 }
763 g_stats.servFails++;
764 break;
765 case RCode::NXDomain:
766 g_stats.nxDomains++;
767 break;
768 case RCode::NoError:
769 g_stats.noErrors++;
770 break;
771 }
772 }
773
774 static string makeLoginfo(const std::unique_ptr<DNSComboWriter>& dc)
775 try
776 {
777 return "("+dc->d_mdp.d_qname.toLogString()+"/"+DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)+" from "+(dc->getRemote())+")";
778 }
779 catch(...)
780 {
781 return "Exception making error message for exception";
782 }
783
784 #ifdef HAVE_PROTOBUF
785 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)
786 {
787 if (!t_protobufServers) {
788 return;
789 }
790
791 Netmask requestorNM(remote, remote.sin4.sin_family == AF_INET ? maskV4 : maskV6);
792 const ComboAddress& requestor = requestorNM.getMaskedNetwork();
793 RecProtoBufMessage message(DNSProtoBufMessage::Query, uniqueId, &requestor, &local, qname, qtype, qclass, id, tcp, len);
794 message.setServerIdentity(SyncRes::s_serverID);
795 message.setEDNSSubnet(ednssubnet, ednssubnet.isIpv4() ? maskV4 : maskV6);
796 message.setRequestorId(requestorId);
797 message.setDeviceId(deviceId);
798
799 if (!policyTags.empty()) {
800 message.setPolicyTags(policyTags);
801 }
802
803 // cerr <<message.toDebugString()<<endl;
804 std::string str;
805 message.serialize(str);
806
807 for (auto& server : *t_protobufServers) {
808 server->queueData(str);
809 }
810 }
811
812 static void protobufLogResponse(const RecProtoBufMessage& message)
813 {
814 if (!t_protobufServers) {
815 return;
816 }
817
818 // cerr <<message.toDebugString()<<endl;
819 std::string str;
820 message.serialize(str);
821
822 for (auto& server : *t_protobufServers) {
823 server->queueData(str);
824 }
825 }
826 #endif
827
828 /**
829 * Chases the CNAME provided by the PolicyCustom RPZ policy.
830 *
831 * @param spoofed: The DNSRecord that was created by the policy, should already be added to ret
832 * @param qtype: The QType of the original query
833 * @param sr: A SyncRes
834 * @param res: An integer that will contain the RCODE of the lookup we do
835 * @param ret: A vector of DNSRecords where the result of the CNAME chase should be appended to
836 */
837 static void handleRPZCustom(const DNSRecord& spoofed, const QType& qtype, SyncRes& sr, int& res, vector<DNSRecord>& ret)
838 {
839 if (spoofed.d_type == QType::CNAME) {
840 bool oldWantsRPZ = sr.getWantsRPZ();
841 sr.setWantsRPZ(false);
842 vector<DNSRecord> ans;
843 res = sr.beginResolve(DNSName(spoofed.d_content->getZoneRepresentation()), qtype, QClass::IN, ans);
844 for (const auto& rec : ans) {
845 if(rec.d_place == DNSResourceRecord::ANSWER) {
846 ret.push_back(rec);
847 }
848 }
849 // Reset the RPZ state of the SyncRes
850 sr.setWantsRPZ(oldWantsRPZ);
851 }
852 }
853
854 static bool addRecordToPacket(DNSPacketWriter& pw, const DNSRecord& rec, uint32_t& minTTL, uint32_t ttlCap, const uint16_t maxAnswerSize)
855 {
856 pw.startRecord(rec.d_name, rec.d_type, (rec.d_ttl > ttlCap ? ttlCap : rec.d_ttl), rec.d_class, rec.d_place);
857
858 if(rec.d_type != QType::OPT) // their TTL ain't real
859 minTTL = min(minTTL, rec.d_ttl);
860
861 rec.d_content->toPacket(pw);
862 if(pw.size() > static_cast<size_t>(maxAnswerSize)) {
863 pw.rollback();
864 if(rec.d_place != DNSResourceRecord::ADDITIONAL) {
865 pw.getHeader()->tc=1;
866 pw.truncate();
867 }
868 return false;
869 }
870
871 return true;
872 }
873
874 #ifdef HAVE_PROTOBUF
875 static std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>> startProtobufServers(const ProtobufExportConfig& config)
876 {
877 auto result = std::make_shared<std::vector<std::unique_ptr<RemoteLogger>>>();
878
879 for (const auto& server : config.servers) {
880 try {
881 result->emplace_back(new RemoteLogger(server, config.timeout, config.maxQueuedEntries, config.reconnectWaitTime, config.asyncConnect));
882 }
883 catch(const std::exception& e) {
884 g_log<<Logger::Error<<"Error while starting protobuf logger to '"<<server<<": "<<e.what()<<endl;
885 }
886 catch(const PDNSException& e) {
887 g_log<<Logger::Error<<"Error while starting protobuf logger to '"<<server<<": "<<e.reason<<endl;
888 }
889 }
890
891 return result;
892 }
893
894 static bool checkProtobufExport(LocalStateHolder<LuaConfigItems>& luaconfsLocal)
895 {
896 if (!luaconfsLocal->protobufExportConfig.enabled) {
897 if (t_protobufServers) {
898 for (auto& server : *t_protobufServers) {
899 server->stop();
900 }
901 t_protobufServers.reset();
902 }
903
904 return false;
905 }
906
907 /* if the server was not running, or if it was running according to a
908 previous configuration */
909 if (!t_protobufServers ||
910 t_protobufServersGeneration < luaconfsLocal->generation) {
911
912 if (t_protobufServers) {
913 for (auto& server : *t_protobufServers) {
914 server->stop();
915 }
916 }
917 t_protobufServers.reset();
918
919 t_protobufServers = startProtobufServers(luaconfsLocal->protobufExportConfig);
920 t_protobufServersGeneration = luaconfsLocal->generation;
921 }
922
923 return true;
924 }
925
926 static bool checkOutgoingProtobufExport(LocalStateHolder<LuaConfigItems>& luaconfsLocal)
927 {
928 if (!luaconfsLocal->outgoingProtobufExportConfig.enabled) {
929 if (t_outgoingProtobufServers) {
930 for (auto& server : *t_outgoingProtobufServers) {
931 server->stop();
932 }
933 }
934 t_outgoingProtobufServers.reset();
935
936 return false;
937 }
938
939 /* if the server was not running, or if it was running according to a
940 previous configuration */
941 if (!t_outgoingProtobufServers ||
942 t_outgoingProtobufServersGeneration < luaconfsLocal->generation) {
943
944 if (t_outgoingProtobufServers) {
945 for (auto& server : *t_outgoingProtobufServers) {
946 server->stop();
947 }
948 }
949 t_outgoingProtobufServers.reset();
950
951 t_outgoingProtobufServers = startProtobufServers(luaconfsLocal->outgoingProtobufExportConfig);
952 t_outgoingProtobufServersGeneration = luaconfsLocal->generation;
953 }
954
955 return true;
956 }
957 #endif /* HAVE_PROTOBUF */
958
959 #ifdef NOD_ENABLED
960 static bool nodCheckNewDomain(const DNSName& dname)
961 {
962 static const QType qt(QType::A);
963 static const uint16_t qc(QClass::IN);
964 bool ret = false;
965 // First check the (sub)domain isn't whitelisted for NOD purposes
966 if (!g_nodDomainWL.check(dname)) {
967 // Now check the NODDB (note this is probablistic so can have FNs/FPs)
968 if (t_nodDBp && t_nodDBp->isNewDomain(dname)) {
969 if (g_nodLog) {
970 // This should probably log to a dedicated log file
971 g_log<<Logger::Notice<<"Newly observed domain nod="<<dname.toLogString()<<endl;
972 }
973 if (!(g_nodLookupDomain.isRoot())) {
974 // Send a DNS A query to <domain>.g_nodLookupDomain
975 DNSName qname = dname;
976 vector<DNSRecord> dummy;
977 qname += g_nodLookupDomain;
978 directResolve(qname, qt, qc, dummy);
979 }
980 ret = true;
981 }
982 }
983 return ret;
984 }
985
986 static void nodAddDomain(const DNSName& dname)
987 {
988 // Don't bother adding domains on the nod whitelist
989 if (!g_nodDomainWL.check(dname)) {
990 if (t_nodDBp) {
991 // This keeps the nod info up to date
992 t_nodDBp->addDomain(dname);
993 }
994 }
995 }
996
997 static bool udrCheckUniqueDNSRecord(const DNSName& dname, uint16_t qtype, const DNSRecord& record)
998 {
999 bool ret = false;
1000 if (record.d_place == DNSResourceRecord::ANSWER ||
1001 record.d_place == DNSResourceRecord::ADDITIONAL) {
1002 // Create a string that represent a triplet of (qname, qtype and RR[type, name, content])
1003 std::stringstream ss;
1004 ss << dname.toDNSStringLC() << ":" << qtype << ":" << qtype << ":" << record.d_type << ":" << record.d_name.toDNSStringLC() << ":" << record.d_content->getZoneRepresentation();
1005 if (t_udrDBp && t_udrDBp->isUniqueResponse(ss.str())) {
1006 if (g_udrLog) {
1007 // This should also probably log to a dedicated file.
1008 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;
1009 }
1010 ret = true;
1011 }
1012 }
1013 return ret;
1014 }
1015 #endif /* NOD_ENABLED */
1016
1017 static void startDoResolve(void *p)
1018 {
1019 auto dc=std::unique_ptr<DNSComboWriter>(reinterpret_cast<DNSComboWriter*>(p));
1020 try {
1021 if (t_queryring)
1022 t_queryring->push_back(make_pair(dc->d_mdp.d_qname, dc->d_mdp.d_qtype));
1023
1024 uint16_t maxanswersize = dc->d_tcp ? 65535 : min(static_cast<uint16_t>(512), g_udpTruncationThreshold);
1025 EDNSOpts edo;
1026 std::vector<pair<uint16_t, string> > ednsOpts;
1027 bool variableAnswer = dc->d_variable;
1028 bool haveEDNS=false;
1029 #ifdef NOD_ENABLED
1030 bool hasUDR = false;
1031 #endif /* NOD_ENABLED */
1032 DNSPacketWriter::optvect_t returnedEdnsOptions; // Here we stuff all the options for the return packet
1033 uint8_t ednsExtRCode = 0;
1034 if(getEDNSOpts(dc->d_mdp, &edo)) {
1035 haveEDNS=true;
1036 if (edo.d_version != 0) {
1037 ednsExtRCode = ERCode::BADVERS;
1038 }
1039
1040 if(!dc->d_tcp) {
1041 /* rfc6891 6.2.3:
1042 "Values lower than 512 MUST be treated as equal to 512."
1043 */
1044 maxanswersize = min(static_cast<uint16_t>(edo.d_packetsize >= 512 ? edo.d_packetsize : 512), g_udpTruncationThreshold);
1045 }
1046 ednsOpts = edo.d_options;
1047 haveEDNS=true;
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(dc->d_mdp.d_header.qr) {
1963 g_stats.ignoredCount++;
1964 if(g_logCommonErrors) {
1965 g_log<<Logger::Error<<"Ignoring answer from TCP client "<< dc->getRemote() <<" on server socket!"<<endl;
1966 }
1967 return;
1968 }
1969 if(dc->d_mdp.d_header.opcode) {
1970 g_stats.ignoredCount++;
1971 if(g_logCommonErrors) {
1972 g_log<<Logger::Error<<"Ignoring non-query opcode from TCP client "<< dc->getRemote() <<" on server socket!"<<endl;
1973 }
1974 return;
1975 }
1976 else if (dh->qdcount == 0) {
1977 g_stats.emptyQueriesCount++;
1978 if(g_logCommonErrors) {
1979 g_log<<Logger::Error<<"Ignoring empty (qdcount == 0) query from "<< dc->getRemote() <<" on server socket!"<<endl;
1980 }
1981 return;
1982 }
1983 else {
1984 ++g_stats.qcounter;
1985 ++g_stats.tcpqcounter;
1986 MT->makeThread(startDoResolve, dc.release()); // deletes dc, will set state to BYTE0 again
1987 return;
1988 }
1989 }
1990 }
1991 }
1992
1993 //! Handle new incoming TCP connection
1994 static void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t& )
1995 {
1996 ComboAddress addr;
1997 socklen_t addrlen=sizeof(addr);
1998 int newsock=accept(fd, (struct sockaddr*)&addr, &addrlen);
1999 if(newsock>=0) {
2000 if(MT->numProcesses() > g_maxMThreads) {
2001 g_stats.overCapacityDrops++;
2002 try {
2003 closesocket(newsock);
2004 }
2005 catch(const PDNSException& e) {
2006 g_log<<Logger::Error<<"Error closing TCP socket after an over capacity drop: "<<e.reason<<endl;
2007 }
2008 return;
2009 }
2010
2011 if(t_remotes)
2012 t_remotes->push_back(addr);
2013 if(t_allowFrom && !t_allowFrom->match(&addr)) {
2014 if(!g_quiet)
2015 g_log<<Logger::Error<<"["<<MT->getTid()<<"] dropping TCP query from "<<addr.toString()<<", address not matched by allow-from"<<endl;
2016
2017 g_stats.unauthorizedTCP++;
2018 try {
2019 closesocket(newsock);
2020 }
2021 catch(const PDNSException& e) {
2022 g_log<<Logger::Error<<"Error closing TCP socket after an ACL drop: "<<e.reason<<endl;
2023 }
2024 return;
2025 }
2026 if(g_maxTCPPerClient && t_tcpClientCounts->count(addr) && (*t_tcpClientCounts)[addr] >= g_maxTCPPerClient) {
2027 g_stats.tcpClientOverflow++;
2028 try {
2029 closesocket(newsock); // don't call TCPConnection::closeAndCleanup here - did not enter it in the counts yet!
2030 }
2031 catch(const PDNSException& e) {
2032 g_log<<Logger::Error<<"Error closing TCP socket after an overflow drop: "<<e.reason<<endl;
2033 }
2034 return;
2035 }
2036
2037 setNonBlocking(newsock);
2038 std::shared_ptr<TCPConnection> tc = std::make_shared<TCPConnection>(newsock, addr);
2039 tc->state=TCPConnection::BYTE0;
2040
2041 t_fdm->addReadFD(tc->getFD(), handleRunningTCPQuestion, tc);
2042
2043 struct timeval now;
2044 Utility::gettimeofday(&now, 0);
2045 t_fdm->setReadTTD(tc->getFD(), now, g_tcpTimeout);
2046 }
2047 }
2048
2049 static string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fromaddr, const ComboAddress& destaddr, struct timeval tv, int fd)
2050 {
2051 gettimeofday(&g_now, 0);
2052 struct timeval diff = g_now - tv;
2053 double delta=(diff.tv_sec*1000 + diff.tv_usec/1000.0);
2054
2055 if(tv.tv_sec && delta > 1000.0) {
2056 g_stats.tooOldDrops++;
2057 return 0;
2058 }
2059
2060 ++g_stats.qcounter;
2061 if(fromaddr.sin4.sin_family==AF_INET6)
2062 g_stats.ipv6qcounter++;
2063
2064 string response;
2065 const struct dnsheader* dh = (struct dnsheader*)question.c_str();
2066 unsigned int ctag=0;
2067 uint32_t qhash = 0;
2068 bool needECS = false;
2069 bool needXPF = g_XPFAcl.match(fromaddr);
2070 std::vector<std::string> policyTags;
2071 LuaContext::LuaObject data;
2072 ComboAddress source = fromaddr;
2073 ComboAddress destination = destaddr;
2074 string requestorId;
2075 string deviceId;
2076 bool logQuery = false;
2077 #ifdef HAVE_PROTOBUF
2078 boost::uuids::uuid uniqueId;
2079 auto luaconfsLocal = g_luaconfs.getLocal();
2080 if (checkProtobufExport(luaconfsLocal)) {
2081 uniqueId = getUniqueID();
2082 needECS = true;
2083 } else if (checkOutgoingProtobufExport(luaconfsLocal)) {
2084 uniqueId = getUniqueID();
2085 }
2086 logQuery = t_protobufServers && luaconfsLocal->protobufExportConfig.logQueries;
2087 bool logResponse = t_protobufServers && luaconfsLocal->protobufExportConfig.logResponses;
2088 #endif
2089 EDNSSubnetOpts ednssubnet;
2090 bool ecsFound = false;
2091 bool ecsParsed = false;
2092 uint16_t ecsBegin = 0;
2093 uint16_t ecsEnd = 0;
2094 uint32_t ttlCap = std::numeric_limits<uint32_t>::max();
2095 bool variable = false;
2096 try {
2097 DNSName qname;
2098 uint16_t qtype=0;
2099 uint16_t qclass=0;
2100 uint32_t age;
2101 bool qnameParsed=false;
2102 #ifdef MALLOC_TRACE
2103 /*
2104 static uint64_t last=0;
2105 if(!last)
2106 g_mtracer->clearAllocators();
2107 cout<<g_mtracer->getAllocs()-last<<" "<<g_mtracer->getNumOut()<<" -- BEGIN TRACE"<<endl;
2108 last=g_mtracer->getAllocs();
2109 cout<<g_mtracer->topAllocatorsString()<<endl;
2110 g_mtracer->clearAllocators();
2111 */
2112 #endif
2113
2114 if(needECS || needXPF || (t_pdl && (t_pdl->d_gettag || t_pdl->d_gettag_ffi))) {
2115 try {
2116 EDNSOptionViewMap ednsOptions;
2117 bool xpfFound = false;
2118
2119 ecsFound = false;
2120
2121 getQNameAndSubnet(question, &qname, &qtype, &qclass,
2122 ecsFound, &ednssubnet, g_gettagNeedsEDNSOptions ? &ednsOptions : nullptr,
2123 xpfFound, needXPF ? &source : nullptr, needXPF ? &destination : nullptr);
2124
2125 qnameParsed = true;
2126 ecsParsed = true;
2127
2128 if(t_pdl) {
2129 try {
2130 if (t_pdl->d_gettag_ffi) {
2131 ctag = t_pdl->gettag_ffi(source, ednssubnet.source, destination, qname, qtype, &policyTags, data, ednsOptions, false, requestorId, deviceId, ttlCap, variable, logQuery);
2132 }
2133 else if (t_pdl->d_gettag) {
2134 ctag = t_pdl->gettag(source, ednssubnet.source, destination, qname, qtype, &policyTags, data, ednsOptions, false, requestorId, deviceId);
2135 }
2136 }
2137 catch(const std::exception& e) {
2138 if(g_logCommonErrors)
2139 g_log<<Logger::Warning<<"Error parsing a query packet qname='"<<qname<<"' for tag determination, setting tag=0: "<<e.what()<<endl;
2140 }
2141 }
2142 }
2143 catch(const std::exception& e)
2144 {
2145 if(g_logCommonErrors)
2146 g_log<<Logger::Warning<<"Error parsing a query packet for tag determination, setting tag=0: "<<e.what()<<endl;
2147 }
2148 }
2149
2150 bool cacheHit = false;
2151 boost::optional<RecProtoBufMessage> pbMessage(boost::none);
2152 #ifdef HAVE_PROTOBUF
2153 if (t_protobufServers) {
2154 pbMessage = RecProtoBufMessage(DNSProtoBufMessage::DNSProtoBufMessageType::Response);
2155 pbMessage->setServerIdentity(SyncRes::s_serverID);
2156 if (logQuery && !(luaconfsLocal->protobufExportConfig.taggedOnly && policyTags.empty())) {
2157 protobufLogQuery(luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, uniqueId, source, destination, ednssubnet.source, false, dh->id, question.size(), qname, qtype, qclass, policyTags, requestorId, deviceId);
2158 }
2159 }
2160 #endif /* HAVE_PROTOBUF */
2161
2162 /* It might seem like a good idea to skip the packet cache lookup if we know that the answer is not cacheable,
2163 but it means that the hash would not be computed. If some script decides at a later time to mark back the answer
2164 as cacheable we would cache it with a wrong tag, so better safe than sorry. */
2165 vState valState;
2166 if (qnameParsed) {
2167 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));
2168 }
2169 else {
2170 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));
2171 }
2172
2173 if (cacheHit) {
2174 if(valState == Bogus) {
2175 if(t_bogusremotes)
2176 t_bogusremotes->push_back(source);
2177 if(t_bogusqueryring)
2178 t_bogusqueryring->push_back(make_pair(qname, qtype));
2179 }
2180
2181 #ifdef HAVE_PROTOBUF
2182 if(t_protobufServers && logResponse && !(luaconfsLocal->protobufExportConfig.taggedOnly && pbMessage->getAppliedPolicy().empty() && pbMessage->getPolicyTags().empty())) {
2183 Netmask requestorNM(source, source.sin4.sin_family == AF_INET ? luaconfsLocal->protobufMaskV4 : luaconfsLocal->protobufMaskV6);
2184 const ComboAddress& requestor = requestorNM.getMaskedNetwork();
2185 pbMessage->update(uniqueId, &requestor, &destination, false, dh->id);
2186 pbMessage->setEDNSSubnet(ednssubnet.source, ednssubnet.source.isIpv4() ? luaconfsLocal->protobufMaskV4 : luaconfsLocal->protobufMaskV6);
2187 pbMessage->setQueryTime(g_now.tv_sec, g_now.tv_usec);
2188 pbMessage->setRequestorId(requestorId);
2189 pbMessage->setDeviceId(deviceId);
2190 protobufLogResponse(*pbMessage);
2191 }
2192 #endif /* HAVE_PROTOBUF */
2193 if(!g_quiet)
2194 g_log<<Logger::Notice<<t_id<< " question answered from packet cache tag="<<ctag<<" from "<<source.toStringWithPort()<<(source != fromaddr ? " (via "+fromaddr.toStringWithPort()+")" : "")<<endl;
2195
2196 g_stats.packetCacheHits++;
2197 SyncRes::s_queries++;
2198 ageDNSPacket(response, age);
2199 struct msghdr msgh;
2200 struct iovec iov;
2201 char cbuf[256];
2202 fillMSGHdr(&msgh, &iov, cbuf, 0, (char*)response.c_str(), response.length(), const_cast<ComboAddress*>(&fromaddr));
2203 msgh.msg_control=NULL;
2204
2205 if(g_fromtosockets.count(fd)) {
2206 addCMsgSrcAddr(&msgh, cbuf, &destaddr, 0);
2207 }
2208 if(sendmsg(fd, &msgh, 0) < 0 && g_logCommonErrors)
2209 g_log<<Logger::Warning<<"Sending UDP reply to client "<<source.toStringWithPort()<<(source != fromaddr ? " (via "+fromaddr.toStringWithPort()+")" : "")<<" failed with: "<<strerror(errno)<<endl;
2210
2211 if(response.length() >= sizeof(struct dnsheader)) {
2212 struct dnsheader tmpdh;
2213 memcpy(&tmpdh, response.c_str(), sizeof(tmpdh));
2214 updateResponseStats(tmpdh.rcode, source, response.length(), 0, 0);
2215 }
2216 g_stats.avgLatencyUsec=(1-1.0/g_latencyStatSize)*g_stats.avgLatencyUsec + 0.0; // we assume 0 usec
2217 g_stats.avgLatencyOursUsec=(1-1.0/g_latencyStatSize)*g_stats.avgLatencyOursUsec + 0.0; // we assume 0 usec
2218 return 0;
2219 }
2220 }
2221 catch(std::exception& e) {
2222 g_log<<Logger::Error<<"Error processing or aging answer packet: "<<e.what()<<endl;
2223 return 0;
2224 }
2225
2226 if(t_pdl) {
2227 if(t_pdl->ipfilter(source, destination, *dh)) {
2228 if(!g_quiet)
2229 g_log<<Logger::Notice<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] DROPPED question from "<<source.toStringWithPort()<<(source != fromaddr ? " (via "+fromaddr.toStringWithPort()+")" : "")<<" based on policy"<<endl;
2230 g_stats.policyDrops++;
2231 return 0;
2232 }
2233 }
2234
2235 if(MT->numProcesses() > g_maxMThreads) {
2236 if(!g_quiet)
2237 g_log<<Logger::Notice<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] DROPPED question from "<<source.toStringWithPort()<<(source != fromaddr ? " (via "+fromaddr.toStringWithPort()+")" : "")<<", over capacity"<<endl;
2238
2239 g_stats.overCapacityDrops++;
2240 return 0;
2241 }
2242
2243 auto dc = std::unique_ptr<DNSComboWriter>(new DNSComboWriter(question, g_now, std::move(policyTags), std::move(data)));
2244 dc->setSocket(fd);
2245 dc->d_tag=ctag;
2246 dc->d_qhash=qhash;
2247 dc->setRemote(fromaddr);
2248 dc->setSource(source);
2249 dc->setLocal(destaddr);
2250 dc->setDestination(destination);
2251 dc->d_tcp=false;
2252 dc->d_ecsFound = ecsFound;
2253 dc->d_ecsParsed = ecsParsed;
2254 dc->d_ecsBegin = ecsBegin;
2255 dc->d_ecsEnd = ecsEnd;
2256 dc->d_ednssubnet = ednssubnet;
2257 dc->d_ttlCap = ttlCap;
2258 dc->d_variable = variable;
2259 #ifdef HAVE_PROTOBUF
2260 if (t_protobufServers || t_outgoingProtobufServers) {
2261 dc->d_uuid = std::move(uniqueId);
2262 }
2263 dc->d_requestorId = requestorId;
2264 dc->d_deviceId = deviceId;
2265 #endif
2266
2267 MT->makeThread(startDoResolve, (void*) dc.release()); // deletes dc
2268 return 0;
2269 }
2270
2271
2272 static void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
2273 {
2274 ssize_t len;
2275 static const size_t maxIncomingQuerySize = 512;
2276 static thread_local std::string data;
2277 ComboAddress fromaddr;
2278 struct msghdr msgh;
2279 struct iovec iov;
2280 char cbuf[256];
2281 bool firstQuery = true;
2282
2283 for(size_t queriesCounter = 0; queriesCounter < s_maxUDPQueriesPerRound; queriesCounter++) {
2284 data.resize(maxIncomingQuerySize);
2285 fromaddr.sin6.sin6_family=AF_INET6; // this makes sure fromaddr is big enough
2286 fillMSGHdr(&msgh, &iov, cbuf, sizeof(cbuf), &data[0], data.size(), &fromaddr);
2287
2288 if((len=recvmsg(fd, &msgh, 0)) >= 0) {
2289
2290 firstQuery = false;
2291
2292 if (static_cast<size_t>(len) < sizeof(dnsheader)) {
2293 g_stats.ignoredCount++;
2294 if (!g_quiet) {
2295 g_log<<Logger::Error<<"Ignoring too-short ("<<std::to_string(len)<<") query from "<<fromaddr.toString()<<endl;
2296 }
2297 return;
2298 }
2299
2300 if (msgh.msg_flags & MSG_TRUNC) {
2301 g_stats.truncatedDrops++;
2302 if (!g_quiet) {
2303 g_log<<Logger::Error<<"Ignoring truncated query from "<<fromaddr.toString()<<endl;
2304 }
2305 return;
2306 }
2307
2308 if(t_remotes) {
2309 t_remotes->push_back(fromaddr);
2310 }
2311
2312 if(t_allowFrom && !t_allowFrom->match(&fromaddr)) {
2313 if(!g_quiet) {
2314 g_log<<Logger::Error<<"["<<MT->getTid()<<"] dropping UDP query from "<<fromaddr.toString()<<", address not matched by allow-from"<<endl;
2315 }
2316
2317 g_stats.unauthorizedUDP++;
2318 return;
2319 }
2320 BOOST_STATIC_ASSERT(offsetof(sockaddr_in, sin_port) == offsetof(sockaddr_in6, sin6_port));
2321 if(!fromaddr.sin4.sin_port) { // also works for IPv6
2322 if(!g_quiet) {
2323 g_log<<Logger::Error<<"["<<MT->getTid()<<"] dropping UDP query from "<<fromaddr.toStringWithPort()<<", can't deal with port 0"<<endl;
2324 }
2325
2326 g_stats.clientParseError++; // not quite the best place to put it, but needs to go somewhere
2327 return;
2328 }
2329
2330 try {
2331 data.resize(static_cast<size_t>(len));
2332 dnsheader* dh=(dnsheader*)&data[0];
2333
2334 if(dh->qr) {
2335 g_stats.ignoredCount++;
2336 if(g_logCommonErrors) {
2337 g_log<<Logger::Error<<"Ignoring answer from "<<fromaddr.toString()<<" on server socket!"<<endl;
2338 }
2339 }
2340 else if(dh->opcode) {
2341 g_stats.ignoredCount++;
2342 if(g_logCommonErrors) {
2343 g_log<<Logger::Error<<"Ignoring non-query opcode "<<dh->opcode<<" from "<<fromaddr.toString()<<" on server socket!"<<endl;
2344 }
2345 }
2346 else if (dh->qdcount == 0) {
2347 g_stats.emptyQueriesCount++;
2348 if(g_logCommonErrors) {
2349 g_log<<Logger::Error<<"Ignoring empty (qdcount == 0) query from "<<fromaddr.toString()<<" on server socket!"<<endl;
2350 }
2351 }
2352 else {
2353 struct timeval tv={0,0};
2354 HarvestTimestamp(&msgh, &tv);
2355 ComboAddress dest;
2356 dest.reset(); // this makes sure we ignore this address if not returned by recvmsg above
2357 auto loc = rplookup(g_listenSocketsAddresses, fd);
2358 if(HarvestDestinationAddress(&msgh, &dest)) {
2359 // but.. need to get port too
2360 if(loc) {
2361 dest.sin4.sin_port = loc->sin4.sin_port;
2362 }
2363 }
2364 else {
2365 if(loc) {
2366 dest = *loc;
2367 }
2368 else {
2369 dest.sin4.sin_family = fromaddr.sin4.sin_family;
2370 socklen_t slen = dest.getSocklen();
2371 getsockname(fd, (sockaddr*)&dest, &slen); // if this fails, we're ok with it
2372 }
2373 }
2374
2375 if(g_weDistributeQueries) {
2376 distributeAsyncFunction(data, boost::bind(doProcessUDPQuestion, data, fromaddr, dest, tv, fd));
2377 }
2378 else {
2379 doProcessUDPQuestion(data, fromaddr, dest, tv, fd);
2380 }
2381 }
2382 }
2383 catch(const MOADNSException &mde) {
2384 g_stats.clientParseError++;
2385 if(g_logCommonErrors) {
2386 g_log<<Logger::Error<<"Unable to parse packet from remote UDP client "<<fromaddr.toString() <<": "<<mde.what()<<endl;
2387 }
2388 }
2389 catch(const std::runtime_error& e) {
2390 g_stats.clientParseError++;
2391 if(g_logCommonErrors) {
2392 g_log<<Logger::Error<<"Unable to parse packet from remote UDP client "<<fromaddr.toString() <<": "<<e.what()<<endl;
2393 }
2394 }
2395 }
2396 else {
2397 // cerr<<t_id<<" had error: "<<stringerror()<<endl;
2398 if(firstQuery && errno == EAGAIN) {
2399 g_stats.noPacketError++;
2400 }
2401
2402 break;
2403 }
2404 }
2405 }
2406
2407 static void makeTCPServerSockets(deferredAdd_t& deferredAdds, std::set<int>& tcpSockets)
2408 {
2409 int fd;
2410 vector<string>locals;
2411 stringtok(locals,::arg()["local-address"]," ,");
2412
2413 if(locals.empty())
2414 throw PDNSException("No local address specified");
2415
2416 for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
2417 ServiceTuple st;
2418 st.port=::arg().asNum("local-port");
2419 parseService(*i, st);
2420
2421 ComboAddress sin;
2422
2423 sin.reset();
2424 sin.sin4.sin_family = AF_INET;
2425 if(!IpToU32(st.host, (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
2426 sin.sin6.sin6_family = AF_INET6;
2427 if(makeIPv6sockaddr(st.host, &sin.sin6) < 0)
2428 throw PDNSException("Unable to resolve local address for TCP server on '"+ st.host +"'");
2429 }
2430
2431 fd=socket(sin.sin6.sin6_family, SOCK_STREAM, 0);
2432 if(fd<0)
2433 throw PDNSException("Making a TCP server socket for resolver: "+stringerror());
2434
2435 setCloseOnExec(fd);
2436
2437 int tmp=1;
2438 if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof tmp)<0) {
2439 g_log<<Logger::Error<<"Setsockopt failed for TCP listening socket"<<endl;
2440 exit(1);
2441 }
2442 if(sin.sin6.sin6_family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &tmp, sizeof(tmp)) < 0) {
2443 g_log<<Logger::Error<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<strerror(errno)<<endl;
2444 }
2445
2446 #ifdef TCP_DEFER_ACCEPT
2447 if(setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &tmp, sizeof tmp) >= 0) {
2448 if(i==locals.begin())
2449 g_log<<Logger::Info<<"Enabled TCP data-ready filter for (slight) DoS protection"<<endl;
2450 }
2451 #endif
2452
2453 if( ::arg().mustDo("non-local-bind") )
2454 Utility::setBindAny(AF_INET, fd);
2455
2456 #ifdef SO_REUSEPORT
2457 if(g_reusePort) {
2458 if(setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &tmp, sizeof(tmp)) < 0)
2459 throw PDNSException("SO_REUSEPORT: "+stringerror());
2460 }
2461 #endif
2462
2463 if (::arg().asNum("tcp-fast-open") > 0) {
2464 #ifdef TCP_FASTOPEN
2465 int fastOpenQueueSize = ::arg().asNum("tcp-fast-open");
2466 if (setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &fastOpenQueueSize, sizeof fastOpenQueueSize) < 0) {
2467 g_log<<Logger::Error<<"Failed to enable TCP Fast Open for listening socket: "<<strerror(errno)<<endl;
2468 }
2469 #else
2470 g_log<<Logger::Warning<<"TCP Fast Open configured but not supported for listening socket"<<endl;
2471 #endif
2472 }
2473
2474 sin.sin4.sin_port = htons(st.port);
2475 socklen_t socklen=sin.sin4.sin_family==AF_INET ? sizeof(sin.sin4) : sizeof(sin.sin6);
2476 if (::bind(fd, (struct sockaddr *)&sin, socklen )<0)
2477 throw PDNSException("Binding TCP server socket for "+ st.host +": "+stringerror());
2478
2479 setNonBlocking(fd);
2480 setSocketSendBuffer(fd, 65000);
2481 listen(fd, 128);
2482 deferredAdds.push_back(make_pair(fd, handleNewTCPQuestion));
2483 tcpSockets.insert(fd);
2484
2485 // we don't need to update g_listenSocketsAddresses since it doesn't work for TCP/IP:
2486 // - fd is not that which we know here, but returned from accept()
2487 if(sin.sin4.sin_family == AF_INET)
2488 g_log<<Logger::Info<<"Listening for TCP queries on "<< sin.toString() <<":"<<st.port<<endl;
2489 else
2490 g_log<<Logger::Info<<"Listening for TCP queries on ["<< sin.toString() <<"]:"<<st.port<<endl;
2491 }
2492 }
2493
2494 static void makeUDPServerSockets(deferredAdd_t& deferredAdds)
2495 {
2496 int one=1;
2497 vector<string>locals;
2498 stringtok(locals,::arg()["local-address"]," ,");
2499
2500 if(locals.empty())
2501 throw PDNSException("No local address specified");
2502
2503 for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
2504 ServiceTuple st;
2505 st.port=::arg().asNum("local-port");
2506 parseService(*i, st);
2507
2508 ComboAddress sin;
2509
2510 sin.reset();
2511 sin.sin4.sin_family = AF_INET;
2512 if(!IpToU32(st.host.c_str() , (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
2513 sin.sin6.sin6_family = AF_INET6;
2514 if(makeIPv6sockaddr(st.host, &sin.sin6) < 0)
2515 throw PDNSException("Unable to resolve local address for UDP server on '"+ st.host +"'");
2516 }
2517
2518 int fd=socket(sin.sin4.sin_family, SOCK_DGRAM, 0);
2519 if(fd < 0) {
2520 throw PDNSException("Making a UDP server socket for resolver: "+netstringerror());
2521 }
2522 if (!setSocketTimestamps(fd))
2523 g_log<<Logger::Warning<<"Unable to enable timestamp reporting for socket"<<endl;
2524
2525 if(IsAnyAddress(sin)) {
2526 if(sin.sin4.sin_family == AF_INET)
2527 if(!setsockopt(fd, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one))) // linux supports this, so why not - might fail on other systems
2528 g_fromtosockets.insert(fd);
2529 #ifdef IPV6_RECVPKTINFO
2530 if(sin.sin4.sin_family == AF_INET6)
2531 if(!setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)))
2532 g_fromtosockets.insert(fd);
2533 #endif
2534 if(sin.sin6.sin6_family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)) < 0) {
2535 g_log<<Logger::Error<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<strerror(errno)<<endl;
2536 }
2537 }
2538 if( ::arg().mustDo("non-local-bind") )
2539 Utility::setBindAny(AF_INET6, fd);
2540
2541 setCloseOnExec(fd);
2542
2543 setSocketReceiveBuffer(fd, 250000);
2544 sin.sin4.sin_port = htons(st.port);
2545
2546
2547 #ifdef SO_REUSEPORT
2548 if(g_reusePort) {
2549 if(setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
2550 throw PDNSException("SO_REUSEPORT: "+stringerror());
2551 }
2552 #endif
2553 socklen_t socklen=sin.getSocklen();
2554 if (::bind(fd, (struct sockaddr *)&sin, socklen)<0)
2555 throw PDNSException("Resolver binding to server socket on port "+ std::to_string(st.port) +" for "+ st.host+": "+stringerror());
2556
2557 setNonBlocking(fd);
2558
2559 deferredAdds.push_back(make_pair(fd, handleNewUDPQuestion));
2560 g_listenSocketsAddresses[fd]=sin; // this is written to only from the startup thread, not from the workers
2561 if(sin.sin4.sin_family == AF_INET)
2562 g_log<<Logger::Info<<"Listening for UDP queries on "<< sin.toString() <<":"<<st.port<<endl;
2563 else
2564 g_log<<Logger::Info<<"Listening for UDP queries on ["<< sin.toString() <<"]:"<<st.port<<endl;
2565 }
2566 }
2567
2568 static void daemonize(void)
2569 {
2570 if(fork())
2571 exit(0); // bye bye
2572
2573 setsid();
2574
2575 int i=open("/dev/null",O_RDWR); /* open stdin */
2576 if(i < 0)
2577 g_log<<Logger::Critical<<"Unable to open /dev/null: "<<stringerror()<<endl;
2578 else {
2579 dup2(i,0); /* stdin */
2580 dup2(i,1); /* stderr */
2581 dup2(i,2); /* stderr */
2582 close(i);
2583 }
2584 }
2585
2586 static void usr1Handler(int)
2587 {
2588 statsWanted=true;
2589 }
2590
2591 static void usr2Handler(int)
2592 {
2593 g_quiet= !g_quiet;
2594 SyncRes::setDefaultLogMode(g_quiet ? SyncRes::LogNone : SyncRes::Log);
2595 ::arg().set("quiet")=g_quiet ? "" : "no";
2596 }
2597
2598 static void doStats(void)
2599 {
2600 static time_t lastOutputTime;
2601 static uint64_t lastQueryCount;
2602
2603 uint64_t cacheHits = broadcastAccFunction<uint64_t>(pleaseGetCacheHits);
2604 uint64_t cacheMisses = broadcastAccFunction<uint64_t>(pleaseGetCacheMisses);
2605
2606 if(g_stats.qcounter && (cacheHits + cacheMisses) && SyncRes::s_queries && SyncRes::s_outqueries) {
2607 g_log<<Logger::Notice<<"stats: "<<g_stats.qcounter<<" questions, "<<
2608 broadcastAccFunction<uint64_t>(pleaseGetCacheSize)<< " cache entries, "<<
2609 broadcastAccFunction<uint64_t>(pleaseGetNegCacheSize)<<" negative entries, "<<
2610 (int)((cacheHits*100.0)/(cacheHits+cacheMisses))<<"% cache hits"<<endl;
2611
2612 g_log<<Logger::Notice<<"stats: throttle map: "
2613 << broadcastAccFunction<uint64_t>(pleaseGetThrottleSize) <<", ns speeds: "
2614 << broadcastAccFunction<uint64_t>(pleaseGetNsSpeedsSize)<<endl;
2615 g_log<<Logger::Notice<<"stats: outpacket/query ratio "<<(int)(SyncRes::s_outqueries*100.0/SyncRes::s_queries)<<"%";
2616 g_log<<Logger::Notice<<", "<<(int)(SyncRes::s_throttledqueries*100.0/(SyncRes::s_outqueries+SyncRes::s_throttledqueries))<<"% throttled, "
2617 <<SyncRes::s_nodelegated<<" no-delegation drops"<<endl;
2618 g_log<<Logger::Notice<<"stats: "<<SyncRes::s_tcpoutqueries<<" outgoing tcp connections, "<<
2619 broadcastAccFunction<uint64_t>(pleaseGetConcurrentQueries)<<" queries running, "<<SyncRes::s_outgoingtimeouts<<" outgoing timeouts"<<endl;
2620
2621 //g_log<<Logger::Notice<<"stats: "<<g_stats.ednsPingMatches<<" ping matches, "<<g_stats.ednsPingMismatches<<" mismatches, "<<
2622 //g_stats.noPingOutQueries<<" outqueries w/o ping, "<< g_stats.noEdnsOutQueries<<" w/o EDNS"<<endl;
2623
2624 g_log<<Logger::Notice<<"stats: " << broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize) <<
2625 " packet cache entries, "<<(int)(100.0*broadcastAccFunction<uint64_t>(pleaseGetPacketCacheHits)/SyncRes::s_queries) << "% packet cache hits"<<endl;
2626
2627 time_t now = time(0);
2628 if(lastOutputTime && lastQueryCount && now != lastOutputTime) {
2629 g_log<<Logger::Notice<<"stats: "<< (SyncRes::s_queries - lastQueryCount) / (now - lastOutputTime) <<" qps (average over "<< (now - lastOutputTime) << " seconds)"<<endl;
2630 }
2631 lastOutputTime = now;
2632 lastQueryCount = SyncRes::s_queries;
2633 }
2634 else if(statsWanted)
2635 g_log<<Logger::Notice<<"stats: no stats yet!"<<endl;
2636
2637 statsWanted=false;
2638 }
2639
2640 static void houseKeeping(void *)
2641 {
2642 static thread_local time_t last_rootupdate, last_prune, last_secpoll, last_trustAnchorUpdate{0};
2643 static thread_local int cleanCounter=0;
2644 static thread_local bool s_running; // houseKeeping can get suspended in secpoll, and be restarted, which makes us do duplicate work
2645 auto luaconfsLocal = g_luaconfs.getLocal();
2646
2647 if (last_trustAnchorUpdate == 0 && !luaconfsLocal->trustAnchorFileInfo.fname.empty() && luaconfsLocal->trustAnchorFileInfo.interval != 0) {
2648 // Loading the Lua config file already "refreshed" the TAs
2649 last_trustAnchorUpdate = g_now.tv_sec + luaconfsLocal->trustAnchorFileInfo.interval * 3600;
2650 }
2651
2652 try {
2653 if(s_running)
2654 return;
2655 s_running=true;
2656
2657 struct timeval now;
2658 Utility::gettimeofday(&now, 0);
2659
2660 if(now.tv_sec - last_prune > (time_t)(5 + t_id)) {
2661 DTime dt;
2662 dt.setTimeval(now);
2663 t_RC->doPrune(g_maxCacheEntries / g_numThreads); // this function is local to a thread, so fine anyhow
2664 t_packetCache->doPruneTo(g_maxPacketCacheEntries / g_numWorkerThreads);
2665
2666 SyncRes::pruneNegCache(g_maxCacheEntries / (g_numWorkerThreads * 10));
2667
2668 if(!((cleanCounter++)%40)) { // this is a full scan!
2669 time_t limit=now.tv_sec-300;
2670 SyncRes::pruneNSSpeeds(limit);
2671 }
2672 last_prune=time(0);
2673 }
2674
2675 if(now.tv_sec - last_rootupdate > 7200) {
2676 int res = SyncRes::getRootNS(g_now, nullptr);
2677 if (!res)
2678 last_rootupdate=now.tv_sec;
2679 }
2680
2681 if(isHandlerThread()) {
2682
2683 if(now.tv_sec - last_secpoll >= 3600) {
2684 try {
2685 doSecPoll(&last_secpoll);
2686 }
2687 catch(std::exception& e)
2688 {
2689 g_log<<Logger::Error<<"Exception while performing security poll: "<<e.what()<<endl;
2690 }
2691 catch(PDNSException& e)
2692 {
2693 g_log<<Logger::Error<<"Exception while performing security poll: "<<e.reason<<endl;
2694 }
2695 catch(ImmediateServFailException &e)
2696 {
2697 g_log<<Logger::Error<<"Exception while performing security poll: "<<e.reason<<endl;
2698 }
2699 catch(...)
2700 {
2701 g_log<<Logger::Error<<"Exception while performing security poll"<<endl;
2702 }
2703 }
2704
2705 if (!luaconfsLocal->trustAnchorFileInfo.fname.empty() && luaconfsLocal->trustAnchorFileInfo.interval != 0 &&
2706 g_now.tv_sec - last_trustAnchorUpdate >= (luaconfsLocal->trustAnchorFileInfo.interval * 3600)) {
2707 g_log<<Logger::Debug<<"Refreshing Trust Anchors from file"<<endl;
2708 try {
2709 map<DNSName, dsmap_t> dsAnchors;
2710 if (updateTrustAnchorsFromFile(luaconfsLocal->trustAnchorFileInfo.fname, dsAnchors)) {
2711 g_luaconfs.modify([&dsAnchors](LuaConfigItems& lci) {
2712 lci.dsAnchors = dsAnchors;
2713 });
2714 }
2715 last_trustAnchorUpdate = now.tv_sec;
2716 } catch (const PDNSException &pe) {
2717 g_log<<Logger::Error<<"Unable to update Trust Anchors: "<<pe.reason<<endl;
2718 }
2719 }
2720 s_running=false;
2721 }
2722 }
2723 catch(PDNSException& ae)
2724 {
2725 s_running=false;
2726 g_log<<Logger::Error<<"Fatal error in housekeeping thread: "<<ae.reason<<endl;
2727 throw;
2728 }
2729 }
2730
2731 static void makeThreadPipes()
2732 {
2733 /* thread 0 is the handler / SNMP, we start at 1 */
2734 for(unsigned int n = 1; n <= (g_numWorkerThreads + g_numDistributorThreads); ++n) {
2735 auto& threadInfos = s_threadInfos.at(n);
2736
2737 int fd[2];
2738 if(pipe(fd) < 0)
2739 unixDie("Creating pipe for inter-thread communications");
2740
2741 threadInfos.pipes.readToThread = fd[0];
2742 threadInfos.pipes.writeToThread = fd[1];
2743
2744 if(pipe(fd) < 0)
2745 unixDie("Creating pipe for inter-thread communications");
2746
2747 threadInfos.pipes.readFromThread = fd[0];
2748 threadInfos.pipes.writeFromThread = fd[1];
2749
2750 if(pipe(fd) < 0)
2751 unixDie("Creating pipe for inter-thread communications");
2752
2753 threadInfos.pipes.readQueriesToThread = fd[0];
2754 threadInfos.pipes.writeQueriesToThread = fd[1];
2755
2756 if (!setNonBlocking(threadInfos.pipes.writeQueriesToThread)) {
2757 unixDie("Making pipe for inter-thread communications non-blocking");
2758 }
2759 }
2760 }
2761
2762 struct ThreadMSG
2763 {
2764 pipefunc_t func;
2765 bool wantAnswer;
2766 };
2767
2768 void broadcastFunction(const pipefunc_t& func)
2769 {
2770 /* This function might be called by the worker with t_id 0 during startup
2771 for the initialization of ACLs and domain maps. After that it should only
2772 be called by the handler. */
2773
2774 if (s_threadInfos.empty() && isHandlerThread()) {
2775 /* the handler and distributors will call themselves below, but
2776 during startup we get called while s_threadInfos has not been
2777 populated yet to update the ACL or domain maps, so we need to
2778 handle that case.
2779 */
2780 func();
2781 }
2782
2783 unsigned int n = 0;
2784 for (const auto& threadInfo : s_threadInfos) {
2785 if(n++ == t_id) {
2786 func(); // don't write to ourselves!
2787 continue;
2788 }
2789
2790 ThreadMSG* tmsg = new ThreadMSG();
2791 tmsg->func = func;
2792 tmsg->wantAnswer = true;
2793 if(write(threadInfo.pipes.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) {
2794 delete tmsg;
2795
2796 unixDie("write to thread pipe returned wrong size or error");
2797 }
2798
2799 string* resp = nullptr;
2800 if(read(threadInfo.pipes.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
2801 unixDie("read from thread pipe returned wrong size or error");
2802
2803 if(resp) {
2804 delete resp;
2805 resp = nullptr;
2806 }
2807 }
2808 }
2809
2810 static bool trySendingQueryToWorker(unsigned int target, ThreadMSG* tmsg)
2811 {
2812 const auto& targetInfo = s_threadInfos[target];
2813 if(!targetInfo.isWorker) {
2814 g_log<<Logger::Error<<"distributeAsyncFunction() tried to assign a query to a non-worker thread"<<endl;
2815 exit(1);
2816 }
2817
2818 const auto& tps = targetInfo.pipes;
2819
2820 ssize_t written = write(tps.writeQueriesToThread, &tmsg, sizeof(tmsg));
2821 if (written > 0) {
2822 if (static_cast<size_t>(written) != sizeof(tmsg)) {
2823 delete tmsg;
2824 unixDie("write to thread pipe returned wrong size or error");
2825 }
2826 }
2827 else {
2828 int error = errno;
2829 if (error == EAGAIN || error == EWOULDBLOCK) {
2830 return false;
2831 } else {
2832 delete tmsg;
2833 unixDie("write to thread pipe returned wrong size or error:" + std::to_string(error));
2834 }
2835 }
2836
2837 return true;
2838 }
2839
2840 // This function is only called by the distributor threads, when pdns-distributes-queries is set
2841 void distributeAsyncFunction(const string& packet, const pipefunc_t& func)
2842 {
2843 if (!isDistributorThread()) {
2844 g_log<<Logger::Error<<"distributeAsyncFunction() has been called by a worker ("<<t_id<<")"<<endl;
2845 exit(1);
2846 }
2847
2848 unsigned int hash = hashQuestion(packet.c_str(), packet.length(), g_disthashseed);
2849 unsigned int target = /* skip handler */ 1 + g_numDistributorThreads + (hash % g_numWorkerThreads);
2850
2851 ThreadMSG* tmsg = new ThreadMSG();
2852 tmsg->func = func;
2853 tmsg->wantAnswer = false;
2854
2855 if (!trySendingQueryToWorker(target, tmsg)) {
2856 /* if this function failed but did not raise an exception, it means that the pipe
2857 was full, let's try another one */
2858 unsigned int newTarget = 0;
2859 do {
2860 newTarget = /* skip handler */ 1 + g_numDistributorThreads + dns_random(g_numWorkerThreads);
2861 } while (newTarget == target);
2862
2863 if (!trySendingQueryToWorker(newTarget, tmsg)) {
2864 g_stats.queryPipeFullDrops++;
2865 delete tmsg;
2866 }
2867 }
2868 }
2869
2870 static void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var)
2871 {
2872 ThreadMSG* tmsg = nullptr;
2873
2874 if(read(fd, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) { // fd == readToThread || fd == readQueriesToThread
2875 unixDie("read from thread pipe returned wrong size or error");
2876 }
2877
2878 void *resp=0;
2879 try {
2880 resp = tmsg->func();
2881 }
2882 catch(std::exception& e) {
2883 if(g_logCommonErrors)
2884 g_log<<Logger::Error<<"PIPE function we executed created exception: "<<e.what()<<endl; // but what if they wanted an answer.. we send 0
2885 }
2886 catch(PDNSException& e) {
2887 if(g_logCommonErrors)
2888 g_log<<Logger::Error<<"PIPE function we executed created PDNS exception: "<<e.reason<<endl; // but what if they wanted an answer.. we send 0
2889 }
2890 if(tmsg->wantAnswer) {
2891 const auto& threadInfo = s_threadInfos.at(t_id);
2892 if(write(threadInfo.pipes.writeFromThread, &resp, sizeof(resp)) != sizeof(resp)) {
2893 delete tmsg;
2894 unixDie("write to thread pipe returned wrong size or error");
2895 }
2896 }
2897
2898 delete tmsg;
2899 }
2900
2901 template<class T> void *voider(const boost::function<T*()>& func)
2902 {
2903 return func();
2904 }
2905
2906 vector<ComboAddress>& operator+=(vector<ComboAddress>&a, const vector<ComboAddress>& b)
2907 {
2908 a.insert(a.end(), b.begin(), b.end());
2909 return a;
2910 }
2911
2912 vector<pair<string, uint16_t> >& operator+=(vector<pair<string, uint16_t> >&a, const vector<pair<string, uint16_t> >& b)
2913 {
2914 a.insert(a.end(), b.begin(), b.end());
2915 return a;
2916 }
2917
2918 vector<pair<DNSName, uint16_t> >& operator+=(vector<pair<DNSName, uint16_t> >&a, const vector<pair<DNSName, uint16_t> >& b)
2919 {
2920 a.insert(a.end(), b.begin(), b.end());
2921 return a;
2922 }
2923
2924
2925 /*
2926 This function should only be called by the handler to gather metrics, wipe the cache,
2927 reload the Lua script (not the Lua config) or change the current trace regex,
2928 and by the SNMP thread to gather metrics. */
2929 template<class T> T broadcastAccFunction(const boost::function<T*()>& func)
2930 {
2931 if (!isHandlerThread()) {
2932 g_log<<Logger::Error<<"broadcastAccFunction has been called by a worker ("<<t_id<<")"<<endl;
2933 exit(1);
2934 }
2935
2936 unsigned int n = 0;
2937 T ret=T();
2938 for (const auto& threadInfo : s_threadInfos) {
2939 if (n++ == t_id) {
2940 continue;
2941 }
2942
2943 const auto& tps = threadInfo.pipes;
2944 ThreadMSG* tmsg = new ThreadMSG();
2945 tmsg->func = boost::bind(voider<T>, func);
2946 tmsg->wantAnswer = true;
2947
2948 if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) {
2949 delete tmsg;
2950 unixDie("write to thread pipe returned wrong size or error");
2951 }
2952
2953 T* resp = nullptr;
2954 if(read(tps.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
2955 unixDie("read from thread pipe returned wrong size or error");
2956
2957 if(resp) {
2958 ret += *resp;
2959 delete resp;
2960 resp = nullptr;
2961 }
2962 }
2963 return ret;
2964 }
2965
2966 template string broadcastAccFunction(const boost::function<string*()>& fun); // explicit instantiation
2967 template uint64_t broadcastAccFunction(const boost::function<uint64_t*()>& fun); // explicit instantiation
2968 template vector<ComboAddress> broadcastAccFunction(const boost::function<vector<ComboAddress> *()>& fun); // explicit instantiation
2969 template vector<pair<DNSName,uint16_t> > broadcastAccFunction(const boost::function<vector<pair<DNSName, uint16_t> > *()>& fun); // explicit instantiation
2970
2971 static void handleRCC(int fd, FDMultiplexer::funcparam_t& var)
2972 {
2973 string remote;
2974 string msg=s_rcc.recv(&remote);
2975 RecursorControlParser rcp;
2976 RecursorControlParser::func_t* command;
2977
2978 string answer=rcp.getAnswer(msg, &command);
2979
2980 // If we are inside a chroot, we need to strip
2981 if (!arg()["chroot"].empty()) {
2982 size_t len = arg()["chroot"].length();
2983 remote = remote.substr(len);
2984 }
2985
2986 try {
2987 s_rcc.send(answer, &remote);
2988 command();
2989 }
2990 catch(std::exception& e) {
2991 g_log<<Logger::Error<<"Error dealing with control socket request: "<<e.what()<<endl;
2992 }
2993 catch(PDNSException& ae) {
2994 g_log<<Logger::Error<<"Error dealing with control socket request: "<<ae.reason<<endl;
2995 }
2996 }
2997
2998 static void handleTCPClientReadable(int fd, FDMultiplexer::funcparam_t& var)
2999 {
3000 PacketID* pident=any_cast<PacketID>(&var);
3001 // cerr<<"handleTCPClientReadable called for fd "<<fd<<", pident->inNeeded: "<<pident->inNeeded<<", "<<pident->sock->getHandle()<<endl;
3002
3003 shared_array<char> buffer(new char[pident->inNeeded]);
3004
3005 ssize_t ret=recv(fd, buffer.get(), pident->inNeeded,0);
3006 if(ret > 0) {
3007 pident->inMSG.append(&buffer[0], &buffer[ret]);
3008 pident->inNeeded-=(size_t)ret;
3009 if(!pident->inNeeded || pident->inIncompleteOkay) {
3010 // cerr<<"Got entire load of "<<pident->inMSG.size()<<" bytes"<<endl;
3011 PacketID pid=*pident;
3012 string msg=pident->inMSG;
3013
3014 t_fdm->removeReadFD(fd);
3015 MT->sendEvent(pid, &msg);
3016 }
3017 else {
3018 // cerr<<"Still have "<<pident->inNeeded<<" left to go"<<endl;
3019 }
3020 }
3021 else {
3022 PacketID tmp=*pident;
3023 t_fdm->removeReadFD(fd); // pident might now be invalid (it isn't, but still)
3024 string empty;
3025 MT->sendEvent(tmp, &empty); // this conveys error status
3026 }
3027 }
3028
3029 static void handleTCPClientWritable(int fd, FDMultiplexer::funcparam_t& var)
3030 {
3031 PacketID* pid=any_cast<PacketID>(&var);
3032 ssize_t ret=send(fd, pid->outMSG.c_str() + pid->outPos, pid->outMSG.size() - pid->outPos,0);
3033 if(ret > 0) {
3034 pid->outPos+=(ssize_t)ret;
3035 if(pid->outPos==pid->outMSG.size()) {
3036 PacketID tmp=*pid;
3037 t_fdm->removeWriteFD(fd);
3038 MT->sendEvent(tmp, &tmp.outMSG); // send back what we sent to convey everything is ok
3039 }
3040 }
3041 else { // error or EOF
3042 PacketID tmp(*pid);
3043 t_fdm->removeWriteFD(fd);
3044 string sent;
3045 MT->sendEvent(tmp, &sent); // we convey error status by sending empty string
3046 }
3047 }
3048
3049 // resend event to everybody chained onto it
3050 static void doResends(MT_t::waiters_t::iterator& iter, PacketID resend, const string& content)
3051 {
3052 if(iter->key.chain.empty())
3053 return;
3054 // cerr<<"doResends called!\n";
3055 for(PacketID::chain_t::iterator i=iter->key.chain.begin(); i != iter->key.chain.end() ; ++i) {
3056 resend.fd=-1;
3057 resend.id=*i;
3058 // cerr<<"\tResending "<<content.size()<<" bytes for fd="<<resend.fd<<" and id="<<resend.id<<endl;
3059
3060 MT->sendEvent(resend, &content);
3061 g_stats.chainResends++;
3062 }
3063 }
3064
3065 static void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t& var)
3066 {
3067 PacketID pid=any_cast<PacketID>(var);
3068 ssize_t len;
3069 std::string packet;
3070 packet.resize(g_outgoingEDNSBufsize);
3071 ComboAddress fromaddr;
3072 socklen_t addrlen=sizeof(fromaddr);
3073
3074 len=recvfrom(fd, &packet.at(0), packet.size(), 0, (sockaddr *)&fromaddr, &addrlen);
3075
3076 if(len < (ssize_t) sizeof(dnsheader)) {
3077 if(len < 0)
3078 ; // cerr<<"Error on fd "<<fd<<": "<<stringerror()<<"\n";
3079 else {
3080 g_stats.serverParseError++;
3081 if(g_logCommonErrors)
3082 g_log<<Logger::Error<<"Unable to parse packet from remote UDP server "<< fromaddr.toString() <<
3083 ": packet smaller than DNS header"<<endl;
3084 }
3085
3086 t_udpclientsocks->returnSocket(fd);
3087 string empty;
3088
3089 MT_t::waiters_t::iterator iter=MT->d_waiters.find(pid);
3090 if(iter != MT->d_waiters.end())
3091 doResends(iter, pid, empty);
3092
3093 MT->sendEvent(pid, &empty); // this denotes error (does lookup again.. at least L1 will be hot)
3094 return;
3095 }
3096
3097 packet.resize(len);
3098 dnsheader dh;
3099 memcpy(&dh, &packet.at(0), sizeof(dh));
3100
3101 PacketID pident;
3102 pident.remote=fromaddr;
3103 pident.id=dh.id;
3104 pident.fd=fd;
3105
3106 if(!dh.qr && g_logCommonErrors) {
3107 g_log<<Logger::Notice<<"Not taking data from question on outgoing socket from "<< fromaddr.toStringWithPort() <<endl;
3108 }
3109
3110 if(!dh.qdcount || // UPC, Nominum, very old BIND on FormErr, NSD
3111 !dh.qr) { // one weird server
3112 pident.domain.clear();
3113 pident.type = 0;
3114 }
3115 else {
3116 try {
3117 if(len > 12)
3118 pident.domain=DNSName(&packet.at(0), len, 12, false, &pident.type); // don't copy this from above - we need to do the actual read
3119 }
3120 catch(std::exception& e) {
3121 g_stats.serverParseError++; // won't be fed to lwres.cc, so we have to increment
3122 g_log<<Logger::Warning<<"Error in packet from remote nameserver "<< fromaddr.toStringWithPort() << ": "<<e.what() << endl;
3123 return;
3124 }
3125 }
3126
3127 MT_t::waiters_t::iterator iter=MT->d_waiters.find(pident);
3128 if(iter != MT->d_waiters.end()) {
3129 doResends(iter, pident, packet);
3130 }
3131
3132 retryWithName:
3133
3134 if(!MT->sendEvent(pident, &packet)) {
3135 // 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
3136 for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
3137 if(pident.fd==mthread->key.fd && mthread->key.remote==pident.remote && mthread->key.type == pident.type &&
3138 pident.domain == mthread->key.domain) {
3139 mthread->key.nearMisses++;
3140 }
3141
3142 // be a bit paranoid here since we're weakening our matching
3143 if(pident.domain.empty() && !mthread->key.domain.empty() && !pident.type && mthread->key.type &&
3144 pident.id == mthread->key.id && mthread->key.remote == pident.remote) {
3145 // cerr<<"Empty response, rest matches though, sending to a waiter"<<endl;
3146 pident.domain = mthread->key.domain;
3147 pident.type = mthread->key.type;
3148 goto retryWithName; // note that this only passes on an error, lwres will still reject the packet
3149 }
3150 }
3151 g_stats.unexpectedCount++; // if we made it here, it really is an unexpected answer
3152 if(g_logCommonErrors) {
3153 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;
3154 }
3155 }
3156 else if(fd >= 0) {
3157 t_udpclientsocks->returnSocket(fd);
3158 }
3159 }
3160
3161 FDMultiplexer* getMultiplexer()
3162 {
3163 FDMultiplexer* ret;
3164 for(const auto& i : FDMultiplexer::getMultiplexerMap()) {
3165 try {
3166 ret=i.second();
3167 return ret;
3168 }
3169 catch(FDMultiplexerException &fe) {
3170 g_log<<Logger::Error<<"Non-fatal error initializing possible multiplexer ("<<fe.what()<<"), falling back"<<endl;
3171 }
3172 catch(...) {
3173 g_log<<Logger::Error<<"Non-fatal error initializing possible multiplexer"<<endl;
3174 }
3175 }
3176 g_log<<Logger::Error<<"No working multiplexer found!"<<endl;
3177 exit(1);
3178 }
3179
3180
3181 static string* doReloadLuaScript()
3182 {
3183 string fname= ::arg()["lua-dns-script"];
3184 try {
3185 if(fname.empty()) {
3186 t_pdl.reset();
3187 g_log<<Logger::Info<<t_id<<" Unloaded current lua script"<<endl;
3188 return new string("unloaded\n");
3189 }
3190 else {
3191 t_pdl = std::make_shared<RecursorLua4>();
3192 t_pdl->loadFile(fname);
3193 }
3194 }
3195 catch(std::exception& e) {
3196 g_log<<Logger::Error<<t_id<<" Retaining current script, error from '"<<fname<<"': "<< e.what() <<endl;
3197 return new string("retaining current script, error from '"+fname+"': "+e.what()+"\n");
3198 }
3199
3200 g_log<<Logger::Warning<<t_id<<" (Re)loaded lua script from '"<<fname<<"'"<<endl;
3201 return new string("(re)loaded '"+fname+"'\n");
3202 }
3203
3204 string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end)
3205 {
3206 if(begin != end)
3207 ::arg().set("lua-dns-script") = *begin;
3208
3209 return broadcastAccFunction<string>(doReloadLuaScript);
3210 }
3211
3212 static string* pleaseUseNewTraceRegex(const std::string& newRegex)
3213 try
3214 {
3215 if(newRegex.empty()) {
3216 t_traceRegex.reset();
3217 return new string("unset\n");
3218 }
3219 else {
3220 t_traceRegex = std::make_shared<Regex>(newRegex);
3221 return new string("ok\n");
3222 }
3223 }
3224 catch(PDNSException& ae)
3225 {
3226 return new string(ae.reason+"\n");
3227 }
3228
3229 string doTraceRegex(vector<string>::const_iterator begin, vector<string>::const_iterator end)
3230 {
3231 return broadcastAccFunction<string>(boost::bind(pleaseUseNewTraceRegex, begin!=end ? *begin : ""));
3232 }
3233
3234 static void checkLinuxIPv6Limits()
3235 {
3236 #ifdef __linux__
3237 string line;
3238 if(readFileIfThere("/proc/sys/net/ipv6/route/max_size", &line)) {
3239 int lim=std::stoi(line);
3240 if(lim < 16384) {
3241 g_log<<Logger::Error<<"If using IPv6, please raise sysctl net.ipv6.route.max_size, currently set to "<<lim<<" which is < 16384"<<endl;
3242 }
3243 }
3244 #endif
3245 }
3246 static void checkOrFixFDS()
3247 {
3248 unsigned int availFDs=getFilenumLimit();
3249 unsigned int wantFDs = g_maxMThreads * g_numWorkerThreads +25; // even healthier margin then before
3250
3251 if(wantFDs > availFDs) {
3252 unsigned int hardlimit= getFilenumLimit(true);
3253 if(hardlimit >= wantFDs) {
3254 setFilenumLimit(wantFDs);
3255 g_log<<Logger::Warning<<"Raised soft limit on number of filedescriptors to "<<wantFDs<<" to match max-mthreads and threads settings"<<endl;
3256 }
3257 else {
3258 int newval = (hardlimit - 25) / g_numWorkerThreads;
3259 g_log<<Logger::Warning<<"Insufficient number of filedescriptors available for max-mthreads*threads setting! ("<<hardlimit<<" < "<<wantFDs<<"), reducing max-mthreads to "<<newval<<endl;
3260 g_maxMThreads = newval;
3261 setFilenumLimit(hardlimit);
3262 }
3263 }
3264 }
3265
3266 static void* recursorThread(unsigned int tid, const string& threadName);
3267
3268 static void* pleaseSupplantACLs(std::shared_ptr<NetmaskGroup> ng)
3269 {
3270 t_allowFrom = ng;
3271 return nullptr;
3272 }
3273
3274 int g_argc;
3275 char** g_argv;
3276
3277 void parseACLs()
3278 {
3279 static bool l_initialized;
3280
3281 if(l_initialized) { // only reload configuration file on second call
3282 string configname=::arg()["config-dir"]+"/recursor.conf";
3283 if(::arg()["config-name"]!="") {
3284 configname=::arg()["config-dir"]+"/recursor-"+::arg()["config-name"]+".conf";
3285 }
3286 cleanSlashes(configname);
3287
3288 if(!::arg().preParseFile(configname.c_str(), "allow-from-file"))
3289 throw runtime_error("Unable to re-parse configuration file '"+configname+"'");
3290 ::arg().preParseFile(configname.c_str(), "allow-from", LOCAL_NETS);
3291 ::arg().preParseFile(configname.c_str(), "include-dir");
3292 ::arg().preParse(g_argc, g_argv, "include-dir");
3293
3294 // then process includes
3295 std::vector<std::string> extraConfigs;
3296 ::arg().gatherIncludes(extraConfigs);
3297
3298 for(const std::string& fn : extraConfigs) {
3299 if(!::arg().preParseFile(fn.c_str(), "allow-from-file", ::arg()["allow-from-file"]))
3300 throw runtime_error("Unable to re-parse configuration file include '"+fn+"'");
3301 if(!::arg().preParseFile(fn.c_str(), "allow-from", ::arg()["allow-from"]))
3302 throw runtime_error("Unable to re-parse configuration file include '"+fn+"'");
3303 }
3304
3305 ::arg().preParse(g_argc, g_argv, "allow-from-file");
3306 ::arg().preParse(g_argc, g_argv, "allow-from");
3307 }
3308
3309 std::shared_ptr<NetmaskGroup> oldAllowFrom = t_allowFrom;
3310 std::shared_ptr<NetmaskGroup> allowFrom = std::make_shared<NetmaskGroup>();
3311
3312 if(!::arg()["allow-from-file"].empty()) {
3313 string line;
3314 ifstream ifs(::arg()["allow-from-file"].c_str());
3315 if(!ifs) {
3316 throw runtime_error("Could not open '"+::arg()["allow-from-file"]+"': "+stringerror());
3317 }
3318
3319 string::size_type pos;
3320 while(getline(ifs,line)) {
3321 pos=line.find('#');
3322 if(pos!=string::npos)
3323 line.resize(pos);
3324 trim(line);
3325 if(line.empty())
3326 continue;
3327
3328 allowFrom->addMask(line);
3329 }
3330 g_log<<Logger::Warning<<"Done parsing " << allowFrom->size() <<" allow-from ranges from file '"<<::arg()["allow-from-file"]<<"' - overriding 'allow-from' setting"<<endl;
3331 }
3332 else if(!::arg()["allow-from"].empty()) {
3333 vector<string> ips;
3334 stringtok(ips, ::arg()["allow-from"], ", ");
3335
3336 g_log<<Logger::Warning<<"Only allowing queries from: ";
3337 for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
3338 allowFrom->addMask(*i);
3339 if(i!=ips.begin())
3340 g_log<<Logger::Warning<<", ";
3341 g_log<<Logger::Warning<<*i;
3342 }
3343 g_log<<Logger::Warning<<endl;
3344 }
3345 else {
3346 if(::arg()["local-address"]!="127.0.0.1" && ::arg().asNum("local-port")==53)
3347 g_log<<Logger::Warning<<"WARNING: Allowing queries from all IP addresses - this can be a security risk!"<<endl;
3348 allowFrom = nullptr;
3349 }
3350
3351 g_initialAllowFrom = allowFrom;
3352 broadcastFunction(boost::bind(pleaseSupplantACLs, allowFrom));
3353 oldAllowFrom = nullptr;
3354
3355 l_initialized = true;
3356 }
3357
3358
3359 static void setupDelegationOnly()
3360 {
3361 vector<string> parts;
3362 stringtok(parts, ::arg()["delegation-only"], ", \t");
3363 for(const auto& p : parts) {
3364 SyncRes::addDelegationOnly(DNSName(p));
3365 }
3366 }
3367
3368 static std::map<unsigned int, std::set<int> > parseCPUMap()
3369 {
3370 std::map<unsigned int, std::set<int> > result;
3371
3372 const std::string value = ::arg()["cpu-map"];
3373
3374 if (!value.empty() && !isSettingThreadCPUAffinitySupported()) {
3375 g_log<<Logger::Warning<<"CPU mapping requested but not supported, skipping"<<endl;
3376 return result;
3377 }
3378
3379 std::vector<std::string> parts;
3380
3381 stringtok(parts, value, " \t");
3382
3383 for(const auto& part : parts) {
3384 if (part.find('=') == string::npos)
3385 continue;
3386
3387 try {
3388 auto headers = splitField(part, '=');
3389 trim(headers.first);
3390 trim(headers.second);
3391
3392 unsigned int threadId = pdns_stou(headers.first);
3393 std::vector<std::string> cpus;
3394
3395 stringtok(cpus, headers.second, ",");
3396
3397 for(const auto& cpu : cpus) {
3398 int cpuId = std::stoi(cpu);
3399
3400 result[threadId].insert(cpuId);
3401 }
3402 }
3403 catch(const std::exception& e) {
3404 g_log<<Logger::Error<<"Error parsing cpu-map entry '"<<part<<"': "<<e.what()<<endl;
3405 }
3406 }
3407
3408 return result;
3409 }
3410
3411 static void setCPUMap(const std::map<unsigned int, std::set<int> >& cpusMap, unsigned int n, pthread_t tid)
3412 {
3413 const auto& cpuMapping = cpusMap.find(n);
3414 if (cpuMapping != cpusMap.cend()) {
3415 int rc = mapThreadToCPUList(tid, cpuMapping->second);
3416 if (rc == 0) {
3417 g_log<<Logger::Info<<"CPU affinity for worker "<<n<<" has been set to CPU map:";
3418 for (const auto cpu : cpuMapping->second) {
3419 g_log<<Logger::Info<<" "<<cpu;
3420 }
3421 g_log<<Logger::Info<<endl;
3422 }
3423 else {
3424 g_log<<Logger::Warning<<"Error setting CPU affinity for worker "<<n<<" to CPU map:";
3425 for (const auto cpu : cpuMapping->second) {
3426 g_log<<Logger::Info<<" "<<cpu;
3427 }
3428 g_log<<Logger::Info<<strerror(rc)<<endl;
3429 }
3430 }
3431 }
3432
3433 #ifdef NOD_ENABLED
3434 static void setupNODThread()
3435 {
3436 if (g_nodEnabled) {
3437 uint32_t num_cells = ::arg().asNum("new-domain-db-size");
3438 t_nodDBp = std::make_shared<nod::NODDB>(num_cells);
3439 try {
3440 t_nodDBp->setCacheDir(::arg()["new-domain-history-dir"]);
3441 }
3442 catch (const PDNSException& e) {
3443 g_log<<Logger::Error<<"new-domain-history-dir (" << ::arg()["new-domain-history-dir"] << ") is not readable or does not exist"<<endl;
3444 _exit(1);
3445 }
3446 if (!t_nodDBp->init()) {
3447 g_log<<Logger::Error<<"Could not initialize domain tracking"<<endl;
3448 _exit(1);
3449 }
3450 std::thread t(nod::NODDB::startHousekeepingThread, t_nodDBp, std::this_thread::get_id());
3451 t.detach();
3452 g_nod_pbtag = ::arg()["new-domain-pb-tag"];
3453 }
3454 if (g_udrEnabled) {
3455 uint32_t num_cells = ::arg().asNum("unique-response-db-size");
3456 t_udrDBp = std::make_shared<nod::UniqueResponseDB>(num_cells);
3457 try {
3458 t_udrDBp->setCacheDir(::arg()["unique-response-history-dir"]);
3459 }
3460 catch (const PDNSException& e) {
3461 g_log<<Logger::Error<<"unique-response-history-dir (" << ::arg()["unique-response-history-dir"] << ") is not readable or does not exist"<<endl;
3462 _exit(1);
3463 }
3464 if (!t_udrDBp->init()) {
3465 g_log<<Logger::Error<<"Could not initialize unique response tracking"<<endl;
3466 _exit(1);
3467 }
3468 std::thread t(nod::UniqueResponseDB::startHousekeepingThread, t_udrDBp, std::this_thread::get_id());
3469 t.detach();
3470 g_udr_pbtag = ::arg()["unique-response-pb-tag"];
3471 }
3472 }
3473
3474 void parseNODWhitelist(const std::string& wlist)
3475 {
3476 vector<string> parts;
3477 stringtok(parts, wlist, ",; ");
3478 for(const auto& a : parts) {
3479 g_nodDomainWL.add(DNSName(a));
3480 }
3481 }
3482
3483 static void setupNODGlobal()
3484 {
3485 // Setup NOD subsystem
3486 g_nodEnabled = ::arg().mustDo("new-domain-tracking");
3487 g_nodLookupDomain = DNSName(::arg()["new-domain-lookup"]);
3488 g_nodLog = ::arg().mustDo("new-domain-log");
3489 parseNODWhitelist(::arg()["new-domain-whitelist"]);
3490
3491 // Setup Unique DNS Response subsystem
3492 g_udrEnabled = ::arg().mustDo("unique-response-tracking");
3493 g_udrLog = ::arg().mustDo("unique-response-log");
3494 }
3495 #endif /* NOD_ENABLED */
3496
3497 static int serviceMain(int argc, char*argv[])
3498 {
3499 g_log.setName(s_programname);
3500 g_log.disableSyslog(::arg().mustDo("disable-syslog"));
3501 g_log.setTimestamps(::arg().mustDo("log-timestamp"));
3502
3503 if(!::arg()["logging-facility"].empty()) {
3504 int val=logFacilityToLOG(::arg().asNum("logging-facility") );
3505 if(val >= 0)
3506 g_log.setFacility(val);
3507 else
3508 g_log<<Logger::Error<<"Unknown logging facility "<<::arg().asNum("logging-facility") <<endl;
3509 }
3510
3511 showProductVersion();
3512
3513 g_disthashseed=dns_random(0xffffffff);
3514
3515 checkLinuxIPv6Limits();
3516 try {
3517 vector<string> addrs;
3518 if(!::arg()["query-local-address6"].empty()) {
3519 SyncRes::s_doIPv6=true;
3520 g_log<<Logger::Warning<<"Enabling IPv6 transport for outgoing queries"<<endl;
3521
3522 stringtok(addrs, ::arg()["query-local-address6"], ", ;");
3523 for(const string& addr : addrs) {
3524 g_localQueryAddresses6.push_back(ComboAddress(addr));
3525 }
3526 }
3527 else {
3528 g_log<<Logger::Warning<<"NOT using IPv6 for outgoing queries - set 'query-local-address6=::' to enable"<<endl;
3529 }
3530 addrs.clear();
3531 stringtok(addrs, ::arg()["query-local-address"], ", ;");
3532 for(const string& addr : addrs) {
3533 g_localQueryAddresses4.push_back(ComboAddress(addr));
3534 }
3535 }
3536 catch(std::exception& e) {
3537 g_log<<Logger::Error<<"Assigning local query addresses: "<<e.what();
3538 exit(99);
3539 }
3540
3541 // keep this ABOVE loadRecursorLuaConfig!
3542 if(::arg()["dnssec"]=="off")
3543 g_dnssecmode=DNSSECMode::Off;
3544 else if(::arg()["dnssec"]=="process-no-validate")
3545 g_dnssecmode=DNSSECMode::ProcessNoValidate;
3546 else if(::arg()["dnssec"]=="process")
3547 g_dnssecmode=DNSSECMode::Process;
3548 else if(::arg()["dnssec"]=="validate")
3549 g_dnssecmode=DNSSECMode::ValidateAll;
3550 else if(::arg()["dnssec"]=="log-fail")
3551 g_dnssecmode=DNSSECMode::ValidateForLog;
3552 else {
3553 g_log<<Logger::Error<<"Unknown DNSSEC mode "<<::arg()["dnssec"]<<endl;
3554 exit(1);
3555 }
3556
3557 g_signatureInceptionSkew = ::arg().asNum("signature-inception-skew");
3558 if (g_signatureInceptionSkew < 0) {
3559 g_log<<Logger::Error<<"A negative value for 'signature-inception-skew' is not allowed"<<endl;
3560 exit(1);
3561 }
3562
3563 g_dnssecLogBogus = ::arg().mustDo("dnssec-log-bogus");
3564 g_maxNSEC3Iterations = ::arg().asNum("nsec3-max-iterations");
3565
3566 g_maxCacheEntries = ::arg().asNum("max-cache-entries");
3567 g_maxPacketCacheEntries = ::arg().asNum("max-packetcache-entries");
3568
3569 luaConfigDelayedThreads delayedLuaThreads;
3570 try {
3571 loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads);
3572 }
3573 catch (PDNSException &e) {
3574 g_log<<Logger::Error<<"Cannot load Lua configuration: "<<e.reason<<endl;
3575 exit(1);
3576 }
3577
3578 parseACLs();
3579 initPublicSuffixList(::arg()["public-suffix-list-file"]);
3580
3581 if(!::arg()["dont-query"].empty()) {
3582 vector<string> ips;
3583 stringtok(ips, ::arg()["dont-query"], ", ");
3584 ips.push_back("0.0.0.0");
3585 ips.push_back("::");
3586
3587 g_log<<Logger::Warning<<"Will not send queries to: ";
3588 for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
3589 SyncRes::addDontQuery(*i);
3590 if(i!=ips.begin())
3591 g_log<<Logger::Warning<<", ";
3592 g_log<<Logger::Warning<<*i;
3593 }
3594 g_log<<Logger::Warning<<endl;
3595 }
3596
3597 g_quiet=::arg().mustDo("quiet");
3598
3599 /* this needs to be done before parseACLs(), which call broadcastFunction() */
3600 g_weDistributeQueries = ::arg().mustDo("pdns-distributes-queries");
3601 if(g_weDistributeQueries) {
3602 g_log<<Logger::Warning<<"PowerDNS Recursor itself will distribute queries over threads"<<endl;
3603 }
3604
3605 setupDelegationOnly();
3606 g_outgoingEDNSBufsize=::arg().asNum("edns-outgoing-bufsize");
3607
3608 if(::arg()["trace"]=="fail") {
3609 SyncRes::setDefaultLogMode(SyncRes::Store);
3610 }
3611 else if(::arg().mustDo("trace")) {
3612 SyncRes::setDefaultLogMode(SyncRes::Log);
3613 ::arg().set("quiet")="no";
3614 g_quiet=false;
3615 g_dnssecLOG=true;
3616 }
3617 string myHostname = getHostname();
3618 if (myHostname == "UNKNOWN"){
3619 g_log<<Logger::Warning<<"Unable to get the hostname, NSID and id.server values will be empty"<<endl;
3620 myHostname = "";
3621 }
3622
3623 SyncRes::s_minimumTTL = ::arg().asNum("minimum-ttl-override");
3624
3625 SyncRes::s_nopacketcache = ::arg().mustDo("disable-packetcache");
3626
3627 SyncRes::s_maxnegttl=::arg().asNum("max-negative-ttl");
3628 SyncRes::s_maxcachettl=max(::arg().asNum("max-cache-ttl"), 15);
3629 SyncRes::s_packetcachettl=::arg().asNum("packetcache-ttl");
3630 // Cap the packetcache-servfail-ttl to the packetcache-ttl
3631 uint32_t packetCacheServFailTTL = ::arg().asNum("packetcache-servfail-ttl");
3632 SyncRes::s_packetcacheservfailttl=(packetCacheServFailTTL > SyncRes::s_packetcachettl) ? SyncRes::s_packetcachettl : packetCacheServFailTTL;
3633 SyncRes::s_serverdownmaxfails=::arg().asNum("server-down-max-fails");
3634 SyncRes::s_serverdownthrottletime=::arg().asNum("server-down-throttle-time");
3635 SyncRes::s_serverID=::arg()["server-id"];
3636 SyncRes::s_maxqperq=::arg().asNum("max-qperq");
3637 SyncRes::s_maxtotusec=1000*::arg().asNum("max-total-msec");
3638 SyncRes::s_maxdepth=::arg().asNum("max-recursion-depth");
3639 SyncRes::s_rootNXTrust = ::arg().mustDo( "root-nx-trust");
3640 if(SyncRes::s_serverID.empty()) {
3641 SyncRes::s_serverID = myHostname;
3642 }
3643
3644 SyncRes::s_ecsipv4limit = ::arg().asNum("ecs-ipv4-bits");
3645 SyncRes::s_ecsipv6limit = ::arg().asNum("ecs-ipv6-bits");
3646
3647 if (!::arg().isEmpty("ecs-scope-zero-address")) {
3648 ComboAddress scopeZero(::arg()["ecs-scope-zero-address"]);
3649 SyncRes::setECSScopeZeroAddress(Netmask(scopeZero, scopeZero.isIPv4() ? 32 : 128));
3650 }
3651 else {
3652 bool found = false;
3653 for (const auto& addr : g_localQueryAddresses4) {
3654 if (!IsAnyAddress(addr)) {
3655 SyncRes::setECSScopeZeroAddress(Netmask(addr, 32));
3656 found = true;
3657 break;
3658 }
3659 }
3660 if (!found) {
3661 for (const auto& addr : g_localQueryAddresses6) {
3662 if (!IsAnyAddress(addr)) {
3663 SyncRes::setECSScopeZeroAddress(Netmask(addr, 128));
3664 found = true;
3665 break;
3666 }
3667 }
3668 if (!found) {
3669 SyncRes::setECSScopeZeroAddress(Netmask("127.0.0.1/32"));
3670 }
3671 }
3672 }
3673
3674 SyncRes::parseEDNSSubnetWhitelist(::arg()["edns-subnet-whitelist"]);
3675 SyncRes::parseEDNSSubnetAddFor(::arg()["ecs-add-for"]);
3676 g_useIncomingECS = ::arg().mustDo("use-incoming-edns-subnet");
3677
3678 g_XPFAcl.toMasks(::arg()["xpf-allow-from"]);
3679 g_xpfRRCode = ::arg().asNum("xpf-rr-code");
3680
3681 g_networkTimeoutMsec = ::arg().asNum("network-timeout");
3682
3683 g_initialDomainMap = parseAuthAndForwards();
3684
3685 g_latencyStatSize=::arg().asNum("latency-statistic-size");
3686
3687 g_logCommonErrors=::arg().mustDo("log-common-errors");
3688 g_logRPZChanges = ::arg().mustDo("log-rpz-changes");
3689
3690 g_anyToTcp = ::arg().mustDo("any-to-tcp");
3691 g_udpTruncationThreshold = ::arg().asNum("udp-truncation-threshold");
3692
3693 g_lowercaseOutgoing = ::arg().mustDo("lowercase-outgoing");
3694
3695 g_numDistributorThreads = ::arg().asNum("distributor-threads");
3696 g_numWorkerThreads = ::arg().asNum("threads");
3697 if (g_numWorkerThreads < 1) {
3698 g_log<<Logger::Warning<<"Asked to run with 0 threads, raising to 1 instead"<<endl;
3699 g_numWorkerThreads = 1;
3700 }
3701
3702 g_numThreads = g_numDistributorThreads + g_numWorkerThreads;
3703 g_maxMThreads = ::arg().asNum("max-mthreads");
3704
3705 g_gettagNeedsEDNSOptions = ::arg().mustDo("gettag-needs-edns-options");
3706
3707 g_statisticsInterval = ::arg().asNum("statistics-interval");
3708
3709 #ifdef SO_REUSEPORT
3710 g_reusePort = ::arg().mustDo("reuseport");
3711 #endif
3712
3713 s_threadInfos.resize(g_numDistributorThreads + g_numWorkerThreads + /* handler */ 1);
3714
3715 if (g_reusePort) {
3716 if (g_weDistributeQueries) {
3717 /* first thread is the handler, then distributors */
3718 for (unsigned int threadId = 1; threadId <= g_numDistributorThreads; threadId++) {
3719 auto& deferredAdds = s_threadInfos.at(threadId).deferredAdds;
3720 auto& tcpSockets = s_threadInfos.at(threadId).tcpSockets;
3721 makeUDPServerSockets(deferredAdds);
3722 makeTCPServerSockets(deferredAdds, tcpSockets);
3723 }
3724 }
3725 else {
3726 /* first thread is the handler, there is no distributor here and workers are accepting queries */
3727 for (unsigned int threadId = 1; threadId <= g_numWorkerThreads; threadId++) {
3728 auto& deferredAdds = s_threadInfos.at(threadId).deferredAdds;
3729 auto& tcpSockets = s_threadInfos.at(threadId).tcpSockets;
3730 makeUDPServerSockets(deferredAdds);
3731 makeTCPServerSockets(deferredAdds, tcpSockets);
3732 }
3733 }
3734 }
3735 else {
3736 std::set<int> tcpSockets;
3737 /* we don't have reuseport so we can only open one socket per
3738 listening addr:port and everyone will listen on it */
3739 makeUDPServerSockets(g_deferredAdds);
3740 makeTCPServerSockets(g_deferredAdds, tcpSockets);
3741
3742 /* every listener (so distributor if g_weDistributeQueries, workers otherwise)
3743 needs to listen to the shared sockets */
3744 if (g_weDistributeQueries) {
3745 /* first thread is the handler, then distributors */
3746 for (unsigned int threadId = 1; threadId <= g_numDistributorThreads; threadId++) {
3747 s_threadInfos.at(threadId).tcpSockets = tcpSockets;
3748 }
3749 }
3750 else {
3751 /* first thread is the handler, there is no distributor here and workers are accepting queries */
3752 for (unsigned int threadId = 1; threadId <= g_numWorkerThreads; threadId++) {
3753 s_threadInfos.at(threadId).tcpSockets = tcpSockets;
3754 }
3755 }
3756 }
3757
3758 #ifdef NOD_ENABLED
3759 // Setup newly observed domain globals
3760 setupNODGlobal();
3761 #endif /* NOD_ENABLED */
3762
3763 int forks;
3764 for(forks = 0; forks < ::arg().asNum("processes") - 1; ++forks) {
3765 if(!fork()) // we are child
3766 break;
3767 }
3768
3769 if(::arg().mustDo("daemon")) {
3770 g_log<<Logger::Warning<<"Calling daemonize, going to background"<<endl;
3771 g_log.toConsole(Logger::Critical);
3772 daemonize();
3773 }
3774 signal(SIGUSR1,usr1Handler);
3775 signal(SIGUSR2,usr2Handler);
3776 signal(SIGPIPE,SIG_IGN);
3777
3778 checkOrFixFDS();
3779
3780 #ifdef HAVE_LIBSODIUM
3781 if (sodium_init() == -1) {
3782 g_log<<Logger::Error<<"Unable to initialize sodium crypto library"<<endl;
3783 exit(99);
3784 }
3785 #endif
3786
3787 openssl_thread_setup();
3788 openssl_seed();
3789 /* setup rng before chroot */
3790 dns_random_init();
3791
3792 if(::arg()["server-id"].empty()) {
3793 ::arg().set("server-id") = myHostname;
3794 }
3795
3796 int newgid=0;
3797 if(!::arg()["setgid"].empty())
3798 newgid=Utility::makeGidNumeric(::arg()["setgid"]);
3799 int newuid=0;
3800 if(!::arg()["setuid"].empty())
3801 newuid=Utility::makeUidNumeric(::arg()["setuid"]);
3802
3803 Utility::dropGroupPrivs(newuid, newgid);
3804
3805 if (!::arg()["chroot"].empty()) {
3806 #ifdef HAVE_SYSTEMD
3807 char *ns;
3808 ns = getenv("NOTIFY_SOCKET");
3809 if (ns != nullptr) {
3810 g_log<<Logger::Error<<"Unable to chroot when running from systemd. Please disable chroot= or set the 'Type' for this service to 'simple'"<<endl;
3811 exit(1);
3812 }
3813 #endif
3814 if (chroot(::arg()["chroot"].c_str())<0 || chdir("/") < 0) {
3815 g_log<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror (errno)<<", exiting"<<endl;
3816 exit(1);
3817 }
3818 else
3819 g_log<<Logger::Info<<"Chrooted to '"<<::arg()["chroot"]<<"'"<<endl;
3820 }
3821
3822 s_pidfname=::arg()["socket-dir"]+"/"+s_programname+".pid";
3823 if(!s_pidfname.empty())
3824 unlink(s_pidfname.c_str()); // remove possible old pid file
3825 writePid();
3826
3827 makeControlChannelSocket( ::arg().asNum("processes") > 1 ? forks : -1);
3828
3829 Utility::dropUserPrivs(newuid);
3830 try {
3831 /* we might still have capabilities remaining, for example if we have been started as root
3832 without --setuid (please don't do that) or as an unprivileged user with ambient capabilities
3833 like CAP_NET_BIND_SERVICE.
3834 */
3835 dropCapabilities();
3836 }
3837 catch(const std::exception& e) {
3838 g_log<<Logger::Warning<<e.what()<<endl;
3839 }
3840
3841 startLuaConfigDelayedThreads(delayedLuaThreads, g_luaconfs.getCopy().generation);
3842
3843 makeThreadPipes();
3844
3845 g_tcpTimeout=::arg().asNum("client-tcp-timeout");
3846 g_maxTCPPerClient=::arg().asNum("max-tcp-per-client");
3847 g_tcpMaxQueriesPerConn=::arg().asNum("max-tcp-queries-per-connection");
3848 s_maxUDPQueriesPerRound=::arg().asNum("max-udp-queries-per-round");
3849
3850 if (::arg().mustDo("snmp-agent")) {
3851 g_snmpAgent = std::make_shared<RecursorSNMPAgent>("recursor", ::arg()["snmp-master-socket"]);
3852 g_snmpAgent->run();
3853 }
3854
3855 int port = ::arg().asNum("udp-source-port-min");
3856 if(port < 1024 || port > 65535){
3857 g_log<<Logger::Error<<"Unable to launch, udp-source-port-min is not a valid port number"<<endl;
3858 exit(99); // this isn't going to fix itself either
3859 }
3860 s_minUdpSourcePort = port;
3861 port = ::arg().asNum("udp-source-port-max");
3862 if(port < 1024 || port > 65535 || port < s_minUdpSourcePort){
3863 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;
3864 exit(99); // this isn't going to fix itself either
3865 }
3866 s_maxUdpSourcePort = port;
3867 std::vector<string> parts {};
3868 stringtok(parts, ::arg()["udp-source-port-avoid"], ", ");
3869 for (const auto &part : parts)
3870 {
3871 port = std::stoi(part);
3872 if(port < 1024 || port > 65535){
3873 g_log<<Logger::Error<<"Unable to launch, udp-source-port-avoid contains an invalid port number: "<<part<<endl;
3874 exit(99); // this isn't going to fix itself either
3875 }
3876 s_avoidUdpSourcePorts.insert(port);
3877 }
3878
3879 unsigned int currentThreadId = 1;
3880 const auto cpusMap = parseCPUMap();
3881
3882 if(g_numThreads == 1) {
3883 g_log<<Logger::Warning<<"Operating unthreaded"<<endl;
3884 #ifdef HAVE_SYSTEMD
3885 sd_notify(0, "READY=1");
3886 #endif
3887
3888 /* This thread handles the web server, carbon, statistics and the control channel */
3889 auto& handlerInfos = s_threadInfos.at(0);
3890 handlerInfos.isHandler = true;
3891 handlerInfos.thread = std::thread(recursorThread, 0, "main");
3892
3893 setCPUMap(cpusMap, currentThreadId, pthread_self());
3894
3895 auto& infos = s_threadInfos.at(currentThreadId);
3896 infos.isListener = true;
3897 infos.isWorker = true;
3898 recursorThread(currentThreadId++, "worker");
3899 }
3900 else {
3901
3902 if (g_weDistributeQueries) {
3903 g_log<<Logger::Warning<<"Launching "<< g_numDistributorThreads <<" distributor threads"<<endl;
3904 for(unsigned int n=0; n < g_numDistributorThreads; ++n) {
3905 auto& infos = s_threadInfos.at(currentThreadId);
3906 infos.isListener = true;
3907 infos.thread = std::thread(recursorThread, currentThreadId++, "distr");
3908
3909 setCPUMap(cpusMap, currentThreadId, infos.thread.native_handle());
3910 }
3911 }
3912
3913 g_log<<Logger::Warning<<"Launching "<< g_numWorkerThreads <<" worker threads"<<endl;
3914
3915 for(unsigned int n=0; n < g_numWorkerThreads; ++n) {
3916 auto& infos = s_threadInfos.at(currentThreadId);
3917 infos.isListener = g_weDistributeQueries ? false : true;
3918 infos.isWorker = true;
3919 infos.thread = std::thread(recursorThread, currentThreadId++, "worker");
3920
3921 setCPUMap(cpusMap, currentThreadId, infos.thread.native_handle());
3922 }
3923
3924 #ifdef HAVE_SYSTEMD
3925 sd_notify(0, "READY=1");
3926 #endif
3927
3928 /* This thread handles the web server, carbon, statistics and the control channel */
3929 auto& infos = s_threadInfos.at(0);
3930 infos.isHandler = true;
3931 infos.thread = std::thread(recursorThread, 0, "web+stat");
3932
3933 s_threadInfos.at(0).thread.join();
3934 }
3935 return 0;
3936 }
3937
3938 static void* recursorThread(unsigned int n, const string& threadName)
3939 try
3940 {
3941 t_id=n;
3942 auto& threadInfo = s_threadInfos.at(t_id);
3943
3944 static string threadPrefix = "pdns-r/";
3945 setThreadName(threadPrefix + threadName);
3946
3947 SyncRes tmp(g_now); // make sure it allocates tsstorage before we do anything, like primeHints or so..
3948 SyncRes::setDomainMap(g_initialDomainMap);
3949 t_allowFrom = g_initialAllowFrom;
3950 t_udpclientsocks = std::unique_ptr<UDPClientSocks>(new UDPClientSocks());
3951 t_tcpClientCounts = std::unique_ptr<tcpClientCounts_t>(new tcpClientCounts_t());
3952 primeHints();
3953
3954 t_packetCache = std::unique_ptr<RecursorPacketCache>(new RecursorPacketCache());
3955
3956 g_log<<Logger::Warning<<"Done priming cache with root hints"<<endl;
3957
3958 #ifdef NOD_ENABLED
3959 if (threadInfo.isWorker)
3960 setupNODThread();
3961 #endif /* NOD_ENABLED */
3962
3963 if(threadInfo.isWorker) {
3964 try {
3965 if(!::arg()["lua-dns-script"].empty()) {
3966 t_pdl = std::make_shared<RecursorLua4>();
3967 t_pdl->loadFile(::arg()["lua-dns-script"]);
3968 g_log<<Logger::Warning<<"Loaded 'lua' script from '"<<::arg()["lua-dns-script"]<<"'"<<endl;
3969 }
3970 }
3971 catch(std::exception &e) {
3972 g_log<<Logger::Error<<"Failed to load 'lua' script from '"<<::arg()["lua-dns-script"]<<"': "<<e.what()<<endl;
3973 _exit(99);
3974 }
3975 }
3976
3977 unsigned int ringsize=::arg().asNum("stats-ringbuffer-entries") / g_numWorkerThreads;
3978 if(ringsize) {
3979 t_remotes = std::unique_ptr<addrringbuf_t>(new addrringbuf_t());
3980 if(g_weDistributeQueries)
3981 t_remotes->set_capacity(::arg().asNum("stats-ringbuffer-entries") / g_numDistributorThreads);
3982 else
3983 t_remotes->set_capacity(ringsize);
3984 t_servfailremotes = std::unique_ptr<addrringbuf_t>(new addrringbuf_t());
3985 t_servfailremotes->set_capacity(ringsize);
3986 t_bogusremotes = std::unique_ptr<addrringbuf_t>(new addrringbuf_t());
3987 t_bogusremotes->set_capacity(ringsize);
3988 t_largeanswerremotes = std::unique_ptr<addrringbuf_t>(new addrringbuf_t());
3989 t_largeanswerremotes->set_capacity(ringsize);
3990 t_timeouts = std::unique_ptr<addrringbuf_t>(new addrringbuf_t());
3991 t_timeouts->set_capacity(ringsize);
3992
3993 t_queryring = std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t> > >(new boost::circular_buffer<pair<DNSName, uint16_t> >());
3994 t_queryring->set_capacity(ringsize);
3995 t_servfailqueryring = std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t> > >(new boost::circular_buffer<pair<DNSName, uint16_t> >());
3996 t_servfailqueryring->set_capacity(ringsize);
3997 t_bogusqueryring = std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t> > >(new boost::circular_buffer<pair<DNSName, uint16_t> >());
3998 t_bogusqueryring->set_capacity(ringsize);
3999 }
4000
4001 MT=std::unique_ptr<MTasker<PacketID,string> >(new MTasker<PacketID,string>(::arg().asNum("stack-size")));
4002
4003 #ifdef HAVE_PROTOBUF
4004 /* start protobuf export threads if needed */
4005 auto luaconfsLocal = g_luaconfs.getLocal();
4006 checkProtobufExport(luaconfsLocal);
4007 checkOutgoingProtobufExport(luaconfsLocal);
4008 #endif /* HAVE_PROTOBUF */
4009
4010 PacketID pident;
4011
4012 t_fdm=getMultiplexer();
4013
4014 if(threadInfo.isHandler) {
4015 if(::arg().mustDo("webserver")) {
4016 g_log<<Logger::Warning << "Enabling web server" << endl;
4017 try {
4018 new RecursorWebServer(t_fdm);
4019 }
4020 catch(PDNSException &e) {
4021 g_log<<Logger::Error<<"Exception: "<<e.reason<<endl;
4022 exit(99);
4023 }
4024 }
4025 g_log<<Logger::Info<<"Enabled '"<< t_fdm->getName() << "' multiplexer"<<endl;
4026 }
4027 else {
4028
4029 t_fdm->addReadFD(threadInfo.pipes.readToThread, handlePipeRequest);
4030 t_fdm->addReadFD(threadInfo.pipes.readQueriesToThread, handlePipeRequest);
4031
4032 if (threadInfo.isListener) {
4033 if (g_reusePort) {
4034 /* then every listener has its own FDs */
4035 for(const auto deferred : threadInfo.deferredAdds) {
4036 t_fdm->addReadFD(deferred.first, deferred.second);
4037 }
4038 }
4039 else {
4040 /* otherwise all listeners are listening on the same ones */
4041 for(const auto deferred : g_deferredAdds) {
4042 t_fdm->addReadFD(deferred.first, deferred.second);
4043 }
4044 }
4045 }
4046 }
4047
4048 registerAllStats();
4049
4050 if(threadInfo.isHandler) {
4051 t_fdm->addReadFD(s_rcc.d_fd, handleRCC); // control channel
4052 }
4053
4054 unsigned int maxTcpClients=::arg().asNum("max-tcp-clients");
4055
4056 bool listenOnTCP(true);
4057
4058 time_t last_stat = 0;
4059 time_t last_carbon=0, last_lua_maintenance=0;
4060 time_t carbonInterval=::arg().asNum("carbon-interval");
4061 time_t luaMaintenanceInterval=::arg().asNum("lua-maintenance-interval");
4062 counter.store(0); // used to periodically execute certain tasks
4063 for(;;) {
4064 while(MT->schedule(&g_now)); // MTasker letting the mthreads do their thing
4065
4066 if(!(counter%500)) {
4067 MT->makeThread(houseKeeping, 0);
4068 }
4069
4070 if(!(counter%55)) {
4071 typedef vector<pair<int, FDMultiplexer::funcparam_t> > expired_t;
4072 expired_t expired=t_fdm->getTimeouts(g_now);
4073
4074 for(expired_t::iterator i=expired.begin() ; i != expired.end(); ++i) {
4075 shared_ptr<TCPConnection> conn=any_cast<shared_ptr<TCPConnection> >(i->second);
4076 if(g_logCommonErrors)
4077 g_log<<Logger::Warning<<"Timeout from remote TCP client "<< conn->d_remote.toStringWithPort() <<endl;
4078 t_fdm->removeReadFD(i->first);
4079 }
4080 }
4081
4082 counter++;
4083
4084 if(threadInfo.isHandler) {
4085 if(statsWanted || (g_statisticsInterval > 0 && (g_now.tv_sec - last_stat) >= g_statisticsInterval)) {
4086 doStats();
4087 last_stat = g_now.tv_sec;
4088 }
4089
4090 Utility::gettimeofday(&g_now, 0);
4091
4092 if((g_now.tv_sec - last_carbon) >= carbonInterval) {
4093 MT->makeThread(doCarbonDump, 0);
4094 last_carbon = g_now.tv_sec;
4095 }
4096 }
4097 if (t_pdl != nullptr) {
4098 // lua-dns-script directive is present, call the maintenance callback if needed
4099 if (threadInfo.isWorker) {
4100 // Only on threads processing queries
4101 if(g_now.tv_sec - last_lua_maintenance >= luaMaintenanceInterval) {
4102 t_pdl->maintenance();
4103 last_lua_maintenance = g_now.tv_sec;
4104 }
4105 }
4106 }
4107
4108 t_fdm->run(&g_now);
4109 // 'run' updates g_now for us
4110
4111 if(threadInfo.isListener) {
4112 if(listenOnTCP) {
4113 if(TCPConnection::getCurrentConnections() > maxTcpClients) { // shutdown, too many connections
4114 for(const auto fd : threadInfo.tcpSockets) {
4115 t_fdm->removeReadFD(fd);
4116 }
4117 listenOnTCP=false;
4118 }
4119 }
4120 else {
4121 if(TCPConnection::getCurrentConnections() <= maxTcpClients) { // reenable
4122 for(const auto fd : threadInfo.tcpSockets) {
4123 t_fdm->addReadFD(fd, handleNewTCPQuestion);
4124 }
4125 listenOnTCP=true;
4126 }
4127 }
4128 }
4129 }
4130 }
4131 catch(PDNSException &ae) {
4132 g_log<<Logger::Error<<"Exception: "<<ae.reason<<endl;
4133 return 0;
4134 }
4135 catch(std::exception &e) {
4136 g_log<<Logger::Error<<"STL Exception: "<<e.what()<<endl;
4137 return 0;
4138 }
4139 catch(...) {
4140 g_log<<Logger::Error<<"any other exception in main: "<<endl;
4141 return 0;
4142 }
4143
4144
4145 int main(int argc, char **argv)
4146 {
4147 g_argc = argc;
4148 g_argv = argv;
4149 g_stats.startupTime=time(0);
4150 versionSetProduct(ProductRecursor);
4151 reportBasicTypes();
4152 reportOtherTypes();
4153
4154 int ret = EXIT_SUCCESS;
4155
4156 try {
4157 ::arg().set("stack-size","stack size per mthread")="200000";
4158 ::arg().set("soa-minimum-ttl","Don't change")="0";
4159 ::arg().set("no-shuffle","Don't change")="off";
4160 ::arg().set("local-port","port to listen on")="53";
4161 ::arg().set("local-address","IP addresses to listen on, separated by spaces or commas. Also accepts ports.")="127.0.0.1";
4162 ::arg().setSwitch("non-local-bind", "Enable binding to non-local addresses by using FREEBIND / BINDANY socket options")="no";
4163 ::arg().set("trace","if we should output heaps of logging. set to 'fail' to only log failing domains")="off";
4164 ::arg().set("dnssec", "DNSSEC mode: off/process-no-validate (default)/process/log-fail/validate")="process-no-validate";
4165 ::arg().set("dnssec-log-bogus", "Log DNSSEC bogus validations")="no";
4166 ::arg().set("signature-inception-skew", "Allow the signature inception to be off by this number of seconds")="60";
4167 ::arg().set("daemon","Operate as a daemon")="no";
4168 ::arg().setSwitch("write-pid","Write a PID file")="yes";
4169 ::arg().set("loglevel","Amount of logging. Higher is more. Do not set below 3")="6";
4170 ::arg().set("disable-syslog","Disable logging to syslog, useful when running inside a supervisor that logs stdout")="no";
4171 ::arg().set("log-timestamp","Print timestamps in log lines, useful to disable when running with a tool that timestamps stdout already")="yes";
4172 ::arg().set("log-common-errors","If we should log rather common errors")="no";
4173 ::arg().set("chroot","switch to chroot jail")="";
4174 ::arg().set("setgid","If set, change group id to this gid for more security")="";
4175 ::arg().set("setuid","If set, change user id to this uid for more security")="";
4176 ::arg().set("network-timeout", "Wait this number of milliseconds for network i/o")="1500";
4177 ::arg().set("threads", "Launch this number of threads")="2";
4178 ::arg().set("distributor-threads", "Launch this number of distributor threads, distributing queries to other threads")="0";
4179 ::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!
4180 ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
4181 ::arg().set("api-config-dir", "Directory where REST API stores config and zones") = "";
4182 ::arg().set("api-key", "Static pre-shared authentication key for access to the REST API") = "";
4183 ::arg().setSwitch("webserver", "Start a webserver (for REST API)") = "no";
4184 ::arg().set("webserver-address", "IP Address of webserver to listen on") = "127.0.0.1";
4185 ::arg().set("webserver-port", "Port of webserver to listen on") = "8082";
4186 ::arg().set("webserver-password", "Password required for accessing the webserver") = "";
4187 ::arg().set("webserver-allow-from","Webserver access is only allowed from these subnets")="127.0.0.1,::1";
4188 ::arg().set("webserver-log-level","Amount of logging in the webserver (none, common, detailed)")="common";
4189 ::arg().set("carbon-ourname", "If set, overrides our reported hostname for carbon stats")="";
4190 ::arg().set("carbon-server", "If set, send metrics in carbon (graphite) format to this server IP address")="";
4191 ::arg().set("carbon-interval", "Number of seconds between carbon (graphite) updates")="30";
4192 ::arg().set("carbon-namespace", "If set overwrites the first part of the carbon string")="pdns";
4193 ::arg().set("carbon-instance", "If set overwrites the the instance name default")="recursor";
4194
4195 ::arg().set("statistics-interval", "Number of seconds between printing of recursor statistics, 0 to disable")="1800";
4196 ::arg().set("quiet","Suppress logging of questions and answers")="";
4197 ::arg().set("logging-facility","Facility to log messages as. 0 corresponds to local0")="";
4198 ::arg().set("config-dir","Location of configuration directory (recursor.conf)")=SYSCONFDIR;
4199 ::arg().set("socket-owner","Owner of socket")="";
4200 ::arg().set("socket-group","Group of socket")="";
4201 ::arg().set("socket-mode", "Permissions for socket")="";
4202
4203 ::arg().set("socket-dir",string("Where the controlsocket will live, ")+LOCALSTATEDIR+" when unset and not chrooted" )="";
4204 ::arg().set("delegation-only","Which domains we only accept delegations from")="";
4205 ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
4206 ::arg().set("query-local-address6","Source IPv6 address for sending queries. IF UNSET, IPv6 WILL NOT BE USED FOR OUTGOING QUERIES")="";
4207 ::arg().set("client-tcp-timeout","Timeout in seconds when talking to TCP clients")="2";
4208 ::arg().set("max-mthreads", "Maximum number of simultaneous Mtasker threads")="2048";
4209 ::arg().set("max-tcp-clients","Maximum number of simultaneous TCP clients")="128";
4210 ::arg().set("server-down-max-fails","Maximum number of consecutive timeouts (and unreachables) to mark a server as down ( 0 => disabled )")="64";
4211 ::arg().set("server-down-throttle-time","Number of seconds to throttle all queries to a server after being marked as down")="60";
4212 ::arg().set("hint-file", "If set, load root hints from this file")="";
4213 ::arg().set("max-cache-entries", "If set, maximum number of entries in the main cache")="1000000";
4214 ::arg().set("max-negative-ttl", "maximum number of seconds to keep a negative cached entry in memory")="3600";
4215 ::arg().set("max-cache-ttl", "maximum number of seconds to keep a cached entry in memory")="86400";
4216 ::arg().set("packetcache-ttl", "maximum number of seconds to keep a cached entry in packetcache")="3600";
4217 ::arg().set("max-packetcache-entries", "maximum number of entries to keep in the packetcache")="500000";
4218 ::arg().set("packetcache-servfail-ttl", "maximum number of seconds to keep a cached servfail entry in packetcache")="60";
4219 ::arg().set("server-id", "Returned when queried for 'id.server' TXT or NSID, defaults to hostname, set custom or 'disabled'")="";
4220 ::arg().set("stats-ringbuffer-entries", "maximum number of packets to store statistics for")="10000";
4221 ::arg().set("version-string", "string reported on version.pdns or version.bind")=fullVersionString();
4222 ::arg().set("allow-from", "If set, only allow these comma separated netmasks to recurse")=LOCAL_NETS;
4223 ::arg().set("allow-from-file", "If set, load allowed netmasks from this file")="";
4224 ::arg().set("entropy-source", "If set, read entropy from this file")="/dev/urandom";
4225 ::arg().set("dont-query", "If set, do not query these netmasks for DNS data")=DONT_QUERY;
4226 ::arg().set("max-tcp-per-client", "If set, maximum number of TCP sessions per client (IP address)")="0";
4227 ::arg().set("max-tcp-queries-per-connection", "If set, maximum number of TCP queries in a TCP connection")="0";
4228 ::arg().set("spoof-nearmiss-max", "If non-zero, assume spoofing after this many near misses")="20";
4229 ::arg().set("single-socket", "If set, only use a single socket for outgoing queries")="off";
4230 ::arg().set("auth-zones", "Zones for which we have authoritative data, comma separated domain=file pairs ")="";
4231 ::arg().set("lua-config-file", "More powerful configuration options")="";
4232
4233 ::arg().set("forward-zones", "Zones for which we forward queries, comma separated domain=ip pairs")="";
4234 ::arg().set("forward-zones-recurse", "Zones for which we forward queries with recursion bit, comma separated domain=ip pairs")="";
4235 ::arg().set("forward-zones-file", "File with (+)domain=ip pairs for forwarding")="";
4236 ::arg().set("export-etc-hosts", "If we should serve up contents from /etc/hosts")="off";
4237 ::arg().set("export-etc-hosts-search-suffix", "Also serve up the contents of /etc/hosts with this suffix")="";
4238 ::arg().set("etc-hosts-file", "Path to 'hosts' file")="/etc/hosts";
4239 ::arg().set("serve-rfc1918", "If we should be authoritative for RFC 1918 private IP space")="yes";
4240 ::arg().set("lua-dns-script", "Filename containing an optional 'lua' script that will be used to modify dns answers")="";
4241 ::arg().set("lua-maintenance-interval", "Number of seconds between calls to the lua user defined maintenance() function")="1";
4242 ::arg().set("latency-statistic-size","Number of latency values to calculate the qa-latency average")="10000";
4243 ::arg().setSwitch( "disable-packetcache", "Disable packetcache" )= "no";
4244 ::arg().set("ecs-ipv4-bits", "Number of bits of IPv4 address to pass for EDNS Client Subnet")="24";
4245 ::arg().set("ecs-ipv6-bits", "Number of bits of IPv6 address to pass for EDNS Client Subnet")="56";
4246 ::arg().set("edns-subnet-whitelist", "List of netmasks and domains that we should enable EDNS subnet for")="";
4247 ::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;
4248 ::arg().set("ecs-scope-zero-address", "Address to send to whitelisted authoritative servers for incoming queries with ECS prefix-length source of 0")="";
4249 ::arg().setSwitch( "use-incoming-edns-subnet", "Pass along received EDNS Client Subnet information")="no";
4250 ::arg().setSwitch( "pdns-distributes-queries", "If PowerDNS itself should distribute queries over threads")="yes";
4251 ::arg().setSwitch( "root-nx-trust", "If set, believe that an NXDOMAIN from the root means the TLD does not exist")="yes";
4252 ::arg().setSwitch( "any-to-tcp","Answer ANY queries with tc=1, shunting to TCP" )="no";
4253 ::arg().setSwitch( "lowercase-outgoing","Force outgoing questions to lowercase")="no";
4254 ::arg().setSwitch("gettag-needs-edns-options", "If EDNS Options should be extracted before calling the gettag() hook")="no";
4255 ::arg().set("udp-truncation-threshold", "Maximum UDP response size before we truncate")="1232";
4256 ::arg().set("edns-outgoing-bufsize", "Outgoing EDNS buffer size")="1232";
4257 ::arg().set("minimum-ttl-override", "Set under adverse conditions, a minimum TTL")="0";
4258 ::arg().set("max-qperq", "Maximum outgoing queries per query")="50";
4259 ::arg().set("max-total-msec", "Maximum total wall-clock time per query in milliseconds, 0 for unlimited")="7000";
4260 ::arg().set("max-recursion-depth", "Maximum number of internal recursion calls per query, 0 for unlimited")="40";
4261 ::arg().set("max-udp-queries-per-round", "Maximum number of UDP queries processed per recvmsg() round, before returning back to normal processing")="10000";
4262
4263 ::arg().set("include-dir","Include *.conf files from this directory")="";
4264 ::arg().set("security-poll-suffix","Domain name from which to query security update notifications")="secpoll.powerdns.com.";
4265
4266 ::arg().setSwitch("reuseport","Enable SO_REUSEPORT allowing multiple recursors processes to listen to 1 address")="no";
4267
4268 ::arg().setSwitch("snmp-agent", "If set, register as an SNMP agent")="no";
4269 ::arg().set("snmp-master-socket", "If set and snmp-agent is set, the socket to use to register to the SNMP master")="";
4270
4271 ::arg().set("tcp-fast-open", "Enable TCP Fast Open support on the listening sockets, using the supplied numerical value as the queue size")="0";
4272 ::arg().set("nsec3-max-iterations", "Maximum number of iterations allowed for an NSEC3 record")="2500";
4273
4274 ::arg().set("cpu-map", "Thread to CPU mapping, space separated thread-id=cpu1,cpu2..cpuN pairs")="";
4275
4276 ::arg().setSwitch("log-rpz-changes", "Log additions and removals to RPZ zones at Info level")="no";
4277
4278 ::arg().set("xpf-allow-from","XPF information is only processed from these subnets")="";
4279 ::arg().set("xpf-rr-code","XPF option code to use")="0";
4280
4281 ::arg().set("udp-source-port-min", "Minimum UDP port to bind on")="1024";
4282 ::arg().set("udp-source-port-max", "Maximum UDP port to bind on")="65535";
4283 ::arg().set("udp-source-port-avoid", "List of comma separated UDP port number to avoid")="11211";
4284 ::arg().set("rng", "Specify random number generator to use. Valid values are auto,sodium,openssl,getrandom,arc4random,urandom.")="auto";
4285 ::arg().set("public-suffix-list-file", "Path to the Public Suffix List file, if any")="";
4286 #ifdef NOD_ENABLED
4287 ::arg().set("new-domain-tracking", "Track newly observed domains (i.e. never seen before).")="no";
4288 ::arg().set("new-domain-log", "Log newly observed domains.")="yes";
4289 ::arg().set("new-domain-lookup", "Perform a DNS lookup newly observed domains as a subdomain of the configured domain")="";
4290 ::arg().set("new-domain-history-dir", "Persist new domain tracking data here to persist between restarts")=string(NODCACHEDIR)+"/nod";
4291 ::arg().set("new-domain-whitelist", "List of domains (and implicitly all subdomains) which will never be considered a new domain")="";
4292 ::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";
4293 ::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";
4294 ::arg().set("unique-response-tracking", "Track unique responses (tuple of query name, type and RR).")="no";
4295 ::arg().set("unique-response-log", "Log unique responses")="yes";
4296 ::arg().set("unique-response-history-dir", "Persist unique response tracking data here to persist between restarts")=string(NODCACHEDIR)+"/udr";
4297 ::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";
4298 ::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";
4299 #endif /* NOD_ENABLED */
4300 ::arg().setCmd("help","Provide a helpful message");
4301 ::arg().setCmd("version","Print version string");
4302 ::arg().setCmd("config","Output blank configuration");
4303 g_log.toConsole(Logger::Info);
4304 ::arg().laxParse(argc,argv); // do a lax parse
4305
4306 string configname=::arg()["config-dir"]+"/recursor.conf";
4307 if(::arg()["config-name"]!="") {
4308 configname=::arg()["config-dir"]+"/recursor-"+::arg()["config-name"]+".conf";
4309 s_programname+="-"+::arg()["config-name"];
4310 }
4311 cleanSlashes(configname);
4312
4313 if(!::arg().getCommands().empty()) {
4314 cerr<<"Fatal: non-option on the command line, perhaps a '--setting=123' statement missed the '='?"<<endl;
4315 exit(99);
4316 }
4317
4318 if(::arg().mustDo("config")) {
4319 cout<<::arg().configstring()<<endl;
4320 exit(0);
4321 }
4322
4323 if(!::arg().file(configname.c_str()))
4324 g_log<<Logger::Warning<<"Unable to parse configuration file '"<<configname<<"'"<<endl;
4325
4326 ::arg().parse(argc,argv);
4327
4328 if( !::arg()["chroot"].empty() && !::arg()["api-config-dir"].empty() ) {
4329 g_log<<Logger::Error<<"Using chroot and enabling the API is not possible"<<endl;
4330 exit(EXIT_FAILURE);
4331 }
4332
4333 if (::arg()["socket-dir"].empty()) {
4334 if (::arg()["chroot"].empty())
4335 ::arg().set("socket-dir") = LOCALSTATEDIR;
4336 else
4337 ::arg().set("socket-dir") = "/";
4338 }
4339
4340 ::arg().set("delegation-only")=toLower(::arg()["delegation-only"]);
4341
4342 if(::arg().asNum("threads")==1) {
4343 if (::arg().mustDo("pdns-distributes-queries")) {
4344 g_log<<Logger::Warning<<"Only one thread, no need to distribute queries ourselves"<<endl;
4345 ::arg().set("pdns-distributes-queries")="no";
4346 }
4347 }
4348
4349 if(::arg().mustDo("pdns-distributes-queries") && ::arg().asNum("distributor-threads") <= 0) {
4350 g_log<<Logger::Warning<<"Asked to run with pdns-distributes-queries set but no distributor threads, raising to 1"<<endl;
4351 ::arg().set("distributor-threads")="1";
4352 }
4353
4354 if (!::arg().mustDo("pdns-distributes-queries")) {
4355 ::arg().set("distributor-threads")="0";
4356 }
4357
4358 if(::arg().mustDo("help")) {
4359 cout<<"syntax:"<<endl<<endl;
4360 cout<<::arg().helpstring(::arg()["help"])<<endl;
4361 exit(0);
4362 }
4363 if(::arg().mustDo("version")) {
4364 showProductVersion();
4365 showBuildConfiguration();
4366 exit(0);
4367 }
4368
4369 Logger::Urgency logUrgency = (Logger::Urgency)::arg().asNum("loglevel");
4370
4371 if (logUrgency < Logger::Error)
4372 logUrgency = Logger::Error;
4373 if(!g_quiet && logUrgency < Logger::Info) { // Logger::Info=6, Logger::Debug=7
4374 logUrgency = Logger::Info; // if you do --quiet=no, you need Info to also see the query log
4375 }
4376 g_log.setLoglevel(logUrgency);
4377 g_log.toConsole(logUrgency);
4378
4379 serviceMain(argc, argv);
4380 }
4381 catch(PDNSException &ae) {
4382 g_log<<Logger::Error<<"Exception: "<<ae.reason<<endl;
4383 ret=EXIT_FAILURE;
4384 }
4385 catch(std::exception &e) {
4386 g_log<<Logger::Error<<"STL Exception: "<<e.what()<<endl;
4387 ret=EXIT_FAILURE;
4388 }
4389 catch(...) {
4390 g_log<<Logger::Error<<"any other exception in main: "<<endl;
4391 ret=EXIT_FAILURE;
4392 }
4393
4394 return ret;
4395 }