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