]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/pdns_recursor.cc
adapt udp-truncation-threshold flag to the recursor and document it
[thirdparty/pdns.git] / pdns / pdns_recursor.cc
CommitLineData
288f4aa9
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
77499b05 3 Copyright (C) 2003 - 2013 PowerDNS.COM BV
288f4aa9
BH
4
5 This program is free software; you can redistribute it and/or modify
f28307ad
BH
6 it under the terms of the GNU General Public License version 2
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
76473b92
KM
23#include <netdb.h>
24#include <sys/stat.h>
25#include <unistd.h>
5a38281c 26#include <boost/foreach.hpp>
f3d1d67b 27#include "json_ws.hh"
49a699c4 28#include <pthread.h>
3ea54bf0 29#include "recpacketcache.hh"
caa6eefa 30#include "utility.hh"
51e2144e 31#include "dns_random.hh"
288f4aa9
BH
32#include <iostream>
33#include <errno.h>
34#include <map>
35#include <set>
97bb160b 36#include "recursor_cache.hh"
38c9ceaa 37#include "cachecleaner.hh"
288f4aa9 38#include <stdio.h>
c75a6a9e 39#include <signal.h>
288f4aa9 40#include <stdlib.h>
bb4bdbaf 41#include "misc.hh"
288f4aa9
BH
42#include "mtasker.hh"
43#include <utility>
288f4aa9
BH
44#include "arguments.hh"
45#include "syncres.hh"
88def049
BH
46#include <fcntl.h>
47#include <fstream>
5c633640
BH
48#include "sstuff.hh"
49#include <boost/tuple/tuple.hpp>
50#include <boost/tuple/tuple_comparison.hpp>
72df400f 51#include <boost/shared_array.hpp>
ea634573 52#include <boost/lexical_cast.hpp>
7f1fa77d 53#include <boost/function.hpp>
5605c067 54#include <boost/algorithm/string.hpp>
40a3dd64 55#include <netinet/tcp.h>
ea634573
BH
56#include "dnsparser.hh"
57#include "dnswriter.hh"
58#include "dnsrecords.hh"
f814d7c8 59#include "zoneparser-tng.hh"
1d5b3ce6 60#include "rec_channel.hh"
aaacf7f2 61#include "logger.hh"
c8ddb7c2 62#include "iputils.hh"
09e6702a 63#include "mplexer.hh"
c038218b 64#include "config.h"
5704e107 65#include "lua-recursor.hh"
ba1a571d 66#include "version.hh"
1d5b3ce6 67
a2bfc3ff
BH
68#ifndef RECURSOR
69#include "statbag.hh"
70StatBag S;
71#endif
72
bb4bdbaf 73__thread FDMultiplexer* t_fdm;
674cf0f6 74__thread unsigned int t_id;
09e6702a 75unsigned int g_maxTCPPerClient;
5b0ddd18 76unsigned int g_networkTimeoutMsec;
09e6702a 77bool g_logCommonErrors;
e661a20b 78bool g_anyToTcp;
a09a8ce0 79uint16_t g_udpTruncationThreshold;
5704e107 80__thread shared_ptr<RecursorLua>* t_pdl;
b3b5459d 81__thread RemoteKeeper* t_remotes;
77499b05 82__thread shared_ptr<Regex>* t_traceRegex;
674cf0f6 83
d7dae798
BH
84RecursorControlChannel s_rcc; // only active in thread 0
85
86// for communicating with our threads
49a699c4
BH
87struct ThreadPipeSet
88{
89 int writeToThread;
90 int readToThread;
91 int writeFromThread;
92 int readFromThread;
93};
3ea54bf0 94
d7dae798 95vector<ThreadPipeSet> g_pipes; // effectively readonly after startup
5c633640 96
d7dae798 97SyncRes::domainmap_t* g_initialDomainMap; // new threads needs this to be setup
49a699c4
BH
98
99#include "namespaces.hh"
3ea54bf0 100
49a699c4 101__thread MemRecursorCache* t_RC;
16beeaa4 102__thread RecursorPacketCache* t_packetCache;
1d5b3ce6
BH
103RecursorStats g_stats;
104bool g_quiet;
49a699c4 105
1bc3c142
BH
106bool g_weDistributeQueries; // if true, only 1 thread listens on the incoming query sockets
107
49a699c4
BH
108static __thread NetmaskGroup* t_allowFrom;
109static NetmaskGroup* g_initialAllowFrom; // new thread needs to be setup with this
110
eb5bae86 111NetmaskGroup* g_dontQuery;
5124de27 112string s_programname="recursor";
49a699c4 113
40a3dd64
BH
114typedef vector<int> tcpListenSockets_t;
115tcpListenSockets_t g_tcpListenSockets; // shared across threads, but this is fine, never written to from a thread. All threads listen on all sockets
3159c9ef 116int g_tcpTimeout;
85c32340 117unsigned int g_maxMThreads;
d7dae798 118struct timeval g_now; // timestamp, updated (too) frequently
40a3dd64 119map<int, ComboAddress> g_listenSocketsAddresses; // is shared across all threads right now
18af64a8 120
d7dae798
BH
121__thread MT_t* MT; // the big MTasker
122
c3828c03
BH
123unsigned int g_numThreads;
124
df14d9f8 125#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, fe80::/10"
49a699c4 126
d7dae798 127//! used to send information to a newborn mthread
ea634573 128struct DNSComboWriter {
3ea54bf0 129 DNSComboWriter(const char* data, uint16_t len, const struct timeval& now) : d_mdp(data, len), d_now(now),
232f0877 130 d_tcp(false), d_socket(-1)
ea634573
BH
131 {}
132 MOADNSParser d_mdp;
00c9b8c1 133 void setRemote(const ComboAddress* sa)
ea634573 134 {
37d3f960 135 d_remote=*sa;
ea634573
BH
136 }
137
138 void setSocket(int sock)
139 {
140 d_socket=sock;
141 }
a1754c6a
BH
142
143 string getRemote() const
144 {
37d3f960 145 return d_remote.toString();
a1754c6a
BH
146 }
147
c9e9e5e0 148 struct timeval d_now;
37d3f960 149 ComboAddress d_remote;
ea634573
BH
150 bool d_tcp;
151 int d_socket;
cd989c87 152 shared_ptr<TCPConnection> d_tcpConnection;
ea634573
BH
153};
154
155
288f4aa9
BH
156ArgvMap &arg()
157{
158 static ArgvMap theArg;
159 return theArg;
160}
4ef015cd 161
09e6702a 162
d8f6d49f 163void handleTCPClientWritable(int fd, FDMultiplexer::funcparam_t& var);
09e6702a 164
50c81227 165// -1 is error, 0 is timeout, 1 is success
5c633640
BH
166int asendtcp(const string& data, Socket* sock)
167{
168 PacketID pident;
169 pident.sock=sock;
170 pident.outMSG=data;
23db0a09 171
bb4bdbaf 172 t_fdm->addWriteFD(sock->getHandle(), handleTCPClientWritable, pident);
50c81227 173 string packet;
5c633640 174
5b0ddd18 175 int ret=MT->waitEvent(pident, &packet, g_networkTimeoutMsec);
23db0a09 176
9170fbaf 177 if(!ret || ret==-1) { // timeout
bb4bdbaf 178 t_fdm->removeWriteFD(sock->getHandle());
5c633640 179 }
50c81227
BH
180 else if(packet.size() !=data.size()) { // main loop tells us what it sent out, or empty in case of an error
181 return -1;
182 }
9170fbaf 183 return ret;
5c633640
BH
184}
185
d8f6d49f 186void handleTCPClientReadable(int fd, FDMultiplexer::funcparam_t& var);
09e6702a 187
9170fbaf 188// -1 is error, 0 is timeout, 1 is success
5c633640 189int arecvtcp(string& data, int len, Socket* sock)
288f4aa9 190{
50c81227 191 data.clear();
5c633640
BH
192 PacketID pident;
193 pident.sock=sock;
194 pident.inNeeded=len;
bb4bdbaf 195 t_fdm->addReadFD(sock->getHandle(), handleTCPClientReadable, pident);
5c633640 196
bb4bdbaf 197 int ret=MT->waitEvent(pident,&data, g_networkTimeoutMsec);
9170fbaf 198 if(!ret || ret==-1) { // timeout
bb4bdbaf 199 t_fdm->removeReadFD(sock->getHandle());
288f4aa9 200 }
50c81227
BH
201 else if(data.empty()) {// error, EOF or other
202 return -1;
203 }
204
9170fbaf 205 return ret;
288f4aa9
BH
206}
207
5a38281c 208vector<ComboAddress> g_localQueryAddresses4, g_localQueryAddresses6;
046c5a5d 209const ComboAddress g_local4("0.0.0.0"), g_local6("::");
1652a63e 210
d7dae798 211//! pick a random query local address
1652a63e 212ComboAddress getQueryLocalAddress(int family, uint16_t port)
5a38281c 213{
1652a63e 214 ComboAddress ret;
5a38281c 215 if(family==AF_INET) {
1652a63e
BH
216 if(g_localQueryAddresses4.empty())
217 ret = g_local4;
218 else
219 ret = g_localQueryAddresses4[dns_random(g_localQueryAddresses4.size())];
220 ret.sin4.sin_port = htons(port);
5a38281c
BH
221 }
222 else {
223 if(g_localQueryAddresses6.empty())
1652a63e
BH
224 ret = g_local6;
225 else
226 ret = g_localQueryAddresses6[dns_random(g_localQueryAddresses6.size())];
227
228 ret.sin6.sin6_port = htons(port);
5a38281c 229 }
1652a63e 230 return ret;
5a38281c 231}
4ef015cd 232
d8f6d49f 233void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t&);
09e6702a 234
d7dae798
BH
235void setSocketBuffer(int fd, int optname, uint32_t size)
236{
237 uint32_t psize=0;
238 socklen_t len=sizeof(psize);
239
240 if(!getsockopt(fd, SOL_SOCKET, optname, (char*)&psize, &len) && psize > size) {
241 L<<Logger::Error<<"Not decreasing socket buffer size from "<<psize<<" to "<<size<<endl;
242 return;
243 }
244
245 if (setsockopt(fd, SOL_SOCKET, optname, (char*)&size, sizeof(size)) < 0 )
246 L<<Logger::Error<<"Warning: unable to raise socket buffer size to "<<size<<": "<<strerror(errno)<<endl;
247}
248
249
250static void setSocketReceiveBuffer(int fd, uint32_t size)
251{
252 setSocketBuffer(fd, SO_RCVBUF, size);
253}
254
255static void setSocketSendBuffer(int fd, uint32_t size)
256{
257 setSocketBuffer(fd, SO_SNDBUF, size);
258}
259
260
4ef015cd
BH
261// you can ask this class for a UDP socket to send a query from
262// this socket is not yours, don't even think about deleting it
263// but after you call 'returnSocket' on it, don't assume anything anymore
264class UDPClientSocks
265{
4ef015cd
BH
266 unsigned int d_numsocks;
267 unsigned int d_maxsocks;
268public:
998a4334 269 UDPClientSocks() : d_numsocks(0), d_maxsocks(5000)
4ef015cd
BH
270 {
271 }
272
996c89cc 273 typedef set<int> socks_t;
4ef015cd
BH
274 socks_t d_socks;
275
d8f6d49f
BH
276 // returning -1 means: temporary OS error (ie, out of files), -2 means OS error
277 int getSocket(const ComboAddress& toaddr, int* fd)
4ef015cd 278 {
d8f6d49f
BH
279 *fd=makeClientSocket(toaddr.sin4.sin_family);
280 if(*fd < 0) // temporary error - receive exception otherwise
281 return -1;
282
283 if(connect(*fd, (struct sockaddr*)(&toaddr), toaddr.getSocklen()) < 0) {
284 int err = errno;
41ff43f8
BH
285 // returnSocket(*fd);
286 Utility::closesocket(*fd);
d8f6d49f 287 if(err==ENETUNREACH) // Seth "My Interfaces Are Like A Yo Yo" Arnold special
4957a608 288 return -2;
998a4334 289 return -1;
d8f6d49f 290 }
998a4334 291
d8f6d49f 292 d_socks.insert(*fd);
998a4334 293 d_numsocks++;
d8f6d49f 294 return 0;
4ef015cd
BH
295 }
296
095c3045
BH
297 void returnSocket(int fd)
298 {
299 socks_t::iterator i=d_socks.find(fd);
34801ab1 300 if(i==d_socks.end()) {
3f81d239 301 throw PDNSException("Trying to return a socket (fd="+lexical_cast<string>(fd)+") not in the pool");
34801ab1 302 }
bb4bdbaf 303 returnSocketLocked(i);
095c3045
BH
304 }
305
4ef015cd 306 // return a socket to the pool, or simply erase it
bb4bdbaf 307 void returnSocketLocked(socks_t::iterator& i)
4ef015cd 308 {
600fc20b 309 if(i==d_socks.end()) {
3f81d239 310 throw PDNSException("Trying to return a socket not in the pool");
600fc20b 311 }
80baf329 312 try {
bb4bdbaf 313 t_fdm->removeReadFD(*i);
80baf329
BH
314 }
315 catch(FDMultiplexerException& e) {
bb4bdbaf 316 // we sometimes return a socket that has not yet been assigned to t_fdm
80baf329 317 }
c038218b 318 Utility::closesocket(*i);
998a4334
BH
319
320 d_socks.erase(i++);
321 --d_numsocks;
4ef015cd 322 }
d8f6d49f
BH
323
324 // returns -1 for errors which might go away, throws for ones that won't
bb4bdbaf 325 static int makeClientSocket(int family)
d8f6d49f
BH
326 {
327 int ret=(int)socket(family, SOCK_DGRAM, 0);
42c235e5 328
d8f6d49f
BH
329 if(ret < 0 && errno==EMFILE) // this is not a catastrophic error
330 return ret;
331
332 if(ret<0)
3f81d239 333 throw PDNSException("Making a socket for resolver (family = "+lexical_cast<string>(family)+"): "+stringerror());
36855b53
BH
334
335 Utility::setCloseOnExec(ret);
5a38281c 336
d8f6d49f
BH
337 int tries=10;
338 while(--tries) {
1652a63e
BH
339 uint16_t port;
340
d8f6d49f 341 if(tries==1) // fall back to kernel 'random'
4957a608 342 port = 0;
1652a63e
BH
343 else
344 port = 1025 + dns_random(64510);
345
346 ComboAddress sin=getQueryLocalAddress(family, port); // does htons for us
5a38281c 347
5a38281c 348 if (::bind(ret, (struct sockaddr *)&sin, sin.getSocklen()) >= 0)
4957a608 349 break;
d8f6d49f
BH
350 }
351 if(!tries)
3f81d239 352 throw PDNSException("Resolver binding to local query client socket: "+stringerror());
d8f6d49f
BH
353
354 Utility::setNonBlocking(ret);
355 return ret;
356 }
49a699c4
BH
357};
358
359static __thread UDPClientSocks* t_udpclientsocks;
4ef015cd 360
288f4aa9 361/* these two functions are used by LWRes */
34801ab1 362// -2 is OS error, -1 is error that depends on the remote, > 0 is success
787e5eab 363int asendto(const char *data, int len, int flags,
4957a608 364 const ComboAddress& toaddr, uint16_t id, const string& domain, uint16_t qtype, int* fd)
288f4aa9 365{
34801ab1
BH
366
367 PacketID pident;
787e5eab
BH
368 pident.domain = domain;
369 pident.remote = toaddr;
370 pident.type = qtype;
34801ab1
BH
371
372 // see if there is an existing outstanding request we can chain on to, using partial equivalence function
373 pair<MT_t::waiters_t::iterator, MT_t::waiters_t::iterator> chain=MT->d_waiters.equal_range(pident, PacketIDBirthdayCompare());
374
375 for(; chain.first != chain.second; chain.first++) {
376 if(chain.first->key.fd > -1) { // don't chain onto existing chained waiter!
e27e91a8 377 /*
4665c31e
BH
378 cerr<<"Orig: "<<pident.domain<<", "<<pident.remote.toString()<<", id="<<id<<endl;
379 cerr<<"Had hit: "<< chain.first->key.domain<<", "<<chain.first->key.remote.toString()<<", id="<<chain.first->key.id
4957a608 380 <<", count="<<chain.first->key.chain.size()<<", origfd: "<<chain.first->key.fd<<endl;
e27e91a8 381 */
34801ab1
BH
382 chain.first->key.chain.insert(id); // we can chain
383 *fd=-1; // gets used in waitEvent / sendEvent later on
384 return 1;
385 }
386 }
387
49a699c4 388 int ret=t_udpclientsocks->getSocket(toaddr, fd);
d8f6d49f
BH
389 if(ret < 0)
390 return ret;
34801ab1 391
998a4334
BH
392 pident.fd=*fd;
393 pident.id=id;
998a4334 394
bb4bdbaf
BH
395 t_fdm->addReadFD(*fd, handleUDPServerResponse, pident);
396 ret = send(*fd, data, len, 0);
397
5b0ddd18 398 int tmp = errno;
bb4bdbaf 399
7302ed0a 400 if(ret < 0)
49a699c4 401 t_udpclientsocks->returnSocket(*fd);
bb4bdbaf 402
5b0ddd18 403 errno = tmp; // this is for logging purposes only
7302ed0a 404 return ret;
288f4aa9
BH
405}
406
9170fbaf 407// -1 is error, 0 is timeout, 1 is success
787e5eab 408int arecvfrom(char *data, int len, int flags, const ComboAddress& fromaddr, int *d_len,
4957a608 409 uint16_t id, const string& domain, uint16_t qtype, int fd, struct timeval* now)
288f4aa9 410{
0d5f0a9f
BH
411 static optional<unsigned int> nearMissLimit;
412 if(!nearMissLimit)
413 nearMissLimit=::arg().asNum("spoof-nearmiss-max");
414
288f4aa9 415 PacketID pident;
4ef015cd 416 pident.fd=fd;
288f4aa9 417 pident.id=id;
0d5f0a9f 418 pident.domain=domain;
787e5eab 419 pident.type = qtype;
996c89cc 420 pident.remote=fromaddr;
b636533b 421
288f4aa9 422 string packet;
5b0ddd18 423 int ret=MT->waitEvent(pident, &packet, g_networkTimeoutMsec, now);
34801ab1 424
9170fbaf 425 if(ret > 0) {
996c89cc 426 if(packet.empty()) // means "error"
998a4334 427 return -1;
998a4334 428
705f31ae 429 *d_len=(int)packet.size();
9170fbaf 430 memcpy(data,packet.c_str(),min(len,*d_len));
0d5f0a9f 431 if(*nearMissLimit && pident.nearMisses > *nearMissLimit) {
996c89cc 432 L<<Logger::Error<<"Too many ("<<pident.nearMisses<<" > "<<*nearMissLimit<<") bogus answers for '"<<domain<<"' from "<<fromaddr.toString()<<", assuming spoof attempt."<<endl;
0d5f0a9f 433 g_stats.spoofCount++;
35ce8576
BH
434 return -1;
435 }
288f4aa9 436 }
09e6702a 437 else {
34801ab1 438 if(fd >= 0)
49a699c4 439 t_udpclientsocks->returnSocket(fd);
09e6702a 440 }
9170fbaf 441 return ret;
288f4aa9
BH
442}
443
aa4e4cbf 444
87a5ea63 445string s_pidfname;
88def049
BH
446static void writePid(void)
447{
18e7758c 448 ofstream of(s_pidfname.c_str(), std::ios_base::app);
88def049 449 if(of)
705f31ae 450 of<< Utility::getpid() <<endl;
88def049 451 else
87a5ea63 452 L<<Logger::Error<<"Requested to write pid for "<<Utility::getpid()<<" to "<<s_pidfname<<" failed: "<<strerror(errno)<<endl;
88def049
BH
453}
454
bd0289fc
BH
455typedef map<ComboAddress, uint32_t, ComboAddress::addressOnlyLessThan> tcpClientCounts_t;
456tcpClientCounts_t __thread* t_tcpClientCounts;
0e9d9ce2 457
cd989c87
BH
458TCPConnection::TCPConnection(int fd, const ComboAddress& addr) : d_remote(addr), d_fd(fd)
459{
1bc9e6bd 460 ++s_currentConnections;
cd989c87 461 (*t_tcpClientCounts)[d_remote]++;
0e408828 462}
cd989c87
BH
463
464TCPConnection::~TCPConnection()
0e408828 465{
cd989c87
BH
466 if(Utility::closesocket(d_fd) < 0)
467 unixDie("closing socket for TCPConnection");
468 if(t_tcpClientCounts->count(d_remote) && !(*t_tcpClientCounts)[d_remote]--)
469 t_tcpClientCounts->erase(d_remote);
1bc9e6bd 470 --s_currentConnections;
0e408828 471}
0e9d9ce2 472
1bc9e6bd 473AtomicCounter TCPConnection::s_currentConnections;
d8f6d49f 474void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var);
6dcd28c3 475
2cc13433
BH
476void updateRcodeStats(int res)
477{
478 switch(res) {
479 case RCode::ServFail:
480 g_stats.servFails++;
481 break;
482 case RCode::NXDomain:
483 g_stats.nxDomains++;
484 break;
485 case RCode::NoError:
486 g_stats.noErrors++;
487 break;
488 }
489}
490
288f4aa9
BH
491void startDoResolve(void *p)
492{
7b1469bb 493 DNSComboWriter* dc=(DNSComboWriter *)p;
0fb1501b 494 string loginfo="";
b23b8614 495
288f4aa9 496 try {
0fb1501b
PD
497 loginfo=" (while setting loginfo)";
498 loginfo=" ("+dc->d_mdp.d_qname+"/"+lexical_cast<string>(dc->d_mdp.d_qtype)+" from "+(dc->d_remote.toString())+")";
dffbaa08 499 uint32_t maxanswersize= dc->d_tcp ? 65535 : 512;
7f7b8d55
BH
500 EDNSOpts edo;
501 if(getEDNSOpts(dc->d_mdp, &edo)) {
a09a8ce0 502 maxanswersize = min(edo.d_packetsize, (uint16_t) (dc->d_tcp ? 65535 : g_udpTruncationThreshold));
10321a98 503 }
09e6702a 504
ea634573 505 vector<DNSResourceRecord> ret;
ea634573 506 vector<uint8_t> packet;
b23b8614
BH
507
508 DNSPacketWriter pw(packet, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass);
ea634573
BH
509
510 pw.getHeader()->aa=0;
511 pw.getHeader()->ra=1;
c154c8a4 512 pw.getHeader()->qr=1;
bb4bdbaf 513 pw.getHeader()->tc=0;
ea634573 514 pw.getHeader()->id=dc->d_mdp.d_header.id;
10321a98 515 pw.getHeader()->rd=dc->d_mdp.d_header.rd;
ea634573 516
904d3219
PD
517 uint32_t minTTL=std::numeric_limits<uint32_t>::max();
518
519 SyncRes sr(dc->d_now);
520 bool tracedQuery=false; // we could consider letting Lua know about this too
521 bool variableAnswer = false;
522
e661a20b
PD
523 if(dc->d_mdp.d_qtype==QType::ANY && !dc->d_tcp && g_anyToTcp) {
524 pw.getHeader()->tc=1;
525 goto sendit;
526 }
527
77499b05
BH
528 if(t_traceRegex->get() && (*t_traceRegex)->match(dc->d_mdp.d_qname)) {
529 sr.setLogMode(SyncRes::Store);
530 tracedQuery=true;
531 }
532
533 if(!g_quiet || tracedQuery)
534 L<<Logger::Warning<<t_id<<" ["<<MT->getTid()<<"] " << (dc->d_tcp ? "TCP " : "") << "question for '"<<dc->d_mdp.d_qname<<"|"
8a63d3ce 535 <<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)<<"' from "<<dc->getRemote()<<endl;
c75a6a9e 536
fededf47 537 sr.setId(MT->getTid());
67828389 538 if(!dc->d_mdp.d_header.rd)
c836dc19
BH
539 sr.setCacheOnly();
540
4485aa35
BH
541 int res;
542
5704e107 543 // if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve
99c69ed3 544 if(!t_pdl->get() || !(*t_pdl)->preresolve(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer)) {
4485aa35
BH
545 res = sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret);
546
674cf0f6 547 if(t_pdl->get()) {
bd53ea9d 548 if(res == RCode::NoError) {
232f0877
CH
549 vector<DNSResourceRecord>::const_iterator i;
550 for(i=ret.begin(); i!=ret.end(); ++i)
551 if(i->qtype.getCode() == dc->d_mdp.d_qtype && i->d_place == DNSResourceRecord::ANSWER)
552 break;
553 if(i == ret.end())
554 (*t_pdl)->nodata(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
555 }
556 else if(res == RCode::NXDomain)
99c69ed3 557 (*t_pdl)->nxdomain(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
bd53ea9d
PD
558
559 (*t_pdl)->postresolve(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
d2322a5e 560 }
4485aa35 561 }
99c69ed3 562
77499b05 563
0fe1d080 564 if(tracedQuery || res < 0 || res == RCode::ServFail || pw.getHeader()->rcode == RCode::ServFail)
85ffbc53 565 {
85ffbc53
PD
566 string trace(sr.getTrace());
567 if(!trace.empty()) {
568 vector<string> lines;
569 boost::split(lines, trace, boost::is_any_of("\n"));
570 BOOST_FOREACH(const string& line, lines) {
571 if(!line.empty())
572 L<<Logger::Warning<< line << endl;
573 }
574 }
575 }
0fe1d080
PD
576
577 if(res < 0) {
578 pw.getHeader()->rcode=RCode::ServFail;
579 // no commit here, because no record
580 g_stats.servFails++;
581 }
288f4aa9 582 else {
ea634573 583 pw.getHeader()->rcode=res;
2cc13433 584 updateRcodeStats(res);
77499b05 585
c154c8a4 586 if(ret.size()) {
92476c8b 587 orderAndShuffle(ret);
4957a608 588
4957a608
BH
589 for(vector<DNSResourceRecord>::const_iterator i=ret.begin(); i!=ret.end(); ++i) {
590 pw.startRecord(i->qname, i->qtype.getCode(), i->ttl, i->qclass, (DNSPacketWriter::Place)i->d_place);
591 minTTL = min(minTTL, i->ttl);
592 if(i->qtype.getCode() == QType::A) { // blast out A record w/o doing whole dnswriter thing
593 uint32_t ip=0;
594 IpToU32(i->content, &ip);
595 pw.xfr32BitInt(htonl(ip));
596 } else {
597 shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(i->qtype.getCode(), i->qclass, i->content));
598 drc->toPacket(pw);
599 }
dffbaa08 600 if(pw.size() > maxanswersize) {
4957a608
BH
601 pw.rollback();
602 if(i->d_place==DNSResourceRecord::ANSWER) // only truncate if we actually omitted parts of the answer
add935a2 603 {
4957a608 604 pw.getHeader()->tc=1;
add935a2
PD
605 pw.truncate();
606 }
4957a608
BH
607 goto sendit; // need to jump over pw.commit
608 }
609 }
b23b8614 610
18af64a8 611 pw.commit();
ea634573 612 }
288f4aa9 613 }
10321a98 614 sendit:;
ea634573 615 if(!dc->d_tcp) {
c038218b 616 sendto(dc->d_socket, (const char*)&*packet.begin(), packet.size(), 0, (struct sockaddr *)(&dc->d_remote), dc->d_remote.getSocklen());
99c69ed3 617 if(!SyncRes::s_nopacketcache && !variableAnswer ) {
49a699c4 618 t_packetCache->insertResponsePacket(string((const char*)&*packet.begin(), packet.size()), g_now.tv_sec,
232f0877
CH
619 min(minTTL,
620 (pw.getHeader()->rcode == RCode::ServFail) ? SyncRes::s_packetcacheservfailttl : SyncRes::s_packetcachettl
621 )
622 );
1051f8a9 623 }
feccc9fc 624 }
9c495589
BH
625 else {
626 char buf[2];
ea634573
BH
627 buf[0]=packet.size()/256;
628 buf[1]=packet.size()%256;
feccc9fc 629
c038218b 630 Utility::iovec iov[2];
feccc9fc 631
ea634573
BH
632 iov[0].iov_base=(void*)buf; iov[0].iov_len=2;
633 iov[1].iov_base=(void*)&*packet.begin(); iov[1].iov_len = packet.size();
feccc9fc 634
c038218b 635 int ret=Utility::writev(dc->d_socket, iov, 2);
0e9d9ce2 636 bool hadError=true;
feccc9fc 637
0e9d9ce2 638 if(ret == 0)
18af64a8 639 L<<Logger::Error<<"EOF writing TCP answer to "<<dc->getRemote()<<endl;
0e9d9ce2 640 else if(ret < 0 )
18af64a8 641 L<<Logger::Error<<"Error writing TCP answer to "<<dc->getRemote()<<": "<< strerror(errno) <<endl;
ea634573 642 else if((unsigned int)ret != 2 + packet.size())
18af64a8 643 L<<Logger::Error<<"Oops, partial answer sent to "<<dc->getRemote()<<" for "<<dc->d_mdp.d_qname<<" (size="<< (2 + packet.size()) <<", sent "<<ret<<")"<<endl;
0e9d9ce2 644 else
18af64a8 645 hadError=false;
09e6702a
BH
646
647 // update tcp connection status, either by closing or moving to 'BYTE0'
18af64a8 648
09e6702a 649 if(hadError) {
18af64a8 650 // no need to remove us from FDM, we weren't there
c36bc97a 651 dc->d_socket = -1;
09e6702a 652 }
a6ae6414 653 else {
cd989c87 654 dc->d_tcpConnection->state=TCPConnection::BYTE0;
18af64a8 655 Utility::gettimeofday(&g_now, 0); // needs to be updated
cd989c87
BH
656 t_fdm->addReadFD(dc->d_socket, handleRunningTCPQuestion, dc->d_tcpConnection);
657 t_fdm->setReadTTD(dc->d_socket, g_now, g_tcpTimeout);
0e9d9ce2 658 }
9c495589 659 }
b23b8614 660
1d5b3ce6 661 if(!g_quiet) {
bb4bdbaf 662 L<<Logger::Error<<t_id<<" ["<<MT->getTid()<<"] answer to "<<(dc->d_mdp.d_header.rd?"":"non-rd ")<<"question '"<<dc->d_mdp.d_qname<<"|"<<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype);
ea634573 663 L<<"': "<<ntohs(pw.getHeader()->ancount)<<" answers, "<<ntohs(pw.getHeader()->arcount)<<" additional, took "<<sr.d_outqueries<<" packets, "<<
18af64a8 664 sr.d_throttledqueries<<" throttled, "<<sr.d_timeouts<<" timeouts, "<<sr.d_tcpoutqueries<<" tcp connections, rcode="<<res<<endl;
c75a6a9e 665 }
b23b8614 666
49a699c4 667 sr.d_outqueries ? t_RC->cacheMisses++ : t_RC->cacheHits++;
fe213470
BH
668 float spent=makeFloat(sr.d_now-dc->d_now);
669 if(spent < 0.001)
670 g_stats.answers0_1++;
671 else if(spent < 0.010)
672 g_stats.answers1_10++;
673 else if(spent < 0.1)
674 g_stats.answers10_100++;
675 else if(spent < 1.0)
676 g_stats.answers100_1000++;
677 else
678 g_stats.answersSlow++;
679
574af7ea 680 uint64_t newLat=(uint64_t)(spent*1000000);
87b8e43a
BH
681 if(newLat < 1000000) // outliers of several minutes exist..
682 g_stats.avgLatencyUsec=(uint64_t)((1-0.0001)*g_stats.avgLatencyUsec + 0.0001*newLat);
b23b8614 683
ea634573 684 delete dc;
c36bc97a 685 dc=0;
288f4aa9 686 }
3f81d239 687 catch(PDNSException &ae) {
0fb1501b 688 L<<Logger::Error<<"startDoResolve problem"<<loginfo<<": "<<ae.reason<<endl;
c36bc97a 689 delete dc;
288f4aa9 690 }
7b1469bb 691 catch(MOADNSException& e) {
0fb1501b 692 L<<Logger::Error<<"DNS parser error"<<loginfo<<": "<<dc->d_mdp.d_qname<<", "<<e.what()<<endl;
c36bc97a 693 delete dc;
7b1469bb 694 }
fdbf35ac 695 catch(std::exception& e) {
0fb1501b 696 L<<Logger::Error<<"STL error"<<loginfo<<": "<<e.what()<<endl;
c36bc97a 697 delete dc;
c154c8a4 698 }
288f4aa9 699 catch(...) {
0fb1501b 700 L<<Logger::Error<<"Any other exception in a resolver context"<<loginfo<<endl;
288f4aa9 701 }
ec6eacbc
BH
702
703 g_stats.maxMThreadStackUsage = max(MT->getMaxStackUsage(), g_stats.maxMThreadStackUsage);
288f4aa9
BH
704}
705
677e2a46 706void makeControlChannelSocket(int processNum=-1)
1d5b3ce6 707{
19e570d2 708 string sockname=::arg()["socket-dir"]+"/pdns_"+s_programname;
677e2a46
BH
709 if(processNum >= 0)
710 sockname += "."+lexical_cast<string>(processNum);
711 sockname+=".controlsocket";
41f7a068 712 s_rcc.listen(sockname);
387de317 713
387de317
BH
714 int sockowner = -1;
715 int sockgroup = -1;
716
717 if (!::arg().isEmpty("socket-group"))
718 sockgroup=::arg().asGid("socket-group");
719 if (!::arg().isEmpty("socket-owner"))
720 sockowner=::arg().asUid("socket-owner");
721
f838ad8d
BH
722 if (sockgroup > -1 || sockowner > -1) {
723 if(chown(sockname.c_str(), sockowner, sockgroup) < 0) {
724 unixDie("Failed to chown control socket");
725 }
726 }
387de317
BH
727
728 // do mode change if socket-mode is given
729 if(!::arg().isEmpty("socket-mode")) {
730 mode_t sockmode=::arg().asMode("socket-mode");
731 chmod(sockname.c_str(), sockmode);
732 }
1d5b3ce6
BH
733}
734
d8f6d49f 735void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)
09e6702a 736{
cd989c87 737 shared_ptr<TCPConnection> conn=any_cast<shared_ptr<TCPConnection> >(var);
c038218b 738
879b3f70 739 if(conn->state==TCPConnection::BYTE0) {
cd989c87 740 int bytes=recv(conn->getFD(), conn->data, 2, 0);
09e6702a 741 if(bytes==1)
667f7e60 742 conn->state=TCPConnection::BYTE1;
09e6702a 743 if(bytes==2) {
a0aa4f64 744 conn->qlen=(((unsigned char)conn->data[0]) << 8)+ (unsigned char)conn->data[1];
667f7e60
BH
745 conn->bytesread=0;
746 conn->state=TCPConnection::GETQUESTION;
09e6702a
BH
747 }
748 if(!bytes || bytes < 0) {
bb4bdbaf 749 t_fdm->removeReadFD(fd);
09e6702a
BH
750 return;
751 }
752 }
667f7e60 753 else if(conn->state==TCPConnection::BYTE1) {
cd989c87 754 int bytes=recv(conn->getFD(), conn->data+1, 1, 0);
09e6702a 755 if(bytes==1) {
667f7e60 756 conn->state=TCPConnection::GETQUESTION;
a0aa4f64 757 conn->qlen=(((unsigned char)conn->data[0]) << 8)+ (unsigned char)conn->data[1];
667f7e60 758 conn->bytesread=0;
09e6702a
BH
759 }
760 if(!bytes || bytes < 0) {
761 if(g_logCommonErrors)
cd989c87 762 L<<Logger::Error<<"TCP client "<< conn->d_remote.toString() <<" disconnected after first byte"<<endl;
bb4bdbaf 763 t_fdm->removeReadFD(fd);
09e6702a
BH
764 return;
765 }
766 }
667f7e60 767 else if(conn->state==TCPConnection::GETQUESTION) {
cd989c87 768 int bytes=recv(conn->getFD(), conn->data + conn->bytesread, conn->qlen - conn->bytesread, 0);
09e6702a 769 if(!bytes || bytes < 0) {
cd989c87 770 L<<Logger::Error<<"TCP client "<< conn->d_remote.toString() <<" disconnected while reading question body"<<endl;
bb4bdbaf 771 t_fdm->removeReadFD(fd);
09e6702a
BH
772 return;
773 }
667f7e60
BH
774 conn->bytesread+=bytes;
775 if(conn->bytesread==conn->qlen) {
bb4bdbaf 776 t_fdm->removeReadFD(fd); // should no longer awake ourselves when there is data to read
879b3f70 777
09e6702a
BH
778 DNSComboWriter* dc=0;
779 try {
cd989c87 780 dc=new DNSComboWriter(conn->data, conn->qlen, g_now);
09e6702a
BH
781 }
782 catch(MOADNSException &mde) {
4957a608
BH
783 g_stats.clientParseError++;
784 if(g_logCommonErrors)
cd989c87 785 L<<Logger::Error<<"Unable to parse packet from TCP client "<< conn->d_remote.toString() <<endl;
4957a608 786 return;
09e6702a 787 }
cd989c87
BH
788 dc->d_tcpConnection = conn; // carry the torch
789 dc->setSocket(conn->getFD()); // this is the only time a copy is made of the actual fd
09e6702a 790 dc->d_tcp=true;
cd989c87 791 dc->setRemote(&conn->d_remote);
879b3f70 792 if(dc->d_mdp.d_header.qr) {
4957a608
BH
793 delete dc;
794 L<<Logger::Error<<"Ignoring answer on server socket!"<<endl;
4957a608 795 return;
879b3f70 796 }
3abcdab2
PD
797 if(dc->d_mdp.d_header.opcode) {
798 delete dc;
799 L<<Logger::Error<<"Ignoring non-query opcode on server socket!"<<endl;
800 return;
801 }
09e6702a 802 else {
4957a608
BH
803 ++g_stats.qcounter;
804 ++g_stats.tcpqcounter;
50a5ef72 805 MT->makeThread(startDoResolve, dc); // deletes dc, will set state to BYTE0 again
4957a608 806 return;
09e6702a
BH
807 }
808 }
809 }
810}
811
6dcd28c3 812//! Handle new incoming TCP connection
d8f6d49f 813void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t& )
09e6702a 814{
37d3f960 815 ComboAddress addr;
09e6702a 816 socklen_t addrlen=sizeof(addr);
705f31ae 817 int newsock=(int)accept(fd, (struct sockaddr*)&addr, &addrlen);
09e6702a 818 if(newsock>0) {
85c32340
BH
819 if(MT->numProcesses() > g_maxMThreads) {
820 g_stats.overCapacityDrops++;
821 Utility::closesocket(newsock);
822 return;
823 }
824
b3b5459d 825 t_remotes->addRemote(addr);
49a699c4 826 if(t_allowFrom && !t_allowFrom->match(&addr)) {
2914b022 827 if(!g_quiet)
4957a608 828 L<<Logger::Error<<"["<<MT->getTid()<<"] dropping TCP query from "<<addr.toString()<<", address not matched by allow-from"<<endl;
2914b022 829
09e6702a 830 g_stats.unauthorizedTCP++;
705f31ae 831 Utility::closesocket(newsock);
09e6702a
BH
832 return;
833 }
bd0289fc 834 if(g_maxTCPPerClient && t_tcpClientCounts->count(addr) && (*t_tcpClientCounts)[addr] >= g_maxTCPPerClient) {
09e6702a 835 g_stats.tcpClientOverflow++;
705f31ae 836 Utility::closesocket(newsock); // don't call TCPConnection::closeAndCleanup here - did not enter it in the counts yet!
09e6702a
BH
837 return;
838 }
cd989c87 839
09e6702a 840 Utility::setNonBlocking(newsock);
cd989c87
BH
841 shared_ptr<TCPConnection> tc(new TCPConnection(newsock, addr));
842 tc->state=TCPConnection::BYTE0;
843
844 t_fdm->addReadFD(tc->getFD(), handleRunningTCPQuestion, tc);
c038218b 845
0bff046b 846 struct timeval now;
c038218b 847 Utility::gettimeofday(&now, 0);
cd989c87 848 t_fdm->setReadTTD(tc->getFD(), now, g_tcpTimeout);
09e6702a
BH
849 }
850}
2914b022 851
1bc3c142
BH
852string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fromaddr, int fd)
853{
854 ++g_stats.qcounter;
d7f10541
BH
855 if(fromaddr.sin4.sin_family==AF_INET6)
856 g_stats.ipv6qcounter++;
1bc3c142
BH
857
858 string response;
859 try {
860 uint32_t age;
861 if(!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(question, g_now.tv_sec, &response, &age)) {
862 if(!g_quiet)
232f0877 863 L<<Logger::Error<<t_id<< " question answered from packet cache from "<<fromaddr.toString()<<endl;
1bc3c142
BH
864
865 g_stats.packetCacheHits++;
866 SyncRes::s_queries++;
867 ageDNSPacket(response, age);
868 sendto(fd, response.c_str(), response.length(), 0, (struct sockaddr*) &fromaddr, fromaddr.getSocklen());
97bee66d
BH
869 if(response.length() >= sizeof(struct dnsheader)) {
870 struct dnsheader dh;
871 memcpy(&dh, response.c_str(), sizeof(dh));
872 updateRcodeStats(dh.rcode);
873 }
1bc3c142
BH
874 g_stats.avgLatencyUsec=(uint64_t)((1-0.0001)*g_stats.avgLatencyUsec + 0); // we assume 0 usec
875 return 0;
876 }
877 }
878 catch(std::exception& e) {
879 L<<Logger::Error<<"Error processing or aging answer packet: "<<e.what()<<endl;
880 return 0;
881 }
882
883
884 if(MT->numProcesses() > g_maxMThreads) {
885 g_stats.overCapacityDrops++;
886 return 0;
887 }
888
889 DNSComboWriter* dc = new DNSComboWriter(question.c_str(), question.size(), g_now);
890 dc->setSocket(fd);
891 dc->setRemote(&fromaddr);
892
893 dc->d_tcp=false;
894 MT->makeThread(startDoResolve, (void*) dc); // deletes dc
895 return 0;
896}
897
d8f6d49f 898void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
5db529f8 899{
a9af3782 900 int len;
5db529f8
BH
901 char data[1500];
902 ComboAddress fromaddr;
903 socklen_t addrlen=sizeof(fromaddr);
85c32340 904
a9af3782 905 if((len=recvfrom(fd, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen)) >= 0) {
b3b5459d 906 t_remotes->addRemote(fromaddr);
b23b8614 907
49a699c4 908 if(t_allowFrom && !t_allowFrom->match(&fromaddr)) {
2914b022 909 if(!g_quiet)
4957a608 910 L<<Logger::Error<<"["<<MT->getTid()<<"] dropping UDP query from "<<fromaddr.toString()<<", address not matched by allow-from"<<endl;
2914b022 911
5db529f8 912 g_stats.unauthorizedUDP++;
a9af3782 913 return;
5db529f8 914 }
5db529f8 915 try {
b23b8614 916 dnsheader* dh=(dnsheader*)data;
5db529f8 917
b23b8614 918 if(dh->qr) {
4957a608
BH
919 if(g_logCommonErrors)
920 L<<Logger::Error<<"Ignoring answer from "<<fromaddr.toString()<<" on server socket!"<<endl;
5db529f8 921 }
3abcdab2
PD
922 else if(dh->opcode) {
923 if(g_logCommonErrors)
924 L<<Logger::Error<<"Ignoring non-query opcode "<<dh->opcode<<" from "<<fromaddr.toString()<<" on server socket!"<<endl;
925 }
5db529f8 926 else {
232f0877
CH
927 string question(data, len);
928 if(g_weDistributeQueries)
929 distributeAsyncFunction(boost::bind(doProcessUDPQuestion, question, fromaddr, fd));
930 else
931 doProcessUDPQuestion(question, fromaddr, fd);
5db529f8
BH
932 }
933 }
934 catch(MOADNSException& mde) {
935 g_stats.clientParseError++;
84e66a59 936 if(g_logCommonErrors)
4957a608 937 L<<Logger::Error<<"Unable to parse packet from remote UDP client "<<fromaddr.toString() <<": "<<mde.what()<<endl;
5db529f8
BH
938 }
939 }
ac0e821b
BH
940 else {
941 // cerr<<t_id<<" had error: "<<stringerror()<<endl;
9326cae1
BH
942 if(errno == EAGAIN)
943 g_stats.noPacketError++;
ac0e821b 944 }
5db529f8
BH
945}
946
1bc3c142 947
5db529f8
BH
948typedef vector<pair<int, function< void(int, any&) > > > deferredAdd_t;
949deferredAdd_t deferredAdd;
950
f28307ad 951void makeTCPServerSockets()
9c495589 952{
37d3f960 953 int fd;
f28307ad 954 vector<string>locals;
2e3d8a19 955 stringtok(locals,::arg()["local-address"]," ,");
9c495589 956
f28307ad 957 if(locals.empty())
3f81d239 958 throw PDNSException("No local address specified");
f28307ad 959
f28307ad 960 for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
32252594
BH
961 ServiceTuple st;
962 st.port=::arg().asNum("local-port");
963 parseService(*i, st);
964
965 ComboAddress sin;
966
f28307ad 967 memset((char *)&sin,0, sizeof(sin));
37d3f960 968 sin.sin4.sin_family = AF_INET;
32252594 969 if(!IpToU32(st.host, (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
37d3f960 970 sin.sin6.sin6_family = AF_INET6;
f71bc087 971 if(makeIPv6sockaddr(st.host, &sin.sin6) < 0)
3f81d239 972 throw PDNSException("Unable to resolve local address for TCP server on '"+ st.host +"'");
37d3f960
BH
973 }
974
975 fd=socket(sin.sin6.sin6_family, SOCK_STREAM, 0);
42c235e5
PD
976 Utility::setCloseOnExec(fd);
977
37d3f960 978 if(fd<0)
3f81d239 979 throw PDNSException("Making a TCP server socket for resolver: "+stringerror());
f28307ad
BH
980
981 int tmp=1;
37d3f960 982 if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
f28307ad 983 L<<Logger::Error<<"Setsockopt failed for TCP listening socket"<<endl;
c8ddb7c2 984 exit(1);
f28307ad
BH
985 }
986
c8ddb7c2 987#ifdef TCP_DEFER_ACCEPT
37d3f960
BH
988 if(setsockopt(fd, SOL_TCP,TCP_DEFER_ACCEPT,(char*)&tmp,sizeof tmp) >= 0) {
989 if(i==locals.begin())
4957a608 990 L<<Logger::Error<<"Enabled TCP data-ready filter for (slight) DoS protection"<<endl;
c8ddb7c2
BH
991 }
992#endif
993
32252594 994 sin.sin4.sin_port = htons(st.port);
37d3f960
BH
995 int socklen=sin.sin4.sin_family==AF_INET ? sizeof(sin.sin4) : sizeof(sin.sin6);
996 if (::bind(fd, (struct sockaddr *)&sin, socklen )<0)
3f81d239 997 throw PDNSException("Binding TCP server socket for "+ st.host +": "+stringerror());
f28307ad 998
37d3f960 999 Utility::setNonBlocking(fd);
49a699c4 1000 setSocketSendBuffer(fd, 65000);
37d3f960 1001 listen(fd, 128);
5db529f8 1002 deferredAdd.push_back(make_pair(fd, handleNewTCPQuestion));
c2136bf0
BH
1003 g_tcpListenSockets.push_back(fd);
1004
aa136564 1005 if(sin.sin4.sin_family == AF_INET)
32252594 1006 L<<Logger::Error<<"Listening for TCP queries on "<< sin.toString() <<":"<<st.port<<endl;
aa136564 1007 else
32252594 1008 L<<Logger::Error<<"Listening for TCP queries on ["<< sin.toString() <<"]:"<<st.port<<endl;
f28307ad 1009 }
9c495589
BH
1010}
1011
bb4bdbaf
BH
1012
1013
f28307ad 1014void makeUDPServerSockets()
288f4aa9 1015{
f28307ad 1016 vector<string>locals;
2e3d8a19 1017 stringtok(locals,::arg()["local-address"]," ,");
288f4aa9 1018
f28307ad 1019 if(locals.empty())
3f81d239 1020 throw PDNSException("No local address specified");
f28307ad 1021
2e3d8a19 1022 if(::arg()["local-address"]=="0.0.0.0") {
c836dc19 1023 L<<Logger::Warning<<"It is advised to bind to explicit addresses with the --local-address option"<<endl;
288f4aa9 1024 }
525b8a7c 1025
f28307ad 1026 for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
32252594
BH
1027 ServiceTuple st;
1028 st.port=::arg().asNum("local-port");
1029 parseService(*i, st);
1030
37d3f960 1031 ComboAddress sin;
996c89cc 1032
37d3f960
BH
1033 memset(&sin, 0, sizeof(sin));
1034 sin.sin4.sin_family = AF_INET;
32252594 1035 if(!IpToU32(st.host.c_str() , (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
37d3f960 1036 sin.sin6.sin6_family = AF_INET6;
f71bc087 1037 if(makeIPv6sockaddr(st.host, &sin.sin6) < 0)
3f81d239 1038 throw PDNSException("Unable to resolve local address for UDP server on '"+ st.host +"'");
37d3f960
BH
1039 }
1040
bb4bdbaf 1041 int fd=socket(sin.sin4.sin_family, SOCK_DGRAM, 0);
42c235e5 1042 Utility::setCloseOnExec(fd);
bb4bdbaf 1043
d3b4137e 1044 if(fd < 0) {
3f81d239 1045 throw PDNSException("Making a UDP server socket for resolver: "+netstringerror());
d3b4137e 1046 }
37d3f960 1047
49a699c4 1048 setSocketReceiveBuffer(fd, 200000);
32252594 1049 sin.sin4.sin_port = htons(st.port);
37d3f960
BH
1050
1051 int socklen=sin.sin4.sin_family==AF_INET ? sizeof(sin.sin4) : sizeof(sin.sin6);
1052 if (::bind(fd, (struct sockaddr *)&sin, socklen)<0)
3f81d239 1053 throw PDNSException("Resolver binding to server socket on port "+ lexical_cast<string>(st.port) +" for "+ st.host+": "+stringerror());
f28307ad
BH
1054
1055 Utility::setNonBlocking(fd);
c2136bf0 1056
0aaecd50 1057 deferredAdd.push_back(make_pair(fd, handleNewUDPQuestion));
40a3dd64 1058 g_listenSocketsAddresses[fd]=sin; // this is written to only from the startup thread, not from the workers
aa136564 1059 if(sin.sin4.sin_family == AF_INET)
32252594 1060 L<<Logger::Error<<"Listening for UDP queries on "<< sin.toString() <<":"<<st.port<<endl;
aa136564 1061 else
32252594 1062 L<<Logger::Error<<"Listening for UDP queries on ["<< sin.toString() <<"]:"<<st.port<<endl;
f28307ad 1063 }
c836dc19 1064}
caa6eefa 1065
9c495589 1066
c836dc19
BH
1067void daemonize(void)
1068{
1069 if(fork())
1070 exit(0); // bye bye
1071
1072 setsid();
1073
27a5ead5
BH
1074 int i=open("/dev/null",O_RDWR); /* open stdin */
1075 if(i < 0)
1076 L<<Logger::Critical<<"Unable to open /dev/null: "<<stringerror()<<endl;
1077 else {
1078 dup2(i,0); /* stdin */
1079 dup2(i,1); /* stderr */
1080 dup2(i,2); /* stderr */
1081 close(i);
1082 }
288f4aa9 1083}
caa6eefa 1084
aaacf7f2 1085uint64_t counter;
c75a6a9e
BH
1086bool statsWanted;
1087
1088void usr1Handler(int)
1089{
1090 statsWanted=true;
1091}
ae1b2e98 1092
9170fbaf
BH
1093void usr2Handler(int)
1094{
77499b05 1095 SyncRes::setDefaultLogMode(SyncRes::Log);
1d5b3ce6
BH
1096 g_quiet=false;
1097 ::arg().set("quiet")="no";
c9e9e5e0 1098
9170fbaf
BH
1099}
1100
c75a6a9e
BH
1101void doStats(void)
1102{
16beeaa4
BH
1103 static time_t lastOutputTime;
1104 static uint64_t lastQueryCount;
1105
3427fa8a
BH
1106 if(g_stats.qcounter && (t_RC->cacheHits + t_RC->cacheMisses) && SyncRes::s_queries && SyncRes::s_outqueries) { // this only runs once thread 0 has had hits
1107 uint64_t cacheHits = broadcastAccFunction<uint64_t>(pleaseGetCacheHits);
1108 uint64_t cacheMisses = broadcastAccFunction<uint64_t>(pleaseGetCacheMisses);
1109
1110 L<<Logger::Warning<<"stats: "<<g_stats.qcounter<<" questions, "<<
1111 broadcastAccFunction<uint64_t>(pleaseGetCacheSize)<< " cache entries, "<<
1112 broadcastAccFunction<uint64_t>(pleaseGetNegCacheSize)<<" negative entries, "<<
1113 (int)((cacheHits*100.0)/(cacheHits+cacheMisses))<<"% cache hits"<<endl;
1114
1115 L<<Logger::Warning<<"stats: throttle map: "
1116 << broadcastAccFunction<uint64_t>(pleaseGetThrottleSize) <<", ns speeds: "
1117 << broadcastAccFunction<uint64_t>(pleaseGetNsSpeedsSize)<<endl;
70c2c8b1
BH
1118 L<<Logger::Warning<<"stats: outpacket/query ratio "<<(int)(SyncRes::s_outqueries*100.0/SyncRes::s_queries)<<"%";
1119 L<<Logger::Warning<<", "<<(int)(SyncRes::s_throttledqueries*100.0/(SyncRes::s_outqueries+SyncRes::s_throttledqueries))<<"% throttled, "
525b8a7c 1120 <<SyncRes::s_nodelegated<<" no-delegation drops"<<endl;
3427fa8a
BH
1121 L<<Logger::Warning<<"stats: "<<SyncRes::s_tcpoutqueries<<" outgoing tcp connections, "<<
1122 broadcastAccFunction<uint64_t>(pleaseGetConcurrentQueries)<<" queries running, "<<SyncRes::s_outgoingtimeouts<<" outgoing timeouts"<<endl;
81883dcc 1123
16beeaa4
BH
1124 //L<<Logger::Warning<<"stats: "<<g_stats.ednsPingMatches<<" ping matches, "<<g_stats.ednsPingMismatches<<" mismatches, "<<
1125 //g_stats.noPingOutQueries<<" outqueries w/o ping, "<< g_stats.noEdnsOutQueries<<" w/o EDNS"<<endl;
1126
1127 L<<Logger::Warning<<"stats: " << broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize) <<
1128 " packet cache entries, "<<(int)(100.0*broadcastAccFunction<uint64_t>(pleaseGetPacketCacheHits)/SyncRes::s_queries) << "% packet cache hits"<<endl;
1129
1130 time_t now = time(0);
1131 if(lastOutputTime && lastQueryCount && now != lastOutputTime) {
1132 L<<Logger::Warning<<"stats: "<< (SyncRes::s_queries - lastQueryCount) / (now - lastOutputTime) <<" qps (average over "<< (now - lastOutputTime) << " seconds)"<<endl;
1133 }
1134 lastOutputTime = now;
1135 lastQueryCount = SyncRes::s_queries;
c75a6a9e 1136 }
7becf07f 1137 else if(statsWanted)
70c2c8b1 1138 L<<Logger::Warning<<"stats: no stats yet!"<<endl;
7becf07f 1139
c75a6a9e
BH
1140 statsWanted=false;
1141}
c836dc19 1142
29f0b1ce 1143static void houseKeeping(void *)
779828c4 1144try
c836dc19 1145{
7393d6c0 1146 static __thread time_t last_stat, last_rootupdate, last_prune;
8baca3fa 1147 static __thread int cleanCounter=0;
c9e9e5e0 1148 struct timeval now;
c038218b 1149 Utility::gettimeofday(&now, 0);
c9e9e5e0 1150
1a16adf0 1151 // clog<<"* "<<t_id<<" "<<(void*)&last_stat<<"\t"<<(unsigned int)last_stat<<endl;
ac0e821b 1152
c3828c03 1153 if(now.tv_sec - last_prune > (time_t)(5 + t_id)) {
5e4a2466
BH
1154 DTime dt;
1155 dt.setTimeval(now);
49a699c4 1156 t_RC->doPrune(); // this function is local to a thread, so fine anyhow
c3828c03 1157 t_packetCache->doPruneTo(::arg().asNum("max-packetcache-entries") / g_numThreads);
33988bfb 1158
1a16adf0 1159 pruneCollection(t_sstorage->negcache, ::arg().asNum("max-cache-entries") / (g_numThreads * 10), 200);
8baca3fa
BH
1160
1161 if(!((cleanCounter++)%40)) { // this is a full scan!
1162 time_t limit=now.tv_sec-300;
ac0e821b 1163 for(SyncRes::nsspeeds_t::iterator i = t_sstorage->nsSpeeds.begin() ; i!= t_sstorage->nsSpeeds.end(); )
8baca3fa 1164 if(i->second.stale(limit))
ac0e821b 1165 t_sstorage->nsSpeeds.erase(i++);
8baca3fa
BH
1166 else
1167 ++i;
1168 }
7393d6c0 1169// L<<Logger::Warning<<"Spent "<<dt.udiff()/1000<<" msec cleaning"<<endl;
ae1b2e98
BH
1170 last_prune=time(0);
1171 }
ac0e821b 1172
3427fa8a 1173 if(!t_id) {
ac0e821b 1174 if(now.tv_sec - last_stat > 1800) {
3427fa8a
BH
1175 doStats();
1176 last_stat=time(0);
1177 }
c836dc19 1178 }
ac0e821b 1179
c038218b 1180 if(now.tv_sec - last_rootupdate > 7200) {
c9e9e5e0 1181 SyncRes sr(now);
2188dcc3 1182 sr.setDoEDNS0(true);
ea634573 1183 vector<DNSResourceRecord> ret;
c836dc19
BH
1184
1185 sr.setNoCache();
a9af3782 1186 int res=sr.beginResolve(".", QType(QType::NS), 1, ret);
c836dc19 1187 if(!res) {
70c2c8b1 1188 L<<Logger::Warning<<"Refreshed . records"<<endl;
c9e9e5e0 1189 last_rootupdate=now.tv_sec;
c836dc19
BH
1190 }
1191 else
1192 L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
1193 }
1194}
3f81d239 1195catch(PDNSException& ae)
779828c4
BH
1196{
1197 L<<Logger::Error<<"Fatal error: "<<ae.reason<<endl;
1198 throw;
1199}
705f31ae 1200;
d6d5dea7 1201
49a699c4
BH
1202void makeThreadPipes()
1203{
c3828c03 1204 for(unsigned int n=0; n < g_numThreads; ++n) {
49a699c4
BH
1205 struct ThreadPipeSet tps;
1206 int fd[2];
1207 if(pipe(fd) < 0)
1208 unixDie("Creating pipe for inter-thread communications");
1209
1210 tps.readToThread = fd[0];
1211 tps.writeToThread = fd[1];
1212
1213 if(pipe(fd) < 0)
1214 unixDie("Creating pipe for inter-thread communications");
1215 tps.readFromThread = fd[0];
1216 tps.writeFromThread = fd[1];
1217
1218 g_pipes.push_back(tps);
1219 }
1220}
1221
00c9b8c1
BH
1222struct ThreadMSG
1223{
1224 pipefunc_t func;
1225 bool wantAnswer;
1226};
1227
49a699c4
BH
1228void broadcastFunction(const pipefunc_t& func, bool skipSelf)
1229{
49a699c4
BH
1230 unsigned int n = 0;
1231 BOOST_FOREACH(ThreadPipeSet& tps, g_pipes)
1232 {
1233 if(n++ == t_id) {
1234 if(!skipSelf)
1235 func(); // don't write to ourselves!
1236 continue;
1237 }
00c9b8c1
BH
1238
1239 ThreadMSG* tmsg = new ThreadMSG();
1240 tmsg->func = func;
1241 tmsg->wantAnswer = true;
1242 if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg))
49a699c4
BH
1243 unixDie("write to thread pipe returned wrong size or error");
1244
1245 string* resp;
1246 if(read(tps.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
1247 unixDie("read from thread pipe returned wrong size or error");
1248
1249 if(resp) {
1250// cerr <<"got response: " << *resp << endl;
1251 delete resp;
1252 }
1253 }
1254}
00c9b8c1
BH
1255void distributeAsyncFunction(const pipefunc_t& func)
1256{
1257 static unsigned int counter;
1bc3c142 1258 unsigned int target = 1 + (++counter % (g_pipes.size()-1));
00c9b8c1
BH
1259 // cerr<<"Sending to: "<<target<<endl;
1260 if(target == t_id) {
1261 func();
1262 return;
1263 }
1264 ThreadPipeSet& tps = g_pipes[target];
1265 ThreadMSG* tmsg = new ThreadMSG();
1266 tmsg->func = func;
1267 tmsg->wantAnswer = false;
1268
1269 if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg))
1270 unixDie("write to thread pipe returned wrong size or error");
1271
1272}
3427fa8a 1273
49a699c4
BH
1274void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var)
1275{
00c9b8c1
BH
1276 ThreadMSG* tmsg;
1277
1278 if(read(fd, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) { // fd == readToThread
49a699c4
BH
1279 unixDie("read from thread pipe returned wrong size or error");
1280 }
3427fa8a 1281
00c9b8c1
BH
1282 void *resp = tmsg->func();
1283 if(tmsg->wantAnswer)
1284 if(write(g_pipes[t_id].writeFromThread, &resp, sizeof(resp)) != sizeof(resp))
1285 unixDie("write to thread pipe returned wrong size or error");
3427fa8a 1286
00c9b8c1 1287 delete tmsg;
49a699c4 1288}
09e6702a 1289
13034931
BH
1290template<class T> void *voider(const boost::function<T*()>& func)
1291{
1292 return func();
1293}
1294
b3b5459d
BH
1295vector<ComboAddress>& operator+=(vector<ComboAddress>&a, const vector<ComboAddress>& b)
1296{
1297 a.insert(a.end(), b.begin(), b.end());
1298 return a;
1299}
1300
13034931 1301template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool skipSelf)
3427fa8a
BH
1302{
1303 unsigned int n = 0;
1304 T ret=T();
1305 BOOST_FOREACH(ThreadPipeSet& tps, g_pipes)
1306 {
1307 if(n++ == t_id) {
1308 if(!skipSelf) {
1309 T* resp = (T*)func(); // don't write to ourselves!
1310 if(resp) {
1311 //~ cerr <<"got direct: " << *resp << endl;
1312 ret += *resp;
1313 delete resp;
1314 }
1315 }
1316 continue;
1317 }
1318
00c9b8c1
BH
1319 ThreadMSG* tmsg = new ThreadMSG();
1320 tmsg->func = boost::bind(voider<T>, func);
1321 tmsg->wantAnswer = true;
1322
1323 if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg))
3427fa8a 1324 unixDie("write to thread pipe returned wrong size or error");
00c9b8c1 1325
3427fa8a
BH
1326
1327 T* resp;
1328 if(read(tps.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
1329 unixDie("read from thread pipe returned wrong size or error");
1330
1331 if(resp) {
1332 //~ cerr <<"got response: " << *resp << endl;
1333 ret += *resp;
1334 delete resp;
1335 }
1336 }
1337 return ret;
1338}
1339
13034931
BH
1340template string broadcastAccFunction(const boost::function<string*()>& fun, bool skipSelf); // explicit instantiation
1341template uint64_t broadcastAccFunction(const boost::function<uint64_t*()>& fun, bool skipSelf); // explicit instantiation
b3b5459d 1342template vector<ComboAddress> broadcastAccFunction(const boost::function<vector<ComboAddress> *()>& fun, bool skipSelf); // explicit instantiation
3427fa8a 1343
d8f6d49f 1344void handleRCC(int fd, FDMultiplexer::funcparam_t& var)
09e6702a
BH
1345{
1346 string remote;
1347 string msg=s_rcc.recv(&remote);
1348 RecursorControlParser rcp;
1349 RecursorControlParser::func_t* command;
77499b05 1350
09e6702a 1351 string answer=rcp.getAnswer(msg, &command);
ab5c053d
BH
1352 try {
1353 s_rcc.send(answer, &remote);
1354 command();
1355 }
fdbf35ac 1356 catch(std::exception& e) {
ab5c053d
BH
1357 L<<Logger::Error<<"Error dealing with control socket request: "<<e.what()<<endl;
1358 }
3f81d239 1359 catch(PDNSException& ae) {
ab5c053d
BH
1360 L<<Logger::Error<<"Error dealing with control socket request: "<<ae.reason<<endl;
1361 }
09e6702a
BH
1362}
1363
d8f6d49f 1364void handleTCPClientReadable(int fd, FDMultiplexer::funcparam_t& var)
09e6702a 1365{
0b18b22e 1366 PacketID* pident=any_cast<PacketID>(&var);
667f7e60 1367 // cerr<<"handleTCPClientReadable called for fd "<<fd<<", pident->inNeeded: "<<pident->inNeeded<<", "<<pident->sock->getHandle()<<endl;
09e6702a 1368
667f7e60 1369 shared_array<char> buffer(new char[pident->inNeeded]);
09e6702a 1370
705f31ae 1371 int ret=recv(fd, buffer.get(), pident->inNeeded,0);
09e6702a 1372 if(ret > 0) {
667f7e60
BH
1373 pident->inMSG.append(&buffer[0], &buffer[ret]);
1374 pident->inNeeded-=ret;
1375 if(!pident->inNeeded) {
1376 // cerr<<"Got entire load of "<<pident->inMSG.size()<<" bytes"<<endl;
1377 PacketID pid=*pident;
1378 string msg=pident->inMSG;
09e6702a 1379
bb4bdbaf 1380 t_fdm->removeReadFD(fd);
09e6702a
BH
1381 MT->sendEvent(pid, &msg);
1382 }
1383 else {
667f7e60 1384 // cerr<<"Still have "<<pident->inNeeded<<" left to go"<<endl;
09e6702a
BH
1385 }
1386 }
1387 else {
667f7e60 1388 PacketID tmp=*pident;
bb4bdbaf 1389 t_fdm->removeReadFD(fd); // pident might now be invalid (it isn't, but still)
09e6702a
BH
1390 string empty;
1391 MT->sendEvent(tmp, &empty); // this conveys error status
1392 }
1393}
1394
d8f6d49f 1395void handleTCPClientWritable(int fd, FDMultiplexer::funcparam_t& var)
09e6702a 1396{
0b18b22e 1397 PacketID* pid=any_cast<PacketID>(&var);
4ca15bca 1398 int ret=send(fd, pid->outMSG.c_str() + pid->outPos, pid->outMSG.size() - pid->outPos,0);
09e6702a 1399 if(ret > 0) {
667f7e60
BH
1400 pid->outPos+=ret;
1401 if(pid->outPos==pid->outMSG.size()) {
1402 PacketID tmp=*pid;
bb4bdbaf 1403 t_fdm->removeWriteFD(fd);
09e6702a
BH
1404 MT->sendEvent(tmp, &tmp.outMSG); // send back what we sent to convey everything is ok
1405 }
1406 }
1407 else { // error or EOF
667f7e60 1408 PacketID tmp(*pid);
bb4bdbaf 1409 t_fdm->removeWriteFD(fd);
09e6702a 1410 string sent;
998a4334 1411 MT->sendEvent(tmp, &sent); // we convey error status by sending empty string
09e6702a
BH
1412 }
1413}
1414
34801ab1
BH
1415// resend event to everybody chained onto it
1416void doResends(MT_t::waiters_t::iterator& iter, PacketID resend, const string& content)
1417{
1418 if(iter->key.chain.empty())
1419 return;
e27e91a8 1420 // cerr<<"doResends called!\n";
34801ab1
BH
1421 for(PacketID::chain_t::iterator i=iter->key.chain.begin(); i != iter->key.chain.end() ; ++i) {
1422 resend.fd=-1;
1423 resend.id=*i;
e27e91a8 1424 // cerr<<"\tResending "<<content.size()<<" bytes for fd="<<resend.fd<<" and id="<<resend.id<<endl;
4665c31e 1425
34801ab1
BH
1426 MT->sendEvent(resend, &content);
1427 g_stats.chainResends++;
34801ab1
BH
1428 }
1429}
1430
d8f6d49f 1431void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t& var)
09e6702a 1432{
600fc20b 1433 PacketID pid=any_cast<PacketID>(var);
998a4334 1434 int len;
09e6702a 1435 char data[1500];
996c89cc 1436 ComboAddress fromaddr;
09e6702a
BH
1437 socklen_t addrlen=sizeof(fromaddr);
1438
998a4334 1439 len=recvfrom(fd, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen);
c1da7976 1440
998a4334
BH
1441 if(len < (int)sizeof(dnsheader)) {
1442 if(len < 0)
996c89cc 1443 ; // cerr<<"Error on fd "<<fd<<": "<<stringerror()<<"\n";
09e6702a
BH
1444 else {
1445 g_stats.serverParseError++;
1446 if(g_logCommonErrors)
85db02c5 1447 L<<Logger::Error<<"Unable to parse packet from remote UDP server "<< fromaddr.toString() <<
e44d9fa7 1448 ": packet smaller than DNS header"<<endl;
998a4334 1449 }
34801ab1 1450
49a699c4 1451 t_udpclientsocks->returnSocket(fd);
34801ab1
BH
1452 string empty;
1453
1454 MT_t::waiters_t::iterator iter=MT->d_waiters.find(pid);
1455 if(iter != MT->d_waiters.end())
1456 doResends(iter, pid, empty);
1457
1458 MT->sendEvent(pid, &empty); // this denotes error (does lookup again.. at least L1 will be hot)
998a4334
BH
1459 return;
1460 }
1461
1462 dnsheader dh;
1463 memcpy(&dh, data, sizeof(dh));
1464
6da3b3ad
PD
1465 PacketID pident;
1466 pident.remote=fromaddr;
1467 pident.id=dh.id;
1468 pident.fd=fd;
34801ab1 1469
6da3b3ad
PD
1470 if(!dh.qr) {
1471 L<<Logger::Warning<<"Not taking data from question on outgoing socket from "<< fromaddr.toStringWithPort() <<endl;
1472 }
1473
1474 if(!dh.qdcount || // UPC, Nominum, very old BIND on FormErr, NSD
1475 !dh.qr) { // one weird server
1476 pident.domain.clear();
1477 pident.type = 0;
1478 }
1479 else {
1480 try {
1481 pident.domain=questionExpand(data, len, pident.type); // don't copy this from above - we need to do the actual read
1482 }
1483 catch(std::exception& e) {
1484 g_stats.serverParseError++; // won't be fed to lwres.cc, so we have to increment
1485 L<<Logger::Warning<<"Error in packet from "<< fromaddr.toStringWithPort() << ": "<<e.what() << endl;
1486 return;
34801ab1 1487 }
6da3b3ad
PD
1488 }
1489 string packet;
1490 packet.assign(data, len);
34801ab1 1491
6da3b3ad
PD
1492 MT_t::waiters_t::iterator iter=MT->d_waiters.find(pident);
1493 if(iter != MT->d_waiters.end()) {
1494 doResends(iter, pident, packet);
1495 }
c1da7976 1496
6da3b3ad 1497retryWithName:
4957a608 1498
6da3b3ad
PD
1499 if(!MT->sendEvent(pident, &packet)) {
1500 // 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
1501 for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
1502 if(pident.fd==mthread->key.fd && mthread->key.remote==pident.remote && mthread->key.type == pident.type &&
1503 pdns_iequals(pident.domain, mthread->key.domain)) {
1504 mthread->key.nearMisses++;
998a4334 1505 }
6da3b3ad
PD
1506
1507 // be a bit paranoid here since we're weakening our matching
1508 if(pident.domain.empty() && !mthread->key.domain.empty() && !pident.type && mthread->key.type &&
1509 pident.id == mthread->key.id && mthread->key.remote == pident.remote) {
1510 // cerr<<"Empty response, rest matches though, sending to a waiter"<<endl;
1511 pident.domain = mthread->key.domain;
1512 pident.type = mthread->key.type;
1513 goto retryWithName; // note that this only passes on an error, lwres will still reject the packet
d4fb76e9 1514 }
09e6702a 1515 }
6da3b3ad
PD
1516 g_stats.unexpectedCount++; // if we made it here, it really is an unexpected answer
1517 if(g_logCommonErrors) {
1518 L<<Logger::Warning<<"Discarding unexpected packet from "<<fromaddr.toStringWithPort()<<": "<<pident.domain<<", "<<pident.type<<", "<<MT->d_waiters.size()<<" waiters"<<endl;
d8f6d49f 1519 }
09e6702a 1520 }
6da3b3ad
PD
1521 else if(fd >= 0) {
1522 t_udpclientsocks->returnSocket(fd);
1523 }
09e6702a
BH
1524}
1525
1f4abb20
BH
1526FDMultiplexer* getMultiplexer()
1527{
1528 FDMultiplexer* ret;
1529 for(FDMultiplexer::FDMultiplexermap_t::const_iterator i = FDMultiplexer::getMultiplexerMap().begin();
1530 i != FDMultiplexer::getMultiplexerMap().end(); ++i) {
1531 try {
1532 ret=i->second();
1f4abb20
BH
1533 return ret;
1534 }
98d0ee4a 1535 catch(FDMultiplexerException &fe) {
0a7f24cb 1536 L<<Logger::Error<<"Non-fatal error initializing possible multiplexer ("<<fe.what()<<"), falling back"<<endl;
98d0ee4a
BH
1537 }
1538 catch(...) {
1539 L<<Logger::Error<<"Non-fatal error initializing possible multiplexer"<<endl;
1540 }
1f4abb20
BH
1541 }
1542 L<<Logger::Error<<"No working multiplexer found!"<<endl;
1543 exit(1);
1544}
1545
5605c067 1546
0f39c1a3 1547string* doReloadLuaScript()
4485aa35 1548{
674cf0f6 1549 string fname= ::arg()["lua-dns-script"];
4485aa35 1550 try {
674cf0f6
BH
1551 if(fname.empty()) {
1552 t_pdl->reset();
1553 L<<Logger::Error<<t_id<<" Unloaded current lua script"<<endl;
0f39c1a3 1554 return new string("unloaded\n");
4485aa35
BH
1555 }
1556 else {
5704e107 1557 *t_pdl = shared_ptr<RecursorLua>(new RecursorLua(fname));
4485aa35
BH
1558 }
1559 }
fdbf35ac 1560 catch(std::exception& e) {
674cf0f6 1561 L<<Logger::Error<<t_id<<" Retaining current script, error from '"<<fname<<"': "<< e.what() <<endl;
0f39c1a3 1562 return new string("retaining current script, error from '"+fname+"': "+e.what()+"\n");
4485aa35 1563 }
674cf0f6
BH
1564
1565 L<<Logger::Warning<<t_id<<" (Re)loaded lua script from '"<<fname<<"'"<<endl;
0f39c1a3 1566 return new string("(re)loaded '"+fname+"'\n");
4485aa35
BH
1567}
1568
49a699c4
BH
1569string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end)
1570{
1571 if(begin != end)
1572 ::arg().set("lua-dns-script") = *begin;
1573
0f39c1a3 1574 return broadcastAccFunction<string>(doReloadLuaScript);
49a699c4
BH
1575}
1576
77499b05
BH
1577string* pleaseUseNewTraceRegex(const std::string& newRegex)
1578try
1579{
1580 if(newRegex.empty()) {
1581 t_traceRegex->reset();
1582 return new string("unset\n");
1583 }
1584 else {
1585 (*t_traceRegex) = shared_ptr<Regex>(new Regex(newRegex));
1586 return new string("ok\n");
1587 }
1588}
3f81d239 1589catch(PDNSException& ae)
77499b05
BH
1590{
1591 return new string(ae.reason+"\n");
1592}
1593
1594string doTraceRegex(vector<string>::const_iterator begin, vector<string>::const_iterator end)
1595{
1596 return broadcastAccFunction<string>(boost::bind(pleaseUseNewTraceRegex, begin!=end ? *begin : ""));
1597}
1598
1599
bb4bdbaf 1600void* recursorThread(void*);
51e2144e 1601
3427fa8a 1602void* pleaseSupplantACLs(NetmaskGroup *ng)
49a699c4
BH
1603{
1604 t_allowFrom = ng;
3427fa8a 1605 return 0;
49a699c4
BH
1606}
1607
dbd23fc2
BH
1608int g_argc;
1609char** g_argv;
1610
18af64a8 1611void parseACLs()
f7c1d4e3 1612{
18af64a8 1613 static bool l_initialized;
49a699c4
BH
1614
1615 if(l_initialized) { // only reload configuration file on second call
18af64a8
BH
1616 string configname=::arg()["config-dir"]+"/recursor.conf";
1617 cleanSlashes(configname);
1618
1619 if(!::arg().preParseFile(configname.c_str(), "allow-from-file"))
1620 L<<Logger::Warning<<"Unable to re-parse configuration file '"<<configname<<"'"<<endl;
dbd23fc2 1621 ::arg().preParse(g_argc, g_argv, "allow-from-file");
49a699c4 1622 ::arg().preParseFile(configname.c_str(), "allow-from", LOCAL_NETS);
dbd23fc2 1623 ::arg().preParse(g_argc, g_argv, "allow-from");
f27e6356 1624 }
49a699c4
BH
1625
1626 NetmaskGroup* oldAllowFrom = t_allowFrom, *allowFrom=new NetmaskGroup;
1627
2c95fc65
BH
1628 if(!::arg()["allow-from-file"].empty()) {
1629 string line;
2c95fc65
BH
1630 ifstream ifs(::arg()["allow-from-file"].c_str());
1631 if(!ifs) {
49a699c4 1632 delete allowFrom;
9c61b9d0 1633 throw runtime_error("Could not open '"+::arg()["allow-from-file"]+"': "+stringerror());
2c95fc65
BH
1634 }
1635
1636 string::size_type pos;
1637 while(getline(ifs,line)) {
1638 pos=line.find('#');
1639 if(pos!=string::npos)
1640 line.resize(pos);
1641 trim(line);
1642 if(line.empty())
1643 continue;
1644
18af64a8 1645 allowFrom->addMask(line);
2c95fc65 1646 }
49a699c4 1647 L<<Logger::Warning<<"Done parsing " << allowFrom->size() <<" allow-from ranges from file '"<<::arg()["allow-from-file"]<<"' - overriding 'allow-from' setting"<<endl;
2c95fc65
BH
1648 }
1649 else if(!::arg()["allow-from"].empty()) {
f7c1d4e3
BH
1650 vector<string> ips;
1651 stringtok(ips, ::arg()["allow-from"], ", ");
c36bc97a 1652
f7c1d4e3
BH
1653 L<<Logger::Warning<<"Only allowing queries from: ";
1654 for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
18af64a8 1655 allowFrom->addMask(*i);
f7c1d4e3 1656 if(i!=ips.begin())
674cf0f6 1657 L<<Logger::Warning<<", ";
f7c1d4e3
BH
1658 L<<Logger::Warning<<*i;
1659 }
1660 L<<Logger::Warning<<endl;
1661 }
49a699c4
BH
1662 else {
1663 if(::arg()["local-address"]!="127.0.0.1" && ::arg().asNum("local-port")==53)
1664 L<<Logger::Error<<"WARNING: Allowing queries from all IP addresses - this can be a security risk!"<<endl;
1665 delete allowFrom;
1666 allowFrom = 0;
1667 }
1668
1669 g_initialAllowFrom = allowFrom;
d7dae798 1670 broadcastFunction(boost::bind(pleaseSupplantACLs, allowFrom));
49a699c4
BH
1671 delete oldAllowFrom;
1672
1673 l_initialized = true;
18af64a8
BH
1674}
1675
1676int serviceMain(int argc, char*argv[])
1677{
5124de27
RA
1678
1679
1680 L.setName(s_programname);
18af64a8
BH
1681
1682 L.setLoglevel((Logger::Urgency)(6)); // info and up
1683
1684 if(!::arg()["logging-facility"].empty()) {
f8499e52
BH
1685 int val=logFacilityToLOG(::arg().asNum("logging-facility") );
1686 if(val >= 0)
1687 theL().setFacility(val);
18af64a8
BH
1688 else
1689 L<<Logger::Error<<"Unknown logging facility "<<::arg().asNum("logging-facility") <<endl;
1690 }
1691
ba1a571d 1692 showProductVersion();
18af64a8 1693
85c32340
BH
1694 #if 0
1695 unsigned int maxFDs, curFDs;
1696 getFDLimits(curFDs, maxFDs);
1697 if(curFDs < 2048)
1698 L<<Logger::Warning<<"Only "<<curFDs<<" file descriptors available (out of: "<<maxFDs<<"), may not be suitable for high performance"<<endl;
1699 #endif
1700
18af64a8 1701 seedRandom(::arg()["entropy-source"]);
2c95fc65 1702
18af64a8
BH
1703 parseACLs();
1704
eb5bae86
BH
1705 if(!::arg()["dont-query"].empty()) {
1706 g_dontQuery=new NetmaskGroup;
1707 vector<string> ips;
1708 stringtok(ips, ::arg()["dont-query"], ", ");
66e0b6ea
BH
1709 ips.push_back("0.0.0.0");
1710 ips.push_back("::");
c36bc97a 1711
eb5bae86
BH
1712 L<<Logger::Warning<<"Will not send queries to: ";
1713 for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
1714 g_dontQuery->addMask(*i);
1715 if(i!=ips.begin())
4957a608 1716 L<<Logger::Warning<<", ";
eb5bae86
BH
1717 L<<Logger::Warning<<*i;
1718 }
1719 L<<Logger::Warning<<endl;
1720 }
1721
f7c1d4e3 1722 g_quiet=::arg().mustDo("quiet");
1bc3c142
BH
1723 g_weDistributeQueries = ::arg().mustDo("pdns-distributes-queries");
1724 if(g_weDistributeQueries) {
1725 L<<Logger::Warning<<"PowerDNS Recursor itself will distribute queries over threads"<<endl;
1726 }
1727
77499b05
BH
1728 if(::arg()["trace"]=="fail") {
1729 SyncRes::setDefaultLogMode(SyncRes::Store);
1730 }
1731 else if(::arg().mustDo("trace")) {
1732 SyncRes::setDefaultLogMode(SyncRes::Log);
f7c1d4e3
BH
1733 ::arg().set("quiet")="no";
1734 g_quiet=false;
1735 }
f7c1d4e3 1736
77499b05 1737
5a38281c
BH
1738 try {
1739 vector<string> addrs;
1740 if(!::arg()["query-local-address6"].empty()) {
1741 SyncRes::s_doIPv6=true;
d4fb76e9 1742 L<<Logger::Warning<<"Enabling IPv6 transport for outgoing queries"<<endl;
5a38281c
BH
1743
1744 stringtok(addrs, ::arg()["query-local-address6"], ", ;");
1745 BOOST_FOREACH(const string& addr, addrs) {
4957a608 1746 g_localQueryAddresses6.push_back(ComboAddress(addr));
5a38281c
BH
1747 }
1748 }
d4fb76e9
BH
1749 else {
1750 L<<Logger::Warning<<"NOT using IPv6 for outgoing queries - set 'query-local-address6=::' to enable"<<endl;
1751 }
5a38281c
BH
1752 addrs.clear();
1753 stringtok(addrs, ::arg()["query-local-address"], ", ;");
1754 BOOST_FOREACH(const string& addr, addrs) {
1755 g_localQueryAddresses4.push_back(ComboAddress(addr));
1756 }
1757 }
1758 catch(std::exception& e) {
1759 L<<Logger::Error<<"Assigning local query addresses: "<<e.what();
1760 exit(99);
f7c1d4e3 1761 }
f555e92e
BH
1762
1763 SyncRes::s_doAAAAAdditionalProcessing = ::arg().mustDo("aaaa-additional-processing");
1764 SyncRes::s_doAdditionalProcessing = ::arg().mustDo("additional-processing") | SyncRes::s_doAAAAAdditionalProcessing;
bb4bdbaf 1765
578361b3 1766 SyncRes::s_noEDNSPing = true; // ::arg().mustDo("disable-edns-ping");
4bfae16d 1767 SyncRes::s_noEDNS = ::arg().mustDo("disable-edns");
578361b3 1768 if(!SyncRes::s_noEDNS) {
1769 L<<Logger::Warning<<"Running in experimental EDNS mode - may cause problems"<<endl;
1770 }
bb4bdbaf 1771
1051f8a9
BH
1772 SyncRes::s_nopacketcache = ::arg().mustDo("disable-packetcache");
1773
f7c1d4e3 1774 SyncRes::s_maxnegttl=::arg().asNum("max-negative-ttl");
c3e753c7 1775 SyncRes::s_maxcachettl=::arg().asNum("max-cache-ttl");
1051f8a9
BH
1776 SyncRes::s_packetcachettl=::arg().asNum("packetcache-ttl");
1777 SyncRes::s_packetcacheservfailttl=::arg().asNum("packetcache-servfail-ttl");
f7c1d4e3
BH
1778 SyncRes::s_serverID=::arg()["server-id"];
1779 if(SyncRes::s_serverID.empty()) {
1780 char tmp[128];
1781 gethostname(tmp, sizeof(tmp)-1);
1782 SyncRes::s_serverID=tmp;
1783 }
1784
5b0ddd18 1785 g_networkTimeoutMsec = ::arg().asNum("network-timeout");
bb4bdbaf 1786
49a699c4 1787 g_initialDomainMap = parseAuthAndForwards();
674cf0f6 1788
b3b5459d 1789
f7c1d4e3 1790 g_logCommonErrors=::arg().mustDo("log-common-errors");
e661a20b
PD
1791
1792 g_anyToTcp = ::arg().mustDo("any-to-tcp");
a09a8ce0
PD
1793 g_udpTruncationThreshold = ::arg().asNum("udp-truncation-threshold");
1794
f7c1d4e3
BH
1795 makeUDPServerSockets();
1796 makeTCPServerSockets();
815099b2 1797
677e2a46
BH
1798 int forks;
1799 for(forks = 0; forks < ::arg().asNum("processes") - 1; ++forks) {
1bc3c142
BH
1800 if(!fork()) // we are child
1801 break;
1802 }
1803
02e7bdeb 1804 s_pidfname=::arg()["socket-dir"]+"/pdns_"+s_programname+".pid";
815099b2
BH
1805 if(!s_pidfname.empty())
1806 unlink(s_pidfname.c_str()); // remove possible old pid file
f7c1d4e3 1807
f7c1d4e3
BH
1808 if(::arg().mustDo("daemon")) {
1809 L<<Logger::Warning<<"Calling daemonize, going to background"<<endl;
1810 L.toConsole(Logger::Critical);
f7c1d4e3
BH
1811 daemonize();
1812 }
1813 signal(SIGUSR1,usr1Handler);
1814 signal(SIGUSR2,usr2Handler);
1815 signal(SIGPIPE,SIG_IGN);
1816 writePid();
677e2a46 1817 makeControlChannelSocket( ::arg().asNum("processes") > 1 ? forks : -1);
138435cb
BH
1818
1819 int newgid=0;
1820 if(!::arg()["setgid"].empty())
1821 newgid=Utility::makeGidNumeric(::arg()["setgid"]);
1822 int newuid=0;
1823 if(!::arg()["setuid"].empty())
1824 newuid=Utility::makeUidNumeric(::arg()["setuid"]);
1825
138435cb
BH
1826 if (!::arg()["chroot"].empty()) {
1827 if (chroot(::arg()["chroot"].c_str())<0 || chdir("/") < 0) {
1828 L<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror (errno)<<", exiting"<<endl;
1829 exit(1);
1830 }
1831 }
1832
1833 Utility::dropPrivs(newuid, newgid);
1bc3c142 1834 g_numThreads = ::arg().asNum("threads") + ::arg().mustDo("pdns-distributes-queries");
343257a4 1835
49a699c4 1836 makeThreadPipes();
5d4dd7fe
BH
1837
1838 g_tcpTimeout=::arg().asNum("client-tcp-timeout");
1839 g_maxTCPPerClient=::arg().asNum("max-tcp-per-client");
85c32340 1840 g_maxMThreads=::arg().asNum("max-mthreads");
343257a4 1841
c3828c03 1842 if(g_numThreads == 1) {
76698c6e 1843 L<<Logger::Warning<<"Operating unthreaded"<<endl;
76698c6e
BH
1844 recursorThread(0);
1845 }
1846 else {
1847 pthread_t tid;
c3828c03
BH
1848 L<<Logger::Warning<<"Launching "<< g_numThreads <<" threads"<<endl;
1849 for(unsigned int n=0; n < g_numThreads; ++n) {
77499b05 1850 pthread_create(&tid, 0, recursorThread, (void*)(long)n);
76698c6e
BH
1851 }
1852 void* res;
49a699c4
BH
1853
1854
76698c6e 1855 pthread_join(tid, &res);
bb4bdbaf 1856 }
bb4bdbaf
BH
1857 return 0;
1858}
1859
1860void* recursorThread(void* ptr)
1861try
1862{
2e2cd8ec 1863 t_id=(int) (long) ptr;
49a699c4 1864 SyncRes tmp(g_now); // make sure it allocates tsstorage before we do anything, like primeHints or so..
ac0e821b 1865 t_sstorage->domainmap = g_initialDomainMap;
49a699c4
BH
1866 t_allowFrom = g_initialAllowFrom;
1867 t_udpclientsocks = new UDPClientSocks();
bd0289fc 1868 t_tcpClientCounts = new tcpClientCounts_t();
49a699c4 1869 primeHints();
674cf0f6 1870
49a699c4
BH
1871 t_packetCache = new RecursorPacketCache();
1872
1873 L<<Logger::Warning<<"Done priming cache with root hints"<<endl;
1874
5704e107 1875 t_pdl = new shared_ptr<RecursorLua>();
49a699c4 1876
674cf0f6
BH
1877 try {
1878 if(!::arg()["lua-dns-script"].empty()) {
5704e107 1879 *t_pdl = shared_ptr<RecursorLua>(new RecursorLua(::arg()["lua-dns-script"]));
674cf0f6
BH
1880 L<<Logger::Warning<<"Loaded 'lua' script from '"<<::arg()["lua-dns-script"]<<"'"<<endl;
1881 }
1882
1883 }
1884 catch(std::exception &e) {
1885 L<<Logger::Error<<"Failed to load 'lua' script from '"<<::arg()["lua-dns-script"]<<"': "<<e.what()<<endl;
1886 exit(99);
1887 }
1888
77499b05
BH
1889 t_traceRegex = new shared_ptr<Regex>();
1890
1891
b3b5459d
BH
1892 t_remotes = new RemoteKeeper();
1893 t_remotes->remotes.resize(::arg().asNum("remotes-ringbuffer-entries") / g_numThreads);
1894
1895 if(!t_remotes->remotes.empty())
1896 memset(&t_remotes->remotes[0], 0, t_remotes->remotes.size() * sizeof(RemoteKeeper::remotes_t::value_type));
1897
1898
bb4bdbaf
BH
1899 MT=new MTasker<PacketID,string>(::arg().asNum("stack-size"));
1900
bb4bdbaf
BH
1901 PacketID pident;
1902
1903 t_fdm=getMultiplexer();
f3d1d67b 1904 if(!t_id) {
9097239c 1905 if(::arg().mustDo("experimental-json-interface")) {
f3d1d67b 1906 L<<Logger::Warning << "Enabling JSON interface" << endl;
8989097d
CH
1907 try {
1908 new JWebserver(t_fdm);
1909 }
1910 catch(PDNSException &e) {
1911 L<<Logger::Error<<"Exception: "<<e.reason<<endl;
1912 exit(99);
1913 }
f3d1d67b 1914 }
83252304 1915 L<<Logger::Error<<"Enabled '"<< t_fdm->getName() << "' multiplexer"<<endl;
f3d1d67b 1916 }
83252304 1917
49a699c4 1918 t_fdm->addReadFD(g_pipes[t_id].readToThread, handlePipeRequest);
83252304 1919
1bc3c142
BH
1920 if(!g_weDistributeQueries || !t_id) // if we distribute queries, only t_id = 0 listens
1921 for(deferredAdd_t::const_iterator i=deferredAdd.begin(); i!=deferredAdd.end(); ++i)
1922 t_fdm->addReadFD(i->first, i->second);
f7c1d4e3 1923
674cf0f6 1924 if(!t_id) {
674cf0f6
BH
1925 t_fdm->addReadFD(s_rcc.d_fd, handleRCC); // control channel
1926 }
1bc3c142 1927
f7c1d4e3 1928 unsigned int maxTcpClients=::arg().asNum("max-tcp-clients");
f7c1d4e3 1929
f7c1d4e3 1930 bool listenOnTCP(true);
49a699c4 1931
3427fa8a 1932 counter=0; // used to periodically execute certain tasks
f7c1d4e3 1933 for(;;) {
ac0e821b 1934 while(MT->schedule(&g_now)); // MTasker letting the mthreads do their thing
f7c1d4e3 1935
3427fa8a
BH
1936 if(!(counter%500)) {
1937 MT->makeThread(houseKeeping, 0);
f7c1d4e3
BH
1938 }
1939
d2392145 1940 if(!(counter%55)) {
d8f6d49f 1941 typedef vector<pair<int, FDMultiplexer::funcparam_t> > expired_t;
bb4bdbaf 1942 expired_t expired=t_fdm->getTimeouts(g_now);
4957a608 1943
f7c1d4e3 1944 for(expired_t::iterator i=expired.begin() ; i != expired.end(); ++i) {
cd989c87 1945 shared_ptr<TCPConnection> conn=any_cast<shared_ptr<TCPConnection> >(i->second);
4957a608 1946 if(g_logCommonErrors)
cd989c87 1947 L<<Logger::Warning<<"Timeout from remote TCP client "<< conn->d_remote.toString() <<endl;
4957a608 1948 t_fdm->removeReadFD(i->first);
f7c1d4e3
BH
1949 }
1950 }
1951
1952 counter++;
1953
3427fa8a 1954 if(!t_id && statsWanted) {
f7c1d4e3
BH
1955 doStats();
1956 }
1957
1958 Utility::gettimeofday(&g_now, 0);
bb4bdbaf 1959 t_fdm->run(&g_now);
3ea54bf0 1960 // 'run' updates g_now for us
f7c1d4e3
BH
1961
1962 if(listenOnTCP) {
50a5ef72 1963 if(TCPConnection::getCurrentConnections() > maxTcpClients) { // shutdown, too many connections
4957a608
BH
1964 for(tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i)
1965 t_fdm->removeReadFD(*i);
1966 listenOnTCP=false;
f7c1d4e3
BH
1967 }
1968 }
1969 else {
50a5ef72 1970 if(TCPConnection::getCurrentConnections() <= maxTcpClients) { // reenable
4957a608
BH
1971 for(tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i)
1972 t_fdm->addReadFD(*i, handleNewTCPQuestion);
1973 listenOnTCP=true;
f7c1d4e3
BH
1974 }
1975 }
1976 }
1977}
3f81d239 1978catch(PDNSException &ae) {
bb4bdbaf
BH
1979 L<<Logger::Error<<"Exception: "<<ae.reason<<endl;
1980 return 0;
1981}
1982catch(std::exception &e) {
1983 L<<Logger::Error<<"STL Exception: "<<e.what()<<endl;
1984 return 0;
1985}
1986catch(...) {
1987 L<<Logger::Error<<"any other exception in main: "<<endl;
1988 return 0;
1989}
1990
51e2144e 1991
288f4aa9
BH
1992int main(int argc, char **argv)
1993{
dbd23fc2
BH
1994 g_argc = argc;
1995 g_argv = argv;
5e3de507 1996 g_stats.startupTime=time(0);
ba1a571d 1997 versionSetProduct("Recursor");
8a63d3ce 1998 reportBasicTypes();
0007c2e5 1999 reportOtherTypes();
ea634573 2000
22030c37 2001 int ret = EXIT_SUCCESS;
caa6eefa 2002
288f4aa9 2003 try {
f888311c 2004 ::arg().set("stack-size","stack size per mthread")="200000";
2e3d8a19
BH
2005 ::arg().set("soa-minimum-ttl","Don't change")="0";
2006 ::arg().set("soa-serial-offset","Don't change")="0";
2007 ::arg().set("no-shuffle","Don't change")="off";
f555e92e 2008 ::arg().set("additional-processing","turn on to do additional processing")="off";
2e3d8a19
BH
2009 ::arg().set("aaaa-additional-processing","turn on to do AAAA additional processing (slow)")="off";
2010 ::arg().set("local-port","port to listen on")="53";
32252594 2011 ::arg().set("local-address","IP addresses to listen on, separated by spaces or commas. Also accepts ports.")="127.0.0.1";
77499b05 2012 ::arg().set("trace","if we should output heaps of logging. set to 'fail' to only log failing domains")="off";
2e3d8a19 2013 ::arg().set("daemon","Operate as a daemon")="yes";
0e9d9ce2 2014 ::arg().set("log-common-errors","If we should log rather common errors")="yes";
2e3d8a19
BH
2015 ::arg().set("chroot","switch to chroot jail")="";
2016 ::arg().set("setgid","If set, change group id to this gid for more security")="";
2017 ::arg().set("setuid","If set, change user id to this uid for more security")="";
5b0ddd18 2018 ::arg().set("network-timeout", "Wait this nummer of milliseconds for network i/o")="1500";
bb4bdbaf 2019 ::arg().set("threads", "Launch this number of threads")="2";
1bc3c142 2020 ::arg().set("processes", "Launch this number of processes (EXPERIMENTAL, DO NOT CHANGE)")="1";
5124de27 2021 ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
9097239c
PD
2022 ::arg().set( "experimental-logfile", "Filename of the log file for JSON parser" )= "/var/log/pdns.log";
2023 ::arg().setSwitch( "experimental-json-interface", "If we should run a JSON webserver") = "no";
c038218b 2024 ::arg().set("quiet","Suppress logging of questions and answers")="";
f27e6356 2025 ::arg().set("logging-facility","Facility to log messages as. 0 corresponds to local0")="";
2e3d8a19 2026 ::arg().set("config-dir","Location of configuration directory (recursor.conf)")=SYSCONFDIR;
fdbf35ac
BH
2027 ::arg().set("socket-owner","Owner of socket")="";
2028 ::arg().set("socket-group","Group of socket")="";
2029 ::arg().set("socket-mode", "Permissions for socket")="";
fdbf35ac 2030
2e3d8a19
BH
2031 ::arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
2032 ::arg().set("delegation-only","Which domains we only accept delegations from")="";
2033 ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
d4fb76e9 2034 ::arg().set("query-local-address6","Source IPv6 address for sending queries. IF UNSET, IPv6 WILL NOT BE USED FOR OUTGOING QUERIES")="";
2e3d8a19 2035 ::arg().set("client-tcp-timeout","Timeout in seconds when talking to TCP clients")="2";
85c32340 2036 ::arg().set("max-mthreads", "Maximum number of simultaneous Mtasker threads")="2048";
2e3d8a19
BH
2037 ::arg().set("max-tcp-clients","Maximum number of simultaneous TCP clients")="128";
2038 ::arg().set("hint-file", "If set, load root hints from this file")="";
b45eb27c 2039 ::arg().set("max-cache-entries", "If set, maximum number of entries in the main cache")="1000000";
a9af3782 2040 ::arg().set("max-negative-ttl", "maximum number of seconds to keep a negative cached entry in memory")="3600";
c3e753c7 2041 ::arg().set("max-cache-ttl", "maximum number of seconds to keep a cached entry in memory")="86400";
1051f8a9 2042 ::arg().set("packetcache-ttl", "maximum number of seconds to keep a cached entry in packetcache")="3600";
927c12b0 2043 ::arg().set("max-packetcache-entries", "maximum number of entries to keep in the packetcache")="500000";
1051f8a9 2044 ::arg().set("packetcache-servfail-ttl", "maximum number of seconds to keep a cached servfail entry in packetcache")="60";
7f7b8d55 2045 ::arg().set("server-id", "Returned when queried for 'server.id' TXT or NSID, defaults to hostname")="";
a9af3782 2046 ::arg().set("remotes-ringbuffer-entries", "maximum number of packets to store statistics for")="0";
ba1a571d 2047 ::arg().set("version-string", "string reported on version.pdns or version.bind")=fullVersionString();
49a699c4 2048 ::arg().set("allow-from", "If set, only allow these comma separated netmasks to recurse")=LOCAL_NETS;
2c95fc65 2049 ::arg().set("allow-from-file", "If set, load allowed netmasks from this file")="";
51e2144e 2050 ::arg().set("entropy-source", "If set, read entropy from this file")="/dev/urandom";
49a699c4 2051 ::arg().set("dont-query", "If set, do not query these netmasks for DNS data")=LOCAL_NETS;
4e120339 2052 ::arg().set("max-tcp-per-client", "If set, maximum number of TCP sessions per client (IP address)")="0";
0d5f0a9f 2053 ::arg().set("spoof-nearmiss-max", "If non-zero, assume spoofing after this many near misses")="20";
4ef015cd 2054 ::arg().set("single-socket", "If set, only use a single socket for outgoing queries")="off";
5605c067
BH
2055 ::arg().set("auth-zones", "Zones for which we have authoritative data, comma separated domain=file pairs ")="";
2056 ::arg().set("forward-zones", "Zones for which we forward queries, comma separated domain=ip pairs")="";
927c12b0
BH
2057 ::arg().set("forward-zones-recurse", "Zones for which we forward queries with recursion bit, comma separated domain=ip pairs")="";
2058 ::arg().set("forward-zones-file", "File with (+)domain=ip pairs for forwarding")="";
5605c067 2059 ::arg().set("export-etc-hosts", "If we should serve up contents from /etc/hosts")="off";
ac0b4eb3 2060 ::arg().set("export-etc-hosts-search-suffix", "Also serve up the contents of /etc/hosts with this suffix")="";
3ea54bf0 2061 ::arg().set("etc-hosts-file", "Path to 'hosts' file")="/etc/hosts";
9bc8c14c 2062 ::arg().set("serve-rfc1918", "If we should be authoritative for RFC 1918 private IP space")="";
4485aa35 2063 ::arg().set("lua-dns-script", "Filename containing an optional 'lua' script that will be used to modify dns answers")="";
578361b3 2064// ::arg().setSwitch( "disable-edns-ping", "Disable EDNSPing - EXPERIMENTAL, LEAVE DISABLED" )= "no";
2065 ::arg().setSwitch( "disable-edns", "Disable EDNS - EXPERIMENTAL, LEAVE DISABLED" )= "";
1bc3c142
BH
2066 ::arg().setSwitch( "disable-packetcache", "Disable packetcache" )= "no";
2067 ::arg().setSwitch( "pdns-distributes-queries", "If PowerDNS itself should distribute queries over threads (EXPERIMENTAL)")="no";
e661a20b 2068 ::arg().setSwitch( "any-to-tcp","Answer ANY queries with tc=1, shunting to TCP" )="no";
a09a8ce0
PD
2069 ::arg().set("udp-truncation-threshold", "Maximum UDP response size before we truncate")="1680";
2070
68e6df3c 2071 ::arg().set("include-dir","Include *.conf files from this directory")="";
2e3d8a19
BH
2072
2073 ::arg().setCmd("help","Provide a helpful message");
ba1a571d 2074 ::arg().setCmd("version","Print version string");
d5141417 2075 ::arg().setCmd("config","Output blank configuration");
f27e6356 2076 L.toConsole(Logger::Info);
2e3d8a19 2077 ::arg().laxParse(argc,argv); // do a lax parse
c75a6a9e 2078
5124de27
RA
2079 if(::arg()["config-name"]!="")
2080 s_programname+="-"+::arg()["config-name"];
2081
2082
577cf284
BH
2083 if(::arg().mustDo("config")) {
2084 cout<<::arg().configstring()<<endl;
2085 exit(0);
2086 }
2087
2088
5124de27 2089 string configname=::arg()["config-dir"]+"/"+s_programname+".conf";
c75a6a9e
BH
2090 cleanSlashes(configname);
2091
2e3d8a19 2092 if(!::arg().file(configname.c_str()))
c75a6a9e
BH
2093 L<<Logger::Warning<<"Unable to parse configuration file '"<<configname<<"'"<<endl;
2094
2e3d8a19 2095 ::arg().parse(argc,argv);
c836dc19 2096
2e3d8a19 2097 ::arg().set("delegation-only")=toLower(::arg()["delegation-only"]);
562588a3 2098
2e3d8a19 2099 if(::arg().mustDo("help")) {
b636533b 2100 cerr<<"syntax:"<<endl<<endl;
2e3d8a19 2101 cerr<<::arg().helpstring(::arg()["help"])<<endl;
b636533b
BH
2102 exit(99);
2103 }
5e3de507 2104 if(::arg().mustDo("version")) {
ba1a571d 2105 showProductVersion();
3613a51c 2106 showBuildConfiguration();
5e3de507
BH
2107 exit(99);
2108 }
b636533b 2109
f7c1d4e3 2110 serviceMain(argc, argv);
288f4aa9 2111 }
3f81d239 2112 catch(PDNSException &ae) {
c836dc19 2113 L<<Logger::Error<<"Exception: "<<ae.reason<<endl;
22030c37 2114 ret=EXIT_FAILURE;
288f4aa9 2115 }
fdbf35ac 2116 catch(std::exception &e) {
c836dc19 2117 L<<Logger::Error<<"STL Exception: "<<e.what()<<endl;
22030c37 2118 ret=EXIT_FAILURE;
288f4aa9
BH
2119 }
2120 catch(...) {
c836dc19 2121 L<<Logger::Error<<"any other exception in main: "<<endl;
22030c37 2122 ret=EXIT_FAILURE;
288f4aa9 2123 }
caa6eefa 2124
22030c37 2125 return ret;
288f4aa9 2126}