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