]>
Commit | Line | Data |
---|---|---|
12c86877 BH |
1 | /* |
2 | PowerDNS Versatile Database Driven Nameserver | |
bf6a52bf | 3 | Copyright (C) 2002 - 2011 PowerDNS.COM BV |
12c86877 BH |
4 | |
5 | This program is free software; you can redistribute it and/or modify | |
22dc646a BH |
6 | it under the terms of the GNU General Public License version 2 |
7 | as published by the Free Software Foundation | |
ea44d9d3 | 8 | |
12c86877 BH |
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 | |
06bd9ccf | 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
12c86877 | 18 | */ |
e8d78143 | 19 | #include "packetcache.hh" |
da44c9ea | 20 | |
12c86877 BH |
21 | #include <cstdio> |
22 | #include <signal.h> | |
23 | #include <cstring> | |
24 | #include <cstdlib> | |
25 | #include <sys/types.h> | |
26 | #include <sys/socket.h> | |
27 | #include <netinet/in.h> | |
28 | #include <arpa/inet.h> | |
29 | #include <iostream> | |
30 | #include <string> | |
31 | #include <sys/stat.h> | |
32 | #include <unistd.h> | |
33 | #include <sys/time.h> | |
34 | #include <sys/types.h> | |
35 | #include <sys/wait.h> | |
36 | #include <errno.h> | |
37 | #include <pthread.h> | |
38 | #include <unistd.h> | |
39 | #include <sys/mman.h> | |
40 | #include <fcntl.h> | |
41 | #include <fstream> | |
040712e0 | 42 | #include <boost/algorithm/string.hpp> |
12c86877 BH |
43 | |
44 | #include "config.h" | |
45 | #include "dns.hh" | |
46 | #include "dnsbackend.hh" | |
47 | #include "ueberbackend.hh" | |
48 | #include "dnspacket.hh" | |
49 | #include "nameserver.hh" | |
50 | #include "distributor.hh" | |
51 | #include "logger.hh" | |
52 | #include "arguments.hh" | |
53 | #include "packethandler.hh" | |
54 | #include "statbag.hh" | |
55 | #include "tcpreceiver.hh" | |
12c86877 BH |
56 | #include "ws.hh" |
57 | #include "misc.hh" | |
58 | #include "dynlistener.hh" | |
59 | #include "dynhandler.hh" | |
60 | #include "communicator.hh" | |
61 | #include "dnsproxy.hh" | |
731f58b8 | 62 | #include "utility.hh" |
12c86877 | 63 | #include "common_startup.hh" |
02116dff | 64 | #include "dnsrecords.hh" |
12c86877 | 65 | |
040712e0 | 66 | |
12c86877 BH |
67 | time_t s_starttime; |
68 | ||
69 | string s_programname="pdns"; // used in packethandler.cc | |
70 | ||
c4ac5865 | 71 | const char *funnytext= |
12c86877 BH |
72 | "*****************************************************************************\n"\ |
73 | "Ok, you just ran pdns_server through 'strings' hoping to find funny messages.\n"\ | |
74 | "Well, you found one. \n"\ | |
75 | "Two ions are flying through their particle accelerator, says the one to the\n" | |
76 | "other 'I think I've lost an electron!' \n"\ | |
77 | "So the other one says, 'Are you sure?'. 'YEAH! I'M POSITIVE!'\n"\ | |
78 | " the pdns crew - pdns@powerdns.com\n" | |
79 | "*****************************************************************************\n"; | |
80 | ||
81 | ||
82 | // start (sys)logging | |
83 | ||
84 | /** \var Logger L | |
85 | \brief All logging is done via L, a Logger instance | |
86 | */ | |
87 | ||
88 | ||
89 | /** | |
90 | \file receiver.cc | |
91 | \brief The main loop of powerdns | |
92 | ||
93 | This file is where it all happens - main is here, as are the two pivotal threads qthread() and athread() | |
94 | */ | |
95 | ||
96 | void daemonize(void) | |
97 | { | |
98 | if(fork()) | |
99 | exit(0); // bye bye | |
100 | ||
101 | setsid(); | |
102 | ||
dd8b6bd1 | 103 | int i=open("/dev/null",O_RDWR); /* open stdin */ |
11a2091b BH |
104 | if(i < 0) |
105 | L<<Logger::Critical<<"Unable to open /dev/null: "<<stringerror()<<endl; | |
106 | else { | |
107 | dup2(i,0); /* stdin */ | |
108 | dup2(i,1); /* stderr */ | |
109 | dup2(i,2); /* stderr */ | |
110 | close(i); | |
111 | } | |
12c86877 BH |
112 | } |
113 | ||
12c86877 | 114 | static int cpid; |
12c86877 BH |
115 | static void takedown(int i) |
116 | { | |
117 | if(cpid) { | |
118 | L<<Logger::Error<<"Guardian is killed, taking down children with us"<<endl; | |
119 | kill(cpid,SIGKILL); | |
93d8ebf9 | 120 | exit(0); |
12c86877 BH |
121 | } |
122 | } | |
123 | ||
124 | static void writePid(void) | |
125 | { | |
e8d78143 | 126 | string fname=::arg()["socket-dir"]+"/"+s_programname+".pid"; |
12c86877 BH |
127 | ofstream of(fname.c_str()); |
128 | if(of) | |
129 | of<<getpid()<<endl; | |
130 | else | |
131 | L<<Logger::Error<<"Requested to write pid for "<<getpid()<<" to "<<fname<<" failed: "<<strerror(errno)<<endl; | |
132 | } | |
133 | ||
aced0e6c BH |
134 | int g_fd1[2], g_fd2[2]; |
135 | FILE *g_fp; | |
136 | pthread_mutex_t g_guardian_lock = PTHREAD_MUTEX_INITIALIZER; | |
12c86877 | 137 | |
64bcb6be RA |
138 | // The next two methods are not in dynhandler.cc because they use a few items declared in this file. |
139 | static string DLCycleHandler(const vector<string>&parts, pid_t ppid) | |
140 | { | |
141 | kill(cpid, SIGKILL); // why? | |
142 | kill(cpid, SIGKILL); // why? | |
143 | sleep(1); | |
144 | return "ok"; | |
145 | } | |
146 | ||
12c86877 BH |
147 | static string DLRestHandler(const vector<string>&parts, pid_t ppid) |
148 | { | |
149 | string line; | |
150 | ||
151 | for(vector<string>::const_iterator i=parts.begin();i!=parts.end();++i) { | |
152 | if(i!=parts.begin()) | |
153 | line.append(1,' '); | |
154 | line.append(*i); | |
155 | } | |
156 | line.append(1,'\n'); | |
157 | ||
aced0e6c BH |
158 | Lock l(&g_guardian_lock); |
159 | ||
160 | try { | |
161 | writen2(g_fd1[1],line.c_str(),line.size()+1); | |
162 | } | |
163 | catch(AhuException &ae) { | |
164 | return "Error communicating with instance: "+ae.reason; | |
165 | } | |
12c86877 | 166 | char mesg[512]; |
20ca8e7d | 167 | string response; |
aced0e6c | 168 | while(fgets(mesg,sizeof(mesg),g_fp)) { |
20ca8e7d BH |
169 | if(*mesg=='\n') |
170 | break; | |
171 | response+=mesg; | |
172 | } | |
040712e0 | 173 | boost::trim_right(response); |
20ca8e7d | 174 | return response; |
12c86877 BH |
175 | } |
176 | ||
64bcb6be | 177 | |
12c86877 BH |
178 | |
179 | static int guardian(int argc, char **argv) | |
180 | { | |
181 | if(isGuarded(argv)) | |
182 | return 0; | |
183 | ||
184 | int infd=0, outfd=1; | |
185 | ||
186 | DynListener dlg(s_programname); | |
3c90953e PD |
187 | dlg.registerFunc("QUIT",&DLQuitHandler, "quit daemon"); |
188 | dlg.registerFunc("CYCLE",&DLCycleHandler, "restart instance"); | |
189 | dlg.registerFunc("PING",&DLPingHandler, "ping guardian"); | |
190 | dlg.registerFunc("STATUS",&DLStatusHandler, "get instance status from guardian"); | |
12c86877 BH |
191 | dlg.registerRestFunc(&DLRestHandler); |
192 | dlg.go(); | |
193 | string progname=argv[0]; | |
194 | ||
195 | bool first=true; | |
196 | cpid=0; | |
197 | ||
aced0e6c BH |
198 | pthread_mutex_lock(&g_guardian_lock); |
199 | ||
12c86877 BH |
200 | for(;;) { |
201 | int pid; | |
202 | setStatus("Launching child"); | |
aced0e6c BH |
203 | |
204 | if(pipe(g_fd1)<0 || pipe(g_fd2)<0) { | |
12c86877 BH |
205 | L<<Logger::Critical<<"Unable to open pipe for coprocess: "<<strerror(errno)<<endl; |
206 | exit(1); | |
207 | } | |
208 | ||
aced0e6c BH |
209 | if(!(g_fp=fdopen(g_fd2[0],"r"))) { |
210 | L<<Logger::Critical<<"Unable to associate a file pointer with pipe: "<<stringerror()<<endl; | |
211 | exit(1); | |
212 | } | |
213 | setbuf(g_fp,0); // no buffering please, confuses select | |
214 | ||
12c86877 BH |
215 | if(!(pid=fork())) { // child |
216 | signal(SIGTERM, SIG_DFL); | |
217 | ||
218 | signal(SIGHUP, SIG_DFL); | |
219 | signal(SIGUSR1, SIG_DFL); | |
220 | signal(SIGUSR2, SIG_DFL); | |
221 | ||
222 | char **const newargv=new char*[argc+2]; | |
223 | int n; | |
224 | ||
e8d78143 | 225 | if(::arg()["config-name"]!="") { |
4957a608 BH |
226 | progname+="-"+::arg()["config-name"]; |
227 | L<<Logger::Error<<"Virtual configuration name: "<<::arg()["config-name"]<<endl; | |
12c86877 BH |
228 | } |
229 | ||
230 | newargv[0]=strdup(const_cast<char *>((progname+"-instance").c_str())); | |
231 | for(n=1;n<argc;n++) { | |
4957a608 | 232 | newargv[n]=argv[n]; |
12c86877 BH |
233 | } |
234 | newargv[n]=0; | |
235 | ||
236 | L<<Logger::Error<<"Guardian is launching an instance"<<endl; | |
aced0e6c BH |
237 | close(g_fd1[1]); |
238 | fclose(g_fp); // this closes g_fd2[0] for us | |
12c86877 | 239 | |
aced0e6c | 240 | if(g_fd1[0]!= infd) { |
4957a608 BH |
241 | dup2(g_fd1[0], infd); |
242 | close(g_fd1[0]); | |
12c86877 BH |
243 | } |
244 | ||
aced0e6c | 245 | if(g_fd2[1]!= outfd) { |
4957a608 BH |
246 | dup2(g_fd2[1], outfd); |
247 | close(g_fd2[1]); | |
12c86877 | 248 | } |
c1663439 | 249 | if(execvp(argv[0], newargv)<0) { |
4957a608 BH |
250 | L<<Logger::Error<<"Unable to execvp '"<<argv[0]<<"': "<<strerror(errno)<<endl; |
251 | char **p=newargv; | |
252 | while(*p) | |
253 | L<<Logger::Error<<*p++<<endl; | |
12c86877 | 254 | |
4957a608 | 255 | exit(1); |
12c86877 | 256 | } |
c1663439 | 257 | L<<Logger::Error<<"execvp returned!!"<<endl; |
12c86877 BH |
258 | // never reached |
259 | } | |
260 | else if(pid>0) { // parent | |
aced0e6c BH |
261 | close(g_fd1[0]); |
262 | close(g_fd2[1]); | |
12c86877 BH |
263 | |
264 | if(first) { | |
4957a608 BH |
265 | first=false; |
266 | signal(SIGTERM, takedown); | |
12c86877 | 267 | |
4957a608 BH |
268 | signal(SIGHUP, SIG_IGN); |
269 | signal(SIGUSR1, SIG_IGN); | |
270 | signal(SIGUSR2, SIG_IGN); | |
12c86877 | 271 | |
4957a608 | 272 | writePid(); |
12c86877 | 273 | } |
aced0e6c | 274 | pthread_mutex_unlock(&g_guardian_lock); |
12c86877 BH |
275 | int status; |
276 | cpid=pid; | |
277 | for(;;) { | |
4957a608 BH |
278 | int ret=waitpid(pid,&status,WNOHANG); |
279 | ||
280 | if(ret<0) { | |
281 | L<<Logger::Error<<"In guardian loop, waitpid returned error: "<<strerror(errno)<<endl; | |
282 | L<<Logger::Error<<"Dying"<<endl; | |
283 | exit(1); | |
284 | } | |
285 | else if(ret) // something exited | |
286 | break; | |
287 | else { // child is alive | |
288 | // execute some kind of ping here | |
289 | if(DLQuitPlease()) | |
290 | takedown(1); // needs a parameter.. | |
291 | setStatus("Child running on pid "+itoa(pid)); | |
292 | sleep(1); | |
293 | } | |
12c86877 | 294 | } |
aced0e6c BH |
295 | |
296 | pthread_mutex_lock(&g_guardian_lock); | |
297 | close(g_fd1[1]); | |
298 | fclose(g_fp); | |
299 | g_fp=0; | |
12c86877 BH |
300 | |
301 | if(WIFEXITED(status)) { | |
4957a608 BH |
302 | int ret=WEXITSTATUS(status); |
303 | ||
304 | if(ret==99) { | |
305 | L<<Logger::Error<<"Child requested a stop, exiting"<<endl; | |
306 | exit(1); | |
307 | } | |
308 | setStatus("Child died with code "+itoa(ret)); | |
309 | L<<Logger::Error<<"Our pdns instance exited with code "<<ret<<endl; | |
310 | L<<Logger::Error<<"Respawning"<<endl; | |
311 | ||
312 | sleep(1); | |
313 | continue; | |
12c86877 BH |
314 | } |
315 | if(WIFSIGNALED(status)) { | |
4957a608 BH |
316 | int sig=WTERMSIG(status); |
317 | setStatus("Child died because of signal "+itoa(sig)); | |
318 | L<<Logger::Error<<"Our pdns instance ("<<pid<<") exited after signal "<<sig<<endl; | |
12c86877 | 319 | #ifdef WCOREDUMP |
4957a608 BH |
320 | if(WCOREDUMP(status)) |
321 | L<<Logger::Error<<"Dumped core"<<endl; | |
12c86877 BH |
322 | #endif |
323 | ||
4957a608 BH |
324 | L<<Logger::Error<<"Respawning"<<endl; |
325 | sleep(1); | |
326 | continue; | |
12c86877 BH |
327 | } |
328 | L<<Logger::Error<<"No clue what happened! Respawning"<<endl; | |
329 | } | |
330 | else { | |
331 | L<<Logger::Error<<"Unable to fork: "<<strerror(errno)<<endl; | |
332 | exit(1); | |
333 | } | |
334 | } | |
335 | } | |
336 | ||
337 | static void UNIX_declareArguments() | |
338 | { | |
65efcdbc | 339 | ::arg().set("config-dir","Location of configuration directory (pdns.conf)")=SYSCONFDIR; |
e8d78143 BH |
340 | ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")=""; |
341 | ::arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR; | |
342 | ::arg().set("module-dir","Default directory for modules")=LIBDIR; | |
343 | ::arg().set("chroot","If set, chroot to this directory for more security")=""; | |
344 | ::arg().set("logging-facility","Log under a specific facility")=""; | |
345 | ::arg().set("daemon","Operate as a daemon")="no"; | |
12c86877 BH |
346 | |
347 | } | |
348 | ||
349 | static void loadModules() | |
350 | { | |
e8d78143 | 351 | if(!::arg()["load-modules"].empty()) { |
12c86877 BH |
352 | vector<string>modules; |
353 | ||
e8d78143 | 354 | stringtok(modules,::arg()["load-modules"],","); |
12c86877 BH |
355 | |
356 | for(vector<string>::const_iterator i=modules.begin();i!=modules.end();++i) { | |
357 | bool res; | |
358 | const string &module=*i; | |
359 | ||
360 | if(module.find(".")==string::npos) | |
4957a608 | 361 | res=UeberBackend::loadmodule(::arg()["module-dir"]+"/lib"+module+"backend.so"); |
12c86877 | 362 | else if(module[0]=='/' || (module[0]=='.' && module[1]=='/') || (module[0]=='.' && module[1]=='.')) // absolute or current path |
4957a608 | 363 | res=UeberBackend::loadmodule(module); |
12c86877 | 364 | else |
4957a608 | 365 | res=UeberBackend::loadmodule(::arg()["module-dir"]+"/"+module); |
12c86877 BH |
366 | |
367 | if(res==false) { | |
4957a608 BH |
368 | L<<Logger::Error<<"receiver unable to load module "<<module<<endl; |
369 | exit(1); | |
12c86877 BH |
370 | } |
371 | } | |
372 | } | |
373 | } | |
374 | ||
30ea693c | 375 | |
12c86877 BH |
376 | |
377 | #ifdef __linux__ | |
378 | #include <execinfo.h> | |
379 | static void tbhandler(int num) | |
380 | { | |
381 | L<<Logger::Critical<<"Got a signal "<<num<<", attempting to print trace: "<<endl; | |
382 | void *array[20]; //only care about last 17 functions (3 taken with tracing support) | |
383 | size_t size; | |
384 | char **strings; | |
385 | size_t i; | |
386 | ||
387 | size = backtrace (array, 20); | |
388 | strings = backtrace_symbols (array, size); //Need -rdynamic gcc (linker) flag for this to work | |
389 | ||
390 | for (i = 0; i < size; i++) //skip useless functions | |
391 | L<<Logger::Error<<strings[i]<<endl; | |
392 | ||
393 | ||
394 | signal(SIGABRT, SIG_DFL); | |
395 | abort();//hopefully will give core | |
396 | ||
397 | } | |
398 | #endif | |
399 | ||
400 | //! The main function of pdns, the pdns process | |
401 | int main(int argc, char **argv) | |
402 | { | |
02116dff BH |
403 | reportAllTypes(); // init MOADNSParser |
404 | ||
12c86877 BH |
405 | s_programname="pdns"; |
406 | s_starttime=time(0); | |
407 | ||
408 | #ifdef __linux__ | |
409 | signal(SIGSEGV,tbhandler); | |
410 | signal(SIGFPE,tbhandler); | |
411 | signal(SIGABRT,tbhandler); | |
412 | signal(SIGILL,tbhandler); | |
413 | #endif | |
414 | ||
35b9a6ff PD |
415 | #if __GNUC__ >= 3 |
416 | std::ios_base::sync_with_stdio(false); | |
417 | #endif | |
12c86877 BH |
418 | |
419 | L.toConsole(Logger::Warning); | |
420 | try { | |
421 | declareArguments(); | |
422 | UNIX_declareArguments(); | |
c4db07b7 | 423 | |
e8d78143 | 424 | ::arg().laxParse(argc,argv); // do a lax parse |
12c86877 | 425 | |
c4db07b7 | 426 | if(::arg().mustDo("version")) { |
30ea693c PD |
427 | cerr<<"Version: "VERSION", compiled on "<<__DATE__", "__TIME__; |
428 | #ifdef __GNUC__ | |
429 | cerr<<" with gcc version "<<__VERSION__; | |
430 | #endif | |
431 | cout<<endl; | |
c4db07b7 PD |
432 | exit(99); |
433 | } | |
434 | ||
e8d78143 BH |
435 | if(::arg()["config-name"]!="") |
436 | s_programname+="-"+::arg()["config-name"]; | |
12c86877 BH |
437 | |
438 | (void)theL(s_programname); | |
439 | ||
e8d78143 | 440 | string configname=::arg()["config-dir"]+"/"+s_programname+".conf"; |
12c86877 BH |
441 | cleanSlashes(configname); |
442 | ||
e8d78143 BH |
443 | if(!::arg().mustDo("config") && !::arg().mustDo("no-config")) // "config" == print a configuration file |
444 | ::arg().laxFile(configname.c_str()); | |
12c86877 | 445 | |
e8d78143 BH |
446 | ::arg().laxParse(argc,argv); // reparse so the commandline still wins |
447 | if(!::arg()["logging-facility"].empty()) { | |
f8499e52 BH |
448 | int val=logFacilityToLOG(::arg().asNum("logging-facility") ); |
449 | if(val >= 0) | |
450 | theL().setFacility(val); | |
6e2514e4 | 451 | else |
4957a608 | 452 | L<<Logger::Error<<"Unknown logging facility "<<::arg().asNum("logging-facility") <<endl; |
12c86877 BH |
453 | } |
454 | ||
e8d78143 BH |
455 | L.setLoglevel((Logger::Urgency)(::arg().asNum("loglevel"))); |
456 | L.toConsole((Logger::Urgency)(::arg().asNum("loglevel"))); | |
12c86877 | 457 | |
e8d78143 BH |
458 | if(::arg().mustDo("help") || ::arg().mustDo("config")) { |
459 | ::arg().set("daemon")="no"; | |
460 | ::arg().set("guardian")="no"; | |
12c86877 BH |
461 | } |
462 | ||
e8d78143 BH |
463 | if(::arg().mustDo("guardian") && !isGuarded(argv)) { |
464 | if(::arg().mustDo("daemon")) { | |
4957a608 BH |
465 | L.toConsole(Logger::Critical); |
466 | daemonize(); | |
12c86877 BH |
467 | } |
468 | guardian(argc, argv); | |
469 | // never get here, guardian will reinvoke process | |
470 | cerr<<"Um, we did get here!"<<endl; | |
471 | } | |
45fdd612 | 472 | |
12c86877 BH |
473 | |
474 | // we really need to do work - either standalone or as an instance | |
5488e86b PD |
475 | |
476 | #ifdef __linux__ | |
477 | if(!::arg().mustDo("traceback-handler")) { | |
478 | L<<Logger::Warning<<"Disabling traceback handler"<<endl; | |
479 | signal(SIGSEGV,SIG_DFL); | |
480 | signal(SIGFPE,SIG_DFL); | |
481 | signal(SIGABRT,SIG_DFL); | |
482 | signal(SIGILL,SIG_DFL); | |
483 | } | |
484 | #endif | |
485 | ||
a28a204a BH |
486 | seedRandom(::arg()["entropy-source"]); |
487 | ||
12c86877 | 488 | loadModules(); |
e8d78143 | 489 | BackendMakers().launch(::arg()["launch"]); // vrooooom! |
f4137d84 | 490 | |
e8d78143 | 491 | if(!::arg().getCommands().empty()) { |
49daa3cd BH |
492 | cerr<<"Fatal: non-option on the command line, perhaps a '--setting=123' statement missed the '='?"<<endl; |
493 | exit(99); | |
494 | } | |
f4137d84 | 495 | |
e8d78143 | 496 | if(::arg().mustDo("help")) { |
12c86877 | 497 | cerr<<"syntax:"<<endl<<endl; |
e8d78143 | 498 | cerr<<::arg().helpstring(::arg()["help"])<<endl; |
12c86877 BH |
499 | exit(99); |
500 | } | |
501 | ||
e8d78143 BH |
502 | if(::arg().mustDo("config")) { |
503 | cout<<::arg().configstring()<<endl; | |
12c86877 BH |
504 | exit(99); |
505 | } | |
506 | ||
e8d78143 | 507 | if(::arg().mustDo("list-modules")) { |
12c86877 BH |
508 | vector<string>modules=BackendMakers().getModules(); |
509 | cerr<<"Modules available:"<<endl; | |
510 | for(vector<string>::const_iterator i=modules.begin();i!=modules.end();++i) | |
4957a608 | 511 | cout<<*i<<endl; |
12c86877 BH |
512 | |
513 | exit(99); | |
514 | } | |
da44c9ea | 515 | |
203c0755 BH |
516 | if(::arg().mustDo("fancy-records")) { |
517 | reportFancyTypes(); | |
518 | } | |
519 | ||
e8d78143 | 520 | if(!::arg().asNum("local-port")) { |
da44c9ea BH |
521 | L<<Logger::Error<<"Unable to launch, binding to no port or port 0 makes no sense"<<endl; |
522 | exit(99); // this isn't going to fix itself either | |
523 | } | |
12c86877 BH |
524 | if(!BackendMakers().numLauncheable()) { |
525 | L<<Logger::Error<<"Unable to launch, no backends configured for querying"<<endl; | |
da44c9ea | 526 | exit(99); // this isn't going to fix itself either |
12c86877 | 527 | } |
e8d78143 | 528 | if(::arg().mustDo("daemon")) { |
12c86877 BH |
529 | L.toConsole(Logger::None); |
530 | if(!isGuarded(argv)) | |
4957a608 | 531 | daemonize(); |
12c86877 BH |
532 | } |
533 | ||
7f7b8d55 BH |
534 | if(::arg()["server-id"].empty()) { |
535 | char tmp[128]; | |
536 | gethostname(tmp, sizeof(tmp)-1); | |
537 | ::arg().set("server-id")=tmp; | |
538 | } | |
539 | ||
12c86877 BH |
540 | if(isGuarded(argv)) { |
541 | L<<Logger::Warning<<"This is a guarded instance of pdns"<<endl; | |
542 | dl=new DynListener; // listens on stdin | |
543 | } | |
544 | else { | |
545 | L<<Logger::Warning<<"This is a standalone pdns"<<endl; | |
546 | ||
e8d78143 | 547 | if(::arg().mustDo("control-console")) |
4957a608 | 548 | dl=new DynListener(); |
12c86877 | 549 | else |
4957a608 | 550 | dl=new DynListener(s_programname); |
12c86877 BH |
551 | |
552 | writePid(); | |
553 | } | |
3c90953e PD |
554 | DynListener::registerFunc("SHOW",&DLShowHandler, "show a specific statistic or * to get a list", "<statistic>"); |
555 | DynListener::registerFunc("RPING",&DLPingHandler, "ping instance"); | |
556 | DynListener::registerFunc("QUIT",&DLRQuitHandler, "quit daemon"); | |
557 | DynListener::registerFunc("UPTIME",&DLUptimeHandler, "get instance uptime"); | |
558 | DynListener::registerFunc("NOTIFY-HOST",&DLNotifyHostHandler, "notify host for specific domain", "<domain> <host>"); | |
559 | DynListener::registerFunc("NOTIFY",&DLNotifyHandler, "queue a notification", "<domain>"); | |
560 | DynListener::registerFunc("RELOAD",&DLReloadHandler, "reload all zones"); | |
561 | DynListener::registerFunc("REDISCOVER",&DLRediscoverHandler, "discover any new zones"); | |
562 | DynListener::registerFunc("VERSION",&DLVersionHandler, "get instance version"); | |
563 | DynListener::registerFunc("PURGE",&DLPurgeHandler, "purge entries from packet cache", "[<record>]"); | |
564 | DynListener::registerFunc("CCOUNTS",&DLCCHandler, "get cache statistics"); | |
565 | DynListener::registerFunc("SET",&DLSettingsHandler, "set config variables", "<var> <value>"); | |
566 | DynListener::registerFunc("RETRIEVE",&DLNotifyRetrieveHandler, "retrieve slave domain", "<domain>"); | |
64bcb6be | 567 | DynListener::registerFunc("CURRENT-CONFIG",&DLCurrentConfigHandler, "Retrieve the current configuration"); |
040712e0 BH |
568 | |
569 | if(!::arg()["tcp-control-address"].empty()) { | |
570 | DynListener* dlTCP=new DynListener(ComboAddress(::arg()["tcp-control-address"], ::arg().asNum("tcp-control-port"))); | |
571 | dlTCP->go(); | |
572 | } | |
12c86877 | 573 | |
12c86877 | 574 | // reparse, with error checking |
e8d78143 BH |
575 | if(!::arg().mustDo("no-config")) |
576 | ::arg().file(configname.c_str()); | |
577 | ::arg().parse(argc,argv); | |
12c86877 BH |
578 | UeberBackend::go(); |
579 | N=new UDPNameserver; // this fails when we are not root, throws exception | |
580 | ||
e8d78143 | 581 | if(!::arg().mustDo("disable-tcp")) |
12c86877 BH |
582 | TN=new TCPNameserver; |
583 | } | |
584 | catch(const ArgException &A) { | |
585 | L<<Logger::Error<<"Fatal error: "<<A.reason<<endl; | |
586 | exit(1); | |
587 | } | |
588 | ||
589 | declareStats(); | |
590 | DLOG(L<<Logger::Warning<<"Verbose logging in effect"<<endl); | |
30ea693c PD |
591 | |
592 | L<<Logger::Warning<<"PowerDNS "<<VERSION<<" (C) 2001-2013 PowerDNS.COM BV ("<<__DATE__", "__TIME__; | |
593 | #ifdef __GNUC__ | |
594 | L<<", gcc "__VERSION__; | |
595 | #endif // add other compilers here | |
596 | L<<") starting up"<<endl; | |
597 | ||
598 | L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. " | |
599 | "This is free software, and you are welcome to redistribute it " | |
600 | "according to the terms of the GPL version 2."<<endl; | |
12c86877 BH |
601 | |
602 | ||
603 | try { | |
604 | ||
605 | mainthread(); | |
606 | } | |
607 | catch(AhuException &AE) { | |
e8d78143 | 608 | if(!::arg().mustDo("daemon")) |
12c86877 BH |
609 | cerr<<"Exiting because: "<<AE.reason<<endl; |
610 | L<<Logger::Error<<"Exiting because: "<<AE.reason<<endl; | |
611 | } | |
adc10f99 | 612 | catch(std::exception &e) { |
e8d78143 | 613 | if(!::arg().mustDo("daemon")) |
12c86877 BH |
614 | cerr<<"Exiting because of STL error: "<<e.what()<<endl; |
615 | L<<Logger::Error<<"Exiting because of STL error: "<<e.what()<<endl; | |
616 | } | |
617 | catch(...) { | |
618 | cerr<<"Uncaught exception of unknown type - sorry"<<endl; | |
619 | } | |
620 | ||
621 | exit(1); | |
622 | ||
623 | } | |
624 | ||
625 |