]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/common_startup.cc
Initial revision
[thirdparty/pdns.git] / pdns / common_startup.cc
1 /*
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 #include "common_startup.hh"
20
21 typedef Distributor<DNSPacket,DNSPacket,PacketHandler> DNSDistributor;
22
23
24 ArgvMap theArg;
25 StatBag S; //!< Statistics are gathered accross PDNS via the StatBag class S
26 PacketCache PC; //!< This is the main PacketCache, shared accross all threads
27 DNSProxy *DP;
28 DynListener *dl;
29 CommunicatorClass Communicator;
30 UDPNameserver *N;
31 int avg_latency;
32 TCPNameserver *TN;
33
34 ArgvMap &arg()
35 {
36 return theArg;
37 }
38
39
40 void 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 failed update requests")="";
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 address to which we bind")="0.0.0.0";
48 arg().set("local-ipv6","Local IP address to which we bind")="";
49 arg().set("max-queue-length","Maximum queuelength before considering situation lost")="5000";
50 arg().set("soa-serial-offset","Make sure that no SOA serial is less than this number")="0";
51 arg().set("only-soa","Make sure that no SOA serial is less than this number")="org";
52 arg().setCmd("help","Provide a helpful message");
53 arg().setCmd("config","Provide a helpful message");
54 arg().setCmd("list-modules","Lists all modules available");
55 arg().setCmd("no-config","Don't parse configuration file");
56
57 arg().set("control-console","Debugging switch - don't use")="no"; // but I know you will!
58 arg().set("fancy-records","Process URL and MBOXFW records")="no";
59 arg().set("wildcard-url","Process URL and MBOXFW records")="no";
60 arg().set("wildcards","Honor wildcards in the database")="";
61 arg().set("loglevel","Amount of logging. Higher is more. Do not set below 3")="4";
62 arg().set("default-soa-name","name to insert in the SOA record if none set in the backend")="a.misconfigured.powerdns.server";
63 arg().set("distributor-threads","Default number of Distributor (backend) threads to start")="3";
64 arg().set("queue-limit","Maximum number of milliseconds to queue a query")="1500";
65 arg().set("recursor","If recursion is desired, IP address of a recursing nameserver")="no";
66 arg().set("lazy-recursion","Only recurse if question cannot be answered locally")="yes";
67 arg().set("allow-recursion","List of netmasks that are allowed to recurse")="";
68
69 arg().set("disable-tcp","Do not listen to TCP queries")="no";
70 arg().set("disable-axfr","Do not allow zone transfers")="no";
71
72 arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
73
74 arg().set("load-modules","Load this module - supply absolute or relative path")="";
75 arg().set("launch","Which backends to launch and order to query them in")="";
76 arg().setSwitch("disable-axfr","Disable zonetransfers but do allow TCP queries")="no";
77 arg().set("allow-axfr-ips","If disabled, DO allow zonetransfers from these IP addresses")="";
78 arg().set("slave-cycle-interval","Reschedule failed SOA serial checks once every .. seconds")="60";
79
80 arg().setSwitch("slave","Act as a slave")="no";
81 arg().setSwitch("master","Act as a master")="no";
82 arg().setSwitch("guardian","Run within a guardian process")="no";
83 arg().setSwitch("skip-cname","Do not perform CNAME indirection for each query")="no";
84 arg().setSwitch("strict-rfc-axfrs","Perform strictly rfc compliant axfrs (very slow)")="no";
85
86 arg().setSwitch("webserver","Start a webserver for monitoring")="no";
87 arg().setSwitch("webserver-print-arguments","If the webserver should print arguments")="no";
88 arg().set("webserver-address","IP Address of webserver to listen on")="127.0.0.1";
89 arg().set("webserver-port","Port of webserver to listen on")="8081";
90 arg().set("webserver-password","Password required for accessing the webserver")="";
91
92 arg().set("receiver-threads","Number of receiver threads to launch")="1";
93
94 arg().setSwitch("out-of-zone-additional-processing","Do out of zone additional processing")="no";
95 arg().setSwitch("query-logging","Hint backends that queries should be logged")="no";
96
97 arg().set("cache-ttl","Seconds to store packets in the PacketCache")="20";
98 arg().set("recursive-cache-ttl","Seconds to store packets in the PacketCache")="10";
99 arg().set("negquery-cache-ttl","Seconds to store packets in the PacketCache")="60";
100 arg().set("query-cache-ttl","Seconds to store packets in the PacketCache")="20";
101 arg().set("soa-minimum-ttl","Default SOA mininum ttl")="3600";
102 arg().set("max-tcp-connections","Maximum number of TCP connections")="10";
103
104 arg().setSwitch( "use-logfile", "Use a log file" )= "no";
105 arg().set( "logfile", "Logfile to use" )= "pdns.log";
106
107 }
108
109
110
111 void declareStats(void)
112 {
113 S.declare("udp-queries","Number of UDP queries received");
114 S.declare("udp-answers","Number of answers sent out over UDP");
115 S.declare("recursing-answers","Number of recursive answers sent out");
116 S.declare("recursing-questions","Number of questions sent to recursor");
117 S.declare("corrupt-packets","Number of corrupt packets received");
118
119 S.declare("tcp-queries","Number of TCP queries received");
120 S.declare("tcp-answers","Number of answers sent out over TCP");
121
122 S.declare("qsize-q","Number of questions waiting for database attention");
123
124 S.declare("deferred-cache-inserts","Amount of cache inserts that were deferred because of maintenance");
125 S.declare("deferred-cache-lookup","Amount of cache lookups that were deferred because of maintenance");
126
127 S.declare("query-cache-hit","Number of hits on the query cache");
128 S.declare("query-cache-miss","Number of misses on the query cache");
129
130
131 S.declare("servfail-packets","Number of times a server-failed packet was sent out");
132 S.declare("latency","Average number of microseconds needed to answer a question");
133 S.declare("timedout-packets","Number of packets which weren't answered within timeout set");
134
135 S.declareRing("queries","UDP Queries Received");
136 S.declareRing("nxdomain-queries","Queries for non-existent records within existent domains");
137 S.declareRing("noerror-queries","Queries for existing records, but for type we don't have");
138 S.declareRing("servfail-queries","Queries that could not be answered due to backend errors");
139 S.declareRing("unauth-queries","Queries for domains that we are not authoritative for");
140 S.declareRing("logmessages","Log Messages");
141 S.declareRing("remotes","Remote server IP addresses");
142 S.declareRing("remotes-unauth","Remote hosts querying domains for which we are not auth");
143 S.declareRing("remotes-corrupt","Remote hosts sending corrupt packets");
144
145 }
146
147
148 int isGuarded(char **argv)
149 {
150 char *p=strstr(argv[0],"-instance");
151
152 return !!p;
153 }
154
155
156 void sendout(const DNSDistributor::AnswerData &AD)
157 {
158 static int &numanswered=*S.getPointer("udp-answers");
159 if(!AD.A)
160 return;
161
162 N->send(AD.A);
163 numanswered++;
164 int diff=AD.A->d_dt.udiff();
165 avg_latency=(int)(0.999*avg_latency+0.001*diff);
166
167 delete AD.A;
168
169
170 }
171
172
173 //! The qthread receives questions over the internet via the Nameserver class, and hands them to the Distributor for futher processing
174 void *qthread(void *p)
175 {
176 DNSDistributor *D=static_cast<DNSDistributor *>(p);
177
178 DNSPacket *P;
179
180 DNSPacket question;
181 DNSPacket cached;
182
183 int &numreceived=*S.getPointer("udp-queries");
184 int &numanswered=*S.getPointer("udp-answers");
185 numreceived=-1;
186 int diff;
187
188 for(;;) {
189 if(!((numreceived++)%50)) { // maintenance tasks
190 S.set("latency",(int)avg_latency);
191 int qcount, acount;
192 D->getQueueSizes(qcount, acount);
193 S.set("qsize-q",qcount);
194 }
195
196 if(!(P=N->receive(&question))) { // receive a packet inline
197 continue; // packet was broken, try again
198 }
199
200
201 S.ringAccount("queries", P->qdomain+"/"+P->qtype.getName());
202 S.ringAccount("remotes",P->getRemote());
203
204 if(PC.get(P,&cached)) { // short circuit - does the PacketCache recognize this question?
205 cached.setRemote((struct sockaddr *)(P->remote),P->d_socklen); // inlined
206 cached.setSocket(P->getSocket()); // inlined
207 cached.spoofID(P->d.id); // inlined
208 cached.d.rd=P->d.rd; // copy in recursion desired bit
209 cached.commitD(); // commit d to the packet inlined
210
211 N->send(&cached); // answer it then inlined
212 diff=P->d_dt.udiff();
213 avg_latency=(int)(0.999*avg_latency+0.001*diff); // 'EWMA'
214
215 numanswered++;
216 continue;
217 }
218
219 D->question(P, &sendout); // otherwise, give to the distributor
220 }
221 return 0;
222 }
223
224
225 void mainthread()
226 {
227 Utility::srandom(time(0));
228
229 int newgid=0;
230 if(!arg()["setgid"].empty())
231 newgid=Utility::makeGidNumeric(arg()["setgid"]);
232 int newuid=0;
233 if(!arg()["setuid"].empty())
234 newuid=Utility::makeUidNumeric(arg()["setuid"]);
235 if(!arg()["chroot"].empty()) {
236 if(chroot(arg()["chroot"].c_str())<0) {
237 L<<Logger::Error<<"Unable to chroot: "<<strerror(errno)<<", exiting"<<endl;
238 exit(1);
239 }
240 else
241 L<<Logger::Error<<"Chrooted to '"<<arg()["chroot"]<<"'"<<endl;
242 }
243 Utility::dropPrivs(newuid, newgid);
244
245 if(arg().mustDo("recursor")){
246 DP=new DNSProxy(arg()["recursor"]);
247 DP->onlyFrom(arg()["allow-recursion"]);
248 DP->go();
249 }
250 // NOW SAFE TO CREATE THREADS!
251 dl->go();
252
253
254
255
256 pthread_t qtid;
257 StatWebServer sws;
258
259 if(arg()["webserver"]!="no")
260 sws.go();
261
262 if(arg().mustDo("slave") || arg().mustDo("master"))
263 Communicator.go();
264
265 if(TN)
266 TN->go(); // tcp nameserver launch
267
268 // fork(); (this worked :-))
269 for(int n=0;n<arg().asNum("receiver-threads");++n) {
270 DNSDistributor *D= new DNSDistributor(arg().asNum("distributor-threads")); // the big dispatcher!
271 pthread_create(&qtid,0,qthread,static_cast<void *>(D)); // receives packets
272 }
273
274 void *p;
275 pthread_join(qtid, &p);
276
277 L<<Logger::Error<<"Mainthread exiting - should never happen"<<endl;
278 }
279
280
281
282