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

Revision 680, 12.8 KB (checked in by ahu, 7 years ago)

the FSF has moved!

  • 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  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 as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
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
39
40void declareArguments()
41{
42  arg().set("local-port","The port on which we listen")="53";
43  arg().setSwitch("log-failed-updates","If PDNS should log failed update requests")="";
44  arg().setSwitch("log-dns-details","If PDNS should log DNS non-erroneous details")="";
45  arg().setSwitch("allow-recursion-override","Set this so that local data fully overrides the recursor")="no";
46  arg().set("urlredirector","Where we send hosts to that need to be url redirected")="127.0.0.1";
47  arg().set("smtpredirector","Our smtpredir MX host")="a.misconfigured.powerdns.smtp.server";
48  arg().set("local-address","Local IP addresses to which we bind")="0.0.0.0";
49  arg().set("local-ipv6","Local IP address to which we bind")="";
50  arg().set("query-local-address","Source IP 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().setCmd("help","Provide a helpful message");
55  arg().setCmd("version","Output version and compilation date");
56  arg().setCmd("config","Provide configuration file on standard output");
57  arg().setCmd("list-modules","Lists all modules available");
58  arg().setCmd("no-config","Don't parse configuration file");
59 
60  arg().set("version-string","PowerDNS version in packets - full, anonymous, powerdns or custom")="full"; 
61  arg().set("control-console","Debugging switch - don't use")="no"; // but I know you will!
62  arg().set("fancy-records","Process URL and MBOXFW records")="no";
63  arg().set("wildcard-url","Process URL and MBOXFW records")="no";
64  arg().set("wildcards","Honor wildcards in the database")="";
65  arg().set("loglevel","Amount of logging. Higher is more. Do not set below 3")="4";
66  arg().set("default-soa-name","name to insert in the SOA record if none set in the backend")="a.misconfigured.powerdns.server";
67  arg().set("distributor-threads","Default number of Distributor (backend) threads to start")="3";
68  arg().set("queue-limit","Maximum number of milliseconds to queue a query")="1500"; 
69  arg().set("recursor","If recursion is desired, IP address of a recursing nameserver")="no"; 
70  arg().set("lazy-recursion","Only recurse if question cannot be answered locally")="yes";
71  arg().set("allow-recursion","List of subnets that are allowed to recurse")="0.0.0.0/0";
72  arg().set("pipebackend-abi-version","Version of the pipe backend ABI")="1";
73 
74  arg().set("disable-tcp","Do not listen to TCP queries")="no";
75  arg().set("disable-axfr","Do not allow zone transfers")="no";
76 
77  arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
78
79  arg().set("load-modules","Load this module - supply absolute or relative path")="";
80  arg().set("launch","Which backends to launch and order to query them in")="";
81  arg().setSwitch("disable-axfr","Disable zonetransfers but do allow TCP queries")="no";
82  arg().set("allow-axfr-ips","Allow zonetransfers only to these subnets")="0.0.0.0/0";
83  arg().set("slave-cycle-interval","Reschedule failed SOA serial checks once every .. seconds")="60";
84 
85  arg().setSwitch("slave","Act as a slave")="no";
86  arg().setSwitch("master","Act as a master")="no";
87  arg().setSwitch("guardian","Run within a guardian process")="no";
88  arg().setSwitch("skip-cname","Do not perform CNAME indirection for each query")="no";
89  arg().setSwitch("strict-rfc-axfrs","Perform strictly rfc compliant axfrs (very slow)")="no";
90  arg().setSwitch("send-root-referral","Send out old-fashioned root-referral instead of ServFail in case of no authority")="no";
91
92  arg().setSwitch("webserver","Start a webserver for monitoring")="no"; 
93  arg().setSwitch("webserver-print-arguments","If the webserver should print arguments")="no"; 
94  arg().set("webserver-address","IP Address of webserver to listen on")="127.0.0.1";
95  arg().set("webserver-port","Port of webserver to listen on")="8081";
96  arg().set("webserver-password","Password required for accessing the webserver")="";
97
98  arg().setSwitch("out-of-zone-additional-processing","Do out of zone additional processing")="yes";
99  arg().setSwitch("do-ipv6-additional-processing", "Do AAAA additional processing")="no";
100  arg().setSwitch("query-logging","Hint backends that queries should be logged")="no";
101 
102  arg().set("cache-ttl","Seconds to store packets in the PacketCache")="20";
103  arg().set("recursive-cache-ttl","Seconds to store packets in the PacketCache")="10";
104  arg().set("negquery-cache-ttl","Seconds to store packets in the PacketCache")="60";
105  arg().set("query-cache-ttl","Seconds to store packets in the PacketCache")="20";
106  arg().set("soa-minimum-ttl","Default SOA mininum ttl")="3600";
107
108  arg().set("soa-refresh-default","Default SOA refresh")="10800";
109  arg().set("soa-retry-default","Default SOA retry")="3600";
110  arg().set("soa-expire-default","Default SOA expire")="604800";
111
112  arg().set("default-ttl","Seconds a result is valid if not set otherwise")="3600";
113  arg().set("max-tcp-connections","Maximum number of TCP connections")="10";
114  arg().setSwitch("no-shuffle","Set this to prevent random shuffling of answers - for regression testing")="off";
115
116  arg().setSwitch( "use-logfile", "Use a log file" )= "no";
117  arg().set( "logfile", "Logfile to use" )= "pdns.log";
118  arg().set("setuid","If set, change user id to this uid for more security")="";
119  arg().set("setgid","If set, change group id to this gid for more security")="";
120}
121
122
123
124void declareStats(void)
125{
126  S.declare("udp-queries","Number of UDP queries received");
127  S.declare("udp-answers","Number of answers sent out over UDP");
128
129  S.declare("udp4-answers","Number of IPv4 answers sent out over UDP");
130  S.declare("udp4-queries","Number of IPv4UDP queries received");
131  S.declare("udp6-answers","Number of IPv6 answers sent out over UDP");
132  S.declare("udp6-queries","Number of IPv6 UDP queries received");
133
134  S.declare("recursing-answers","Number of recursive answers sent out");
135  S.declare("recursing-questions","Number of questions sent to recursor");
136  S.declare("corrupt-packets","Number of corrupt packets received");
137
138  S.declare("tcp-queries","Number of TCP queries received");
139  S.declare("tcp-answers","Number of answers sent out over TCP");
140
141  S.declare("qsize-q","Number of questions waiting for database attention");
142
143  S.declare("deferred-cache-inserts","Amount of cache inserts that were deferred because of maintenance");
144  S.declare("deferred-cache-lookup","Amount of cache lookups that were deferred because of maintenance");
145
146  S.declare("query-cache-hit","Number of hits on the query cache");
147  S.declare("query-cache-miss","Number of misses on the query cache");
148
149
150  S.declare("servfail-packets","Number of times a server-failed packet was sent out");
151  S.declare("latency","Average number of microseconds needed to answer a question");
152  S.declare("timedout-packets","Number of packets which weren't answered within timeout set");
153
154  S.declareRing("queries","UDP Queries Received");
155  S.declareRing("nxdomain-queries","Queries for non-existent records within existent domains");
156  S.declareRing("noerror-queries","Queries for existing records, but for type we don't have");
157  S.declareRing("servfail-queries","Queries that could not be answered due to backend errors");
158  S.declareRing("unauth-queries","Queries for domains that we are not authoritative for");
159  S.declareRing("logmessages","Log Messages");
160  S.declareRing("remotes","Remote server IP addresses");
161  S.declareRing("remotes-unauth","Remote hosts querying domains for which we are not auth");
162  S.declareRing("remotes-corrupt","Remote hosts sending corrupt packets");
163
164}
165
166
167int isGuarded(char **argv)
168{
169  char *p=strstr(argv[0],"-instance");
170
171  return !!p;
172}
173
174
175void sendout(const DNSDistributor::AnswerData &AD)
176{
177  static int &numanswered=*S.getPointer("udp-answers");
178  static int &numanswered4=*S.getPointer("udp4-answers");
179  static int &numanswered6=*S.getPointer("udp6-answers");
180
181  if(!AD.A)
182    return;
183 
184  N->send(AD.A);
185  numanswered++;
186
187  if(AD.A->d_socklen==sizeof(sockaddr_in))
188    numanswered4++;
189  else
190    numanswered6++;
191
192  int diff=AD.A->d_dt.udiff();
193  avg_latency=(int)(1023*avg_latency/1024+diff/1024);
194
195  delete AD.A; 
196}
197
198
199//! The qthread receives questions over the internet via the Nameserver class, and hands them to the Distributor for futher processing
200void *qthread(void *p)
201{
202  DNSDistributor *D=static_cast<DNSDistributor *>(p);
203
204  DNSPacket *P;
205
206  DNSPacket question;
207  DNSPacket cached;
208
209  int &numreceived=*S.getPointer("udp-queries");
210  int &numanswered=*S.getPointer("udp-answers");
211
212  int &numreceived4=*S.getPointer("udp4-queries");
213  int &numanswered4=*S.getPointer("udp4-answers");
214
215  int &numreceived6=*S.getPointer("udp6-queries");
216  int &numanswered6=*S.getPointer("udp6-answers");
217  numreceived=-1;
218  int diff;
219
220  for(;;) {
221    if(!((numreceived++)%50)) { // maintenance tasks
222      S.set("latency",(int)avg_latency);
223      int qcount, acount;
224      D->getQueueSizes(qcount, acount);
225      S.set("qsize-q",qcount);
226    }
227   
228    if(!(P=N->receive(&question))) { // receive a packet         inline
229      continue;                    // packet was broken, try again
230    }
231
232    if(P->d_socklen==sizeof(sockaddr_in))
233      numreceived4++;
234    else
235      numreceived6++;
236
237    S.ringAccount("queries", P->qdomain+"/"+P->qtype.getName());
238    S.ringAccount("remotes",P->getRemote());
239
240    if(PC.get(P,&cached)) { // short circuit - does the PacketCache recognize this question?
241      cached.setRemote((struct sockaddr *)(P->remote),P->d_socklen);  // inlined
242      cached.setSocket(P->getSocket());                               // inlined
243      cached.spoofID(P->d.id);                                        // inlined
244      cached.d.rd=P->d.rd; // copy in recursion desired bit
245      cached.commitD(); // commit d to the packet                        inlined
246
247      N->send(&cached);   // answer it then                              inlined
248      diff=P->d_dt.udiff();                                                   
249      avg_latency=(int)(0.999*avg_latency+0.001*diff); // 'EWMA'
250     
251      numanswered++;
252      if(P->d_socklen==sizeof(sockaddr_in))
253        numanswered4++;
254      else
255        numanswered6++;
256
257      continue;
258    }
259
260    D->question(P, &sendout); // otherwise, give to the distributor
261  }
262  return 0;
263}
264
265
266void mainthread()
267{
268  Utility::srandom(time(0));
269
270   int newgid=0;     
271   if(!arg()["setgid"].empty()) 
272     newgid=Utility::makeGidNumeric(arg()["setgid"]);     
273   int newuid=0;     
274   if(!arg()["setuid"].empty())       
275     newuid=Utility::makeUidNumeric(arg()["setuid"]); 
276#ifndef WIN32
277
278   if(!arg()["chroot"].empty()) { 
279     if(arg().mustDo("master") || arg().mustDo("slave"))
280        gethostbyname("a.root-servers.net"); // this forces all lookup libraries to be loaded
281     if(chroot(arg()["chroot"].c_str())<0) {
282       L<<Logger::Error<<"Unable to chroot to '"+arg()["chroot"]+"': "<<strerror(errno)<<", exiting"<<endl; 
283       exit(1);
284     }   
285     else
286       L<<Logger::Error<<"Chrooted to '"<<arg()["chroot"]<<"'"<<endl;     
287   } 
288#endif
289
290   Utility::dropPrivs(newuid, newgid);
291
292  if(arg().mustDo("recursor")){
293    DP=new DNSProxy(arg()["recursor"]);
294    DP->onlyFrom(arg()["allow-recursion"]);
295    DP->go();
296  }
297  // NOW SAFE TO CREATE THREADS!
298  dl->go();
299
300  pthread_t qtid;
301  StatWebServer sws;
302
303  if(arg().mustDo("webserver"))
304    sws.go();
305 
306  if(arg().mustDo("slave") || arg().mustDo("master"))
307    Communicator.go(); 
308
309  if(TN)
310    TN->go(); // tcp nameserver launch
311   
312  //  fork(); (this worked :-))
313  DNSDistributor *D= new DNSDistributor(arg().asNum("distributor-threads")); // the big dispatcher!
314  pthread_create(&qtid,0,qthread,static_cast<void *>(D)); // receives packets
315
316  void *p;
317  pthread_join(qtid, &p);
318 
319  L<<Logger::Error<<"Mainthread exiting - should never happen"<<endl;
320}
321
322
323
324
Note: See TracBrowser for help on using the browser.