root/trunk/pdns/pdns/common_startup.cc @ 2009

Revision 2009, 15.4 KB (checked in by ahu, 2 years ago)

widen allow-axfr-ips to IPv6, plus add query-local-address6 for inbound AXFR & outbound notifications over IPv6

  • 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) 2005 - 2010  PowerDNS.COM BV
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License version 2
7    as published by the Free Software Foundation
8   
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18*/
19#include "common_startup.hh"
20
21typedef Distributor<DNSPacket,DNSPacket,PacketHandler> DNSDistributor;
22
23
24ArgvMap theArg;
25StatBag S;  //!< Statistics are gathered accross PDNS via the StatBag class S
26PacketCache PC; //!< This is the main PacketCache, shared accross all threads
27DNSProxy *DP;
28DynListener *dl;
29CommunicatorClass Communicator;
30UDPNameserver *N;
31int avg_latency;
32TCPNameserver *TN;
33
34ArgvMap &arg()
35{
36  return theArg;
37}
38
39void declareArguments()
40{
41  ::arg().set("local-port","The port on which we listen")="53";
42  ::arg().setSwitch("log-failed-updates","If PDNS should log failed update requests")="";
43  ::arg().setSwitch("log-dns-details","If PDNS should log DNS non-erroneous details")="";
44  ::arg().setSwitch("allow-recursion-override","Set this so that local data fully overrides the recursor")="no";
45  ::arg().set("urlredirector","Where we send hosts to that need to be url redirected")="127.0.0.1";
46  ::arg().set("smtpredirector","Our smtpredir MX host")="a.misconfigured.powerdns.smtp.server";
47  ::arg().set("local-address","Local IP addresses to which we bind")="0.0.0.0";
48  ::arg().set("local-ipv6","Local IP address to which we bind")="";
49  ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
50  ::arg().set("query-local-address6","Source IPv6 address for sending queries")="::";
51  ::arg().set("max-queue-length","Maximum queuelength before considering situation lost")="5000";
52  ::arg().set("soa-serial-offset","Make sure that no SOA serial is less than this number")="0";
53 
54  ::arg().set("retrieval-threads", "Number of AXFR-retrieval threads for slave operation")="2";
55
56  ::arg().setCmd("help","Provide a helpful message");
57  ::arg().setCmd("version","Output version and compilation date");
58  ::arg().setCmd("config","Provide configuration file on standard output");
59  ::arg().setCmd("list-modules","Lists all modules available");
60  ::arg().setCmd("no-config","Don't parse configuration file");
61 
62  ::arg().set("version-string","PowerDNS version in packets - full, anonymous, powerdns or custom")="full"; 
63  ::arg().set("control-console","Debugging switch - don't use")="no"; // but I know you will!
64  ::arg().set("fancy-records","Process URL and MBOXFW records")="no";
65  ::arg().set("wildcard-url","Process URL and MBOXFW records")="no";
66  ::arg().set("wildcards","Honor wildcards in the database")="";
67  ::arg().set("loglevel","Amount of logging. Higher is more. Do not set below 3")="4";
68  ::arg().set("default-soa-name","name to insert in the SOA record if none set in the backend")="a.misconfigured.powerdns.server";
69  ::arg().set("distributor-threads","Default number of Distributor (backend) threads to start")="3";
70  ::arg().set("signing-threads","Default number of signer threads to start")="3";
71  ::arg().set("receiver-threads","Default number of Distributor (backend) threads to start")="1";
72  ::arg().set("queue-limit","Maximum number of milliseconds to queue a query")="1500"; 
73  ::arg().set("recursor","If recursion is desired, IP address of a recursing nameserver")="no"; 
74  ::arg().set("lazy-recursion","Only recurse if question cannot be answered locally")="yes";
75  ::arg().set("allow-recursion","List of subnets that are allowed to recurse")="0.0.0.0/0";
76  ::arg().set("pipebackend-abi-version","Version of the pipe backend ABI")="1";
77 
78  ::arg().set("disable-tcp","Do not listen to TCP queries")="no";
79  ::arg().set("disable-axfr","Do not allow zone transfers")="no";
80 
81  ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
82
83  ::arg().set("load-modules","Load this module - supply absolute or relative path")="";
84  ::arg().set("launch","Which backends to launch and order to query them in")="";
85  ::arg().setSwitch("disable-axfr","Disable zonetransfers but do allow TCP queries")="no";
86  ::arg().set("allow-axfr-ips","Allow zonetransfers only to these subnets")="0.0.0.0/0,::/0";
87  ::arg().set("slave-cycle-interval","Reschedule failed SOA serial checks once every .. seconds")="60";
88
89  ::arg().set("tcp-control-address","If set, PowerDNS can be controlled over TCP on this address")="";
90  ::arg().set("tcp-control-port","If set, PowerDNS can be controlled over TCP on this address")="53000";
91  ::arg().set("tcp-control-secret","If set, PowerDNS can be controlled over TCP after passing this secret")="";
92  ::arg().set("tcp-control-range","If set, remote control of PowerDNS is possible over these networks only")="127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10";
93 
94  ::arg().setSwitch("slave","Act as a slave")="no";
95  ::arg().setSwitch("master","Act as a master")="no";
96  ::arg().setSwitch("guardian","Run within a guardian process")="no";
97  ::arg().setSwitch("skip-cname","Do not perform CNAME indirection for each query")="no";
98  ::arg().setSwitch("strict-rfc-axfrs","Perform strictly rfc compliant axfrs (very slow)")="no";
99  ::arg().setSwitch("send-root-referral","Send out old-fashioned root-referral instead of ServFail in case of no authority")="no";
100
101  ::arg().setSwitch("webserver","Start a webserver for monitoring")="no"; 
102  ::arg().setSwitch("webserver-print-arguments","If the webserver should print arguments")="no"; 
103  ::arg().set("webserver-address","IP Address of webserver to listen on")="127.0.0.1";
104  ::arg().set("webserver-port","Port of webserver to listen on")="8081";
105  ::arg().set("webserver-password","Password required for accessing the webserver")="";
106
107  ::arg().setSwitch("out-of-zone-additional-processing","Do out of zone additional processing")="yes";
108  ::arg().setSwitch("do-ipv6-additional-processing", "Do AAAA additional processing")="no";
109  ::arg().setSwitch("query-logging","Hint backends that queries should be logged")="no";
110 
111  ::arg().set("cache-ttl","Seconds to store packets in the PacketCache")="20";
112  ::arg().set("recursive-cache-ttl","Seconds to store packets in the PacketCache")="10";
113  ::arg().set("negquery-cache-ttl","Seconds to store packets in the PacketCache")="60";
114  ::arg().set("query-cache-ttl","Seconds to store packets in the PacketCache")="20";
115  ::arg().set("soa-minimum-ttl","Default SOA mininum ttl")="3600";
116  ::arg().set("server-id", "Returned when queried for 'server.id' TXT or NSID, defaults to hostname")="";
117  ::arg().set("soa-refresh-default","Default SOA refresh")="10800";
118  ::arg().set("soa-retry-default","Default SOA retry")="3600";
119  ::arg().set("soa-expire-default","Default SOA expire")="604800";
120
121  ::arg().set("trusted-notification-proxy", "IP address of incoming notification proxy")="";
122  ::arg().set("slave-renotify", "If we should send out notifications for slaved updates")="no";
123
124  ::arg().set("default-ttl","Seconds a result is valid if not set otherwise")="3600";
125  ::arg().set("max-tcp-connections","Maximum number of TCP connections")="10";
126  ::arg().setSwitch("no-shuffle","Set this to prevent random shuffling of answers - for regression testing")="off";
127  ::arg().setSwitch("per-zone-axfr-acls","When set, backends that implement it perform per-zone AXFL ACL checks")="off";
128
129  ::arg().setSwitch( "use-logfile", "Use a log file (Windows only)" )= "no";
130  ::arg().set( "logfile", "Logfile to use (Windows only)" )= "pdns.log";
131  ::arg().set("setuid","If set, change user id to this uid for more security")="";
132  ::arg().set("setgid","If set, change group id to this gid for more security")="";
133
134  ::arg().set("max-cache-entries", "Maximum number of cache entries")="1000000";
135  ::arg().set("entropy-source", "If set, read entropy from this file")="/dev/urandom";
136}
137
138void declareStats(void)
139{
140  S.declare("udp-queries","Number of UDP queries received");
141  S.declare("udp-answers","Number of answers sent out over UDP");
142
143  S.declare("udp4-answers","Number of IPv4 answers sent out over UDP");
144  S.declare("udp4-queries","Number of IPv4UDP queries received");
145  S.declare("udp6-answers","Number of IPv6 answers sent out over UDP");
146  S.declare("udp6-queries","Number of IPv6 UDP queries received");
147
148  S.declare("recursing-answers","Number of recursive answers sent out");
149  S.declare("recursing-questions","Number of questions sent to recursor");
150  S.declare("corrupt-packets","Number of corrupt packets received");
151
152  S.declare("tcp-queries","Number of TCP queries received");
153  S.declare("tcp-answers","Number of answers sent out over TCP");
154
155  S.declare("qsize-q","Number of questions waiting for database attention");
156
157  S.declare("deferred-cache-inserts","Amount of cache inserts that were deferred because of maintenance");
158  S.declare("deferred-cache-lookup","Amount of cache lookups that were deferred because of maintenance");
159
160  S.declare("query-cache-hit","Number of hits on the query cache");
161  S.declare("query-cache-miss","Number of misses on the query cache");
162
163
164  S.declare("servfail-packets","Number of times a server-failed packet was sent out");
165  S.declare("latency","Average number of microseconds needed to answer a question");
166  S.declare("timedout-packets","Number of packets which weren't answered within timeout set");
167
168  S.declareRing("queries","UDP Queries Received");
169  S.declareRing("nxdomain-queries","Queries for non-existent records within existent domains");
170  S.declareRing("noerror-queries","Queries for existing records, but for type we don't have");
171  S.declareRing("servfail-queries","Queries that could not be answered due to backend errors");
172  S.declareRing("unauth-queries","Queries for domains that we are not authoritative for");
173  S.declareRing("logmessages","Log Messages");
174  S.declareRing("remotes","Remote server IP addresses");
175  S.declareRing("remotes-unauth","Remote hosts querying domains for which we are not auth");
176  S.declareRing("remotes-corrupt","Remote hosts sending corrupt packets");
177
178}
179
180
181int isGuarded(char **argv)
182{
183  char *p=strstr(argv[0],"-instance");
184
185  return !!p;
186}
187
188
189void sendout(const DNSDistributor::AnswerData &AD)
190{
191  static unsigned int &numanswered=*S.getPointer("udp-answers");
192  static unsigned int &numanswered4=*S.getPointer("udp4-answers");
193  static unsigned int &numanswered6=*S.getPointer("udp6-answers");
194
195  if(!AD.A)
196    return;
197 
198  N->send(AD.A);
199  numanswered++;
200
201  if(AD.A->remote.getSocklen()==sizeof(sockaddr_in))
202    numanswered4++;
203  else
204    numanswered6++;
205
206  int diff=AD.A->d_dt.udiff();
207  avg_latency=(int)(1023*avg_latency/1024+diff/1024);
208
209  delete AD.A; 
210}
211
212static DNSDistributor* g_distributor;
213static pthread_mutex_t d_distributorlock =PTHREAD_MUTEX_INITIALIZER;
214static bool g_mustlockdistributor;
215
216//! The qthread receives questions over the internet via the Nameserver class, and hands them to the Distributor for futher processing
217void *qthread(void *number)
218{
219  DNSPacket *P;
220
221  DNSPacket question;
222  DNSPacket cached;
223
224  unsigned int &numreceived=*S.getPointer("udp-queries");
225  unsigned int &numanswered=*S.getPointer("udp-answers");
226
227  unsigned int &numreceived4=*S.getPointer("udp4-queries");
228  unsigned int &numanswered4=*S.getPointer("udp4-answers");
229
230  unsigned int &numreceived6=*S.getPointer("udp6-queries");
231  unsigned int &numanswered6=*S.getPointer("udp6-answers");
232  numreceived=-1;
233  int diff;
234  bool logDNSDetails= ::arg().mustDo("log-dns-details");
235 
236  for(;;) {
237    if(number==0) { // only run on main thread
238      if(!((numreceived++)%250)) { // maintenance tasks
239        S.set("latency",(int)avg_latency);
240        int qcount, acount;
241        g_distributor->getQueueSizes(qcount, acount);
242        S.set("qsize-q",qcount);
243      }
244    }
245
246    if(!(P=N->receive(&question))) { // receive a packet         inline
247      continue;                    // packet was broken, try again
248    }
249
250    if(P->remote.getSocklen()==sizeof(sockaddr_in))
251      numreceived4++;
252    else
253      numreceived6++;
254
255    S.ringAccount("queries", P->qdomain+"/"+P->qtype.getName());
256    S.ringAccount("remotes",P->getRemote());
257    if(logDNSDetails) 
258      L << Logger::Notice<<"Remote "<< P->remote.toString() <<" wants '" << P->qdomain<<"|"<<P->qtype.getName() << 
259        "', do = " <<P->d_dnssecOk <<", bufsize = "<< P->getMaxReplyLen()<<": ";
260
261    if((P->d.opcode != Opcode::Notify) && P->couldBeCached() && PC.get(P, &cached)) { // short circuit - does the PacketCache recognize this question?
262      if(logDNSDetails)
263        L<<"packetcache HIT"<<endl;
264      cached.setRemote(&P->remote);  // inlined
265      cached.setSocket(P->getSocket());                               // inlined
266      cached.setMaxReplyLen(P->getMaxReplyLen());
267      cached.d.rd=P->d.rd; // copy in recursion desired bit
268      cached.d.id=P->d.id;
269      cached.commitD(); // commit d to the packet                        inlined
270
271      N->send(&cached);   // answer it then                              inlined
272      diff=P->d_dt.udiff();                                                   
273      avg_latency=(int)(0.999*avg_latency+0.001*diff); // 'EWMA'
274     
275      numanswered++;
276      if(P->remote.sin4.sin_family==AF_INET)
277        numanswered4++;
278      else
279        numanswered6++;
280
281      continue;
282    }
283    if(logDNSDetails)
284        L<<"packetcache MISS"<<endl;
285    if(g_mustlockdistributor) {
286      Lock l(&d_distributorlock);
287      g_distributor->question(P, &sendout); // otherwise, give to the distributor
288    }
289    else
290      g_distributor->question(P, &sendout); // otherwise, give to the distributor
291  }
292  return 0;
293}
294
295void mainthread()
296{
297  Utility::srandom(time(0));
298
299   int newgid=0;     
300   if(!::arg()["setgid"].empty()) 
301     newgid=Utility::makeGidNumeric(::arg()["setgid"]);     
302   int newuid=0;     
303   if(!::arg()["setuid"].empty())       
304     newuid=Utility::makeUidNumeric(::arg()["setuid"]); 
305#ifndef WIN32
306
307   if(!::arg()["chroot"].empty()) { 
308     if(::arg().mustDo("master") || ::arg().mustDo("slave"))
309        gethostbyname("a.root-servers.net"); // this forces all lookup libraries to be loaded
310     if(chroot(::arg()["chroot"].c_str())<0 || chdir("/")<0) {
311       L<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror(errno)<<", exiting"<<endl; 
312       exit(1);
313     }   
314     else
315       L<<Logger::Error<<"Chrooted to '"<<::arg()["chroot"]<<"'"<<endl;     
316   } 
317#endif
318  StatWebServer sws;
319  Utility::dropPrivs(newuid, newgid);
320
321  if(::arg().mustDo("recursor")){
322    DP=new DNSProxy(::arg()["recursor"]);
323    DP->onlyFrom(::arg()["allow-recursion"]);
324    DP->go();
325  }
326  // NOW SAFE TO CREATE THREADS!
327  dl->go();
328
329  pthread_t qtid;
330
331
332  if(::arg().mustDo("webserver"))
333    sws.go();
334 
335  if(::arg().mustDo("slave") || ::arg().mustDo("master"))
336    Communicator.go(); 
337
338  if(TN)
339    TN->go(); // tcp nameserver launch
340   
341  //  fork(); (this worked :-))
342  g_distributor = new DNSDistributor(::arg().asNum("distributor-threads")); // the big dispatcher!
343  if(::arg().asNum("receiver-threads") > 1) {
344    g_mustlockdistributor=true;
345  }
346  for(int n=0; n < ::arg().asNum("receiver-threads"); ++n)
347    pthread_create(&qtid,0,qthread, reinterpret_cast<void *>(n)); // receives packets
348
349  void *p;
350  pthread_join(qtid, &p);
351 
352  L<<Logger::Error<<"Mainthread exiting - should never happen"<<endl;
353}
354
355
356
357
Note: See TracBrowser for help on using the browser.