]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/receiver.cc
Remove disable-tcp option
[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
BH
74
75time_t s_starttime;
76
77string s_programname="pdns"; // used in packethandler.cc
78
c4ac5865 79const char *funnytext=
12c86877
BH
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
12c86877
BH
92
93/**
94\file receiver.cc
95\brief The main loop of powerdns
96
97This file is where it all happens - main is here, as are the two pivotal threads qthread() and athread()
98*/
99
100void daemonize(void)
101{
102 if(fork())
103 exit(0); // bye bye
104
105 setsid();
106
dd8b6bd1 107 int i=open("/dev/null",O_RDWR); /* open stdin */
11a2091b 108 if(i < 0)
e6a9dde5 109 g_log<<Logger::Critical<<"Unable to open /dev/null: "<<stringerror()<<endl;
11a2091b
BH
110 else {
111 dup2(i,0); /* stdin */
112 dup2(i,1); /* stderr */
113 dup2(i,2); /* stderr */
114 close(i);
115 }
12c86877
BH
116}
117
12c86877 118static int cpid;
12c86877
BH
119static void takedown(int i)
120{
121 if(cpid) {
e6a9dde5 122 g_log<<Logger::Error<<"Guardian is killed, taking down children with us"<<endl;
882ca9d9
KM
123 kill(cpid,SIGKILL);
124 exit(0);
12c86877
BH
125 }
126}
127
128static void writePid(void)
129{
191f2e47 130 if(!::arg().mustDo("write-pid"))
131 return;
132
f0f3f0b0
PL
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";
12c86877
BH
144 ofstream of(fname.c_str());
145 if(of)
146 of<<getpid()<<endl;
147 else
e6a9dde5 148 g_log<<Logger::Error<<"Writing pid for "<<getpid()<<" to "<<fname<<" failed: "<<strerror(errno)<<endl;
12c86877
BH
149}
150
aced0e6c
BH
151int g_fd1[2], g_fd2[2];
152FILE *g_fp;
153pthread_mutex_t g_guardian_lock = PTHREAD_MUTEX_INITIALIZER;
12c86877 154
64bcb6be
RA
155// The next two methods are not in dynhandler.cc because they use a few items declared in this file.
156static string DLCycleHandler(const vector<string>&parts, pid_t ppid)
157{
882ca9d9
KM
158 kill(cpid, SIGKILL); // why?
159 kill(cpid, SIGKILL); // why?
64bcb6be
RA
160 sleep(1);
161 return "ok";
162}
163
12c86877
BH
164static 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
aced0e6c
BH
175 Lock l(&g_guardian_lock);
176
177 try {
178 writen2(g_fd1[1],line.c_str(),line.size()+1);
179 }
3f81d239 180 catch(PDNSException &ae) {
aced0e6c
BH
181 return "Error communicating with instance: "+ae.reason;
182 }
12c86877 183 char mesg[512];
20ca8e7d 184 string response;
aced0e6c 185 while(fgets(mesg,sizeof(mesg),g_fp)) {
188b28bd 186 if(*mesg=='\0')
20ca8e7d
BH
187 break;
188 response+=mesg;
189 }
040712e0 190 boost::trim_right(response);
20ca8e7d 191 return response;
12c86877
BH
192}
193
64bcb6be 194
12c86877
BH
195
196static 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);
3c90953e
PD
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");
12c86877
BH
208 dlg.registerRestFunc(&DLRestHandler);
209 dlg.go();
210 string progname=argv[0];
211
212 bool first=true;
882ca9d9 213 cpid=0;
12c86877 214
aced0e6c
BH
215 pthread_mutex_lock(&g_guardian_lock);
216
12c86877
BH
217 for(;;) {
218 int pid;
219 setStatus("Launching child");
aced0e6c
BH
220
221 if(pipe(g_fd1)<0 || pipe(g_fd2)<0) {
e6a9dde5 222 g_log<<Logger::Critical<<"Unable to open pipe for coprocess: "<<strerror(errno)<<endl;
12c86877
BH
223 exit(1);
224 }
225
aced0e6c 226 if(!(g_fp=fdopen(g_fd2[0],"r"))) {
e6a9dde5 227 g_log<<Logger::Critical<<"Unable to associate a file pointer with pipe: "<<stringerror()<<endl;
aced0e6c
BH
228 exit(1);
229 }
230 setbuf(g_fp,0); // no buffering please, confuses select
231
12c86877 232 if(!(pid=fork())) { // child
882ca9d9
KM
233 signal(SIGTERM, SIG_DFL);
234
12c86877
BH
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
e8d78143 242 if(::arg()["config-name"]!="") {
4957a608 243 progname+="-"+::arg()["config-name"];
e6a9dde5 244 g_log<<Logger::Error<<"Virtual configuration name: "<<::arg()["config-name"]<<endl;
12c86877
BH
245 }
246
247 newargv[0]=strdup(const_cast<char *>((progname+"-instance").c_str()));
248 for(n=1;n<argc;n++) {
4957a608 249 newargv[n]=argv[n];
12c86877
BH
250 }
251 newargv[n]=0;
252
e6a9dde5 253 g_log<<Logger::Error<<"Guardian is launching an instance"<<endl;
aced0e6c
BH
254 close(g_fd1[1]);
255 fclose(g_fp); // this closes g_fd2[0] for us
12c86877 256
aced0e6c 257 if(g_fd1[0]!= infd) {
4957a608
BH
258 dup2(g_fd1[0], infd);
259 close(g_fd1[0]);
12c86877
BH
260 }
261
aced0e6c 262 if(g_fd2[1]!= outfd) {
4957a608
BH
263 dup2(g_fd2[1], outfd);
264 close(g_fd2[1]);
12c86877 265 }
c1663439 266 if(execvp(argv[0], newargv)<0) {
e6a9dde5 267 g_log<<Logger::Error<<"Unable to execvp '"<<argv[0]<<"': "<<strerror(errno)<<endl;
4957a608
BH
268 char **p=newargv;
269 while(*p)
e6a9dde5 270 g_log<<Logger::Error<<*p++<<endl;
12c86877 271
4957a608 272 exit(1);
12c86877 273 }
e6a9dde5 274 g_log<<Logger::Error<<"execvp returned!!"<<endl;
12c86877
BH
275 // never reached
276 }
277 else if(pid>0) { // parent
aced0e6c
BH
278 close(g_fd1[0]);
279 close(g_fd2[1]);
12c86877
BH
280
281 if(first) {
4957a608 282 first=false;
882ca9d9
KM
283 signal(SIGTERM, takedown);
284
4957a608
BH
285 signal(SIGHUP, SIG_IGN);
286 signal(SIGUSR1, SIG_IGN);
287 signal(SIGUSR2, SIG_IGN);
12c86877 288
4957a608 289 writePid();
12c86877 290 }
aced0e6c 291 pthread_mutex_unlock(&g_guardian_lock);
12c86877
BH
292 int status;
293 cpid=pid;
294 for(;;) {
4957a608
BH
295 int ret=waitpid(pid,&status,WNOHANG);
296
297 if(ret<0) {
e6a9dde5
PL
298 g_log<<Logger::Error<<"In guardian loop, waitpid returned error: "<<strerror(errno)<<endl;
299 g_log<<Logger::Error<<"Dying"<<endl;
4957a608
BH
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 }
12c86877 311 }
aced0e6c
BH
312
313 pthread_mutex_lock(&g_guardian_lock);
314 close(g_fd1[1]);
315 fclose(g_fp);
316 g_fp=0;
12c86877
BH
317
318 if(WIFEXITED(status)) {
4957a608
BH
319 int ret=WEXITSTATUS(status);
320
321 if(ret==99) {
e6a9dde5 322 g_log<<Logger::Error<<"Child requested a stop, exiting"<<endl;
4957a608
BH
323 exit(1);
324 }
325 setStatus("Child died with code "+itoa(ret));
e6a9dde5 326 g_log<<Logger::Error<<"Our pdns instance exited with code "<<ret<<", respawning"<<endl;
4957a608 327
882ca9d9
KM
328 sleep(1);
329 continue;
12c86877
BH
330 }
331 if(WIFSIGNALED(status)) {
4957a608
BH
332 int sig=WTERMSIG(status);
333 setStatus("Child died because of signal "+itoa(sig));
e6a9dde5 334 g_log<<Logger::Error<<"Our pdns instance ("<<pid<<") exited after signal "<<sig<<endl;
12c86877 335#ifdef WCOREDUMP
4957a608 336 if(WCOREDUMP(status))
e6a9dde5 337 g_log<<Logger::Error<<"Dumped core"<<endl;
12c86877
BH
338#endif
339
e6a9dde5 340 g_log<<Logger::Error<<"Respawning"<<endl;
882ca9d9
KM
341 sleep(1);
342 continue;
12c86877 343 }
e6a9dde5 344 g_log<<Logger::Error<<"No clue what happened! Respawning"<<endl;
12c86877
BH
345 }
346 else {
e6a9dde5 347 g_log<<Logger::Error<<"Unable to fork: "<<strerror(errno)<<endl;
12c86877
BH
348 exit(1);
349 }
350 }
351}
352
1a61508c 353#ifdef __GLIBC__
12c86877
BH
354#include <execinfo.h>
355static void tbhandler(int num)
356{
e6a9dde5 357 g_log<<Logger::Critical<<"Got a signal "<<num<<", attempting to print trace: "<<endl;
12c86877
BH
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
e6a9dde5 367 g_log<<Logger::Error<<strings[i]<<endl;
12c86877
BH
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
377int main(int argc, char **argv)
ba1a571d 378{
3e135495 379 versionSetProduct(ProductAuthoritative);
02116dff
BH
380 reportAllTypes(); // init MOADNSParser
381
12c86877
BH
382 s_programname="pdns";
383 s_starttime=time(0);
384
2005fe2e 385#ifdef __GLIBC__
12c86877
BH
386 signal(SIGSEGV,tbhandler);
387 signal(SIGFPE,tbhandler);
388 signal(SIGABRT,tbhandler);
389 signal(SIGILL,tbhandler);
390#endif
391
35b9a6ff 392 std::ios_base::sync_with_stdio(false);
12c86877 393
e6a9dde5 394 g_log.toConsole(Logger::Warning);
12c86877
BH
395 try {
396 declareArguments();
c4db07b7 397
e8d78143 398 ::arg().laxParse(argc,argv); // do a lax parse
12c86877 399
c4db07b7 400 if(::arg().mustDo("version")) {
ba1a571d 401 showProductVersion();
3613a51c 402 showBuildConfiguration();
c4db07b7
PD
403 exit(99);
404 }
405
e8d78143
BH
406 if(::arg()["config-name"]!="")
407 s_programname+="-"+::arg()["config-name"];
12c86877 408
e6a9dde5 409 g_log.setName(s_programname);
12c86877 410
e8d78143 411 string configname=::arg()["config-dir"]+"/"+s_programname+".conf";
12c86877
BH
412 cleanSlashes(configname);
413
e8d78143
BH
414 if(!::arg().mustDo("config") && !::arg().mustDo("no-config")) // "config" == print a configuration file
415 ::arg().laxFile(configname.c_str());
12c86877 416
e8d78143
BH
417 ::arg().laxParse(argc,argv); // reparse so the commandline still wins
418 if(!::arg()["logging-facility"].empty()) {
f8499e52
BH
419 int val=logFacilityToLOG(::arg().asNum("logging-facility") );
420 if(val >= 0)
e6a9dde5 421 g_log.setFacility(val);
6e2514e4 422 else
e6a9dde5 423 g_log<<Logger::Error<<"Unknown logging facility "<<::arg().asNum("logging-facility") <<endl;
12c86877
BH
424 }
425
e6a9dde5
PL
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")));
12c86877 430
e8d78143
BH
431 if(::arg().mustDo("help") || ::arg().mustDo("config")) {
432 ::arg().set("daemon")="no";
433 ::arg().set("guardian")="no";
12c86877
BH
434 }
435
e8d78143
BH
436 if(::arg().mustDo("guardian") && !isGuarded(argv)) {
437 if(::arg().mustDo("daemon")) {
e6a9dde5 438 g_log.toConsole(Logger::Critical);
4957a608 439 daemonize();
12c86877
BH
440 }
441 guardian(argc, argv);
442 // never get here, guardian will reinvoke process
443 cerr<<"Um, we did get here!"<<endl;
444 }
45fdd612 445
12c86877
BH
446
447 // we really need to do work - either standalone or as an instance
5488e86b 448
2005fe2e 449#ifdef __GLIBC__
5488e86b 450 if(!::arg().mustDo("traceback-handler")) {
e6a9dde5 451 g_log<<Logger::Warning<<"Disabling traceback handler"<<endl;
5488e86b
PD
452 signal(SIGSEGV,SIG_DFL);
453 signal(SIGFPE,SIG_DFL);
454 signal(SIGABRT,SIG_DFL);
455 signal(SIGILL,SIG_DFL);
456 }
457#endif
458
d4f29089
KM
459#ifdef HAVE_LIBSODIUM
460 if (sodium_init() == -1) {
461 cerr<<"Unable to initialize sodium crypto library"<<endl;
462 exit(99);
463 }
464#endif
7581a35b 465
7581a35b
KM
466 openssl_thread_setup();
467 openssl_seed();
e97cb679
AT
468 /* setup rng */
469 dns_random_init();
7581a35b 470
d4168b30
CHB
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
e8d78143 480 BackendMakers().launch(::arg()["launch"]); // vrooooom!
f4137d84 481
e8d78143 482 if(!::arg().getCommands().empty()) {
49daa3cd
BH
483 cerr<<"Fatal: non-option on the command line, perhaps a '--setting=123' statement missed the '='?"<<endl;
484 exit(99);
485 }
f4137d84 486
e8d78143 487 if(::arg().mustDo("help")) {
ff5ba4f9
WA
488 cout<<"syntax:"<<endl<<endl;
489 cout<<::arg().helpstring(::arg()["help"])<<endl;
490 exit(0);
12c86877
BH
491 }
492
e8d78143
BH
493 if(::arg().mustDo("config")) {
494 cout<<::arg().configstring()<<endl;
70463abb 495 exit(0);
12c86877
BH
496 }
497
e8d78143 498 if(::arg().mustDo("list-modules")) {
44ac5977 499 auto modules = BackendMakers().getModules();
500 cout<<"Modules available:"<<endl;
501 for(const auto& m : modules)
502 cout<< m <<endl;
12c86877 503
44ac5977 504 _exit(99);
12c86877 505 }
da44c9ea 506
e8d78143 507 if(!::arg().asNum("local-port")) {
e6a9dde5 508 g_log<<Logger::Error<<"Unable to launch, binding to no port or port 0 makes no sense"<<endl;
da44c9ea
BH
509 exit(99); // this isn't going to fix itself either
510 }
12c86877 511 if(!BackendMakers().numLauncheable()) {
e6a9dde5 512 g_log<<Logger::Error<<"Unable to launch, no backends configured for querying"<<endl;
da44c9ea 513 exit(99); // this isn't going to fix itself either
12c86877 514 }
e8d78143 515 if(::arg().mustDo("daemon")) {
e6a9dde5 516 g_log.toConsole(Logger::None);
12c86877 517 if(!isGuarded(argv))
4957a608 518 daemonize();
12c86877
BH
519 }
520
521 if(isGuarded(argv)) {
e6a9dde5 522 g_log<<Logger::Warning<<"This is a guarded instance of pdns"<<endl;
12c86877
BH
523 dl=new DynListener; // listens on stdin
524 }
525 else {
e6a9dde5 526 g_log<<Logger::Warning<<"This is a standalone pdns"<<endl;
12c86877 527
e8d78143 528 if(::arg().mustDo("control-console"))
4957a608 529 dl=new DynListener();
12c86877 530 else
4957a608 531 dl=new DynListener(s_programname);
12c86877
BH
532
533 writePid();
534 }
3c90953e
PD
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");
ba7244a5 546 DynListener::registerFunc("QTYPES", &DLQTypesHandler, "get QType statistics");
93698ef3
PD
547 DynListener::registerFunc("RESPSIZES", &DLRSizesHandler, "get histogram of response sizes");
548 DynListener::registerFunc("REMOTES", &DLRemotesHandler, "get top remotes");
3c90953e
PD
549 DynListener::registerFunc("SET",&DLSettingsHandler, "set config variables", "<var> <value>");
550 DynListener::registerFunc("RETRIEVE",&DLNotifyRetrieveHandler, "retrieve slave domain", "<domain>");
496d5c60 551 DynListener::registerFunc("CURRENT-CONFIG",&DLCurrentConfigHandler, "retrieve the current configuration");
cd76677f 552 DynListener::registerFunc("LIST-ZONES",&DLListZones, "show list of zones", "[master|slave|native]");
24e0b305 553 DynListener::registerFunc("TOKEN-LOGIN", &DLTokenLogin, "Login to a PKCS#11 token", "<module> <slot> <pin>");
040712e0
BH
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 }
12c86877 559
12c86877 560 // reparse, with error checking
e8d78143
BH
561 if(!::arg().mustDo("no-config"))
562 ::arg().file(configname.c_str());
563 ::arg().parse(argc,argv);
5bc3abe7
PD
564
565 if(::arg()["server-id"].empty()) {
566 char tmp[128];
a6fbcb6e
PL
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 }
5bc3abe7
PD
572 }
573
12c86877 574 UeberBackend::go();
12f224ab
RG
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) {
e6a9dde5 587 g_log<<Logger::Error<<"Unable to reuse port, falling back to original bind"<<endl;
12f224ab
RG
588 break;
589 }
590 }
591 }
592
998fddc3 593 TN = new TCPNameserver;
12c86877
BH
594 }
595 catch(const ArgException &A) {
e6a9dde5 596 g_log<<Logger::Error<<"Fatal error: "<<A.reason<<endl;
12c86877
BH
597 exit(1);
598 }
599
600 declareStats();
e6a9dde5 601 DLOG(g_log<<Logger::Warning<<"Verbose logging in effect"<<endl);
12c86877 602
ba1a571d 603 showProductVersion();
12c86877
BH
604
605 try {
12c86877
BH
606 mainthread();
607 }
3f81d239 608 catch(PDNSException &AE) {
e8d78143 609 if(!::arg().mustDo("daemon"))
12c86877 610 cerr<<"Exiting because: "<<AE.reason<<endl;
e6a9dde5 611 g_log<<Logger::Error<<"Exiting because: "<<AE.reason<<endl;
12c86877 612 }
adc10f99 613 catch(std::exception &e) {
e8d78143 614 if(!::arg().mustDo("daemon"))
12c86877 615 cerr<<"Exiting because of STL error: "<<e.what()<<endl;
e6a9dde5 616 g_log<<Logger::Error<<"Exiting because of STL error: "<<e.what()<<endl;
12c86877
BH
617 }
618 catch(...) {
619 cerr<<"Uncaught exception of unknown type - sorry"<<endl;
620 }
621
622 exit(1);
623
624}
625
626