static void message_viewer_wire_end(message_viewer *mv, long time_duration) { output_stream *os = mv->os; time_t timep; time(&timep); osformat(os, ";; Query time: %ld msec\n", time_duration); /** @todo 20150716 gve -- still need to implemented the server viewable line */ // osformat(os, ";; SERVER: %{hostaddr}(%{hostaddr})\n", config->server, config->server); osformat(os, ";; WHEN: %s", ctime(&timep)); if(mv->view_mode_with & VM_WITH_XFR) { osformatln(os, ";; XFR size: %lu records (messages %lu, bytes %lu)", mv->resource_records_total[1], mv->messages, mv->bytes); } else { osformatln(os, ";; MSG SIZE rcvd: %ld", mv->bytes); } osformat(os, "\n"); }
static void message_viewer_wire_start(message_viewer *mv) { output_stream *os = mv->os; /* ------------------------------------------------------------ */ osformatln(os, "; ( server found)"); /// @todo 20150709 gve -- still need to find a way to show amount of servers osformatln(os, ";; global options: "); /// @todo 20150709 gve -- no global options given output_stream *os = mv->os; }
static ya_result config_zone_section_init(config_data *config) { ya_result return_code; tmp_zone_idx++; /* store the previously configured zone, if any */ config_zone_section_register(config); /* make a new zone section ready */ tmp_zones = zone_alloc(); if(FAIL(return_code = confs_init(zone_tab, tmp_zones))) { zone_free(tmp_zones); tmp_zones = NULL; osformatln(termerr, "config: zone: configuration initialize (zone): %r", return_code); } return return_code; }
void tcp_init_with_env() { char tmp[256]; const char* tcp_flags_cfg = getenv(DNSCORE_TCP_FLAGS); if(tcp_flags_cfg != NULL) { strncpy(tmp, tcp_flags_cfg, sizeof(tmp)-1); tmp[sizeof(tmp) - 1] = '\0'; size_t tmp_len = strlen(tmp); for(int i = 0; i < tmp_len; i++) { if(tmp[i] == ',') { tmp[i] = ' '; } } const char *p = parse_skip_spaces(tmp); while(*p != '\0') { s32 keyword = -1; s32 word_len = parse_skip_word_specific(p, strlen(p), tcp_env_keywords, 4, &keyword); if(FAIL(word_len)) { break; } switch(keyword) { case 0: // nodelay tcp_nodelay = TRUE; break; case 1: // delay tcp_nodelay = FALSE; break; case 2: // cork tcp_cork = TRUE; break; case 3: // nocork tcp_cork = FALSE; break; default: osformatln(termerr, "syntax error in env %s", DNSCORE_TCP_FLAGS); flusherr(); break; } p += word_len; p = parse_skip_spaces(p); } } }
void print_version(int level) { switch(level) { case 1: osformatln(termout, "%s %s (%s)", PROGRAM_NAME, PROGRAM_VERSION, RELEASEDATE); break; case 2: osformatln(termout, "%s %s (released %s, compiled %s)", PROGRAM_NAME, PROGRAM_VERSION, RELEASEDATE, COMPILEDATE); break; case 3: osformatln(termout, "%s %s (released %s, compiled %s)", PROGRAM_NAME, PROGRAM_VERSION, RELEASEDATE, COMPILEDATE); show_authors(); break; default: osformat(termout, "\nYou want to know too much!\n\n"); break; } }
/** @brief Function for setting the parameters found in the zone container * * @code * <zone> * ... * </zone> * @endcode * * @param[in] variable * @param[in] value * @param[out] config * * @retval OK * @retval NONE */ static ya_result set_variable_zone(char *variable, char *value, char *argument) { ya_result return_code = confs_set(zone_tab, tmp_zones, variable, value); if(FAIL(return_code)) { osformatln(termerr, "error: setting variable: zone.%s = '%s': %r", variable, value, return_code); } return return_code; }
static void message_viewer_wire_question_record(message_viewer *mv, u8 *record_wire, u16 rclass, u16 rtype) { if(mv->view_mode_with & VM_WITH_XFR) { return; } output_stream *os_ = mv->os; /* * There is no padding support for formats on complex types (padding is ignored) * Doing it would be relatively expensive for it's best doing it manually when needed (afaik: only here) */ counter_output_stream_data counters; output_stream cos; counter_output_stream_init(os_, &cos, &counters); output_stream *os = &cos; u64 next = counters.write_count + 24 + 8; /* write NAME + alignment for next item */ osformat(os, ";%{dnsname}", record_wire, ' '); while(counters.write_count < next) { output_stream_write_u8(os, (u8) ' '); } output_stream_write_u8(os, (u8) ' '); next = counters.write_count + 7; /* write CLASS + alignment for next item */ osformat(os, "%7{dnsclass}", &rclass); while(counters.write_count < next) { output_stream_write_u8(os, (u8) ' '); } output_stream_write_u8(os, (u8) ' '); // next = counters.write_count + 7; /* write TYPE */ osformatln(os, "%7{dnstype}", &rtype); }
static ya_result config_zone_section_assign(config_data *config) { u32 port = 0; ya_result return_code; config_zone_section_register(config); if(FAIL(return_code = parse_u32_check_range(config->server_port, &port, 1, MAX_U16, 10))) { osformatln(termerr, "config: zone: wrong dns port set in main '%s': %r", config->server_port, return_code); return return_code; } zone_set_lock(&config->zones); treeset_avl_iterator iter; treeset_avl_iterator_init(&config->zones.set, &iter); while(treeset_avl_iterator_hasnext(&iter)) { treeset_node *zone_node = treeset_avl_iterator_next_node(&iter); zone_data *zone = (zone_data *)zone_node->data; zone_setdefaults(zone); if(!config_check_bounds_s32(SIGNATURE_VALIDITY_INTERVAL_MIN, SIGNATURE_VALIDITY_INTERVAL_MAX, zone->sig_validity_interval, "sig-validity-interval")) { return ERROR; } if(!config_check_bounds_s32(SIGNATURE_VALIDITY_REGENERATION_MIN, SIGNATURE_VALIDITY_REGENERATION_MAX, zone->sig_validity_regeneration, "sig-validity-regeneration")) { return ERROR; } if(!config_check_bounds_s32(SIGNATURE_VALIDITY_JITTER_MIN, SIGNATURE_VALIDITY_JITTER_MAX, zone->sig_validity_jitter, "sig-validity-jitter")) { return ERROR; } if(!config_check_bounds_s32(NOTIFY_RETRY_COUNT_MIN, NOTIFY_RETRY_COUNT_MAX, zone->notify.retry_count, "notify-retry-count")) { return ERROR; } if(!config_check_bounds_s32(NOTIFY_RETRY_PERIOD_MIN, NOTIFY_RETRY_PERIOD_MAX, zone->notify.retry_period, "notify-period-count")) { return ERROR; } if(!config_check_bounds_s32(NOTIFY_RETRY_PERIOD_INCREASE_MIN, NOTIFY_RETRY_PERIOD_INCREASE_MAX, zone->notify.retry_period_increase, "notify-period-increase")) { return ERROR; } zone->ctrl_flags |= ZONE_CTRL_FLAG_READ_FROM_CONF; } zone_set_unlock(&config->zones); return SUCCESS; }
static ya_result config_main_section_postprocess(struct config_section_descriptor_s *csd) { u32 port = 0; u32 cpu_per_core = (sys_has_hyperthreading())?2:1; int ret; char tmp[PATH_MAX]; if(FAIL(parse_u32_check_range(g_config->server_port, &port, 1, MAX_U16, 10))) { port = DNS_DEFAULT_PORT; ttylog_err("config: main: wrong dns port set in main '%s', defaulted to %d", g_config->server_port, port); } if(g_config->hostname_chaos == NULL) { #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200112L if(gethostname(tmp, sizeof(tmp)) == 0) { g_config->hostname_chaos = strdup(tmp); } else { osformatln(termerr,"config: main: unable to get hostname: %r", ERRNO_ERROR); g_config->hostname_chaos = strdup("not disclosed"); } #else g_config->hostname_chaos = strdup("not disclosed"); #endif } if(g_config->thread_affinity_multiplier == 0) { g_config->thread_affinity_multiplier = cpu_per_core; } class_ch_set_hostname(g_config->hostname_chaos); class_ch_set_id_server(g_config->serverid_chaos); class_ch_set_version(g_config->version_chaos); host_set_default_port_value(g_config->listen, ntohs(port)); if(g_config->server_flags & SERVER_FL_CHROOT) { uid_t euid = geteuid(); if(euid != 0) { ttylog_err("config: main: chroot has been enabled but euid is not root (%i != 0)", (int)euid); return INVALID_STATE_ERROR; } } else // disables the base-path/chroot-path feature { if(strcmp(g_config->chroot_path, "/") != 0) { free(g_config->chroot_path); g_config->chroot_path = strdup("/"); chroot_set_path(g_config->chroot_path); } } message_edns0_setmaxsize(g_config->edns0_max_size); g_config->total_interfaces = host_address_count(g_config->listen); if(g_config->total_interfaces > MAX_INTERFACES) { ttylog_err("error: more than %d listening addresses defined.", MAX_INTERFACES); return CONFIG_TOO_MANY_HOSTS; } #ifndef SO_REUSEPORT if(g_config->network_model == 1) { ttylog_err("error: network-model 1 requires features not available on this system (SO_REUSEPORT)"); return FEATURE_NOT_SUPPORTED; } #endif g_config->axfr_retry_jitter = BOUND(AXFR_RETRY_JITTER_MIN, g_config->axfr_retry_jitter, g_config->axfr_retry_delay); g_config->dnssec_thread_count = BOUND(1, g_config->dnssec_thread_count, sys_get_cpu_count()); if(g_config->cpu_count_override > 0) { sys_set_cpu_count(g_config->cpu_count_override); } if(g_config->thread_count_by_address == 0) { ttylog_err("config: single thread engine has been removed, thread-count-by-address set to 1"); g_config->thread_count_by_address = 1; } if(g_config->thread_count_by_address < 0) { g_config->thread_count_by_address = MAX(sys_get_cpu_count() / cpu_per_core, 1); } else if((g_config->thread_count_by_address > sys_get_cpu_count())) { g_config->thread_count_by_address = MAX(sys_get_cpu_count() / cpu_per_core, 1); ttylog_err("config: bounding down thread-count-by-address to the number of physical CPUs (%d)", g_config->thread_count_by_address); } g_config->tcp_query_min_rate_us = g_config->tcp_query_min_rate * 0.000001; #if HAS_DNSSEC_SUPPORT g_config->dnssec_thread_count = BOUND(1, g_config->dnssec_thread_count, sys_get_cpu_count()); if(!IS_TYPE_PRIVATE(g_config->sig_signing_type)) { ttylog_err("error: signing type is not in the accepted range: %hx", g_config->sig_signing_type); return CONFIG_WRONG_SIG_TYPE; } if(g_config->sig_validity_interval > SIGNATURE_VALIDITY_INTERVAL_MAX) { ttylog_err("error: signature validity interval too high"); return CONFIG_WRONG_SIG_VALIDITY; } if(g_config->sig_validity_regeneration * SIGNATURE_VALIDITY_REGENERATION_S * 2 > g_config->sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S) { ttylog_err("error: default signature regeneration is more than half the interval (%ds * 2 > %ds)", g_config->sig_validity_regeneration * SIGNATURE_VALIDITY_REGENERATION_S, g_config->sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S); return CONFIG_WRONG_SIG_REGEN; } #endif /// @note config_main_verify_and_update_directory updates the folder with the base_path /** * * @note All base paths are updated with the chroot variable so it does not * need to be added all the time. * */ const char *base_path = g_config->chroot_path; if(FAIL(ret = config_main_verify_and_update_directory(base_path, &g_config->data_path))) { return ret; } if(FAIL(ret = config_main_verify_and_update_directory(base_path, &g_config->keys_path))) { return ret; } if(FAIL(ret = config_main_verify_and_update_directory(base_path, &g_config->log_path))) { return ret; } #if 0 /* fix */ #else if(FAIL(ret = config_main_verify_and_update_file(base_path, &g_config->pid_file))) { return ret; } #endif g_config->reloadable = TRUE; if((g_config->server_flags & SERVER_FL_CHROOT) != 0) { if(FAIL(chroot_manage_path(&g_config->config_file, g_config->config_file, FALSE))) { log_warn("config file '%s' will not be accessible within the chroot jail '%s' : config reload will not work", g_config->config_file, base_path); g_config->reloadable = FALSE; } } if(FAIL(ret = config_main_verify_and_update_directory(base_path, &g_config->xfr_path))) { return ret; } #if ZDB_HAS_DNSSEC_SUPPORT dnssec_keystore_setpath(g_config->keys_path); dnssec_set_xfr_path(g_config->xfr_path); journal_set_xfr_path(g_config->xfr_path); #endif if((logger_get_uid() != g_config->uid) || (logger_get_gid() != g_config->gid)) { logger_set_uid(g_config->uid); logger_set_gid(g_config->gid); logger_reopen(); } return SUCCESS; }
void zdb_init() { if(zdb_init_done) { return; } /* DO or DIE */ if(dnscore_getfingerprint() != (dnsdb_getfingerprint() & dnscore_fingerprint_mask())) { osformatln(termerr, "Mismatched fingerprints: %08x != (%08x = %08x & %08x)", dnscore_getfingerprint(), dnsdb_getfingerprint() & dnscore_fingerprint_mask(), dnsdb_getfingerprint() , dnscore_fingerprint_mask()); flusherr(); exit(-1); } zdb_init_done = TRUE; /* Init the dns core */ dnscore_init(); /* Init the error table */ zdb_register_errors(); /* Init the hash tables */ hash_init(); #if ZDB_OPENSSL_SUPPORT!=0 /* Init openssl */ ENGINE_load_openssl(); ENGINE_load_builtin_engines(); ssl_mutex_count = CRYPTO_num_locks(); MALLOC_OR_DIE(pthread_mutex_t*, ssl_mutex, ssl_mutex_count * sizeof (pthread_mutex_t), ZDB_SSLMUTEX_TAG); int i; for(i = 0; i < ssl_mutex_count; i++) { pthread_mutex_init(&ssl_mutex[i], NULL); } CRYPTO_set_id_callback(ssl_thread_id); CRYPTO_set_locking_callback(ssl_lock); #endif #if ZDB_USE_THREADPOOL != 0 /* * The default value for the database. * This initialization will do nothing if it has already been done. * * The server will have to do it before calling zdb_init(); * */ u32 count = sys_get_cpu_count() + 2; ya_result return_value = thread_pool_init(count); if(FAIL(return_value)) { log_crit("unable to initialise the thread pool to %d threads: %r", count, return_value); /* will ultimately lead to the end of the program */ exit(-1); } thread_pool_initialized_by_zdb = (return_value == count); #endif #if ZDB_USES_ZALLOC != 0 zdb_set_zowner(pthread_self()); #endif logger_start(); zdb_rdtsc_registations(); }
static ya_result config_section_handles_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { if(logger_channel_get_usage_count(key) >= 0) { return CONFIG_LOGGER_HANDLE_ALREADY_DEFINED; // already defined } char value_target[PATH_MAX]; parse_copy_word(value_target, sizeof(value_target), value); if(strcasecmp("stdout", value_target) == 0) { output_stream stdout_os; fd_output_stream_attach(&stdout_os, dup_ex(1)); logger_channel *stdout_channel = logger_channel_alloc(); logger_channel_stream_open(&stdout_os, FALSE, stdout_channel); logger_channel_register(key, stdout_channel); } else if(strcasecmp("stderr", value_target) == 0) { output_stream stderr_os; fd_output_stream_attach(&stderr_os, dup_ex(2)); logger_channel *stderr_channel = logger_channel_alloc(); logger_channel_stream_open(&stderr_os, FALSE, stderr_channel); logger_channel_register(key, stderr_channel); } else if(strcasecmp("syslog", value_target) == 0) { char* token; /* * Tokenize */ u32 options = 0; u32 facility = 0; /* WARNING: NEVER EVER USE A CONST STRING AS ARGUMENT OR strtok WILL SIGSEGV */ char *tmp_value = strdup(value); // value, not value_target for(token = strtok(tmp_value, SYSLOG_CHANNEL_TOKEN_DELIMITER); token != NULL; token = strtok(NULL, SYSLOG_CHANNEL_TOKEN_DELIMITER)) { u32 token_value; if(ISOK(get_value_from_casename(syslog_channel_arguments_options, token, &token_value))) { options |= token_value; } else if(ISOK(get_value_from_casename(syslog_channel_arguments_facility, token, &token_value))) { facility = token_value; // Facility is NOT a bit mask } else { /* Note: empty statement is taken care of here */ osformatln(termerr, "wrong syslog argument '%s' : ", csd->vtbl->name); free(tmp_value); return PARSE_INVALID_ARGUMENT; } } free(tmp_value); logger_channel *syslog_channel = logger_channel_alloc(); logger_channel_syslog_open(key, options, facility, syslog_channel); logger_channel_register(key, syslog_channel); } else { const char *chroot_base = chroot_get_path(); uid_t uid = logger_get_uid(); gid_t gid = logger_get_gid(); ya_result return_code; unsigned int access_rights; char fullpath[PATH_MAX]; // find the end of the word // cut it const char *path_limit = parse_next_blank(value); size_t path_len = path_limit - value; size_t pathbase_len; if(value[0] != '/') { pathbase_len = snformat(fullpath, sizeof(fullpath), "%s%s", chroot_base, log_path); } else { pathbase_len = snformat(fullpath, sizeof(fullpath), "%s", chroot_base); } if(pathbase_len + path_len + 1 >= sizeof(fullpath)) { return CONFIG_FILE_PATH_TOO_BIG; } memcpy(&fullpath[pathbase_len], value, path_len); path_len += pathbase_len; fullpath[path_len] = '\0'; // parse the next word, it is supposed to be an octal number if(sscanf(path_limit, "%o", &access_rights) != 1) { access_rights = FILE_CHANNEL_DEFAULT_ACCESS_RIGHTS; } // if the path starts with a slash, it's absolute, else it's relative // to the log directory logger_channel* file_channel = logger_channel_alloc(); if(FAIL(return_code = logger_channel_file_open(fullpath, uid, gid, access_rights, FALSE, file_channel))) { osformatln(termerr, "config: unable to open file channel '%s' (%d:%d %o) : %r", fullpath, uid, gid, access_rights, return_code); flusherr(); return return_code; } logger_channel_register(key, file_channel); } return SUCCESS; }