static void setup(void) { isc_result_t result; isc_resourcevalue_t old_openfiles; #ifdef HAVE_LIBSCF char *instance = NULL; #endif /* * Get the user and group information before changing the root * directory, so the administrator does not need to keep a copy * of the user and group databases in the chroot'ed environment. */ ns_os_inituserinfo(ns_g_username); /* * Initialize time conversion information */ ns_os_tzset(); ns_os_opendevnull(); #ifdef HAVE_LIBSCF /* Check if named is under smf control, before chroot. */ result = ns_smf_get_instance(&instance, 0, ns_g_mctx); /* We don't care about instance, just check if we got one. */ if (result == ISC_R_SUCCESS) ns_smf_got_instance = 1; else ns_smf_got_instance = 0; if (instance != NULL) isc_mem_free(ns_g_mctx, instance); #endif /* HAVE_LIBSCF */ #ifdef PATH_RANDOMDEV /* * Initialize system's random device as fallback entropy source * if running chroot'ed. */ if (ns_g_chrootdir != NULL) { result = isc_entropy_create(ns_g_mctx, &ns_g_fallbackentropy); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("isc_entropy_create() failed: %s", isc_result_totext(result)); result = isc_entropy_createfilesource(ns_g_fallbackentropy, PATH_RANDOMDEV); if (result != ISC_R_SUCCESS) { ns_main_earlywarning("could not open pre-chroot " "entropy source %s: %s", PATH_RANDOMDEV, isc_result_totext(result)); isc_entropy_detach(&ns_g_fallbackentropy); } } #endif #ifdef ISC_PLATFORM_USETHREADS /* * Check for the number of cpu's before ns_os_chroot(). */ ns_g_cpus_detected = isc_os_ncpus(); #endif ns_os_chroot(ns_g_chrootdir); /* * For operating systems which have a capability mechanism, now * is the time to switch to minimal privs and change our user id. * On traditional UNIX systems, this call will be a no-op, and we * will change the user ID after reading the config file the first * time. (We need to read the config file to know which possibly * privileged ports to bind() to.) */ ns_os_minprivs(); result = ns_log_init(ISC_TF(ns_g_username != NULL)); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("ns_log_init() failed: %s", isc_result_totext(result)); /* * Now is the time to daemonize (if we're not running in the * foreground). We waited until now because we wanted to get * a valid logging context setup. We cannot daemonize any later, * because calling create_managers() will create threads, which * would be lost after fork(). */ if (!ns_g_foreground) ns_os_daemonize(); /* * We call isc_app_start() here as some versions of FreeBSD's fork() * destroys all the signal handling it sets up. */ result = isc_app_start(); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("isc_app_start() failed: %s", isc_result_totext(result)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "starting %s %s%s%s <id:%s>", ns_g_product, ns_g_version, *ns_g_description ? " " : "", ns_g_description, ns_g_srcid); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "built with %s", ns_g_configargs); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "running as: %s%s", program_name, saved_command_line); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "----------------------------------------------------"); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "BIND 9 is maintained by Internet Systems Consortium,"); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "Inc. (ISC), a non-profit 501(c)(3) public-benefit "); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "corporation. Support and training for BIND 9 are "); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "available at https://www.isc.org/support"); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "----------------------------------------------------"); dump_symboltable(); /* * Get the initial resource limits. */ (void)isc_resource_getlimit(isc_resource_stacksize, &ns_g_initstacksize); (void)isc_resource_getlimit(isc_resource_datasize, &ns_g_initdatasize); (void)isc_resource_getlimit(isc_resource_coresize, &ns_g_initcoresize); (void)isc_resource_getlimit(isc_resource_openfiles, &ns_g_initopenfiles); /* * System resources cannot effectively be tuned on some systems. * Raise the limit in such cases for safety. */ old_openfiles = ns_g_initopenfiles; ns_os_adjustnofile(); (void)isc_resource_getlimit(isc_resource_openfiles, &ns_g_initopenfiles); if (old_openfiles != ns_g_initopenfiles) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "adjusted limit on open files from " "%" ISC_PRINT_QUADFORMAT "u to " "%" ISC_PRINT_QUADFORMAT "u", old_openfiles, ns_g_initopenfiles); } /* * If the named configuration filename is relative, prepend the current * directory's name before possibly changing to another directory. */ if (! isc_file_isabsolute(ns_g_conffile)) { result = isc_file_absolutepath(ns_g_conffile, absolute_conffile, sizeof(absolute_conffile)); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("could not construct absolute path " "of configuration file: %s", isc_result_totext(result)); ns_g_conffile = absolute_conffile; } /* * Record the server's startup time. */ result = isc_time_now(&ns_g_boottime); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("isc_time_now() failed: %s", isc_result_totext(result)); result = create_managers(); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("create_managers() failed: %s", isc_result_totext(result)); ns_builtin_init(); /* * Add calls to register sdb drivers here. */ /* xxdb_init(); */ #ifdef ISC_DLZ_DLOPEN /* * Register the DLZ "dlopen" driver. */ result = dlz_dlopen_init(ns_g_mctx); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("dlz_dlopen_init() failed: %s", isc_result_totext(result)); #endif #if CONTRIB_DLZ /* * Register any other contributed DLZ drivers. */ result = dlz_drivers_init(); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("dlz_drivers_init() failed: %s", isc_result_totext(result)); #endif ns_server_create(ns_g_mctx, &ns_g_server); #ifdef HAVE_LIBSECCOMP setup_seccomp(); #endif /* HAVE_LIBSECCOMP */ }
FILE * ns_os_openfile(const char *filename, mode_t mode, isc_boolean_t switch_user) { char strbuf[ISC_STRERRORSIZE], *f; FILE *fp; int fd; /* * Make the containing directory if it doesn't exist. */ f = strdup(filename); if (f == NULL) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("couldn't strdup() '%s': %s", filename, strbuf); return (NULL); } if (mkdirpath(f, ns_main_earlywarning) == -1) { free(f); return (NULL); } free(f); if (switch_user && runas_pw != NULL) { #ifndef HAVE_LINUXTHREADS gid_t oldgid = getgid(); #endif /* Set UID/GID to the one we'll be running with eventually */ setperms(runas_pw->pw_uid, runas_pw->pw_gid); fd = safe_open(filename, mode, ISC_FALSE); #ifndef HAVE_LINUXTHREADS /* Restore UID/GID to root */ setperms(0, oldgid); #endif /* HAVE_LINUXTHREADS */ if (fd == -1) { #ifndef HAVE_LINUXTHREADS fd = safe_open(filename, mode, ISC_FALSE); if (fd != -1) { ns_main_earlywarning("Required root " "permissions to open " "'%s'.", filename); } else { ns_main_earlywarning("Could not open " "'%s'.", filename); } ns_main_earlywarning("Please check file and " "directory permissions " "or reconfigure the filename."); #else /* HAVE_LINUXTHREADS */ ns_main_earlywarning("Could not open " "'%s'.", filename); ns_main_earlywarning("Please check file and " "directory permissions " "or reconfigure the filename."); #endif /* HAVE_LINUXTHREADS */ } } else { fd = safe_open(filename, mode, ISC_FALSE); } if (fd < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("could not open file '%s': %s", filename, strbuf); return (NULL); } fp = fdopen(fd, "w"); if (fp == NULL) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("could not fdopen() file '%s': %s", filename, strbuf); } return (fp); }
int main(int argc, char *argv[]) { isc_result_t result; #ifdef HAVE_LIBSCF char *instance = NULL; #endif #ifdef HAVE_GPERFTOOLS_PROFILER (void) ProfilerStart(NULL); #endif /* * Record version in core image. * strings named.core | grep "named version:" */ strlcat(version, #if defined(NO_VERSION_DATE) || !defined(__DATE__) "named version: BIND " VERSION " <" SRCID ">", #else "named version: BIND " VERSION " <" SRCID "> (" __DATE__ ")", #endif sizeof(version)); result = isc_file_progname(*argv, program_name, sizeof(program_name)); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("program name too long"); if (strcmp(program_name, "lwresd") == 0) ns_g_lwresdonly = ISC_TRUE; if (result != ISC_R_SUCCESS) ns_main_earlyfatal("failed to build internal symbol table"); isc_assertion_setcallback(assertion_failed); isc_error_setfatal(library_fatal_error); isc_error_setunexpected(library_unexpected_error); ns_os_init(program_name); dns_result_register(); dst_result_register(); isccc_result_register(); #ifdef PKCS11CRYPTO pk11_result_register(); #endif parse_command_line(argc, argv); /* * Warn about common configuration error. */ if (ns_g_chrootdir != NULL) { int len = strlen(ns_g_chrootdir); if (strncmp(ns_g_chrootdir, ns_g_conffile, len) == 0 && (ns_g_conffile[len] == '/' || ns_g_conffile[len] == '\\')) ns_main_earlywarning("config filename (-c %s) contains " "chroot path (-t %s)", ns_g_conffile, ns_g_chrootdir); } result = isc_mem_create(0, 0, &ns_g_mctx); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("isc_mem_create() failed: %s", isc_result_totext(result)); isc_mem_setname(ns_g_mctx, "main", NULL); setup(); /* * Start things running and then wait for a shutdown request * or reload. */ do { result = isc_app_run(); if (result == ISC_R_RELOAD) { ns_server_reloadwanted(ns_g_server); } else if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_run(): %s", isc_result_totext(result)); /* * Force exit. */ result = ISC_R_SUCCESS; } } while (result != ISC_R_SUCCESS); #ifdef HAVE_LIBSCF if (ns_smf_want_disable == 1) { result = ns_smf_get_instance(&instance, 1, ns_g_mctx); if (result == ISC_R_SUCCESS && instance != NULL) { if (smf_disable_instance(instance, 0) != 0) UNEXPECTED_ERROR(__FILE__, __LINE__, "smf_disable_instance() " "failed for %s : %s", instance, scf_strerror(scf_error())); } if (instance != NULL) isc_mem_free(ns_g_mctx, instance); } #endif /* HAVE_LIBSCF */ cleanup(); if (want_stats) { isc_mem_stats(ns_g_mctx, stdout); isc_mutex_stats(stdout); } if (ns_g_memstatistics && memstats != NULL) { FILE *fp = NULL; result = isc_stdio_open(memstats, "w", &fp); if (result == ISC_R_SUCCESS) { isc_mem_stats(ns_g_mctx, fp); isc_mutex_stats(fp); isc_stdio_close(fp); } } isc_mem_destroy(&ns_g_mctx); isc_mem_checkdestroyed(stderr); ns_main_setmemstats(NULL); isc_app_finish(); ns_os_closedevnull(); ns_os_shutdown(); #ifdef HAVE_GPERFTOOLS_PROFILER ProfilerStop(); #endif return (0); }