root/trunk/pdns/pdns/pdns_recursor.cc @ 1511

Revision 1511, 62.9 KB (checked in by ahu, 3 years ago)

reinstate top-remotes

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