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

Revision 740, 40.7 KB (checked in by ahu, 7 years ago)

solaris completion ports don't survive fork

  • 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 - 2006  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#include "utility.hh"
20#include <iostream>
21#include <errno.h>
22#include <map>
23#include <set>
24#ifndef WIN32
25#include <netdb.h>
26#endif // WIN32
27#include "recursor_cache.hh"
28#include <stdio.h>
29#include <signal.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <netinet/tcp.h>
33#include "mtasker.hh"
34#include <utility>
35#include "arguments.hh"
36#include "syncres.hh"
37#include <fcntl.h>
38#include <fstream>
39#include "sstuff.hh"
40#include <boost/tuple/tuple.hpp>
41#include <boost/tuple/tuple_comparison.hpp>
42#include <boost/shared_array.hpp>
43#include <boost/lexical_cast.hpp>
44#include <boost/function.hpp>
45#include "dnsparser.hh"
46#include "dnswriter.hh"
47#include "dnsrecords.hh"
48#include "zoneparser-tng.hh"
49#include "rec_channel.hh"
50#include "logger.hh"
51#include "iputils.hh"
52#include "mplexer.hh"
53
54#ifndef RECURSOR
55#include "statbag.hh"
56StatBag S;
57#endif
58
59FDMultiplexer* g_fdm;
60unsigned int g_maxTCPPerClient;
61bool g_logCommonErrors;
62using namespace boost;
63
64#ifdef __FreeBSD__           // see cvstrac ticket #26
65#include <pthread.h>
66#include <semaphore.h>
67#endif
68
69MemRecursorCache RC;
70RecursorStats g_stats;
71bool g_quiet;
72NetmaskGroup* g_allowFrom;
73string s_programname="pdns_recursor";
74vector<int> g_tcpListenSockets;
75int g_tcpTimeout;
76
77struct DNSComboWriter {
78  DNSComboWriter(const char* data, uint16_t len, const struct timeval& now) : d_mdp(data, len), d_now(now), d_tcp(false), d_socket(-1)
79  {}
80  MOADNSParser d_mdp;
81  void setRemote(ComboAddress* sa)
82  {
83    d_remote=*sa;
84  }
85
86  void setSocket(int sock)
87  {
88    d_socket=sock;
89  }
90
91  string getRemote() const
92  {
93    return d_remote.toString();
94  }
95
96  struct timeval d_now;
97  ComboAddress d_remote;
98  bool d_tcp;
99  int d_socket;
100};
101
102
103#ifndef WIN32
104#ifndef __FreeBSD__
105extern "C" {
106  int sem_init(sem_t*, int, unsigned int){return 0;}
107  int sem_wait(sem_t*){return 0;}
108  int sem_trywait(sem_t*){return 0;}
109  int sem_post(sem_t*){return 0;}
110  int sem_getvalue(sem_t*, int*){return 0;}
111  pthread_t pthread_self(void){return (pthread_t) 0;}
112  int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr){ return 0; }
113  int pthread_mutex_lock(pthread_mutex_t *mutex){ return 0; }
114  int pthread_mutex_unlock(pthread_mutex_t *mutex) { return 0; }
115  int pthread_mutex_destroy(pthread_mutex_t *mutex) { return 0; }
116}
117#endif // __FreeBSD__
118#endif // WIN32
119
120ArgvMap &arg()
121{
122  static ArgvMap theArg;
123  return theArg;
124}
125
126struct timeval g_now;
127typedef vector<int> tcpserversocks_t;
128
129typedef MTasker<PacketID,string> MT_t;
130MT_t* MT;
131
132
133void handleTCPClientWritable(int fd, boost::any& var);
134
135// -1 is error, 0 is timeout, 1 is success
136int asendtcp(const string& data, Socket* sock) 
137{
138  PacketID pident;
139  pident.sock=sock;
140  pident.outMSG=data;
141
142  g_fdm->addWriteFD(sock->getHandle(), handleTCPClientWritable, pident);
143  string packet;
144
145  int ret=MT->waitEvent(pident,&packet,1);
146  if(!ret || ret==-1) { // timeout
147    g_fdm->removeWriteFD(sock->getHandle());
148  }
149  else if(packet.size() !=data.size()) { // main loop tells us what it sent out, or empty in case of an error
150    return -1;
151  }
152  return ret;
153}
154
155void handleTCPClientReadable(int fd, boost::any& var);
156
157// -1 is error, 0 is timeout, 1 is success
158int arecvtcp(string& data, int len, Socket* sock) 
159{
160  data.clear();
161  PacketID pident;
162  pident.sock=sock;
163  pident.inNeeded=len;
164  g_fdm->addReadFD(sock->getHandle(), handleTCPClientReadable, pident);
165
166  int ret=MT->waitEvent(pident,&data,1);
167  if(!ret || ret==-1) { // timeout
168    g_fdm->removeReadFD(sock->getHandle());
169  }
170  else if(data.empty()) {// error, EOF or other
171    return -1;
172  }
173
174  return ret;
175}
176
177// returns -1 for errors which might go away, throws for ones that won't
178int makeClientSocket()
179{
180  int ret=socket(AF_INET, SOCK_DGRAM, 0);
181  if(ret < 0 && errno==EMFILE) // this is not a catastrophic error
182    return ret;
183
184  if(ret<0) 
185    throw AhuException("Making a socket for resolver: "+stringerror());
186
187  static optional<struct sockaddr_in> sin;
188  if(!sin) {
189    struct sockaddr_in tmp;
190    sin=tmp;
191    memset((char *)&*sin,0, sizeof(sin));
192    sin->sin_family = AF_INET;
193   
194    if(!IpToU32(::arg()["query-local-address"], &sin->sin_addr.s_addr))
195      throw AhuException("Unable to resolve local address '"+ ::arg()["query-local-address"] +"'"); 
196  }
197 
198  int tries=10;
199  while(--tries) {
200    uint16_t port=1025+Utility::random()%64510;
201    if(tries==1)  // fall back to kernel 'random'
202        port=0;
203
204    sin->sin_port = htons(port); 
205   
206    if (::bind(ret, (struct sockaddr *)&*sin, sizeof(*sin)) >= 0) 
207      break;
208  }
209  if(!tries)
210    throw AhuException("Resolver binding to local query client socket: "+stringerror());
211
212  Utility::setNonBlocking(ret);
213  return ret;
214}
215
216void handleUDPServerResponse(int fd, boost::any&);
217
218// you can ask this class for a UDP socket to send a query from
219// this socket is not yours, don't even think about deleting it
220// but after you call 'returnSocket' on it, don't assume anything anymore
221class UDPClientSocks
222{
223  unsigned int d_numsocks;
224  unsigned int d_maxsocks;
225
226public:
227  UDPClientSocks() : d_numsocks(0), d_maxsocks(5000)
228  {
229  }
230
231  typedef map<int,int> socks_t;
232  socks_t d_socks;
233
234  // returning -1 means: temporary OS error (ie, out of files)
235  int getSocket()
236  {
237    pair<int, int> sock=make_pair(makeClientSocket(), 1);
238    if(sock.first < 0) // temporary error - exception otherwise
239      return -1;
240
241    d_socks.insert(sock);
242    d_numsocks++;
243    return sock.first;
244  }
245
246  void returnSocket(int fd)
247  {
248    socks_t::iterator i=d_socks.find(fd);
249    returnSocket(i);
250  }
251
252  // return a socket to the pool, or simply erase it
253  void returnSocket(socks_t::iterator& i)
254  {
255    if(i==d_socks.end()) {
256      throw AhuException("Trying to return a socket not in the pool");
257    }
258    g_fdm->removeReadFD(i->first);
259    ::close(i->first);
260   
261    d_socks.erase(i++);
262    --d_numsocks;
263  }
264}g_udpclientsocks;
265
266
267/* these two functions are used by LWRes */
268// -2 is OS error, -1 is error that depends on the remote, > 1 is success
269int asendto(const char *data, int len, int flags, struct sockaddr *toaddr, int addrlen, int id, const string& domain, int* fd) 
270{
271  *fd=g_udpclientsocks.getSocket();
272  if(*fd < 0)
273    return -2;
274  PacketID pident;
275  pident.fd=*fd;
276  pident.id=id;
277  pident.domain=domain;
278  memcpy(&pident.remote, toaddr, sizeof(pident.remote));
279 
280  int ret=connect(*fd, toaddr, addrlen);
281  if(ret < 0)
282    return ret;
283
284  g_fdm->addReadFD(*fd, handleUDPServerResponse, pident);
285  return send(*fd, data, len, 0);
286}
287
288// -1 is error, 0 is timeout, 1 is success
289int arecvfrom(char *data, int len, int flags, struct sockaddr *toaddr, Utility::socklen_t *addrlen, int *d_len, int id, const string& domain, int fd)
290{
291  static optional<unsigned int> nearMissLimit;
292  if(!nearMissLimit) 
293    nearMissLimit=::arg().asNum("spoof-nearmiss-max");
294
295  PacketID pident;
296  pident.fd=fd;
297  pident.id=id;
298  pident.domain=domain;
299  memcpy(&pident.remote, toaddr, sizeof(pident.remote));
300
301  string packet;
302  int ret=MT->waitEvent(pident, &packet, 1);
303  if(ret > 0) {
304    if(packet.empty()) {// means "error"
305      return -1; 
306    }
307
308    *d_len=packet.size();
309    memcpy(data,packet.c_str(),min(len,*d_len));
310    if(*nearMissLimit && pident.nearMisses > *nearMissLimit) {
311      L<<Logger::Error<<"Too many ("<<pident.nearMisses<<" > "<<*nearMissLimit<<") bogus answers for '"<<domain<<"' from "<<sockAddrToString((struct sockaddr_in*)toaddr)<<", assuming spoof attempt."<<endl;
312      g_stats.spoofCount++;
313      return -1;
314    }
315  }
316  else {
317    g_udpclientsocks.returnSocket(fd);
318  }
319  return ret;
320}
321
322void setBuffer(int fd, int optname, uint32_t size)
323{
324  uint32_t psize=0;
325  socklen_t len=sizeof(psize);
326 
327  if(!getsockopt(fd, SOL_SOCKET, optname, (char*)&psize, &len) && psize > size) {
328    L<<Logger::Error<<"Not decreasing socket buffer size from "<<psize<<" to "<<size<<endl;
329    return; 
330  }
331
332  if (setsockopt(fd, SOL_SOCKET, optname, (char*)&size, sizeof(size)) < 0 )
333    L<<Logger::Error<<"Warning: unable to raise socket buffer size to "<<size<<": "<<strerror(errno)<<endl;
334}
335
336
337static void setReceiveBuffer(int fd, uint32_t size)
338{
339  setBuffer(fd, SO_RCVBUF, size);
340}
341
342static void setSendBuffer(int fd, uint32_t size)
343{
344  setBuffer(fd, SO_SNDBUF, size);
345}
346
347static void writePid(void)
348{
349  string fname=::arg()["socket-dir"]+"/"+s_programname+".pid";
350  ofstream of(fname.c_str());
351  if(of)
352    of<< getpid() <<endl;
353  else
354    L<<Logger::Error<<"Requested to write pid for "<<getpid()<<" to "<<fname<<" failed: "<<strerror(errno)<<endl;
355}
356
357void primeHints(void)
358{
359  // prime root cache
360  set<DNSResourceRecord>nsset;
361
362  if(::arg()["hint-file"].empty()) {
363    static char*ips[]={"198.41.0.4", "192.228.79.201", "192.33.4.12", "128.8.10.90", "192.203.230.10", "192.5.5.241", "192.112.36.4", "128.63.2.53", 
364                       "192.36.148.17","192.58.128.30", "193.0.14.129", "198.32.64.12", "202.12.27.33"};
365    DNSResourceRecord arr, nsrr;
366    arr.qtype=QType::A;
367    arr.ttl=time(0)+3600000;
368    nsrr.qtype=QType::NS;
369    nsrr.ttl=time(0)+3600000;
370   
371    for(char c='a';c<='m';++c) {
372      static char templ[40];
373      strncpy(templ,"a.root-servers.net.", sizeof(templ) - 1);
374      *templ=c;
375      arr.qname=nsrr.content=templ;
376      arr.content=ips[c-'a'];
377      set<DNSResourceRecord> aset;
378      aset.insert(arr);
379      RC.replace(string(templ), QType(QType::A), aset);
380     
381      nsset.insert(nsrr);
382    }
383  }
384  else {
385    ZoneParserTNG zpt(::arg()["hint-file"]);
386    DNSResourceRecord rr;
387    set<DNSResourceRecord> aset;
388
389    while(zpt.get(rr)) {
390      rr.ttl+=time(0);
391      if(rr.qtype.getCode()==QType::A) {
392        set<DNSResourceRecord> aset;
393        aset.insert(rr);
394        RC.replace(rr.qname, QType(QType::A), aset);
395      }
396      if(rr.qtype.getCode()==QType::NS) {
397        rr.content=toLower(rr.content);
398        nsset.insert(rr);
399      }
400    }
401  }
402  RC.replace(".", QType(QType::NS), nsset); // and stuff in the cache
403}
404
405map<ComboAddress, uint32_t> g_tcpClientCounts;
406
407struct TCPConnection
408{
409  int fd;
410  enum stateenum {BYTE0, BYTE1, GETQUESTION, DONE} state;
411  int qlen;
412  int bytesread;
413  ComboAddress remote;
414  char data[65535];
415  time_t startTime;
416
417  void closeAndCleanup()
418  {
419    close(fd);
420    if(!g_tcpClientCounts[remote]--) 
421      g_tcpClientCounts.erase(remote);
422    s_currentConnections--;
423  }
424  static unsigned int s_currentConnections; //!< total number of current TCP connections
425};
426
427unsigned int TCPConnection::s_currentConnections; 
428
429void startDoResolve(void *p)
430{
431  DNSComboWriter* dc=(DNSComboWriter *)p;
432  try {
433    uint16_t maxudpsize=512;
434    MOADNSParser::EDNSOpts edo;
435    if(dc->d_mdp.getEDNSOpts(&edo)) {
436      maxudpsize=edo.d_packetsize;
437    }
438   
439    vector<DNSResourceRecord> ret;
440   
441    vector<uint8_t> packet;
442    DNSPacketWriter pw(packet, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass);
443
444    pw.getHeader()->aa=0;
445    pw.getHeader()->ra=1;
446    pw.getHeader()->qr=1;
447    pw.getHeader()->id=dc->d_mdp.d_header.id;
448    pw.getHeader()->rd=dc->d_mdp.d_header.rd;
449
450    SyncRes sr(dc->d_now);
451    if(!g_quiet)
452      L<<Logger::Error<<"["<<MT->getTid()<<"] " << (dc->d_tcp ? "TCP " : "") << "question for '"<<dc->d_mdp.d_qname<<"|"
453       <<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)<<"' from "<<dc->getRemote()<<endl;
454
455    sr.setId(MT->getTid());
456    if(!dc->d_mdp.d_header.rd)
457      sr.setCacheOnly();
458
459    int res=sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret);
460    if(res<0) {
461      pw.getHeader()->rcode=RCode::ServFail;
462      // no commit here, because no record
463      g_stats.servFails++;
464    }
465    else {
466      pw.getHeader()->rcode=res;
467      switch(res) {
468      case RCode::ServFail:
469        g_stats.servFails++;
470        break;
471      case RCode::NXDomain:
472        g_stats.nxDomains++;
473        break;
474      case RCode::NoError:
475        g_stats.noErrors++;
476        break;
477      }
478     
479      if(ret.size()) {
480        shuffle(ret);
481        for(vector<DNSResourceRecord>::const_iterator i=ret.begin();i!=ret.end();++i) {
482          pw.startRecord(i->qname, i->qtype.getCode(), i->ttl, i->qclass, (DNSPacketWriter::Place)i->d_place);
483          shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(i->qtype.getCode(), i->qclass, i->content));
484         
485          drc->toPacket(pw);
486       
487          if(!dc->d_tcp && pw.size() > maxudpsize) {
488            pw.rollback();
489            if(i->d_place==DNSResourceRecord::ANSWER)  // only truncate if we actually omitted parts of the answer
490              pw.getHeader()->tc=1;
491            goto sendit; // need to jump over pw.commit
492          }
493        }
494        pw.commit();
495      }
496    }
497  sendit:;
498    if(!dc->d_tcp) {
499      sendto(dc->d_socket, &*packet.begin(), packet.size(), 0, (struct sockaddr *)(&dc->d_remote), dc->d_remote.getSocklen());
500    }
501    else {
502      char buf[2];
503      buf[0]=packet.size()/256;
504      buf[1]=packet.size()%256;
505
506      struct iovec iov[2];
507
508      iov[0].iov_base=(void*)buf;              iov[0].iov_len=2;
509      iov[1].iov_base=(void*)&*packet.begin(); iov[1].iov_len = packet.size();
510
511      int ret=writev(dc->d_socket, iov, 2);
512      bool hadError=true;
513
514      if(ret == 0) 
515        L<<Logger::Error<<"EOF writing TCP answer to "<<dc->getRemote()<<endl;
516      else if(ret < 0 ) 
517        L<<Logger::Error<<"Error writing TCP answer to "<<dc->getRemote()<<": "<< strerror(errno) <<endl;
518      else if((unsigned int)ret != 2 + packet.size())
519        L<<Logger::Error<<"Oops, partial answer sent to "<<dc->getRemote()<<" for "<<dc->d_mdp.d_qname<<" (size="<< (2 + packet.size()) <<", sent "<<ret<<")"<<endl;
520      else
521        hadError=false;
522     
523      // update tcp connection status, either by closing or moving to 'BYTE0'
524
525      if(hadError) {
526        g_fdm->removeReadFD(dc->d_socket);
527        close(dc->d_socket);
528      }
529      else {
530        any_cast<TCPConnection&>(g_fdm->getReadParameter(dc->d_socket)).state=TCPConnection::BYTE0;
531        struct timeval now; 
532        gettimeofday(&now, 0); // needs to be updated
533        g_fdm->setReadTTD(dc->d_socket, now, g_tcpTimeout);
534      }
535    }
536
537    if(!g_quiet) {
538      L<<Logger::Error<<"["<<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);
539      L<<"': "<<ntohs(pw.getHeader()->ancount)<<" answers, "<<ntohs(pw.getHeader()->arcount)<<" additional, took "<<sr.d_outqueries<<" packets, "<<
540        sr.d_throttledqueries<<" throttled, "<<sr.d_timeouts<<" timeouts, "<<sr.d_tcpoutqueries<<" tcp connections, rcode="<<res<<endl;
541    }
542   
543    sr.d_outqueries ? RC.cacheMisses++ : RC.cacheHits++; 
544    float spent=makeFloat(sr.d_now-dc->d_now);
545    if(spent < 0.001)
546      g_stats.answers0_1++;
547    else if(spent < 0.010)
548      g_stats.answers1_10++;
549    else if(spent < 0.1)
550      g_stats.answers10_100++;
551    else if(spent < 1.0)
552      g_stats.answers100_1000++;
553    else
554      g_stats.answersSlow++;
555
556    uint64_t newLat=(uint64_t)(spent*1000000);
557    if(newLat < 1000000)  // outliers of several minutes exist..
558      g_stats.avgLatencyUsec=(uint64_t)((1-0.0001)*g_stats.avgLatencyUsec + 0.0001*newLat);
559    delete dc;
560  }
561  catch(AhuException &ae) {
562    L<<Logger::Error<<"startDoResolve problem: "<<ae.reason<<endl;
563  }
564  catch(MOADNSException& e) {
565    L<<Logger::Error<<"DNS parser error: "<<dc->d_mdp.d_qname<<", "<<e.what()<<endl;
566  }
567  catch(exception& e) {
568    L<<Logger::Error<<"STL error: "<<e.what()<<endl;
569  }
570  catch(...) {
571    L<<Logger::Error<<"Any other exception in a resolver context"<<endl;
572  }
573}
574
575RecursorControlChannel s_rcc;
576
577void makeControlChannelSocket()
578{
579  string sockname=::arg()["socket-dir"]+"/pdns_recursor.controlsocket";
580  if(::arg().mustDo("fork")) {
581    sockname+="."+lexical_cast<string>(getpid());
582    L<<Logger::Warning<<"Forked control socket name: "<<sockname<<endl;
583  }
584  s_rcc.listen(sockname);
585}
586
587void handleRunningTCPQuestion(int fd, boost::any& var)
588{
589  TCPConnection& conn=any_cast<TCPConnection&>(var);
590
591  if(conn.state==TCPConnection::BYTE0) {
592    int bytes=read(conn.fd,conn.data,2);
593    if(bytes==1)
594      conn.state=TCPConnection::BYTE1;
595    if(bytes==2) { 
596      conn.qlen=(conn.data[0]<<8)+conn.data[1];
597      conn.bytesread=0;
598      conn.state=TCPConnection::GETQUESTION;
599    }
600    if(!bytes || bytes < 0) {
601      TCPConnection tmp(conn); 
602      g_fdm->removeReadFD(fd);
603      tmp.closeAndCleanup();
604      return;
605    }
606  }
607  else if(conn.state==TCPConnection::BYTE1) {
608    int bytes=read(conn.fd,conn.data+1,1);
609    if(bytes==1) {
610      conn.state=TCPConnection::GETQUESTION;
611      conn.qlen=(conn.data[0]<<8)+conn.data[1];
612      conn.bytesread=0;
613    }
614    if(!bytes || bytes < 0) {
615      if(g_logCommonErrors)
616        L<<Logger::Error<<"TCP client "<< conn.remote.toString() <<" disconnected after first byte"<<endl;
617      TCPConnection tmp(conn); 
618      g_fdm->removeReadFD(fd);
619      tmp.closeAndCleanup();  // conn loses validity here..
620      return;
621    }
622  }
623  else if(conn.state==TCPConnection::GETQUESTION) {
624    int bytes=read(conn.fd,conn.data + conn.bytesread,conn.qlen - conn.bytesread);
625    if(!bytes || bytes < 0) {
626      L<<Logger::Error<<"TCP client "<< conn.remote.toString() <<" disconnected while reading question body"<<endl;
627      TCPConnection tmp(conn);
628      g_fdm->removeReadFD(fd);
629      tmp.closeAndCleanup();  // conn loses validity here..
630
631      return;
632    }
633    conn.bytesread+=bytes;
634    if(conn.bytesread==conn.qlen) {
635      conn.state=TCPConnection::DONE;        // this makes us immune from timeouts, from now on *we* are responsible
636      DNSComboWriter* dc=0;
637      try {
638        dc=new DNSComboWriter(conn.data, conn.qlen, g_now);
639      }
640      catch(MOADNSException &mde) {
641        g_stats.clientParseError++; 
642        L<<Logger::Error<<"Unable to parse packet from TCP client "<< conn.remote.toString() <<endl;
643        TCPConnection tmp(conn); 
644        g_fdm->removeReadFD(fd);
645        tmp.closeAndCleanup();
646        return;
647      }
648     
649      dc->setSocket(conn.fd);
650      dc->d_tcp=true;
651      dc->setRemote(&conn.remote);
652      if(dc->d_mdp.d_header.qr)
653        L<<Logger::Error<<"Ignoring answer on server socket!"<<endl;
654      else {
655        ++g_stats.qcounter;
656        ++g_stats.tcpqcounter;
657        MT->makeThread(startDoResolve, dc);
658        return;
659      }
660    }
661  }
662}
663
664//! Handle new incoming TCP connection
665void handleNewTCPQuestion(int fd, boost::any& )
666{
667  ComboAddress addr;
668  socklen_t addrlen=sizeof(addr);
669  int newsock=accept(fd, (struct sockaddr*)&addr, &addrlen);
670  if(newsock>0) {
671    g_stats.addRemote(addr);
672    if(g_allowFrom && !g_allowFrom->match(&addr)) {
673      g_stats.unauthorizedTCP++;
674      close(newsock);
675      return;
676    }
677   
678    if(g_maxTCPPerClient && g_tcpClientCounts.count(addr) && g_tcpClientCounts[addr] >= g_maxTCPPerClient) {
679      g_stats.tcpClientOverflow++;
680      close(newsock); // don't call TCPConnection::closeAndCleanup here - did not enter it in the counts yet!
681      return;
682    }
683    g_tcpClientCounts[addr]++;
684    Utility::setNonBlocking(newsock);
685    TCPConnection tc;
686    tc.fd=newsock;
687    tc.state=TCPConnection::BYTE0;
688    tc.remote=addr;
689    tc.startTime=g_now.tv_sec;
690    TCPConnection::s_currentConnections++;
691    g_fdm->addReadFD(tc.fd, handleRunningTCPQuestion, tc);
692    struct timeval now;
693    gettimeofday(&now, 0);
694    g_fdm->setReadTTD(tc.fd, now, g_tcpTimeout);
695  }
696}
697
698void handleNewUDPQuestion(int fd, boost::any& var)
699{
700  int len;
701  char data[1500];
702  ComboAddress fromaddr;
703  socklen_t addrlen=sizeof(fromaddr);
704
705  if((len=recvfrom(fd, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen)) >= 0) {
706    g_stats.addRemote(fromaddr);
707    if(g_allowFrom && !g_allowFrom->match(&fromaddr)) {
708      g_stats.unauthorizedUDP++;
709      return;
710    }
711   
712    try {
713      DNSComboWriter* dc = new DNSComboWriter(data, len, g_now);
714     
715      dc->setRemote(&fromaddr);
716     
717      if(dc->d_mdp.d_header.qr) {
718        if(g_logCommonErrors)
719          L<<Logger::Error<<"Ignoring answer from "<<dc->getRemote()<<" on server socket!"<<endl;
720      }
721      else {
722        ++g_stats.qcounter;
723        dc->setSocket(fd);
724        dc->d_tcp=false;
725        MT->makeThread(startDoResolve, (void*) dc);
726      }
727    }
728    catch(MOADNSException& mde) {
729      g_stats.clientParseError++; 
730      L<<Logger::Error<<"Unable to parse packet from remote UDP client "<<fromaddr.toString() <<": "<<mde.what()<<endl;
731    }
732  }
733}
734
735typedef vector<pair<int, function< void(int, any&) > > > deferredAdd_t;
736deferredAdd_t deferredAdd;
737
738void makeTCPServerSockets()
739{
740  int fd;
741  vector<string>locals;
742  stringtok(locals,::arg()["local-address"]," ,");
743
744  if(locals.empty())
745    throw AhuException("No local address specified");
746 
747  ComboAddress sin;
748  for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
749    memset((char *)&sin,0, sizeof(sin));
750    sin.sin4.sin_family = AF_INET;
751    if(!IpToU32(*i, &sin.sin4.sin_addr.s_addr)) {
752      sin.sin6.sin6_family = AF_INET6;
753      if(inet_pton(AF_INET6, i->c_str(), &sin.sin6.sin6_addr) <= 0)
754        throw AhuException("Unable to resolve local address '"+ *i +"'"); 
755    }
756
757    fd=socket(sin.sin6.sin6_family, SOCK_STREAM, 0);
758    if(fd<0) 
759      throw AhuException("Making a TCP server socket for resolver: "+stringerror());
760
761    int tmp=1;
762    if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
763      L<<Logger::Error<<"Setsockopt failed for TCP listening socket"<<endl;
764      exit(1);
765    }
766   
767#ifdef TCP_DEFER_ACCEPT
768    if(setsockopt(fd, SOL_TCP,TCP_DEFER_ACCEPT,(char*)&tmp,sizeof tmp) >= 0) {
769      if(i==locals.begin())
770        L<<Logger::Error<<"Enabled TCP data-ready filter for (slight) DoS protection"<<endl;
771    }
772#endif
773
774    sin.sin4.sin_port = htons(::arg().asNum("local-port")); 
775    int socklen=sin.sin4.sin_family==AF_INET ? sizeof(sin.sin4) : sizeof(sin.sin6);
776    if (::bind(fd, (struct sockaddr *)&sin, socklen )<0) 
777      throw AhuException("Binding TCP server socket for "+*i+": "+stringerror());
778   
779    Utility::setNonBlocking(fd);
780    setSendBuffer(fd, 65000);
781    listen(fd, 128);
782    deferredAdd.push_back(make_pair(fd, handleNewTCPQuestion));
783    //    g_fdm->addReadFD(fd, handleNewTCPQuestion);
784    if(sin.sin4.sin_family == AF_INET) 
785      L<<Logger::Error<<"Listening for TCP queries on "<< sin.toString() <<":"<<::arg().asNum("local-port")<<endl;
786    else
787      L<<Logger::Error<<"Listening for TCP queries on ["<< sin.toString() <<"]:"<<::arg().asNum("local-port")<<endl;
788  }
789}
790
791void makeUDPServerSockets()
792{
793  vector<string>locals;
794  stringtok(locals,::arg()["local-address"]," ,");
795
796  if(locals.empty())
797    throw AhuException("No local address specified");
798 
799  if(::arg()["local-address"]=="0.0.0.0") {
800    L<<Logger::Warning<<"It is advised to bind to explicit addresses with the --local-address option"<<endl;
801  }
802
803  for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
804    ComboAddress sin;
805    memset(&sin, 0, sizeof(sin));
806    sin.sin4.sin_family = AF_INET;
807    if(!IpToU32(*i, &sin.sin4.sin_addr.s_addr)) {
808      sin.sin6.sin6_family = AF_INET6;
809      if(inet_pton(AF_INET6, i->c_str(), &sin.sin6.sin6_addr) <= 0)
810        throw AhuException("Unable to resolve local address '"+ *i +"'"); 
811    }
812   
813    int fd=socket(sin.sin4.sin_family, SOCK_DGRAM,0);
814    if(fd<0) 
815      throw AhuException("Making a UDP server socket for resolver: "+stringerror());
816
817    setReceiveBuffer(fd, 200000);
818    sin.sin4.sin_port = htons(::arg().asNum("local-port")); 
819
820    int socklen=sin.sin4.sin_family==AF_INET ? sizeof(sin.sin4) : sizeof(sin.sin6);
821    if (::bind(fd, (struct sockaddr *)&sin, socklen)<0) 
822      throw AhuException("Resolver binding to server socket for "+*i+": "+stringerror());
823   
824    Utility::setNonBlocking(fd);
825    //    g_fdm->addReadFD(fd, handleNewUDPQuestion);
826    deferredAdd.push_back(make_pair(fd, handleNewUDPQuestion));
827    g_tcpListenSockets.push_back(fd);
828    if(sin.sin4.sin_family == AF_INET) 
829      L<<Logger::Error<<"Listening for UDP queries on "<< sin.toString() <<":"<<::arg().asNum("local-port")<<endl;
830    else
831      L<<Logger::Error<<"Listening for UDP queries on ["<< sin.toString() <<"]:"<<::arg().asNum("local-port")<<endl;
832  }
833}
834
835
836#ifndef WIN32
837void daemonize(void)
838{
839  if(fork())
840    exit(0); // bye bye
841 
842  setsid(); 
843
844  // cleanup open fds, but skip sockets
845  close(0);
846  close(1);
847  close(2);
848}
849#endif
850
851uint64_t counter;
852bool statsWanted;
853
854
855void usr1Handler(int)
856{
857  statsWanted=true;
858}
859
860
861
862void usr2Handler(int)
863{
864  SyncRes::setLog(true);
865  g_quiet=false;
866  ::arg().set("quiet")="no";
867
868}
869
870void doStats(void)
871{
872  if(g_stats.qcounter) {
873    L<<Logger::Error<<"stats: "<<g_stats.qcounter<<" questions, "<<RC.size()<<" cache entries, "<<SyncRes::s_negcache.size()<<" negative entries, "
874     <<(int)((RC.cacheHits*100.0)/(RC.cacheHits+RC.cacheMisses))<<"% cache hits"<<endl;
875    L<<Logger::Error<<"stats: throttle map: "<<SyncRes::s_throttle.size()<<", ns speeds: "
876     <<SyncRes::s_nsSpeeds.size()<<endl; // ", bytes: "<<RC.bytes()<<endl;
877    L<<Logger::Error<<"stats: outpacket/query ratio "<<(int)(SyncRes::s_outqueries*100.0/SyncRes::s_queries)<<"%";
878    L<<Logger::Error<<", "<<(int)(SyncRes::s_throttledqueries*100.0/(SyncRes::s_outqueries+SyncRes::s_throttledqueries))<<"% throttled, "
879     <<SyncRes::s_nodelegated<<" no-delegation drops"<<endl;
880    L<<Logger::Error<<"stats: "<<SyncRes::s_tcpoutqueries<<" outgoing tcp connections, "<<MT->numProcesses()<<" queries running, "<<SyncRes::s_outgoingtimeouts<<" outgoing timeouts"<<endl;
881  }
882  else if(statsWanted) 
883    L<<Logger::Error<<"stats: no stats yet!"<<endl;
884
885  statsWanted=false;
886}
887
888static void houseKeeping(void *)
889{
890  static time_t last_stat, last_rootupdate, last_prune;
891  struct timeval now;
892  gettimeofday(&now, 0);
893
894  if(now.tv_sec - last_prune > 300) { 
895    DTime dt;
896    dt.setTimeval(now);
897    RC.doPrune();
898   
899    typedef SyncRes::negcache_t::nth_index<1>::type negcache_by_ttd_index_t;
900    negcache_by_ttd_index_t& ttdindex=boost::multi_index::get<1>(SyncRes::s_negcache);
901
902    negcache_by_ttd_index_t::iterator i=ttdindex.lower_bound(now.tv_sec);
903    ttdindex.erase(ttdindex.begin(), i);
904
905    time_t limit=now.tv_sec-300;
906    for(SyncRes::nsspeeds_t::iterator i = SyncRes::s_nsSpeeds.begin() ; i!= SyncRes::s_nsSpeeds.end(); )
907      if(i->second.stale(limit))
908        SyncRes::s_nsSpeeds.erase(i++);
909      else
910        ++i;
911
912    //   cerr<<"Pruned "<<pruned<<" records, left "<<SyncRes::s_negcache.size()<<"\n";
913//    cout<<"Prune took "<<dt.udiff()<<"usec\n";
914    last_prune=time(0);
915  }
916  if(now.tv_sec - last_stat>1800) { 
917    doStats();
918    last_stat=time(0);
919  }
920  if(now.tv_sec -last_rootupdate>7200) {
921    SyncRes sr(now);
922    vector<DNSResourceRecord> ret;
923
924    sr.setNoCache();
925    int res=sr.beginResolve(".", QType(QType::NS), 1, ret);
926    if(!res) {
927      L<<Logger::Error<<"Refreshed . records"<<endl;
928      last_rootupdate=now.tv_sec;
929    }
930    else
931      L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
932  }
933}
934
935
936
937#if 0
938#include <execinfo.h>
939
940  multimap<uint32_t,string> rev;
941  for(map<string,uint32_t>::const_iterator i=casesptr->begin(); i!=casesptr->end(); ++i) {
942    rev.insert(make_pair(i->second,i->first));
943  }
944  for(multimap<uint32_t,string>::const_iterator i=rev.begin(); i!= rev.end(); ++i)
945    cout<<i->first<<" times: \n"<<i->second<<"\n";
946
947  cout.flush();
948
949map<string,uint32_t>* casesptr;
950static string maketrace()
951{
952  void *array[20]; //only care about last 17 functions (3 taken with tracing support)
953  size_t size;
954  char **strings;
955  size_t i;
956
957  size = backtrace (array, 5);
958  strings = backtrace_symbols (array, size); //Need -rdynamic gcc (linker) flag for this to work
959
960  string ret;
961
962  for (i = 0; i < size; i++) //skip useless functions
963    ret+=string(strings[i])+"\n";
964  return ret;
965}
966
967extern "C" {
968
969int gettimeofday (struct timeval *__restrict __tv,
970                  __timezone_ptr_t __tz)
971{
972  static map<string, uint32_t> s_cases;
973  casesptr=&s_cases;
974  s_cases[maketrace()]++;
975  __tv->tv_sec=time(0);
976  return 0;
977}
978
979}
980#endif
981
982string questionExpand(const char* packet, uint16_t len)
983{
984  const char* end=packet+len;
985  const char* pos=packet+12;
986  unsigned char labellen;
987  string ret;
988  ret.reserve(len-12);
989  while((labellen=*pos++)) {
990    if(pos+labellen > end)
991      break;
992    ret.append(pos, labellen);
993    ret.append(1,'.');
994    pos+=labellen;
995  }
996  if(ret.empty())
997    ret=".";
998  return ret;
999}
1000
1001
1002void handleRCC(int fd, boost::any& var)
1003{
1004  string remote;
1005  string msg=s_rcc.recv(&remote);
1006  RecursorControlParser rcp;
1007  RecursorControlParser::func_t* command;
1008  string answer=rcp.getAnswer(msg, &command);
1009  s_rcc.send(answer, &remote);
1010  command();
1011}
1012
1013void handleTCPClientReadable(int fd, boost::any& var)
1014{
1015  PacketID& pident=any_cast<PacketID&>(var);
1016  //  cerr<<"handleTCPClientReadable called for fd "<<fd<<", pident.inNeeded: "<<pident.inNeeded<<", "<<pident.sock->getHandle()<<endl;
1017
1018  shared_array<char> buffer(new char[pident.inNeeded]);
1019
1020  int ret=read(fd, buffer.get(), pident.inNeeded);
1021  if(ret > 0) {
1022    pident.inMSG.append(&buffer[0], &buffer[ret]);
1023    pident.inNeeded-=ret;
1024    if(!pident.inNeeded) {
1025      //      cerr<<"Got entire load of "<<pident.inMSG.size()<<" bytes"<<endl;
1026      PacketID pid=pident;
1027      string msg=pident.inMSG;
1028     
1029      g_fdm->removeReadFD(fd);
1030      MT->sendEvent(pid, &msg); 
1031    }
1032    else {
1033      //      cerr<<"Still have "<<pident.inNeeded<<" left to go"<<endl;
1034    }
1035  }
1036  else {
1037    PacketID tmp=pident;
1038    g_fdm->removeReadFD(fd); // pident might now be invalid (it isn't, but still)
1039    string empty;
1040    MT->sendEvent(tmp, &empty); // this conveys error status
1041  }
1042}
1043
1044void handleTCPClientWritable(int fd, boost::any& var)
1045{
1046  PacketID& pid=any_cast<PacketID&>(var);
1047 
1048  int ret=write(fd, pid.outMSG.c_str(), pid.outMSG.size() - pid.outPos);
1049  if(ret > 0) {
1050    pid.outPos+=ret;
1051    if(pid.outPos==pid.outMSG.size()) {
1052      PacketID tmp=pid;
1053      g_fdm->removeWriteFD(fd);
1054      MT->sendEvent(tmp, &tmp.outMSG);  // send back what we sent to convey everything is ok
1055    }
1056  }
1057  else {  // error or EOF
1058    PacketID tmp(pid);
1059    g_fdm->removeWriteFD(fd);
1060    string sent;
1061    MT->sendEvent(tmp, &sent);         // we convey error status by sending empty string
1062  }
1063}
1064
1065void handleUDPServerResponse(int fd, boost::any& var)
1066{
1067  PacketID pid=any_cast<PacketID>(var);
1068  int len;
1069  char data[1500];
1070  struct sockaddr_in fromaddr;
1071  socklen_t addrlen=sizeof(fromaddr);
1072
1073  len=recvfrom(fd, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen);
1074
1075  if(len < (int)sizeof(dnsheader)) {
1076    if(len < 0)
1077      ; //       cerr<<"Error on fd "<<fd<<": "<<stringerror()<<"\n";
1078    else {
1079      g_stats.serverParseError++; 
1080      if(g_logCommonErrors)
1081        L<<Logger::Error<<"Unable to parse packet from remote UDP server "<< sockAddrToString((struct sockaddr_in*) &fromaddr) <<
1082          ": packet smalller than DNS header"<<endl;
1083    }
1084    string empty;
1085    g_udpclientsocks.returnSocket(fd);
1086    MT->sendEvent(pid, &empty); // this denotes error
1087    return;
1088  } 
1089
1090  dnsheader dh;
1091  memcpy(&dh, data, sizeof(dh));
1092 
1093  if(!dh.qdcount) // UPC, Nominum?
1094    return;
1095 
1096  if(dh.qr) {
1097    PacketID pident;
1098    pident.remote=fromaddr;
1099    pident.id=dh.id;
1100    pident.fd=fd;
1101    pident.domain=questionExpand(data, len); // don't copy this from above - we need to do the actual read
1102    string packet;
1103    packet.assign(data, len);
1104    if(!MT->sendEvent(pident, &packet)) {
1105      // if(g_logCommonErrors)
1106      //   L<<Logger::Warning<<"Discarding unexpected packet from "<<sockAddrToString((struct sockaddr_in*) &fromaddr, addrlen)<<endl;
1107      g_stats.unexpectedCount++;
1108     
1109      for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
1110        if(pident.fd==mthread->key.fd && !memcmp(&mthread->key.remote.sin_addr, &pident.remote.sin_addr, sizeof(pident.remote.sin_addr)) && 
1111           !strcasecmp(pident.domain.c_str(), mthread->key.domain.c_str())) {
1112          mthread->key.nearMisses++;
1113        }
1114      }
1115    }
1116    else 
1117      g_udpclientsocks.returnSocket(fd);
1118  }
1119  else
1120    L<<Logger::Warning<<"Ignoring question on outgoing socket from "<< sockAddrToString((struct sockaddr_in*) &fromaddr)  <<endl;
1121}
1122
1123FDMultiplexer* getMultiplexer()
1124{
1125  FDMultiplexer* ret;
1126  for(FDMultiplexer::FDMultiplexermap_t::const_iterator i = FDMultiplexer::getMultiplexerMap().begin();
1127      i != FDMultiplexer::getMultiplexerMap().end(); ++i) {
1128    try {
1129      ret=i->second();
1130      L<<Logger::Error<<"Enabled '"<<ret->getName()<<"' multiplexer"<<endl;
1131      return ret;
1132    }
1133    catch(...)
1134      {}
1135  }
1136  L<<Logger::Error<<"No working multiplexer found!"<<endl;
1137  exit(1);
1138}
1139
1140int main(int argc, char **argv) 
1141{
1142  reportBasicTypes();
1143
1144  int ret = EXIT_SUCCESS;
1145#ifdef WIN32
1146    WSADATA wsaData;
1147    WSAStartup( MAKEWORD( 2, 0 ), &wsaData );
1148#endif // WIN32
1149
1150  try {
1151    Utility::srandom(time(0));
1152    ::arg().set("soa-minimum-ttl","Don't change")="0";
1153    ::arg().set("soa-serial-offset","Don't change")="0";
1154    ::arg().set("no-shuffle","Don't change")="off";
1155    ::arg().set("aaaa-additional-processing","turn on to do AAAA additional processing (slow)")="off";
1156    ::arg().set("local-port","port to listen on")="53";
1157    ::arg().set("local-address","IP addresses to listen on, separated by spaces or commas")="127.0.0.1";
1158    ::arg().set("trace","if we should output heaps of logging")="off";
1159    ::arg().set("daemon","Operate as a daemon")="yes";
1160    ::arg().set("log-common-errors","If we should log rather common errors")="yes";
1161    ::arg().set("chroot","switch to chroot jail")="";
1162    ::arg().set("setgid","If set, change group id to this gid for more security")="";
1163    ::arg().set("setuid","If set, change user id to this uid for more security")="";
1164    ::arg().set("quiet","Suppress logging of questions and answers")="true";
1165    ::arg().set("config-dir","Location of configuration directory (recursor.conf)")=SYSCONFDIR;
1166    ::arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
1167    ::arg().set("delegation-only","Which domains we only accept delegations from")="";
1168    ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
1169    //    ::arg().set("query-local-port","Source port address for sending queries, defaults to random")="";
1170    ::arg().set("client-tcp-timeout","Timeout in seconds when talking to TCP clients")="2";
1171    ::arg().set("max-tcp-clients","Maximum number of simultaneous TCP clients")="128";
1172    ::arg().set("hint-file", "If set, load root hints from this file")="";
1173    ::arg().set("max-cache-entries", "If set, maximum number of entries in the main cache")="0";
1174    ::arg().set("max-negative-ttl", "maximum number of seconds to keep a negative cached entry in memory")="3600";
1175    ::arg().set("server-id", "Returned when queried for 'server.id' TXT, defaults to hostname")="";
1176    ::arg().set("remotes-ringbuffer-entries", "maximum number of packets to store statistics for")="0";
1177    ::arg().set("version-string", "maximum number of packets to store statistics for")="PowerDNS Recursor "VERSION" $Id$";
1178    ::arg().set("allow-from", "If set, only allow these comma separated netmasks to recurse")="127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12";
1179    ::arg().set("max-tcp-per-client", "If set, maximum number of TCP sessions per client (IP address)")="0";
1180    ::arg().set("fork", "If set, fork the daemon for possible double performance")="no";
1181    ::arg().set("spoof-nearmiss-max", "If non-zero, assume spoofing after this many near misses")="20";
1182    ::arg().set("single-socket", "If set, only use a single socket for outgoing queries")="off";
1183
1184    ::arg().setCmd("help","Provide a helpful message");
1185    L.toConsole(Logger::Warning);
1186    ::arg().laxParse(argc,argv); // do a lax parse
1187
1188    string configname=::arg()["config-dir"]+"/recursor.conf";
1189    cleanSlashes(configname);
1190
1191    if(!::arg().file(configname.c_str())) 
1192      L<<Logger::Warning<<"Unable to parse configuration file '"<<configname<<"'"<<endl;
1193
1194    ::arg().parse(argc,argv);
1195
1196    ::arg().set("delegation-only")=toLower(::arg()["delegation-only"]);
1197
1198    if(::arg().mustDo("help")) {
1199      cerr<<"syntax:"<<endl<<endl;
1200      cerr<<::arg().helpstring(::arg()["help"])<<endl;
1201      exit(99);
1202    }
1203
1204    L.setName("pdns_recursor");
1205
1206
1207    L<<Logger::Warning<<"PowerDNS recursor "<<VERSION<<" (C) 2001-2006 PowerDNS.COM BV ("<<__DATE__", "__TIME__;
1208#ifdef __GNUC__
1209    L<<", gcc "__VERSION__;
1210#endif // add other compilers here
1211    L<<") starting up"<<endl;
1212
1213    L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. "
1214      "This is free software, and you are welcome to redistribute it "
1215      "according to the terms of the GPL version 2."<<endl;
1216
1217    L<<Logger::Warning<<"Operating in "<<(sizeof(unsigned long)*8) <<" bits mode"<<endl;
1218
1219    if(!::arg()["allow-from"].empty()) {
1220      g_allowFrom=new NetmaskGroup;
1221      vector<string> ips;
1222      stringtok(ips, ::arg()["allow-from"], ", ");
1223      L<<Logger::Warning<<"Only allowing queries from: ";
1224      for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
1225        g_allowFrom->addMask(*i);
1226        if(i!=ips.begin())
1227          L<<Logger::Warning<<", ";
1228        L<<Logger::Warning<<*i;
1229      }
1230      L<<Logger::Warning<<endl;
1231    }
1232    else if(::arg()["local-address"]!="127.0.0.1" && ::arg().asNum("local-port")==53)
1233      L<<Logger::Error<<"WARNING: Allowing queries from all IP addresses - this can be a security risk!"<<endl;
1234   
1235    g_quiet=::arg().mustDo("quiet");
1236    if(::arg().mustDo("trace")) {
1237      SyncRes::setLog(true);
1238      ::arg().set("quiet")="no";
1239      g_quiet=false;
1240    }
1241
1242    SyncRes::s_maxnegttl=::arg().asNum("max-negative-ttl");
1243    SyncRes::s_serverID=::arg()["server-id"];
1244    if(SyncRes::s_serverID.empty()) {
1245      char tmp[128];
1246      gethostname(tmp, sizeof(tmp)-1);
1247      SyncRes::s_serverID=tmp;
1248    }
1249
1250    g_stats.remotes.resize(::arg().asNum("remotes-ringbuffer-entries"));
1251    memset(&*g_stats.remotes.begin(), 0, g_stats.remotes.size() * sizeof(RecursorStats::remotes_t::value_type));
1252    g_logCommonErrors=::arg().mustDo("log-common-errors");
1253
1254    makeUDPServerSockets();
1255    makeTCPServerSockets();
1256
1257    if(::arg().mustDo("fork")) {
1258      fork();
1259      L<<Logger::Warning<<"This is forked pid "<<getpid()<<endl;
1260    }
1261    g_fdm=getMultiplexer();
1262    makeControlChannelSocket();
1263   
1264    MT=new MTasker<PacketID,string>(100000);
1265   
1266    PacketID pident;
1267    primeHints();   
1268    L<<Logger::Warning<<"Done priming cache with root hints"<<endl;
1269#ifndef WIN32
1270    if(::arg().mustDo("daemon")) {
1271      L<<Logger::Warning<<"Calling daemonize, going to background"<<endl;
1272      L.toConsole(Logger::Critical);
1273      daemonize();
1274    }
1275   
1276    for(deferredAdd_t::const_iterator i=deferredAdd.begin(); i!=deferredAdd.end(); ++i) 
1277      g_fdm->addReadFD(i->first, i->second);
1278
1279    signal(SIGUSR1,usr1Handler);
1280    signal(SIGUSR2,usr2Handler);
1281    signal(SIGPIPE,SIG_IGN);
1282
1283    writePid();
1284#endif
1285
1286    int newgid=0;
1287    if(!::arg()["setgid"].empty())
1288      newgid=Utility::makeGidNumeric(::arg()["setgid"]);
1289    int newuid=0;
1290    if(!::arg()["setuid"].empty())
1291      newuid=Utility::makeUidNumeric(::arg()["setuid"]);
1292
1293
1294    if (!::arg()["chroot"].empty()) {
1295        if (chroot(::arg()["chroot"].c_str())<0) {
1296            L<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror (errno)<<", exiting"<<endl;
1297            exit(1);
1298        }
1299    }
1300
1301    Utility::dropPrivs(newuid, newgid);
1302
1303
1304    counter=0;
1305    unsigned int maxTcpClients=::arg().asNum("max-tcp-clients");
1306    g_tcpTimeout=::arg().asNum("client-tcp-timeout");
1307
1308    g_maxTCPPerClient=::arg().asNum("max-tcp-per-client");
1309
1310    g_fdm->addReadFD(s_rcc.d_fd, handleRCC); // control channel
1311    bool listenOnTCP(true);
1312
1313    for(;;) {
1314      while(MT->schedule()); // housekeeping, let threads do their thing
1315     
1316      if(!(counter%500)) {
1317        MT->makeThread(houseKeeping,0);
1318      }
1319
1320      if(!(counter%11)) {
1321        typedef vector<pair<int, boost::any> > expired_t;
1322        expired_t expired=g_fdm->getTimeouts(g_now);
1323       
1324        for(expired_t::iterator i=expired.begin() ; i != expired.end(); ++i) {
1325          TCPConnection conn=any_cast<TCPConnection>(i->second);
1326          if(conn.state != TCPConnection::DONE) {
1327            if(g_logCommonErrors)
1328              L<<Logger::Warning<<"Timeout from remote TCP client "<< conn.remote.toString() <<endl;
1329            g_fdm->removeReadFD(i->first);
1330            conn.closeAndCleanup();
1331          }
1332        }
1333      }
1334     
1335      counter++;
1336
1337      if(statsWanted) {
1338        doStats();
1339      }
1340
1341      gettimeofday(&g_now, 0);
1342      g_fdm->run(&g_now);
1343
1344      if(listenOnTCP) {
1345        if(TCPConnection::s_currentConnections > maxTcpClients) {  // shutdown
1346          for_each(g_tcpListenSockets.begin(), g_tcpListenSockets.end(), 
1347                   boost::bind(&FDMultiplexer::removeReadFD, g_fdm, _1));
1348          listenOnTCP=false;
1349        }
1350      }
1351      else {
1352        if(TCPConnection::s_currentConnections <= maxTcpClients) {  // reenable
1353          for_each(g_tcpListenSockets.begin(), g_tcpListenSockets.end(), 
1354                   boost::bind(&FDMultiplexer::addReadFD, 
1355                               g_fdm, _1, handleNewTCPQuestion, boost::any()));
1356          listenOnTCP=true;
1357        }
1358      }
1359    }
1360  }
1361  catch(AhuException &ae) {
1362    L<<Logger::Error<<"Exception: "<<ae.reason<<endl;
1363    ret=EXIT_FAILURE;
1364  }
1365  catch(exception &e) {
1366    L<<Logger::Error<<"STL Exception: "<<e.what()<<endl;
1367    ret=EXIT_FAILURE;
1368  }
1369  catch(...) {
1370    L<<Logger::Error<<"any other exception in main: "<<endl;
1371    ret=EXIT_FAILURE;
1372  }
1373 
1374#ifdef WIN32
1375  WSACleanup();
1376#endif // WIN32
1377
1378  return ret;
1379}
Note: See TracBrowser for help on using the browser.