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