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