]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/receiver.cc
Merge pull request #7945 from pieterlexis/syncres-CNAME-cache-cleanup
[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
104void daemonize(void)
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())
140 fname = LOCALSTATEDIR;
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
e6a9dde5 152 g_log<<Logger::Error<<"Writing pid for "<<getpid()<<" to "<<fname<<" failed: "<<strerror(errno)<<endl;
12c86877
BH
153}
154
aced0e6c
BH
155int g_fd1[2], g_fd2[2];
156FILE *g_fp;
157pthread_mutex_t g_guardian_lock = PTHREAD_MUTEX_INITIALIZER;
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
aced0e6c
BH
179 Lock l(&g_guardian_lock);
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
aced0e6c
BH
219 pthread_mutex_lock(&g_guardian_lock);
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) {
e6a9dde5 226 g_log<<Logger::Critical<<"Unable to open pipe for coprocess: "<<strerror(errno)<<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) {
e6a9dde5 271 g_log<<Logger::Error<<"Unable to execvp '"<<argv[0]<<"': "<<strerror(errno)<<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 }
aced0e6c 295 pthread_mutex_unlock(&g_guardian_lock);
12c86877
BH
296 int status;
297 cpid=pid;
298 for(;;) {
4957a608
BH
299 int ret=waitpid(pid,&status,WNOHANG);
300
301 if(ret<0) {
e6a9dde5
PL
302 g_log<<Logger::Error<<"In guardian loop, waitpid returned error: "<<strerror(errno)<<endl;
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
BH
316
317 pthread_mutex_lock(&g_guardian_lock);
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 {
e6a9dde5 351 g_log<<Logger::Error<<"Unable to fork: "<<strerror(errno)<<endl;
12c86877
BH
352 exit(1);
353 }
354 }
355}
356
1a61508c 357#ifdef __GLIBC__
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
2005fe2e 389#ifdef __GLIBC__
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
e8d78143
BH
418 if(!::arg().mustDo("config") && !::arg().mustDo("no-config")) // "config" == print a configuration file
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
2005fe2e 453#ifdef __GLIBC__
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()) {
49daa3cd
BH
491 cerr<<"Fatal: non-option on the command line, perhaps a '--setting=123' statement missed the '='?"<<endl;
492 exit(99);
493 }
f4137d84 494
e8d78143 495 if(::arg().mustDo("help")) {
ff5ba4f9
WA
496 cout<<"syntax:"<<endl<<endl;
497 cout<<::arg().helpstring(::arg()["help"])<<endl;
498 exit(0);
12c86877
BH
499 }
500
e8d78143
BH
501 if(::arg().mustDo("config")) {
502 cout<<::arg().configstring()<<endl;
70463abb 503 exit(0);
12c86877
BH
504 }
505
e8d78143 506 if(::arg().mustDo("list-modules")) {
44ac5977 507 auto modules = BackendMakers().getModules();
508 cout<<"Modules available:"<<endl;
509 for(const auto& m : modules)
510 cout<< m <<endl;
12c86877 511
44ac5977 512 _exit(99);
12c86877 513 }
da44c9ea 514
e8d78143 515 if(!::arg().asNum("local-port")) {
e6a9dde5 516 g_log<<Logger::Error<<"Unable to launch, binding to no port or port 0 makes no sense"<<endl;
da44c9ea
BH
517 exit(99); // this isn't going to fix itself either
518 }
12c86877 519 if(!BackendMakers().numLauncheable()) {
e6a9dde5 520 g_log<<Logger::Error<<"Unable to launch, no backends configured for querying"<<endl;
da44c9ea 521 exit(99); // this isn't going to fix itself either
12c86877 522 }
e8d78143 523 if(::arg().mustDo("daemon")) {
e6a9dde5 524 g_log.toConsole(Logger::None);
12c86877 525 if(!isGuarded(argv))
4957a608 526 daemonize();
12c86877
BH
527 }
528
529 if(isGuarded(argv)) {
e6a9dde5 530 g_log<<Logger::Warning<<"This is a guarded instance of pdns"<<endl;
12c86877
BH
531 dl=new DynListener; // listens on stdin
532 }
533 else {
e6a9dde5 534 g_log<<Logger::Warning<<"This is a standalone pdns"<<endl;
12c86877 535
e8d78143 536 if(::arg().mustDo("control-console"))
4957a608 537 dl=new DynListener();
12c86877 538 else
4957a608 539 dl=new DynListener(s_programname);
12c86877
BH
540
541 writePid();
542 }
3c90953e
PD
543 DynListener::registerFunc("SHOW",&DLShowHandler, "show a specific statistic or * to get a list", "<statistic>");
544 DynListener::registerFunc("RPING",&DLPingHandler, "ping instance");
545 DynListener::registerFunc("QUIT",&DLRQuitHandler, "quit daemon");
546 DynListener::registerFunc("UPTIME",&DLUptimeHandler, "get instance uptime");
547 DynListener::registerFunc("NOTIFY-HOST",&DLNotifyHostHandler, "notify host for specific domain", "<domain> <host>");
548 DynListener::registerFunc("NOTIFY",&DLNotifyHandler, "queue a notification", "<domain>");
549 DynListener::registerFunc("RELOAD",&DLReloadHandler, "reload all zones");
550 DynListener::registerFunc("REDISCOVER",&DLRediscoverHandler, "discover any new zones");
551 DynListener::registerFunc("VERSION",&DLVersionHandler, "get instance version");
552 DynListener::registerFunc("PURGE",&DLPurgeHandler, "purge entries from packet cache", "[<record>]");
553 DynListener::registerFunc("CCOUNTS",&DLCCHandler, "get cache statistics");
ba7244a5 554 DynListener::registerFunc("QTYPES", &DLQTypesHandler, "get QType statistics");
93698ef3
PD
555 DynListener::registerFunc("RESPSIZES", &DLRSizesHandler, "get histogram of response sizes");
556 DynListener::registerFunc("REMOTES", &DLRemotesHandler, "get top remotes");
3c90953e
PD
557 DynListener::registerFunc("SET",&DLSettingsHandler, "set config variables", "<var> <value>");
558 DynListener::registerFunc("RETRIEVE",&DLNotifyRetrieveHandler, "retrieve slave domain", "<domain>");
496d5c60 559 DynListener::registerFunc("CURRENT-CONFIG",&DLCurrentConfigHandler, "retrieve the current configuration");
cd76677f 560 DynListener::registerFunc("LIST-ZONES",&DLListZones, "show list of zones", "[master|slave|native]");
24e0b305 561 DynListener::registerFunc("TOKEN-LOGIN", &DLTokenLogin, "Login to a PKCS#11 token", "<module> <slot> <pin>");
040712e0
BH
562
563 if(!::arg()["tcp-control-address"].empty()) {
564 DynListener* dlTCP=new DynListener(ComboAddress(::arg()["tcp-control-address"], ::arg().asNum("tcp-control-port")));
565 dlTCP->go();
566 }
12c86877 567
12c86877 568 // reparse, with error checking
e8d78143
BH
569 if(!::arg().mustDo("no-config"))
570 ::arg().file(configname.c_str());
571 ::arg().parse(argc,argv);
5bc3abe7
PD
572
573 if(::arg()["server-id"].empty()) {
574 char tmp[128];
a6fbcb6e
PL
575 if(gethostname(tmp, sizeof(tmp)-1) == 0) {
576 ::arg().set("server-id")=tmp;
577 } else {
578 g_log<<Logger::Warning<<"Unable to get the hostname, NSID and id.server values will be empty: "<<strerror(errno)<<endl;
579 }
5bc3abe7
PD
580 }
581
12c86877 582 UeberBackend::go();
12f224ab
RG
583 N=std::make_shared<UDPNameserver>(); // this fails when we are not root, throws exception
584 g_udpReceivers.push_back(N);
585
586 size_t rthreads = ::arg().asNum("receiver-threads", 1);
587 if (rthreads > 1 && N->canReusePort()) {
588 g_udpReceivers.resize(rthreads);
589
590 for (size_t idx = 1; idx < rthreads; idx++) {
591 try {
592 g_udpReceivers[idx] = std::make_shared<UDPNameserver>(true);
593 }
594 catch(const PDNSException& e) {
e6a9dde5 595 g_log<<Logger::Error<<"Unable to reuse port, falling back to original bind"<<endl;
12f224ab
RG
596 break;
597 }
598 }
599 }
600
8c98b341 601 TN = make_unique<TCPNameserver>();
12c86877
BH
602 }
603 catch(const ArgException &A) {
e6a9dde5 604 g_log<<Logger::Error<<"Fatal error: "<<A.reason<<endl;
12c86877
BH
605 exit(1);
606 }
607
608 declareStats();
f3245c8c
OM
609 S.blacklist("special-memory-usage");
610
e6a9dde5 611 DLOG(g_log<<Logger::Warning<<"Verbose logging in effect"<<endl);
12c86877 612
ba1a571d 613 showProductVersion();
12c86877
BH
614
615 try {
12c86877
BH
616 mainthread();
617 }
3f81d239 618 catch(PDNSException &AE) {
e8d78143 619 if(!::arg().mustDo("daemon"))
12c86877 620 cerr<<"Exiting because: "<<AE.reason<<endl;
e6a9dde5 621 g_log<<Logger::Error<<"Exiting because: "<<AE.reason<<endl;
12c86877 622 }
adc10f99 623 catch(std::exception &e) {
e8d78143 624 if(!::arg().mustDo("daemon"))
12c86877 625 cerr<<"Exiting because of STL error: "<<e.what()<<endl;
e6a9dde5 626 g_log<<Logger::Error<<"Exiting because of STL error: "<<e.what()<<endl;
12c86877
BH
627 }
628 catch(...) {
629 cerr<<"Uncaught exception of unknown type - sorry"<<endl;
630 }
631
632 exit(1);
633
634}
635
636