]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/receiver.cc
Correct doc for ecs-add-for default
[thirdparty/pdns.git] / pdns / receiver.cc
CommitLineData
12c86877 1/*
6edbf68a
PL
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 */
870a0fe4
AT
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
e8d78143 25#include "packetcache.hh"
da44c9ea 26
12c86877
BH
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>
040712e0 48#include <boost/algorithm/string.hpp>
d4f29089
KM
49#ifdef HAVE_LIBSODIUM
50#include <sodium.h>
51#endif
7581a35b 52#include "opensslsigners.hh"
12c86877 53
12c86877
BH
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"
12c86877
BH
65#include "misc.hh"
66#include "dynlistener.hh"
67#include "dynhandler.hh"
68#include "communicator.hh"
69#include "dnsproxy.hh"
731f58b8 70#include "utility.hh"
12c86877 71#include "common_startup.hh"
02116dff 72#include "dnsrecords.hh"
ba1a571d 73#include "version.hh"
12c86877 74
8340b048
RG
75#ifdef HAVE_LUA_RECORDS
76#include "minicurl.hh"
77#endif /* HAVE_LUA_RECORDS */
78
12c86877
BH
79time_t s_starttime;
80
81string s_programname="pdns"; // used in packethandler.cc
82
c4ac5865 83const char *funnytext=
12c86877
BH
84"*****************************************************************************\n"\
85"Ok, you just ran pdns_server through 'strings' hoping to find funny messages.\n"\
86"Well, you found one. \n"\
87"Two ions are flying through their particle accelerator, says the one to the\n"
88"other 'I think I've lost an electron!' \n"\
89"So the other one says, 'Are you sure?'. 'YEAH! I'M POSITIVE!'\n"\
90" the pdns crew - pdns@powerdns.com\n"
91"*****************************************************************************\n";
92
93
94// start (sys)logging
95
12c86877
BH
96
97/**
98\file receiver.cc
99\brief The main loop of powerdns
100
101This file is where it all happens - main is here, as are the two pivotal threads qthread() and athread()
102*/
103
050e6877 104static void daemonize(void)
12c86877
BH
105{
106 if(fork())
107 exit(0); // bye bye
108
109 setsid();
110
dd8b6bd1 111 int i=open("/dev/null",O_RDWR); /* open stdin */
11a2091b 112 if(i < 0)
e6a9dde5 113 g_log<<Logger::Critical<<"Unable to open /dev/null: "<<stringerror()<<endl;
11a2091b
BH
114 else {
115 dup2(i,0); /* stdin */
116 dup2(i,1); /* stderr */
117 dup2(i,2); /* stderr */
118 close(i);
119 }
12c86877
BH
120}
121
12c86877 122static int cpid;
12c86877
BH
123static void takedown(int i)
124{
125 if(cpid) {
e6a9dde5 126 g_log<<Logger::Error<<"Guardian is killed, taking down children with us"<<endl;
882ca9d9
KM
127 kill(cpid,SIGKILL);
128 exit(0);
12c86877
BH
129 }
130}
131
132static void writePid(void)
133{
191f2e47 134 if(!::arg().mustDo("write-pid"))
135 return;
136
f0f3f0b0
PL
137 string fname=::arg()["socket-dir"];
138 if (::arg()["socket-dir"].empty()) {
139 if (::arg()["chroot"].empty())
2dfe5b32 140 fname = std::string(LOCALSTATEDIR) + "/pdns";
f0f3f0b0
PL
141 else
142 fname = ::arg()["chroot"] + "/";
143 } else if (!::arg()["socket-dir"].empty() && !::arg()["chroot"].empty()) {
144 fname = ::arg()["chroot"] + ::arg()["socket-dir"];
145 }
146
147 fname += + "/" + s_programname + ".pid";
12c86877
BH
148 ofstream of(fname.c_str());
149 if(of)
150 of<<getpid()<<endl;
151 else
04360367 152 g_log<<Logger::Error<<"Writing pid for "<<getpid()<<" to "<<fname<<" failed: "<<stringerror()<<endl;
12c86877
BH
153}
154
aced0e6c
BH
155int g_fd1[2], g_fd2[2];
156FILE *g_fp;
0ddde5fb 157std::mutex g_guardian_lock;
12c86877 158
64bcb6be
RA
159// The next two methods are not in dynhandler.cc because they use a few items declared in this file.
160static string DLCycleHandler(const vector<string>&parts, pid_t ppid)
161{
882ca9d9
KM
162 kill(cpid, SIGKILL); // why?
163 kill(cpid, SIGKILL); // why?
64bcb6be
RA
164 sleep(1);
165 return "ok";
166}
167
12c86877
BH
168static string DLRestHandler(const vector<string>&parts, pid_t ppid)
169{
170 string line;
171
172 for(vector<string>::const_iterator i=parts.begin();i!=parts.end();++i) {
173 if(i!=parts.begin())
174 line.append(1,' ');
175 line.append(*i);
176 }
177 line.append(1,'\n');
178
0ddde5fb 179 std::lock_guard<std::mutex> l(g_guardian_lock);
aced0e6c
BH
180
181 try {
182 writen2(g_fd1[1],line.c_str(),line.size()+1);
183 }
3f81d239 184 catch(PDNSException &ae) {
aced0e6c
BH
185 return "Error communicating with instance: "+ae.reason;
186 }
12c86877 187 char mesg[512];
20ca8e7d 188 string response;
aced0e6c 189 while(fgets(mesg,sizeof(mesg),g_fp)) {
188b28bd 190 if(*mesg=='\0')
20ca8e7d
BH
191 break;
192 response+=mesg;
193 }
040712e0 194 boost::trim_right(response);
20ca8e7d 195 return response;
12c86877
BH
196}
197
64bcb6be 198
12c86877
BH
199
200static int guardian(int argc, char **argv)
201{
202 if(isGuarded(argv))
203 return 0;
204
205 int infd=0, outfd=1;
206
207 DynListener dlg(s_programname);
3c90953e
PD
208 dlg.registerFunc("QUIT",&DLQuitHandler, "quit daemon");
209 dlg.registerFunc("CYCLE",&DLCycleHandler, "restart instance");
210 dlg.registerFunc("PING",&DLPingHandler, "ping guardian");
211 dlg.registerFunc("STATUS",&DLStatusHandler, "get instance status from guardian");
12c86877
BH
212 dlg.registerRestFunc(&DLRestHandler);
213 dlg.go();
214 string progname=argv[0];
215
216 bool first=true;
882ca9d9 217 cpid=0;
12c86877 218
0ddde5fb 219 g_guardian_lock.lock();
aced0e6c 220
12c86877
BH
221 for(;;) {
222 int pid;
223 setStatus("Launching child");
aced0e6c
BH
224
225 if(pipe(g_fd1)<0 || pipe(g_fd2)<0) {
04360367 226 g_log<<Logger::Critical<<"Unable to open pipe for coprocess: "<<stringerror()<<endl;
12c86877
BH
227 exit(1);
228 }
229
aced0e6c 230 if(!(g_fp=fdopen(g_fd2[0],"r"))) {
e6a9dde5 231 g_log<<Logger::Critical<<"Unable to associate a file pointer with pipe: "<<stringerror()<<endl;
aced0e6c
BH
232 exit(1);
233 }
234 setbuf(g_fp,0); // no buffering please, confuses select
235
12c86877 236 if(!(pid=fork())) { // child
882ca9d9
KM
237 signal(SIGTERM, SIG_DFL);
238
12c86877
BH
239 signal(SIGHUP, SIG_DFL);
240 signal(SIGUSR1, SIG_DFL);
241 signal(SIGUSR2, SIG_DFL);
242
243 char **const newargv=new char*[argc+2];
244 int n;
245
e8d78143 246 if(::arg()["config-name"]!="") {
4957a608 247 progname+="-"+::arg()["config-name"];
e6a9dde5 248 g_log<<Logger::Error<<"Virtual configuration name: "<<::arg()["config-name"]<<endl;
12c86877
BH
249 }
250
251 newargv[0]=strdup(const_cast<char *>((progname+"-instance").c_str()));
252 for(n=1;n<argc;n++) {
4957a608 253 newargv[n]=argv[n];
12c86877
BH
254 }
255 newargv[n]=0;
256
e6a9dde5 257 g_log<<Logger::Error<<"Guardian is launching an instance"<<endl;
aced0e6c
BH
258 close(g_fd1[1]);
259 fclose(g_fp); // this closes g_fd2[0] for us
12c86877 260
aced0e6c 261 if(g_fd1[0]!= infd) {
4957a608
BH
262 dup2(g_fd1[0], infd);
263 close(g_fd1[0]);
12c86877
BH
264 }
265
aced0e6c 266 if(g_fd2[1]!= outfd) {
4957a608
BH
267 dup2(g_fd2[1], outfd);
268 close(g_fd2[1]);
12c86877 269 }
c1663439 270 if(execvp(argv[0], newargv)<0) {
04360367 271 g_log<<Logger::Error<<"Unable to execvp '"<<argv[0]<<"': "<<stringerror()<<endl;
4957a608
BH
272 char **p=newargv;
273 while(*p)
e6a9dde5 274 g_log<<Logger::Error<<*p++<<endl;
12c86877 275
4957a608 276 exit(1);
12c86877 277 }
e6a9dde5 278 g_log<<Logger::Error<<"execvp returned!!"<<endl;
12c86877
BH
279 // never reached
280 }
281 else if(pid>0) { // parent
aced0e6c
BH
282 close(g_fd1[0]);
283 close(g_fd2[1]);
12c86877
BH
284
285 if(first) {
4957a608 286 first=false;
882ca9d9
KM
287 signal(SIGTERM, takedown);
288
4957a608
BH
289 signal(SIGHUP, SIG_IGN);
290 signal(SIGUSR1, SIG_IGN);
291 signal(SIGUSR2, SIG_IGN);
12c86877 292
4957a608 293 writePid();
12c86877 294 }
0ddde5fb 295 g_guardian_lock.unlock();
12c86877
BH
296 int status;
297 cpid=pid;
298 for(;;) {
4957a608
BH
299 int ret=waitpid(pid,&status,WNOHANG);
300
301 if(ret<0) {
04360367 302 g_log<<Logger::Error<<"In guardian loop, waitpid returned error: "<<stringerror()<<endl;
e6a9dde5 303 g_log<<Logger::Error<<"Dying"<<endl;
4957a608
BH
304 exit(1);
305 }
306 else if(ret) // something exited
307 break;
308 else { // child is alive
309 // execute some kind of ping here
310 if(DLQuitPlease())
311 takedown(1); // needs a parameter..
312 setStatus("Child running on pid "+itoa(pid));
313 sleep(1);
314 }
12c86877 315 }
aced0e6c 316
0ddde5fb 317 g_guardian_lock.lock();
aced0e6c
BH
318 close(g_fd1[1]);
319 fclose(g_fp);
320 g_fp=0;
12c86877
BH
321
322 if(WIFEXITED(status)) {
4957a608
BH
323 int ret=WEXITSTATUS(status);
324
325 if(ret==99) {
e6a9dde5 326 g_log<<Logger::Error<<"Child requested a stop, exiting"<<endl;
4957a608
BH
327 exit(1);
328 }
329 setStatus("Child died with code "+itoa(ret));
e6a9dde5 330 g_log<<Logger::Error<<"Our pdns instance exited with code "<<ret<<", respawning"<<endl;
4957a608 331
882ca9d9
KM
332 sleep(1);
333 continue;
12c86877
BH
334 }
335 if(WIFSIGNALED(status)) {
4957a608
BH
336 int sig=WTERMSIG(status);
337 setStatus("Child died because of signal "+itoa(sig));
e6a9dde5 338 g_log<<Logger::Error<<"Our pdns instance ("<<pid<<") exited after signal "<<sig<<endl;
12c86877 339#ifdef WCOREDUMP
4957a608 340 if(WCOREDUMP(status))
e6a9dde5 341 g_log<<Logger::Error<<"Dumped core"<<endl;
12c86877
BH
342#endif
343
e6a9dde5 344 g_log<<Logger::Error<<"Respawning"<<endl;
882ca9d9
KM
345 sleep(1);
346 continue;
12c86877 347 }
e6a9dde5 348 g_log<<Logger::Error<<"No clue what happened! Respawning"<<endl;
12c86877
BH
349 }
350 else {
04360367 351 g_log<<Logger::Error<<"Unable to fork: "<<stringerror()<<endl;
12c86877
BH
352 exit(1);
353 }
354 }
355}
356
331d3d27 357#if defined(__GLIBC__) && !defined(__UCLIBC__)
12c86877
BH
358#include <execinfo.h>
359static void tbhandler(int num)
360{
e6a9dde5 361 g_log<<Logger::Critical<<"Got a signal "<<num<<", attempting to print trace: "<<endl;
12c86877
BH
362 void *array[20]; //only care about last 17 functions (3 taken with tracing support)
363 size_t size;
364 char **strings;
365 size_t i;
366
367 size = backtrace (array, 20);
368 strings = backtrace_symbols (array, size); //Need -rdynamic gcc (linker) flag for this to work
369
370 for (i = 0; i < size; i++) //skip useless functions
e6a9dde5 371 g_log<<Logger::Error<<strings[i]<<endl;
12c86877
BH
372
373
374 signal(SIGABRT, SIG_DFL);
375 abort();//hopefully will give core
376
377}
378#endif
379
380//! The main function of pdns, the pdns process
381int main(int argc, char **argv)
ba1a571d 382{
3e135495 383 versionSetProduct(ProductAuthoritative);
02116dff
BH
384 reportAllTypes(); // init MOADNSParser
385
12c86877
BH
386 s_programname="pdns";
387 s_starttime=time(0);
388
331d3d27 389#if defined(__GLIBC__) && !defined(__UCLIBC__)
12c86877
BH
390 signal(SIGSEGV,tbhandler);
391 signal(SIGFPE,tbhandler);
392 signal(SIGABRT,tbhandler);
393 signal(SIGILL,tbhandler);
394#endif
395
35b9a6ff 396 std::ios_base::sync_with_stdio(false);
12c86877 397
e6a9dde5 398 g_log.toConsole(Logger::Warning);
12c86877
BH
399 try {
400 declareArguments();
c4db07b7 401
e8d78143 402 ::arg().laxParse(argc,argv); // do a lax parse
12c86877 403
c4db07b7 404 if(::arg().mustDo("version")) {
ba1a571d 405 showProductVersion();
3613a51c 406 showBuildConfiguration();
c4db07b7
PD
407 exit(99);
408 }
409
e8d78143
BH
410 if(::arg()["config-name"]!="")
411 s_programname+="-"+::arg()["config-name"];
12c86877 412
e6a9dde5 413 g_log.setName(s_programname);
12c86877 414
e8d78143 415 string configname=::arg()["config-dir"]+"/"+s_programname+".conf";
12c86877
BH
416 cleanSlashes(configname);
417
8c360f20 418 if(::arg()["config"] != "default" && !::arg().mustDo("no-config")) // "config" == print a configuration file
e8d78143 419 ::arg().laxFile(configname.c_str());
12c86877 420
e8d78143
BH
421 ::arg().laxParse(argc,argv); // reparse so the commandline still wins
422 if(!::arg()["logging-facility"].empty()) {
f8499e52
BH
423 int val=logFacilityToLOG(::arg().asNum("logging-facility") );
424 if(val >= 0)
e6a9dde5 425 g_log.setFacility(val);
6e2514e4 426 else
e6a9dde5 427 g_log<<Logger::Error<<"Unknown logging facility "<<::arg().asNum("logging-facility") <<endl;
12c86877
BH
428 }
429
e6a9dde5
PL
430 g_log.setLoglevel((Logger::Urgency)(::arg().asNum("loglevel")));
431 g_log.disableSyslog(::arg().mustDo("disable-syslog"));
432 g_log.setTimestamps(::arg().mustDo("log-timestamp"));
433 g_log.toConsole((Logger::Urgency)(::arg().asNum("loglevel")));
12c86877 434
e8d78143
BH
435 if(::arg().mustDo("help") || ::arg().mustDo("config")) {
436 ::arg().set("daemon")="no";
437 ::arg().set("guardian")="no";
12c86877
BH
438 }
439
e8d78143
BH
440 if(::arg().mustDo("guardian") && !isGuarded(argv)) {
441 if(::arg().mustDo("daemon")) {
e6a9dde5 442 g_log.toConsole(Logger::Critical);
4957a608 443 daemonize();
12c86877
BH
444 }
445 guardian(argc, argv);
446 // never get here, guardian will reinvoke process
447 cerr<<"Um, we did get here!"<<endl;
448 }
45fdd612 449
12c86877
BH
450
451 // we really need to do work - either standalone or as an instance
5488e86b 452
331d3d27 453#if defined(__GLIBC__) && !defined(__UCLIBC__)
5488e86b 454 if(!::arg().mustDo("traceback-handler")) {
e6a9dde5 455 g_log<<Logger::Warning<<"Disabling traceback handler"<<endl;
5488e86b
PD
456 signal(SIGSEGV,SIG_DFL);
457 signal(SIGFPE,SIG_DFL);
458 signal(SIGABRT,SIG_DFL);
459 signal(SIGILL,SIG_DFL);
460 }
461#endif
462
d4f29089
KM
463#ifdef HAVE_LIBSODIUM
464 if (sodium_init() == -1) {
465 cerr<<"Unable to initialize sodium crypto library"<<endl;
466 exit(99);
467 }
468#endif
7581a35b 469
7581a35b
KM
470 openssl_thread_setup();
471 openssl_seed();
e97cb679
AT
472 /* setup rng */
473 dns_random_init();
7581a35b 474
8340b048
RG
475#ifdef HAVE_LUA_RECORDS
476 MiniCurl::init();
477#endif /* HAVE_LUA_RECORDS */
478
d4168b30
CHB
479 if(!::arg()["load-modules"].empty()) {
480 vector<string> modules;
481
482 stringtok(modules,::arg()["load-modules"], ", ");
483 if (!UeberBackend::loadModules(modules, ::arg()["module-dir"])) {
484 exit(1);
485 }
486 }
487
e8d78143 488 BackendMakers().launch(::arg()["launch"]); // vrooooom!
f4137d84 489
e8d78143 490 if(!::arg().getCommands().empty()) {
94ea3c7b
PL
491 cerr<<"Fatal: non-option";
492 if (::arg().getCommands().size() > 1) {
493 cerr<<"s";
494 }
495 cerr<<" (";
496 bool first = true;
497 for (auto const c : ::arg().getCommands()) {
498 if (!first) {
499 cerr<<", ";
500 }
501 first = false;
502 cerr<<c;
503 }
504 cerr<<") on the command line, perhaps a '--setting=123' statement missed the '='?"<<endl;
49daa3cd
BH
505 exit(99);
506 }
f4137d84 507
e8d78143 508 if(::arg().mustDo("help")) {
ff5ba4f9
WA
509 cout<<"syntax:"<<endl<<endl;
510 cout<<::arg().helpstring(::arg()["help"])<<endl;
511 exit(0);
12c86877
BH
512 }
513
e8d78143 514 if(::arg().mustDo("config")) {
8864bdf6
KM
515 string config = ::arg()["config"];
516 if (config == "default") {
517 cout<<::arg().configstring(false, true);
518 } else if (config == "diff") {
519 cout<<::arg().configstring(true, false);
8c360f20
KM
520 } else if (config == "check") {
521 try {
522 if(!::arg().mustDo("no-config"))
523 ::arg().file(configname.c_str());
524 ::arg().parse(argc,argv);
525 exit(0);
526 }
527 catch(const ArgException &A) {
528 cerr<<"Fatal error: "<<A.reason<<endl;
529 exit(1);
530 }
8864bdf6
KM
531 } else {
532 cout<<::arg().configstring(true, true);
533 }
70463abb 534 exit(0);
12c86877
BH
535 }
536
e8d78143 537 if(::arg().mustDo("list-modules")) {
44ac5977 538 auto modules = BackendMakers().getModules();
539 cout<<"Modules available:"<<endl;
540 for(const auto& m : modules)
541 cout<< m <<endl;
12c86877 542
44ac5977 543 _exit(99);
12c86877 544 }
da44c9ea 545
e8d78143 546 if(!::arg().asNum("local-port")) {
e6a9dde5 547 g_log<<Logger::Error<<"Unable to launch, binding to no port or port 0 makes no sense"<<endl;
da44c9ea
BH
548 exit(99); // this isn't going to fix itself either
549 }
12c86877 550 if(!BackendMakers().numLauncheable()) {
e6a9dde5 551 g_log<<Logger::Error<<"Unable to launch, no backends configured for querying"<<endl;
da44c9ea 552 exit(99); // this isn't going to fix itself either
12c86877 553 }
e8d78143 554 if(::arg().mustDo("daemon")) {
e6a9dde5 555 g_log.toConsole(Logger::None);
12c86877 556 if(!isGuarded(argv))
4957a608 557 daemonize();
12c86877
BH
558 }
559
560 if(isGuarded(argv)) {
e6a9dde5 561 g_log<<Logger::Warning<<"This is a guarded instance of pdns"<<endl;
c2826d2e 562 dl=make_unique<DynListener>(); // listens on stdin
12c86877
BH
563 }
564 else {
e6a9dde5 565 g_log<<Logger::Warning<<"This is a standalone pdns"<<endl;
12c86877 566
e8d78143 567 if(::arg().mustDo("control-console"))
c2826d2e 568 dl=make_unique<DynListener>();
12c86877 569 else
c2826d2e 570 dl=std::unique_ptr<DynListener>(new DynListener(s_programname));
12c86877
BH
571
572 writePid();
573 }
3c90953e
PD
574 DynListener::registerFunc("SHOW",&DLShowHandler, "show a specific statistic or * to get a list", "<statistic>");
575 DynListener::registerFunc("RPING",&DLPingHandler, "ping instance");
576 DynListener::registerFunc("QUIT",&DLRQuitHandler, "quit daemon");
577 DynListener::registerFunc("UPTIME",&DLUptimeHandler, "get instance uptime");
578 DynListener::registerFunc("NOTIFY-HOST",&DLNotifyHostHandler, "notify host for specific domain", "<domain> <host>");
579 DynListener::registerFunc("NOTIFY",&DLNotifyHandler, "queue a notification", "<domain>");
580 DynListener::registerFunc("RELOAD",&DLReloadHandler, "reload all zones");
581 DynListener::registerFunc("REDISCOVER",&DLRediscoverHandler, "discover any new zones");
582 DynListener::registerFunc("VERSION",&DLVersionHandler, "get instance version");
583 DynListener::registerFunc("PURGE",&DLPurgeHandler, "purge entries from packet cache", "[<record>]");
584 DynListener::registerFunc("CCOUNTS",&DLCCHandler, "get cache statistics");
ba7244a5 585 DynListener::registerFunc("QTYPES", &DLQTypesHandler, "get QType statistics");
93698ef3
PD
586 DynListener::registerFunc("RESPSIZES", &DLRSizesHandler, "get histogram of response sizes");
587 DynListener::registerFunc("REMOTES", &DLRemotesHandler, "get top remotes");
3c90953e
PD
588 DynListener::registerFunc("SET",&DLSettingsHandler, "set config variables", "<var> <value>");
589 DynListener::registerFunc("RETRIEVE",&DLNotifyRetrieveHandler, "retrieve slave domain", "<domain>");
8864bdf6 590 DynListener::registerFunc("CURRENT-CONFIG",&DLCurrentConfigHandler, "retrieve the current configuration", "[diff|default]");
cd76677f 591 DynListener::registerFunc("LIST-ZONES",&DLListZones, "show list of zones", "[master|slave|native]");
24e0b305 592 DynListener::registerFunc("TOKEN-LOGIN", &DLTokenLogin, "Login to a PKCS#11 token", "<module> <slot> <pin>");
040712e0
BH
593
594 if(!::arg()["tcp-control-address"].empty()) {
595 DynListener* dlTCP=new DynListener(ComboAddress(::arg()["tcp-control-address"], ::arg().asNum("tcp-control-port")));
596 dlTCP->go();
597 }
12c86877 598
12c86877 599 // reparse, with error checking
e8d78143
BH
600 if(!::arg().mustDo("no-config"))
601 ::arg().file(configname.c_str());
602 ::arg().parse(argc,argv);
5bc3abe7
PD
603
604 if(::arg()["server-id"].empty()) {
605 char tmp[128];
a6fbcb6e
PL
606 if(gethostname(tmp, sizeof(tmp)-1) == 0) {
607 ::arg().set("server-id")=tmp;
608 } else {
04360367 609 g_log<<Logger::Warning<<"Unable to get the hostname, NSID and id.server values will be empty: "<<stringerror()<<endl;
a6fbcb6e 610 }
5bc3abe7
PD
611 }
612
12c86877 613 UeberBackend::go();
12f224ab
RG
614 N=std::make_shared<UDPNameserver>(); // this fails when we are not root, throws exception
615 g_udpReceivers.push_back(N);
616
617 size_t rthreads = ::arg().asNum("receiver-threads", 1);
618 if (rthreads > 1 && N->canReusePort()) {
619 g_udpReceivers.resize(rthreads);
620
621 for (size_t idx = 1; idx < rthreads; idx++) {
622 try {
623 g_udpReceivers[idx] = std::make_shared<UDPNameserver>(true);
624 }
625 catch(const PDNSException& e) {
e6a9dde5 626 g_log<<Logger::Error<<"Unable to reuse port, falling back to original bind"<<endl;
12f224ab
RG
627 break;
628 }
629 }
630 }
631
8c98b341 632 TN = make_unique<TCPNameserver>();
12c86877
BH
633 }
634 catch(const ArgException &A) {
e6a9dde5 635 g_log<<Logger::Error<<"Fatal error: "<<A.reason<<endl;
12c86877
BH
636 exit(1);
637 }
638
639 declareStats();
f3245c8c
OM
640 S.blacklist("special-memory-usage");
641
e6a9dde5 642 DLOG(g_log<<Logger::Warning<<"Verbose logging in effect"<<endl);
12c86877 643
ba1a571d 644 showProductVersion();
12c86877
BH
645
646 try {
12c86877
BH
647 mainthread();
648 }
3f81d239 649 catch(PDNSException &AE) {
e8d78143 650 if(!::arg().mustDo("daemon"))
12c86877 651 cerr<<"Exiting because: "<<AE.reason<<endl;
e6a9dde5 652 g_log<<Logger::Error<<"Exiting because: "<<AE.reason<<endl;
12c86877 653 }
adc10f99 654 catch(std::exception &e) {
e8d78143 655 if(!::arg().mustDo("daemon"))
12c86877 656 cerr<<"Exiting because of STL error: "<<e.what()<<endl;
e6a9dde5 657 g_log<<Logger::Error<<"Exiting because of STL error: "<<e.what()<<endl;
12c86877
BH
658 }
659 catch(...) {
660 cerr<<"Uncaught exception of unknown type - sorry"<<endl;
661 }
662
663 exit(1);
664
665}
666
667