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