]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/pdns_recursor.cc
make it explicit that servfail packets get stored for servfail-packetcache-ttl seconds
[thirdparty/pdns.git] / pdns / pdns_recursor.cc
CommitLineData
288f4aa9
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
32cb6fd4 3 Copyright (C) 2003 - 2016 PowerDNS.COM BV
288f4aa9
BH
4
5 This program is free software; you can redistribute it and/or modify
3ddb9247 6 it under the terms of the GNU General Public License version 2
f28307ad 7 as published by the Free Software Foundation
288f4aa9 8
f782fe38
MH
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
12
288f4aa9
BH
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
06bd9ccf 20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
288f4aa9 21*/
caa6eefa 22
870a0fe4
AT
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
3e61e7f7 26
76473b92
KM
27#include <netdb.h>
28#include <sys/stat.h>
29#include <unistd.h>
fa8fd4d2 30
2470b36e 31#include "ws-recursor.hh"
49a699c4 32#include <pthread.h>
3ea54bf0 33#include "recpacketcache.hh"
3ddb9247 34#include "utility.hh"
51e2144e 35#include "dns_random.hh"
288f4aa9
BH
36#include <iostream>
37#include <errno.h>
81859ba5 38#include <boost/static_assert.hpp>
288f4aa9
BH
39#include <map>
40#include <set>
97bb160b 41#include "recursor_cache.hh"
38c9ceaa 42#include "cachecleaner.hh"
288f4aa9 43#include <stdio.h>
c75a6a9e 44#include <signal.h>
288f4aa9 45#include <stdlib.h>
bb4bdbaf 46#include "misc.hh"
288f4aa9
BH
47#include "mtasker.hh"
48#include <utility>
288f4aa9
BH
49#include "arguments.hh"
50#include "syncres.hh"
88def049
BH
51#include <fcntl.h>
52#include <fstream>
3e61e7f7 53#include "sortlist.hh"
54extern SortList g_sortlist;
5c633640
BH
55#include "sstuff.hh"
56#include <boost/tuple/tuple.hpp>
57#include <boost/tuple/tuple_comparison.hpp>
72df400f 58#include <boost/shared_array.hpp>
7f1fa77d 59#include <boost/function.hpp>
5605c067 60#include <boost/algorithm/string.hpp>
8f7473d7 61#ifdef MALLOC_TRACE
62#include "malloctrace.hh"
63#endif
40a3dd64 64#include <netinet/tcp.h>
ea634573
BH
65#include "dnsparser.hh"
66#include "dnswriter.hh"
67#include "dnsrecords.hh"
f814d7c8 68#include "zoneparser-tng.hh"
1d5b3ce6 69#include "rec_channel.hh"
aaacf7f2 70#include "logger.hh"
c8ddb7c2 71#include "iputils.hh"
09e6702a 72#include "mplexer.hh"
c038218b 73#include "config.h"
808c5ef7 74#include "lua-recursor4.hh"
ba1a571d 75#include "version.hh"
79332bff 76#include "responsestats.hh"
d67620e4 77#include "secpoll-recursor.hh"
c5c066bf 78#include "dnsname.hh"
644dd1da 79#include "filterpo.hh"
80#include "rpzloader.hh"
b3f0ed10 81#include "validate-recursor.hh"
f3c18728 82#include "rec-lua-conf.hh"
83
a2bfc3ff
BH
84#ifndef RECURSOR
85#include "statbag.hh"
86StatBag S;
87#endif
f3c18728 88
bb4bdbaf 89__thread FDMultiplexer* t_fdm;
674cf0f6 90__thread unsigned int t_id;
09e6702a 91unsigned int g_maxTCPPerClient;
5b0ddd18 92unsigned int g_networkTimeoutMsec;
08f3f638 93uint64_t g_latencyStatSize;
09e6702a 94bool g_logCommonErrors;
e661a20b 95bool g_anyToTcp;
b33c2462 96uint16_t g_udpTruncationThreshold, g_outgoingEDNSBufsize;
a3e7b735 97__thread shared_ptr<RecursorLua4>* t_pdl;
60c8afa8 98
99__thread addrringbuf_t* t_remotes, *t_servfailremotes, *t_largeanswerremotes;
100
c5c066bf 101__thread boost::circular_buffer<pair<DNSName, uint16_t> >* t_queryring, *t_servfailqueryring;
77499b05 102__thread shared_ptr<Regex>* t_traceRegex;
674cf0f6 103
376effcf 104NetmaskGroup g_ednssubnets;
105SuffixMatchNode g_ednsdomains;
106
d7dae798
BH
107RecursorControlChannel s_rcc; // only active in thread 0
108
109// for communicating with our threads
49a699c4
BH
110struct ThreadPipeSet
111{
112 int writeToThread;
113 int readToThread;
114 int writeFromThread;
115 int readFromThread;
116};
3ea54bf0 117
d7dae798 118vector<ThreadPipeSet> g_pipes; // effectively readonly after startup
5c633640 119
d7dae798 120SyncRes::domainmap_t* g_initialDomainMap; // new threads needs this to be setup
49a699c4
BH
121
122#include "namespaces.hh"
3ea54bf0 123
49a699c4 124__thread MemRecursorCache* t_RC;
16beeaa4 125__thread RecursorPacketCache* t_packetCache;
1d5b3ce6
BH
126RecursorStats g_stats;
127bool g_quiet;
49a699c4 128
1bc3c142
BH
129bool g_weDistributeQueries; // if true, only 1 thread listens on the incoming query sockets
130
41942bb3 131__thread NetmaskGroup* t_allowFrom;
49a699c4
BH
132static NetmaskGroup* g_initialAllowFrom; // new thread needs to be setup with this
133
eb5bae86 134NetmaskGroup* g_dontQuery;
2d733c0f 135string s_programname="pdns_recursor";
49a699c4 136
40a3dd64
BH
137typedef vector<int> tcpListenSockets_t;
138tcpListenSockets_t g_tcpListenSockets; // shared across threads, but this is fine, never written to from a thread. All threads listen on all sockets
3159c9ef 139int g_tcpTimeout;
85c32340 140unsigned int g_maxMThreads;
183eb877 141__thread struct timeval g_now; // timestamp, updated (too) frequently
84433b79 142typedef map<int, ComboAddress> listenSocketsAddresses_t; // is shared across all threads right now
143listenSocketsAddresses_t g_listenSocketsAddresses; // is shared across all threads right now
cbc03320 144set<int> g_fromtosockets; // listen sockets that use 'sendfromto()' mechanism
18af64a8 145
d7dae798
BH
146__thread MT_t* MT; // the big MTasker
147
f8f243b0 148unsigned int g_numThreads, g_numWorkerThreads;
c3828c03 149
12cd44ee 150#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"
151// Bad Nets taken from both:
3ddb9247 152// http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
12cd44ee 153// and
154// http://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
155// where such a network may not be considered a valid destination
156#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"
157#define DONT_QUERY LOCAL_NETS ", " BAD_NETS
49a699c4 158
d7dae798 159//! used to send information to a newborn mthread
ea634573 160struct DNSComboWriter {
3ddb9247 161 DNSComboWriter(const char* data, uint16_t len, const struct timeval& now) : d_mdp(data, len), d_now(now),
232f0877 162 d_tcp(false), d_socket(-1)
ea634573
BH
163 {}
164 MOADNSParser d_mdp;
00c9b8c1 165 void setRemote(const ComboAddress* sa)
ea634573 166 {
37d3f960 167 d_remote=*sa;
ea634573
BH
168 }
169
b71b60ee 170 void setLocal(const ComboAddress& sa)
171 {
172 d_local=sa;
173 }
174
175
ea634573
BH
176 void setSocket(int sock)
177 {
178 d_socket=sock;
179 }
a1754c6a
BH
180
181 string getRemote() const
182 {
37d3f960 183 return d_remote.toString();
a1754c6a
BH
184 }
185
c9e9e5e0 186 struct timeval d_now;
b71b60ee 187 ComboAddress d_remote, d_local;
ea634573
BH
188 bool d_tcp;
189 int d_socket;
49a3500d 190 int d_tag;
191 string d_query;
cd989c87 192 shared_ptr<TCPConnection> d_tcpConnection;
e8340d27 193 vector<pair<uint16_t, string> > d_ednsOpts;
ea634573
BH
194};
195
196
288f4aa9
BH
197ArgvMap &arg()
198{
199 static ArgvMap theArg;
200 return theArg;
201}
4ef015cd 202
09e6702a 203
d8f6d49f 204void handleTCPClientWritable(int fd, FDMultiplexer::funcparam_t& var);
09e6702a 205
50c81227 206// -1 is error, 0 is timeout, 1 is success
3ddb9247 207int asendtcp(const string& data, Socket* sock)
5c633640
BH
208{
209 PacketID pident;
210 pident.sock=sock;
211 pident.outMSG=data;
3ddb9247 212
bb4bdbaf 213 t_fdm->addWriteFD(sock->getHandle(), handleTCPClientWritable, pident);
50c81227 214 string packet;
5c633640 215
5b0ddd18 216 int ret=MT->waitEvent(pident, &packet, g_networkTimeoutMsec);
23db0a09 217
9170fbaf 218 if(!ret || ret==-1) { // timeout
bb4bdbaf 219 t_fdm->removeWriteFD(sock->getHandle());
5c633640 220 }
50c81227
BH
221 else if(packet.size() !=data.size()) { // main loop tells us what it sent out, or empty in case of an error
222 return -1;
223 }
9170fbaf 224 return ret;
5c633640
BH
225}
226
d8f6d49f 227void handleTCPClientReadable(int fd, FDMultiplexer::funcparam_t& var);
09e6702a 228
9170fbaf 229// -1 is error, 0 is timeout, 1 is success
825fa717 230int arecvtcp(string& data, int len, Socket* sock, bool incompleteOkay)
288f4aa9 231{
50c81227 232 data.clear();
5c633640
BH
233 PacketID pident;
234 pident.sock=sock;
235 pident.inNeeded=len;
825fa717 236 pident.inIncompleteOkay=incompleteOkay;
bb4bdbaf 237 t_fdm->addReadFD(sock->getHandle(), handleTCPClientReadable, pident);
5c633640 238
bb4bdbaf 239 int ret=MT->waitEvent(pident,&data, g_networkTimeoutMsec);
9170fbaf 240 if(!ret || ret==-1) { // timeout
bb4bdbaf 241 t_fdm->removeReadFD(sock->getHandle());
288f4aa9 242 }
50c81227
BH
243 else if(data.empty()) {// error, EOF or other
244 return -1;
245 }
246
9170fbaf 247 return ret;
288f4aa9
BH
248}
249
fba1e944 250void handleGenUDPQueryResponse(int fd, FDMultiplexer::funcparam_t& var)
4465e941 251{
fba1e944 252 PacketID pident=*any_cast<PacketID>(&var);
4465e941 253 char resp[512];
254 int ret=recv(fd, resp, sizeof(resp), 0);
255 t_fdm->removeReadFD(fd);
256 if(ret >= 0) {
257 string data(resp, ret);
fba1e944 258 MT->sendEvent(pident, &data);
4465e941 259 }
260 else {
fba1e944 261 string empty;
262 MT->sendEvent(pident, &empty);
263 // cerr<<"Had some kind of error: "<<ret<<", "<<strerror(errno)<<endl;
4465e941 264 }
265}
fba1e944 266string GenUDPQueryResponse(const ComboAddress& dest, const string& query)
4465e941 267{
4465e941 268 Socket s(dest.sin4.sin_family, SOCK_DGRAM);
269 s.setNonBlocking();
270 ComboAddress local = getQueryLocalAddress(dest.sin4.sin_family, 0);
271
272 s.bind(local);
273 s.connect(dest);
4465e941 274 s.send(query);
275
276 PacketID pident;
277 pident.sock=&s;
278 pident.type=0;
fba1e944 279 t_fdm->addReadFD(s.getHandle(), handleGenUDPQueryResponse, pident);
4465e941 280
281 string data;
fba1e944 282
4465e941 283 int ret=MT->waitEvent(pident,&data, g_networkTimeoutMsec);
fba1e944 284
4465e941 285 if(!ret || ret==-1) { // timeout
4465e941 286 t_fdm->removeReadFD(s.getHandle());
287 }
288 else if(data.empty()) {// error, EOF or other
fba1e944 289 // we could special case this
4465e941 290 return data;
291 }
4465e941 292 return data;
293}
294
295
3ddb9247 296vector<ComboAddress> g_localQueryAddresses4, g_localQueryAddresses6;
046c5a5d 297const ComboAddress g_local4("0.0.0.0"), g_local6("::");
1652a63e 298
d7dae798 299//! pick a random query local address
1652a63e 300ComboAddress getQueryLocalAddress(int family, uint16_t port)
5a38281c 301{
1652a63e 302 ComboAddress ret;
5a38281c 303 if(family==AF_INET) {
3ddb9247 304 if(g_localQueryAddresses4.empty())
1652a63e 305 ret = g_local4;
3ddb9247 306 else
1652a63e
BH
307 ret = g_localQueryAddresses4[dns_random(g_localQueryAddresses4.size())];
308 ret.sin4.sin_port = htons(port);
5a38281c
BH
309 }
310 else {
311 if(g_localQueryAddresses6.empty())
1652a63e
BH
312 ret = g_local6;
313 else
314 ret = g_localQueryAddresses6[dns_random(g_localQueryAddresses6.size())];
3ddb9247 315
1652a63e 316 ret.sin6.sin6_port = htons(port);
5a38281c 317 }
1652a63e 318 return ret;
5a38281c 319}
4ef015cd 320
d8f6d49f 321void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t&);
09e6702a 322
d7dae798
BH
323void setSocketBuffer(int fd, int optname, uint32_t size)
324{
325 uint32_t psize=0;
326 socklen_t len=sizeof(psize);
3ddb9247 327
d7dae798
BH
328 if(!getsockopt(fd, SOL_SOCKET, optname, (char*)&psize, &len) && psize > size) {
329 L<<Logger::Error<<"Not decreasing socket buffer size from "<<psize<<" to "<<size<<endl;
3ddb9247 330 return;
d7dae798
BH
331 }
332
333 if (setsockopt(fd, SOL_SOCKET, optname, (char*)&size, sizeof(size)) < 0 )
c057bfaa 334 L<<Logger::Error<<"Unable to raise socket buffer size to "<<size<<": "<<strerror(errno)<<endl;
d7dae798
BH
335}
336
337
338static void setSocketReceiveBuffer(int fd, uint32_t size)
339{
340 setSocketBuffer(fd, SO_RCVBUF, size);
341}
342
343static void setSocketSendBuffer(int fd, uint32_t size)
344{
345 setSocketBuffer(fd, SO_SNDBUF, size);
346}
347
348
4ef015cd
BH
349// you can ask this class for a UDP socket to send a query from
350// this socket is not yours, don't even think about deleting it
351// but after you call 'returnSocket' on it, don't assume anything anymore
352class UDPClientSocks
353{
4ef015cd 354 unsigned int d_numsocks;
4ef015cd 355public:
e2642526 356 UDPClientSocks() : d_numsocks(0)
4ef015cd
BH
357 {
358 }
359
996c89cc 360 typedef set<int> socks_t;
4ef015cd
BH
361 socks_t d_socks;
362
2ee280cf 363 // returning -2 means: temporary OS error (ie, out of files), -1 means error related to remote
d8f6d49f 364 int getSocket(const ComboAddress& toaddr, int* fd)
4ef015cd 365 {
d8f6d49f
BH
366 *fd=makeClientSocket(toaddr.sin4.sin_family);
367 if(*fd < 0) // temporary error - receive exception otherwise
2ee280cf 368 return -2;
d8f6d49f
BH
369
370 if(connect(*fd, (struct sockaddr*)(&toaddr), toaddr.getSocklen()) < 0) {
371 int err = errno;
41ff43f8 372 // returnSocket(*fd);
3897b9e1 373 closesocket(*fd);
d8f6d49f 374 if(err==ENETUNREACH) // Seth "My Interfaces Are Like A Yo Yo" Arnold special
4957a608 375 return -2;
998a4334 376 return -1;
d8f6d49f 377 }
998a4334 378
d8f6d49f 379 d_socks.insert(*fd);
998a4334 380 d_numsocks++;
d8f6d49f 381 return 0;
4ef015cd
BH
382 }
383
095c3045
BH
384 void returnSocket(int fd)
385 {
386 socks_t::iterator i=d_socks.find(fd);
34801ab1 387 if(i==d_socks.end()) {
335da0ba 388 throw PDNSException("Trying to return a socket (fd="+std::to_string(fd)+") not in the pool");
34801ab1 389 }
bb4bdbaf 390 returnSocketLocked(i);
095c3045
BH
391 }
392
4ef015cd 393 // return a socket to the pool, or simply erase it
bb4bdbaf 394 void returnSocketLocked(socks_t::iterator& i)
4ef015cd 395 {
600fc20b 396 if(i==d_socks.end()) {
3f81d239 397 throw PDNSException("Trying to return a socket not in the pool");
600fc20b 398 }
80baf329 399 try {
bb4bdbaf 400 t_fdm->removeReadFD(*i);
80baf329
BH
401 }
402 catch(FDMultiplexerException& e) {
bb4bdbaf 403 // we sometimes return a socket that has not yet been assigned to t_fdm
80baf329 404 }
3897b9e1 405 closesocket(*i);
3ddb9247 406
998a4334
BH
407 d_socks.erase(i++);
408 --d_numsocks;
4ef015cd 409 }
d8f6d49f
BH
410
411 // returns -1 for errors which might go away, throws for ones that won't
bb4bdbaf 412 static int makeClientSocket(int family)
d8f6d49f 413 {
a903b39c 414 int ret=(int)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 415
d8f6d49f
BH
416 if(ret < 0 && errno==EMFILE) // this is not a catastrophic error
417 return ret;
3ddb9247
PD
418
419 if(ret<0)
335da0ba 420 throw PDNSException("Making a socket for resolver (family = "+std::to_string(family)+"): "+stringerror());
36855b53 421
7eb73ffa 422 // setCloseOnExec(ret); // we're not going to exec
5a38281c 423
d8f6d49f 424 int tries=10;
3aa91c3e 425 ComboAddress sin;
d8f6d49f 426 while(--tries) {
1652a63e 427 uint16_t port;
3ddb9247 428
d8f6d49f 429 if(tries==1) // fall back to kernel 'random'
4957a608 430 port = 0;
1652a63e
BH
431 else
432 port = 1025 + dns_random(64510);
5a38281c 433
3aa91c3e 434 sin=getQueryLocalAddress(family, port); // does htons for us
5a38281c 435
3ddb9247 436 if (::bind(ret, (struct sockaddr *)&sin, sin.getSocklen()) >= 0)
4957a608 437 break;
d8f6d49f
BH
438 }
439 if(!tries)
3aa91c3e 440 throw PDNSException("Resolver binding to local query client socket on "+sin.toString()+": "+stringerror());
3ddb9247 441
3897b9e1 442 setNonBlocking(ret);
d8f6d49f
BH
443 return ret;
444 }
49a699c4
BH
445};
446
447static __thread UDPClientSocks* t_udpclientsocks;
4ef015cd 448
288f4aa9 449/* these two functions are used by LWRes */
34801ab1 450// -2 is OS error, -1 is error that depends on the remote, > 0 is success
3ddb9247
PD
451int asendto(const char *data, int len, int flags,
452 const ComboAddress& toaddr, uint16_t id, const DNSName& domain, uint16_t qtype, int* fd)
288f4aa9 453{
34801ab1
BH
454
455 PacketID pident;
787e5eab
BH
456 pident.domain = domain;
457 pident.remote = toaddr;
458 pident.type = qtype;
34801ab1
BH
459
460 // see if there is an existing outstanding request we can chain on to, using partial equivalence function
461 pair<MT_t::waiters_t::iterator, MT_t::waiters_t::iterator> chain=MT->d_waiters.equal_range(pident, PacketIDBirthdayCompare());
462
463 for(; chain.first != chain.second; chain.first++) {
464 if(chain.first->key.fd > -1) { // don't chain onto existing chained waiter!
e27e91a8 465 /*
4665c31e
BH
466 cerr<<"Orig: "<<pident.domain<<", "<<pident.remote.toString()<<", id="<<id<<endl;
467 cerr<<"Had hit: "<< chain.first->key.domain<<", "<<chain.first->key.remote.toString()<<", id="<<chain.first->key.id
4957a608 468 <<", count="<<chain.first->key.chain.size()<<", origfd: "<<chain.first->key.fd<<endl;
e27e91a8 469 */
34801ab1
BH
470 chain.first->key.chain.insert(id); // we can chain
471 *fd=-1; // gets used in waitEvent / sendEvent later on
472 return 1;
473 }
474 }
475
49a699c4 476 int ret=t_udpclientsocks->getSocket(toaddr, fd);
d8f6d49f
BH
477 if(ret < 0)
478 return ret;
34801ab1 479
998a4334
BH
480 pident.fd=*fd;
481 pident.id=id;
3ddb9247 482
bb4bdbaf
BH
483 t_fdm->addReadFD(*fd, handleUDPServerResponse, pident);
484 ret = send(*fd, data, len, 0);
485
5b0ddd18 486 int tmp = errno;
bb4bdbaf 487
7302ed0a 488 if(ret < 0)
49a699c4 489 t_udpclientsocks->returnSocket(*fd);
bb4bdbaf 490
5b0ddd18 491 errno = tmp; // this is for logging purposes only
7302ed0a 492 return ret;
288f4aa9
BH
493}
494
9170fbaf 495// -1 is error, 0 is timeout, 1 is success
3ddb9247 496int arecvfrom(char *data, int len, int flags, const ComboAddress& fromaddr, int *d_len,
c5c066bf 497 uint16_t id, const DNSName& domain, uint16_t qtype, int fd, struct timeval* now)
288f4aa9 498{
0d5f0a9f 499 static optional<unsigned int> nearMissLimit;
3ddb9247 500 if(!nearMissLimit)
0d5f0a9f
BH
501 nearMissLimit=::arg().asNum("spoof-nearmiss-max");
502
288f4aa9 503 PacketID pident;
4ef015cd 504 pident.fd=fd;
288f4aa9 505 pident.id=id;
0d5f0a9f 506 pident.domain=domain;
787e5eab 507 pident.type = qtype;
996c89cc 508 pident.remote=fromaddr;
b636533b 509
288f4aa9 510 string packet;
5b0ddd18 511 int ret=MT->waitEvent(pident, &packet, g_networkTimeoutMsec, now);
34801ab1 512
9170fbaf 513 if(ret > 0) {
996c89cc 514 if(packet.empty()) // means "error"
3ddb9247 515 return -1;
998a4334 516
705f31ae 517 *d_len=(int)packet.size();
9170fbaf 518 memcpy(data,packet.c_str(),min(len,*d_len));
0d5f0a9f 519 if(*nearMissLimit && pident.nearMisses > *nearMissLimit) {
996c89cc 520 L<<Logger::Error<<"Too many ("<<pident.nearMisses<<" > "<<*nearMissLimit<<") bogus answers for '"<<domain<<"' from "<<fromaddr.toString()<<", assuming spoof attempt."<<endl;
0d5f0a9f 521 g_stats.spoofCount++;
35ce8576
BH
522 return -1;
523 }
288f4aa9 524 }
09e6702a 525 else {
34801ab1 526 if(fd >= 0)
49a699c4 527 t_udpclientsocks->returnSocket(fd);
09e6702a 528 }
9170fbaf 529 return ret;
288f4aa9
BH
530}
531
aa4e4cbf 532
87a5ea63 533string s_pidfname;
88def049
BH
534static void writePid(void)
535{
191f2e47 536 if(!::arg().mustDo("write-pid"))
537 return;
18e7758c 538 ofstream of(s_pidfname.c_str(), std::ios_base::app);
88def049 539 if(of)
705f31ae 540 of<< Utility::getpid() <<endl;
88def049 541 else
c057bfaa 542 L<<Logger::Error<<"Writing pid for "<<Utility::getpid()<<" to "<<s_pidfname<<" failed: "<<strerror(errno)<<endl;
88def049
BH
543}
544
bd0289fc
BH
545typedef map<ComboAddress, uint32_t, ComboAddress::addressOnlyLessThan> tcpClientCounts_t;
546tcpClientCounts_t __thread* t_tcpClientCounts;
0e9d9ce2 547
cd989c87 548TCPConnection::TCPConnection(int fd, const ComboAddress& addr) : d_remote(addr), d_fd(fd)
3ddb9247
PD
549{
550 ++s_currentConnections;
cd989c87 551 (*t_tcpClientCounts)[d_remote]++;
0e408828 552}
cd989c87
BH
553
554TCPConnection::~TCPConnection()
0e408828 555{
3ddb9247 556 if(closesocket(d_fd) < 0)
cd989c87 557 unixDie("closing socket for TCPConnection");
3ddb9247 558 if(t_tcpClientCounts->count(d_remote) && !(*t_tcpClientCounts)[d_remote]--)
cd989c87 559 t_tcpClientCounts->erase(d_remote);
1bc9e6bd 560 --s_currentConnections;
0e408828 561}
0e9d9ce2 562
3ddb9247 563AtomicCounter TCPConnection::s_currentConnections;
d8f6d49f 564void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var);
6dcd28c3 565
92011b8f 566// the idea is, only do things that depend on the *response* here. Incoming accounting is on incoming.
c5c066bf 567void updateResponseStats(int res, const ComboAddress& remote, unsigned int packetsize, const DNSName* query, uint16_t qtype)
2cc13433 568{
92011b8f 569 if(packetsize > 1000 && t_largeanswerremotes)
570 t_largeanswerremotes->push_back(remote);
2cc13433
BH
571 switch(res) {
572 case RCode::ServFail:
92011b8f 573 if(t_servfailremotes) {
574 t_servfailremotes->push_back(remote);
575 if(query) // packet cache
576 t_servfailqueryring->push_back(make_pair(*query, qtype));
577 }
2cc13433
BH
578 g_stats.servFails++;
579 break;
580 case RCode::NXDomain:
581 g_stats.nxDomains++;
582 break;
583 case RCode::NoError:
584 g_stats.noErrors++;
585 break;
586 }
587}
588
a903b39c 589static string makeLoginfo(DNSComboWriter* dc)
590try
591{
c5c066bf 592 return "("+dc->d_mdp.d_qname.toString()+"/"+DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)+" from "+(dc->d_remote.toString())+")";
a903b39c 593}
594catch(...)
595{
596 return "Exception making error message for exception";
597}
598
288f4aa9
BH
599void startDoResolve(void *p)
600{
7b1469bb 601 DNSComboWriter* dc=(DNSComboWriter *)p;
288f4aa9 602 try {
92011b8f 603 t_queryring->push_back(make_pair(dc->d_mdp.d_qname, dc->d_mdp.d_qtype));
604
b18ace73 605 uint32_t maxanswersize= dc->d_tcp ? 65535 : min((uint16_t) 512, g_udpTruncationThreshold);
7f7b8d55 606 EDNSOpts edo;
8e079f3a 607 bool haveEDNS=false;
608 if(getEDNSOpts(dc->d_mdp, &edo)) {
609 if(!dc->d_tcp)
610 maxanswersize = min(edo.d_packetsize, g_udpTruncationThreshold);
e8340d27 611 dc->d_ednsOpts = edo.d_options;
8e079f3a 612 haveEDNS=true;
10321a98 613 }
e325f20c 614 vector<DNSRecord> ret;
ea634573 615 vector<uint8_t> packet;
b23b8614 616
ad42489c 617 auto luaconfsLocal = g_luaconfs.getLocal();
618
3ddb9247 619 DNSPacketWriter pw(packet, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass);
ea634573
BH
620
621 pw.getHeader()->aa=0;
622 pw.getHeader()->ra=1;
c154c8a4 623 pw.getHeader()->qr=1;
bb4bdbaf 624 pw.getHeader()->tc=0;
ea634573 625 pw.getHeader()->id=dc->d_mdp.d_header.id;
10321a98 626 pw.getHeader()->rd=dc->d_mdp.d_header.rd;
57769f13 627 pw.getHeader()->cd=dc->d_mdp.d_header.cd;
ea634573 628
904d3219
PD
629 uint32_t minTTL=std::numeric_limits<uint32_t>::max();
630
631 SyncRes sr(dc->d_now);
3457a2a0 632 if(t_pdl) {
633 sr.setLuaEngine(*t_pdl);
4ea94941 634 sr.d_requestor=dc->d_remote;
3457a2a0 635 }
57769f13 636
5b9853c9 637 if(pw.getHeader()->cd || edo.d_Z & EDNSOpts::DNSSECOK) {
638 g_stats.dnssecQueries++;
57769f13 639 sr.d_doDNSSEC=true;
5b9853c9 640 }
57769f13 641
904d3219
PD
642 bool tracedQuery=false; // we could consider letting Lua know about this too
643 bool variableAnswer = false;
644
56b4d21b 645 int res;
39ec5d29 646 DNSFilterEngine::Policy dfepol;
647 DNSRecord spoofed;
e661a20b 648 if(dc->d_mdp.d_qtype==QType::ANY && !dc->d_tcp && g_anyToTcp) {
56b4d21b
PD
649 pw.getHeader()->tc = 1;
650 res = 0;
651 variableAnswer = true;
e661a20b
PD
652 goto sendit;
653 }
654
c5c066bf 655 if(t_traceRegex->get() && (*t_traceRegex)->match(dc->d_mdp.d_qname.toString())) {
77499b05
BH
656 sr.setLogMode(SyncRes::Store);
657 tracedQuery=true;
658 }
3ddb9247 659
8f7473d7 660
77499b05 661 if(!g_quiet || tracedQuery)
461df9d2 662 L<<Logger::Warning<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] " << (dc->d_tcp ? "TCP " : "") << "question for '"<<dc->d_mdp.d_qname<<"|"
8a63d3ce 663 <<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)<<"' from "<<dc->getRemote()<<endl;
c75a6a9e 664
fededf47 665 sr.setId(MT->getTid());
67828389 666 if(!dc->d_mdp.d_header.rd)
c836dc19
BH
667 sr.setCacheOnly();
668
84433b79 669
3ddb9247 670 // if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve
e325f20c 671
ad42489c 672 dfepol = luaconfsLocal->dfe.getQueryPolicy(dc->d_mdp.d_qname, dc->d_remote);
39ec5d29 673
674 switch(dfepol.d_kind) {
675 case DNSFilterEngine::PolicyKind::NoAction:
644dd1da 676 break;
39ec5d29 677 case DNSFilterEngine::PolicyKind::Drop:
644dd1da 678 g_stats.policyDrops++;
679 delete dc;
680 dc=0;
681 return;
39ec5d29 682 case DNSFilterEngine::PolicyKind::NXDOMAIN:
644dd1da 683 res=RCode::NXDomain;
684 goto haveAnswer;
685
39ec5d29 686 case DNSFilterEngine::PolicyKind::NODATA:
687 res=RCode::NoError;
688 goto haveAnswer;
689
690 case DNSFilterEngine::PolicyKind::Custom:
644dd1da 691 res=RCode::NoError;
39ec5d29 692 spoofed.d_name=dc->d_mdp.d_qname;
5a1f298f 693 spoofed.d_type=dfepol.d_custom->getType();
3876ee44 694 spoofed.d_ttl = dfepol.d_ttl;
39ec5d29 695 spoofed.d_class = 1;
696 spoofed.d_content = dfepol.d_custom;
589ad24b 697 spoofed.d_place = DNSResourceRecord::ANSWER;
39ec5d29 698 ret.push_back(spoofed);
644dd1da 699 goto haveAnswer;
700
39ec5d29 701
702 case DNSFilterEngine::PolicyKind::Truncate:
644dd1da 703 if(!dc->d_tcp) {
704 res=RCode::NoError;
705 pw.getHeader()->tc=1;
706 goto haveAnswer;
707 }
708 break;
709 }
710
808c5ef7 711
e8340d27 712 if(!t_pdl->get() || !(*t_pdl)->preresolve(dc->d_remote, dc->d_local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, dc->d_ednsOpts.empty() ? 0 : &dc->d_ednsOpts, res, &variableAnswer)) {
44971ca0
PD
713 try {
714 res = sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret);
715 }
716 catch(ImmediateServFailException &e) {
854d44e3 717 if(g_logCommonErrors)
718 L<<Logger::Notice<<"Sending SERVFAIL to "<<dc->getRemote()<<" during resolve of '"<<dc->d_mdp.d_qname<<"' because: "<<e.reason<<endl;
44971ca0
PD
719 res = RCode::ServFail;
720 }
4485aa35 721
ad42489c 722 dfepol = luaconfsLocal->dfe.getPostPolicy(ret);
39ec5d29 723 switch(dfepol.d_kind) {
724 case DNSFilterEngine::PolicyKind::NoAction:
644dd1da 725 break;
39ec5d29 726 case DNSFilterEngine::PolicyKind::Drop:
644dd1da 727 g_stats.policyDrops++;
728 delete dc;
729 dc=0;
730 return;
39ec5d29 731 case DNSFilterEngine::PolicyKind::NXDOMAIN:
644dd1da 732 ret.clear();
733 res=RCode::NXDomain;
734 goto haveAnswer;
735
39ec5d29 736 case DNSFilterEngine::PolicyKind::NODATA:
644dd1da 737 ret.clear();
738 res=RCode::NoError;
739 goto haveAnswer;
740
39ec5d29 741 case DNSFilterEngine::PolicyKind::Truncate:
644dd1da 742 if(!dc->d_tcp) {
743 ret.clear();
744 res=RCode::NoError;
745 pw.getHeader()->tc=1;
746 goto haveAnswer;
747 }
748 break;
39ec5d29 749
750 case DNSFilterEngine::PolicyKind::Custom:
ad42489c 751 ret.clear();
39ec5d29 752 res=RCode::NoError;
753 spoofed.d_name=dc->d_mdp.d_qname;
5a1f298f 754 spoofed.d_type=dfepol.d_custom->getType();
3876ee44 755 spoofed.d_ttl = dfepol.d_ttl;
39ec5d29 756 spoofed.d_class = 1;
757 spoofed.d_content = dfepol.d_custom;
589ad24b 758 spoofed.d_place = DNSResourceRecord::ANSWER;
39ec5d29 759 ret.push_back(spoofed);
760 goto haveAnswer;
644dd1da 761 }
a3e7b735 762
674cf0f6 763 if(t_pdl->get()) {
bd53ea9d 764 if(res == RCode::NoError) {
e325f20c 765 auto i=ret.cbegin();
766 for(; i!= ret.cend(); ++i)
e693ff5a 767 if(i->d_type == dc->d_mdp.d_qtype && i->d_place == DNSResourceRecord::ANSWER)
232f0877 768 break;
e325f20c 769 if(i == ret.cend())
a6147cd2 770 (*t_pdl)->nodata(dc->d_remote, dc->d_local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
a3e7b735 771 }
772 else if(res == RCode::NXDomain)
a6147cd2 773 (*t_pdl)->nxdomain(dc->d_remote, dc->d_local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
644dd1da 774
a3e7b735 775
a6147cd2 776 (*t_pdl)->postresolve(dc->d_remote, dc->d_local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
93f0da94 777
d2322a5e 778 }
4485aa35 779 }
644dd1da 780 haveAnswer:;
3e8216c8 781 if(res == PolicyDecision::DROP) {
e9c2ad3a 782 g_stats.policyDrops++;
ae7e77ad 783 delete dc;
784 dc=0;
785 return;
3ddb9247 786 }
3e8216c8 787 if(tracedQuery || res == PolicyDecision::PASS || res == RCode::ServFail || pw.getHeader()->rcode == RCode::ServFail)
1dc8f4d0 788 {
85ffbc53
PD
789 string trace(sr.getTrace());
790 if(!trace.empty()) {
791 vector<string> lines;
792 boost::split(lines, trace, boost::is_any_of("\n"));
1dc8f4d0 793 for(const string& line : lines) {
85ffbc53
PD
794 if(!line.empty())
795 L<<Logger::Warning<< line << endl;
796 }
797 }
798 }
3ddb9247 799
b3f0ed10 800 if(res == PolicyDecision::PASS) { // XXX what does this MEAN? Why servfail on PASS?
0fe1d080
PD
801 pw.getHeader()->rcode=RCode::ServFail;
802 // no commit here, because no record
803 g_stats.servFails++;
804 }
288f4aa9 805 else {
ea634573 806 pw.getHeader()->rcode=res;
92011b8f 807
8e079f3a 808 if(haveEDNS) {
12ce523e 809 if(g_dnssecmode != DNSSECMode::Off && ((edo.d_Z & EDNSOpts::DNSSECOK) || g_dnssecmode == DNSSECMode::ValidateAll || g_dnssecmode==DNSSECMode::ValidateForLog)) {
8e079f3a 810 auto state=validateRecords(ret);
811 if(state == Secure) {
812 pw.getHeader()->ad=1;
813 }
814 else if(state == Insecure) {
815 pw.getHeader()->ad=0;
816 }
817 else if(state == Bogus && !pw.getHeader()->cd) {
12ce523e 818 if(g_dnssecmode == DNSSECMode::ValidateAll || (edo.d_Z & EDNSOpts::DNSSECOK)) {
819 pw.getHeader()->rcode=RCode::ServFail;
820 goto sendit;
821 }
822 else {
823 L<<Logger::Warning<<"Failed to validate "<<dc->d_mdp.d_qname<<" for "<<dc->d_remote.toStringWithPort()<<endl;
824 }
8e079f3a 825 }
b3f0ed10 826 }
827 }
828
8e079f3a 829
830
c154c8a4 831 if(ret.size()) {
92476c8b 832 orderAndShuffle(ret);
ad42489c 833 if(auto sl = luaconfsLocal->sortlist.getOrderCmp(dc->d_remote)) {
3e61e7f7 834 sort(ret.begin(), ret.end(), *sl);
835 variableAnswer=true;
836 }
8e079f3a 837 }
838 if(haveEDNS) {
839 ret.push_back(makeOpt(edo.d_packetsize, 0, edo.d_Z));
840 }
841
842 for(auto i=ret.cbegin(); i!=ret.cend(); ++i) {
843 pw.startRecord(i->d_name, i->d_type, i->d_ttl, i->d_class, i->d_place);
844 if(i->d_type != QType::OPT) // their TTL ain't real
845 minTTL = min(minTTL, i->d_ttl);
846 i->d_content->toPacket(pw);
847 if(pw.size() > maxanswersize) {
848 pw.rollback();
849 if(i->d_place==DNSResourceRecord::ANSWER) // only truncate if we actually omitted parts of the answer
add935a2 850 {
4957a608 851 pw.getHeader()->tc=1;
add935a2
PD
852 pw.truncate();
853 }
8e079f3a 854 goto sendit; // need to jump over pw.commit
855 }
ea634573 856 }
8e079f3a 857 if(ret.size())
858 pw.commit();
288f4aa9 859 }
10321a98 860 sendit:;
b3f0ed10 861
79332bff 862 g_rs.submitResponse(dc->d_mdp.d_qtype, packet.size(), !dc->d_tcp);
92011b8f 863 updateResponseStats(res, dc->d_remote, packet.size(), &dc->d_mdp.d_qname, dc->d_mdp.d_qtype);
ea634573 864 if(!dc->d_tcp) {
b71b60ee 865 struct msghdr msgh;
866 struct iovec iov;
867 char cbuf[256];
868 fillMSGHdr(&msgh, &iov, cbuf, 0, (char*)&*packet.begin(), packet.size(), &dc->d_remote);
cbc03320 869 if(g_fromtosockets.count(dc->d_socket)) {
fbe2a2e0 870 addCMsgSrcAddr(&msgh, cbuf, &dc->d_local, 0);
cbc03320 871 } else
579cae19 872 msgh.msg_control=NULL;
cbc03320 873 if(sendmsg(dc->d_socket, &msgh, 0) < 0 && g_logCommonErrors)
874 L<<Logger::Warning<<"Sending UDP reply to client "<<dc->d_remote.toStringWithPort()<<" failed with: "<<strerror(errno)<<endl;
3762e821 875 if(!SyncRes::s_nopacketcache && !variableAnswer && !sr.wasVariable() ) {
76e2b9e3 876
877 t_packetCache->insertResponsePacket(dc->d_tag, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_query,
878 string((const char*)&*packet.begin(), packet.size()),
3ddb9247 879 g_now.tv_sec,
76e2b9e3 880 pw.getHeader()->rcode == RCode::ServFail ? SyncRes::s_packetcacheservfailttl :
881 min(minTTL,SyncRes::s_packetcachettl));
1051f8a9 882 }
3762e821 883 // else cerr<<"Not putting in packet cache: "<<sr.wasVariable()<<endl;
feccc9fc 884 }
9c495589
BH
885 else {
886 char buf[2];
ea634573
BH
887 buf[0]=packet.size()/256;
888 buf[1]=packet.size()%256;
feccc9fc 889
c038218b 890 Utility::iovec iov[2];
feccc9fc 891
ea634573
BH
892 iov[0].iov_base=(void*)buf; iov[0].iov_len=2;
893 iov[1].iov_base=(void*)&*packet.begin(); iov[1].iov_len = packet.size();
feccc9fc 894
c038218b 895 int ret=Utility::writev(dc->d_socket, iov, 2);
0e9d9ce2 896 bool hadError=true;
feccc9fc 897
3ddb9247 898 if(ret == 0)
18af64a8 899 L<<Logger::Error<<"EOF writing TCP answer to "<<dc->getRemote()<<endl;
3ddb9247 900 else if(ret < 0 )
18af64a8 901 L<<Logger::Error<<"Error writing TCP answer to "<<dc->getRemote()<<": "<< strerror(errno) <<endl;
ea634573 902 else if((unsigned int)ret != 2 + packet.size())
18af64a8 903 L<<Logger::Error<<"Oops, partial answer sent to "<<dc->getRemote()<<" for "<<dc->d_mdp.d_qname<<" (size="<< (2 + packet.size()) <<", sent "<<ret<<")"<<endl;
0e9d9ce2 904 else
18af64a8 905 hadError=false;
3ddb9247 906
09e6702a 907 // update tcp connection status, either by closing or moving to 'BYTE0'
3ddb9247 908
09e6702a 909 if(hadError) {
18af64a8 910 // no need to remove us from FDM, we weren't there
c36bc97a 911 dc->d_socket = -1;
09e6702a 912 }
a6ae6414 913 else {
cd989c87 914 dc->d_tcpConnection->state=TCPConnection::BYTE0;
18af64a8 915 Utility::gettimeofday(&g_now, 0); // needs to be updated
cd989c87
BH
916 t_fdm->addReadFD(dc->d_socket, handleRunningTCPQuestion, dc->d_tcpConnection);
917 t_fdm->setReadTTD(dc->d_socket, g_now, g_tcpTimeout);
0e9d9ce2 918 }
9c495589 919 }
3ddb9247 920
1d5b3ce6 921 if(!g_quiet) {
461df9d2 922 L<<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);
ea634573 923 L<<"': "<<ntohs(pw.getHeader()->ancount)<<" answers, "<<ntohs(pw.getHeader()->arcount)<<" additional, took "<<sr.d_outqueries<<" packets, "<<
9de3e034 924 sr.d_totUsec/1000.0<<" ms, "<<
925 sr.d_throttledqueries<<" throttled, "<<sr.d_timeouts<<" timeouts, "<<sr.d_tcpoutqueries<<" tcp connections, rcode="<<res<<endl;
c75a6a9e 926 }
b23b8614 927
3ddb9247 928 sr.d_outqueries ? t_RC->cacheMisses++ : t_RC->cacheHits++;
fe213470
BH
929 float spent=makeFloat(sr.d_now-dc->d_now);
930 if(spent < 0.001)
931 g_stats.answers0_1++;
932 else if(spent < 0.010)
933 g_stats.answers1_10++;
934 else if(spent < 0.1)
935 g_stats.answers10_100++;
936 else if(spent < 1.0)
937 g_stats.answers100_1000++;
938 else
939 g_stats.answersSlow++;
940
574af7ea 941 uint64_t newLat=(uint64_t)(spent*1000000);
b841314c 942 newLat = min(newLat,(uint64_t)(((uint64_t) g_networkTimeoutMsec)*1000)); // outliers of several minutes exist..
08f3f638 943 g_stats.avgLatencyUsec=(1-1.0/g_latencyStatSize)*g_stats.avgLatencyUsec + (float)newLat/g_latencyStatSize;
0a6b1027 944 // no worries, we do this for packet cache hits elsewhere
c6d04bdc 945 // cout<<dc->d_mdp.d_qname<<"\t"<<MT->getUsec()<<"\t"<<sr.d_outqueries<<endl;
ea634573 946 delete dc;
c36bc97a 947 dc=0;
288f4aa9 948 }
3f81d239 949 catch(PDNSException &ae) {
a903b39c 950 L<<Logger::Error<<"startDoResolve problem "<<makeLoginfo(dc)<<": "<<ae.reason<<endl;
c36bc97a 951 delete dc;
288f4aa9 952 }
7b1469bb 953 catch(MOADNSException& e) {
a903b39c 954 L<<Logger::Error<<"DNS parser error "<<makeLoginfo(dc) <<": "<<dc->d_mdp.d_qname<<", "<<e.what()<<endl;
c36bc97a 955 delete dc;
7b1469bb 956 }
fdbf35ac 957 catch(std::exception& e) {
a903b39c 958 L<<Logger::Error<<"STL error "<< makeLoginfo(dc)<<": "<<e.what()<<endl;
c36bc97a 959 delete dc;
c154c8a4 960 }
288f4aa9 961 catch(...) {
a903b39c 962 L<<Logger::Error<<"Any other exception in a resolver context "<< makeLoginfo(dc) <<endl;
288f4aa9 963 }
3ddb9247 964
ec6eacbc 965 g_stats.maxMThreadStackUsage = max(MT->getMaxStackUsage(), g_stats.maxMThreadStackUsage);
288f4aa9
BH
966}
967
677e2a46 968void makeControlChannelSocket(int processNum=-1)
1d5b3ce6 969{
2d733c0f 970 string sockname=::arg()["socket-dir"]+"/"+s_programname;
677e2a46 971 if(processNum >= 0)
335da0ba 972 sockname += "."+std::to_string(processNum);
677e2a46 973 sockname+=".controlsocket";
41f7a068 974 s_rcc.listen(sockname);
3ddb9247 975
387de317
BH
976 int sockowner = -1;
977 int sockgroup = -1;
978
979 if (!::arg().isEmpty("socket-group"))
980 sockgroup=::arg().asGid("socket-group");
981 if (!::arg().isEmpty("socket-owner"))
982 sockowner=::arg().asUid("socket-owner");
3ddb9247 983
f838ad8d
BH
984 if (sockgroup > -1 || sockowner > -1) {
985 if(chown(sockname.c_str(), sockowner, sockgroup) < 0) {
986 unixDie("Failed to chown control socket");
987 }
988 }
387de317
BH
989
990 // do mode change if socket-mode is given
991 if(!::arg().isEmpty("socket-mode")) {
992 mode_t sockmode=::arg().asMode("socket-mode");
993 chmod(sockname.c_str(), sockmode);
994 }
1d5b3ce6
BH
995}
996
d8f6d49f 997void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)
09e6702a 998{
cd989c87 999 shared_ptr<TCPConnection> conn=any_cast<shared_ptr<TCPConnection> >(var);
c038218b 1000
879b3f70 1001 if(conn->state==TCPConnection::BYTE0) {
b841314c 1002 ssize_t bytes=recv(conn->getFD(), conn->data, 2, 0);
09e6702a 1003 if(bytes==1)
667f7e60 1004 conn->state=TCPConnection::BYTE1;
3ddb9247 1005 if(bytes==2) {
a0aa4f64 1006 conn->qlen=(((unsigned char)conn->data[0]) << 8)+ (unsigned char)conn->data[1];
667f7e60
BH
1007 conn->bytesread=0;
1008 conn->state=TCPConnection::GETQUESTION;
09e6702a
BH
1009 }
1010 if(!bytes || bytes < 0) {
bb4bdbaf 1011 t_fdm->removeReadFD(fd);
09e6702a
BH
1012 return;
1013 }
1014 }
667f7e60 1015 else if(conn->state==TCPConnection::BYTE1) {
b841314c 1016 ssize_t bytes=recv(conn->getFD(), conn->data+1, 1, 0);
09e6702a 1017 if(bytes==1) {
667f7e60 1018 conn->state=TCPConnection::GETQUESTION;
a0aa4f64 1019 conn->qlen=(((unsigned char)conn->data[0]) << 8)+ (unsigned char)conn->data[1];
667f7e60 1020 conn->bytesread=0;
09e6702a
BH
1021 }
1022 if(!bytes || bytes < 0) {
1023 if(g_logCommonErrors)
cd989c87 1024 L<<Logger::Error<<"TCP client "<< conn->d_remote.toString() <<" disconnected after first byte"<<endl;
bb4bdbaf 1025 t_fdm->removeReadFD(fd);
09e6702a
BH
1026 return;
1027 }
1028 }
667f7e60 1029 else if(conn->state==TCPConnection::GETQUESTION) {
b841314c 1030 ssize_t bytes=recv(conn->getFD(), conn->data + conn->bytesread, conn->qlen - conn->bytesread, 0);
f9d67b41 1031 if(!bytes || bytes < 0 || bytes > std::numeric_limits<std::uint16_t>::max()) {
cd989c87 1032 L<<Logger::Error<<"TCP client "<< conn->d_remote.toString() <<" disconnected while reading question body"<<endl;
bb4bdbaf 1033 t_fdm->removeReadFD(fd);
09e6702a
BH
1034 return;
1035 }
b841314c 1036 conn->bytesread+=(uint16_t)bytes;
667f7e60 1037 if(conn->bytesread==conn->qlen) {
bb4bdbaf 1038 t_fdm->removeReadFD(fd); // should no longer awake ourselves when there is data to read
879b3f70 1039
09e6702a
BH
1040 DNSComboWriter* dc=0;
1041 try {
cd989c87 1042 dc=new DNSComboWriter(conn->data, conn->qlen, g_now);
09e6702a
BH
1043 }
1044 catch(MOADNSException &mde) {
3ddb9247 1045 g_stats.clientParseError++;
4957a608 1046 if(g_logCommonErrors)
cd989c87 1047 L<<Logger::Error<<"Unable to parse packet from TCP client "<< conn->d_remote.toString() <<endl;
4957a608 1048 return;
09e6702a 1049 }
cd989c87
BH
1050 dc->d_tcpConnection = conn; // carry the torch
1051 dc->setSocket(conn->getFD()); // this is the only time a copy is made of the actual fd
09e6702a 1052 dc->d_tcp=true;
cd989c87 1053 dc->setRemote(&conn->d_remote);
a6147cd2 1054 ComboAddress dest;
1055 memset(&dest, 0, sizeof(dest));
1056 dest.sin4.sin_family = conn->d_remote.sin4.sin_family;
1057 socklen_t len = dest.getSocklen();
1058 getsockname(conn->getFD(), (sockaddr*)&dest, &len); // if this fails, we're ok with it
1059 dc->setLocal(dest);
1060
879b3f70 1061 if(dc->d_mdp.d_header.qr) {
4957a608 1062 delete dc;
048f5db6 1063 g_stats.ignoredCount++;
4328f463 1064 L<<Logger::Error<<"Ignoring answer from TCP client "<< conn->d_remote.toString() <<" on server socket!"<<endl;
4957a608 1065 return;
879b3f70 1066 }
3abcdab2
PD
1067 if(dc->d_mdp.d_header.opcode) {
1068 delete dc;
048f5db6 1069 g_stats.ignoredCount++;
4328f463 1070 L<<Logger::Error<<"Ignoring non-query opcode from TCP client "<< conn->d_remote.toString() <<" on server socket!"<<endl;
3abcdab2
PD
1071 return;
1072 }
09e6702a 1073 else {
4957a608
BH
1074 ++g_stats.qcounter;
1075 ++g_stats.tcpqcounter;
50a5ef72 1076 MT->makeThread(startDoResolve, dc); // deletes dc, will set state to BYTE0 again
4957a608 1077 return;
09e6702a
BH
1078 }
1079 }
1080 }
1081}
1082
6dcd28c3 1083//! Handle new incoming TCP connection
d8f6d49f 1084void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t& )
09e6702a 1085{
37d3f960 1086 ComboAddress addr;
09e6702a 1087 socklen_t addrlen=sizeof(addr);
705f31ae 1088 int newsock=(int)accept(fd, (struct sockaddr*)&addr, &addrlen);
b841314c 1089 if(newsock>=0) {
85c32340
BH
1090 if(MT->numProcesses() > g_maxMThreads) {
1091 g_stats.overCapacityDrops++;
3897b9e1 1092 closesocket(newsock);
85c32340
BH
1093 return;
1094 }
1095
92011b8f 1096 if(t_remotes)
1097 t_remotes->push_back(addr);
49a699c4 1098 if(t_allowFrom && !t_allowFrom->match(&addr)) {
3ddb9247 1099 if(!g_quiet)
4957a608 1100 L<<Logger::Error<<"["<<MT->getTid()<<"] dropping TCP query from "<<addr.toString()<<", address not matched by allow-from"<<endl;
2914b022 1101
09e6702a 1102 g_stats.unauthorizedTCP++;
3897b9e1 1103 closesocket(newsock);
09e6702a
BH
1104 return;
1105 }
bd0289fc 1106 if(g_maxTCPPerClient && t_tcpClientCounts->count(addr) && (*t_tcpClientCounts)[addr] >= g_maxTCPPerClient) {
09e6702a 1107 g_stats.tcpClientOverflow++;
3897b9e1 1108 closesocket(newsock); // don't call TCPConnection::closeAndCleanup here - did not enter it in the counts yet!
09e6702a
BH
1109 return;
1110 }
3ddb9247 1111
3897b9e1 1112 setNonBlocking(newsock);
cd989c87
BH
1113 shared_ptr<TCPConnection> tc(new TCPConnection(newsock, addr));
1114 tc->state=TCPConnection::BYTE0;
3ddb9247 1115
cd989c87 1116 t_fdm->addReadFD(tc->getFD(), handleRunningTCPQuestion, tc);
c038218b 1117
0bff046b 1118 struct timeval now;
c038218b 1119 Utility::gettimeofday(&now, 0);
cd989c87 1120 t_fdm->setReadTTD(tc->getFD(), now, g_tcpTimeout);
09e6702a
BH
1121 }
1122}
3ddb9247 1123
b71b60ee 1124string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fromaddr, const ComboAddress& destaddr, struct timeval tv, int fd)
1bc3c142 1125{
183eb877 1126 gettimeofday(&g_now, 0);
b71b60ee 1127 struct timeval diff = g_now - tv;
1128 double delta=(diff.tv_sec*1000 + diff.tv_usec/1000.0);
183eb877 1129
22cf1fda 1130 if(tv.tv_sec && delta > 1000.0) {
b71b60ee 1131 g_stats.tooOldDrops++;
1132 return 0;
1133 }
1134
1bc3c142 1135 ++g_stats.qcounter;
d7f10541
BH
1136 if(fromaddr.sin4.sin_family==AF_INET6)
1137 g_stats.ipv6qcounter++;
1bc3c142
BH
1138
1139 string response;
93f0da94 1140 const struct dnsheader* dh = (struct dnsheader*)question.c_str();
49a3500d 1141 unsigned int ctag=0;
1bc3c142
BH
1142 try {
1143 uint32_t age;
8f7473d7 1144#ifdef MALLOC_TRACE
1145 /*
1146 static uint64_t last=0;
1147 if(!last)
1148 g_mtracer->clearAllocators();
1149 cout<<g_mtracer->getAllocs()-last<<" "<<g_mtracer->getNumOut()<<" -- BEGIN TRACE"<<endl;
1150 last=g_mtracer->getAllocs();
1151 cout<<g_mtracer->topAllocatorsString()<<endl;
1152 g_mtracer->clearAllocators();
1153 */
1154#endif
c0725e58 1155 if(t_pdl->get() && (*t_pdl)->d_gettag) {
12ce523e 1156 unsigned int consumed=0;
49a3500d 1157 uint16_t qtype=0;
1158 DNSName qname(question.c_str(), question.length(), sizeof(dnsheader), false, &qtype, 0, &consumed);
1159 ctag=(*t_pdl)->gettag(fromaddr, destaddr, qname, qtype);
12ce523e 1160 }
3ddb9247 1161
49a3500d 1162 if(!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(ctag, question, g_now.tv_sec, &response, &age)) {
1163 if(!g_quiet)
1164 L<<Logger::Notice<<t_id<< " question answered from packet cache tag="<<ctag<<" from "<<fromaddr.toString()<<endl;
8f7473d7 1165
1bc3c142
BH
1166 g_stats.packetCacheHits++;
1167 SyncRes::s_queries++;
1168 ageDNSPacket(response, age);
b71b60ee 1169 struct msghdr msgh;
1170 struct iovec iov;
1171 char cbuf[256];
1172 fillMSGHdr(&msgh, &iov, cbuf, 0, (char*)response.c_str(), response.length(), const_cast<ComboAddress*>(&fromaddr));
cbc03320 1173 if(g_fromtosockets.count(fd)) {
fbe2a2e0 1174 addCMsgSrcAddr(&msgh, cbuf, &destaddr, 0);
b71b60ee 1175 }
579cae19
PD
1176 else {
1177 msgh.msg_control=NULL;
1178 }
cbc03320 1179 if(sendmsg(fd, &msgh, 0) < 0 && g_logCommonErrors)
1180 L<<Logger::Warning<<"Sending UDP reply to client "<<fromaddr.toStringWithPort()<<" failed with: "<<strerror(errno)<<endl;
b71b60ee 1181
97bee66d
BH
1182 if(response.length() >= sizeof(struct dnsheader)) {
1183 struct dnsheader dh;
1184 memcpy(&dh, response.c_str(), sizeof(dh));
92011b8f 1185 updateResponseStats(dh.rcode, fromaddr, response.length(), 0, 0);
97bee66d 1186 }
08f3f638 1187 g_stats.avgLatencyUsec=(1-1.0/g_latencyStatSize)*g_stats.avgLatencyUsec + 0.0; // we assume 0 usec
1bc3c142
BH
1188 return 0;
1189 }
3ddb9247 1190 }
1bc3c142
BH
1191 catch(std::exception& e) {
1192 L<<Logger::Error<<"Error processing or aging answer packet: "<<e.what()<<endl;
1193 return 0;
1194 }
3ddb9247 1195
4ea94941 1196 if(t_pdl->get()) {
93f0da94 1197 if((*t_pdl)->ipfilter(fromaddr, destaddr, *dh)) {
4ea94941 1198 if(!g_quiet)
1199 L<<Logger::Notice<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] DROPPED question from "<<fromaddr.toStringWithPort()<<" based on policy"<<endl;
1200 g_stats.policyDrops++;
1201 return 0;
1202 }
1203 }
1204
1bc3c142 1205 if(MT->numProcesses() > g_maxMThreads) {
461df9d2 1206 if(!g_quiet)
854d44e3 1207 L<<Logger::Notice<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] DROPPED question from "<<fromaddr.toStringWithPort()<<", over capacity"<<endl;
461df9d2 1208
1bc3c142
BH
1209 g_stats.overCapacityDrops++;
1210 return 0;
1211 }
3ddb9247 1212
1bc3c142
BH
1213 DNSComboWriter* dc = new DNSComboWriter(question.c_str(), question.size(), g_now);
1214 dc->setSocket(fd);
49a3500d 1215 dc->d_tag=ctag;
1216 dc->d_query = question;
1bc3c142 1217 dc->setRemote(&fromaddr);
b71b60ee 1218 dc->setLocal(destaddr);
1bc3c142
BH
1219 dc->d_tcp=false;
1220 MT->makeThread(startDoResolve, (void*) dc); // deletes dc
1221 return 0;
3ddb9247
PD
1222}
1223
b71b60ee 1224
d8f6d49f 1225void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
5db529f8 1226{
a9af3782 1227 int len;
5db529f8
BH
1228 char data[1500];
1229 ComboAddress fromaddr;
b71b60ee 1230 struct msghdr msgh;
1231 struct iovec iov;
1232 char cbuf[256];
1233
1234 fromaddr.sin6.sin6_family=AF_INET6; // this makes sure fromaddr is big enough
1235 fillMSGHdr(&msgh, &iov, cbuf, sizeof(cbuf), data, sizeof(data), &fromaddr);
1236
3ddb9247 1237 for(;;)
b71b60ee 1238 if((len=recvmsg(fd, &msgh, 0)) >= 0) {
92011b8f 1239 if(t_remotes)
1240 t_remotes->push_back(fromaddr);
b23b8614 1241
49a699c4 1242 if(t_allowFrom && !t_allowFrom->match(&fromaddr)) {
3ddb9247 1243 if(!g_quiet)
4957a608 1244 L<<Logger::Error<<"["<<MT->getTid()<<"] dropping UDP query from "<<fromaddr.toString()<<", address not matched by allow-from"<<endl;
2914b022 1245
5db529f8 1246 g_stats.unauthorizedUDP++;
a9af3782 1247 return;
5db529f8 1248 }
15c01deb 1249 BOOST_STATIC_ASSERT(offsetof(sockaddr_in, sin_port) == offsetof(sockaddr_in6, sin6_port));
81859ba5 1250 if(!fromaddr.sin4.sin_port) { // also works for IPv6
3ddb9247 1251 if(!g_quiet)
81859ba5 1252 L<<Logger::Error<<"["<<MT->getTid()<<"] dropping UDP query from "<<fromaddr.toStringWithPort()<<", can't deal with port 0"<<endl;
1253
1254 g_stats.clientParseError++; // not quite the best place to put it, but needs to go somewhere
1255 return;
1256 }
5db529f8 1257 try {
b23b8614 1258 dnsheader* dh=(dnsheader*)data;
3ddb9247 1259
b23b8614 1260 if(dh->qr) {
048f5db6 1261 g_stats.ignoredCount++;
4957a608
BH
1262 if(g_logCommonErrors)
1263 L<<Logger::Error<<"Ignoring answer from "<<fromaddr.toString()<<" on server socket!"<<endl;
5db529f8 1264 }
3abcdab2 1265 else if(dh->opcode) {
048f5db6 1266 g_stats.ignoredCount++;
3abcdab2
PD
1267 if(g_logCommonErrors)
1268 L<<Logger::Error<<"Ignoring non-query opcode "<<dh->opcode<<" from "<<fromaddr.toString()<<" on server socket!"<<endl;
1269 }
5db529f8 1270 else {
232f0877 1271 string question(data, len);
b71b60ee 1272 struct timeval tv={0,0};
1273 HarvestTimestamp(&msgh, &tv);
1274 ComboAddress dest;
1275 memset(&dest, 0, sizeof(dest)); // this makes sure we igore this address if not returned by recvmsg above
a6147cd2 1276 auto loc = rplookup(g_listenSocketsAddresses, fd);
1277 if(HarvestDestinationAddress(&msgh, &dest)) {
1278 // but.. need to get port too
1279 if(loc)
1280 dest.sin4.sin_port = loc->sin4.sin_port;
1281 }
1282 else {
1283 if(loc) {
1284 dest = *loc;
1285 }
1286 else {
1287 dest.sin4.sin_family = fromaddr.sin4.sin_family;
1288 socklen_t len = dest.getSocklen();
1289 getsockname(fd, (sockaddr*)&dest, &len); // if this fails, we're ok with it
1290 }
1291 }
232f0877 1292 if(g_weDistributeQueries)
b71b60ee 1293 distributeAsyncFunction(question, boost::bind(doProcessUDPQuestion, question, fromaddr, dest, tv, fd));
232f0877 1294 else
b71b60ee 1295 doProcessUDPQuestion(question, fromaddr, dest, tv, fd);
5db529f8
BH
1296 }
1297 }
1298 catch(MOADNSException& mde) {
3ddb9247 1299 g_stats.clientParseError++;
84e66a59 1300 if(g_logCommonErrors)
4957a608 1301 L<<Logger::Error<<"Unable to parse packet from remote UDP client "<<fromaddr.toString() <<": "<<mde.what()<<endl;
5db529f8 1302 }
0b602819
KM
1303 catch(std::runtime_error& e) {
1304 g_stats.clientParseError++;
1305 if(g_logCommonErrors)
1306 L<<Logger::Error<<"Unable to parse packet from remote UDP client "<<fromaddr.toString() <<": "<<e.what()<<endl;
5db529f8
BH
1307 }
1308 }
ac0e821b
BH
1309 else {
1310 // cerr<<t_id<<" had error: "<<stringerror()<<endl;
3ddb9247 1311 if(errno == EAGAIN)
9326cae1 1312 g_stats.noPacketError++;
bf3b0cec 1313 break;
ac0e821b 1314 }
5db529f8
BH
1315}
1316
1bc3c142 1317
5db529f8
BH
1318typedef vector<pair<int, function< void(int, any&) > > > deferredAdd_t;
1319deferredAdd_t deferredAdd;
1320
f28307ad 1321void makeTCPServerSockets()
9c495589 1322{
37d3f960 1323 int fd;
f28307ad 1324 vector<string>locals;
2e3d8a19 1325 stringtok(locals,::arg()["local-address"]," ,");
9c495589 1326
f28307ad 1327 if(locals.empty())
3f81d239 1328 throw PDNSException("No local address specified");
3ddb9247 1329
f28307ad 1330 for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
32252594
BH
1331 ServiceTuple st;
1332 st.port=::arg().asNum("local-port");
1333 parseService(*i, st);
3ddb9247 1334
32252594
BH
1335 ComboAddress sin;
1336
f28307ad 1337 memset((char *)&sin,0, sizeof(sin));
37d3f960 1338 sin.sin4.sin_family = AF_INET;
32252594 1339 if(!IpToU32(st.host, (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
37d3f960 1340 sin.sin6.sin6_family = AF_INET6;
f71bc087 1341 if(makeIPv6sockaddr(st.host, &sin.sin6) < 0)
3ddb9247 1342 throw PDNSException("Unable to resolve local address for TCP server on '"+ st.host +"'");
37d3f960
BH
1343 }
1344
1345 fd=socket(sin.sin6.sin6_family, SOCK_STREAM, 0);
3ddb9247 1346 if(fd<0)
3f81d239 1347 throw PDNSException("Making a TCP server socket for resolver: "+stringerror());
f28307ad 1348
3897b9e1 1349 setCloseOnExec(fd);
a903b39c 1350
f28307ad 1351 int tmp=1;
37d3f960 1352 if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
f28307ad 1353 L<<Logger::Error<<"Setsockopt failed for TCP listening socket"<<endl;
c8ddb7c2 1354 exit(1);
f28307ad 1355 }
0dfa94ab 1356 if(sin.sin6.sin6_family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &tmp, sizeof(tmp)) < 0) {
1357 L<<Logger::Error<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<strerror(errno)<<endl;
1358 }
1359
c8ddb7c2 1360#ifdef TCP_DEFER_ACCEPT
37d3f960
BH
1361 if(setsockopt(fd, SOL_TCP,TCP_DEFER_ACCEPT,(char*)&tmp,sizeof tmp) >= 0) {
1362 if(i==locals.begin())
4957a608 1363 L<<Logger::Error<<"Enabled TCP data-ready filter for (slight) DoS protection"<<endl;
c8ddb7c2
BH
1364 }
1365#endif
1366
fec7dd5a
SS
1367 if( ::arg().mustDo("non-local-bind") )
1368 Utility::setBindAny(AF_INET, fd);
1369
2332f42d 1370#ifdef SO_REUSEPORT
1371 if(::arg().mustDo("reuseport")) {
1372 int one=1;
1373 if(setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
1374 throw PDNSException("SO_REUSEPORT: "+stringerror());
1375 }
1376#endif
1377
32252594 1378 sin.sin4.sin_port = htons(st.port);
37d3f960 1379 int socklen=sin.sin4.sin_family==AF_INET ? sizeof(sin.sin4) : sizeof(sin.sin6);
3ddb9247 1380 if (::bind(fd, (struct sockaddr *)&sin, socklen )<0)
3f81d239 1381 throw PDNSException("Binding TCP server socket for "+ st.host +": "+stringerror());
3ddb9247 1382
3897b9e1 1383 setNonBlocking(fd);
49a699c4 1384 setSocketSendBuffer(fd, 65000);
37d3f960 1385 listen(fd, 128);
5db529f8 1386 deferredAdd.push_back(make_pair(fd, handleNewTCPQuestion));
c2136bf0 1387 g_tcpListenSockets.push_back(fd);
84433b79 1388 // we don't need to update g_listenSocketsAddresses since it doesn't work for TCP/IP:
1389 // - fd is not that which we know here, but returned from accept()
3ddb9247 1390 if(sin.sin4.sin_family == AF_INET)
32252594 1391 L<<Logger::Error<<"Listening for TCP queries on "<< sin.toString() <<":"<<st.port<<endl;
aa136564 1392 else
32252594 1393 L<<Logger::Error<<"Listening for TCP queries on ["<< sin.toString() <<"]:"<<st.port<<endl;
f28307ad 1394 }
9c495589
BH
1395}
1396
f28307ad 1397void makeUDPServerSockets()
288f4aa9 1398{
fec7dd5a 1399 int one=1;
f28307ad 1400 vector<string>locals;
2e3d8a19 1401 stringtok(locals,::arg()["local-address"]," ,");
288f4aa9 1402
f28307ad 1403 if(locals.empty())
3f81d239 1404 throw PDNSException("No local address specified");
3ddb9247 1405
f28307ad 1406 for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
32252594
BH
1407 ServiceTuple st;
1408 st.port=::arg().asNum("local-port");
1409 parseService(*i, st);
1410
37d3f960 1411 ComboAddress sin;
996c89cc 1412
37d3f960
BH
1413 memset(&sin, 0, sizeof(sin));
1414 sin.sin4.sin_family = AF_INET;
32252594 1415 if(!IpToU32(st.host.c_str() , (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
37d3f960 1416 sin.sin6.sin6_family = AF_INET6;
f71bc087 1417 if(makeIPv6sockaddr(st.host, &sin.sin6) < 0)
3ddb9247 1418 throw PDNSException("Unable to resolve local address for UDP server on '"+ st.host +"'");
37d3f960 1419 }
3ddb9247 1420
bb4bdbaf 1421 int fd=socket(sin.sin4.sin_family, SOCK_DGRAM, 0);
d3b4137e 1422 if(fd < 0) {
3f81d239 1423 throw PDNSException("Making a UDP server socket for resolver: "+netstringerror());
d3b4137e 1424 }
915b0c39
AT
1425 if (!setSocketTimestamps(fd))
1426 L<<Logger::Warning<<"Unable to enable timestamp reporting for socket"<<endl;
0dfa94ab 1427
b71b60ee 1428 if(IsAnyAddress(sin)) {
cbc03320 1429 if(sin.sin4.sin_family == AF_INET)
1430 if(!setsockopt(fd, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one))) // linux supports this, so why not - might fail on other systems
1431 g_fromtosockets.insert(fd);
757d3179 1432#ifdef IPV6_RECVPKTINFO
cbc03320 1433 if(sin.sin4.sin_family == AF_INET6)
1434 if(!setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)))
1435 g_fromtosockets.insert(fd);
757d3179 1436#endif
0dfa94ab 1437 if(sin.sin6.sin6_family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)) < 0) {
1438 L<<Logger::Error<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<strerror(errno)<<endl;
1439 }
b71b60ee 1440 }
fec7dd5a
SS
1441 if( ::arg().mustDo("non-local-bind") )
1442 Utility::setBindAny(AF_INET6, fd);
1443
3897b9e1 1444 setCloseOnExec(fd);
a903b39c 1445
4e9a20e6 1446 setSocketReceiveBuffer(fd, 250000);
32252594 1447 sin.sin4.sin_port = htons(st.port);
37d3f960 1448
2332f42d 1449
1450#ifdef SO_REUSEPORT
1451 if(::arg().mustDo("reuseport")) {
1452 int one=1;
1453 if(setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
1454 throw PDNSException("SO_REUSEPORT: "+stringerror());
1455 }
1456#endif
1457 int socklen=sin.getSocklen();
3ddb9247 1458 if (::bind(fd, (struct sockaddr *)&sin, socklen)<0)
335da0ba 1459 throw PDNSException("Resolver binding to server socket on port "+ std::to_string(st.port) +" for "+ st.host+": "+stringerror());
3ddb9247 1460
3897b9e1 1461 setNonBlocking(fd);
c2136bf0 1462
0aaecd50 1463 deferredAdd.push_back(make_pair(fd, handleNewUDPQuestion));
40a3dd64 1464 g_listenSocketsAddresses[fd]=sin; // this is written to only from the startup thread, not from the workers
3ddb9247 1465 if(sin.sin4.sin_family == AF_INET)
32252594 1466 L<<Logger::Error<<"Listening for UDP queries on "<< sin.toString() <<":"<<st.port<<endl;
aa136564 1467 else
32252594 1468 L<<Logger::Error<<"Listening for UDP queries on ["<< sin.toString() <<"]:"<<st.port<<endl;
f28307ad 1469 }
c836dc19 1470}
caa6eefa 1471
9c495589 1472
c836dc19
BH
1473void daemonize(void)
1474{
1475 if(fork())
1476 exit(0); // bye bye
3ddb9247
PD
1477
1478 setsid();
c836dc19 1479
27a5ead5 1480 int i=open("/dev/null",O_RDWR); /* open stdin */
3ddb9247 1481 if(i < 0)
27a5ead5
BH
1482 L<<Logger::Critical<<"Unable to open /dev/null: "<<stringerror()<<endl;
1483 else {
1484 dup2(i,0); /* stdin */
1485 dup2(i,1); /* stderr */
1486 dup2(i,2); /* stderr */
1487 close(i);
1488 }
288f4aa9 1489}
caa6eefa 1490
cc59bce6 1491AtomicCounter counter;
c75a6a9e
BH
1492bool statsWanted;
1493
1494void usr1Handler(int)
1495{
1496 statsWanted=true;
1497}
ae1b2e98 1498
9170fbaf
BH
1499void usr2Handler(int)
1500{
f1f34cc2 1501 g_quiet= !g_quiet;
1502 SyncRes::setDefaultLogMode(g_quiet ? SyncRes::LogNone : SyncRes::Log);
1503 ::arg().set("quiet")=g_quiet ? "" : "no";
9170fbaf
BH
1504}
1505
c75a6a9e
BH
1506void doStats(void)
1507{
16beeaa4
BH
1508 static time_t lastOutputTime;
1509 static uint64_t lastQueryCount;
d299d4f5 1510
1511 uint64_t cacheHits = broadcastAccFunction<uint64_t>(pleaseGetCacheHits);
1512 uint64_t cacheMisses = broadcastAccFunction<uint64_t>(pleaseGetCacheMisses);
3ddb9247 1513
d299d4f5 1514 if(g_stats.qcounter && (cacheHits + cacheMisses) && SyncRes::s_queries && SyncRes::s_outqueries) {
3427fa8a
BH
1515 L<<Logger::Warning<<"stats: "<<g_stats.qcounter<<" questions, "<<
1516 broadcastAccFunction<uint64_t>(pleaseGetCacheSize)<< " cache entries, "<<
1517 broadcastAccFunction<uint64_t>(pleaseGetNegCacheSize)<<" negative entries, "<<
3ddb9247
PD
1518 (int)((cacheHits*100.0)/(cacheHits+cacheMisses))<<"% cache hits"<<endl;
1519
3427fa8a
BH
1520 L<<Logger::Warning<<"stats: throttle map: "
1521 << broadcastAccFunction<uint64_t>(pleaseGetThrottleSize) <<", ns speeds: "
3ddb9247 1522 << broadcastAccFunction<uint64_t>(pleaseGetNsSpeedsSize)<<endl;
70c2c8b1
BH
1523 L<<Logger::Warning<<"stats: outpacket/query ratio "<<(int)(SyncRes::s_outqueries*100.0/SyncRes::s_queries)<<"%";
1524 L<<Logger::Warning<<", "<<(int)(SyncRes::s_throttledqueries*100.0/(SyncRes::s_outqueries+SyncRes::s_throttledqueries))<<"% throttled, "
525b8a7c 1525 <<SyncRes::s_nodelegated<<" no-delegation drops"<<endl;
3427fa8a
BH
1526 L<<Logger::Warning<<"stats: "<<SyncRes::s_tcpoutqueries<<" outgoing tcp connections, "<<
1527 broadcastAccFunction<uint64_t>(pleaseGetConcurrentQueries)<<" queries running, "<<SyncRes::s_outgoingtimeouts<<" outgoing timeouts"<<endl;
81883dcc 1528
16beeaa4
BH
1529 //L<<Logger::Warning<<"stats: "<<g_stats.ednsPingMatches<<" ping matches, "<<g_stats.ednsPingMismatches<<" mismatches, "<<
1530 //g_stats.noPingOutQueries<<" outqueries w/o ping, "<< g_stats.noEdnsOutQueries<<" w/o EDNS"<<endl;
3ddb9247 1531
16beeaa4
BH
1532 L<<Logger::Warning<<"stats: " << broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize) <<
1533 " packet cache entries, "<<(int)(100.0*broadcastAccFunction<uint64_t>(pleaseGetPacketCacheHits)/SyncRes::s_queries) << "% packet cache hits"<<endl;
3ddb9247 1534
16beeaa4
BH
1535 time_t now = time(0);
1536 if(lastOutputTime && lastQueryCount && now != lastOutputTime) {
1537 L<<Logger::Warning<<"stats: "<< (SyncRes::s_queries - lastQueryCount) / (now - lastOutputTime) <<" qps (average over "<< (now - lastOutputTime) << " seconds)"<<endl;
1538 }
1539 lastOutputTime = now;
1540 lastQueryCount = SyncRes::s_queries;
c75a6a9e 1541 }
3ddb9247 1542 else if(statsWanted)
70c2c8b1 1543 L<<Logger::Warning<<"stats: no stats yet!"<<endl;
7becf07f 1544
c75a6a9e
BH
1545 statsWanted=false;
1546}
c836dc19 1547
29f0b1ce 1548static void houseKeeping(void *)
c836dc19 1549{
d67620e4 1550 static __thread time_t last_stat, last_rootupdate, last_prune, last_secpoll;
8baca3fa 1551 static __thread int cleanCounter=0;
cc59bce6 1552 static __thread bool s_running; // houseKeeping can get suspended in secpoll, and be restarted, which makes us do duplicate work
1553 try {
1554 if(s_running)
1555 return;
1556 s_running=true;
3ddb9247 1557
cc59bce6 1558 struct timeval now;
1559 Utility::gettimeofday(&now, 0);
3ddb9247
PD
1560
1561 if(now.tv_sec - last_prune > (time_t)(5 + t_id)) {
cc59bce6 1562 DTime dt;
1563 dt.setTimeval(now);
1564 t_RC->doPrune(); // this function is local to a thread, so fine anyhow
f8f243b0 1565 t_packetCache->doPruneTo(::arg().asNum("max-packetcache-entries") / g_numWorkerThreads);
3ddb9247 1566
f8f243b0 1567 pruneCollection(t_sstorage->negcache, ::arg().asNum("max-cache-entries") / (g_numWorkerThreads * 10), 200);
3ddb9247 1568
cc59bce6 1569 if(!((cleanCounter++)%40)) { // this is a full scan!
1570 time_t limit=now.tv_sec-300;
1571 for(SyncRes::nsspeeds_t::iterator i = t_sstorage->nsSpeeds.begin() ; i!= t_sstorage->nsSpeeds.end(); )
1572 if(i->second.stale(limit))
1573 t_sstorage->nsSpeeds.erase(i++);
1574 else
1575 ++i;
1576 }
1577 last_prune=time(0);
d67620e4 1578 }
3ddb9247 1579
cc59bce6 1580 if(now.tv_sec - last_rootupdate > 7200) {
1581 SyncRes sr(now);
1582 sr.setDoEDNS0(true);
e325f20c 1583 vector<DNSRecord> ret;
3ddb9247 1584
cc59bce6 1585 sr.setNoCache();
1586 int res=-1;
18b73338 1587 try {
6ed9a611 1588 res=sr.beginResolve(DNSName("."), QType(QType::NS), 1, ret);
cc59bce6 1589 }
3aa91c3e 1590 catch(PDNSException& e)
1591 {
1592 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
1593 }
1594
1595 catch(std::exception& e)
1596 {
1597 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.what()<<endl;
1598 }
1599
cc59bce6 1600 catch(...)
1601 {
1602 L<<Logger::Error<<"Failed to update . records, got an exception"<<endl;
1603 }
1604 if(!res) {
1605 L<<Logger::Notice<<"Refreshed . records"<<endl;
1606 last_rootupdate=now.tv_sec;
1607 }
1608 else
1609 L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
1610 }
3ddb9247 1611
cc59bce6 1612 if(!t_id) {
3ddb9247 1613 if(now.tv_sec - last_stat >= 1800) {
cc59bce6 1614 doStats();
1615 last_stat=time(0);
1616 }
3ddb9247 1617
cc59bce6 1618 if(now.tv_sec - last_secpoll >= 3600) {
1619 try {
1620 doSecPoll(&last_secpoll);
1621 }
1622 catch(...) {}
18b73338 1623 }
d67620e4 1624 }
cc59bce6 1625 s_running=false;
d67620e4 1626 }
cc59bce6 1627 catch(PDNSException& ae)
1628 {
1629 s_running=false;
1630 L<<Logger::Error<<"Fatal error in housekeeping thread: "<<ae.reason<<endl;
1631 throw;
1632 }
779828c4 1633}
d6d5dea7 1634
49a699c4
BH
1635void makeThreadPipes()
1636{
c3828c03 1637 for(unsigned int n=0; n < g_numThreads; ++n) {
49a699c4
BH
1638 struct ThreadPipeSet tps;
1639 int fd[2];
1640 if(pipe(fd) < 0)
1641 unixDie("Creating pipe for inter-thread communications");
3ddb9247 1642
49a699c4
BH
1643 tps.readToThread = fd[0];
1644 tps.writeToThread = fd[1];
3ddb9247 1645
49a699c4
BH
1646 if(pipe(fd) < 0)
1647 unixDie("Creating pipe for inter-thread communications");
1648 tps.readFromThread = fd[0];
1649 tps.writeFromThread = fd[1];
3ddb9247 1650
49a699c4
BH
1651 g_pipes.push_back(tps);
1652 }
1653}
1654
00c9b8c1
BH
1655struct ThreadMSG
1656{
1657 pipefunc_t func;
1658 bool wantAnswer;
1659};
1660
49a699c4
BH
1661void broadcastFunction(const pipefunc_t& func, bool skipSelf)
1662{
49a699c4 1663 unsigned int n = 0;
1dc8f4d0 1664 for(ThreadPipeSet& tps : g_pipes)
49a699c4
BH
1665 {
1666 if(n++ == t_id) {
1667 if(!skipSelf)
1668 func(); // don't write to ourselves!
1669 continue;
1670 }
3ddb9247 1671
00c9b8c1
BH
1672 ThreadMSG* tmsg = new ThreadMSG();
1673 tmsg->func = func;
1674 tmsg->wantAnswer = true;
b841314c
RG
1675 if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) {
1676 delete tmsg;
49a699c4 1677 unixDie("write to thread pipe returned wrong size or error");
b841314c 1678 }
3ddb9247 1679
49a699c4
BH
1680 string* resp;
1681 if(read(tps.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
1682 unixDie("read from thread pipe returned wrong size or error");
3ddb9247 1683
49a699c4
BH
1684 if(resp) {
1685// cerr <<"got response: " << *resp << endl;
1686 delete resp;
1687 }
1688 }
1689}
06ea9015 1690
2fafb640 1691static uint32_t g_disthashseed;
8171ab83 1692void distributeAsyncFunction(const string& packet, const pipefunc_t& func)
00c9b8c1 1693{
8171ab83 1694 unsigned int hash = hashQuestion(packet.c_str(), packet.length(), g_disthashseed);
06ea9015 1695 unsigned int target = 1 + (hash % (g_pipes.size()-1));
1696
00c9b8c1
BH
1697 if(target == t_id) {
1698 func();
1699 return;
1700 }
3ddb9247 1701 ThreadPipeSet& tps = g_pipes[target];
00c9b8c1
BH
1702 ThreadMSG* tmsg = new ThreadMSG();
1703 tmsg->func = func;
1704 tmsg->wantAnswer = false;
3ddb9247 1705
b841314c
RG
1706 if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) {
1707 delete tmsg;
3ddb9247 1708 unixDie("write to thread pipe returned wrong size or error");
b841314c 1709 }
00c9b8c1 1710}
3427fa8a 1711
49a699c4
BH
1712void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var)
1713{
00c9b8c1 1714 ThreadMSG* tmsg;
3ddb9247
PD
1715
1716 if(read(fd, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) { // fd == readToThread
49a699c4
BH
1717 unixDie("read from thread pipe returned wrong size or error");
1718 }
3ddb9247 1719
2f22827a 1720 void *resp=0;
1721 try {
1722 resp = tmsg->func();
1723 }
1724 catch(std::exception& e) {
1725 L<<Logger::Error<<"PIPE function we executed created exception: "<<e.what()<<endl; // but what if they wanted an answer.. we send 0
1726 }
1727 catch(PDNSException& e) {
1728 L<<Logger::Error<<"PIPE function we executed created PDNS exception: "<<e.reason<<endl; // but what if they wanted an answer.. we send 0
1729 }
00c9b8c1
BH
1730 if(tmsg->wantAnswer)
1731 if(write(g_pipes[t_id].writeFromThread, &resp, sizeof(resp)) != sizeof(resp))
1732 unixDie("write to thread pipe returned wrong size or error");
3ddb9247 1733
00c9b8c1 1734 delete tmsg;
49a699c4 1735}
09e6702a 1736
13034931
BH
1737template<class T> void *voider(const boost::function<T*()>& func)
1738{
1739 return func();
1740}
1741
b3b5459d
BH
1742vector<ComboAddress>& operator+=(vector<ComboAddress>&a, const vector<ComboAddress>& b)
1743{
1744 a.insert(a.end(), b.begin(), b.end());
1745 return a;
1746}
1747
92011b8f 1748vector<pair<string, uint16_t> >& operator+=(vector<pair<string, uint16_t> >&a, const vector<pair<string, uint16_t> >& b)
1749{
1750 a.insert(a.end(), b.begin(), b.end());
1751 return a;
1752}
1753
3ddb9247
PD
1754vector<pair<DNSName, uint16_t> >& operator+=(vector<pair<DNSName, uint16_t> >&a, const vector<pair<DNSName, uint16_t> >& b)
1755{
1756 a.insert(a.end(), b.begin(), b.end());
1757 return a;
1758}
1759
92011b8f 1760
13034931 1761template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool skipSelf)
3427fa8a
BH
1762{
1763 unsigned int n = 0;
1764 T ret=T();
1dc8f4d0 1765 for(ThreadPipeSet& tps : g_pipes)
3427fa8a
BH
1766 {
1767 if(n++ == t_id) {
1768 if(!skipSelf) {
1769 T* resp = (T*)func(); // don't write to ourselves!
1770 if(resp) {
1771 //~ cerr <<"got direct: " << *resp << endl;
1772 ret += *resp;
1773 delete resp;
1774 }
1775 }
1776 continue;
1777 }
3ddb9247 1778
00c9b8c1
BH
1779 ThreadMSG* tmsg = new ThreadMSG();
1780 tmsg->func = boost::bind(voider<T>, func);
1781 tmsg->wantAnswer = true;
3ddb9247 1782
b841314c
RG
1783 if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) {
1784 delete tmsg;
3427fa8a 1785 unixDie("write to thread pipe returned wrong size or error");
b841314c 1786 }
3ddb9247 1787
3427fa8a
BH
1788 T* resp;
1789 if(read(tps.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
1790 unixDie("read from thread pipe returned wrong size or error");
3ddb9247 1791
3427fa8a
BH
1792 if(resp) {
1793 //~ cerr <<"got response: " << *resp << endl;
1794 ret += *resp;
1795 delete resp;
1796 }
1797 }
1798 return ret;
1799}
1800
13034931
BH
1801template string broadcastAccFunction(const boost::function<string*()>& fun, bool skipSelf); // explicit instantiation
1802template uint64_t broadcastAccFunction(const boost::function<uint64_t*()>& fun, bool skipSelf); // explicit instantiation
b3b5459d 1803template vector<ComboAddress> broadcastAccFunction(const boost::function<vector<ComboAddress> *()>& fun, bool skipSelf); // explicit instantiation
3ddb9247 1804template vector<pair<DNSName,uint16_t> > broadcastAccFunction(const boost::function<vector<pair<DNSName, uint16_t> > *()>& fun, bool skipSelf); // explicit instantiation
3427fa8a 1805
d8f6d49f 1806void handleRCC(int fd, FDMultiplexer::funcparam_t& var)
09e6702a
BH
1807{
1808 string remote;
1809 string msg=s_rcc.recv(&remote);
1810 RecursorControlParser rcp;
1811 RecursorControlParser::func_t* command;
3ddb9247 1812
09e6702a 1813 string answer=rcp.getAnswer(msg, &command);
f0f3f0b0
PL
1814
1815 // If we are inside a chroot, we need to strip
1816 if (!arg()["chroot"].empty()) {
1817 int len = arg()["chroot"].length();
1818 remote = remote.substr(len);
1819 }
1820
ab5c053d
BH
1821 try {
1822 s_rcc.send(answer, &remote);
1823 command();
1824 }
fdbf35ac 1825 catch(std::exception& e) {
ab5c053d
BH
1826 L<<Logger::Error<<"Error dealing with control socket request: "<<e.what()<<endl;
1827 }
3f81d239 1828 catch(PDNSException& ae) {
ab5c053d
BH
1829 L<<Logger::Error<<"Error dealing with control socket request: "<<ae.reason<<endl;
1830 }
09e6702a
BH
1831}
1832
d8f6d49f 1833void handleTCPClientReadable(int fd, FDMultiplexer::funcparam_t& var)
09e6702a 1834{
0b18b22e 1835 PacketID* pident=any_cast<PacketID>(&var);
667f7e60 1836 // cerr<<"handleTCPClientReadable called for fd "<<fd<<", pident->inNeeded: "<<pident->inNeeded<<", "<<pident->sock->getHandle()<<endl;
09e6702a 1837
667f7e60 1838 shared_array<char> buffer(new char[pident->inNeeded]);
09e6702a 1839
705f31ae 1840 int ret=recv(fd, buffer.get(), pident->inNeeded,0);
09e6702a 1841 if(ret > 0) {
667f7e60
BH
1842 pident->inMSG.append(&buffer[0], &buffer[ret]);
1843 pident->inNeeded-=ret;
825fa717 1844 if(!pident->inNeeded || pident->inIncompleteOkay) {
667f7e60
BH
1845 // cerr<<"Got entire load of "<<pident->inMSG.size()<<" bytes"<<endl;
1846 PacketID pid=*pident;
1847 string msg=pident->inMSG;
3ddb9247 1848
bb4bdbaf 1849 t_fdm->removeReadFD(fd);
3ddb9247 1850 MT->sendEvent(pid, &msg);
09e6702a
BH
1851 }
1852 else {
667f7e60 1853 // cerr<<"Still have "<<pident->inNeeded<<" left to go"<<endl;
09e6702a
BH
1854 }
1855 }
1856 else {
667f7e60 1857 PacketID tmp=*pident;
bb4bdbaf 1858 t_fdm->removeReadFD(fd); // pident might now be invalid (it isn't, but still)
09e6702a
BH
1859 string empty;
1860 MT->sendEvent(tmp, &empty); // this conveys error status
1861 }
1862}
1863
d8f6d49f 1864void handleTCPClientWritable(int fd, FDMultiplexer::funcparam_t& var)
09e6702a 1865{
0b18b22e 1866 PacketID* pid=any_cast<PacketID>(&var);
4ca15bca 1867 int ret=send(fd, pid->outMSG.c_str() + pid->outPos, pid->outMSG.size() - pid->outPos,0);
09e6702a 1868 if(ret > 0) {
667f7e60
BH
1869 pid->outPos+=ret;
1870 if(pid->outPos==pid->outMSG.size()) {
1871 PacketID tmp=*pid;
bb4bdbaf 1872 t_fdm->removeWriteFD(fd);
09e6702a
BH
1873 MT->sendEvent(tmp, &tmp.outMSG); // send back what we sent to convey everything is ok
1874 }
1875 }
1876 else { // error or EOF
667f7e60 1877 PacketID tmp(*pid);
bb4bdbaf 1878 t_fdm->removeWriteFD(fd);
09e6702a 1879 string sent;
998a4334 1880 MT->sendEvent(tmp, &sent); // we convey error status by sending empty string
09e6702a
BH
1881 }
1882}
1883
34801ab1
BH
1884// resend event to everybody chained onto it
1885void doResends(MT_t::waiters_t::iterator& iter, PacketID resend, const string& content)
1886{
1887 if(iter->key.chain.empty())
1888 return;
e27e91a8 1889 // cerr<<"doResends called!\n";
34801ab1
BH
1890 for(PacketID::chain_t::iterator i=iter->key.chain.begin(); i != iter->key.chain.end() ; ++i) {
1891 resend.fd=-1;
1892 resend.id=*i;
e27e91a8 1893 // cerr<<"\tResending "<<content.size()<<" bytes for fd="<<resend.fd<<" and id="<<resend.id<<endl;
4665c31e 1894
34801ab1
BH
1895 MT->sendEvent(resend, &content);
1896 g_stats.chainResends++;
34801ab1
BH
1897 }
1898}
1899
d8f6d49f 1900void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t& var)
09e6702a 1901{
600fc20b 1902 PacketID pid=any_cast<PacketID>(var);
998a4334 1903 int len;
e45beeda 1904 char data[g_outgoingEDNSBufsize];
996c89cc 1905 ComboAddress fromaddr;
09e6702a
BH
1906 socklen_t addrlen=sizeof(fromaddr);
1907
998a4334 1908 len=recvfrom(fd, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen);
c1da7976 1909
998a4334
BH
1910 if(len < (int)sizeof(dnsheader)) {
1911 if(len < 0)
996c89cc 1912 ; // cerr<<"Error on fd "<<fd<<": "<<stringerror()<<"\n";
09e6702a 1913 else {
3ddb9247 1914 g_stats.serverParseError++;
09e6702a 1915 if(g_logCommonErrors)
85db02c5 1916 L<<Logger::Error<<"Unable to parse packet from remote UDP server "<< fromaddr.toString() <<
e44d9fa7 1917 ": packet smaller than DNS header"<<endl;
998a4334 1918 }
34801ab1 1919
49a699c4 1920 t_udpclientsocks->returnSocket(fd);
34801ab1
BH
1921 string empty;
1922
1923 MT_t::waiters_t::iterator iter=MT->d_waiters.find(pid);
3ddb9247 1924 if(iter != MT->d_waiters.end())
34801ab1 1925 doResends(iter, pid, empty);
3ddb9247 1926
34801ab1 1927 MT->sendEvent(pid, &empty); // this denotes error (does lookup again.. at least L1 will be hot)
998a4334 1928 return;
3ddb9247 1929 }
998a4334
BH
1930
1931 dnsheader dh;
1932 memcpy(&dh, data, sizeof(dh));
3ddb9247 1933
6da3b3ad
PD
1934 PacketID pident;
1935 pident.remote=fromaddr;
1936 pident.id=dh.id;
1937 pident.fd=fd;
34801ab1 1938
33a928af 1939 if(!dh.qr && g_logCommonErrors) {
854d44e3 1940 L<<Logger::Notice<<"Not taking data from question on outgoing socket from "<< fromaddr.toStringWithPort() <<endl;
6da3b3ad
PD
1941 }
1942
1943 if(!dh.qdcount || // UPC, Nominum, very old BIND on FormErr, NSD
1944 !dh.qr) { // one weird server
1945 pident.domain.clear();
1946 pident.type = 0;
1947 }
1948 else {
1949 try {
8171ab83 1950 pident.domain=DNSName(data, len, 12, false, &pident.type); // don't copy this from above - we need to do the actual read
6da3b3ad
PD
1951 }
1952 catch(std::exception& e) {
1953 g_stats.serverParseError++; // won't be fed to lwres.cc, so we have to increment
1954 L<<Logger::Warning<<"Error in packet from "<< fromaddr.toStringWithPort() << ": "<<e.what() << endl;
1955 return;
34801ab1 1956 }
6da3b3ad
PD
1957 }
1958 string packet;
1959 packet.assign(data, len);
34801ab1 1960
6da3b3ad
PD
1961 MT_t::waiters_t::iterator iter=MT->d_waiters.find(pident);
1962 if(iter != MT->d_waiters.end()) {
1963 doResends(iter, pident, packet);
1964 }
c1da7976 1965
6da3b3ad 1966retryWithName:
4957a608 1967
6da3b3ad
PD
1968 if(!MT->sendEvent(pident, &packet)) {
1969 // 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
1970 for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
1971 if(pident.fd==mthread->key.fd && mthread->key.remote==pident.remote && mthread->key.type == pident.type &&
e325f20c 1972 pident.domain == mthread->key.domain) {
6da3b3ad 1973 mthread->key.nearMisses++;
998a4334 1974 }
6da3b3ad
PD
1975
1976 // be a bit paranoid here since we're weakening our matching
3ddb9247 1977 if(pident.domain.empty() && !mthread->key.domain.empty() && !pident.type && mthread->key.type &&
6da3b3ad
PD
1978 pident.id == mthread->key.id && mthread->key.remote == pident.remote) {
1979 // cerr<<"Empty response, rest matches though, sending to a waiter"<<endl;
1980 pident.domain = mthread->key.domain;
1981 pident.type = mthread->key.type;
1982 goto retryWithName; // note that this only passes on an error, lwres will still reject the packet
d4fb76e9 1983 }
09e6702a 1984 }
6da3b3ad
PD
1985 g_stats.unexpectedCount++; // if we made it here, it really is an unexpected answer
1986 if(g_logCommonErrors) {
8a464ee3 1987 L<<Logger::Warning<<"Discarding unexpected packet from "<<fromaddr.toStringWithPort()<<": "<< (pident.domain.empty() ? "<empty>" : pident.domain.toString())<<", "<<pident.type<<", "<<MT->d_waiters.size()<<" waiters"<<endl;
d8f6d49f 1988 }
09e6702a 1989 }
6da3b3ad
PD
1990 else if(fd >= 0) {
1991 t_udpclientsocks->returnSocket(fd);
1992 }
09e6702a
BH
1993}
1994
1f4abb20
BH
1995FDMultiplexer* getMultiplexer()
1996{
1997 FDMultiplexer* ret;
1998 for(FDMultiplexer::FDMultiplexermap_t::const_iterator i = FDMultiplexer::getMultiplexerMap().begin();
1999 i != FDMultiplexer::getMultiplexerMap().end(); ++i) {
2000 try {
2001 ret=i->second();
1f4abb20
BH
2002 return ret;
2003 }
98d0ee4a 2004 catch(FDMultiplexerException &fe) {
0a7f24cb 2005 L<<Logger::Error<<"Non-fatal error initializing possible multiplexer ("<<fe.what()<<"), falling back"<<endl;
98d0ee4a
BH
2006 }
2007 catch(...) {
2008 L<<Logger::Error<<"Non-fatal error initializing possible multiplexer"<<endl;
2009 }
1f4abb20
BH
2010 }
2011 L<<Logger::Error<<"No working multiplexer found!"<<endl;
2012 exit(1);
2013}
2014
3ddb9247 2015
0f39c1a3 2016string* doReloadLuaScript()
4485aa35 2017{
674cf0f6 2018 string fname= ::arg()["lua-dns-script"];
4485aa35 2019 try {
674cf0f6
BH
2020 if(fname.empty()) {
2021 t_pdl->reset();
2022 L<<Logger::Error<<t_id<<" Unloaded current lua script"<<endl;
0f39c1a3 2023 return new string("unloaded\n");
4485aa35
BH
2024 }
2025 else {
a3e7b735 2026 *t_pdl = shared_ptr<RecursorLua4>(new RecursorLua4(fname));
4485aa35
BH
2027 }
2028 }
fdbf35ac 2029 catch(std::exception& e) {
674cf0f6 2030 L<<Logger::Error<<t_id<<" Retaining current script, error from '"<<fname<<"': "<< e.what() <<endl;
0f39c1a3 2031 return new string("retaining current script, error from '"+fname+"': "+e.what()+"\n");
4485aa35 2032 }
3ddb9247 2033
674cf0f6 2034 L<<Logger::Warning<<t_id<<" (Re)loaded lua script from '"<<fname<<"'"<<endl;
0f39c1a3 2035 return new string("(re)loaded '"+fname+"'\n");
4485aa35
BH
2036}
2037
49a699c4
BH
2038string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end)
2039{
3ddb9247 2040 if(begin != end)
49a699c4 2041 ::arg().set("lua-dns-script") = *begin;
3ddb9247 2042
0f39c1a3 2043 return broadcastAccFunction<string>(doReloadLuaScript);
3ddb9247 2044}
49a699c4 2045
77499b05
BH
2046string* pleaseUseNewTraceRegex(const std::string& newRegex)
2047try
2048{
2049 if(newRegex.empty()) {
2050 t_traceRegex->reset();
2051 return new string("unset\n");
2052 }
2053 else {
2054 (*t_traceRegex) = shared_ptr<Regex>(new Regex(newRegex));
2055 return new string("ok\n");
2056 }
2057}
3f81d239 2058catch(PDNSException& ae)
77499b05
BH
2059{
2060 return new string(ae.reason+"\n");
2061}
2062
2063string doTraceRegex(vector<string>::const_iterator begin, vector<string>::const_iterator end)
2064{
2065 return broadcastAccFunction<string>(boost::bind(pleaseUseNewTraceRegex, begin!=end ? *begin : ""));
2066}
2067
4e9a20e6 2068static void checkLinuxIPv6Limits()
2069{
2070#ifdef __linux__
2071 string line;
2072 if(readFileIfThere("/proc/sys/net/ipv6/route/max_size", &line)) {
335da0ba 2073 int lim=std::stoi(line);
4e9a20e6 2074 if(lim < 16384) {
36849ff2 2075 L<<Logger::Error<<"If using IPv6, please raise sysctl net.ipv6.route.max_size, currently set to "<<lim<<" which is < 16384"<<endl;
4e9a20e6 2076 }
2077 }
2078#endif
2079}
36849ff2 2080static void checkOrFixFDS()
4e9a20e6 2081{
c0063e60 2082 unsigned int availFDs=getFilenumLimit();
2083 unsigned int wantFDs = g_maxMThreads * g_numWorkerThreads +25; // even healthier margin then before
2084
2085 if(wantFDs > availFDs) {
067ad20e 2086 unsigned int hardlimit= getFilenumLimit(true);
2087 if(hardlimit >= wantFDs) {
c0063e60 2088 setFilenumLimit(wantFDs);
2089 L<<Logger::Warning<<"Raised soft limit on number of filedescriptors to "<<wantFDs<<" to match max-mthreads and threads settings"<<endl;
36849ff2 2090 }
2091 else {
067ad20e 2092 int newval = (hardlimit - 25) / g_numWorkerThreads;
2093 L<<Logger::Warning<<"Insufficient number of filedescriptors available for max-mthreads*threads setting! ("<<hardlimit<<" < "<<wantFDs<<"), reducing max-mthreads to "<<newval<<endl;
36849ff2 2094 g_maxMThreads = newval;
067ad20e 2095 setFilenumLimit(hardlimit);
36849ff2 2096 }
2097 }
4e9a20e6 2098}
77499b05 2099
bb4bdbaf 2100void* recursorThread(void*);
51e2144e 2101
3427fa8a 2102void* pleaseSupplantACLs(NetmaskGroup *ng)
49a699c4
BH
2103{
2104 t_allowFrom = ng;
3427fa8a 2105 return 0;
49a699c4
BH
2106}
2107
dbd23fc2
BH
2108int g_argc;
2109char** g_argv;
2110
18af64a8 2111void parseACLs()
f7c1d4e3 2112{
18af64a8 2113 static bool l_initialized;
3ddb9247 2114
49a699c4 2115 if(l_initialized) { // only reload configuration file on second call
18af64a8
BH
2116 string configname=::arg()["config-dir"]+"/recursor.conf";
2117 cleanSlashes(configname);
3ddb9247
PD
2118
2119 if(!::arg().preParseFile(configname.c_str(), "allow-from-file"))
7e818521 2120 throw runtime_error("Unable to re-parse configuration file '"+configname+"'");
49a699c4 2121 ::arg().preParseFile(configname.c_str(), "allow-from", LOCAL_NETS);
242b90e1 2122 ::arg().preParseFile(configname.c_str(), "include-dir");
829849d6
AT
2123 ::arg().preParse(g_argc, g_argv, "include-dir");
2124
2125 // then process includes
2126 std::vector<std::string> extraConfigs;
242b90e1
AT
2127 ::arg().gatherIncludes(extraConfigs);
2128
1dc8f4d0 2129 for(const std::string& fn : extraConfigs) {
7e818521 2130 if(!::arg().preParseFile(fn.c_str(), "allow-from-file", ::arg()["allow-from-file"]))
2131 throw runtime_error("Unable to re-parse configuration file include '"+fn+"'");
2132 if(!::arg().preParseFile(fn.c_str(), "allow-from", ::arg()["allow-from"]))
2133 throw runtime_error("Unable to re-parse configuration file include '"+fn+"'");
829849d6 2134 }
ca2c884c
AT
2135
2136 ::arg().preParse(g_argc, g_argv, "allow-from-file");
2137 ::arg().preParse(g_argc, g_argv, "allow-from");
f27e6356 2138 }
49a699c4
BH
2139
2140 NetmaskGroup* oldAllowFrom = t_allowFrom, *allowFrom=new NetmaskGroup;
3ddb9247 2141
2c95fc65
BH
2142 if(!::arg()["allow-from-file"].empty()) {
2143 string line;
2c95fc65
BH
2144 ifstream ifs(::arg()["allow-from-file"].c_str());
2145 if(!ifs) {
3ddb9247 2146 delete allowFrom;
9c61b9d0 2147 throw runtime_error("Could not open '"+::arg()["allow-from-file"]+"': "+stringerror());
2c95fc65
BH
2148 }
2149
2150 string::size_type pos;
2151 while(getline(ifs,line)) {
2152 pos=line.find('#');
2153 if(pos!=string::npos)
2154 line.resize(pos);
2155 trim(line);
2156 if(line.empty())
2157 continue;
2158
18af64a8 2159 allowFrom->addMask(line);
2c95fc65 2160 }
49a699c4 2161 L<<Logger::Warning<<"Done parsing " << allowFrom->size() <<" allow-from ranges from file '"<<::arg()["allow-from-file"]<<"' - overriding 'allow-from' setting"<<endl;
2c95fc65
BH
2162 }
2163 else if(!::arg()["allow-from"].empty()) {
f7c1d4e3
BH
2164 vector<string> ips;
2165 stringtok(ips, ::arg()["allow-from"], ", ");
3ddb9247 2166
f7c1d4e3
BH
2167 L<<Logger::Warning<<"Only allowing queries from: ";
2168 for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
18af64a8 2169 allowFrom->addMask(*i);
f7c1d4e3 2170 if(i!=ips.begin())
674cf0f6 2171 L<<Logger::Warning<<", ";
f7c1d4e3
BH
2172 L<<Logger::Warning<<*i;
2173 }
2174 L<<Logger::Warning<<endl;
2175 }
49a699c4 2176 else {
3ddb9247 2177 if(::arg()["local-address"]!="127.0.0.1" && ::arg().asNum("local-port")==53)
49a699c4
BH
2178 L<<Logger::Error<<"WARNING: Allowing queries from all IP addresses - this can be a security risk!"<<endl;
2179 delete allowFrom;
2180 allowFrom = 0;
2181 }
3ddb9247 2182
49a699c4 2183 g_initialAllowFrom = allowFrom;
d7dae798 2184 broadcastFunction(boost::bind(pleaseSupplantACLs, allowFrom));
49a699c4 2185 delete oldAllowFrom;
3ddb9247 2186
49a699c4 2187 l_initialized = true;
18af64a8
BH
2188}
2189
795215f2 2190boost::optional<Netmask> getEDNSSubnetMask(const ComboAddress& local, const DNSName&dn, const ComboAddress& rem)
2191{
2192 if(local.sin4.sin_family != AF_INET || local.sin4.sin_addr.s_addr) { // detect unset 'requestor'
2193 if(g_ednsdomains.check(dn) || g_ednssubnets.match(rem)) {
1353273b 2194 int bits =local.sin4.sin_family == AF_INET ? 24 : 56;
795215f2 2195 ComboAddress trunc(local);
2196 trunc.truncate(bits);
2197 return boost::optional<Netmask>(Netmask(trunc, bits));
2198 }
2199 }
2200 return boost::optional<Netmask>();
2201}
2202
2203void parseEDNSSubnetWhitelist(const std::string& wlist)
2204{
2205 vector<string> parts;
39588f55 2206 stringtok(parts, wlist, ",; ");
795215f2 2207 for(const auto& a : parts) {
2208 try {
2209 Netmask nm(a);
2210 g_ednssubnets.addMask(nm);
2211 }
2212 catch(...) {
2213 g_ednsdomains.add(DNSName(a));
2214 }
2215 }
2216}
2217
756e82cf 2218SuffixMatchNode g_delegationOnly;
2219static void setupDelegationOnly()
2220{
2221 vector<string> parts;
2222 stringtok(parts, ::arg()["delegation-only"], ", \t");
2223 for(const auto& p : parts) {
2224 g_delegationOnly.add(DNSName(p));
2225 }
2226}
795215f2 2227
18af64a8
BH
2228int serviceMain(int argc, char*argv[])
2229{
5124de27 2230 L.setName(s_programname);
18af64a8
BH
2231 L.setLoglevel((Logger::Urgency)(6)); // info and up
2232
2233 if(!::arg()["logging-facility"].empty()) {
f8499e52
BH
2234 int val=logFacilityToLOG(::arg().asNum("logging-facility") );
2235 if(val >= 0)
2236 theL().setFacility(val);
18af64a8
BH
2237 else
2238 L<<Logger::Error<<"Unknown logging facility "<<::arg().asNum("logging-facility") <<endl;
2239 }
2240
ba1a571d 2241 showProductVersion();
18af64a8 2242 seedRandom(::arg()["entropy-source"]);
06ea9015 2243 g_disthashseed=dns_random(0xffffffff);
2244
ad42489c 2245 loadRecursorLuaConfig(::arg()["lua-config-file"]);
2246
18af64a8 2247 parseACLs();
92011b8f 2248 sortPublicSuffixList();
2249
eb5bae86
BH
2250 if(!::arg()["dont-query"].empty()) {
2251 g_dontQuery=new NetmaskGroup;
2252 vector<string> ips;
2253 stringtok(ips, ::arg()["dont-query"], ", ");
66e0b6ea
BH
2254 ips.push_back("0.0.0.0");
2255 ips.push_back("::");
c36bc97a 2256
eb5bae86
BH
2257 L<<Logger::Warning<<"Will not send queries to: ";
2258 for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
2259 g_dontQuery->addMask(*i);
2260 if(i!=ips.begin())
4957a608 2261 L<<Logger::Warning<<", ";
eb5bae86
BH
2262 L<<Logger::Warning<<*i;
2263 }
2264 L<<Logger::Warning<<endl;
2265 }
2266
f7c1d4e3 2267 g_quiet=::arg().mustDo("quiet");
3ddb9247 2268
1bc3c142
BH
2269 g_weDistributeQueries = ::arg().mustDo("pdns-distributes-queries");
2270 if(g_weDistributeQueries) {
2271 L<<Logger::Warning<<"PowerDNS Recursor itself will distribute queries over threads"<<endl;
2272 }
3ddb9247 2273
756e82cf 2274 setupDelegationOnly();
b33c2462 2275 g_outgoingEDNSBufsize=::arg().asNum("edns-outgoing-bufsize");
756e82cf 2276
12ce523e 2277 if(::arg()["dnssec"]=="off")
2278 g_dnssecmode=DNSSECMode::Off;
2279 else if(::arg()["dnssec"]=="process")
2280 g_dnssecmode=DNSSECMode::Process;
2281 else if(::arg()["dnssec"]=="validate")
2282 g_dnssecmode=DNSSECMode::ValidateAll;
2283 else if(::arg()["dnssec"]=="log-fail")
2284 g_dnssecmode=DNSSECMode::ValidateForLog;
2285 else {
2286 L<<Logger::Error<<"Unknown DNSSEC mode "<<::arg()["dnssec"]<<endl;
2287 exit(1);
2288 }
2289
77499b05
BH
2290 if(::arg()["trace"]=="fail") {
2291 SyncRes::setDefaultLogMode(SyncRes::Store);
2292 }
2293 else if(::arg().mustDo("trace")) {
2294 SyncRes::setDefaultLogMode(SyncRes::Log);
f7c1d4e3
BH
2295 ::arg().set("quiet")="no";
2296 g_quiet=false;
2297 }
3ddb9247 2298
aadceba8 2299 SyncRes::s_minimumTTL = ::arg().asNum("minimum-ttl-override");
2300
4e9a20e6 2301 checkLinuxIPv6Limits();
5a38281c 2302 try {
3ddb9247 2303 vector<string> addrs;
5a38281c
BH
2304 if(!::arg()["query-local-address6"].empty()) {
2305 SyncRes::s_doIPv6=true;
d4fb76e9 2306 L<<Logger::Warning<<"Enabling IPv6 transport for outgoing queries"<<endl;
3ddb9247 2307
5a38281c 2308 stringtok(addrs, ::arg()["query-local-address6"], ", ;");
1dc8f4d0 2309 for(const string& addr : addrs) {
4957a608 2310 g_localQueryAddresses6.push_back(ComboAddress(addr));
5a38281c
BH
2311 }
2312 }
d4fb76e9
BH
2313 else {
2314 L<<Logger::Warning<<"NOT using IPv6 for outgoing queries - set 'query-local-address6=::' to enable"<<endl;
2315 }
5a38281c
BH
2316 addrs.clear();
2317 stringtok(addrs, ::arg()["query-local-address"], ", ;");
1dc8f4d0 2318 for(const string& addr : addrs) {
5a38281c
BH
2319 g_localQueryAddresses4.push_back(ComboAddress(addr));
2320 }
2321 }
2322 catch(std::exception& e) {
2323 L<<Logger::Error<<"Assigning local query addresses: "<<e.what();
2324 exit(99);
f7c1d4e3 2325 }
f555e92e 2326
1051f8a9
BH
2327 SyncRes::s_nopacketcache = ::arg().mustDo("disable-packetcache");
2328
f7c1d4e3 2329 SyncRes::s_maxnegttl=::arg().asNum("max-negative-ttl");
c3e753c7 2330 SyncRes::s_maxcachettl=::arg().asNum("max-cache-ttl");
1051f8a9
BH
2331 SyncRes::s_packetcachettl=::arg().asNum("packetcache-ttl");
2332 SyncRes::s_packetcacheservfailttl=::arg().asNum("packetcache-servfail-ttl");
628e2c7b
PA
2333 SyncRes::s_serverdownmaxfails=::arg().asNum("server-down-max-fails");
2334 SyncRes::s_serverdownthrottletime=::arg().asNum("server-down-throttle-time");
f7c1d4e3 2335 SyncRes::s_serverID=::arg()["server-id"];
173d790e 2336 SyncRes::s_maxqperq=::arg().asNum("max-qperq");
9de3e034 2337 SyncRes::s_maxtotusec=1000*::arg().asNum("max-total-msec");
01402d56 2338 SyncRes::s_rootNXTrust = ::arg().mustDo( "root-nx-trust");
f7c1d4e3
BH
2339 if(SyncRes::s_serverID.empty()) {
2340 char tmp[128];
2341 gethostname(tmp, sizeof(tmp)-1);
2342 SyncRes::s_serverID=tmp;
2343 }
3ddb9247 2344
5b0ddd18 2345 g_networkTimeoutMsec = ::arg().asNum("network-timeout");
bb4bdbaf 2346
49a699c4 2347 g_initialDomainMap = parseAuthAndForwards();
3ddb9247 2348
08f3f638 2349 g_latencyStatSize=::arg().asNum("latency-statistic-size");
3ddb9247 2350
f7c1d4e3 2351 g_logCommonErrors=::arg().mustDo("log-common-errors");
e661a20b
PD
2352
2353 g_anyToTcp = ::arg().mustDo("any-to-tcp");
a09a8ce0
PD
2354 g_udpTruncationThreshold = ::arg().asNum("udp-truncation-threshold");
2355
f7c1d4e3
BH
2356 makeUDPServerSockets();
2357 makeTCPServerSockets();
815099b2 2358
376effcf 2359 parseEDNSSubnetWhitelist(::arg()["edns-subnet-whitelist"]);
2360
677e2a46
BH
2361 int forks;
2362 for(forks = 0; forks < ::arg().asNum("processes") - 1; ++forks) {
1bc3c142
BH
2363 if(!fork()) // we are child
2364 break;
2365 }
3ddb9247 2366
f7c1d4e3
BH
2367 if(::arg().mustDo("daemon")) {
2368 L<<Logger::Warning<<"Calling daemonize, going to background"<<endl;
2369 L.toConsole(Logger::Critical);
f7c1d4e3
BH
2370 daemonize();
2371 }
2372 signal(SIGUSR1,usr1Handler);
2373 signal(SIGUSR2,usr2Handler);
2374 signal(SIGPIPE,SIG_IGN);
a6414fdc 2375 g_numThreads = ::arg().asNum("threads") + ::arg().mustDo("pdns-distributes-queries");
c0063e60 2376 g_numWorkerThreads = ::arg().asNum("threads");
a6414fdc
AT
2377 g_maxMThreads = ::arg().asNum("max-mthreads");
2378 checkOrFixFDS();
3ddb9247 2379
138435cb
BH
2380 int newgid=0;
2381 if(!::arg()["setgid"].empty())
2382 newgid=Utility::makeGidNumeric(::arg()["setgid"]);
2383 int newuid=0;
2384 if(!::arg()["setuid"].empty())
2385 newuid=Utility::makeUidNumeric(::arg()["setuid"]);
2386
f1d6a7ce
KM
2387 Utility::dropGroupPrivs(newuid, newgid);
2388
138435cb
BH
2389 if (!::arg()["chroot"].empty()) {
2390 if (chroot(::arg()["chroot"].c_str())<0 || chdir("/") < 0) {
2391 L<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror (errno)<<", exiting"<<endl;
2392 exit(1);
2393 }
f0f3f0b0
PL
2394 else
2395 L<<Logger::Error<<"Chrooted to '"<<::arg()["chroot"]<<"'"<<endl;
138435cb
BH
2396 }
2397
f0f3f0b0
PL
2398 s_pidfname=::arg()["socket-dir"]+"/"+s_programname+".pid";
2399 if(!s_pidfname.empty())
2400 unlink(s_pidfname.c_str()); // remove possible old pid file
2401 writePid();
2402
2403 makeControlChannelSocket( ::arg().asNum("processes") > 1 ? forks : -1);
2404
f1d6a7ce 2405 Utility::dropUserPrivs(newuid);
c0063e60 2406
49a699c4 2407 makeThreadPipes();
3ddb9247 2408
5d4dd7fe
BH
2409 g_tcpTimeout=::arg().asNum("client-tcp-timeout");
2410 g_maxTCPPerClient=::arg().asNum("max-tcp-per-client");
343257a4 2411
c3828c03 2412 if(g_numThreads == 1) {
76698c6e 2413 L<<Logger::Warning<<"Operating unthreaded"<<endl;
76698c6e
BH
2414 recursorThread(0);
2415 }
2416 else {
2417 pthread_t tid;
c3828c03
BH
2418 L<<Logger::Warning<<"Launching "<< g_numThreads <<" threads"<<endl;
2419 for(unsigned int n=0; n < g_numThreads; ++n) {
77499b05 2420 pthread_create(&tid, 0, recursorThread, (void*)(long)n);
76698c6e
BH
2421 }
2422 void* res;
49a699c4 2423
3ddb9247 2424
76698c6e 2425 pthread_join(tid, &res);
bb4bdbaf 2426 }
bb4bdbaf
BH
2427 return 0;
2428}
2429
2430void* recursorThread(void* ptr)
2431try
2432{
2e2cd8ec 2433 t_id=(int) (long) ptr;
49a699c4 2434 SyncRes tmp(g_now); // make sure it allocates tsstorage before we do anything, like primeHints or so..
ac0e821b 2435 t_sstorage->domainmap = g_initialDomainMap;
49a699c4
BH
2436 t_allowFrom = g_initialAllowFrom;
2437 t_udpclientsocks = new UDPClientSocks();
bd0289fc 2438 t_tcpClientCounts = new tcpClientCounts_t();
49a699c4 2439 primeHints();
3ddb9247 2440
49a699c4 2441 t_packetCache = new RecursorPacketCache();
3ddb9247 2442
49a699c4 2443 L<<Logger::Warning<<"Done priming cache with root hints"<<endl;
3ddb9247 2444
a3e7b735 2445 t_pdl = new shared_ptr<RecursorLua4>();
3ddb9247 2446
674cf0f6
BH
2447 try {
2448 if(!::arg()["lua-dns-script"].empty()) {
a3e7b735 2449 *t_pdl = shared_ptr<RecursorLua4>(new RecursorLua4(::arg()["lua-dns-script"]));
674cf0f6
BH
2450 L<<Logger::Warning<<"Loaded 'lua' script from '"<<::arg()["lua-dns-script"]<<"'"<<endl;
2451 }
674cf0f6
BH
2452 }
2453 catch(std::exception &e) {
2454 L<<Logger::Error<<"Failed to load 'lua' script from '"<<::arg()["lua-dns-script"]<<"': "<<e.what()<<endl;
62f0ae62 2455 _exit(99);
674cf0f6 2456 }
3ddb9247 2457
77499b05 2458 t_traceRegex = new shared_ptr<Regex>();
f8f243b0 2459 unsigned int ringsize=::arg().asNum("stats-ringbuffer-entries") / g_numWorkerThreads;
92011b8f 2460 if(ringsize) {
60c8afa8 2461 t_remotes = new addrringbuf_t();
f8f243b0 2462 if(g_weDistributeQueries) // if so, only 1 thread does recvfrom
3ddb9247 2463 t_remotes->set_capacity(::arg().asNum("stats-ringbuffer-entries"));
f8f243b0 2464 else
3ddb9247 2465 t_remotes->set_capacity(ringsize);
60c8afa8 2466 t_servfailremotes = new addrringbuf_t();
3ddb9247 2467 t_servfailremotes->set_capacity(ringsize);
60c8afa8 2468 t_largeanswerremotes = new addrringbuf_t();
3ddb9247 2469 t_largeanswerremotes->set_capacity(ringsize);
92011b8f 2470
c5c066bf 2471 t_queryring = new boost::circular_buffer<pair<DNSName, uint16_t> >();
3ddb9247 2472 t_queryring->set_capacity(ringsize);
c5c066bf 2473 t_servfailqueryring = new boost::circular_buffer<pair<DNSName, uint16_t> >();
3ddb9247 2474 t_servfailqueryring->set_capacity(ringsize);
92011b8f 2475 }
3ddb9247 2476
bb4bdbaf 2477 MT=new MTasker<PacketID,string>(::arg().asNum("stack-size"));
3ddb9247 2478
bb4bdbaf
BH
2479 PacketID pident;
2480
2481 t_fdm=getMultiplexer();
f3d1d67b 2482 if(!t_id) {
d07bf7ff 2483 if(::arg().mustDo("webserver")) {
30a1aa92 2484 L<<Logger::Warning << "Enabling web server" << endl;
8989097d 2485 try {
1ce57618 2486 new RecursorWebServer(t_fdm);
8989097d
CH
2487 }
2488 catch(PDNSException &e) {
2489 L<<Logger::Error<<"Exception: "<<e.reason<<endl;
2490 exit(99);
2491 }
f3d1d67b 2492 }
83252304 2493 L<<Logger::Error<<"Enabled '"<< t_fdm->getName() << "' multiplexer"<<endl;
f3d1d67b 2494 }
83252304 2495
49a699c4 2496 t_fdm->addReadFD(g_pipes[t_id].readToThread, handlePipeRequest);
83252304 2497
1bc3c142 2498 if(!g_weDistributeQueries || !t_id) // if we distribute queries, only t_id = 0 listens
3ddb9247 2499 for(deferredAdd_t::const_iterator i=deferredAdd.begin(); i!=deferredAdd.end(); ++i)
1bc3c142 2500 t_fdm->addReadFD(i->first, i->second);
3ddb9247 2501
674cf0f6 2502 if(!t_id) {
674cf0f6
BH
2503 t_fdm->addReadFD(s_rcc.d_fd, handleRCC); // control channel
2504 }
1bc3c142 2505
f7c1d4e3 2506 unsigned int maxTcpClients=::arg().asNum("max-tcp-clients");
3ddb9247 2507
f7c1d4e3 2508 bool listenOnTCP(true);
49a699c4 2509
2c78bd57 2510 time_t last_carbon=0;
2511 time_t carbonInterval=::arg().asNum("carbon-interval");
cc59bce6 2512 counter=AtomicCounter(0); // used to periodically execute certain tasks
f7c1d4e3 2513 for(;;) {
ac0e821b 2514 while(MT->schedule(&g_now)); // MTasker letting the mthreads do their thing
3ddb9247 2515
3427fa8a
BH
2516 if(!(counter%500)) {
2517 MT->makeThread(houseKeeping, 0);
f7c1d4e3
BH
2518 }
2519
d2392145 2520 if(!(counter%55)) {
d8f6d49f 2521 typedef vector<pair<int, FDMultiplexer::funcparam_t> > expired_t;
bb4bdbaf 2522 expired_t expired=t_fdm->getTimeouts(g_now);
3ddb9247 2523
f7c1d4e3 2524 for(expired_t::iterator i=expired.begin() ; i != expired.end(); ++i) {
cd989c87 2525 shared_ptr<TCPConnection> conn=any_cast<shared_ptr<TCPConnection> >(i->second);
4957a608 2526 if(g_logCommonErrors)
cd989c87 2527 L<<Logger::Warning<<"Timeout from remote TCP client "<< conn->d_remote.toString() <<endl;
4957a608 2528 t_fdm->removeReadFD(i->first);
f7c1d4e3
BH
2529 }
2530 }
3ddb9247 2531
f7c1d4e3
BH
2532 counter++;
2533
3427fa8a 2534 if(!t_id && statsWanted) {
f7c1d4e3
BH
2535 doStats();
2536 }
2537
2538 Utility::gettimeofday(&g_now, 0);
2c78bd57 2539
2540 if(!t_id && (g_now.tv_sec - last_carbon >= carbonInterval)) {
2541 MT->makeThread(doCarbonDump, 0);
2542 last_carbon = g_now.tv_sec;
2543 }
2544
bb4bdbaf 2545 t_fdm->run(&g_now);
3ea54bf0 2546 // 'run' updates g_now for us
f7c1d4e3 2547
b8ef5c5c 2548 if(!g_weDistributeQueries || !t_id) { // if pdns distributes queries, only tid 0 should do this
5c889cf5 2549 if(listenOnTCP) {
2550 if(TCPConnection::getCurrentConnections() > maxTcpClients) { // shutdown, too many connections
2551 for(tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i)
2552 t_fdm->removeReadFD(*i);
2553 listenOnTCP=false;
2554 }
f7c1d4e3 2555 }
5c889cf5 2556 else {
2557 if(TCPConnection::getCurrentConnections() <= maxTcpClients) { // reenable
2558 for(tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i)
2559 t_fdm->addReadFD(*i, handleNewTCPQuestion);
2560 listenOnTCP=true;
2561 }
f7c1d4e3
BH
2562 }
2563 }
2564 }
2565}
3f81d239 2566catch(PDNSException &ae) {
bb4bdbaf
BH
2567 L<<Logger::Error<<"Exception: "<<ae.reason<<endl;
2568 return 0;
2569}
2570catch(std::exception &e) {
2571 L<<Logger::Error<<"STL Exception: "<<e.what()<<endl;
2572 return 0;
2573}
2574catch(...) {
2575 L<<Logger::Error<<"any other exception in main: "<<endl;
2576 return 0;
2577}
2578
51e2144e 2579
3ddb9247 2580int main(int argc, char **argv)
288f4aa9 2581{
dbd23fc2
BH
2582 g_argc = argc;
2583 g_argv = argv;
5e3de507 2584 g_stats.startupTime=time(0);
3e135495 2585 versionSetProduct(ProductRecursor);
8a63d3ce 2586 reportBasicTypes();
0007c2e5 2587 reportOtherTypes();
ea634573 2588
22030c37 2589 int ret = EXIT_SUCCESS;
caa6eefa 2590
288f4aa9 2591 try {
f888311c 2592 ::arg().set("stack-size","stack size per mthread")="200000";
2e3d8a19 2593 ::arg().set("soa-minimum-ttl","Don't change")="0";
2e3d8a19 2594 ::arg().set("no-shuffle","Don't change")="off";
2e3d8a19 2595 ::arg().set("local-port","port to listen on")="53";
32252594 2596 ::arg().set("local-address","IP addresses to listen on, separated by spaces or commas. Also accepts ports.")="127.0.0.1";
fec7dd5a 2597 ::arg().setSwitch("non-local-bind", "Enable binding to non-local addresses by using FREEBIND / BINDANY socket options")="no";
77499b05 2598 ::arg().set("trace","if we should output heaps of logging. set to 'fail' to only log failing domains")="off";
12ce523e 2599 ::arg().set("dnssec", "DNSSEC mode: off/process (default)/log-fail/validate")="process";
d3f809bf 2600 ::arg().set("daemon","Operate as a daemon")="no";
191f2e47 2601 ::arg().setSwitch("write-pid","Write a PID file")="yes";
34162f8f 2602 ::arg().set("loglevel","Amount of logging. Higher is more. Do not set below 3")="4";
0e9d9ce2 2603 ::arg().set("log-common-errors","If we should log rather common errors")="yes";
2e3d8a19
BH
2604 ::arg().set("chroot","switch to chroot jail")="";
2605 ::arg().set("setgid","If set, change group id to this gid for more security")="";
2606 ::arg().set("setuid","If set, change user id to this uid for more security")="";
5b0ddd18 2607 ::arg().set("network-timeout", "Wait this nummer of milliseconds for network i/o")="1500";
bb4bdbaf 2608 ::arg().set("threads", "Launch this number of threads")="2";
1bc3c142 2609 ::arg().set("processes", "Launch this number of processes (EXPERIMENTAL, DO NOT CHANGE)")="1";
5124de27 2610 ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
d07bf7ff 2611 ::arg().set("api-config-dir", "Directory where REST API stores config and zones") = "";
479e0976
CH
2612 ::arg().set("api-key", "Static pre-shared authentication key for access to the REST API") = "";
2613 ::arg().set("api-logfile", "Location of the server logfile (used by the REST API)") = "/var/log/pdns.log";
2614 ::arg().set("api-readonly", "Disallow data modification through the REST API when set") = "no";
2615 ::arg().setSwitch("webserver", "Start a webserver (for REST API)") = "no";
d07bf7ff
PL
2616 ::arg().set("webserver-address", "IP Address of webserver to listen on") = "127.0.0.1";
2617 ::arg().set("webserver-port", "Port of webserver to listen on") = "8082";
2618 ::arg().set("webserver-password", "Password required for accessing the webserver") = "";
69e7f117 2619 ::arg().set("webserver-allow-from","Webserver access is only allowed from these subnets")="0.0.0.0/0,::/0";
cc08b5a9 2620 ::arg().set("carbon-ourname", "If set, overrides our reported hostname for carbon stats")="";
2c78bd57 2621 ::arg().set("carbon-server", "If set, send metrics in carbon (graphite) format to this server")="";
2622 ::arg().set("carbon-interval", "Number of seconds between carbon (graphite) updates")="30";
c038218b 2623 ::arg().set("quiet","Suppress logging of questions and answers")="";
f27e6356 2624 ::arg().set("logging-facility","Facility to log messages as. 0 corresponds to local0")="";
2e3d8a19 2625 ::arg().set("config-dir","Location of configuration directory (recursor.conf)")=SYSCONFDIR;
fdbf35ac
BH
2626 ::arg().set("socket-owner","Owner of socket")="";
2627 ::arg().set("socket-group","Group of socket")="";
2628 ::arg().set("socket-mode", "Permissions for socket")="";
3ddb9247 2629
f0f3f0b0 2630 ::arg().set("socket-dir",string("Where the controlsocket will live, ")+LOCALSTATEDIR+" when unset and not chrooted" )="";
2e3d8a19
BH
2631 ::arg().set("delegation-only","Which domains we only accept delegations from")="";
2632 ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
d4fb76e9 2633 ::arg().set("query-local-address6","Source IPv6 address for sending queries. IF UNSET, IPv6 WILL NOT BE USED FOR OUTGOING QUERIES")="";
2e3d8a19 2634 ::arg().set("client-tcp-timeout","Timeout in seconds when talking to TCP clients")="2";
85c32340 2635 ::arg().set("max-mthreads", "Maximum number of simultaneous Mtasker threads")="2048";
2e3d8a19 2636 ::arg().set("max-tcp-clients","Maximum number of simultaneous TCP clients")="128";
324dc148 2637 ::arg().set("server-down-max-fails","Maximum number of consecutive timeouts (and unreachables) to mark a server as down ( 0 => disabled )")="64";
979edd70 2638 ::arg().set("server-down-throttle-time","Number of seconds to throttle all queries to a server after being marked as down")="60";
2e3d8a19 2639 ::arg().set("hint-file", "If set, load root hints from this file")="";
b45eb27c 2640 ::arg().set("max-cache-entries", "If set, maximum number of entries in the main cache")="1000000";
a9af3782 2641 ::arg().set("max-negative-ttl", "maximum number of seconds to keep a negative cached entry in memory")="3600";
c3e753c7 2642 ::arg().set("max-cache-ttl", "maximum number of seconds to keep a cached entry in memory")="86400";
1051f8a9 2643 ::arg().set("packetcache-ttl", "maximum number of seconds to keep a cached entry in packetcache")="3600";
927c12b0 2644 ::arg().set("max-packetcache-entries", "maximum number of entries to keep in the packetcache")="500000";
1051f8a9 2645 ::arg().set("packetcache-servfail-ttl", "maximum number of seconds to keep a cached servfail entry in packetcache")="60";
7f7b8d55 2646 ::arg().set("server-id", "Returned when queried for 'server.id' TXT or NSID, defaults to hostname")="";
92011b8f 2647 ::arg().set("stats-ringbuffer-entries", "maximum number of packets to store statistics for")="10000";
ba1a571d 2648 ::arg().set("version-string", "string reported on version.pdns or version.bind")=fullVersionString();
49a699c4 2649 ::arg().set("allow-from", "If set, only allow these comma separated netmasks to recurse")=LOCAL_NETS;
2c95fc65 2650 ::arg().set("allow-from-file", "If set, load allowed netmasks from this file")="";
51e2144e 2651 ::arg().set("entropy-source", "If set, read entropy from this file")="/dev/urandom";
3ddb9247 2652 ::arg().set("dont-query", "If set, do not query these netmasks for DNS data")=DONT_QUERY;
4e120339 2653 ::arg().set("max-tcp-per-client", "If set, maximum number of TCP sessions per client (IP address)")="0";
0d5f0a9f 2654 ::arg().set("spoof-nearmiss-max", "If non-zero, assume spoofing after this many near misses")="20";
4ef015cd 2655 ::arg().set("single-socket", "If set, only use a single socket for outgoing queries")="off";
5605c067 2656 ::arg().set("auth-zones", "Zones for which we have authoritative data, comma separated domain=file pairs ")="";
3e61e7f7 2657 ::arg().set("lua-config-file", "More powerful configuration options")="";
644dd1da 2658
5605c067 2659 ::arg().set("forward-zones", "Zones for which we forward queries, comma separated domain=ip pairs")="";
927c12b0
BH
2660 ::arg().set("forward-zones-recurse", "Zones for which we forward queries with recursion bit, comma separated domain=ip pairs")="";
2661 ::arg().set("forward-zones-file", "File with (+)domain=ip pairs for forwarding")="";
5605c067 2662 ::arg().set("export-etc-hosts", "If we should serve up contents from /etc/hosts")="off";
ac0b4eb3 2663 ::arg().set("export-etc-hosts-search-suffix", "Also serve up the contents of /etc/hosts with this suffix")="";
3ea54bf0 2664 ::arg().set("etc-hosts-file", "Path to 'hosts' file")="/etc/hosts";
9bc8c14c 2665 ::arg().set("serve-rfc1918", "If we should be authoritative for RFC 1918 private IP space")="";
4485aa35 2666 ::arg().set("lua-dns-script", "Filename containing an optional 'lua' script that will be used to modify dns answers")="";
08f3f638 2667 ::arg().set("latency-statistic-size","Number of latency values to calculate the qa-latency average")="10000";
3ddb9247 2668 ::arg().setSwitch( "disable-packetcache", "Disable packetcache" )= "no";
3f975863 2669 ::arg().set("edns-subnet-whitelist", "List of netmasks and domains that we should enable EDNS subnet for")="";
966d3ba8 2670 ::arg().setSwitch( "pdns-distributes-queries", "If PowerDNS itself should distribute queries over threads")="";
cd6310a8 2671 ::arg().setSwitch( "root-nx-trust", "If set, believe that an NXDOMAIN from the root means the TLD does not exist")="no";
e661a20b 2672 ::arg().setSwitch( "any-to-tcp","Answer ANY queries with tc=1, shunting to TCP" )="no";
a09a8ce0 2673 ::arg().set("udp-truncation-threshold", "Maximum UDP response size before we truncate")="1680";
b33c2462 2674 ::arg().set("edns-outgoing-bufsize", "Outgoing EDNS buffer size")="1680";
aadceba8 2675 ::arg().set("minimum-ttl-override", "Set under adverse conditions, a minimum TTL")="0";
173d790e 2676 ::arg().set("max-qperq", "Maximum outgoing queries per query")="50";
c5950146 2677 ::arg().set("max-total-msec", "Maximum total wall-clock time per query in milliseconds, 0 for unlimited")="7000";
a09a8ce0 2678
68e6df3c 2679 ::arg().set("include-dir","Include *.conf files from this directory")="";
d67620e4 2680 ::arg().set("security-poll-suffix","Domain name from which to query security update notifications")="secpoll.powerdns.com.";
2332f42d 2681
2682 ::arg().setSwitch("reuseport","Enable SO_REUSEPORT allowing multiple recursors processes to listen to 1 address")="no";
2e3d8a19
BH
2683
2684 ::arg().setCmd("help","Provide a helpful message");
ba1a571d 2685 ::arg().setCmd("version","Print version string");
d5141417 2686 ::arg().setCmd("config","Output blank configuration");
f27e6356 2687 L.toConsole(Logger::Info);
2e3d8a19 2688 ::arg().laxParse(argc,argv); // do a lax parse
c75a6a9e 2689
2d733c0f
CH
2690 string configname=::arg()["config-dir"]+"/recursor.conf";
2691 if(::arg()["config-name"]!="") {
2692 configname=::arg()["config-dir"]+"/recursor-"+::arg()["config-name"]+".conf";
5124de27 2693 s_programname+="-"+::arg()["config-name"];
2d733c0f
CH
2694 }
2695 cleanSlashes(configname);
5124de27 2696
577cf284
BH
2697 if(::arg().mustDo("config")) {
2698 cout<<::arg().configstring()<<endl;
2699 exit(0);
2700 }
2701
3ddb9247 2702 if(!::arg().file(configname.c_str()))
c75a6a9e
BH
2703 L<<Logger::Warning<<"Unable to parse configuration file '"<<configname<<"'"<<endl;
2704
2e3d8a19 2705 ::arg().parse(argc,argv);
c836dc19 2706
f0f3f0b0
PL
2707 if( !::arg()["chroot"].empty() && !::arg()["api-config-dir"].empty() && !::arg().mustDo("api-readonly") ) {
2708 L<<Logger::Error<<"Using chroot and a writable API is not possible"<<endl;
2709 exit(EXIT_FAILURE);
2710 }
2711
2712 if (::arg()["socket-dir"].empty()) {
2713 if (::arg()["chroot"].empty())
2714 ::arg().set("socket-dir") = LOCALSTATEDIR;
2715 else
2716 ::arg().set("socket-dir") = "/";
2717 }
2718
2e3d8a19 2719 ::arg().set("delegation-only")=toLower(::arg()["delegation-only"]);
562588a3 2720
61d74169 2721 if(::arg().asNum("threads")==1)
2722 ::arg().set("pdns-distributes-queries")="no";
2723
2e3d8a19 2724 if(::arg().mustDo("help")) {
ff5ba4f9
WA
2725 cout<<"syntax:"<<endl<<endl;
2726 cout<<::arg().helpstring(::arg()["help"])<<endl;
2727 exit(0);
b636533b 2728 }
5e3de507 2729 if(::arg().mustDo("version")) {
ba1a571d 2730 showProductVersion();
3613a51c 2731 showBuildConfiguration();
5e3de507
BH
2732 exit(99);
2733 }
b636533b 2734
34162f8f 2735 Logger::Urgency logUrgency = (Logger::Urgency)::arg().asNum("loglevel");
f48d7b65 2736
34162f8f
CH
2737 if (logUrgency < Logger::Error)
2738 logUrgency = Logger::Error;
f48d7b65 2739 if(!g_quiet && logUrgency < Logger::Info) { // Logger::Info=6, Logger::Debug=7
2740 logUrgency = Logger::Info; // if you do --quiet=no, you need Info to also see the query log
2741 }
34162f8f
CH
2742 L.setLoglevel(logUrgency);
2743 L.toConsole(logUrgency);
2744
f7c1d4e3 2745 serviceMain(argc, argv);
288f4aa9 2746 }
3f81d239 2747 catch(PDNSException &ae) {
c836dc19 2748 L<<Logger::Error<<"Exception: "<<ae.reason<<endl;
22030c37 2749 ret=EXIT_FAILURE;
288f4aa9 2750 }
fdbf35ac 2751 catch(std::exception &e) {
c836dc19 2752 L<<Logger::Error<<"STL Exception: "<<e.what()<<endl;
22030c37 2753 ret=EXIT_FAILURE;
288f4aa9
BH
2754 }
2755 catch(...) {
c836dc19 2756 L<<Logger::Error<<"any other exception in main: "<<endl;
22030c37 2757 ret=EXIT_FAILURE;
288f4aa9 2758 }
3ddb9247 2759
22030c37 2760 return ret;
288f4aa9 2761}