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