00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00064
00065
00066 #define NS_MAIN 1
00067
00068 #include <named/builtin.h>
00069 #include <named/control.h>
00070 #include <named/globals.h>
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
00091
00092
00093
00094 #ifdef CONTRIB_DLZ
00095
00096
00097
00098 #include <dlz/dlz_drivers.h>
00099 #endif
00100
00101
00102
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
00178
00179
00180 if (ns_g_lctx != NULL) {
00181
00182
00183
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
00246
00247
00248 if (ns_g_lctx != NULL) {
00249
00250
00251
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
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
00347
00348
00349
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
00440
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
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
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':
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
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
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
00541 ns_g_chrootdir = isc_commandline_argument;
00542 break;
00543 case 'T':
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
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
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
00692
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
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
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
00819
00820
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
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
00901
00902
00903 seccomp_release(ctx);
00904 }
00905 #endif
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
00917
00918
00919
00920 ns_os_inituserinfo(ns_g_username);
00921
00922
00923
00924
00925 ns_os_tzset();
00926
00927 ns_os_opendevnull();
00928
00929 #ifdef HAVE_LIBSCF
00930
00931 result = ns_smf_get_instance(&instance, 0, ns_g_mctx);
00932
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
00940
00941 #ifdef PATH_RANDOMDEV
00942
00943
00944
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
00967
00968 ns_g_cpus_detected = isc_os_ncpus();
00969 #endif
00970
00971 ns_os_chroot(ns_g_chrootdir);
00972
00973
00974
00975
00976
00977
00978
00979
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
00990
00991
00992
00993
00994
00995 if (!ns_g_foreground)
00996 ns_os_daemonize();
00997
00998
00999
01000
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
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
01055
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
01072
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
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
01102
01103
01104
01105 #ifdef ISC_DLZ_DLOPEN
01106
01107
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
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
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
01146
01147
01148
01149 #ifdef CONTRIB_DLZ
01150
01151
01152
01153 dlz_drivers_clear();
01154 #endif
01155 #ifdef ISC_DLZ_DLOPEN
01156
01157
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
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
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
01250
01251
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
01266
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
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
01322
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
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
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 }