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

Revision 749, 41.0 KB (checked in by ahu, 7 years ago)

work around 3.4.4 compiler bugs (freebsd 6 system compiler)

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