1 /* $NetBSD: main.c,v 1.18 2025/01/26 16:24:33 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /*! \file */ 17 18 #include <ctype.h> 19 #include <inttypes.h> 20 #include <locale.h> 21 #include <stdbool.h> 22 #include <stdlib.h> 23 #include <string.h> 24 25 #ifdef HAVE_DNSTAP 26 #include <protobuf-c/protobuf-c.h> 27 #endif 28 29 #include <isc/attributes.h> 30 #include <isc/backtrace.h> 31 #include <isc/commandline.h> 32 #include <isc/dir.h> 33 #include <isc/file.h> 34 #include <isc/fips.h> 35 #include <isc/hash.h> 36 #include <isc/httpd.h> 37 #include <isc/managers.h> 38 #include <isc/netmgr.h> 39 #include <isc/os.h> 40 #include <isc/result.h> 41 #include <isc/signal.h> 42 #include <isc/stdio.h> 43 #include <isc/string.h> 44 #include <isc/timer.h> 45 #include <isc/util.h> 46 #include <isc/uv.h> 47 #include <isc/xml.h> 48 49 #include <dns/dispatch.h> 50 #include <dns/dyndb.h> 51 #include <dns/name.h> 52 #include <dns/resolver.h> 53 #include <dns/view.h> 54 55 #include <dlz/dlz_dlopen_driver.h> 56 57 #ifdef HAVE_GPERFTOOLS_PROFILER 58 #include <gperftools/profiler.h> 59 #endif /* ifdef HAVE_GPERFTOOLS_PROFILER */ 60 61 #ifdef HAVE_JSON_C 62 #include <json_c_version.h> 63 #endif /* HAVE_JSON_C */ 64 65 #ifdef HAVE_GEOIP2 66 #include <maxminddb.h> 67 #endif /* ifdef HAVE_GEOIP2 */ 68 69 /* 70 * Defining NAMED_MAIN provides storage declarations (rather than extern) 71 * for variables in named/globals.h. 72 */ 73 #define NAMED_MAIN 1 74 75 #include <ns/interfacemgr.h> 76 77 #include <named/builtin.h> 78 #include <named/config.h> 79 #include <named/control.h> 80 #include <named/fuzz.h> 81 #include <named/globals.h> /* Explicit, though named/log.h includes it. */ 82 #include <named/log.h> 83 #include <named/main.h> 84 #include <named/os.h> 85 #include <named/server.h> 86 #ifdef HAVE_LIBSCF 87 #include <named/smf_globals.h> 88 #endif /* ifdef HAVE_LIBSCF */ 89 90 #include <openssl/crypto.h> 91 #include <openssl/evp.h> 92 #include <openssl/opensslv.h> 93 #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 94 #include <openssl/err.h> 95 #include <openssl/provider.h> 96 #endif 97 #ifdef HAVE_LIBXML2 98 #include <libxml/parser.h> 99 #include <libxml/xmlversion.h> 100 #endif /* ifdef HAVE_LIBXML2 */ 101 #ifdef HAVE_ZLIB 102 #include <zlib.h> 103 #endif /* ifdef HAVE_ZLIB */ 104 #ifdef HAVE_LIBNGHTTP2 105 #include <nghttp2/nghttp2.h> 106 #endif 107 108 /* On DragonFly BSD the header does not provide jemalloc API */ 109 #if defined(HAVE_MALLOC_NP_H) && !defined(__DragonFly__) 110 #include <malloc_np.h> 111 #include <sys/malloc.h> /* For M_VERSION */ 112 #elif defined(HAVE_JEMALLOC) 113 #include <jemalloc/jemalloc.h> 114 #endif 115 116 /* 117 * Include header files for database drivers here. 118 */ 119 /* #include "xxdb.h" */ 120 121 extern unsigned int dns_zone_mkey_hour; 122 extern unsigned int dns_zone_mkey_day; 123 extern unsigned int dns_zone_mkey_month; 124 125 static bool want_stats = false; 126 static char program_name[NAME_MAX] = "named"; 127 static char absolute_conffile[PATH_MAX]; 128 static char saved_command_line[4096] = { 0 }; 129 static char ellipsis[5] = { 0 }; 130 static char version[512]; 131 static int maxudp = 0; 132 133 /* 134 * -T options: 135 */ 136 static bool dropedns = false; 137 static bool ednsformerr = false; 138 static bool ednsnotimp = false; 139 static bool ednsrefused = false; 140 static bool fixedlocal = false; 141 static bool noaa = false; 142 static bool noedns = false; 143 static bool nonearest = false; 144 static bool nosoa = false; 145 static bool notcp = false; 146 static bool sigvalinsecs = false; 147 static bool transferinsecs = false; 148 static bool transferslowly = false; 149 static bool transferstuck = false; 150 151 /* 152 * -4 and -6 153 */ 154 static bool disable6 = false; 155 static bool disable4 = false; 156 157 #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 158 static OSSL_PROVIDER *fips = NULL, *base = NULL; 159 #endif 160 161 void 162 named_main_earlywarning(const char *format, ...) { 163 va_list args; 164 165 va_start(args, format); 166 if (named_g_lctx != NULL) { 167 isc_log_vwrite(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 168 NAMED_LOGMODULE_MAIN, ISC_LOG_WARNING, format, 169 args); 170 } else { 171 fprintf(stderr, "%s: ", program_name); 172 vfprintf(stderr, format, args); 173 fprintf(stderr, "\n"); 174 fflush(stderr); 175 } 176 va_end(args); 177 } 178 179 void 180 named_main_earlyfatal(const char *format, ...) { 181 va_list args; 182 183 va_start(args, format); 184 if (named_g_lctx != NULL) { 185 isc_log_vwrite(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 186 NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, format, 187 args); 188 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 189 NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, 190 "exiting (due to early fatal error)"); 191 } else { 192 fprintf(stderr, "%s: ", program_name); 193 vfprintf(stderr, format, args); 194 fprintf(stderr, "\n"); 195 fflush(stderr); 196 } 197 va_end(args); 198 199 _exit(EXIT_FAILURE); 200 } 201 202 noreturn static void 203 assertion_failed(const char *file, int line, isc_assertiontype_t type, 204 const char *cond); 205 206 static void 207 assertion_failed(const char *file, int line, isc_assertiontype_t type, 208 const char *cond) { 209 /* 210 * Handle assertion failures. 211 */ 212 213 if (named_g_lctx != NULL) { 214 /* 215 * Reset the assertion callback in case it is the log 216 * routines causing the assertion. 217 */ 218 isc_assertion_setcallback(NULL); 219 220 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 221 NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, 222 "%s:%d: %s(%s) failed", file, line, 223 isc_assertion_typetotext(type), cond); 224 isc_backtrace_log(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 225 NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL); 226 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 227 NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, 228 "exiting (due to assertion failure)"); 229 } else { 230 fprintf(stderr, "%s:%d: %s(%s) failed\n", file, line, 231 isc_assertion_typetotext(type), cond); 232 fflush(stderr); 233 } 234 235 if (named_g_coreok) { 236 abort(); 237 } 238 _exit(EXIT_FAILURE); 239 } 240 241 noreturn static void 242 library_fatal_error(const char *file, int line, const char *func, 243 const char *format, va_list args) ISC_FORMAT_PRINTF(3, 0); 244 245 static void 246 library_fatal_error(const char *file, int line, const char *func, 247 const char *format, va_list args) { 248 /* 249 * Handle isc_error_fatal() calls from our libraries. 250 */ 251 252 if (named_g_lctx != NULL) { 253 /* 254 * Reset the error callback in case it is the log 255 * routines causing the assertion. 256 */ 257 isc_error_setfatal(NULL); 258 259 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 260 NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, 261 "%s:%d:%s(): fatal error: ", file, line, func); 262 isc_log_vwrite(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 263 NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, format, 264 args); 265 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 266 NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, 267 "exiting (due to fatal error in library)"); 268 } else { 269 fprintf(stderr, "%s:%d:%s(): fatal error: ", file, line, func); 270 vfprintf(stderr, format, args); 271 fprintf(stderr, "\n"); 272 fflush(stderr); 273 } 274 275 if (named_g_coreok) { 276 abort(); 277 } 278 _exit(EXIT_FAILURE); 279 } 280 281 static void 282 library_unexpected_error(const char *file, int line, const char *func, 283 const char *format, va_list args) 284 ISC_FORMAT_PRINTF(3, 0); 285 286 static void 287 library_unexpected_error(const char *file, int line, const char *func, 288 const char *format, va_list args) { 289 /* 290 * Handle isc_error_unexpected() calls from our libraries. 291 */ 292 293 if (named_g_lctx != NULL) { 294 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 295 NAMED_LOGMODULE_MAIN, ISC_LOG_ERROR, 296 "%s:%d:%s(): unexpected error: ", file, line, 297 func); 298 isc_log_vwrite(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 299 NAMED_LOGMODULE_MAIN, ISC_LOG_ERROR, format, 300 args); 301 } else { 302 fprintf(stderr, "%s:%d:%s(): fatal error: ", file, line, func); 303 vfprintf(stderr, format, args); 304 fprintf(stderr, "\n"); 305 fflush(stderr); 306 } 307 } 308 309 static void 310 usage(void) { 311 fprintf(stderr, "usage: named [-4|-6] [-c conffile] [-d debuglevel] " 312 "[-D comment] [-E engine]\n" 313 " [-f|-g] [-L logfile] [-n number_of_cpus] " 314 "[-p port] [-s]\n" 315 " [-S sockets] [-t chrootdir] [-u " 316 "username] [-U listeners]\n" 317 " [-m " 318 "{usage|trace|record|size|mctx}]\n" 319 " [-M fill|nofill]\n" 320 "usage: named [-v|-V|-C]\n"); 321 } 322 323 static void 324 save_command_line(int argc, char *argv[]) { 325 int i; 326 char *dst = saved_command_line; 327 char *eob = saved_command_line + sizeof(saved_command_line) - 1; 328 char *rollback = dst; 329 330 for (i = 1; i < argc && dst < eob; i++) { 331 char *src = argv[i]; 332 bool quoted = false; 333 334 rollback = dst; 335 *dst++ = ' '; 336 337 while (*src != '\0' && dst < eob) { 338 if (isalnum(*(unsigned char *)src) || *src == ',' || 339 *src == '-' || *src == '_' || *src == '.' || 340 *src == '/') 341 { 342 *dst++ = *src++; 343 } else if (isprint(*(unsigned char *)src)) { 344 if (dst + 2 >= eob) { 345 goto add_ellipsis; 346 } 347 *dst++ = '\\'; 348 *dst++ = *src++; 349 } else { 350 /* 351 * Control character found in the input, 352 * quote the whole arg and restart 353 */ 354 if (!quoted) { 355 dst = rollback; 356 src = argv[i]; 357 358 if (dst + 3 >= eob) { 359 goto add_ellipsis; 360 } 361 362 *dst++ = ' '; 363 *dst++ = '$'; 364 *dst++ = '\''; 365 366 quoted = true; 367 continue; 368 } else { 369 char tmp[5]; 370 int c = snprintf(tmp, sizeof(tmp), 371 "\\%03o", *src++); 372 if (dst + c >= eob) { 373 goto add_ellipsis; 374 } 375 memmove(dst, tmp, c); 376 dst += c; 377 } 378 } 379 } 380 if (quoted) { 381 if (dst == eob) { 382 goto add_ellipsis; 383 } 384 *dst++ = '\''; 385 } 386 } 387 388 if (dst < eob) { 389 return; 390 } 391 add_ellipsis: 392 dst = rollback; 393 *dst = '\0'; 394 strlcpy(ellipsis, " ...", sizeof(ellipsis)); 395 } 396 397 static int 398 parse_int(char *arg, const char *desc) { 399 char *endp; 400 int tmp; 401 long int ltmp; 402 403 ltmp = strtol(arg, &endp, 10); 404 tmp = (int)ltmp; 405 if (*endp != '\0') { 406 named_main_earlyfatal("%s '%s' must be numeric", desc, arg); 407 } 408 if (tmp < 0 || tmp != ltmp) { 409 named_main_earlyfatal("%s '%s' out of range", desc, arg); 410 } 411 return tmp; 412 } 413 414 static struct flag_def { 415 const char *name; 416 unsigned int value; 417 bool negate; 418 } mem_debug_flags[] = { { "none", 0, false }, 419 { "trace", ISC_MEM_DEBUGTRACE, false }, 420 { "record", ISC_MEM_DEBUGRECORD, false }, 421 { "usage", ISC_MEM_DEBUGUSAGE, false }, 422 { NULL, 0, false } }, 423 mem_context_flags[] = { { "fill", ISC_MEMFLAG_FILL, false }, 424 { "nofill", ISC_MEMFLAG_FILL, true }, 425 { NULL, 0, false } }; 426 427 static void 428 set_flags(const char *arg, struct flag_def *defs, unsigned int *ret) { 429 bool clear = false; 430 431 for (;;) { 432 const struct flag_def *def; 433 const char *end = strchr(arg, ','); 434 int arglen; 435 if (end == NULL) { 436 end = arg + strlen(arg); 437 } 438 arglen = (int)(end - arg); 439 for (def = defs; def->name != NULL; def++) { 440 if (arglen == (int)strlen(def->name) && 441 memcmp(arg, def->name, arglen) == 0) 442 { 443 if (def->value == 0) { 444 clear = true; 445 } 446 if (def->negate) { 447 *ret &= ~(def->value); 448 } else { 449 *ret |= def->value; 450 } 451 goto found; 452 } 453 } 454 named_main_earlyfatal("unrecognized flag '%.*s'", arglen, arg); 455 found: 456 if (clear || (*end == '\0')) { 457 break; 458 } 459 arg = end + 1; 460 } 461 462 if (clear) { 463 *ret = 0; 464 } 465 } 466 467 static void 468 list_dnssec_algorithms(isc_buffer_t *b) { 469 for (dst_algorithm_t i = DST_ALG_UNKNOWN; i < DST_MAX_ALGS; i++) { 470 if (i == DST_ALG_GSSAPI || 471 (i >= DST_ALG_HMAC_FIRST && i <= DST_ALG_HMAC_LAST)) 472 { 473 continue; 474 } 475 if (dst_algorithm_supported(i)) { 476 isc_buffer_putstr(b, " "); 477 (void)dns_secalg_totext(i, b); 478 } 479 } 480 } 481 482 static void 483 list_ds_algorithms(isc_buffer_t *b) { 484 for (size_t i = 0; i < 256; i++) { 485 if (dst_ds_digest_supported(i)) { 486 isc_buffer_putstr(b, " "); 487 (void)dns_dsdigest_totext(i, b); 488 } 489 } 490 } 491 492 static void 493 list_hmac_algorithms(isc_buffer_t *b) { 494 isc_buffer_t sb = *b; 495 for (dst_algorithm_t i = DST_ALG_HMAC_FIRST; i <= DST_ALG_HMAC_LAST; 496 i++) 497 { 498 if (i == DST_ALG_GSSAPI) { 499 continue; 500 } 501 if (dst_algorithm_supported(i)) { 502 isc_buffer_putstr(b, " "); 503 isc_buffer_putstr(b, dst_hmac_algorithm_totext(i)); 504 } 505 } 506 for (unsigned char *s = isc_buffer_used(&sb); s != isc_buffer_used(b); 507 s++) 508 { 509 *s = toupper(*s); 510 } 511 } 512 513 static void 514 logit(isc_buffer_t *b) { 515 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 516 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "%.*s", 517 (int)isc_buffer_usedlength(b), 518 (char *)isc_buffer_base(b)); 519 } 520 521 static void 522 printit(isc_buffer_t *b) { 523 printf("%.*s\n", (int)isc_buffer_usedlength(b), 524 (char *)isc_buffer_base(b)); 525 } 526 527 static void 528 format_supported_algorithms(void (*emit)(isc_buffer_t *b)) { 529 isc_buffer_t b; 530 char buf[512]; 531 532 isc_buffer_init(&b, buf, sizeof(buf)); 533 isc_buffer_putstr(&b, "DNSSEC algorithms:"); 534 list_dnssec_algorithms(&b); 535 (*emit)(&b); 536 537 isc_buffer_init(&b, buf, sizeof(buf)); 538 isc_buffer_putstr(&b, "DS algorithms:"); 539 list_ds_algorithms(&b); 540 (*emit)(&b); 541 542 isc_buffer_init(&b, buf, sizeof(buf)); 543 isc_buffer_putstr(&b, "HMAC algorithms:"); 544 list_hmac_algorithms(&b); 545 (*emit)(&b); 546 547 isc_buffer_init(&b, buf, sizeof(buf)); 548 isc_buffer_printf(&b, "TKEY mode 2 support (Diffie-Hellman): %s", "no"); 549 (*emit)(&b); 550 551 isc_buffer_init(&b, buf, sizeof(buf)); 552 isc_buffer_printf(&b, "TKEY mode 3 support (GSS-API): %s", 553 dst_algorithm_supported(DST_ALG_GSSAPI) ? "yes" 554 : "no"); 555 (*emit)(&b); 556 } 557 558 static void 559 printversion(bool verbose) { 560 char rndcconf[PATH_MAX], *dot = NULL; 561 isc_mem_t *mctx = NULL; 562 isc_result_t result; 563 isc_buffer_t b; 564 char buf[512]; 565 #if defined(HAVE_GEOIP2) 566 cfg_parser_t *parser = NULL; 567 cfg_obj_t *config = NULL; 568 const cfg_obj_t *defaults = NULL, *obj = NULL; 569 #endif /* if defined(HAVE_GEOIP2) */ 570 571 printf("%s%s <id:%s>\n", PACKAGE_STRING, PACKAGE_DESCRIPTION, 572 PACKAGE_SRCID); 573 574 if (!verbose) { 575 return; 576 } 577 578 printf("running on %s\n", named_os_uname()); 579 printf("built by %s with %s\n", PACKAGE_BUILDER, PACKAGE_CONFIGARGS); 580 #ifdef __clang__ 581 printf("compiled by CLANG %s\n", __VERSION__); 582 #else /* ifdef __clang__ */ 583 #if defined(__ICC) || defined(__INTEL_COMPILER) 584 printf("compiled by ICC %s\n", __VERSION__); 585 #else /* if defined(__ICC) || defined(__INTEL_COMPILER) */ 586 #ifdef __GNUC__ 587 printf("compiled by GCC %s\n", __VERSION__); 588 #endif /* ifdef __GNUC__ */ 589 #endif /* if defined(__ICC) || defined(__INTEL_COMPILER) */ 590 #endif /* ifdef __clang__ */ 591 #ifdef __SUNPRO_C 592 printf("compiled by Solaris Studio %x\n", __SUNPRO_C); 593 #endif /* ifdef __SUNPRO_C */ 594 printf("compiled with OpenSSL version: %s\n", OPENSSL_VERSION_TEXT); 595 #if !defined(LIBRESSL_VERSION_NUMBER) && \ 596 OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 or higher */ 597 printf("linked to OpenSSL version: %s\n", 598 OpenSSL_version(OPENSSL_VERSION)); 599 600 #else /* if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= \ 601 * 0x10100000L */ 602 printf("linked to OpenSSL version: %s\n", 603 SSLeay_version(SSLEAY_VERSION)); 604 #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ 605 printf("compiled with libuv version: %d.%d.%d\n", UV_VERSION_MAJOR, 606 UV_VERSION_MINOR, UV_VERSION_PATCH); 607 printf("linked to libuv version: %s\n", uv_version_string()); 608 printf("compiled with %s version: %s\n", RCU_FLAVOR, RCU_VERSION); 609 #if defined(JEMALLOC_VERSION) 610 printf("compiled with jemalloc version: %u.%u.%u\n", 611 JEMALLOC_VERSION_MAJOR, JEMALLOC_VERSION_MINOR, 612 JEMALLOC_VERSION_BUGFIX); 613 #elif defined(M_VERSION) 614 printf("compiled with system jemalloc version: %u\n", M_VERSION); 615 #endif 616 #if HAVE_LIBNGHTTP2 617 nghttp2_info *nginfo = NULL; 618 printf("compiled with libnghttp2 version: %s\n", NGHTTP2_VERSION); 619 nginfo = nghttp2_version(1); 620 printf("linked to libnghttp2 version: %s\n", nginfo->version_str); 621 #endif 622 #ifdef HAVE_LIBXML2 623 printf("compiled with libxml2 version: %s\n", LIBXML_DOTTED_VERSION); 624 printf("linked to libxml2 version: %s\n", xmlParserVersion); 625 #endif /* ifdef HAVE_LIBXML2 */ 626 #if defined(HAVE_JSON_C) 627 printf("compiled with json-c version: %s\n", JSON_C_VERSION); 628 printf("linked to json-c version: %s\n", json_c_version()); 629 #endif /* if defined(HAVE_JSON_C) */ 630 #if defined(HAVE_ZLIB) && defined(ZLIB_VERSION) 631 printf("compiled with zlib version: %s\n", ZLIB_VERSION); 632 printf("linked to zlib version: %s\n", zlibVersion()); 633 #endif /* if defined(HAVE_ZLIB) && defined(ZLIB_VERSION) */ 634 #if defined(HAVE_GEOIP2) 635 /* Unfortunately, no version define on link time */ 636 printf("linked to maxminddb version: %s\n", MMDB_lib_version()); 637 #endif /* if defined(HAVE_GEOIP2) */ 638 #if defined(HAVE_DNSTAP) 639 printf("compiled with protobuf-c version: %s\n", PROTOBUF_C_VERSION); 640 printf("linked to protobuf-c version: %s\n", protobuf_c_version()); 641 #endif /* if defined(HAVE_DNSTAP) */ 642 printf("threads support is enabled\n"); 643 644 isc_mem_create(&mctx); 645 result = dst_lib_init(mctx, named_g_engine); 646 if (result == ISC_R_SUCCESS) { 647 isc_buffer_init(&b, buf, sizeof(buf)); 648 format_supported_algorithms(printit); 649 printf("\n"); 650 dst_lib_destroy(); 651 } else { 652 printf("DST initialization failure: %s\n", 653 isc_result_totext(result)); 654 } 655 656 /* 657 * The default rndc.conf and rndc.key paths are in the same 658 * directory, but named only has rndc.key defined internally. 659 * We construct the rndc.conf path from it. 660 */ 661 strlcpy(rndcconf, named_g_keyfile, sizeof(rndcconf)); 662 dot = strrchr(rndcconf, '.'); 663 if (dot != NULL) { 664 size_t len = dot - rndcconf + 1; 665 snprintf(dot + 1, PATH_MAX - len, "conf"); 666 } 667 668 /* 669 * Print default configuration paths. 670 */ 671 printf("default paths:\n"); 672 printf(" named configuration: %s\n", named_g_conffile); 673 printf(" rndc configuration: %s\n", rndcconf); 674 printf(" nsupdate session key: %s\n", named_g_defaultsessionkeyfile); 675 printf(" named PID file: %s\n", named_g_defaultpidfile); 676 #if defined(HAVE_GEOIP2) 677 #define RTC(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS) 678 RTC(cfg_parser_create(mctx, named_g_lctx, &parser)); 679 RTC(named_config_parsedefaults(parser, &config)); 680 RTC(cfg_map_get(config, "options", &defaults)); 681 RTC(cfg_map_get(defaults, "geoip-directory", &obj)); 682 if (cfg_obj_isstring(obj)) { 683 printf(" geoip-directory: %s\n", cfg_obj_asstring(obj)); 684 } 685 cfg_obj_destroy(parser, &config); 686 cfg_parser_destroy(&parser); 687 isc_mem_detach(&mctx); 688 #endif /* HAVE_GEOIP2 */ 689 } 690 691 static void 692 parse_fuzz_arg(void) { 693 if (!strncmp(isc_commandline_argument, "client:", 7)) { 694 named_g_fuzz_addr = isc_commandline_argument + 7; 695 named_g_fuzz_type = isc_fuzz_client; 696 } else if (!strncmp(isc_commandline_argument, "tcp:", 4)) { 697 named_g_fuzz_addr = isc_commandline_argument + 4; 698 named_g_fuzz_type = isc_fuzz_tcpclient; 699 } else if (!strncmp(isc_commandline_argument, "resolver:", 9)) { 700 named_g_fuzz_addr = isc_commandline_argument + 9; 701 named_g_fuzz_type = isc_fuzz_resolver; 702 } else if (!strncmp(isc_commandline_argument, "http:", 5)) { 703 named_g_fuzz_addr = isc_commandline_argument + 5; 704 named_g_fuzz_type = isc_fuzz_http; 705 } else if (!strncmp(isc_commandline_argument, "rndc:", 5)) { 706 named_g_fuzz_addr = isc_commandline_argument + 5; 707 named_g_fuzz_type = isc_fuzz_rndc; 708 } else { 709 named_main_earlyfatal("unknown fuzzing type '%s'", 710 isc_commandline_argument); 711 } 712 } 713 714 static void 715 parse_T_opt(char *option) { 716 const char *p; 717 char *last = NULL; 718 /* 719 * force the server to behave (or misbehave) in 720 * specified ways for testing purposes. 721 */ 722 if (!strcmp(option, "dropedns")) { 723 dropedns = true; 724 } else if (!strcmp(option, "ednsformerr")) { 725 ednsformerr = true; 726 } else if (!strcmp(option, "ednsnotimp")) { 727 ednsnotimp = true; 728 } else if (!strcmp(option, "ednsrefused")) { 729 ednsrefused = true; 730 } else if (!strcmp(option, "fixedlocal")) { 731 fixedlocal = true; 732 } else if (!strcmp(option, "keepstderr")) { 733 named_g_keepstderr = true; 734 } else if (!strcmp(option, "noaa")) { 735 noaa = true; 736 } else if (!strcmp(option, "noedns")) { 737 noedns = true; 738 } else if (!strcmp(option, "nonearest")) { 739 nonearest = true; 740 } else if (!strcmp(option, "nosoa")) { 741 nosoa = true; 742 } else if (!strcmp(option, "nosyslog")) { 743 named_g_nosyslog = true; 744 } else if (!strcmp(option, "notcp")) { 745 notcp = true; 746 } else if (!strncmp(option, "maxcachesize=", 13)) { 747 named_g_maxcachesize = atoi(option + 13); 748 } else if (!strcmp(option, "maxudp512")) { 749 maxudp = 512; 750 } else if (!strcmp(option, "maxudp1460")) { 751 maxudp = 1460; 752 } else if (!strncmp(option, "maxudp=", 7)) { 753 maxudp = atoi(option + 7); 754 if (maxudp <= 0) { 755 named_main_earlyfatal("bad maxudp"); 756 } 757 } else if (!strncmp(option, "mkeytimers=", 11)) { 758 p = strtok_r(option + 11, "/", &last); 759 if (p == NULL) { 760 named_main_earlyfatal("bad mkeytimer"); 761 } 762 763 dns_zone_mkey_hour = atoi(p); 764 if (dns_zone_mkey_hour == 0) { 765 named_main_earlyfatal("bad mkeytimer"); 766 } 767 768 p = strtok_r(NULL, "/", &last); 769 if (p == NULL) { 770 dns_zone_mkey_day = (24 * dns_zone_mkey_hour); 771 dns_zone_mkey_month = (30 * dns_zone_mkey_day); 772 return; 773 } 774 775 dns_zone_mkey_day = atoi(p); 776 if (dns_zone_mkey_day < dns_zone_mkey_hour) { 777 named_main_earlyfatal("bad mkeytimer"); 778 } 779 780 p = strtok_r(NULL, "/", &last); 781 if (p == NULL) { 782 dns_zone_mkey_month = (30 * dns_zone_mkey_day); 783 return; 784 } 785 786 dns_zone_mkey_month = atoi(p); 787 if (dns_zone_mkey_month < dns_zone_mkey_day) { 788 named_main_earlyfatal("bad mkeytimer"); 789 } 790 } else if (!strcmp(option, "sigvalinsecs")) { 791 sigvalinsecs = true; 792 } else if (!strcmp(option, "transferinsecs")) { 793 transferinsecs = true; 794 } else if (!strcmp(option, "transferslowly")) { 795 transferslowly = true; 796 } else if (!strcmp(option, "transferstuck")) { 797 transferstuck = true; 798 } else if (!strncmp(option, "tat=", 4)) { 799 named_g_tat_interval = atoi(option + 4); 800 } else { 801 fprintf(stderr, "unknown -T flag '%s'\n", option); 802 } 803 } 804 805 static void 806 parse_port(char *arg) { 807 enum { DNSPORT, TLSPORT, HTTPSPORT, HTTPPORT } ptype = DNSPORT; 808 char *value = arg; 809 int port; 810 811 if (strncmp(arg, "dns=", 4) == 0) { 812 value = arg + 4; 813 } else if (strncmp(arg, "tls=", 4) == 0) { 814 value = arg + 4; 815 ptype = TLSPORT; 816 } else if (strncmp(arg, "https=", 6) == 0) { 817 value = arg + 6; 818 ptype = HTTPSPORT; 819 } else if (strncmp(arg, "http=", 5) == 0) { 820 value = arg + 6; 821 ptype = HTTPPORT; 822 } 823 824 port = parse_int(value, "port"); 825 if (port < 1 || port > 65535) { 826 named_main_earlyfatal("port '%s' out of range", value); 827 } 828 829 switch (ptype) { 830 case DNSPORT: 831 named_g_port = port; 832 break; 833 case TLSPORT: 834 named_g_tlsport = port; 835 break; 836 case HTTPSPORT: 837 named_g_httpsport = port; 838 break; 839 case HTTPPORT: 840 named_g_httpport = port; 841 break; 842 default: 843 UNREACHABLE(); 844 } 845 } 846 847 static void 848 parse_command_line(int argc, char *argv[]) { 849 int ch; 850 const char *p; 851 852 save_command_line(argc, argv); 853 854 /* 855 * NAMED_MAIN_ARGS is defined in main.h, so that it can be used 856 * both by named and by ntservice hooks. 857 */ 858 isc_commandline_errprint = false; 859 while ((ch = isc_commandline_parse(argc, argv, NAMED_MAIN_ARGS)) != -1) 860 { 861 switch (ch) { 862 case '4': 863 if (disable4) { 864 named_main_earlyfatal("cannot specify " 865 "-4 and -6"); 866 } 867 if (isc_net_probeipv4() != ISC_R_SUCCESS) { 868 named_main_earlyfatal("IPv4 not supported " 869 "by OS"); 870 } 871 isc_net_disableipv6(); 872 disable6 = true; 873 break; 874 case '6': 875 if (disable6) { 876 named_main_earlyfatal("cannot specify " 877 "-4 and -6"); 878 } 879 if (isc_net_probeipv6() != ISC_R_SUCCESS) { 880 named_main_earlyfatal("IPv6 not supported " 881 "by OS"); 882 } 883 isc_net_disableipv4(); 884 disable4 = true; 885 break; 886 case 'A': 887 parse_fuzz_arg(); 888 break; 889 case 'c': 890 named_g_conffile = isc_commandline_argument; 891 named_g_conffileset = true; 892 break; 893 case 'C': 894 printf("# Built-in default values. " 895 "This is NOT the run-time configuration!\n"); 896 printf("%s", named_config_getdefault()); 897 exit(EXIT_SUCCESS); 898 case 'd': 899 named_g_debuglevel = parse_int(isc_commandline_argument, 900 "debug " 901 "level"); 902 break; 903 case 'D': 904 /* Descriptive comment for 'ps'. */ 905 break; 906 case 'E': 907 named_g_engine = isc_commandline_argument; 908 break; 909 case 'f': 910 named_g_foreground = true; 911 break; 912 case 'g': 913 named_g_foreground = true; 914 named_g_logstderr = true; 915 break; 916 case 'L': 917 named_g_logfile = isc_commandline_argument; 918 break; 919 case 'M': 920 set_flags(isc_commandline_argument, mem_context_flags, 921 &isc_mem_defaultflags); 922 break; 923 case 'm': 924 set_flags(isc_commandline_argument, mem_debug_flags, 925 &isc_mem_debugging); 926 break; 927 case 'N': /* Deprecated. */ 928 case 'n': 929 named_g_cpus = parse_int(isc_commandline_argument, 930 "number of cpus"); 931 if (named_g_cpus == 0) { 932 named_g_cpus = 1; 933 } 934 break; 935 case 'p': 936 parse_port(isc_commandline_argument); 937 break; 938 case 's': 939 /* XXXRTH temporary syntax */ 940 want_stats = true; 941 break; 942 case 'S': 943 /* Formerly maxsocks */ 944 break; 945 case 't': 946 /* XXXJAB should we make a copy? */ 947 named_g_chrootdir = isc_commandline_argument; 948 break; 949 case 'T': /* NOT DOCUMENTED */ 950 parse_T_opt(isc_commandline_argument); 951 break; 952 case 'U': 953 /* Obsolete. No longer in use. Ignore. */ 954 named_main_earlywarning("option '-U' has been removed"); 955 break; 956 case 'u': 957 named_g_username = isc_commandline_argument; 958 break; 959 case 'v': 960 printversion(false); 961 exit(EXIT_SUCCESS); 962 case 'V': 963 printversion(true); 964 exit(EXIT_SUCCESS); 965 case 'x': 966 /* Obsolete. No longer in use. Ignore. */ 967 break; 968 case 'X': 969 /* Obsolete. No longer in use. Abort. */ 970 named_main_earlyfatal("option '-X' has been removed"); 971 break; 972 case 'F': 973 #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 974 fips = OSSL_PROVIDER_load(NULL, "fips"); 975 if (fips == NULL) { 976 ERR_clear_error(); 977 named_main_earlyfatal( 978 "Failed to load FIPS provider"); 979 } 980 base = OSSL_PROVIDER_load(NULL, "base"); 981 if (base == NULL) { 982 OSSL_PROVIDER_unload(fips); 983 ERR_clear_error(); 984 named_main_earlyfatal( 985 "Failed to load base provider"); 986 } 987 #endif 988 if (isc_fips_mode()) { /* Already in FIPS mode. */ 989 break; 990 } 991 if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { 992 named_main_earlyfatal( 993 "setting FIPS mode failed"); 994 } 995 break; 996 case '?': 997 usage(); 998 if (isc_commandline_option == '?') { 999 exit(EXIT_SUCCESS); 1000 } 1001 p = strchr(NAMED_MAIN_ARGS, isc_commandline_option); 1002 if (p == NULL || *++p != ':') { 1003 named_main_earlyfatal("unknown option '-%c'", 1004 isc_commandline_option); 1005 } else { 1006 named_main_earlyfatal("option '-%c' requires " 1007 "an argument", 1008 isc_commandline_option); 1009 } 1010 FALLTHROUGH; 1011 default: 1012 named_main_earlyfatal("parsing options returned %d", 1013 ch); 1014 } 1015 } 1016 1017 argc -= isc_commandline_index; 1018 argv += isc_commandline_index; 1019 POST(argv); 1020 1021 if (argc > 0) { 1022 usage(); 1023 named_main_earlyfatal("extra command line arguments"); 1024 } 1025 } 1026 1027 static isc_result_t 1028 create_managers(void) { 1029 /* 1030 * Set the default named_g_cpus if it was not set from the command line 1031 */ 1032 INSIST(named_g_cpus_detected > 0); 1033 if (named_g_cpus == 0) { 1034 named_g_cpus = named_g_cpus_detected; 1035 } 1036 1037 isc_log_write( 1038 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, 1039 ISC_LOG_INFO, "found %u CPU%s, using %u worker thread%s", 1040 named_g_cpus_detected, named_g_cpus_detected == 1 ? "" : "s", 1041 named_g_cpus, named_g_cpus == 1 ? "" : "s"); 1042 1043 isc_managers_create(&named_g_mctx, named_g_cpus, &named_g_loopmgr, 1044 &named_g_netmgr); 1045 1046 isc_nm_maxudp(named_g_netmgr, maxudp); 1047 1048 return ISC_R_SUCCESS; 1049 } 1050 1051 static void 1052 setup(void) { 1053 isc_result_t result; 1054 ns_server_t *sctx; 1055 #ifdef HAVE_LIBSCF 1056 char *instance = NULL; 1057 #endif /* ifdef HAVE_LIBSCF */ 1058 1059 /* 1060 * Get the user and group information before changing the root 1061 * directory, so the administrator does not need to keep a copy 1062 * of the user and group databases in the chroot'ed environment. 1063 */ 1064 named_os_inituserinfo(named_g_username); 1065 1066 /* 1067 * Initialize time conversion information 1068 */ 1069 named_os_tzset(); 1070 1071 named_os_opendevnull(); 1072 1073 #ifdef HAVE_LIBSCF 1074 /* Check if named is under smf control, before chroot. */ 1075 result = named_smf_get_instance(&instance, 0, named_g_mctx); 1076 /* We don't care about instance, just check if we got one. */ 1077 if (result == ISC_R_SUCCESS) { 1078 named_smf_got_instance = 1; 1079 } else { 1080 named_smf_got_instance = 0; 1081 } 1082 if (instance != NULL) { 1083 isc_mem_free(named_g_mctx, instance); 1084 } 1085 #endif /* HAVE_LIBSCF */ 1086 1087 /* 1088 * Check for the number of cpu's before named_os_chroot(). 1089 */ 1090 named_g_cpus_detected = isc_os_ncpus(); 1091 1092 named_os_chroot(named_g_chrootdir); 1093 1094 /* 1095 * For operating systems which have a capability mechanism, now 1096 * is the time to switch to minimal privs and change our user id. 1097 * On traditional UNIX systems, this call will be a no-op, and we 1098 * will change the user ID after reading the config file the first 1099 * time. (We need to read the config file to know which possibly 1100 * privileged ports to bind() to.) 1101 */ 1102 named_os_minprivs(); 1103 1104 result = named_log_init(named_g_username != NULL); 1105 if (result != ISC_R_SUCCESS) { 1106 named_main_earlyfatal("named_log_init() failed: %s", 1107 isc_result_totext(result)); 1108 } 1109 1110 /* 1111 * Now is the time to daemonize (if we're not running in the 1112 * foreground). We waited until now because we wanted to get 1113 * a valid logging context setup. We cannot daemonize any later, 1114 * because calling create_managers() will create threads, which 1115 * would be lost after fork(). 1116 */ 1117 if (!named_g_foreground) { 1118 named_os_daemonize(); 1119 } 1120 1121 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1122 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1123 "starting %s%s <id:%s>", PACKAGE_STRING, 1124 PACKAGE_DESCRIPTION, PACKAGE_SRCID); 1125 1126 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1127 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "running on %s", 1128 named_os_uname()); 1129 1130 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1131 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "built with %s", 1132 PACKAGE_CONFIGARGS); 1133 1134 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1135 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1136 "running as: %s%s%s", program_name, saved_command_line, 1137 ellipsis); 1138 #ifdef __clang__ 1139 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1140 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1141 "compiled by CLANG %s", __VERSION__); 1142 #else /* ifdef __clang__ */ 1143 #if defined(__ICC) || defined(__INTEL_COMPILER) 1144 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1145 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1146 "compiled by ICC %s", __VERSION__); 1147 #else /* if defined(__ICC) || defined(__INTEL_COMPILER) */ 1148 #ifdef __GNUC__ 1149 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1150 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1151 "compiled by GCC %s", __VERSION__); 1152 #endif /* ifdef __GNUC__ */ 1153 #endif /* if defined(__ICC) || defined(__INTEL_COMPILER) */ 1154 #endif /* ifdef __clang__ */ 1155 #ifdef __SUNPRO_C 1156 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1157 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1158 "compiled by Solaris Studio %x", __SUNPRO_C); 1159 #endif /* ifdef __SUNPRO_C */ 1160 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1161 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1162 "compiled with OpenSSL version: %s", 1163 OPENSSL_VERSION_TEXT); 1164 #if !defined(LIBRESSL_VERSION_NUMBER) && \ 1165 OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 or higher */ 1166 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1167 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1168 "linked to OpenSSL version: %s", 1169 OpenSSL_version(OPENSSL_VERSION)); 1170 #else /* if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= \ 1171 * 0x10100000L */ 1172 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1173 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1174 "linked to OpenSSL version: %s", 1175 SSLeay_version(SSLEAY_VERSION)); 1176 #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ 1177 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1178 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1179 "compiled with libuv version: %d.%d.%d", UV_VERSION_MAJOR, 1180 UV_VERSION_MINOR, UV_VERSION_PATCH); 1181 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1182 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1183 "linked to libuv version: %s", uv_version_string()); 1184 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1185 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1186 "compiled with %s version: %s", RCU_FLAVOR, RCU_VERSION); 1187 #if defined(JEMALLOC_VERSION) 1188 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1189 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1190 "compiled with jemalloc version: %u.%u.%u", 1191 JEMALLOC_VERSION_MAJOR, JEMALLOC_VERSION_MINOR, 1192 JEMALLOC_VERSION_BUGFIX); 1193 #elif defined(M_VERSION) 1194 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1195 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1196 "compiled with system jemalloc version: %u", M_VERSION); 1197 #endif 1198 #if HAVE_LIBNGHTTP2 1199 nghttp2_info *nginfo = NULL; 1200 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1201 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1202 "compiled with libnghttp2 version: %s", NGHTTP2_VERSION); 1203 nginfo = nghttp2_version(1); 1204 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1205 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1206 "linked to libnghttp2 version: %s", nginfo->version_str); 1207 #endif 1208 #ifdef HAVE_LIBXML2 1209 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1210 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1211 "compiled with libxml2 version: %s", 1212 LIBXML_DOTTED_VERSION); 1213 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1214 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1215 "linked to libxml2 version: %s", xmlParserVersion); 1216 #endif /* ifdef HAVE_LIBXML2 */ 1217 #if defined(HAVE_JSON_C) 1218 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1219 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1220 "compiled with json-c version: %s", JSON_C_VERSION); 1221 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1222 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1223 "linked to json-c version: %s", json_c_version()); 1224 #endif /* if defined(HAVE_JSON_C) */ 1225 #if defined(HAVE_ZLIB) && defined(ZLIB_VERSION) 1226 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1227 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1228 "compiled with zlib version: %s", ZLIB_VERSION); 1229 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1230 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1231 "linked to zlib version: %s", zlibVersion()); 1232 #endif /* if defined(HAVE_ZLIB) && defined(ZLIB_VERSION) */ 1233 #if defined(HAVE_GEOIP2) 1234 /* Unfortunately, no version define on link time */ 1235 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1236 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1237 "linked to maxminddb version: %s", MMDB_lib_version()); 1238 #endif /* if defined(HAVE_GEOIP2) */ 1239 #if defined(HAVE_DNSTAP) 1240 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1241 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1242 "compiled with protobuf-c version: %s", 1243 PROTOBUF_C_VERSION); 1244 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1245 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1246 "linked to protobuf-c version: %s", protobuf_c_version()); 1247 #endif /* if defined(HAVE_DNSTAP) */ 1248 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1249 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1250 "----------------------------------------------------"); 1251 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1252 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1253 "BIND 9 is maintained by Internet Systems Consortium,"); 1254 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1255 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1256 "Inc. (ISC), a non-profit 501(c)(3) public-benefit "); 1257 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1258 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1259 "corporation. Support and training for BIND 9 are "); 1260 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1261 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1262 "available at https://www.isc.org/support"); 1263 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1264 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, 1265 "----------------------------------------------------"); 1266 1267 /* 1268 * System resources cannot effectively be tuned on some systems. 1269 * Raise the limit in such cases for safety. 1270 */ 1271 named_os_adjustnofile(); 1272 1273 /* 1274 * If the named configuration filename is relative, prepend the current 1275 * directory's name before possibly changing to another directory. 1276 */ 1277 if (!isc_file_isabsolute(named_g_conffile)) { 1278 result = isc_file_absolutepath(named_g_conffile, 1279 absolute_conffile, 1280 sizeof(absolute_conffile)); 1281 if (result != ISC_R_SUCCESS) { 1282 named_main_earlyfatal("could not construct " 1283 "absolute path " 1284 "of configuration file: %s", 1285 isc_result_totext(result)); 1286 } 1287 named_g_conffile = absolute_conffile; 1288 } 1289 1290 /* 1291 * Record the server's startup time. 1292 */ 1293 named_g_boottime = isc_time_now(); 1294 1295 result = create_managers(); 1296 if (result != ISC_R_SUCCESS) { 1297 named_main_earlyfatal("create_managers() failed: %s", 1298 isc_result_totext(result)); 1299 } 1300 1301 named_builtin_init(); 1302 1303 /* 1304 * Add calls to register sdb drivers here. 1305 */ 1306 /* xxdb_init(); */ 1307 1308 /* 1309 * Register the DLZ "dlopen" driver. 1310 */ 1311 result = dlz_dlopen_init(named_g_mctx); 1312 if (result != ISC_R_SUCCESS) { 1313 named_main_earlyfatal("dlz_dlopen_init() failed: %s", 1314 isc_result_totext(result)); 1315 } 1316 1317 named_server_create(named_g_mctx, &named_g_server); 1318 ENSURE(named_g_server != NULL); 1319 sctx = named_g_server->sctx; 1320 1321 /* 1322 * Report supported algorithms now that dst_lib_init() has 1323 * been called via named_server_create(). 1324 */ 1325 format_supported_algorithms(logit); 1326 1327 /* 1328 * Modify server context according to command line options 1329 */ 1330 if (disable4) { 1331 ns_server_setoption(sctx, NS_SERVER_DISABLE4, true); 1332 } 1333 if (disable6) { 1334 ns_server_setoption(sctx, NS_SERVER_DISABLE6, true); 1335 } 1336 if (dropedns) { 1337 ns_server_setoption(sctx, NS_SERVER_DROPEDNS, true); 1338 } 1339 if (ednsformerr) { /* STD13 server */ 1340 ns_server_setoption(sctx, NS_SERVER_EDNSFORMERR, true); 1341 } 1342 if (ednsnotimp) { 1343 ns_server_setoption(sctx, NS_SERVER_EDNSNOTIMP, true); 1344 } 1345 if (ednsrefused) { 1346 ns_server_setoption(sctx, NS_SERVER_EDNSREFUSED, true); 1347 } 1348 if (fixedlocal) { 1349 ns_server_setoption(sctx, NS_SERVER_FIXEDLOCAL, true); 1350 } 1351 if (noaa) { 1352 ns_server_setoption(sctx, NS_SERVER_NOAA, true); 1353 } 1354 if (noedns) { 1355 ns_server_setoption(sctx, NS_SERVER_NOEDNS, true); 1356 } 1357 if (nonearest) { 1358 ns_server_setoption(sctx, NS_SERVER_NONEAREST, true); 1359 } 1360 if (nosoa) { 1361 ns_server_setoption(sctx, NS_SERVER_NOSOA, true); 1362 } 1363 if (notcp) { 1364 ns_server_setoption(sctx, NS_SERVER_NOTCP, true); 1365 } 1366 if (sigvalinsecs) { 1367 ns_server_setoption(sctx, NS_SERVER_SIGVALINSECS, true); 1368 } 1369 if (transferinsecs) { 1370 ns_server_setoption(sctx, NS_SERVER_TRANSFERINSECS, true); 1371 } 1372 if (transferslowly) { 1373 ns_server_setoption(sctx, NS_SERVER_TRANSFERSLOWLY, true); 1374 } 1375 if (transferstuck) { 1376 ns_server_setoption(sctx, NS_SERVER_TRANSFERSTUCK, true); 1377 } 1378 } 1379 1380 static void 1381 cleanup(void) { 1382 if (named_g_mapped != NULL) { 1383 dns_acl_detach(&named_g_mapped); 1384 } 1385 1386 named_server_destroy(&named_g_server); 1387 1388 named_builtin_deinit(); 1389 1390 /* 1391 * Add calls to unregister sdb drivers here. 1392 */ 1393 /* xxdb_clear(); */ 1394 1395 /* 1396 * Unregister "dlopen" DLZ driver. 1397 */ 1398 dlz_dlopen_clear(); 1399 1400 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1401 NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "exiting"); 1402 named_log_shutdown(); 1403 } 1404 1405 static char *memstats = NULL; 1406 1407 void 1408 named_main_setmemstats(const char *filename) { 1409 /* 1410 * Caller has to ensure locking. 1411 */ 1412 1413 if (memstats != NULL) { 1414 free(memstats); 1415 memstats = NULL; 1416 } 1417 1418 if (filename == NULL) { 1419 return; 1420 } 1421 1422 memstats = strdup(filename); 1423 } 1424 1425 #ifdef HAVE_LIBSCF 1426 /* 1427 * Get FMRI for the named process. 1428 */ 1429 isc_result_t 1430 named_smf_get_instance(char **ins_name, int debug, isc_mem_t *mctx) { 1431 scf_handle_t *h = NULL; 1432 int namelen; 1433 char *instance; 1434 1435 REQUIRE(ins_name != NULL && *ins_name == NULL); 1436 1437 if ((h = scf_handle_create(SCF_VERSION)) == NULL) { 1438 if (debug) { 1439 UNEXPECTED_ERROR("scf_handle_create() failed: %s", 1440 scf_strerror(scf_error())); 1441 } 1442 return ISC_R_FAILURE; 1443 } 1444 1445 if (scf_handle_bind(h) == -1) { 1446 if (debug) { 1447 UNEXPECTED_ERROR("scf_handle_bind() failed: %s", 1448 scf_strerror(scf_error())); 1449 } 1450 scf_handle_destroy(h); 1451 return ISC_R_FAILURE; 1452 } 1453 1454 if ((namelen = scf_myname(h, NULL, 0)) == -1) { 1455 if (debug) { 1456 UNEXPECTED_ERROR("scf_myname() failed: %s", 1457 scf_strerror(scf_error())); 1458 } 1459 scf_handle_destroy(h); 1460 return ISC_R_FAILURE; 1461 } 1462 1463 if ((instance = isc_mem_allocate(mctx, namelen + 1)) == NULL) { 1464 UNEXPECTED_ERROR("named_smf_get_instance memory " 1465 "allocation failed: %s", 1466 isc_result_totext(ISC_R_NOMEMORY)); 1467 scf_handle_destroy(h); 1468 return ISC_R_FAILURE; 1469 } 1470 1471 if (scf_myname(h, instance, namelen + 1) == -1) { 1472 if (debug) { 1473 UNEXPECTED_ERROR("scf_myname() failed: %s", 1474 scf_strerror(scf_error())); 1475 } 1476 scf_handle_destroy(h); 1477 isc_mem_free(mctx, instance); 1478 return ISC_R_FAILURE; 1479 } 1480 1481 scf_handle_destroy(h); 1482 *ins_name = instance; 1483 return ISC_R_SUCCESS; 1484 } 1485 #endif /* HAVE_LIBSCF */ 1486 1487 /* main entry point, possibly hooked */ 1488 1489 int 1490 main(int argc, char *argv[]) { 1491 isc_result_t result; 1492 #ifdef HAVE_LIBSCF 1493 char *instance = NULL; 1494 #endif /* ifdef HAVE_LIBSCF */ 1495 1496 #ifdef HAVE_GPERFTOOLS_PROFILER 1497 (void)ProfilerStart(NULL); 1498 #endif /* ifdef HAVE_GPERFTOOLS_PROFILER */ 1499 1500 /* 1501 * Technically, this call is superfluous because on startup of the main 1502 * program, the portable "C" locale is selected by default. This 1503 * explicit call here is for a reference that the BIND 9 code base is 1504 * not locale aware and the locale MUST be set to "C" (or "POSIX") when 1505 * calling any BIND 9 library code. If you are calling external 1506 * libraries that use locale, such calls must be wrapped into 1507 * setlocale(LC_ALL, ""); before the call and setlocale(LC_ALL, "C"); 1508 * after the call, and no BIND 9 library calls must be made in between. 1509 */ 1510 setlocale(LC_ALL, "C"); 1511 1512 /* 1513 * Record version in core image. 1514 * strings named.core | grep "named version:" 1515 */ 1516 strlcat(version, 1517 #if defined(NO_VERSION_DATE) || !defined(__DATE__) 1518 "named version: BIND " PACKAGE_VERSION " <" PACKAGE_SRCID ">", 1519 #else 1520 "named version: BIND " PACKAGE_VERSION " <" PACKAGE_SRCID 1521 "> (" __DATE__ ")", 1522 #endif 1523 sizeof(version)); 1524 result = isc_file_progname(*argv, program_name, sizeof(program_name)); 1525 if (result != ISC_R_SUCCESS) { 1526 named_main_earlyfatal("program name too long"); 1527 } 1528 1529 isc_assertion_setcallback(assertion_failed); 1530 isc_error_setfatal(library_fatal_error); 1531 isc_error_setunexpected(library_unexpected_error); 1532 1533 named_os_init(program_name); 1534 1535 parse_command_line(argc, argv); 1536 1537 #ifdef ENABLE_AFL 1538 if (named_g_fuzz_type != isc_fuzz_none) { 1539 named_fuzz_setup(); 1540 } 1541 1542 if (named_g_fuzz_type == isc_fuzz_resolver) { 1543 dns_resolver_setfuzzing(); 1544 } else if (named_g_fuzz_type == isc_fuzz_http) { 1545 isc_httpd_setfinishhook(named_fuzz_notify); 1546 } 1547 #endif /* ifdef ENABLE_AFL */ 1548 /* 1549 * Warn about common configuration error. 1550 */ 1551 if (named_g_chrootdir != NULL) { 1552 int len = strlen(named_g_chrootdir); 1553 if (strncmp(named_g_chrootdir, named_g_conffile, len) == 0 && 1554 (named_g_conffile[len] == '/' || 1555 named_g_conffile[len] == '\\')) 1556 { 1557 named_main_earlywarning("config filename (-c %s) " 1558 "contains chroot path (-t %s)", 1559 named_g_conffile, 1560 named_g_chrootdir); 1561 } 1562 } 1563 1564 setup(); 1565 isc_mem_setname(named_g_mctx, "main"); 1566 INSIST(named_g_server != NULL); 1567 1568 /* 1569 * Start things running 1570 */ 1571 isc_signal_start(named_g_server->sighup); 1572 1573 /* 1574 * Pause the loop manager in fatal. 1575 */ 1576 named_g_loopmgr_running = true; 1577 isc_loopmgr_run(named_g_loopmgr); 1578 1579 #ifdef HAVE_LIBSCF 1580 if (named_smf_want_disable == 1) { 1581 result = named_smf_get_instance(&instance, 1, named_g_mctx); 1582 if (result == ISC_R_SUCCESS && instance != NULL) { 1583 if (smf_disable_instance(instance, 0) != 0) { 1584 UNEXPECTED_ERROR("smf_disable_instance() " 1585 "failed for %s : %s", 1586 instance, 1587 scf_strerror(scf_error())); 1588 } 1589 } 1590 if (instance != NULL) { 1591 isc_mem_free(named_g_mctx, instance); 1592 } 1593 } 1594 #endif /* HAVE_LIBSCF */ 1595 1596 cleanup(); 1597 1598 if (want_stats) { 1599 isc_mem_stats(named_g_mctx, stdout); 1600 } 1601 1602 if (named_g_memstatistics && memstats != NULL) { 1603 FILE *fp = NULL; 1604 result = isc_stdio_open(memstats, "w", &fp); 1605 if (result == ISC_R_SUCCESS) { 1606 isc_mem_stats(named_g_mctx, fp); 1607 (void)isc_stdio_close(fp); 1608 } 1609 } 1610 1611 isc_managers_destroy(&named_g_mctx, &named_g_loopmgr, &named_g_netmgr); 1612 1613 #if ENABLE_LEAK_DETECTION 1614 isc__tls_setdestroycheck(true); 1615 isc__uv_setdestroycheck(true); 1616 isc__xml_setdestroycheck(true); 1617 #endif 1618 1619 isc_mem_checkdestroyed(stderr); 1620 1621 named_main_setmemstats(NULL); 1622 1623 named_os_closedevnull(); 1624 1625 named_os_shutdown(); 1626 1627 #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 1628 if (base != NULL) { 1629 OSSL_PROVIDER_unload(base); 1630 } 1631 if (fips != NULL) { 1632 OSSL_PROVIDER_unload(fips); 1633 } 1634 #endif 1635 1636 #ifdef HAVE_GPERFTOOLS_PROFILER 1637 ProfilerStop(); 1638 #endif /* ifdef HAVE_GPERFTOOLS_PROFILER */ 1639 1640 return 0; 1641 } 1642