main.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /*! \file */
00019 
00020 #include <config.h>
00021 
00022 #include <ctype.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 
00026 #include <isc/app.h>
00027 #include <isc/backtrace.h>
00028 #include <isc/commandline.h>
00029 #include <isc/dir.h>
00030 #include <isc/entropy.h>
00031 #include <isc/file.h>
00032 #include <isc/hash.h>
00033 #include <isc/os.h>
00034 #include <isc/platform.h>
00035 #include <isc/print.h>
00036 #include <isc/resource.h>
00037 #include <isc/stdio.h>
00038 #include <isc/string.h>
00039 #include <isc/task.h>
00040 #include <isc/timer.h>
00041 #include <isc/util.h>
00042 
00043 #include <isccc/result.h>
00044 
00045 #include <dns/dispatch.h>
00046 #include <dns/name.h>
00047 #include <dns/result.h>
00048 #include <dns/view.h>
00049 
00050 #include <dst/result.h>
00051 #ifdef PKCS11CRYPTO
00052 #include <pk11/result.h>
00053 #endif
00054 
00055 #include <dlz/dlz_dlopen_driver.h>
00056 
00057 #ifdef HAVE_GPERFTOOLS_PROFILER
00058 #include <gperftools/profiler.h>
00059 #endif
00060 
00061 
00062 /*
00063  * Defining NS_MAIN provides storage declarations (rather than extern)
00064  * for variables in named/globals.h.
00065  */
00066 #define NS_MAIN 1
00067 
00068 #include <named/builtin.h>
00069 #include <named/control.h>
00070 #include <named/globals.h>      /* Explicit, though named/log.h includes it. */
00071 #include <named/interfacemgr.h>
00072 #include <named/log.h>
00073 #include <named/os.h>
00074 #include <named/server.h>
00075 #include <named/lwresd.h>
00076 #include <named/main.h>
00077 #include <named/seccomp.h>
00078 #ifdef HAVE_LIBSCF
00079 #include <named/ns_smf_globals.h>
00080 #endif
00081 
00082 #ifdef OPENSSL
00083 #include <openssl/opensslv.h>
00084 #include <openssl/crypto.h>
00085 #endif
00086 #ifdef HAVE_LIBXML2
00087 #include <libxml/xmlversion.h>
00088 #endif
00089 /*
00090  * Include header files for database drivers here.
00091  */
00092 /* #include "xxdb.h" */
00093 
00094 #ifdef CONTRIB_DLZ
00095 /*
00096  * Include contributed DLZ drivers if appropriate.
00097  */
00098 #include <dlz/dlz_drivers.h>
00099 #endif
00100 
00101 /*
00102  * The maximum number of stack frames to dump on assertion failure.
00103  */
00104 #ifndef BACKTRACE_MAXFRAME
00105 #define BACKTRACE_MAXFRAME 128
00106 #endif
00107 
00108 extern int isc_dscp_check_value;
00109 extern unsigned int dns_zone_mkey_hour;
00110 extern unsigned int dns_zone_mkey_day;
00111 extern unsigned int dns_zone_mkey_month;
00112 
00113 static isc_boolean_t    want_stats = ISC_FALSE;
00114 static char             program_name[ISC_DIR_NAMEMAX] = "named";
00115 static char             absolute_conffile[ISC_DIR_PATHMAX];
00116 static char             saved_command_line[512];
00117 static char             version[512];
00118 static unsigned int     maxsocks = 0;
00119 static int              maxudp = 0;
00120 
00121 void
00122 ns_main_earlywarning(const char *format, ...) {
00123         va_list args;
00124 
00125         va_start(args, format);
00126         if (ns_g_lctx != NULL) {
00127                 isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00128                                NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
00129                                format, args);
00130         } else {
00131                 fprintf(stderr, "%s: ", program_name);
00132                 vfprintf(stderr, format, args);
00133                 fprintf(stderr, "\n");
00134                 fflush(stderr);
00135         }
00136         va_end(args);
00137 }
00138 
00139 void
00140 ns_main_earlyfatal(const char *format, ...) {
00141         va_list args;
00142 
00143         va_start(args, format);
00144         if (ns_g_lctx != NULL) {
00145                 isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00146                                NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
00147                                format, args);
00148                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00149                                NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
00150                                "exiting (due to early fatal error)");
00151         } else {
00152                 fprintf(stderr, "%s: ", program_name);
00153                 vfprintf(stderr, format, args);
00154                 fprintf(stderr, "\n");
00155                 fflush(stderr);
00156         }
00157         va_end(args);
00158 
00159         exit(1);
00160 }
00161 
00162 ISC_PLATFORM_NORETURN_PRE static void
00163 assertion_failed(const char *file, int line, isc_assertiontype_t type,
00164                  const char *cond) ISC_PLATFORM_NORETURN_POST;
00165 
00166 static void
00167 assertion_failed(const char *file, int line, isc_assertiontype_t type,
00168                  const char *cond)
00169 {
00170         void *tracebuf[BACKTRACE_MAXFRAME];
00171         int i, nframes;
00172         isc_result_t result;
00173         const char *logsuffix = "";
00174         const char *fname;
00175 
00176         /*
00177          * Handle assertion failures.
00178          */
00179 
00180         if (ns_g_lctx != NULL) {
00181                 /*
00182                  * Reset the assertion callback in case it is the log
00183                  * routines causing the assertion.
00184                  */
00185                 isc_assertion_setcallback(NULL);
00186 
00187                 result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME,
00188                                                 &nframes);
00189                 if (result == ISC_R_SUCCESS && nframes > 0)
00190                         logsuffix = ", back trace";
00191                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00192                               NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
00193                               "%s:%d: %s(%s) failed%s", file, line,
00194                               isc_assertion_typetotext(type), cond, logsuffix);
00195                 if (result == ISC_R_SUCCESS) {
00196                         for (i = 0; i < nframes; i++) {
00197                                 unsigned long offset;
00198 
00199                                 fname = NULL;
00200                                 result = isc_backtrace_getsymbol(tracebuf[i],
00201                                                                  &fname,
00202                                                                  &offset);
00203                                 if (result == ISC_R_SUCCESS) {
00204                                         isc_log_write(ns_g_lctx,
00205                                                       NS_LOGCATEGORY_GENERAL,
00206                                                       NS_LOGMODULE_MAIN,
00207                                                       ISC_LOG_CRITICAL,
00208                                                       "#%d %p in %s()+0x%lx", i,
00209                                                       tracebuf[i], fname,
00210                                                       offset);
00211                                 } else {
00212                                         isc_log_write(ns_g_lctx,
00213                                                       NS_LOGCATEGORY_GENERAL,
00214                                                       NS_LOGMODULE_MAIN,
00215                                                       ISC_LOG_CRITICAL,
00216                                                       "#%d %p in ??", i,
00217                                                       tracebuf[i]);
00218                                 }
00219                         }
00220                 }
00221                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00222                               NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
00223                               "exiting (due to assertion failure)");
00224         } else {
00225                 fprintf(stderr, "%s:%d: %s(%s) failed\n",
00226                         file, line, isc_assertion_typetotext(type), cond);
00227                 fflush(stderr);
00228         }
00229 
00230         if (ns_g_coreok)
00231                 abort();
00232         exit(1);
00233 }
00234 
00235 ISC_PLATFORM_NORETURN_PRE static void
00236 library_fatal_error(const char *file, int line, const char *format,
00237                     va_list args)
00238 ISC_FORMAT_PRINTF(3, 0) ISC_PLATFORM_NORETURN_POST;
00239 
00240 static void
00241 library_fatal_error(const char *file, int line, const char *format,
00242                     va_list args)
00243 {
00244         /*
00245          * Handle isc_error_fatal() calls from our libraries.
00246          */
00247 
00248         if (ns_g_lctx != NULL) {
00249                 /*
00250                  * Reset the error callback in case it is the log
00251                  * routines causing the assertion.
00252                  */
00253                 isc_error_setfatal(NULL);
00254 
00255                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00256                               NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
00257                               "%s:%d: fatal error:", file, line);
00258                 isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00259                                NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
00260                                format, args);
00261                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00262                               NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
00263                               "exiting (due to fatal error in library)");
00264         } else {
00265                 fprintf(stderr, "%s:%d: fatal error: ", file, line);
00266                 vfprintf(stderr, format, args);
00267                 fprintf(stderr, "\n");
00268                 fflush(stderr);
00269         }
00270 
00271         if (ns_g_coreok)
00272                 abort();
00273         exit(1);
00274 }
00275 
00276 static void
00277 library_unexpected_error(const char *file, int line, const char *format,
00278                          va_list args) ISC_FORMAT_PRINTF(3, 0);
00279 
00280 static void
00281 library_unexpected_error(const char *file, int line, const char *format,
00282                          va_list args)
00283 {
00284         /*
00285          * Handle isc_error_unexpected() calls from our libraries.
00286          */
00287 
00288         if (ns_g_lctx != NULL) {
00289                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00290                               NS_LOGMODULE_MAIN, ISC_LOG_ERROR,
00291                               "%s:%d: unexpected error:", file, line);
00292                 isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00293                                NS_LOGMODULE_MAIN, ISC_LOG_ERROR,
00294                                format, args);
00295         } else {
00296                 fprintf(stderr, "%s:%d: fatal error: ", file, line);
00297                 vfprintf(stderr, format, args);
00298                 fprintf(stderr, "\n");
00299                 fflush(stderr);
00300         }
00301 }
00302 
00303 static void
00304 lwresd_usage(void) {
00305         fprintf(stderr,
00306                 "usage: lwresd [-4|-6] [-c conffile | -C resolvconffile] "
00307                 "[-d debuglevel]\n"
00308                 "              [-f|-g] [-n number_of_cpus] [-p port] "
00309                 "[-P listen-port] [-s]\n"
00310                 "              [-t chrootdir] [-u username] [-i pidfile]\n"
00311                 "              [-m {usage|trace|record|size|mctx}]\n");
00312 }
00313 
00314 static void
00315 usage(void) {
00316         if (ns_g_lwresdonly) {
00317                 lwresd_usage();
00318                 return;
00319         }
00320         fprintf(stderr,
00321                 "usage: named [-4|-6] [-c conffile] [-d debuglevel] "
00322                 "[-E engine] [-f|-g]\n"
00323                 "             [-n number_of_cpus] [-p port] [-s] "
00324                 "[-t chrootdir] [-u username]\n"
00325                 "             [-m {usage|trace|record|size|mctx}]\n");
00326 }
00327 
00328 static void
00329 save_command_line(int argc, char *argv[]) {
00330         int i;
00331         char *src;
00332         char *dst;
00333         char *eob;
00334         const char truncated[] = "...";
00335         isc_boolean_t quoted = ISC_FALSE;
00336 
00337         dst = saved_command_line;
00338         eob = saved_command_line + sizeof(saved_command_line);
00339 
00340         for (i = 1; i < argc && dst < eob; i++) {
00341                 *dst++ = ' ';
00342 
00343                 src = argv[i];
00344                 while (*src != '\0' && dst < eob) {
00345                         /*
00346                          * This won't perfectly produce a shell-independent
00347                          * pastable command line in all circumstances, but
00348                          * comes close, and for practical purposes will
00349                          * nearly always be fine.
00350                          */
00351                         if (quoted || isalnum(*src & 0xff) ||
00352                             *src == '-' || *src == '_' ||
00353                             *src == '.' || *src == '/') {
00354                                 *dst++ = *src++;
00355                                 quoted = ISC_FALSE;
00356                         } else {
00357                                 *dst++ = '\\';
00358                                 quoted = ISC_TRUE;
00359                         }
00360                 }
00361         }
00362 
00363         INSIST(sizeof(saved_command_line) >= sizeof(truncated));
00364 
00365         if (dst == eob)
00366                 strcpy(eob - sizeof(truncated), truncated);
00367         else
00368                 *dst = '\0';
00369 }
00370 
00371 static int
00372 parse_int(char *arg, const char *desc) {
00373         char *endp;
00374         int tmp;
00375         long int ltmp;
00376 
00377         ltmp = strtol(arg, &endp, 10);
00378         tmp = (int) ltmp;
00379         if (*endp != '\0')
00380                 ns_main_earlyfatal("%s '%s' must be numeric", desc, arg);
00381         if (tmp < 0 || tmp != ltmp)
00382                 ns_main_earlyfatal("%s '%s' out of range", desc, arg);
00383         return (tmp);
00384 }
00385 
00386 static struct flag_def {
00387         const char *name;
00388         unsigned int value;
00389 } mem_debug_flags[] = {
00390         { "none", 0},
00391         { "trace",  ISC_MEM_DEBUGTRACE },
00392         { "record", ISC_MEM_DEBUGRECORD },
00393         { "usage", ISC_MEM_DEBUGUSAGE },
00394         { "size", ISC_MEM_DEBUGSIZE },
00395         { "mctx", ISC_MEM_DEBUGCTX },
00396         { NULL, 0 }
00397 };
00398 
00399 static void
00400 set_flags(const char *arg, struct flag_def *defs, unsigned int *ret) {
00401         isc_boolean_t clear = ISC_FALSE;
00402 
00403         for (;;) {
00404                 const struct flag_def *def;
00405                 const char *end = strchr(arg, ',');
00406                 int arglen;
00407                 if (end == NULL)
00408                         end = arg + strlen(arg);
00409                 arglen = (int)(end - arg);
00410                 for (def = defs; def->name != NULL; def++) {
00411                         if (arglen == (int)strlen(def->name) &&
00412                             memcmp(arg, def->name, arglen) == 0) {
00413                                 if (def->value == 0)
00414                                         clear = ISC_TRUE;
00415                                 *ret |= def->value;
00416                                 goto found;
00417                         }
00418                 }
00419                 ns_main_earlyfatal("unrecognized flag '%.*s'", arglen, arg);
00420          found:
00421                 if (clear || (*end == '\0'))
00422                         break;
00423                 arg = end + 1;
00424         }
00425 
00426         if (clear)
00427                 *ret = 0;
00428 }
00429 
00430 static void
00431 parse_command_line(int argc, char *argv[]) {
00432         int ch;
00433         int port;
00434         const char *p;
00435 
00436         save_command_line(argc, argv);
00437 
00438         /*
00439          * NS_MAIN_ARGS is defined in main.h, so that it can be used
00440          * both by named and by ntservice hooks.
00441          */
00442         isc_commandline_errprint = ISC_FALSE;
00443         while ((ch = isc_commandline_parse(argc, argv, NS_MAIN_ARGS)) != -1) {
00444                 switch (ch) {
00445                 case '4':
00446                         if (ns_g_disable4)
00447                                 ns_main_earlyfatal("cannot specify -4 and -6");
00448                         if (isc_net_probeipv4() != ISC_R_SUCCESS)
00449                                 ns_main_earlyfatal("IPv4 not supported by OS");
00450                         isc_net_disableipv6();
00451                         ns_g_disable6 = ISC_TRUE;
00452                         break;
00453                 case '6':
00454                         if (ns_g_disable6)
00455                                 ns_main_earlyfatal("cannot specify -4 and -6");
00456                         if (isc_net_probeipv6() != ISC_R_SUCCESS)
00457                                 ns_main_earlyfatal("IPv6 not supported by OS");
00458                         isc_net_disableipv4();
00459                         ns_g_disable4 = ISC_TRUE;
00460                         break;
00461                 case 'c':
00462                         ns_g_conffile = isc_commandline_argument;
00463                         lwresd_g_conffile = isc_commandline_argument;
00464                         if (lwresd_g_useresolvconf)
00465                                 ns_main_earlyfatal("cannot specify -c and -C");
00466                         ns_g_conffileset = ISC_TRUE;
00467                         break;
00468                 case 'C':
00469                         lwresd_g_resolvconffile = isc_commandline_argument;
00470                         if (ns_g_conffileset)
00471                                 ns_main_earlyfatal("cannot specify -c and -C");
00472                         lwresd_g_useresolvconf = ISC_TRUE;
00473                         break;
00474                 case 'd':
00475                         ns_g_debuglevel = parse_int(isc_commandline_argument,
00476                                                     "debug level");
00477                         break;
00478                 case 'D':
00479                         /* Descriptive comment for 'ps'. */
00480                         break;
00481                 case 'E':
00482                         ns_g_engine = isc_commandline_argument;
00483                         break;
00484                 case 'f':
00485                         ns_g_foreground = ISC_TRUE;
00486                         break;
00487                 case 'g':
00488                         ns_g_foreground = ISC_TRUE;
00489                         ns_g_logstderr = ISC_TRUE;
00490                         break;
00491                 /* XXXBEW -i should be removed */
00492                 case 'i':
00493                         lwresd_g_defaultpidfile = isc_commandline_argument;
00494                         break;
00495                 case 'l':
00496                         ns_g_lwresdonly = ISC_TRUE;
00497                         break;
00498                 case 'L':
00499                         ns_g_logfile = isc_commandline_argument;
00500                         break;
00501                 case 'M':
00502                         if (strcmp(isc_commandline_argument, "external") == 0)
00503                                 isc_mem_defaultflags = 0;
00504                         break;
00505                 case 'm':
00506                         set_flags(isc_commandline_argument, mem_debug_flags,
00507                                   &isc_mem_debugging);
00508                         break;
00509                 case 'N': /* Deprecated. */
00510                 case 'n':
00511                         ns_g_cpus = parse_int(isc_commandline_argument,
00512                                               "number of cpus");
00513                         if (ns_g_cpus == 0)
00514                                 ns_g_cpus = 1;
00515                         break;
00516                 case 'p':
00517                         port = parse_int(isc_commandline_argument, "port");
00518                         if (port < 1 || port > 65535)
00519                                 ns_main_earlyfatal("port '%s' out of range",
00520                                                    isc_commandline_argument);
00521                         ns_g_port = port;
00522                         break;
00523                 /* XXXBEW Should -P be removed? */
00524                 case 'P':
00525                         port = parse_int(isc_commandline_argument, "port");
00526                         if (port < 1 || port > 65535)
00527                                 ns_main_earlyfatal("port '%s' out of range",
00528                                                    isc_commandline_argument);
00529                         lwresd_g_listenport = port;
00530                         break;
00531                 case 's':
00532                         /* XXXRTH temporary syntax */
00533                         want_stats = ISC_TRUE;
00534                         break;
00535                 case 'S':
00536                         maxsocks = parse_int(isc_commandline_argument,
00537                                              "max number of sockets");
00538                         break;
00539                 case 't':
00540                         /* XXXJAB should we make a copy? */
00541                         ns_g_chrootdir = isc_commandline_argument;
00542                         break;
00543                 case 'T':       /* NOT DOCUMENTED */
00544                         /*
00545                          * force the server to behave (or misbehave) in
00546                          * specified ways for testing purposes.
00547                          *
00548                          * clienttest: make clients single shot with their
00549                          *             own memory context.
00550                          * delay=xxxx: delay client responses by xxxx ms to
00551                          *             simulate remote servers.
00552                          * dscp=x:     check that dscp values are as
00553                          *             expected and assert otherwise.
00554                          */
00555                         if (!strcmp(isc_commandline_argument, "clienttest"))
00556                                 ns_g_clienttest = ISC_TRUE;
00557                         else if (!strcmp(isc_commandline_argument, "nosoa"))
00558                                 ns_g_nosoa = ISC_TRUE;
00559                         else if (!strcmp(isc_commandline_argument, "noaa"))
00560                                 ns_g_noaa = ISC_TRUE;
00561                         else if (!strcmp(isc_commandline_argument, "maxudp512"))
00562                                 maxudp = 512;
00563                         else if (!strcmp(isc_commandline_argument, "maxudp1460"))
00564                                 maxudp = 1460;
00565                         else if (!strcmp(isc_commandline_argument, "dropedns"))
00566                                 ns_g_dropedns = ISC_TRUE;
00567                         else if (!strcmp(isc_commandline_argument, "noedns"))
00568                                 ns_g_noedns = ISC_TRUE;
00569                         else if (!strncmp(isc_commandline_argument,
00570                                           "maxudp=", 7))
00571                                 maxudp = atoi(isc_commandline_argument + 7);
00572                         else if (!strncmp(isc_commandline_argument,
00573                                           "delay=", 6))
00574                                 ns_g_delay = atoi(isc_commandline_argument + 6);
00575                         else if (!strcmp(isc_commandline_argument, "nosyslog"))
00576                                 ns_g_nosyslog = ISC_TRUE;
00577                         else if (!strcmp(isc_commandline_argument, "nonearest"))
00578                                 ns_g_nonearest = ISC_TRUE;
00579                         else if (!strncmp(isc_commandline_argument, "dscp=", 5))
00580                                 isc_dscp_check_value =
00581                                            atoi(isc_commandline_argument + 5);
00582                         else if (!strncmp(isc_commandline_argument,
00583                                           "mkeytimers=", 11))
00584                         {
00585                                 p = strtok(isc_commandline_argument + 11, "/");
00586                                 if (p == NULL)
00587                                         ns_main_earlyfatal("bad mkeytimer");
00588                                 dns_zone_mkey_hour = atoi(p);
00589                                 if (dns_zone_mkey_hour == 0)
00590                                         ns_main_earlyfatal("bad mkeytimer");
00591 
00592                                 p = strtok(NULL, "/");
00593                                 if (p == NULL) {
00594                                         dns_zone_mkey_day =
00595                                                 (24 * dns_zone_mkey_hour);
00596                                         dns_zone_mkey_month =
00597                                                 (30 * dns_zone_mkey_day);
00598                                         break;
00599                                 }
00600                                 dns_zone_mkey_day = atoi(p);
00601                                 if (dns_zone_mkey_day < dns_zone_mkey_hour)
00602                                         ns_main_earlyfatal("bad mkeytimer");
00603 
00604                                 p = strtok(NULL, "/");
00605                                 if (p == NULL) {
00606                                         dns_zone_mkey_month =
00607                                                 (30 * dns_zone_mkey_day);
00608                                         break;
00609                                 }
00610                                 dns_zone_mkey_month = atoi(p);
00611                                 if (dns_zone_mkey_month < dns_zone_mkey_day)
00612                                         ns_main_earlyfatal("bad mkeytimer");
00613                         } else if (!strcmp(isc_commandline_argument, "notcp"))
00614                                 ns_g_notcp = ISC_TRUE;
00615                         else
00616                                 fprintf(stderr, "unknown -T flag '%s\n",
00617                                         isc_commandline_argument);
00618                         break;
00619                 case 'U':
00620                         ns_g_udpdisp = parse_int(isc_commandline_argument,
00621                                                  "number of UDP listeners "
00622                                                  "per interface");
00623                         break;
00624                 case 'u':
00625                         ns_g_username = isc_commandline_argument;
00626                         break;
00627                 case 'v':
00628                         printf("%s %s%s%s <id:%s>\n",
00629                                ns_g_product, ns_g_version,
00630                                (*ns_g_description != '\0') ? " " : "",
00631                                ns_g_description, ns_g_srcid);
00632                         exit(0);
00633                 case 'V':
00634                         printf("%s %s%s%s <id:%s>\n", ns_g_product, ns_g_version,
00635                                (*ns_g_description != '\0') ? " " : "",
00636                                ns_g_description, ns_g_srcid);
00637                         printf("built by %s with %s\n",
00638                                ns_g_builder, ns_g_configargs);
00639 #ifdef __clang__
00640                         printf("compiled by CLANG %s\n", __VERSION__);
00641 #else
00642 #if defined(__ICC) || defined(__INTEL_COMPILER)
00643                         printf("compiled by ICC %s\n", __VERSION__);
00644 #else
00645 #ifdef __GNUC__
00646                         printf("compiled by GCC %s\n", __VERSION__);
00647 #endif
00648 #endif
00649 #endif
00650 #ifdef _MSC_VER
00651                         printf("compiled by MSVC %d\n", _MSC_VER);
00652 #endif
00653 #ifdef __SUNPRO_C
00654                         printf("compiled by Solaris Studio %x\n", __SUNPRO_C);
00655 #endif
00656 #ifdef OPENSSL
00657                         printf("compiled with OpenSSL version: %s\n",
00658                                OPENSSL_VERSION_TEXT);
00659                         printf("linked to OpenSSL version: %s\n",
00660                                SSLeay_version(SSLEAY_VERSION));
00661 #endif
00662 #ifdef HAVE_LIBXML2
00663                         printf("compiled with libxml2 version: %s\n",
00664                                LIBXML_DOTTED_VERSION);
00665                         printf("linked to libxml2 version: %s\n",
00666                                xmlParserVersion);
00667 #endif
00668 #ifdef HAVE_JSON
00669                         printf("compiled with libjson-c version: %s\n",
00670                                JSON_C_VERSION);
00671                         printf("linked to libjson-c version: %s\n",
00672                                json_c_version());
00673 #endif
00674 #ifdef ISC_PLATFORM_USETHREADS
00675                         printf("threads support is enabled\n");
00676 #else
00677                         printf("threads support is disabled\n");
00678 #endif
00679                         exit(0);
00680                 case 'x':
00681                         /* Obsolete. No longer in use. Ignore. */
00682                         break;
00683                 case 'X':
00684                         ns_g_forcelock = ISC_TRUE;
00685                         if (strcasecmp(isc_commandline_argument, "none") != 0)
00686                                 ns_g_defaultlockfile = isc_commandline_argument;
00687                         else
00688                                 ns_g_defaultlockfile = NULL;
00689                         break;
00690                 case 'F':
00691                         /* Reserved for FIPS mode */
00692                         /* FALLTHROUGH */
00693                 case '?':
00694                         usage();
00695                         if (isc_commandline_option == '?')
00696                                 exit(0);
00697                         p = strchr(NS_MAIN_ARGS, isc_commandline_option);
00698                         if (p == NULL || *++p != ':')
00699                                 ns_main_earlyfatal("unknown option '-%c'",
00700                                                    isc_commandline_option);
00701                         else
00702                                 ns_main_earlyfatal("option '-%c' requires "
00703                                                    "an argument",
00704                                                    isc_commandline_option);
00705                         /* FALLTHROUGH */
00706                 default:
00707                         ns_main_earlyfatal("parsing options returned %d", ch);
00708                 }
00709         }
00710 
00711         argc -= isc_commandline_index;
00712         argv += isc_commandline_index;
00713         POST(argv);
00714 
00715         if (argc > 0) {
00716                 usage();
00717                 ns_main_earlyfatal("extra command line arguments");
00718         }
00719 }
00720 
00721 static isc_result_t
00722 create_managers(void) {
00723         isc_result_t result;
00724         unsigned int socks;
00725 
00726 #ifdef ISC_PLATFORM_USETHREADS
00727         if (ns_g_cpus == 0)
00728                 ns_g_cpus = ns_g_cpus_detected;
00729         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
00730                       ISC_LOG_INFO, "found %u CPU%s, using %u worker thread%s",
00731                       ns_g_cpus_detected, ns_g_cpus_detected == 1 ? "" : "s",
00732                       ns_g_cpus, ns_g_cpus == 1 ? "" : "s");
00733 #else
00734         ns_g_cpus = 1;
00735 #endif
00736 #ifdef WIN32
00737         ns_g_udpdisp = 1;
00738 #else
00739         if (ns_g_udpdisp == 0) {
00740                 if (ns_g_cpus_detected == 1)
00741                         ns_g_udpdisp = 1;
00742                 else if (ns_g_cpus_detected < 4)
00743                         ns_g_udpdisp = 2;
00744                 else
00745                         ns_g_udpdisp = ns_g_cpus_detected / 2;
00746         }
00747         if (ns_g_udpdisp > ns_g_cpus)
00748                 ns_g_udpdisp = ns_g_cpus;
00749 #endif
00750 #ifdef ISC_PLATFORM_USETHREADS
00751         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
00752                       ISC_LOG_INFO, "using %u UDP listener%s per interface",
00753                       ns_g_udpdisp, ns_g_udpdisp == 1 ? "" : "s");
00754 #endif
00755 
00756         result = isc_taskmgr_create(ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr);
00757         if (result != ISC_R_SUCCESS) {
00758                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00759                                  "isc_taskmgr_create() failed: %s",
00760                                  isc_result_totext(result));
00761                 return (ISC_R_UNEXPECTED);
00762         }
00763 
00764         result = isc_timermgr_create(ns_g_mctx, &ns_g_timermgr);
00765         if (result != ISC_R_SUCCESS) {
00766                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00767                                  "isc_timermgr_create() failed: %s",
00768                                  isc_result_totext(result));
00769                 return (ISC_R_UNEXPECTED);
00770         }
00771 
00772         result = isc_socketmgr_create2(ns_g_mctx, &ns_g_socketmgr, maxsocks);
00773         if (result != ISC_R_SUCCESS) {
00774                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00775                                  "isc_socketmgr_create() failed: %s",
00776                                  isc_result_totext(result));
00777                 return (ISC_R_UNEXPECTED);
00778         }
00779         isc__socketmgr_maxudp(ns_g_socketmgr, maxudp);
00780         result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &socks);
00781         if (result == ISC_R_SUCCESS) {
00782                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00783                               NS_LOGMODULE_SERVER,
00784                               ISC_LOG_INFO, "using up to %u sockets", socks);
00785         }
00786 
00787         result = isc_entropy_create(ns_g_mctx, &ns_g_entropy);
00788         if (result != ISC_R_SUCCESS) {
00789                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00790                                  "isc_entropy_create() failed: %s",
00791                                  isc_result_totext(result));
00792                 return (ISC_R_UNEXPECTED);
00793         }
00794 
00795         result = isc_hash_create(ns_g_mctx, ns_g_entropy, DNS_NAME_MAXWIRE);
00796         if (result != ISC_R_SUCCESS) {
00797                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00798                                  "isc_hash_create() failed: %s",
00799                                  isc_result_totext(result));
00800                 return (ISC_R_UNEXPECTED);
00801         }
00802 
00803         return (ISC_R_SUCCESS);
00804 }
00805 
00806 static void
00807 destroy_managers(void) {
00808         ns_lwresd_shutdown();
00809 
00810         /*
00811          * isc_taskmgr_destroy() will block until all tasks have exited,
00812          */
00813         isc_taskmgr_destroy(&ns_g_taskmgr);
00814         isc_timermgr_destroy(&ns_g_timermgr);
00815         isc_socketmgr_destroy(&ns_g_socketmgr);
00816 
00817         /*
00818          * isc_hash_destroy() cannot be called as long as a resolver may be
00819          * running.  Calling this after isc_taskmgr_destroy() ensures the
00820          * call is safe.
00821          */
00822         isc_hash_destroy();
00823 }
00824 
00825 static void
00826 dump_symboltable(void) {
00827         int i;
00828         isc_result_t result;
00829         const char *fname;
00830         const void *addr;
00831 
00832         if (isc__backtrace_nsymbols == 0)
00833                 return;
00834 
00835         if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(99)))
00836                 return;
00837 
00838         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
00839                       ISC_LOG_DEBUG(99), "Symbol table:");
00840 
00841         for (i = 0, result = ISC_R_SUCCESS; result == ISC_R_SUCCESS; i++) {
00842                 addr = NULL;
00843                 fname = NULL;
00844                 result = isc_backtrace_getsymbolfromindex(i, &addr, &fname);
00845                 if (result == ISC_R_SUCCESS) {
00846                         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00847                                       NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(99),
00848                                       "[%d] %p %s", i, addr, fname);
00849                 }
00850         }
00851 }
00852 
00853 #ifdef HAVE_LIBSECCOMP
00854 static void
00855 setup_seccomp() {
00856         scmp_filter_ctx ctx;
00857         unsigned int i;
00858         int ret;
00859 
00860         /* Make sure the lists are in sync */
00861         INSIST((sizeof(scmp_syscalls) / sizeof(int)) ==
00862                (sizeof(scmp_syscall_names) / sizeof(const char *)));
00863 
00864         ctx = seccomp_init(SCMP_ACT_KILL);
00865         if (ctx == NULL) {
00866                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00867                               NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
00868                               "libseccomp activation failed");
00869                 return;
00870         }
00871 
00872         for (i = 0 ; i < sizeof(scmp_syscalls)/sizeof(*(scmp_syscalls)); i++) {
00873                 ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW,
00874                                        scmp_syscalls[i], 0);
00875                 if (ret < 0)
00876                         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00877                                       NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
00878                                       "libseccomp rule failed: %s",
00879                                       scmp_syscall_names[i]);
00880 
00881                 else
00882                         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00883                                       NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(9),
00884                                       "added libseccomp rule: %s",
00885                                       scmp_syscall_names[i]);
00886         }
00887 
00888         ret = seccomp_load(ctx);
00889         if (ret < 0) {
00890                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00891                               NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
00892                               "libseccomp unable to load filter");
00893         } else {
00894                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00895                               NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
00896                               "libseccomp sandboxing active");
00897         }
00898 
00899         /*
00900          * Release filter in ctx. Filters already loaded are not
00901          * affected.
00902          */
00903         seccomp_release(ctx);
00904 }
00905 #endif /* HAVE_LIBSECCOMP */
00906 
00907 static void
00908 setup(void) {
00909         isc_result_t result;
00910         isc_resourcevalue_t old_openfiles;
00911 #ifdef HAVE_LIBSCF
00912         char *instance = NULL;
00913 #endif
00914 
00915         /*
00916          * Get the user and group information before changing the root
00917          * directory, so the administrator does not need to keep a copy
00918          * of the user and group databases in the chroot'ed environment.
00919          */
00920         ns_os_inituserinfo(ns_g_username);
00921 
00922         /*
00923          * Initialize time conversion information
00924          */
00925         ns_os_tzset();
00926 
00927         ns_os_opendevnull();
00928 
00929 #ifdef HAVE_LIBSCF
00930         /* Check if named is under smf control, before chroot. */
00931         result = ns_smf_get_instance(&instance, 0, ns_g_mctx);
00932         /* We don't care about instance, just check if we got one. */
00933         if (result == ISC_R_SUCCESS)
00934                 ns_smf_got_instance = 1;
00935         else
00936                 ns_smf_got_instance = 0;
00937         if (instance != NULL)
00938                 isc_mem_free(ns_g_mctx, instance);
00939 #endif /* HAVE_LIBSCF */
00940 
00941 #ifdef PATH_RANDOMDEV
00942         /*
00943          * Initialize system's random device as fallback entropy source
00944          * if running chroot'ed.
00945          */
00946         if (ns_g_chrootdir != NULL) {
00947                 result = isc_entropy_create(ns_g_mctx, &ns_g_fallbackentropy);
00948                 if (result != ISC_R_SUCCESS)
00949                         ns_main_earlyfatal("isc_entropy_create() failed: %s",
00950                                            isc_result_totext(result));
00951 
00952                 result = isc_entropy_createfilesource(ns_g_fallbackentropy,
00953                                                       PATH_RANDOMDEV);
00954                 if (result != ISC_R_SUCCESS) {
00955                         ns_main_earlywarning("could not open pre-chroot "
00956                                              "entropy source %s: %s",
00957                                              PATH_RANDOMDEV,
00958                                              isc_result_totext(result));
00959                         isc_entropy_detach(&ns_g_fallbackentropy);
00960                 }
00961         }
00962 #endif
00963 
00964 #ifdef ISC_PLATFORM_USETHREADS
00965         /*
00966          * Check for the number of cpu's before ns_os_chroot().
00967          */
00968         ns_g_cpus_detected = isc_os_ncpus();
00969 #endif
00970 
00971         ns_os_chroot(ns_g_chrootdir);
00972 
00973         /*
00974          * For operating systems which have a capability mechanism, now
00975          * is the time to switch to minimal privs and change our user id.
00976          * On traditional UNIX systems, this call will be a no-op, and we
00977          * will change the user ID after reading the config file the first
00978          * time.  (We need to read the config file to know which possibly
00979          * privileged ports to bind() to.)
00980          */
00981         ns_os_minprivs();
00982 
00983         result = ns_log_init(ISC_TF(ns_g_username != NULL));
00984         if (result != ISC_R_SUCCESS)
00985                 ns_main_earlyfatal("ns_log_init() failed: %s",
00986                                    isc_result_totext(result));
00987 
00988         /*
00989          * Now is the time to daemonize (if we're not running in the
00990          * foreground).  We waited until now because we wanted to get
00991          * a valid logging context setup.  We cannot daemonize any later,
00992          * because calling create_managers() will create threads, which
00993          * would be lost after fork().
00994          */
00995         if (!ns_g_foreground)
00996                 ns_os_daemonize();
00997 
00998         /*
00999          * We call isc_app_start() here as some versions of FreeBSD's fork()
01000          * destroys all the signal handling it sets up.
01001          */
01002         result = isc_app_start();
01003         if (result != ISC_R_SUCCESS)
01004                 ns_main_earlyfatal("isc_app_start() failed: %s",
01005                                    isc_result_totext(result));
01006 
01007         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
01008                       ISC_LOG_NOTICE, "starting %s %s%s%s <id:%s>",
01009                       ns_g_product, ns_g_version,
01010                       *ns_g_description ? " " : "", ns_g_description,
01011                       ns_g_srcid);
01012 
01013         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
01014                       ISC_LOG_NOTICE, "built with %s", ns_g_configargs);
01015 
01016         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
01017                       ISC_LOG_NOTICE, "running as: %s%s",
01018                       program_name, saved_command_line);
01019 
01020         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
01021                       ISC_LOG_NOTICE,
01022                       "----------------------------------------------------");
01023         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
01024                       ISC_LOG_NOTICE,
01025                       "BIND 9 is maintained by Internet Systems Consortium,");
01026         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
01027                       ISC_LOG_NOTICE,
01028                       "Inc. (ISC), a non-profit 501(c)(3) public-benefit ");
01029         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
01030                       ISC_LOG_NOTICE,
01031                       "corporation.  Support and training for BIND 9 are ");
01032         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
01033                       ISC_LOG_NOTICE,
01034                       "available at https://www.isc.org/support");
01035         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
01036                       ISC_LOG_NOTICE,
01037                       "----------------------------------------------------");
01038 
01039         dump_symboltable();
01040 
01041         /*
01042          * Get the initial resource limits.
01043          */
01044         (void)isc_resource_getlimit(isc_resource_stacksize,
01045                                     &ns_g_initstacksize);
01046         (void)isc_resource_getlimit(isc_resource_datasize,
01047                                     &ns_g_initdatasize);
01048         (void)isc_resource_getlimit(isc_resource_coresize,
01049                                     &ns_g_initcoresize);
01050         (void)isc_resource_getlimit(isc_resource_openfiles,
01051                                     &ns_g_initopenfiles);
01052 
01053         /*
01054          * System resources cannot effectively be tuned on some systems.
01055          * Raise the limit in such cases for safety.
01056          */
01057         old_openfiles = ns_g_initopenfiles;
01058         ns_os_adjustnofile();
01059         (void)isc_resource_getlimit(isc_resource_openfiles,
01060                                     &ns_g_initopenfiles);
01061         if (old_openfiles != ns_g_initopenfiles) {
01062                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
01063                               NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
01064                               "adjusted limit on open files from "
01065                               "%" ISC_PRINT_QUADFORMAT "u to "
01066                               "%" ISC_PRINT_QUADFORMAT "u",
01067                               old_openfiles, ns_g_initopenfiles);
01068         }
01069 
01070         /*
01071          * If the named configuration filename is relative, prepend the current
01072          * directory's name before possibly changing to another directory.
01073          */
01074         if (! isc_file_isabsolute(ns_g_conffile)) {
01075                 result = isc_file_absolutepath(ns_g_conffile,
01076                                                absolute_conffile,
01077                                                sizeof(absolute_conffile));
01078                 if (result != ISC_R_SUCCESS)
01079                         ns_main_earlyfatal("could not construct absolute path "
01080                                            "of configuration file: %s",
01081                                            isc_result_totext(result));
01082                 ns_g_conffile = absolute_conffile;
01083         }
01084 
01085         /*
01086          * Record the server's startup time.
01087          */
01088         result = isc_time_now(&ns_g_boottime);
01089         if (result != ISC_R_SUCCESS)
01090                 ns_main_earlyfatal("isc_time_now() failed: %s",
01091                                    isc_result_totext(result));
01092 
01093         result = create_managers();
01094         if (result != ISC_R_SUCCESS)
01095                 ns_main_earlyfatal("create_managers() failed: %s",
01096                                    isc_result_totext(result));
01097 
01098         ns_builtin_init();
01099 
01100         /*
01101          * Add calls to register sdb drivers here.
01102          */
01103         /* xxdb_init(); */
01104 
01105 #ifdef ISC_DLZ_DLOPEN
01106         /*
01107          * Register the DLZ "dlopen" driver.
01108          */
01109         result = dlz_dlopen_init(ns_g_mctx);
01110         if (result != ISC_R_SUCCESS)
01111                 ns_main_earlyfatal("dlz_dlopen_init() failed: %s",
01112                                    isc_result_totext(result));
01113 #endif
01114 
01115 #if CONTRIB_DLZ
01116         /*
01117          * Register any other contributed DLZ drivers.
01118          */
01119         result = dlz_drivers_init();
01120         if (result != ISC_R_SUCCESS)
01121                 ns_main_earlyfatal("dlz_drivers_init() failed: %s",
01122                                    isc_result_totext(result));
01123 #endif
01124 
01125         ns_server_create(ns_g_mctx, &ns_g_server);
01126 
01127 #ifdef HAVE_LIBSECCOMP
01128         setup_seccomp();
01129 #endif /* HAVE_LIBSECCOMP */
01130 }
01131 
01132 static void
01133 cleanup(void) {
01134         destroy_managers();
01135 
01136         ns_server_destroy(&ns_g_server);
01137 
01138         isc_entropy_detach(&ns_g_entropy);
01139         if (ns_g_fallbackentropy != NULL)
01140                 isc_entropy_detach(&ns_g_fallbackentropy);
01141 
01142         ns_builtin_deinit();
01143 
01144         /*
01145          * Add calls to unregister sdb drivers here.
01146          */
01147         /* xxdb_clear(); */
01148 
01149 #ifdef CONTRIB_DLZ
01150         /*
01151          * Unregister contributed DLZ drivers.
01152          */
01153         dlz_drivers_clear();
01154 #endif
01155 #ifdef ISC_DLZ_DLOPEN
01156         /*
01157          * Unregister "dlopen" DLZ driver.
01158          */
01159         dlz_dlopen_clear();
01160 #endif
01161 
01162         dns_name_destroy();
01163 
01164         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
01165                       ISC_LOG_NOTICE, "exiting");
01166         ns_log_shutdown();
01167 }
01168 
01169 static char *memstats = NULL;
01170 
01171 void
01172 ns_main_setmemstats(const char *filename) {
01173         /*
01174          * Caller has to ensure locking.
01175          */
01176 
01177         if (memstats != NULL) {
01178                 free(memstats);
01179                 memstats = NULL;
01180         }
01181         if (filename == NULL)
01182                 return;
01183         memstats = malloc(strlen(filename) + 1);
01184         if (memstats)
01185                 strcpy(memstats, filename);
01186 }
01187 
01188 #ifdef HAVE_LIBSCF
01189 /*
01190  * Get FMRI for the named process.
01191  */
01192 isc_result_t
01193 ns_smf_get_instance(char **ins_name, int debug, isc_mem_t *mctx) {
01194         scf_handle_t *h = NULL;
01195         int namelen;
01196         char *instance;
01197 
01198         REQUIRE(ins_name != NULL && *ins_name == NULL);
01199 
01200         if ((h = scf_handle_create(SCF_VERSION)) == NULL) {
01201                 if (debug)
01202                         UNEXPECTED_ERROR(__FILE__, __LINE__,
01203                                          "scf_handle_create() failed: %s",
01204                                          scf_strerror(scf_error()));
01205                 return (ISC_R_FAILURE);
01206         }
01207 
01208         if (scf_handle_bind(h) == -1) {
01209                 if (debug)
01210                         UNEXPECTED_ERROR(__FILE__, __LINE__,
01211                                          "scf_handle_bind() failed: %s",
01212                                          scf_strerror(scf_error()));
01213                 scf_handle_destroy(h);
01214                 return (ISC_R_FAILURE);
01215         }
01216 
01217         if ((namelen = scf_myname(h, NULL, 0)) == -1) {
01218                 if (debug)
01219                         UNEXPECTED_ERROR(__FILE__, __LINE__,
01220                                          "scf_myname() failed: %s",
01221                                          scf_strerror(scf_error()));
01222                 scf_handle_destroy(h);
01223                 return (ISC_R_FAILURE);
01224         }
01225 
01226         if ((instance = isc_mem_allocate(mctx, namelen + 1)) == NULL) {
01227                 UNEXPECTED_ERROR(__FILE__, __LINE__,
01228                                  "ns_smf_get_instance memory "
01229                                  "allocation failed: %s",
01230                                  isc_result_totext(ISC_R_NOMEMORY));
01231                 scf_handle_destroy(h);
01232                 return (ISC_R_FAILURE);
01233         }
01234 
01235         if (scf_myname(h, instance, namelen + 1) == -1) {
01236                 if (debug)
01237                         UNEXPECTED_ERROR(__FILE__, __LINE__,
01238                                          "scf_myname() failed: %s",
01239                                          scf_strerror(scf_error()));
01240                 scf_handle_destroy(h);
01241                 isc_mem_free(mctx, instance);
01242                 return (ISC_R_FAILURE);
01243         }
01244 
01245         scf_handle_destroy(h);
01246         *ins_name = instance;
01247         return (ISC_R_SUCCESS);
01248 }
01249 #endif /* HAVE_LIBSCF */
01250 
01251 /* main entry point, possibly hooked */
01252 
01253 int
01254 main(int argc, char *argv[]) {
01255         isc_result_t result;
01256 #ifdef HAVE_LIBSCF
01257         char *instance = NULL;
01258 #endif
01259 
01260 #ifdef HAVE_GPERFTOOLS_PROFILER
01261         (void) ProfilerStart(NULL);
01262 #endif
01263 
01264         /*
01265          * Record version in core image.
01266          * strings named.core | grep "named version:"
01267          */
01268         strlcat(version,
01269 #if defined(NO_VERSION_DATE) || !defined(__DATE__)
01270                 "named version: BIND " VERSION " <" SRCID ">",
01271 #else
01272                 "named version: BIND " VERSION " <" SRCID "> (" __DATE__ ")",
01273 #endif
01274                 sizeof(version));
01275         result = isc_file_progname(*argv, program_name, sizeof(program_name));
01276         if (result != ISC_R_SUCCESS)
01277                 ns_main_earlyfatal("program name too long");
01278 
01279         if (strcmp(program_name, "lwresd") == 0)
01280                 ns_g_lwresdonly = ISC_TRUE;
01281 
01282         if (result != ISC_R_SUCCESS)
01283                 ns_main_earlyfatal("failed to build internal symbol table");
01284 
01285         isc_assertion_setcallback(assertion_failed);
01286         isc_error_setfatal(library_fatal_error);
01287         isc_error_setunexpected(library_unexpected_error);
01288 
01289         ns_os_init(program_name);
01290 
01291         dns_result_register();
01292         dst_result_register();
01293         isccc_result_register();
01294 #ifdef PKCS11CRYPTO
01295         pk11_result_register();
01296 #endif
01297 
01298         parse_command_line(argc, argv);
01299 
01300         /*
01301          * Warn about common configuration error.
01302          */
01303         if (ns_g_chrootdir != NULL) {
01304                 int len = strlen(ns_g_chrootdir);
01305                 if (strncmp(ns_g_chrootdir, ns_g_conffile, len) == 0 &&
01306                     (ns_g_conffile[len] == '/' || ns_g_conffile[len] == '\\'))
01307                         ns_main_earlywarning("config filename (-c %s) contains "
01308                                              "chroot path (-t %s)",
01309                                              ns_g_conffile, ns_g_chrootdir);
01310         }
01311 
01312         result = isc_mem_create(0, 0, &ns_g_mctx);
01313         if (result != ISC_R_SUCCESS)
01314                 ns_main_earlyfatal("isc_mem_create() failed: %s",
01315                                    isc_result_totext(result));
01316         isc_mem_setname(ns_g_mctx, "main", NULL);
01317 
01318         setup();
01319 
01320         /*
01321          * Start things running and then wait for a shutdown request
01322          * or reload.
01323          */
01324         do {
01325                 result = isc_app_run();
01326 
01327                 if (result == ISC_R_RELOAD) {
01328                         ns_server_reloadwanted(ns_g_server);
01329                 } else if (result != ISC_R_SUCCESS) {
01330                         UNEXPECTED_ERROR(__FILE__, __LINE__,
01331                                          "isc_app_run(): %s",
01332                                          isc_result_totext(result));
01333                         /*
01334                          * Force exit.
01335                          */
01336                         result = ISC_R_SUCCESS;
01337                 }
01338         } while (result != ISC_R_SUCCESS);
01339 
01340 #ifdef HAVE_LIBSCF
01341         if (ns_smf_want_disable == 1) {
01342                 result = ns_smf_get_instance(&instance, 1, ns_g_mctx);
01343                 if (result == ISC_R_SUCCESS && instance != NULL) {
01344                         if (smf_disable_instance(instance, 0) != 0)
01345                                 UNEXPECTED_ERROR(__FILE__, __LINE__,
01346                                                  "smf_disable_instance() "
01347                                                  "failed for %s : %s",
01348                                                  instance,
01349                                                  scf_strerror(scf_error()));
01350                 }
01351                 if (instance != NULL)
01352                         isc_mem_free(ns_g_mctx, instance);
01353         }
01354 #endif /* HAVE_LIBSCF */
01355 
01356         cleanup();
01357 
01358         if (want_stats) {
01359                 isc_mem_stats(ns_g_mctx, stdout);
01360                 isc_mutex_stats(stdout);
01361         }
01362 
01363         if (ns_g_memstatistics && memstats != NULL) {
01364                 FILE *fp = NULL;
01365                 result = isc_stdio_open(memstats, "w", &fp);
01366                 if (result == ISC_R_SUCCESS) {
01367                         isc_mem_stats(ns_g_mctx, fp);
01368                         isc_mutex_stats(fp);
01369                         isc_stdio_close(fp);
01370                 }
01371         }
01372         isc_mem_destroy(&ns_g_mctx);
01373         isc_mem_checkdestroyed(stderr);
01374 
01375         ns_main_setmemstats(NULL);
01376 
01377         isc_app_finish();
01378 
01379         ns_os_closedevnull();
01380 
01381         ns_os_shutdown();
01382 
01383 #ifdef HAVE_GPERFTOOLS_PROFILER
01384         ProfilerStop();
01385 #endif
01386 
01387         return (0);
01388 }

Generated on Tue Apr 28 17:40:54 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha