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