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

Revision 1534, 62.8 KB (checked in by ahu, 3 years ago)

discovered by Darren Gamble, 'make install' did not work if a (currently) invalid configuration file was found. Plus documented --config.

  • 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  s_rcc.listen(sockname);
661}
662
663void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)
664{
665  TCPConnection* conn=any_cast<TCPConnection>(&var);
666
667  if(conn->state==TCPConnection::BYTE0) {
668    int bytes=recv(conn->fd, conn->data, 2, 0);
669    if(bytes==1)
670      conn->state=TCPConnection::BYTE1;
671    if(bytes==2) { 
672      conn->qlen=(((unsigned char)conn->data[0]) << 8)+ (unsigned char)conn->data[1];
673      conn->bytesread=0;
674      conn->state=TCPConnection::GETQUESTION;
675    }
676    if(!bytes || bytes < 0) {
677      TCPConnection tmp(*conn); 
678      t_fdm->removeReadFD(fd);
679      tmp.closeAndCleanup();
680      return;
681    }
682  }
683  else if(conn->state==TCPConnection::BYTE1) {
684    int bytes=recv(conn->fd, conn->data+1, 1, 0);
685    if(bytes==1) {
686      conn->state=TCPConnection::GETQUESTION;
687      conn->qlen=(((unsigned char)conn->data[0]) << 8)+ (unsigned char)conn->data[1];
688      conn->bytesread=0;
689    }
690    if(!bytes || bytes < 0) {
691      if(g_logCommonErrors)
692        L<<Logger::Error<<"TCP client "<< conn->remote.toString() <<" disconnected after first byte"<<endl;
693      TCPConnection tmp(*conn); 
694      t_fdm->removeReadFD(fd);
695      tmp.closeAndCleanup();  // conn loses validity here..
696      return;
697    }
698  }
699  else if(conn->state==TCPConnection::GETQUESTION) {
700    int bytes=recv(conn->fd, conn->data + conn->bytesread, conn->qlen - conn->bytesread, 0);
701    if(!bytes || bytes < 0) {
702      L<<Logger::Error<<"TCP client "<< conn->remote.toString() <<" disconnected while reading question body"<<endl;
703      TCPConnection tmp(*conn);
704      t_fdm->removeReadFD(fd);
705      tmp.closeAndCleanup();  // conn loses validity here..
706
707      return;
708    }
709    conn->bytesread+=bytes;
710    if(conn->bytesread==conn->qlen) {
711      TCPConnection tconn(*conn); 
712      t_fdm->removeReadFD(fd); // should no longer awake ourselves when there is data to read
713
714      DNSComboWriter* dc=0;
715      try {
716        dc=new DNSComboWriter(tconn.data, tconn.qlen, g_now);
717      }
718      catch(MOADNSException &mde) {
719        g_stats.clientParseError++; 
720        if(g_logCommonErrors)
721          L<<Logger::Error<<"Unable to parse packet from TCP client "<< tconn.remote.toString() <<endl;
722        tconn.closeAndCleanup();
723        return;
724      }
725     
726      dc->setSocket(tconn.fd);
727      dc->d_tcp=true;
728      dc->setRemote(&tconn.remote);
729      if(dc->d_mdp.d_header.qr) {
730        delete dc;
731        L<<Logger::Error<<"Ignoring answer on server socket!"<<endl;
732        tconn.closeAndCleanup();
733        return;
734      }
735      else {
736        ++g_stats.qcounter;
737        ++g_stats.tcpqcounter;
738        MT->makeThread(startDoResolve, dc); // deletes dc
739        return;
740      }
741    }
742  }
743}
744
745//! Handle new incoming TCP connection
746void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t& )
747{
748  ComboAddress addr;
749  socklen_t addrlen=sizeof(addr);
750  int newsock=(int)accept(fd, (struct sockaddr*)&addr, &addrlen);
751  if(newsock>0) {
752    if(MT->numProcesses() > g_maxMThreads) {
753      g_stats.overCapacityDrops++;
754      Utility::closesocket(newsock);
755      return;
756    }
757
758    t_remotes->addRemote(addr);
759    if(t_allowFrom && !t_allowFrom->match(&addr)) {
760      if(!g_quiet) 
761        L<<Logger::Error<<"["<<MT->getTid()<<"] dropping TCP query from "<<addr.toString()<<", address not matched by allow-from"<<endl;
762
763      g_stats.unauthorizedTCP++;
764      Utility::closesocket(newsock);
765      return;
766    }
767   
768    if(g_maxTCPPerClient && g_tcpClientCounts.count(addr) && g_tcpClientCounts[addr] >= g_maxTCPPerClient) {
769      g_stats.tcpClientOverflow++;
770      Utility::closesocket(newsock); // don't call TCPConnection::closeAndCleanup here - did not enter it in the counts yet!
771      return;
772    }
773    g_tcpClientCounts[addr]++;
774    Utility::setNonBlocking(newsock);
775    TCPConnection tc;
776    tc.fd=newsock;
777    tc.state=TCPConnection::BYTE0;
778    tc.remote=addr;
779    tc.startTime=g_now.tv_sec;
780    TCPConnection::s_currentConnections++;
781    t_fdm->addReadFD(tc.fd, handleRunningTCPQuestion, tc);
782
783    struct timeval now;
784    Utility::gettimeofday(&now, 0);
785    t_fdm->setReadTTD(tc.fd, now, g_tcpTimeout);
786  }
787}
788 
789void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
790{
791  int len;
792  char data[1500];
793  ComboAddress fromaddr;
794  socklen_t addrlen=sizeof(fromaddr);
795 
796  if((len=recvfrom(fd, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen)) >= 0) {
797    t_remotes->addRemote(fromaddr);
798
799    if(t_allowFrom && !t_allowFrom->match(&fromaddr)) {
800      if(!g_quiet) 
801        L<<Logger::Error<<"["<<MT->getTid()<<"] dropping UDP query from "<<fromaddr.toString()<<", address not matched by allow-from"<<endl;
802
803      g_stats.unauthorizedUDP++;
804      return;
805    }
806    try {
807      dnsheader* dh=(dnsheader*)data;
808     
809      if(dh->qr) {
810        if(g_logCommonErrors)
811          L<<Logger::Error<<"Ignoring answer from "<<fromaddr.toString()<<" on server socket!"<<endl;
812      }
813      else {
814        ++g_stats.qcounter;
815
816        string response;
817        try {
818          if(!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(string(data, len), g_now.tv_sec, &response)) {
819            if(!g_quiet)
820              L<<Logger::Error<<t_id<< " question answered from packet cache from "<<fromaddr.toString()<<endl;
821 
822            g_stats.packetCacheHits++;
823            SyncRes::s_queries++;
824            sendto(fd, response.c_str(), response.length(), 0, (struct sockaddr*) &fromaddr, fromaddr.getSocklen());
825            if(response.length() >= sizeof(struct dnsheader))
826              updateRcodeStats(((struct dnsheader*)response.c_str())->rcode);
827            g_stats.avgLatencyUsec=(uint64_t)((1-0.0001)*g_stats.avgLatencyUsec + 0); // we assume 0 usec
828            return;
829          }
830        } 
831        catch(std::exception& e) {
832          throw MOADNSException(e.what()); // translate
833        }
834        if(MT->numProcesses() > g_maxMThreads) {
835          g_stats.overCapacityDrops++;
836          return;
837        }
838 
839        DNSComboWriter* dc = new DNSComboWriter(data, len, g_now);
840        dc->setSocket(fd);
841        dc->setRemote(&fromaddr);
842
843        dc->d_tcp=false;
844
845        MT->makeThread(startDoResolve, (void*) dc); // deletes dc
846      }
847    }
848    catch(MOADNSException& mde) {
849      g_stats.clientParseError++; 
850      if(g_logCommonErrors)
851        L<<Logger::Error<<"Unable to parse packet from remote UDP client "<<fromaddr.toString() <<": "<<mde.what()<<endl;
852    }
853  }
854  else {
855    // cerr<<t_id<<" had error: "<<stringerror()<<endl;
856  }
857}
858
859typedef vector<pair<int, function< void(int, any&) > > > deferredAdd_t;
860deferredAdd_t deferredAdd;
861
862void makeTCPServerSockets()
863{
864  int fd;
865  vector<string>locals;
866  stringtok(locals,::arg()["local-address"]," ,");
867
868  if(locals.empty())
869    throw AhuException("No local address specified");
870 
871  for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
872    ServiceTuple st;
873    st.port=::arg().asNum("local-port");
874    parseService(*i, st);
875   
876    ComboAddress sin;
877
878    memset((char *)&sin,0, sizeof(sin));
879    sin.sin4.sin_family = AF_INET;
880    if(!IpToU32(st.host, (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
881      sin.sin6.sin6_family = AF_INET6;
882      if(Utility::inet_pton(AF_INET6, st.host.c_str(), &sin.sin6.sin6_addr) <= 0)
883        throw AhuException("Unable to resolve local address for TCP server on '"+ st.host +"'"); 
884    }
885
886    fd=socket(sin.sin6.sin6_family, SOCK_STREAM, 0);
887    if(fd<0) 
888      throw AhuException("Making a TCP server socket for resolver: "+stringerror());
889
890    int tmp=1;
891    if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
892      L<<Logger::Error<<"Setsockopt failed for TCP listening socket"<<endl;
893      exit(1);
894    }
895   
896#ifdef TCP_DEFER_ACCEPT
897    if(setsockopt(fd, SOL_TCP,TCP_DEFER_ACCEPT,(char*)&tmp,sizeof tmp) >= 0) {
898      if(i==locals.begin())
899        L<<Logger::Error<<"Enabled TCP data-ready filter for (slight) DoS protection"<<endl;
900    }
901#endif
902
903    sin.sin4.sin_port = htons(st.port);
904    int socklen=sin.sin4.sin_family==AF_INET ? sizeof(sin.sin4) : sizeof(sin.sin6);
905    if (::bind(fd, (struct sockaddr *)&sin, socklen )<0) 
906      throw AhuException("Binding TCP server socket for "+ st.host +": "+stringerror());
907   
908    Utility::setNonBlocking(fd);
909    setSocketSendBuffer(fd, 65000);
910    listen(fd, 128);
911    deferredAdd.push_back(make_pair(fd, handleNewTCPQuestion));
912    g_tcpListenSockets.push_back(fd);
913
914    if(sin.sin4.sin_family == AF_INET) 
915      L<<Logger::Error<<"Listening for TCP queries on "<< sin.toString() <<":"<<st.port<<endl;
916    else
917      L<<Logger::Error<<"Listening for TCP queries on ["<< sin.toString() <<"]:"<<st.port<<endl;
918  }
919}
920
921
922
923void makeUDPServerSockets()
924{
925  vector<string>locals;
926  stringtok(locals,::arg()["local-address"]," ,");
927
928  if(locals.empty())
929    throw AhuException("No local address specified");
930 
931  if(::arg()["local-address"]=="0.0.0.0") {
932    L<<Logger::Warning<<"It is advised to bind to explicit addresses with the --local-address option"<<endl;
933  }
934
935  for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
936    ServiceTuple st;
937    st.port=::arg().asNum("local-port");
938    parseService(*i, st);
939
940    ComboAddress sin;
941
942    memset(&sin, 0, sizeof(sin));
943    sin.sin4.sin_family = AF_INET;
944    if(!IpToU32(st.host.c_str() , (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
945      sin.sin6.sin6_family = AF_INET6;
946      if(Utility::inet_pton(AF_INET6, st.host.c_str(), &sin.sin6.sin6_addr) <= 0)
947        throw AhuException("Unable to resolve local address for UDP server on '"+ st.host +"'"); 
948    }
949   
950    int fd=socket(sin.sin4.sin_family, SOCK_DGRAM, 0);
951
952    if(fd < 0) {
953      throw AhuException("Making a UDP server socket for resolver: "+netstringerror());
954    }
955
956    setSocketReceiveBuffer(fd, 200000);
957    sin.sin4.sin_port = htons(st.port);
958
959    int socklen=sin.sin4.sin_family==AF_INET ? sizeof(sin.sin4) : sizeof(sin.sin6);
960    if (::bind(fd, (struct sockaddr *)&sin, socklen)<0) 
961      throw AhuException("Resolver binding to server socket on port "+ lexical_cast<string>(st.port) +" for "+ st.host+": "+stringerror());
962   
963    Utility::setNonBlocking(fd);
964
965    deferredAdd.push_back(make_pair(fd, handleNewUDPQuestion));
966    g_listenSocketsAddresses[fd]=sin;  // this is written to only from the startup thread, not from the workers
967    if(sin.sin4.sin_family == AF_INET) 
968      L<<Logger::Error<<"Listening for UDP queries on "<< sin.toString() <<":"<<st.port<<endl;
969    else
970      L<<Logger::Error<<"Listening for UDP queries on ["<< sin.toString() <<"]:"<<st.port<<endl;
971  }
972}
973
974
975#ifndef WIN32
976void daemonize(void)
977{
978  if(fork())
979    exit(0); // bye bye
980 
981  setsid(); 
982
983  int i=open("/dev/null",O_RDWR); /* open stdin */
984  if(i < 0) 
985    L<<Logger::Critical<<"Unable to open /dev/null: "<<stringerror()<<endl;
986  else {
987    dup2(i,0); /* stdin */
988    dup2(i,1); /* stderr */
989    dup2(i,2); /* stderr */
990    close(i);
991  }
992}
993#endif
994
995uint64_t counter;
996bool statsWanted;
997
998void usr1Handler(int)
999{
1000  statsWanted=true;
1001}
1002
1003void usr2Handler(int)
1004{
1005  SyncRes::setLog(true);
1006  g_quiet=false;
1007  ::arg().set("quiet")="no";
1008
1009}
1010
1011void doStats(void)
1012{
1013  static time_t lastOutputTime;
1014  static uint64_t lastQueryCount;
1015 
1016  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
1017    uint64_t cacheHits = broadcastAccFunction<uint64_t>(pleaseGetCacheHits);
1018    uint64_t cacheMisses = broadcastAccFunction<uint64_t>(pleaseGetCacheMisses);
1019   
1020    L<<Logger::Warning<<"stats: "<<g_stats.qcounter<<" questions, "<<
1021      broadcastAccFunction<uint64_t>(pleaseGetCacheSize)<< " cache entries, "<<
1022      broadcastAccFunction<uint64_t>(pleaseGetNegCacheSize)<<" negative entries, "<<
1023      (int)((cacheHits*100.0)/(cacheHits+cacheMisses))<<"% cache hits"<<endl; 
1024   
1025    L<<Logger::Warning<<"stats: throttle map: "
1026      << broadcastAccFunction<uint64_t>(pleaseGetThrottleSize) <<", ns speeds: "
1027      << broadcastAccFunction<uint64_t>(pleaseGetNsSpeedsSize)<<endl; 
1028    L<<Logger::Warning<<"stats: outpacket/query ratio "<<(int)(SyncRes::s_outqueries*100.0/SyncRes::s_queries)<<"%";
1029    L<<Logger::Warning<<", "<<(int)(SyncRes::s_throttledqueries*100.0/(SyncRes::s_outqueries+SyncRes::s_throttledqueries))<<"% throttled, "
1030     <<SyncRes::s_nodelegated<<" no-delegation drops"<<endl;
1031    L<<Logger::Warning<<"stats: "<<SyncRes::s_tcpoutqueries<<" outgoing tcp connections, "<<
1032      broadcastAccFunction<uint64_t>(pleaseGetConcurrentQueries)<<" queries running, "<<SyncRes::s_outgoingtimeouts<<" outgoing timeouts"<<endl;
1033
1034    //L<<Logger::Warning<<"stats: "<<g_stats.ednsPingMatches<<" ping matches, "<<g_stats.ednsPingMismatches<<" mismatches, "<<
1035      //g_stats.noPingOutQueries<<" outqueries w/o ping, "<< g_stats.noEdnsOutQueries<<" w/o EDNS"<<endl;
1036   
1037    L<<Logger::Warning<<"stats: " <<  broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize) <<
1038    " packet cache entries, "<<(int)(100.0*broadcastAccFunction<uint64_t>(pleaseGetPacketCacheHits)/SyncRes::s_queries) << "% packet cache hits"<<endl;
1039   
1040    time_t now = time(0);
1041    if(lastOutputTime && lastQueryCount && now != lastOutputTime) {
1042      L<<Logger::Warning<<"stats: "<< (SyncRes::s_queries - lastQueryCount) / (now - lastOutputTime) <<" qps (average over "<< (now - lastOutputTime) << " seconds)"<<endl;
1043    }
1044    lastOutputTime = now;
1045    lastQueryCount = SyncRes::s_queries;
1046  }
1047  else if(statsWanted) 
1048    L<<Logger::Warning<<"stats: no stats yet!"<<endl;
1049
1050  statsWanted=false;
1051}
1052
1053static void houseKeeping(void *)
1054try
1055{
1056  static __thread time_t last_stat, last_rootupdate, last_prune;
1057  static __thread int cleanCounter=0;
1058  struct timeval now;
1059  Utility::gettimeofday(&now, 0);
1060
1061//  clog<<"* "<<t_id<<" "<<(void*)&last_stat<<"\t"<<(unsigned int)last_stat<<endl;
1062
1063  if(now.tv_sec - last_prune > (time_t)(5 + t_id)) { 
1064    DTime dt;
1065    dt.setTimeval(now);
1066    t_RC->doPrune(); // this function is local to a thread, so fine anyhow
1067    t_packetCache->doPruneTo(::arg().asNum("max-packetcache-entries") / g_numThreads);
1068   
1069    typedef SyncRes::negcache_t::nth_index<1>::type negcache_by_ttd_index_t;
1070    negcache_by_ttd_index_t& ttdindex=boost::multi_index::get<1>(t_sstorage->negcache); 
1071
1072    negcache_by_ttd_index_t::iterator i=ttdindex.lower_bound(now.tv_sec);
1073    ttdindex.erase(ttdindex.begin(), i);
1074   
1075    if(!((cleanCounter++)%40)) {  // this is a full scan!
1076      time_t limit=now.tv_sec-300;
1077      for(SyncRes::nsspeeds_t::iterator i = t_sstorage->nsSpeeds.begin() ; i!= t_sstorage->nsSpeeds.end(); )
1078        if(i->second.stale(limit))
1079          t_sstorage->nsSpeeds.erase(i++);
1080        else
1081          ++i;
1082    }
1083//    L<<Logger::Warning<<"Spent "<<dt.udiff()/1000<<" msec cleaning"<<endl;
1084    last_prune=time(0);
1085  }
1086 
1087  if(!t_id) {
1088    if(now.tv_sec - last_stat > 1800) { 
1089      doStats();
1090      last_stat=time(0);
1091    }
1092  }
1093 
1094  if(now.tv_sec - last_rootupdate > 7200) {
1095    SyncRes sr(now);
1096    sr.setDoEDNS0(true);
1097    vector<DNSResourceRecord> ret;
1098
1099    sr.setNoCache();
1100    int res=sr.beginResolve(".", QType(QType::NS), 1, ret);
1101    if(!res) {
1102      L<<Logger::Warning<<"Refreshed . records"<<endl;
1103      last_rootupdate=now.tv_sec;
1104    }
1105    else
1106      L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
1107  }
1108}
1109catch(AhuException& ae)
1110{
1111  L<<Logger::Error<<"Fatal error: "<<ae.reason<<endl;
1112  throw;
1113}
1114;
1115
1116void makeThreadPipes()
1117{
1118  for(unsigned int n=0; n < g_numThreads; ++n) {
1119    struct ThreadPipeSet tps;
1120    int fd[2];
1121    if(pipe(fd) < 0)
1122      unixDie("Creating pipe for inter-thread communications");
1123   
1124    tps.readToThread = fd[0];
1125    tps.writeToThread = fd[1];
1126   
1127    if(pipe(fd) < 0)
1128      unixDie("Creating pipe for inter-thread communications");
1129    tps.readFromThread = fd[0];
1130    tps.writeFromThread = fd[1];
1131   
1132    g_pipes.push_back(tps);
1133  }
1134}
1135
1136void broadcastFunction(const pipefunc_t& func, bool skipSelf)
1137{
1138  unsigned int n = 0;
1139  BOOST_FOREACH(ThreadPipeSet& tps, g_pipes) 
1140  {
1141    if(n++ == t_id) {
1142      if(!skipSelf)
1143        func(); // don't write to ourselves!
1144      continue;
1145    }
1146     
1147    pipefunc_t *funcptr = new pipefunc_t(func);
1148    if(write(tps.writeToThread, &funcptr, sizeof(funcptr)) != sizeof(funcptr))
1149      unixDie("write to thread pipe returned wrong size or error");
1150   
1151    string* resp;
1152    if(read(tps.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
1153      unixDie("read from thread pipe returned wrong size or error");
1154   
1155    if(resp) {
1156//      cerr <<"got response: " << *resp << endl;
1157      delete resp;
1158    }
1159  }
1160}
1161
1162
1163
1164void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var)
1165{
1166  pipefunc_t* func;
1167  if(read(fd, &func, sizeof(func)) != sizeof(func)) { // fd == readToThread
1168    unixDie("read from thread pipe returned wrong size or error");
1169  }
1170 
1171  void *resp = (*func)();
1172 
1173  if(write(g_pipes[t_id].writeFromThread, &resp, sizeof(resp)) != sizeof(resp))
1174    unixDie("write to thread pipe returned wrong size or error");
1175 
1176  delete func;
1177}
1178
1179template<class T> void *voider(const boost::function<T*()>& func)
1180{
1181  return func();
1182}
1183
1184vector<ComboAddress>& operator+=(vector<ComboAddress>&a, const vector<ComboAddress>& b)
1185{
1186  a.insert(a.end(), b.begin(), b.end());
1187  return a;
1188}
1189
1190
1191
1192template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool skipSelf)
1193{
1194  unsigned int n = 0;
1195  T ret=T();
1196  BOOST_FOREACH(ThreadPipeSet& tps, g_pipes) 
1197  {
1198    if(n++ == t_id) {
1199      if(!skipSelf) {
1200        T* resp = (T*)func(); // don't write to ourselves!
1201        if(resp) {
1202          //~ cerr <<"got direct: " << *resp << endl;
1203          ret += *resp;
1204          delete resp;
1205        }
1206      }
1207      continue;
1208    }
1209     
1210    pipefunc_t *funcptr = new pipefunc_t(boost::bind(voider<T>, func));
1211    if(write(tps.writeToThread, &funcptr, sizeof(funcptr)) != sizeof(funcptr))
1212      unixDie("write to thread pipe returned wrong size or error");
1213   
1214    T* resp;
1215    if(read(tps.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
1216      unixDie("read from thread pipe returned wrong size or error");
1217   
1218    if(resp) {
1219      //~ cerr <<"got response: " << *resp << endl;
1220      ret += *resp;
1221      delete resp;
1222    }
1223  }
1224  return ret;
1225}
1226
1227template string broadcastAccFunction(const boost::function<string*()>& fun, bool skipSelf); // explicit instantiation
1228template uint64_t broadcastAccFunction(const boost::function<uint64_t*()>& fun, bool skipSelf); // explicit instantiation
1229template vector<ComboAddress> broadcastAccFunction(const boost::function<vector<ComboAddress> *()>& fun, bool skipSelf); // explicit instantiation
1230
1231void handleRCC(int fd, FDMultiplexer::funcparam_t& var)
1232{
1233  string remote;
1234  string msg=s_rcc.recv(&remote);
1235  RecursorControlParser rcp;
1236  RecursorControlParser::func_t* command;
1237  string answer=rcp.getAnswer(msg, &command);
1238  try {
1239    s_rcc.send(answer, &remote);
1240    command();
1241  }
1242  catch(std::exception& e) {
1243    L<<Logger::Error<<"Error dealing with control socket request: "<<e.what()<<endl;
1244  }
1245  catch(AhuException& ae) {
1246    L<<Logger::Error<<"Error dealing with control socket request: "<<ae.reason<<endl;
1247  }
1248}
1249
1250void handleTCPClientReadable(int fd, FDMultiplexer::funcparam_t& var)
1251{
1252  PacketID* pident=any_cast<PacketID>(&var);
1253  //  cerr<<"handleTCPClientReadable called for fd "<<fd<<", pident->inNeeded: "<<pident->inNeeded<<", "<<pident->sock->getHandle()<<endl;
1254
1255  shared_array<char> buffer(new char[pident->inNeeded]);
1256
1257  int ret=recv(fd, buffer.get(), pident->inNeeded,0);
1258  if(ret > 0) {
1259    pident->inMSG.append(&buffer[0], &buffer[ret]);
1260    pident->inNeeded-=ret;
1261    if(!pident->inNeeded) {
1262      //      cerr<<"Got entire load of "<<pident->inMSG.size()<<" bytes"<<endl;
1263      PacketID pid=*pident;
1264      string msg=pident->inMSG;
1265     
1266      t_fdm->removeReadFD(fd);
1267      MT->sendEvent(pid, &msg); 
1268    }
1269    else {
1270      //      cerr<<"Still have "<<pident->inNeeded<<" left to go"<<endl;
1271    }
1272  }
1273  else {
1274    PacketID tmp=*pident;
1275    t_fdm->removeReadFD(fd); // pident might now be invalid (it isn't, but still)
1276    string empty;
1277    MT->sendEvent(tmp, &empty); // this conveys error status
1278  }
1279}
1280
1281void handleTCPClientWritable(int fd, FDMultiplexer::funcparam_t& var)
1282{
1283  PacketID* pid=any_cast<PacketID>(&var);
1284  int ret=send(fd, pid->outMSG.c_str() + pid->outPos, pid->outMSG.size() - pid->outPos,0);
1285  if(ret > 0) {
1286    pid->outPos+=ret;
1287    if(pid->outPos==pid->outMSG.size()) {
1288      PacketID tmp=*pid;
1289      t_fdm->removeWriteFD(fd);
1290      MT->sendEvent(tmp, &tmp.outMSG);  // send back what we sent to convey everything is ok
1291    }
1292  }
1293  else {  // error or EOF
1294    PacketID tmp(*pid);
1295    t_fdm->removeWriteFD(fd);
1296    string sent;
1297    MT->sendEvent(tmp, &sent);         // we convey error status by sending empty string
1298  }
1299}
1300
1301// resend event to everybody chained onto it
1302void doResends(MT_t::waiters_t::iterator& iter, PacketID resend, const string& content)
1303{
1304  if(iter->key.chain.empty())
1305    return;
1306  //  cerr<<"doResends called!\n";
1307  for(PacketID::chain_t::iterator i=iter->key.chain.begin(); i != iter->key.chain.end() ; ++i) {
1308    resend.fd=-1;
1309    resend.id=*i;
1310    //    cerr<<"\tResending "<<content.size()<<" bytes for fd="<<resend.fd<<" and id="<<resend.id<<endl;
1311
1312    MT->sendEvent(resend, &content);
1313    g_stats.chainResends++;
1314  }
1315}
1316
1317void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t& var)
1318{
1319  PacketID pid=any_cast<PacketID>(var);
1320  int len;
1321  char data[1500];
1322  ComboAddress fromaddr;
1323  socklen_t addrlen=sizeof(fromaddr);
1324
1325  len=recvfrom(fd, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen);
1326
1327  if(len < (int)sizeof(dnsheader)) {
1328    if(len < 0)
1329      ; //      cerr<<"Error on fd "<<fd<<": "<<stringerror()<<"\n";
1330    else {
1331      g_stats.serverParseError++; 
1332      if(g_logCommonErrors)
1333        L<<Logger::Error<<"Unable to parse packet from remote UDP server "<< sockAddrToString((struct sockaddr_in*) &fromaddr) <<
1334          ": packet smalller than DNS header"<<endl;
1335    }
1336
1337    t_udpclientsocks->returnSocket(fd);
1338    string empty;
1339
1340    MT_t::waiters_t::iterator iter=MT->d_waiters.find(pid);
1341    if(iter != MT->d_waiters.end()) 
1342      doResends(iter, pid, empty);
1343   
1344    MT->sendEvent(pid, &empty); // this denotes error (does lookup again.. at least L1 will be hot)
1345    return;
1346  } 
1347
1348  dnsheader dh;
1349  memcpy(&dh, data, sizeof(dh));
1350 
1351  if(dh.qr) {
1352    PacketID pident;
1353    pident.remote=fromaddr;
1354    pident.id=dh.id;
1355    pident.fd=fd;
1356    if(!dh.qdcount) { // UPC, Nominum, very old BIND on FormErr, NSD
1357      pident.domain.clear();
1358      pident.type = 0;
1359    }
1360    else {
1361      try {
1362        pident.domain=questionExpand(data, len, pident.type); // don't copy this from above - we need to do the actual read
1363      }
1364      catch(std::exception& e) {
1365        g_stats.serverParseError++; // won't be fed to lwres.cc, so we have to increment
1366        L<<Logger::Warning<<"Error in packet from "<<sockAddrToString((struct sockaddr_in*) &fromaddr) << ": "<<e.what() << endl;
1367        return;
1368      }
1369    }
1370    string packet;
1371    packet.assign(data, len);
1372
1373    MT_t::waiters_t::iterator iter=MT->d_waiters.find(pident);
1374    if(iter != MT->d_waiters.end()) {
1375      doResends(iter, pident, packet);
1376    }
1377
1378  retryWithName:
1379
1380    if(!MT->sendEvent(pident, &packet)) {
1381     
1382      // 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
1383      for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
1384        if(pident.fd==mthread->key.fd && mthread->key.remote==pident.remote &&  mthread->key.type == pident.type &&
1385           pdns_iequals(pident.domain, mthread->key.domain)) {
1386          mthread->key.nearMisses++;
1387        }
1388
1389        // be a bit paranoid here since we're weakening our matching
1390        if(pident.domain.empty() && !mthread->key.domain.empty() && !pident.type && mthread->key.type && 
1391           pident.id  == mthread->key.id && mthread->key.remote == pident.remote) {
1392          //        cerr<<"Empty response, rest matches though, sending to a waiter"<<endl;
1393          pident.domain = mthread->key.domain;
1394          pident.type = mthread->key.type;
1395          goto retryWithName;
1396        }
1397      }
1398      g_stats.unexpectedCount++; // if we made it here, it really is an unexpected answer
1399      if(g_logCommonErrors)
1400        L<<Logger::Warning<<"Discarding unexpected packet from "<<fromaddr.toString()<<": "<<pident.domain<<", "<<pident.type<<endl;
1401    }
1402    else if(fd >= 0) {
1403      t_udpclientsocks->returnSocket(fd);
1404    }
1405  }
1406  else
1407    L<<Logger::Warning<<"Ignoring question on outgoing socket from "<< sockAddrToString((struct sockaddr_in*) &fromaddr)  <<endl;
1408}
1409
1410FDMultiplexer* getMultiplexer()
1411{
1412  FDMultiplexer* ret;
1413  for(FDMultiplexer::FDMultiplexermap_t::const_iterator i = FDMultiplexer::getMultiplexerMap().begin();
1414      i != FDMultiplexer::getMultiplexerMap().end(); ++i) {
1415    try {
1416      ret=i->second();
1417      return ret;
1418    }
1419    catch(FDMultiplexerException &fe) {
1420      L<<Logger::Error<<"Non-fatal error initializing possible multiplexer ("<<fe.what()<<"), falling back"<<endl;
1421    }
1422    catch(...) {
1423      L<<Logger::Error<<"Non-fatal error initializing possible multiplexer"<<endl;
1424    }
1425  }
1426  L<<Logger::Error<<"No working multiplexer found!"<<endl;
1427  exit(1);
1428}
1429
1430 
1431void* doReloadLuaScript()
1432{
1433  string fname= ::arg()["lua-dns-script"];
1434  try {
1435    if(fname.empty()) {
1436      t_pdl->reset();
1437      L<<Logger::Error<<t_id<<" Unloaded current lua script"<<endl;
1438    }
1439    else {
1440      *t_pdl = shared_ptr<PowerDNSLua>(new PowerDNSLua(fname));
1441    }
1442  }
1443  catch(std::exception& e) {
1444    L<<Logger::Error<<t_id<<" Retaining current script, error from '"<<fname<<"': "<< e.what() <<endl;
1445  }
1446   
1447  L<<Logger::Warning<<t_id<<" (Re)loaded lua script from '"<<fname<<"'"<<endl;
1448  return 0;
1449}
1450
1451string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end)
1452{
1453  if(begin != end) 
1454    ::arg().set("lua-dns-script") = *begin;
1455 
1456  broadcastFunction(doReloadLuaScript);
1457 
1458  return "ok, reload/unload queued\n";
1459} 
1460
1461void* recursorThread(void*);
1462
1463void* pleaseSupplantACLs(NetmaskGroup *ng)
1464{
1465  t_allowFrom = ng;
1466  return 0;
1467}
1468
1469void parseACLs()
1470{
1471  static bool l_initialized;
1472 
1473  if(l_initialized) { // only reload configuration file on second call
1474    string configname=::arg()["config-dir"]+"/recursor.conf";
1475    cleanSlashes(configname);
1476   
1477    if(!::arg().preParseFile(configname.c_str(), "allow-from-file")) 
1478      L<<Logger::Warning<<"Unable to re-parse configuration file '"<<configname<<"'"<<endl;
1479   
1480    ::arg().preParseFile(configname.c_str(), "allow-from", LOCAL_NETS);
1481  }
1482
1483  NetmaskGroup* oldAllowFrom = t_allowFrom, *allowFrom=new NetmaskGroup;
1484 
1485  if(!::arg()["allow-from-file"].empty()) {
1486    string line;
1487    ifstream ifs(::arg()["allow-from-file"].c_str());
1488    if(!ifs) {
1489      delete allowFrom; 
1490      throw runtime_error("Could not open '"+::arg()["allow-from-file"]+"': "+stringerror());
1491    }
1492
1493    string::size_type pos;
1494    while(getline(ifs,line)) {
1495      pos=line.find('#');
1496      if(pos!=string::npos)
1497        line.resize(pos);
1498      trim(line);
1499      if(line.empty())
1500        continue;
1501
1502      allowFrom->addMask(line);
1503    }
1504    L<<Logger::Warning<<"Done parsing " << allowFrom->size() <<" allow-from ranges from file '"<<::arg()["allow-from-file"]<<"' - overriding 'allow-from' setting"<<endl;
1505  }
1506  else if(!::arg()["allow-from"].empty()) {
1507    vector<string> ips;
1508    stringtok(ips, ::arg()["allow-from"], ", ");
1509    L<<Logger::Warning<<"Only allowing queries from: ";
1510    for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
1511      allowFrom->addMask(*i);
1512      if(i!=ips.begin())
1513        L<<Logger::Warning<<", ";
1514      L<<Logger::Warning<<*i;
1515    }
1516    L<<Logger::Warning<<endl;
1517  }
1518  else {
1519    if(::arg()["local-address"]!="127.0.0.1" && ::arg().asNum("local-port")==53) 
1520      L<<Logger::Error<<"WARNING: Allowing queries from all IP addresses - this can be a security risk!"<<endl;
1521    delete allowFrom;
1522    allowFrom = 0;
1523  }
1524 
1525  g_initialAllowFrom = allowFrom;
1526  broadcastFunction(boost::bind(pleaseSupplantACLs, allowFrom));
1527  delete oldAllowFrom;
1528 
1529  l_initialized = true;
1530}
1531
1532int serviceMain(int argc, char*argv[])
1533{
1534  L.setName("pdns_recursor");
1535
1536  L.setLoglevel((Logger::Urgency)(6)); // info and up
1537
1538  if(!::arg()["logging-facility"].empty()) {
1539    boost::optional<int> val=logFacilityToLOG(::arg().asNum("logging-facility") );
1540    if(val)
1541      theL().setFacility(*val);
1542    else
1543      L<<Logger::Error<<"Unknown logging facility "<<::arg().asNum("logging-facility") <<endl;
1544  }
1545
1546  L<<Logger::Warning<<"PowerDNS recursor "<<VERSION<<" (C) 2001-2010 PowerDNS.COM BV ("<<__DATE__", "__TIME__;
1547#ifdef __GNUC__
1548  L<<", gcc "__VERSION__;
1549#endif // add other compilers here
1550#ifdef _MSC_VER
1551  L<<", MSVC "<<_MSC_VER;
1552#endif
1553  L<<") starting up"<<endl;
1554 
1555  L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. "
1556    "This is free software, and you are welcome to redistribute it "
1557    "according to the terms of the GPL version 2."<<endl;
1558 
1559  L<<Logger::Warning<<"Operating in "<<(sizeof(unsigned long)*8) <<" bits mode"<<endl;
1560 
1561  #if 0
1562  unsigned int maxFDs, curFDs;
1563  getFDLimits(curFDs, maxFDs);
1564  if(curFDs < 2048)
1565    L<<Logger::Warning<<"Only "<<curFDs<<" file descriptors available (out of: "<<maxFDs<<"), may not be suitable for high performance"<<endl;
1566  #endif
1567 
1568  seedRandom(::arg()["entropy-source"]);
1569
1570  parseACLs();
1571 
1572  if(!::arg()["dont-query"].empty()) {
1573    g_dontQuery=new NetmaskGroup;
1574    vector<string> ips;
1575    stringtok(ips, ::arg()["dont-query"], ", ");
1576    L<<Logger::Warning<<"Will not send queries to: ";
1577    for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
1578      g_dontQuery->addMask(*i);
1579      if(i!=ips.begin())
1580        L<<Logger::Warning<<", ";
1581      L<<Logger::Warning<<*i;
1582    }
1583    L<<Logger::Warning<<endl;
1584  }
1585
1586  g_quiet=::arg().mustDo("quiet");
1587  if(::arg().mustDo("trace")) {
1588    SyncRes::setLog(true);
1589    ::arg().set("quiet")="no";
1590    g_quiet=false;
1591  }
1592 
1593  try {
1594    vector<string> addrs; 
1595    if(!::arg()["query-local-address6"].empty()) {
1596      SyncRes::s_doIPv6=true;
1597      L<<Logger::Error<<"Enabling IPv6 transport for outgoing queries"<<endl;
1598     
1599      stringtok(addrs, ::arg()["query-local-address6"], ", ;");
1600      BOOST_FOREACH(const string& addr, addrs) {
1601        g_localQueryAddresses6.push_back(ComboAddress(addr));
1602      }
1603    }
1604    addrs.clear();
1605    stringtok(addrs, ::arg()["query-local-address"], ", ;");
1606    BOOST_FOREACH(const string& addr, addrs) {
1607      g_localQueryAddresses4.push_back(ComboAddress(addr));
1608    }
1609  }
1610  catch(std::exception& e) {
1611    L<<Logger::Error<<"Assigning local query addresses: "<<e.what();
1612    exit(99);
1613  }
1614 
1615  SyncRes::s_noEDNSPing = ::arg().mustDo("disable-edns-ping");
1616  SyncRes::s_noEDNS = ::arg().mustDo("disable-edns");
1617
1618  SyncRes::s_nopacketcache = ::arg().mustDo("disable-packetcache");
1619
1620  SyncRes::s_maxnegttl=::arg().asNum("max-negative-ttl");
1621  SyncRes::s_maxcachettl=::arg().asNum("max-cache-ttl");
1622  SyncRes::s_packetcachettl=::arg().asNum("packetcache-ttl");
1623  SyncRes::s_packetcacheservfailttl=::arg().asNum("packetcache-servfail-ttl");
1624  SyncRes::s_serverID=::arg()["server-id"];
1625  if(SyncRes::s_serverID.empty()) {
1626    char tmp[128];
1627    gethostname(tmp, sizeof(tmp)-1);
1628    SyncRes::s_serverID=tmp;
1629  }
1630 
1631  g_networkTimeoutMsec = ::arg().asNum("network-timeout");
1632
1633  g_initialDomainMap = parseAuthAndForwards();
1634 
1635   
1636  g_logCommonErrors=::arg().mustDo("log-common-errors");
1637 
1638  makeUDPServerSockets();
1639  makeTCPServerSockets();
1640
1641  s_pidfname=::arg()["socket-dir"]+"/"+s_programname+".pid";
1642  if(!s_pidfname.empty())
1643    unlink(s_pidfname.c_str()); // remove possible old pid file
1644 
1645#ifndef WIN32
1646  if(::arg().mustDo("daemon")) {
1647    L<<Logger::Warning<<"Calling daemonize, going to background"<<endl;
1648    L.toConsole(Logger::Critical);
1649    daemonize();
1650  }
1651  signal(SIGUSR1,usr1Handler);
1652  signal(SIGUSR2,usr2Handler);
1653  signal(SIGPIPE,SIG_IGN);
1654  writePid();
1655#endif
1656  makeControlChannelSocket();
1657 
1658  int newgid=0;
1659  if(!::arg()["setgid"].empty())
1660    newgid=Utility::makeGidNumeric(::arg()["setgid"]);
1661  int newuid=0;
1662  if(!::arg()["setuid"].empty())
1663    newuid=Utility::makeUidNumeric(::arg()["setuid"]);
1664
1665#ifndef WIN32
1666  if (!::arg()["chroot"].empty()) {
1667    if (chroot(::arg()["chroot"].c_str())<0 || chdir("/") < 0) {
1668      L<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror (errno)<<", exiting"<<endl;
1669      exit(1);
1670    }
1671  }
1672
1673  Utility::dropPrivs(newuid, newgid);
1674 
1675 
1676  g_numThreads = ::arg().asNum("threads");
1677 
1678  makeThreadPipes();
1679 
1680  g_tcpTimeout=::arg().asNum("client-tcp-timeout");
1681  g_maxTCPPerClient=::arg().asNum("max-tcp-per-client");
1682  g_maxMThreads=::arg().asNum("max-mthreads");
1683
1684  if(g_numThreads == 1) {
1685    L<<Logger::Warning<<"Operating unthreaded"<<endl;
1686    recursorThread(0);
1687  }
1688  else {
1689    pthread_t tid;
1690    L<<Logger::Warning<<"Launching "<< g_numThreads <<" threads"<<endl;
1691    for(unsigned int n=0; n < g_numThreads; ++n) {
1692      pthread_create(&tid, 0, recursorThread, (void*)n);
1693    }
1694    void* res;
1695
1696   
1697    pthread_join(tid, &res);
1698  }
1699  return 0;
1700}
1701
1702void* recursorThread(void* ptr)
1703try
1704{
1705  t_id=(int) (long) ptr;
1706  SyncRes tmp(g_now); // make sure it allocates tsstorage before we do anything, like primeHints or so..
1707  t_sstorage->domainmap = g_initialDomainMap;
1708  t_allowFrom = g_initialAllowFrom;
1709  t_udpclientsocks = new UDPClientSocks();
1710  primeHints();
1711 
1712  t_packetCache = new RecursorPacketCache();
1713 
1714  L<<Logger::Warning<<"Done priming cache with root hints"<<endl;
1715   
1716  t_RC->d_followRFC2181=::arg().mustDo("auth-can-lower-ttl");
1717  t_pdl = new shared_ptr<PowerDNSLua>();
1718 
1719  try {
1720    if(!::arg()["lua-dns-script"].empty()) {
1721      *t_pdl = shared_ptr<PowerDNSLua>(new PowerDNSLua(::arg()["lua-dns-script"]));
1722      L<<Logger::Warning<<"Loaded 'lua' script from '"<<::arg()["lua-dns-script"]<<"'"<<endl;
1723    }
1724   
1725  }
1726  catch(std::exception &e) {
1727    L<<Logger::Error<<"Failed to load 'lua' script from '"<<::arg()["lua-dns-script"]<<"': "<<e.what()<<endl;
1728    exit(99);
1729  }
1730 
1731  t_remotes = new RemoteKeeper();
1732  t_remotes->remotes.resize(::arg().asNum("remotes-ringbuffer-entries") / g_numThreads); 
1733 
1734  if(!t_remotes->remotes.empty())
1735    memset(&t_remotes->remotes[0], 0, t_remotes->remotes.size() * sizeof(RemoteKeeper::remotes_t::value_type));
1736 
1737 
1738  MT=new MTasker<PacketID,string>(::arg().asNum("stack-size"));
1739 
1740  PacketID pident;
1741
1742  t_fdm=getMultiplexer();
1743  if(!t_id) 
1744    L<<Logger::Error<<"Enabled '"<< t_fdm->getName() << "' multiplexer"<<endl;
1745
1746  t_fdm->addReadFD(g_pipes[t_id].readToThread, handlePipeRequest);
1747
1748  for(deferredAdd_t::const_iterator i=deferredAdd.begin(); i!=deferredAdd.end(); ++i) 
1749    t_fdm->addReadFD(i->first, i->second);
1750 
1751  if(!t_id) {
1752   
1753    t_fdm->addReadFD(s_rcc.d_fd, handleRCC); // control channel
1754  }
1755#endif
1756 
1757  unsigned int maxTcpClients=::arg().asNum("max-tcp-clients");
1758 
1759  bool listenOnTCP(true);
1760
1761  counter=0; // used to periodically execute certain tasks
1762  for(;;) {
1763    while(MT->schedule(&g_now)); // MTasker letting the mthreads do their thing
1764     
1765    if(!(counter%500)) {
1766      MT->makeThread(houseKeeping, 0);
1767    }
1768
1769    if(!(counter%55)) {
1770      typedef vector<pair<int, FDMultiplexer::funcparam_t> > expired_t;
1771      expired_t expired=t_fdm->getTimeouts(g_now);
1772       
1773      for(expired_t::iterator i=expired.begin() ; i != expired.end(); ++i) {
1774        TCPConnection conn=any_cast<TCPConnection>(i->second);
1775        if(g_logCommonErrors)
1776          L<<Logger::Warning<<"Timeout from remote TCP client "<< conn.remote.toString() <<endl;
1777        t_fdm->removeReadFD(i->first);
1778        conn.closeAndCleanup();
1779      }
1780    }
1781     
1782    counter++;
1783
1784    if(!t_id && statsWanted) {
1785      doStats();
1786    }
1787
1788    Utility::gettimeofday(&g_now, 0);
1789    t_fdm->run(&g_now);
1790    // 'run' updates g_now for us
1791
1792    if(listenOnTCP) {
1793      if(TCPConnection::s_currentConnections > maxTcpClients) {  // shutdown, too many connections
1794        for(tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i)
1795          t_fdm->removeReadFD(*i);
1796        listenOnTCP=false;
1797      }
1798    }
1799    else {
1800      if(TCPConnection::s_currentConnections <= maxTcpClients) {  // reenable
1801        for(tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i)
1802          t_fdm->addReadFD(*i, handleNewTCPQuestion);
1803        listenOnTCP=true;
1804      }
1805    }
1806  }
1807}
1808catch(AhuException &ae) {
1809  L<<Logger::Error<<"Exception: "<<ae.reason<<endl;
1810  return 0;
1811}
1812catch(std::exception &e) {
1813   L<<Logger::Error<<"STL Exception: "<<e.what()<<endl;
1814   return 0;
1815}
1816catch(...) {
1817   L<<Logger::Error<<"any other exception in main: "<<endl;
1818   return 0;
1819}
1820
1821#ifdef WIN32
1822void doWindowsServiceArguments(RecursorService& recursor)
1823{
1824  if(::arg().mustDo( "register-service" )) {
1825    if ( !recursor.registerService( "The PowerDNS Recursor.", true )) {
1826      cerr << "Could not register service." << endl;
1827      exit( 99 );
1828    }
1829   
1830    exit( 0 );
1831  }
1832
1833  if ( ::arg().mustDo( "unregister-service" )) {
1834    recursor.unregisterService();
1835    exit( 0 );
1836  }
1837}
1838#endif
1839
1840
1841int main(int argc, char **argv) 
1842{
1843  g_stats.startupTime=time(0);
1844  reportBasicTypes();
1845
1846  int ret = EXIT_SUCCESS;
1847#ifdef WIN32
1848  RecursorService service;
1849  WSADATA wsaData;
1850  if(WSAStartup( MAKEWORD( 2, 2 ), &wsaData )) {
1851    cerr<<"Unable to initialize winsock\n";
1852    exit(1);
1853  }
1854#endif // WIN32
1855
1856  try {
1857    ::arg().set("stack-size","stack size per mthread")="200000";
1858    ::arg().set("soa-minimum-ttl","Don't change")="0";
1859    ::arg().set("soa-serial-offset","Don't change")="0";
1860    ::arg().set("no-shuffle","Don't change")="off";
1861    ::arg().set("aaaa-additional-processing","turn on to do AAAA additional processing (slow)")="off";
1862    ::arg().set("local-port","port to listen on")="53";
1863    ::arg().set("local-address","IP addresses to listen on, separated by spaces or commas. Also accepts ports.")="127.0.0.1";
1864    ::arg().set("trace","if we should output heaps of logging")="off";
1865    ::arg().set("daemon","Operate as a daemon")="yes";
1866    ::arg().set("log-common-errors","If we should log rather common errors")="yes";
1867    ::arg().set("chroot","switch to chroot jail")="";
1868    ::arg().set("setgid","If set, change group id to this gid for more security")="";
1869    ::arg().set("setuid","If set, change user id to this uid for more security")="";
1870    ::arg().set("network-timeout", "Wait this nummer of milliseconds for network i/o")="1500";
1871    ::arg().set("threads", "Launch this number of threads")="2";
1872#ifdef WIN32
1873    ::arg().set("quiet","Suppress logging of questions and answers")="off";
1874    ::arg().setSwitch( "register-service", "Register the service" )= "no";
1875    ::arg().setSwitch( "unregister-service", "Unregister the service" )= "no";
1876    ::arg().setSwitch( "ntservice", "Run as service" )= "no";
1877    ::arg().setSwitch( "use-ntlog", "Use the NT logging facilities" )= "yes"; 
1878    ::arg().setSwitch( "use-logfile", "Use a log file" )= "no"; 
1879    ::arg().setSwitch( "logfile", "Filename of the log file" )= "recursor.log"; 
1880#else
1881    ::arg().set("quiet","Suppress logging of questions and answers")="";
1882    ::arg().set("logging-facility","Facility to log messages as. 0 corresponds to local0")="";
1883#endif
1884    ::arg().set("config-dir","Location of configuration directory (recursor.conf)")=SYSCONFDIR;
1885#ifndef WIN32
1886    ::arg().set("socket-owner","Owner of socket")="";
1887    ::arg().set("socket-group","Group of socket")="";
1888    ::arg().set("socket-mode", "Permissions for socket")="";
1889#endif
1890   
1891    ::arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
1892    ::arg().set("delegation-only","Which domains we only accept delegations from")="";
1893    ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
1894    ::arg().set("query-local-address6","Source IPv6 address for sending queries")="";
1895    ::arg().set("client-tcp-timeout","Timeout in seconds when talking to TCP clients")="2";
1896    ::arg().set("max-mthreads", "Maximum number of simultaneous Mtasker threads")="2048";
1897    ::arg().set("max-tcp-clients","Maximum number of simultaneous TCP clients")="128";
1898    ::arg().set("hint-file", "If set, load root hints from this file")="";
1899    ::arg().set("max-cache-entries", "If set, maximum number of entries in the main cache")="1000000";
1900    ::arg().set("max-negative-ttl", "maximum number of seconds to keep a negative cached entry in memory")="3600";
1901    ::arg().set("max-cache-ttl", "maximum number of seconds to keep a cached entry in memory")="86400";
1902    ::arg().set("packetcache-ttl", "maximum number of seconds to keep a cached entry in packetcache")="3600";
1903    ::arg().set("max-packetcache-entries", "maximum number of entries to keep in the packetcache")="500000";
1904    ::arg().set("packetcache-servfail-ttl", "maximum number of seconds to keep a cached servfail entry in packetcache")="60";
1905    ::arg().set("server-id", "Returned when queried for 'server.id' TXT or NSID, defaults to hostname")="";
1906    ::arg().set("remotes-ringbuffer-entries", "maximum number of packets to store statistics for")="0";
1907    ::arg().set("version-string", "string reported on version.pdns or version.bind")="PowerDNS Recursor "VERSION" $Id$";
1908    ::arg().set("allow-from", "If set, only allow these comma separated netmasks to recurse")=LOCAL_NETS;
1909    ::arg().set("allow-from-file", "If set, load allowed netmasks from this file")="";
1910    ::arg().set("entropy-source", "If set, read entropy from this file")="/dev/urandom";
1911    ::arg().set("dont-query", "If set, do not query these netmasks for DNS data")=LOCAL_NETS; 
1912    ::arg().set("max-tcp-per-client", "If set, maximum number of TCP sessions per client (IP address)")="0";
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 with recursion bit, 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    if(::arg().mustDo("config")) {
1936      cout<<::arg().configstring()<<endl;
1937      exit(0);
1938    }
1939
1940
1941    string configname=::arg()["config-dir"]+"/recursor.conf";
1942    cleanSlashes(configname);
1943
1944    if(!::arg().file(configname.c_str())) 
1945      L<<Logger::Warning<<"Unable to parse configuration file '"<<configname<<"'"<<endl;
1946
1947    ::arg().parse(argc,argv);
1948
1949    ::arg().set("delegation-only")=toLower(::arg()["delegation-only"]);
1950
1951    if(::arg().mustDo("help")) {
1952      cerr<<"syntax:"<<endl<<endl;
1953      cerr<<::arg().helpstring(::arg()["help"])<<endl;
1954      exit(99);
1955    }
1956    if(::arg().mustDo("version")) {
1957      cerr<<"version: "VERSION<<endl;
1958      exit(99);
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.