"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.17.5/bin/named/main.c" (4 Sep 2020, 43950 Bytes) of package /linux/misc/dns/bind9/9.17.5/bind-9.17.5.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "main.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 9.17.4_vs_9.17.5.

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