📄 server.c
字号:
ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE); clean: ns_listenlist_detach(&list); return; fail: /* * Even when we failed the procedure, most of other interfaces * should work correctly. We therefore just warn it. */ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "could not adjust the listen-on list; " "some interfaces may not work"); goto clean;}/* * This event callback is invoked to do periodic network * interface scanning. */static voidinterface_timer_tick(isc_task_t *task, isc_event_t *event) { isc_result_t result; ns_server_t *server = (ns_server_t *) event->ev_arg; INSIST(task == server->task); UNUSED(task); isc_event_free(&event); /* * XXX should scan interfaces unlocked and get exclusive access * only to replace ACLs. */ result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); scan_interfaces(server, ISC_FALSE); isc_task_endexclusive(server->task);}static voidheartbeat_timer_tick(isc_task_t *task, isc_event_t *event) { ns_server_t *server = (ns_server_t *) event->ev_arg; dns_view_t *view; UNUSED(task); isc_event_free(&event); view = ISC_LIST_HEAD(server->viewlist); while (view != NULL) { dns_view_dialup(view); view = ISC_LIST_NEXT(view, link); }}/* * Replace the current value of '*field', a dynamically allocated * string or NULL, with a dynamically allocated copy of the * null-terminated string pointed to by 'value', or NULL. */static isc_result_tsetstring(ns_server_t *server, char **field, const char *value) { char *copy; if (value != NULL) { copy = isc_mem_strdup(server->mctx, value); if (copy == NULL) return (ISC_R_NOMEMORY); } else { copy = NULL; } if (*field != NULL) isc_mem_free(server->mctx, *field); *field = copy; return (ISC_R_SUCCESS);} /* * Replace the current value of '*field', a dynamically allocated * string or NULL, with another dynamically allocated string * or NULL if whether 'obj' is a string or void value, respectively. */static isc_result_tsetoptstring(ns_server_t *server, char **field, cfg_obj_t *obj) { if (cfg_obj_isvoid(obj)) return (setstring(server, field, NULL)); else return (setstring(server, field, cfg_obj_asstring(obj)));}static voidset_limit(cfg_obj_t **maps, const char *configname, const char *description, isc_resource_t resourceid, isc_resourcevalue_t defaultvalue){ cfg_obj_t *obj = NULL; char *resource; isc_resourcevalue_t value; isc_result_t result; if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS) return; if (cfg_obj_isstring(obj)) { resource = cfg_obj_asstring(obj); if (strcasecmp(resource, "unlimited") == 0) value = ISC_RESOURCE_UNLIMITED; else { INSIST(strcasecmp(resource, "default") == 0); value = defaultvalue; } } else value = cfg_obj_asuint64(obj); result = isc_resource_setlimit(resourceid, value); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, result == ISC_R_SUCCESS ? ISC_LOG_DEBUG(3) : ISC_LOG_WARNING, "set maximum %s to %" ISC_PRINT_QUADFORMAT "d: %s", description, value, isc_result_totext(result));}#define SETLIMIT(cfgvar, resource, description) \ set_limit(maps, cfgvar, description, isc_resource_ ## resource, \ ns_g_init ## resource)static voidset_limits(cfg_obj_t **maps) { SETLIMIT("stacksize", stacksize, "stack size"); SETLIMIT("datasize", datasize, "data size"); SETLIMIT("coresize", coresize, "core size"); SETLIMIT("files", openfiles, "open files");}static isc_result_tportlist_fromconf(dns_portlist_t *portlist, unsigned int family, cfg_obj_t *ports){ cfg_listelt_t *element; isc_result_t result = ISC_R_SUCCESS; for (element = cfg_list_first(ports); element != NULL; element = cfg_list_next(element)) { cfg_obj_t *obj = cfg_listelt_value(element); in_port_t port = (in_port_t)cfg_obj_asuint32(obj); result = dns_portlist_add(portlist, family, port); if (result != ISC_R_SUCCESS) break; } return (result);}static isc_result_tload_configuration(const char *filename, ns_server_t *server, isc_boolean_t first_time){ isc_result_t result; cfg_parser_t *parser = NULL; cfg_obj_t *config; cfg_obj_t *options; cfg_obj_t *views; cfg_obj_t *obj; cfg_obj_t *v4ports, *v6ports; cfg_obj_t *maps[3]; cfg_obj_t *builtin_views; cfg_listelt_t *element; dns_view_t *view = NULL; dns_view_t *view_next; dns_viewlist_t viewlist; dns_viewlist_t tmpviewlist; ns_aclconfctx_t aclconfctx; isc_uint32_t interface_interval; isc_uint32_t heartbeat_interval; isc_uint32_t udpsize; in_port_t listen_port; int i; ns_aclconfctx_init(&aclconfctx); ISC_LIST_INIT(viewlist); /* Ensure exclusive access to configuration data. */ result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); /* * Parse the global default pseudo-config file. */ if (first_time) { CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config)); RUNTIME_CHECK(cfg_map_get(ns_g_config, "options", &ns_g_defaults) == ISC_R_SUCCESS); } /* * Parse the configuration file using the new config code. */ result = ISC_R_FAILURE; config = NULL; /* * Unless this is lwresd with the -C option, parse the config file. */ if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading configuration from '%s'", filename); CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); cfg_parser_setcallback(parser, directory_callback, NULL); result = cfg_parse_file(parser, filename, &cfg_type_namedconf, &config); } /* * If this is lwresd with the -C option, or lwresd with no -C or -c * option where the above parsing failed, parse resolv.conf. */ if (ns_g_lwresdonly && (lwresd_g_useresolvconf || (!ns_g_conffileset && result == ISC_R_FILENOTFOUND))) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading configuration from '%s'", lwresd_g_resolvconffile); if (parser != NULL) cfg_parser_destroy(&parser); CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); result = ns_lwresd_parseeresolvconf(ns_g_mctx, parser, &config); } CHECK(result); /* * Check the validity of the configuration. */ CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx)); /* * Fill in the maps array, used for resolving defaults. */ i = 0; options = NULL; result = cfg_map_get(config, "options", &options); if (result == ISC_R_SUCCESS) maps[i++] = options; maps[i++] = ns_g_defaults; maps[i++] = NULL; /* * Set process limits, which (usually) needs to be done as root. */ set_limits(maps); /* * Configure various server options. */ configure_server_quota(maps, "transfers-out", &server->xfroutquota); configure_server_quota(maps, "tcp-clients", &server->tcpquota); configure_server_quota(maps, "recursive-clients", &server->recursionquota); CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx, ns_g_mctx, &server->blackholeacl)); if (server->blackholeacl != NULL) dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, server->blackholeacl); obj = NULL; result = ns_config_get(maps, "match-mapped-addresses", &obj); INSIST(result == ISC_R_SUCCESS); server->aclenv.match_mapped = cfg_obj_asboolean(obj); v4ports = NULL; v6ports = NULL; (void)ns_config_get(maps, "avoid-v4-udp-ports", &v4ports); (void)ns_config_get(maps, "avoid-v6-udp-ports", &v6ports); if (v4ports != NULL || v6ports != NULL) { dns_portlist_t *portlist = NULL; result = dns_portlist_create(ns_g_mctx, &portlist); if (result == ISC_R_SUCCESS && v4ports != NULL) result = portlist_fromconf(portlist, AF_INET, v4ports); if (result == ISC_R_SUCCESS && v6ports != NULL) portlist_fromconf(portlist, AF_INET6, v6ports); if (result == ISC_R_SUCCESS) dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, portlist); if (portlist != NULL) dns_portlist_detach(&portlist); CHECK(result); } else dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, NULL); /* * Set the EDNS UDP size when we don't match a view. */ obj = NULL; result = ns_config_get(maps, "edns-udp-size", &obj); INSIST(result == ISC_R_SUCCESS); udpsize = cfg_obj_asuint32(obj); if (udpsize < 512) udpsize = 512; if (udpsize > 4096) udpsize = 4096; ns_g_udpsize = (isc_uint16_t)udpsize; /* * Configure the zone manager. */ obj = NULL; result = ns_config_get(maps, "transfers-in", &obj); INSIST(result == ISC_R_SUCCESS); dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "transfers-per-ns", &obj); INSIST(result == ISC_R_SUCCESS); dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "serial-query-rate", &obj); INSIST(result == ISC_R_SUCCESS); dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj)); /* * Determine which port to use for listening for incoming connections. */ if (ns_g_port != 0) listen_port = ns_g_port; else CHECKM(ns_config_getport(config, &listen_port), "port"); /* * Find the listen queue depth. */ obj = NULL; result = ns_config_get(maps, "tcp-listen-queue", &obj); INSIST(result == ISC_R_SUCCESS); ns_g_listen = cfg_obj_asuint32(obj); if (ns_g_listen < 3) ns_g_listen = 3; /* * Configure the interface manager according to the "listen-on" * statement. */ { cfg_obj_t *clistenon = NULL; ns_listenlist_t *listenon = NULL; clistenon = NULL; /* * Even though listen-on is present in the default * configuration, we can't use it here, since it isn't * used if we're in lwresd mode. This way is easier. */ if (options != NULL) (void)cfg_map_get(options, "listen-on", &clistenon); if (clistenon != NULL) { result = ns_listenlist_fromconfig(clistenon, config, &aclconfctx, ns_g_mctx, &listenon); } else if (!ns_g_lwresdonly) { /* * Not specified, use default. */ CHECK(ns_listenlist_default(ns_g_mctx, listen_port, ISC_TRUE, &listenon)); } if (listenon != NULL) { ns_interfacemgr_setlistenon4(server->interfacemgr, listenon); ns_listenlist_detach(&listenon); } } /* * Ditto for IPv6. */ { cfg_obj_t *clistenon = NULL; ns_listenlist_t *listenon = NULL; if (options != NULL) (void)cfg_map_get(options, "listen-on-v6", &clistenon); if (clistenon != NULL) { result = ns_listenlist_fromconfig(clistenon, config, &aclconfctx, ns_g_mctx, &listenon); } else if (!ns_g_lwresdonly) { /* * Not specified, use default. */ CHECK(ns_listenlist_default(ns_g_mctx, listen_port, ISC_FALSE, &listenon)); } if (listenon != NULL) { ns_interfacemgr_setlistenon6(server->interfacemgr, listenon); ns_listenlist_detach(&listenon); } } /* * Rescan the interface list to pick up changes in the * listen-on option. It's important that we do this before we try * to configure the query source, since the dispatcher we use might * be shared with an interface. */ scan_interfaces(server, ISC_TRUE); /* * Arrange for further interface scanning to occur periodically * as specified by the "interface-interval" option. */ obj = NULL; result = ns_config_get(maps, "interface-interval", &obj); INSIST(result == ISC_R_SUCCESS); interface_interval = cfg_obj_asuint32(obj) * 60; if (interface_interval == 0) { CHECK(isc_timer_reset(server->interface_timer, isc_timertype_inactive, NULL, NULL, ISC_TRUE)); } else if (server->interface_interval != interface_interval) { isc_interval_t interval; isc_interval_set(&interval, interface_interval, 0); CHECK(isc_timer_reset(server->interface_timer, isc_timertype_ticker, NULL, &interval, ISC_FALSE)); } server->interface_interval = interface_interval; /* * Configure the dialup heartbeat timer. */ obj = NULL; result = ns_config_get(maps, "heartbeat-interval", &obj); INSIST(result == ISC_R_SUCCESS); heartbeat_interval = cfg_obj_asuint32(obj) * 60; if (heartbeat_interval == 0) { CHECK(isc_timer_reset(server->heartbeat_timer, isc_timertype_inactive, NULL, NULL, ISC_TRUE)); } else if (server->heartbeat_interval != heartbeat_interval) { isc_interval_t interval; isc_interval_set(&interval, heartbeat_interval, 0); CHECK(isc_timer_reset(server->heartbeat_timer, isc_timertype_ticker, NULL, &interval, ISC_FALSE)); } server->heartbeat_interval = heartbeat_interval; /* * Configure and freeze all explicit views. Explicit * views that have zones were already created at parsing * time, but views with no zones must be created here. */ views = NULL; (void)cfg_map_get(config, "view", &views); for (element = cfg_list_first(views); element != NULL; element = cfg_list_next(element)) { cfg_obj_t *vconfig = cfg_listelt_value(element); view = NULL; CHECK(create_view(vconfig, &viewlist, &view)); INSIST(view != NULL); CHECK(configure_view(view, config, vconfig, ns_g_mctx, &aclconfctx, ISC_TRUE)); dns_view_freeze(view); dns_view_detach(&view); } /* * Make sure we have a default view if and only if there * were no explicit views. */ if (views == NULL) { /* * No explicit views; there ought to be a default vi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -