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