nsd.c revision 1.1.1.1.8.1 1 /*
2 * nsd.c -- nsd(8)
3 *
4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5 *
6 * See LICENSE for the license.
7 *
8 */
9
10 #include "config.h"
11
12 #include <sys/types.h>
13 #include <sys/param.h>
14 #include <sys/socket.h>
15 #include <sys/stat.h>
16 #include <sys/uio.h>
17 #include <sys/wait.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20 #ifdef HAVE_GRP_H
21 #include <grp.h>
22 #endif /* HAVE_GRP_H */
23 #ifdef HAVE_SETUSERCONTEXT
24 #include <login_cap.h>
25 #endif /* HAVE_SETUSERCONTEXT */
26
27 #include <assert.h>
28 #include <ctype.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <limits.h>
32 #include <netdb.h>
33 #include <pwd.h>
34 #include <signal.h>
35 #include <stdarg.h>
36 #include <stddef.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <time.h>
41 #include <unistd.h>
42
43 #include "nsd.h"
44 #include "options.h"
45 #include "tsig.h"
46 #include "remote.h"
47 #include "xfrd-disk.h"
48
49 /* The server handler... */
50 struct nsd nsd;
51 static char hostname[MAXHOSTNAMELEN];
52 extern config_parser_state_type* cfg_parser;
53
54 static void error(const char *format, ...) ATTR_FORMAT(printf, 1, 2);
55
56 /*
57 * Print the help text.
58 *
59 */
60 static void
61 usage (void)
62 {
63 fprintf(stderr, "Usage: nsd [OPTION]...\n");
64 fprintf(stderr, "Name Server Daemon.\n\n");
65 fprintf(stderr,
66 "Supported options:\n"
67 " -4 Only listen to IPv4 connections.\n"
68 " -6 Only listen to IPv6 connections.\n"
69 " -a ip-address[@port] Listen to the specified incoming IP address (and port)\n"
70 " May be specified multiple times).\n"
71 " -c configfile Read specified configfile instead of %s.\n"
72 " -d do not fork as a daemon process.\n"
73 #ifndef NDEBUG
74 " -F facilities Specify the debug facilities.\n"
75 #endif /* NDEBUG */
76 " -f database Specify the database to load.\n"
77 " -h Print this help information.\n"
78 , CONFIGFILE);
79 fprintf(stderr,
80 " -i identity Specify the identity when queried for id.server CHAOS TXT.\n"
81 " -I nsid Specify the NSID. This must be a hex string.\n"
82 #ifndef NDEBUG
83 " -L level Specify the debug level.\n"
84 #endif /* NDEBUG */
85 " -l filename Specify the log file.\n"
86 " -N server-count The number of servers to start.\n"
87 " -n tcp-count The maximum number of TCP connections per server.\n"
88 " -P pidfile Specify the PID file to write.\n"
89 " -p port Specify the port to listen to.\n"
90 " -s seconds Dump statistics every SECONDS seconds.\n"
91 " -t chrootdir Change root to specified directory on startup.\n"
92 );
93 fprintf(stderr,
94 " -u user Change effective uid to the specified user.\n"
95 " -V level Specify verbosity level.\n"
96 " -v Print version information.\n"
97 );
98 fprintf(stderr, "Version %s. Report bugs to <%s>.\n",
99 PACKAGE_VERSION, PACKAGE_BUGREPORT);
100 }
101
102 /*
103 * Print the version exit.
104 *
105 */
106 static void
107 version(void)
108 {
109 fprintf(stderr, "%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
110 fprintf(stderr, "Written by NLnet Labs.\n\n");
111 fprintf(stderr,
112 "Copyright (C) 2001-2006 NLnet Labs. This is free software.\n"
113 "There is NO warranty; not even for MERCHANTABILITY or FITNESS\n"
114 "FOR A PARTICULAR PURPOSE.\n");
115 exit(0);
116 }
117
118 /*
119 * Something went wrong, give error messages and exit.
120 *
121 */
122 static void
123 error(const char *format, ...)
124 {
125 va_list args;
126 va_start(args, format);
127 log_vmsg(LOG_ERR, format, args);
128 va_end(args);
129 exit(1);
130 }
131
132 static void
133 append_trailing_slash(const char** dirname, region_type* region)
134 {
135 int l = strlen(*dirname);
136 if (l>0 && (*dirname)[l-1] != '/' && l < 0xffffff) {
137 char *dirname_slash = region_alloc(region, l+2);
138 memcpy(dirname_slash, *dirname, l+1);
139 strlcat(dirname_slash, "/", l+2);
140 /* old dirname is leaked, this is only used for chroot, once */
141 *dirname = dirname_slash;
142 }
143 }
144
145 static int
146 file_inside_chroot(const char* fname, const char* chr)
147 {
148 /* true if filename starts with chroot or is not absolute */
149 return ((fname && fname[0] && strncmp(fname, chr, strlen(chr)) == 0) ||
150 (fname && fname[0] != '/'));
151 }
152
153 void
154 get_ip_port_frm_str(const char* arg, const char** hostname,
155 const char** port)
156 {
157 /* parse src[@port] option */
158 char* delim = NULL;
159 if (arg) {
160 delim = strchr(arg, '@');
161 }
162
163 if (delim) {
164 *delim = '\0';
165 *port = delim+1;
166 }
167 *hostname = arg;
168 }
169
170 /* append interface to interface array (names, udp, tcp) */
171 void
172 add_interface(char*** nodes, struct nsd* nsd, char* ip)
173 {
174 /* realloc the arrays */
175 if(nsd->ifs == 0) {
176 *nodes = xalloc_zero(sizeof(*nodes));
177 nsd->udp = xalloc_zero(sizeof(*nsd->udp));
178 nsd->tcp = xalloc_zero(sizeof(*nsd->udp));
179 } else {
180 region_remove_cleanup(nsd->region, free, *nodes);
181 region_remove_cleanup(nsd->region, free, nsd->udp);
182 region_remove_cleanup(nsd->region, free, nsd->tcp);
183 *nodes = xrealloc(*nodes, (nsd->ifs+1)*sizeof(*nodes));
184 nsd->udp = xrealloc(nsd->udp, (nsd->ifs+1)*sizeof(*nsd->udp));
185 nsd->tcp = xrealloc(nsd->tcp, (nsd->ifs+1)*sizeof(*nsd->udp));
186 (*nodes)[nsd->ifs] = NULL;
187 memset(&nsd->udp[nsd->ifs], 0, sizeof(*nsd->udp));
188 memset(&nsd->tcp[nsd->ifs], 0, sizeof(*nsd->tcp));
189 }
190 region_add_cleanup(nsd->region, free, *nodes);
191 region_add_cleanup(nsd->region, free, nsd->udp);
192 region_add_cleanup(nsd->region, free, nsd->tcp);
193
194 /* add it */
195 (*nodes)[nsd->ifs] = ip;
196 ++nsd->ifs;
197 }
198
199 /*
200 * Fetch the nsd parent process id from the nsd pidfile
201 *
202 */
203 pid_t
204 readpid(const char *file)
205 {
206 int fd;
207 pid_t pid;
208 char pidbuf[16];
209 char *t;
210 int l;
211
212 if ((fd = open(file, O_RDONLY)) == -1) {
213 return -1;
214 }
215
216 if (((l = read(fd, pidbuf, sizeof(pidbuf)))) == -1) {
217 close(fd);
218 return -1;
219 }
220
221 close(fd);
222
223 /* Empty pidfile means no pidfile... */
224 if (l == 0) {
225 errno = ENOENT;
226 return -1;
227 }
228
229 pid = (pid_t) strtol(pidbuf, &t, 10);
230
231 if (*t && *t != '\n') {
232 return -1;
233 }
234 return pid;
235 }
236
237 /*
238 * Store the nsd parent process id in the nsd pidfile
239 *
240 */
241 int
242 writepid(struct nsd *nsd)
243 {
244 FILE * fd;
245 char pidbuf[32];
246
247 snprintf(pidbuf, sizeof(pidbuf), "%lu\n", (unsigned long) nsd->pid);
248
249 if ((fd = fopen(nsd->pidfile, "w")) == NULL ) {
250 log_msg(LOG_ERR, "cannot open pidfile %s: %s",
251 nsd->pidfile, strerror(errno));
252 return -1;
253 }
254
255 if (!write_data(fd, pidbuf, strlen(pidbuf))) {
256 log_msg(LOG_ERR, "cannot write pidfile %s: %s",
257 nsd->pidfile, strerror(errno));
258 fclose(fd);
259 return -1;
260 }
261 fclose(fd);
262
263 if (chown(nsd->pidfile, nsd->uid, nsd->gid) == -1) {
264 log_msg(LOG_ERR, "cannot chown %u.%u %s: %s",
265 (unsigned) nsd->uid, (unsigned) nsd->gid,
266 nsd->pidfile, strerror(errno));
267 return -1;
268 }
269
270 return 0;
271 }
272
273 void
274 unlinkpid(const char* file)
275 {
276 int fd = -1;
277
278 if (file) {
279 /* truncate pidfile */
280 fd = open(file, O_WRONLY | O_TRUNC, 0644);
281 if (fd == -1) {
282 /* Truncate the pid file. */
283 log_msg(LOG_ERR, "can not truncate the pid file %s: %s", file, strerror(errno));
284 } else
285 close(fd);
286
287 /* unlink pidfile */
288 if (unlink(file) == -1)
289 log_msg(LOG_WARNING, "failed to unlink pidfile %s: %s",
290 file, strerror(errno));
291 }
292 }
293
294 /*
295 * Incoming signals, set appropriate actions.
296 *
297 */
298 void
299 sig_handler(int sig)
300 {
301 /* To avoid race cond. We really don't want to use log_msg() in this handler */
302
303 /* Are we a child server? */
304 if (nsd.server_kind != NSD_SERVER_MAIN) {
305 switch (sig) {
306 case SIGCHLD:
307 nsd.signal_hint_child = 1;
308 break;
309 case SIGALRM:
310 break;
311 case SIGINT:
312 case SIGTERM:
313 nsd.signal_hint_quit = 1;
314 break;
315 case SIGILL:
316 case SIGUSR1: /* Dump stats on SIGUSR1. */
317 nsd.signal_hint_statsusr = 1;
318 break;
319 default:
320 break;
321 }
322 return;
323 }
324
325 /* We are the main process */
326 switch (sig) {
327 case SIGCHLD:
328 nsd.signal_hint_child = 1;
329 return;
330 case SIGHUP:
331 nsd.signal_hint_reload_hup = 1;
332 return;
333 case SIGALRM:
334 nsd.signal_hint_stats = 1;
335 break;
336 case SIGILL:
337 /*
338 * For backwards compatibility with BIND 8 and older
339 * versions of NSD.
340 */
341 nsd.signal_hint_statsusr = 1;
342 break;
343 case SIGUSR1:
344 /* Dump statistics. */
345 nsd.signal_hint_statsusr = 1;
346 break;
347 case SIGINT:
348 case SIGTERM:
349 default:
350 nsd.signal_hint_shutdown = 1;
351 break;
352 }
353 }
354
355 /*
356 * Statistic output...
357 *
358 */
359 #ifdef BIND8_STATS
360 void
361 bind8_stats (struct nsd *nsd)
362 {
363 char buf[MAXSYSLOGMSGLEN];
364 char *msg, *t;
365 int i, len;
366
367 /* Current time... */
368 time_t now;
369 if(!nsd->st.period)
370 return;
371 time(&now);
372
373 /* NSTATS */
374 t = msg = buf + snprintf(buf, MAXSYSLOGMSGLEN, "NSTATS %lld %lu",
375 (long long) now, (unsigned long) nsd->st.boot);
376 for (i = 0; i <= 255; i++) {
377 /* How much space left? */
378 if ((len = buf + MAXSYSLOGMSGLEN - t) < 32) {
379 log_msg(LOG_INFO, "%s", buf);
380 t = msg;
381 len = buf + MAXSYSLOGMSGLEN - t;
382 }
383
384 if (nsd->st.qtype[i] != 0) {
385 t += snprintf(t, len, " %s=%lu", rrtype_to_string(i), nsd->st.qtype[i]);
386 }
387 }
388 if (t > msg)
389 log_msg(LOG_INFO, "%s", buf);
390
391 /* XSTATS */
392 /* Only print it if we're in the main daemon or have anything to report... */
393 if (nsd->server_kind == NSD_SERVER_MAIN
394 || nsd->st.dropped || nsd->st.raxfr || (nsd->st.qudp + nsd->st.qudp6 - nsd->st.dropped)
395 || nsd->st.txerr || nsd->st.opcode[OPCODE_QUERY] || nsd->st.opcode[OPCODE_IQUERY]
396 || nsd->st.wrongzone || nsd->st.ctcp + nsd->st.ctcp6 || nsd->st.rcode[RCODE_SERVFAIL]
397 || nsd->st.rcode[RCODE_FORMAT] || nsd->st.nona || nsd->st.rcode[RCODE_NXDOMAIN]
398 || nsd->st.opcode[OPCODE_UPDATE]) {
399
400 log_msg(LOG_INFO, "XSTATS %lld %lu"
401 " RR=%lu RNXD=%lu RFwdR=%lu RDupR=%lu RFail=%lu RFErr=%lu RErr=%lu RAXFR=%lu"
402 " RLame=%lu ROpts=%lu SSysQ=%lu SAns=%lu SFwdQ=%lu SDupQ=%lu SErr=%lu RQ=%lu"
403 " RIQ=%lu RFwdQ=%lu RDupQ=%lu RTCP=%lu SFwdR=%lu SFail=%lu SFErr=%lu SNaAns=%lu"
404 " SNXD=%lu RUQ=%lu RURQ=%lu RUXFR=%lu RUUpd=%lu",
405 (long long) now, (unsigned long) nsd->st.boot,
406 nsd->st.dropped, (unsigned long)0, (unsigned long)0, (unsigned long)0, (unsigned long)0,
407 (unsigned long)0, (unsigned long)0, nsd->st.raxfr, (unsigned long)0, (unsigned long)0,
408 (unsigned long)0, nsd->st.qudp + nsd->st.qudp6 - nsd->st.dropped, (unsigned long)0,
409 (unsigned long)0, nsd->st.txerr,
410 nsd->st.opcode[OPCODE_QUERY], nsd->st.opcode[OPCODE_IQUERY], nsd->st.wrongzone,
411 (unsigned long)0, nsd->st.ctcp + nsd->st.ctcp6,
412 (unsigned long)0, nsd->st.rcode[RCODE_SERVFAIL], nsd->st.rcode[RCODE_FORMAT],
413 nsd->st.nona, nsd->st.rcode[RCODE_NXDOMAIN],
414 (unsigned long)0, (unsigned long)0, (unsigned long)0, nsd->st.opcode[OPCODE_UPDATE]);
415 }
416
417 }
418 #endif /* BIND8_STATS */
419
420 extern char *optarg;
421 extern int optind;
422
423 int
424 main(int argc, char *argv[])
425 {
426 /* Scratch variables... */
427 int c;
428 pid_t oldpid;
429 size_t i;
430 struct sigaction action;
431 #ifdef HAVE_GETPWNAM
432 struct passwd *pwd = NULL;
433 #endif /* HAVE_GETPWNAM */
434
435 struct addrinfo hints[2];
436 int hints_in_use = 1;
437 char** nodes = NULL; /* array of address strings, size nsd.ifs */
438 const char *udp_port = 0;
439 const char *tcp_port = 0;
440
441 const char *configfile = CONFIGFILE;
442
443 char* argv0 = (argv0 = strrchr(argv[0], '/')) ? argv0 + 1 : argv[0];
444
445 log_init(argv0);
446
447 /* Initialize the server handler... */
448 memset(&nsd, 0, sizeof(struct nsd));
449 nsd.region = region_create(xalloc, free);
450 nsd.dbfile = 0;
451 nsd.pidfile = 0;
452 nsd.server_kind = NSD_SERVER_MAIN;
453 memset(&hints, 0, sizeof(*hints)*2);
454 hints[0].ai_family = DEFAULT_AI_FAMILY;
455 hints[0].ai_flags = AI_PASSIVE;
456 hints[1].ai_family = DEFAULT_AI_FAMILY;
457 hints[1].ai_flags = AI_PASSIVE;
458 nsd.identity = 0;
459 nsd.version = VERSION;
460 nsd.username = 0;
461 nsd.chrootdir = 0;
462 nsd.nsid = NULL;
463 nsd.nsid_len = 0;
464
465 nsd.child_count = 0;
466 nsd.maximum_tcp_count = 0;
467 nsd.current_tcp_count = 0;
468 nsd.grab_ip6_optional = 0;
469 nsd.file_rotation_ok = 0;
470
471 /* Set up our default identity to gethostname(2) */
472 if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
473 nsd.identity = hostname;
474 } else {
475 log_msg(LOG_ERR,
476 "failed to get the host name: %s - using default identity",
477 strerror(errno));
478 nsd.identity = IDENTITY;
479 }
480
481 /* Parse the command line... */
482 while ((c = getopt(argc, argv, "46a:c:df:hi:I:l:N:n:P:p:s:u:t:X:V:v"
483 #ifndef NDEBUG /* <mattthijs> only when configured with --enable-checking */
484 "F:L:"
485 #endif /* NDEBUG */
486 )) != -1) {
487 switch (c) {
488 case '4':
489 hints[0].ai_family = AF_INET;
490 break;
491 case '6':
492 #ifdef INET6
493 hints[0].ai_family = AF_INET6;
494 #else /* !INET6 */
495 error("IPv6 support not enabled.");
496 #endif /* INET6 */
497 break;
498 case 'a':
499 add_interface(&nodes, &nsd, optarg);
500 break;
501 case 'c':
502 configfile = optarg;
503 break;
504 case 'd':
505 nsd.debug = 1;
506 break;
507 case 'f':
508 nsd.dbfile = optarg;
509 break;
510 case 'h':
511 usage();
512 exit(0);
513 case 'i':
514 nsd.identity = optarg;
515 break;
516 case 'I':
517 if (nsd.nsid_len != 0) {
518 /* can only be given once */
519 break;
520 }
521 if (strncasecmp(optarg, "ascii_", 6) == 0) {
522 nsd.nsid = xalloc(strlen(optarg+6));
523 nsd.nsid_len = strlen(optarg+6);
524 memmove(nsd.nsid, optarg+6, nsd.nsid_len);
525 } else {
526 if (strlen(optarg) % 2 != 0) {
527 error("the NSID must be a hex string of an even length.");
528 }
529 nsd.nsid = xalloc(strlen(optarg) / 2);
530 nsd.nsid_len = strlen(optarg) / 2;
531 if (hex_pton(optarg, nsd.nsid, nsd.nsid_len) == -1) {
532 error("hex string cannot be parsed '%s' in NSID.", optarg);
533 }
534 }
535 break;
536 case 'l':
537 nsd.log_filename = optarg;
538 break;
539 case 'N':
540 i = atoi(optarg);
541 if (i <= 0) {
542 error("number of child servers must be greater than zero.");
543 } else {
544 nsd.child_count = i;
545 }
546 break;
547 case 'n':
548 i = atoi(optarg);
549 if (i <= 0) {
550 error("number of concurrent TCP connections must greater than zero.");
551 } else {
552 nsd.maximum_tcp_count = i;
553 }
554 break;
555 case 'P':
556 nsd.pidfile = optarg;
557 break;
558 case 'p':
559 if (atoi(optarg) == 0) {
560 error("port argument must be numeric.");
561 }
562 tcp_port = optarg;
563 udp_port = optarg;
564 break;
565 case 's':
566 #ifdef BIND8_STATS
567 nsd.st.period = atoi(optarg);
568 #else /* !BIND8_STATS */
569 error("BIND 8 statistics not enabled.");
570 #endif /* BIND8_STATS */
571 break;
572 case 't':
573 #ifdef HAVE_CHROOT
574 nsd.chrootdir = optarg;
575 #else /* !HAVE_CHROOT */
576 error("chroot not supported on this platform.");
577 #endif /* HAVE_CHROOT */
578 break;
579 case 'u':
580 nsd.username = optarg;
581 break;
582 case 'V':
583 verbosity = atoi(optarg);
584 break;
585 case 'v':
586 version();
587 /* version exits */
588 break;
589 #ifndef NDEBUG
590 case 'F':
591 sscanf(optarg, "%x", &nsd_debug_facilities);
592 break;
593 case 'L':
594 sscanf(optarg, "%d", &nsd_debug_level);
595 break;
596 #endif /* NDEBUG */
597 case '?':
598 default:
599 usage();
600 exit(1);
601 }
602 }
603 argc -= optind;
604 /* argv += optind; */
605
606 /* Commandline parse error */
607 if (argc != 0) {
608 usage();
609 exit(1);
610 }
611
612 if (strlen(nsd.identity) > UCHAR_MAX) {
613 error("server identity too long (%u characters)",
614 (unsigned) strlen(nsd.identity));
615 }
616 if(!tsig_init(nsd.region))
617 error("init tsig failed");
618
619 /* Read options */
620 nsd.options = nsd_options_create(region_create_custom(xalloc, free,
621 DEFAULT_CHUNK_SIZE, DEFAULT_LARGE_OBJECT_SIZE,
622 DEFAULT_INITIAL_CLEANUP_SIZE, 1));
623 if(!parse_options_file(nsd.options, configfile, NULL, NULL)) {
624 error("could not read config: %s\n", configfile);
625 }
626 if(!parse_zone_list_file(nsd.options)) {
627 error("could not read zonelist file %s\n",
628 nsd.options->zonelistfile);
629 }
630 if(nsd.options->do_ip4 && !nsd.options->do_ip6) {
631 hints[0].ai_family = AF_INET;
632 }
633 #ifdef INET6
634 if(nsd.options->do_ip6 && !nsd.options->do_ip4) {
635 hints[0].ai_family = AF_INET6;
636 }
637 #endif /* INET6 */
638 if(nsd.options->ip_addresses)
639 {
640 ip_address_option_type* ip = nsd.options->ip_addresses;
641 while(ip) {
642 add_interface(&nodes, &nsd, ip->address);
643 ip = ip->next;
644 }
645 }
646 if (verbosity == 0)
647 verbosity = nsd.options->verbosity;
648 #ifndef NDEBUG
649 if (nsd_debug_level > 0 && verbosity == 0)
650 verbosity = nsd_debug_level;
651 #endif /* NDEBUG */
652 if(nsd.options->debug_mode) nsd.debug=1;
653 if(!nsd.dbfile)
654 {
655 if(nsd.options->database)
656 nsd.dbfile = nsd.options->database;
657 else
658 nsd.dbfile = DBFILE;
659 }
660 if(!nsd.pidfile)
661 {
662 if(nsd.options->pidfile)
663 nsd.pidfile = nsd.options->pidfile;
664 else
665 nsd.pidfile = PIDFILE;
666 }
667 if(strcmp(nsd.identity, hostname)==0 || strcmp(nsd.identity,IDENTITY)==0)
668 {
669 if(nsd.options->identity)
670 nsd.identity = nsd.options->identity;
671 }
672 if(nsd.options->version) {
673 nsd.version = nsd.options->version;
674 }
675 if (nsd.options->logfile && !nsd.log_filename) {
676 nsd.log_filename = nsd.options->logfile;
677 }
678 if(nsd.child_count == 0) {
679 nsd.child_count = nsd.options->server_count;
680 }
681 #ifdef SO_REUSEPORT
682 if(nsd.options->reuseport && nsd.child_count > 1) {
683 nsd.reuseport = nsd.child_count;
684 }
685 #endif /* SO_REUSEPORT */
686 if(nsd.maximum_tcp_count == 0) {
687 nsd.maximum_tcp_count = nsd.options->tcp_count;
688 }
689 nsd.tcp_timeout = nsd.options->tcp_timeout;
690 nsd.tcp_query_count = nsd.options->tcp_query_count;
691 nsd.tcp_mss = nsd.options->tcp_mss;
692 nsd.outgoing_tcp_mss = nsd.options->outgoing_tcp_mss;
693 nsd.ipv4_edns_size = nsd.options->ipv4_edns_size;
694 nsd.ipv6_edns_size = nsd.options->ipv6_edns_size;
695
696 if(udp_port == 0)
697 {
698 if(nsd.options->port != 0) {
699 udp_port = nsd.options->port;
700 tcp_port = nsd.options->port;
701 } else {
702 udp_port = UDP_PORT;
703 tcp_port = TCP_PORT;
704 }
705 }
706 #ifdef BIND8_STATS
707 if(nsd.st.period == 0) {
708 nsd.st.period = nsd.options->statistics;
709 }
710 #endif /* BIND8_STATS */
711 #ifdef HAVE_CHROOT
712 if(nsd.chrootdir == 0) nsd.chrootdir = nsd.options->chroot;
713 #ifdef CHROOTDIR
714 /* if still no chrootdir, fallback to default */
715 if(nsd.chrootdir == 0) nsd.chrootdir = CHROOTDIR;
716 #endif /* CHROOTDIR */
717 #endif /* HAVE_CHROOT */
718 if(nsd.username == 0) {
719 if(nsd.options->username) nsd.username = nsd.options->username;
720 else nsd.username = USER;
721 }
722 if(nsd.options->zonesdir && nsd.options->zonesdir[0]) {
723 if(chdir(nsd.options->zonesdir)) {
724 error("cannot chdir to '%s': %s",
725 nsd.options->zonesdir, strerror(errno));
726 }
727 DEBUG(DEBUG_IPC,1, (LOG_INFO, "changed directory to %s",
728 nsd.options->zonesdir));
729 }
730
731 /* EDNS0 */
732 edns_init_data(&nsd.edns_ipv4, nsd.options->ipv4_edns_size);
733 #if defined(INET6)
734 #if defined(IPV6_USE_MIN_MTU) || defined(IPV6_MTU)
735 edns_init_data(&nsd.edns_ipv6, nsd.options->ipv6_edns_size);
736 #else /* no way to set IPV6 MTU, send no bigger than that. */
737 if (nsd.options->ipv6_edns_size < IPV6_MIN_MTU)
738 edns_init_data(&nsd.edns_ipv6, nsd.options->ipv6_edns_size);
739 else
740 edns_init_data(&nsd.edns_ipv6, IPV6_MIN_MTU);
741 #endif /* IPV6 MTU) */
742 #endif /* defined(INET6) */
743
744 if (nsd.nsid_len == 0 && nsd.options->nsid) {
745 if (strlen(nsd.options->nsid) % 2 != 0) {
746 error("the NSID must be a hex string of an even length.");
747 }
748 nsd.nsid = xalloc(strlen(nsd.options->nsid) / 2);
749 nsd.nsid_len = strlen(nsd.options->nsid) / 2;
750 if (hex_pton(nsd.options->nsid, nsd.nsid, nsd.nsid_len) == -1) {
751 error("hex string cannot be parsed '%s' in NSID.", nsd.options->nsid);
752 }
753 }
754 edns_init_nsid(&nsd.edns_ipv4, nsd.nsid_len);
755 #if defined(INET6)
756 edns_init_nsid(&nsd.edns_ipv6, nsd.nsid_len);
757 #endif /* defined(INET6) */
758
759 /* Number of child servers to fork. */
760 nsd.children = (struct nsd_child *) region_alloc_array(
761 nsd.region, nsd.child_count, sizeof(struct nsd_child));
762 for (i = 0; i < nsd.child_count; ++i) {
763 nsd.children[i].kind = NSD_SERVER_BOTH;
764 nsd.children[i].pid = -1;
765 nsd.children[i].child_fd = -1;
766 nsd.children[i].parent_fd = -1;
767 nsd.children[i].handler = NULL;
768 nsd.children[i].need_to_send_STATS = 0;
769 nsd.children[i].need_to_send_QUIT = 0;
770 nsd.children[i].need_to_exit = 0;
771 nsd.children[i].has_exited = 0;
772 #ifdef BIND8_STATS
773 nsd.children[i].query_count = 0;
774 #endif
775 }
776
777 nsd.this_child = NULL;
778
779 /* We need at least one active interface */
780 if (nsd.ifs == 0) {
781 add_interface(&nodes, &nsd, NULL);
782
783 /*
784 * With IPv6 we'd like to open two separate sockets,
785 * one for IPv4 and one for IPv6, both listening to
786 * the wildcard address (unless the -4 or -6 flags are
787 * specified).
788 *
789 * However, this is only supported on platforms where
790 * we can turn the socket option IPV6_V6ONLY _on_.
791 * Otherwise we just listen to a single IPv6 socket
792 * and any incoming IPv4 connections will be
793 * automatically mapped to our IPv6 socket.
794 */
795 #ifdef INET6
796 if (hints[0].ai_family == AF_UNSPEC) {
797 #ifdef IPV6_V6ONLY
798 add_interface(&nodes, &nsd, NULL);
799 hints[0].ai_family = AF_INET6;
800 hints[1].ai_family = AF_INET;
801 hints_in_use = 2;
802 nsd.grab_ip6_optional = 1;
803 #else /* !IPV6_V6ONLY */
804 hints[0].ai_family = AF_INET6;
805 #endif /* IPV6_V6ONLY */
806 }
807 #endif /* INET6 */
808 }
809
810 /* Set up the address info structures with real interface/port data */
811 assert(nodes);
812 for (i = 0; i < nsd.ifs; ++i) {
813 int r;
814 const char* node = NULL;
815 const char* service = NULL;
816 int h = ((hints_in_use == 1)?0:i%hints_in_use);
817
818 /* We don't perform name-lookups */
819 if (nodes[i] != NULL)
820 hints[h].ai_flags |= AI_NUMERICHOST;
821 get_ip_port_frm_str(nodes[i], &node, &service);
822
823 hints[h].ai_socktype = SOCK_DGRAM;
824 if ((r=getaddrinfo(node, (service?service:udp_port), &hints[h], &nsd.udp[i].addr)) != 0) {
825 #ifdef INET6
826 if(nsd.grab_ip6_optional && hints[0].ai_family == AF_INET6) {
827 log_msg(LOG_WARNING, "No IPv6, fallback to IPv4. getaddrinfo: %s",
828 r==EAI_SYSTEM?strerror(errno):gai_strerror(r));
829 continue;
830 }
831 #endif
832 error("cannot parse address '%s': getaddrinfo: %s %s",
833 nodes[i]?nodes[i]:"(null)",
834 gai_strerror(r),
835 r==EAI_SYSTEM?strerror(errno):"");
836 }
837
838 hints[h].ai_socktype = SOCK_STREAM;
839 if ((r=getaddrinfo(node, (service?service:tcp_port), &hints[h], &nsd.tcp[i].addr)) != 0) {
840 error("cannot parse address '%s': getaddrinfo: %s %s",
841 nodes[i]?nodes[i]:"(null)",
842 gai_strerror(r),
843 r==EAI_SYSTEM?strerror(errno):"");
844 }
845 }
846
847 /* Parse the username into uid and gid */
848 nsd.gid = getgid();
849 nsd.uid = getuid();
850 #ifdef HAVE_GETPWNAM
851 /* Parse the username into uid and gid */
852 if (*nsd.username) {
853 if (isdigit((unsigned char)*nsd.username)) {
854 char *t;
855 nsd.uid = strtol(nsd.username, &t, 10);
856 if (*t != 0) {
857 if (*t != '.' || !isdigit((unsigned char)*++t)) {
858 error("-u user or -u uid or -u uid.gid");
859 }
860 nsd.gid = strtol(t, &t, 10);
861 } else {
862 /* Lookup the group id in /etc/passwd */
863 if ((pwd = getpwuid(nsd.uid)) == NULL) {
864 error("user id %u does not exist.", (unsigned) nsd.uid);
865 } else {
866 nsd.gid = pwd->pw_gid;
867 }
868 }
869 } else {
870 /* Lookup the user id in /etc/passwd */
871 if ((pwd = getpwnam(nsd.username)) == NULL) {
872 error("user '%s' does not exist.", nsd.username);
873 } else {
874 nsd.uid = pwd->pw_uid;
875 nsd.gid = pwd->pw_gid;
876 }
877 }
878 }
879 /* endpwent(); */
880 #endif /* HAVE_GETPWNAM */
881
882 #if defined(HAVE_SSL)
883 key_options_tsig_add(nsd.options);
884 #endif
885
886 append_trailing_slash(&nsd.options->xfrdir, nsd.options->region);
887 /* Check relativity of pathnames to chroot */
888 if (nsd.chrootdir && nsd.chrootdir[0]) {
889 /* existing chrootdir: append trailing slash for strncmp checking */
890 append_trailing_slash(&nsd.chrootdir, nsd.region);
891 append_trailing_slash(&nsd.options->zonesdir, nsd.options->region);
892
893 /* zonesdir must be absolute and within chroot,
894 * all other pathnames may be relative to zonesdir */
895 if (strncmp(nsd.options->zonesdir, nsd.chrootdir, strlen(nsd.chrootdir)) != 0) {
896 error("zonesdir %s has to be an absolute path that starts with the chroot path %s",
897 nsd.options->zonesdir, nsd.chrootdir);
898 } else if (!file_inside_chroot(nsd.pidfile, nsd.chrootdir)) {
899 error("pidfile %s is not relative to %s: chroot not possible",
900 nsd.pidfile, nsd.chrootdir);
901 } else if (!file_inside_chroot(nsd.dbfile, nsd.chrootdir)) {
902 error("database %s is not relative to %s: chroot not possible",
903 nsd.dbfile, nsd.chrootdir);
904 } else if (!file_inside_chroot(nsd.options->xfrdfile, nsd.chrootdir)) {
905 error("xfrdfile %s is not relative to %s: chroot not possible",
906 nsd.options->xfrdfile, nsd.chrootdir);
907 } else if (!file_inside_chroot(nsd.options->zonelistfile, nsd.chrootdir)) {
908 error("zonelistfile %s is not relative to %s: chroot not possible",
909 nsd.options->zonelistfile, nsd.chrootdir);
910 } else if (!file_inside_chroot(nsd.options->xfrdir, nsd.chrootdir)) {
911 error("xfrdir %s is not relative to %s: chroot not possible",
912 nsd.options->xfrdir, nsd.chrootdir);
913 }
914 }
915
916 /* Set up the logging */
917 log_open(LOG_PID, FACILITY, nsd.log_filename);
918 if (!nsd.log_filename)
919 log_set_log_function(log_syslog);
920 else if (nsd.uid && nsd.gid) {
921 if(chown(nsd.log_filename, nsd.uid, nsd.gid) != 0)
922 VERBOSITY(2, (LOG_WARNING, "chown %s failed: %s",
923 nsd.log_filename, strerror(errno)));
924 }
925 log_msg(LOG_NOTICE, "%s starting (%s)", argv0, PACKAGE_STRING);
926
927 /* Do we have a running nsd? */
928 if ((oldpid = readpid(nsd.pidfile)) == -1) {
929 if (errno != ENOENT) {
930 log_msg(LOG_ERR, "can't read pidfile %s: %s",
931 nsd.pidfile, strerror(errno));
932 }
933 } else {
934 if (kill(oldpid, 0) == 0 || errno == EPERM) {
935 log_msg(LOG_WARNING,
936 "%s is already running as %u, continuing",
937 argv0, (unsigned) oldpid);
938 } else {
939 log_msg(LOG_ERR,
940 "...stale pid file from process %u",
941 (unsigned) oldpid);
942 }
943 }
944
945 /* Setup the signal handling... */
946 action.sa_handler = sig_handler;
947 sigfillset(&action.sa_mask);
948 action.sa_flags = 0;
949 sigaction(SIGTERM, &action, NULL);
950 sigaction(SIGHUP, &action, NULL);
951 sigaction(SIGINT, &action, NULL);
952 sigaction(SIGILL, &action, NULL);
953 sigaction(SIGUSR1, &action, NULL);
954 sigaction(SIGALRM, &action, NULL);
955 sigaction(SIGCHLD, &action, NULL);
956 action.sa_handler = SIG_IGN;
957 sigaction(SIGPIPE, &action, NULL);
958
959 /* Initialize... */
960 nsd.mode = NSD_RUN;
961 nsd.signal_hint_child = 0;
962 nsd.signal_hint_reload = 0;
963 nsd.signal_hint_reload_hup = 0;
964 nsd.signal_hint_quit = 0;
965 nsd.signal_hint_shutdown = 0;
966 nsd.signal_hint_stats = 0;
967 nsd.signal_hint_statsusr = 0;
968 nsd.quit_sync_done = 0;
969
970 /* Initialize the server... */
971 if (server_init(&nsd) != 0) {
972 error("server initialization failed, %s could "
973 "not be started", argv0);
974 }
975 #if defined(HAVE_SSL)
976 if(nsd.options->control_enable) {
977 /* read ssl keys while superuser and outside chroot */
978 if(!(nsd.rc = daemon_remote_create(nsd.options)))
979 error("could not perform remote control setup");
980 }
981 #endif /* HAVE_SSL */
982
983 /* Unless we're debugging, fork... */
984 if (!nsd.debug) {
985 int fd;
986
987 /* Take off... */
988 switch ((nsd.pid = fork())) {
989 case 0:
990 /* Child */
991 break;
992 case -1:
993 error("fork() failed: %s", strerror(errno));
994 break;
995 default:
996 /* Parent is done */
997 server_close_all_sockets(nsd.udp, nsd.ifs);
998 server_close_all_sockets(nsd.tcp, nsd.ifs);
999 exit(0);
1000 }
1001
1002 /* Detach ourselves... */
1003 if (setsid() == -1) {
1004 error("setsid() failed: %s", strerror(errno));
1005 }
1006
1007 if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
1008 (void)dup2(fd, STDIN_FILENO);
1009 (void)dup2(fd, STDOUT_FILENO);
1010 (void)dup2(fd, STDERR_FILENO);
1011 if (fd > 2)
1012 (void)close(fd);
1013 }
1014 }
1015
1016 /* Get our process id */
1017 nsd.pid = getpid();
1018
1019 /* Set user context */
1020 #ifdef HAVE_GETPWNAM
1021 if (*nsd.username) {
1022 #ifdef HAVE_SETUSERCONTEXT
1023 /* setusercontext does initgroups, setuid, setgid, and
1024 * also resource limits from login config, but we
1025 * still call setresuid, setresgid to be sure to set all uid */
1026 if (setusercontext(NULL, pwd, nsd.uid,
1027 LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0)
1028 log_msg(LOG_WARNING, "unable to setusercontext %s: %s",
1029 nsd.username, strerror(errno));
1030 #endif /* HAVE_SETUSERCONTEXT */
1031 }
1032 #endif /* HAVE_GETPWNAM */
1033
1034 /* Chroot */
1035 #ifdef HAVE_CHROOT
1036 if (nsd.chrootdir && nsd.chrootdir[0]) {
1037 int l = strlen(nsd.chrootdir)-1; /* ends in trailing slash */
1038
1039 if (file_inside_chroot(nsd.log_filename, nsd.chrootdir))
1040 nsd.file_rotation_ok = 1;
1041
1042 /* strip chroot from pathnames if they're absolute */
1043 nsd.options->zonesdir += l;
1044 if (nsd.log_filename){
1045 if (nsd.log_filename[0] == '/')
1046 nsd.log_filename += l;
1047 }
1048 if (nsd.pidfile[0] == '/')
1049 nsd.pidfile += l;
1050 if (nsd.dbfile[0] == '/')
1051 nsd.dbfile += l;
1052 if (nsd.options->xfrdfile[0] == '/')
1053 nsd.options->xfrdfile += l;
1054 if (nsd.options->zonelistfile[0] == '/')
1055 nsd.options->zonelistfile += l;
1056 if (nsd.options->xfrdir[0] == '/')
1057 nsd.options->xfrdir += l;
1058
1059 /* strip chroot from pathnames of "include:" statements
1060 * on subsequent repattern commands */
1061 cfg_parser->chroot = nsd.chrootdir;
1062
1063 #ifdef HAVE_TZSET
1064 /* set timezone whilst not yet in chroot */
1065 tzset();
1066 #endif
1067 if (chroot(nsd.chrootdir)) {
1068 error("unable to chroot: %s", strerror(errno));
1069 }
1070 if (chdir("/")) {
1071 error("unable to chdir to chroot: %s", strerror(errno));
1072 }
1073 DEBUG(DEBUG_IPC,1, (LOG_INFO, "changed root directory to %s",
1074 nsd.chrootdir));
1075 /* chdir to zonesdir again after chroot */
1076 if(nsd.options->zonesdir && nsd.options->zonesdir[0]) {
1077 if(chdir(nsd.options->zonesdir)) {
1078 error("unable to chdir to '%s': %s",
1079 nsd.options->zonesdir, strerror(errno));
1080 }
1081 DEBUG(DEBUG_IPC,1, (LOG_INFO, "changed directory to %s",
1082 nsd.options->zonesdir));
1083 }
1084 }
1085 else
1086 #endif /* HAVE_CHROOT */
1087 nsd.file_rotation_ok = 1;
1088
1089 DEBUG(DEBUG_IPC,1, (LOG_INFO, "file rotation on %s %sabled",
1090 nsd.log_filename, nsd.file_rotation_ok?"en":"dis"));
1091
1092 /* Write pidfile */
1093 if (writepid(&nsd) == -1) {
1094 log_msg(LOG_ERR, "cannot overwrite the pidfile %s: %s",
1095 nsd.pidfile, strerror(errno));
1096 }
1097
1098 /* Drop the permissions */
1099 #ifdef HAVE_GETPWNAM
1100 if (*nsd.username) {
1101 #ifdef HAVE_INITGROUPS
1102 if(initgroups(nsd.username, nsd.gid) != 0)
1103 log_msg(LOG_WARNING, "unable to initgroups %s: %s",
1104 nsd.username, strerror(errno));
1105 #endif /* HAVE_INITGROUPS */
1106 endpwent();
1107
1108 #ifdef HAVE_SETRESGID
1109 if(setresgid(nsd.gid,nsd.gid,nsd.gid) != 0)
1110 #elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID)
1111 if(setregid(nsd.gid,nsd.gid) != 0)
1112 #else /* use setgid */
1113 if(setgid(nsd.gid) != 0)
1114 #endif /* HAVE_SETRESGID */
1115 error("unable to set group id of %s: %s",
1116 nsd.username, strerror(errno));
1117
1118 #ifdef HAVE_SETRESUID
1119 if(setresuid(nsd.uid,nsd.uid,nsd.uid) != 0)
1120 #elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID)
1121 if(setreuid(nsd.uid,nsd.uid) != 0)
1122 #else /* use setuid */
1123 if(setuid(nsd.uid) != 0)
1124 #endif /* HAVE_SETRESUID */
1125 error("unable to set user id of %s: %s",
1126 nsd.username, strerror(errno));
1127
1128 DEBUG(DEBUG_IPC,1, (LOG_INFO, "dropped user privileges, run as %s",
1129 nsd.username));
1130 }
1131 #endif /* HAVE_GETPWNAM */
1132 xfrd_make_tempdir(&nsd);
1133 #ifdef USE_ZONE_STATS
1134 options_zonestatnames_create(nsd.options);
1135 server_zonestat_alloc(&nsd);
1136 #endif /* USE_ZONE_STATS */
1137
1138 if(nsd.server_kind == NSD_SERVER_MAIN) {
1139 server_prepare_xfrd(&nsd);
1140 /* xfrd forks this before reading database, so it does not get
1141 * the memory size of the database */
1142 server_start_xfrd(&nsd, 0, 0);
1143 /* close zonelistfile in non-xfrd processes */
1144 zone_list_close(nsd.options);
1145 }
1146 if (server_prepare(&nsd) != 0) {
1147 unlinkpid(nsd.pidfile);
1148 error("server preparation failed, %s could "
1149 "not be started", argv0);
1150 }
1151 if(nsd.server_kind == NSD_SERVER_MAIN) {
1152 server_send_soa_xfrd(&nsd, 0);
1153 }
1154
1155 /* Really take off */
1156 log_msg(LOG_NOTICE, "%s started (%s), pid %d",
1157 argv0, PACKAGE_STRING, (int) nsd.pid);
1158
1159 if (nsd.server_kind == NSD_SERVER_MAIN) {
1160 server_main(&nsd);
1161 } else {
1162 server_child(&nsd);
1163 }
1164
1165 /* NOTREACH */
1166 exit(0);
1167 }
1168