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