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

Revision 810, 46.6 KB (checked in by ahu, 7 years ago)

tiny fixup

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