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