bind server.c
整体功能分析
server.c 主要完成BIND 服务器的启动、关闭、reload、reconfig、refresh 等命令的处理,进行服务器、视图和区域配置的解析和处理。
函数调用关系
setup调用ns_server_create 函数创建默认服务器对象。
ns_server
定义在/bin/named/include/named/server.h
保存服务器配置。
struct
ns_server {
unsigned int magic;
isc_mem_t * mctx;
isc_task_t * task;
isc_quota_t xfroutquota; // transfers-out 配额
isc_quota_t tcpquota; // tcp-clients 配额
isc_quota_t recursionquota; // recursive-clients 配额
dns_acl_t *blackholeacl; // Blackhole ACL
char * statsfile; // 统计文件名
char * dumpfile; // Dump 文件名
char * recfile; // recursive 文件名
isc_boolean_t version_set; // 用户是否自定义版本
char * version; // 用户定义的版本
isc_boolean_t hostname_set; // 用户是否自定义主机名
char * hostname; // 用户定义的主机名
isc_boolean_t server_usehostname; // 将主机名作为server id
char * server_id; // 用户定义的server id
dns_aclenv_t aclenv; // 当前的ACL 环境
dns_loadmgr_t * loadmgr; // 负载管理器
dns_zonemgr_t * zonemgr; // 区域管理器
dns_viewlist_t viewlist; // 视图列表
ns_interfacemgr_t * interfacemgr; // 接口管理器
dns_db_t * in_roothints; // root hints
dns_tkeyctx_t * tkeyctx; // TKEY
isc_timer_t * interface_timer; // 计时器
isc_timer_t * heartbeat_timer;
isc_timer_t * pps_timer;
isc_uint32_t interface_interval; // 重新扫描网络接口间隔
isc_uint32_t heartbeat_interval;
isc_mutex_t reload_event_lock; // reload 事件锁
isc_event_t * reload_event; // reload 事件
isc_boolean_t flushonshutdown; // flush zones on
shutdown
isc_boolean_t log_queries; // 兼容BIND 8
dns_stats_t * nsstats; // 服务器统计
dns_stats_t * rcvquerystats; // 接收的查询请求统计
dns_stats_t * opcodestats; // 接收的消息统计
dns_stats_t * zonestats; // 区域管理器统计
dns_stats_t * resolverstats; // 解析器统计
ns_controls_t * controls; // 控制通道
unsigned int dispatchgen;
ns_dispatchlist_t dispatches; // 调度器
dns_acache_t *acache; // Additional section caching
ns_statschannellist_t statschannels; // 统计通道
};
主要代码
void
ns_server_create(isc_mem_t *mctx, ns_server_t **serverp)
{isc_result_t result;/*分配server内存*/ns_server_t *server = isc_mem_get(mctx, sizeof(*server));.../* Initialize configuration data with default values. */...result = isc_quota_init(&server->recursionquota, 100);RUNTIME_CHECK(result == ISC_R_SUCCESS);result = dns_aclenv_init(mctx, &server->aclenv);RUNTIME_CHECK(result == ISC_R_SUCCESS);/* Initialize server data structures. */server->zonemgr = NULL;server->interfacemgr = NULL;ISC_LIST_INIT(server->viewlist);server->in_roothints = NULL;server->blackholeacl = NULL;CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL,&server->in_roothints),"setting up root hints");CHECKFATAL(isc_mutex_init(&server->reload_event_lock),"initializing reload event lock");server->reload_event =isc_event_allocate(ns_g_mctx, server,NS_EVENT_RELOAD,ns_server_reload,server,sizeof(isc_event_t));CHECKFATAL(server->reload_event == NULL ?ISC_R_NOMEMORY : ISC_R_SUCCESS,"allocating reload event");CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY),"initializing DST");server->tkeyctx = NULL;CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy,&server->tkeyctx),"creating TKEY context");/** Setup the server task, which is responsible for coordinating* startup and shutdown of the server.*/CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task),"creating server task");isc_task_setname(server->task, "server", server);CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server),"isc_task_onshutdown");CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),"isc_app_onrun");server->interface_timer = NULL;server->heartbeat_timer = NULL;server->pps_timer = NULL;server->interface_interval = 0;server->heartbeat_interval = 0;CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,ns_g_socketmgr, &server->zonemgr),"dns_zonemgr_create");server->statsfile = isc_mem_strdup(server->mctx, "named.stats");CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,"isc_mem_strdup");server->nsstats = NULL;server->rcvquerystats = NULL;server->opcodestats = NULL;server->zonestats = NULL;server->resolverstats = NULL;server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,"isc_mem_strdup");server->recfile = isc_mem_strdup(server->mctx, "named.recursing");CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,"isc_mem_strdup");server->hostname_set = ISC_FALSE;server->hostname = NULL;server->version_set = ISC_FALSE;server->version = NULL;server->server_usehostname = ISC_FALSE;server->server_id = NULL;CHECKFATAL(dns_generalstats_create(ns_g_mctx, &server->nsstats,dns_nsstatscounter_max),"dns_stats_create (server)");CHECKFATAL(dns_rdatatypestats_create(ns_g_mctx,&server->rcvquerystats),"dns_stats_create (rcvquery)");CHECKFATAL(dns_opcodestats_create(ns_g_mctx, &server->opcodestats),"dns_stats_create (opcode)");CHECKFATAL(dns_generalstats_create(ns_g_mctx, &server->zonestats,dns_zonestatscounter_max),"dns_stats_create (zone)");CHECKFATAL(dns_generalstats_create(ns_g_mctx, &server->resolverstats,dns_resstatscounter_max),"dns_stats_create (resolver)");server->flushonshutdown = ISC_FALSE;server->log_queries = ISC_FALSE;server->controls = NULL;CHECKFATAL(ns_controls_create(server, &server->controls),"ns_controls_create");server->dispatchgen = 0;ISC_LIST_INIT(server->dispatches);ISC_LIST_INIT(server->statschannels);server->magic = NS_SERVER_MAGIC;*serverp = server;
}
主要函数
run_server
调用run_server 函数启动服务器,该函数负责创建加载服务器配置,创建调度管理器、接口管理器,加载区域文件。
load_configuration 函数加载服务器配置文件、区域文件,设定监听端口,配置日志功能:
configure_server_quota 配置服务器配额(如tcp-clients,recursive-clients)
configure_view_acl 配置视图的访问控制列表
ns_listenlist_fromconfig 创建监听列表
ns_listenelt_fromconfig 创建监听列表
scan_interfaces 扫描网络接口
create_view 创建视图
configure_view 配置视图
configure_zone 配置区域
ns_add_reserved_dispatch
configure_hints 配置根服务器
configure_order 配置视图的rrset-order
configure_view_sortlist 配置视图的sortlist 排序
configure_view_dnsseckeys 配置视图的DNSSEC 密匙
load_zones 函数从磁盘读取区域配置文件。
shutdown_server
负责处理关闭服务器的过程,包括日志写入、结束统计、关闭接口管
理器、关闭区管理器(end_reserved_dispatches,ns_server_destroy)
ns_server_reload
ns_server_reloadcommand 负责处理reload 命令,调用zone_from_args 读取参数中的区域配置,调用reload 函数重新载入服务器配置,调用dns_zone_detach 函数重新载入区域配置。
reload 在载入服务器配置和区域文件时的过程与服务器启动时比较接近:
loadconfig 载入named.conf 配置
load_configuration
configure_server_quota 配置服务器配额
…
load_configuration
该函数处理named.conf 中的配置选项。
如果需要在named.conf 中增加一些自定义的选项, 首先修改
/lib/isccfg/namedconf.c,增加相应的选项处理规则。然后再在load_configuration 函数中增加处理该选项的代码。
/*
参数 const char *filename 为配置文件路径,例如“/etc/named.conf”
参数 ns_server_t *server 表明该server 是否为第一次进行load_configuration 操作:
参数 isc_boolean_t first_time
启动服务器时run_server 调用此函数,first_time = ISC_TRUE;
重新加载配置loadconfig 调用此函数,first_time = ISC_FALSE
*/
static isc_result_t
load_configuration(const char *filename, ns_server_t *server,isc_boolean_t first_time)
{...cfg_obj_t *config; //配置解析器cfg_parser_t *parser = NULL;//配置解析结果...cfg_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);/* /lib/isccfg/include/isccfg/cfg.h 文件中定义了配置文件的解析器。cfg_parser_create 创建一个配置解析器。*/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);/** Check if max number of open sockets that the system allows is* sufficiently large. Failing this condition is not necessarily fatal,* but may cause subsequent runtime failures for a busy recursive* server.*/result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &maxsocks);if (result != ISC_R_SUCCESS)maxsocks = 0;result = isc_resource_getcurlimit(isc_resource_openfiles, &nfiles);if (result == ISC_R_SUCCESS && (isc_resourcevalue_t)maxsocks > nfiles) {isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,NS_LOGMODULE_SERVER, ISC_LOG_WARNING,"max open files (%" ISC_PRINT_QUADFORMAT "u)"" is smaller than max sockets (%u)",nfiles, maxsocks);}/** Set the number of socket reserved for TCP, stdio etc.*/obj = NULL;result = ns_config_get(maps, "reserved-sockets", &obj);INSIST(result == ISC_R_SUCCESS);reserved = cfg_obj_asuint32(obj);if (maxsocks != 0) {if (maxsocks < 128U) /* Prevent underflow. */reserved = 0;else if (reserved > maxsocks - 128U) /* Minimum UDP space. */reserved = maxsocks - 128;}/* Minimum TCP/stdio space. */if (reserved < 128U)reserved = 128;if (reserved + 128U > maxsocks && maxsocks != 0) {isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,NS_LOGMODULE_SERVER, ISC_LOG_WARNING,"less than 128 UDP sockets available after ""applying 'reserved-sockets' and 'maxsockets'");}isc__socketmgr_setreserved(ns_g_socketmgr, reserved);/** 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);if (server->recursionquota.max > 1000)isc_quota_soft(&server->recursionquota,server->recursionquota.max - 100);elseisc_quota_soft(&server->recursionquota, 0);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);CHECKM(ns_statschannels_configure(ns_g_server, config, &aclconfctx),"configuring statistics server(s)");/** Configure sets of UDP query source ports. 处理use-v4-udp-ports, avoid-v4-udp-ports, use-v6-udpports,*/CHECKM(isc_portset_create(ns_g_mctx, &v4portset),"creating UDP port set");CHECKM(isc_portset_create(ns_g_mctx, &v6portset),"creating UDP port set");usev4ports = NULL;usev6ports = NULL;avoidv4ports = NULL;avoidv6ports = NULL;(void)ns_config_get(maps, "use-v4-udp-ports", &usev4ports);if (usev4ports != NULL)portset_fromconf(v4portset, usev4ports, ISC_TRUE);else {CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low,&udpport_high),"get the default UDP/IPv4 port range");if (udpport_low == udpport_high)isc_portset_add(v4portset, udpport_low);else {isc_portset_addrange(v4portset, udpport_low,udpport_high);}isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,NS_LOGMODULE_SERVER, ISC_LOG_INFO,"using default UDP/IPv4 port range: [%d, %d]",udpport_low, udpport_high);}(void)ns_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports);if (avoidv4ports != NULL)portset_fromconf(v4portset, avoidv4ports, ISC_FALSE);(void)ns_config_get(maps, "use-v6-udp-ports", &usev6ports);if (usev6ports != NULL)portset_fromconf(v6portset, usev6ports, ISC_TRUE);else {CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low,&udpport_high),"get the default UDP/IPv6 port range");if (udpport_low == udpport_high)isc_portset_add(v6portset, udpport_low);else {isc_portset_addrange(v6portset, udpport_low,udpport_high);}isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,NS_LOGMODULE_SERVER, ISC_LOG_INFO,"using default UDP/IPv6 port range: [%d, %d]",udpport_low, udpport_high);}(void)ns_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports);if (avoidv6ports != NULL)portset_fromconf(v6portset, avoidv6ports, ISC_FALSE);dns_dispatchmgr_setavailports(ns_g_dispatchmgr, v4portset, v6portset);/** 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;elseCHECKM(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.*/{const 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.*/{const 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) {isc_boolean_t enable;/** Not specified, use default.*/enable = ISC_TF(isc_net_probeipv4() != ISC_R_SUCCESS);CHECK(ns_listenlist_default(ns_g_mctx, listen_port,enable, &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_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_set(&interval, heartbeat_interval, 0);CHECK(isc_timer_reset(server->heartbeat_timer,isc_timertype_ticker,NULL, &interval, ISC_FALSE));}server->heartbeat_interval = heartbeat_interval;isc_interval_set(&interval, 1200, 0);CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL,&interval, ISC_FALSE));/** 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)){const 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 view.* There may already be one created as a side effect* of zone statements, or we may have to create one.* In either case, we need to configure and freeze it.*/CHECK(create_view(NULL, &viewlist, &view));CHECK(configure_view(view, config, NULL, ns_g_mctx,&aclconfctx, ISC_TRUE));dns_view_freeze(view);dns_view_detach(&view);}/** Create (or recreate) the built-in views. Currently* there is only one, the _bind view.*/builtin_views = NULL;RUNTIME_CHECK(cfg_map_get(ns_g_config, "view",&builtin_views) == ISC_R_SUCCESS);for (element = cfg_list_first(builtin_views);element != NULL;element = cfg_list_next(element)){const cfg_obj_t *vconfig = cfg_listelt_value(element);CHECK(create_view(vconfig, &viewlist, &view));CHECK(configure_view(view, config, vconfig, ns_g_mctx,&aclconfctx, ISC_FALSE));dns_view_freeze(view);dns_view_detach(&view);view = NULL;}/** Swap our new view list with the production one.*/tmpviewlist = server->viewlist;server->viewlist = viewlist;viewlist = tmpviewlist;/** Load the TKEY information from the configuration.*/if (options != NULL) {dns_tkeyctx_t *t = NULL;CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy,&t),"configuring TKEY");if (server->tkeyctx != NULL)dns_tkeyctx_destroy(&server->tkeyctx);server->tkeyctx = t;}/** Bind the control port(s).*/CHECKM(ns_controls_configure(ns_g_server->controls, config,&aclconfctx),"binding control channel(s)");/** Bind the lwresd port(s).*/CHECKM(ns_lwresd_configure(ns_g_mctx, config),"binding lightweight resolver ports");/** Open the source of entropy.*/if (first_time) {obj = NULL;result = ns_config_get(maps, "random-device", &obj);if (result != ISC_R_SUCCESS) {isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,NS_LOGMODULE_SERVER, ISC_LOG_INFO,"no source of entropy found");} else {const char *randomdev = cfg_obj_asstring(obj);result = isc_entropy_createfilesource(ns_g_entropy,randomdev);if (result != ISC_R_SUCCESS)isc_log_write(ns_g_lctx,NS_LOGCATEGORY_GENERAL,NS_LOGMODULE_SERVER,ISC_LOG_INFO,"could not open entropy source ""%s: %s",randomdev,isc_result_totext(result));
#ifdef PATH_RANDOMDEVif (ns_g_fallbackentropy != NULL) {if (result != ISC_R_SUCCESS) {isc_log_write(ns_g_lctx,NS_LOGCATEGORY_GENERAL,NS_LOGMODULE_SERVER,ISC_LOG_INFO,"using pre-chroot entropy source ""%s",PATH_RANDOMDEV);isc_entropy_detach(&ns_g_entropy);isc_entropy_attach(ns_g_fallbackentropy,&ns_g_entropy);}isc_entropy_detach(&ns_g_fallbackentropy);}
#endif}}/** Relinquish root privileges.*/if (first_time)ns_os_changeuser();/** Check that the working directory is writable.*/if (access(".", W_OK) != 0) {isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,NS_LOGMODULE_SERVER, ISC_LOG_ERROR,"the working directory is not writable");}/** Configure the logging system.** Do this after changing UID to make sure that any log* files specified in named.conf get created by the* unprivileged user, not root.*/if (ns_g_logstderr) {isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,NS_LOGMODULE_SERVER, ISC_LOG_INFO,"ignoring config file logging ""statement due to -g option");} else {const cfg_obj_t *logobj = NULL;isc_logconfig_t *logc = NULL;CHECKM(isc_logconfig_create(ns_g_lctx, &logc),"creating new logging configuration");logobj = NULL;(void)cfg_map_get(config, "logging", &logobj);if (logobj != NULL) {CHECKM(ns_log_configure(logc, logobj),"configuring logging");} else {CHECKM(ns_log_setdefaultchannels(logc),"setting up default logging channels");CHECKM(ns_log_setunmatchedcategory(logc),"setting up default 'category unmatched'");CHECKM(ns_log_setdefaultcategory(logc),"setting up default 'category default'");}result = isc_logconfig_use(ns_g_lctx, logc);if (result != ISC_R_SUCCESS) {isc_logconfig_destroy(&logc);CHECKM(result, "installing logging configuration");}isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),"now using logging configuration from ""config file");}/** Set the default value of the query logging flag depending* whether a "queries" category has been defined. This is* a disgusting hack, but we need to do this for BIND 8* compatibility.*/if (first_time) {const cfg_obj_t *logobj = NULL;const cfg_obj_t *categories = NULL;obj = NULL;if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) {server->log_queries = cfg_obj_asboolean(obj);} else {(void)cfg_map_get(config, "logging", &logobj);if (logobj != NULL)(void)cfg_map_get(logobj, "category",&categories);if (categories != NULL) {const cfg_listelt_t *element;for (element = cfg_list_first(categories);element != NULL;element = cfg_list_next(element)){const cfg_obj_t *catobj;const char *str;obj = cfg_listelt_value(element);catobj = cfg_tuple_get(obj, "name");str = cfg_obj_asstring(catobj);if (strcasecmp(str, "queries") == 0)server->log_queries = ISC_TRUE;}}}}obj = NULL;if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS)if (cfg_obj_isvoid(obj))ns_os_writepidfile(NULL, first_time);elsens_os_writepidfile(cfg_obj_asstring(obj), first_time);else if (ns_g_lwresdonly)ns_os_writepidfile(lwresd_g_defaultpidfile, first_time);elsens_os_writepidfile(ns_g_defaultpidfile, first_time);obj = NULL;if (options != NULL &&cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS)ns_g_memstatistics = cfg_obj_asboolean(obj);elsens_g_memstatistics =ISC_TF((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0);obj = NULL;if (ns_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS)ns_main_setmemstats(cfg_obj_asstring(obj));else if (ns_g_memstatistics)ns_main_setmemstats("named.memstats");elsens_main_setmemstats(NULL);obj = NULL;result = ns_config_get(maps, "statistics-file", &obj);INSIST(result == ISC_R_SUCCESS);CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)),"strdup");obj = NULL;result = ns_config_get(maps, "dump-file", &obj);INSIST(result == ISC_R_SUCCESS);CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)),"strdup");obj = NULL;result = ns_config_get(maps, "recursing-file", &obj);INSIST(result == ISC_R_SUCCESS);CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)),"strdup");obj = NULL;result = ns_config_get(maps, "version", &obj);if (result == ISC_R_SUCCESS) {CHECKM(setoptstring(server, &server->version, obj), "strdup");server->version_set = ISC_TRUE;} else {server->version_set = ISC_FALSE;}obj = NULL;result = ns_config_get(maps, "hostname", &obj);if (result == ISC_R_SUCCESS) {CHECKM(setoptstring(server, &server->hostname, obj), "strdup");server->hostname_set = ISC_TRUE;} else {server->hostname_set = ISC_FALSE;}obj = NULL;result = ns_config_get(maps, "server-id", &obj);server->server_usehostname = ISC_FALSE;if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {/* The parser translates "hostname" to ISC_TRUE */server->server_usehostname = cfg_obj_asboolean(obj);result = setstring(server, &server->server_id, NULL);RUNTIME_CHECK(result == ISC_R_SUCCESS);} else if (result == ISC_R_SUCCESS) {/* Found a quoted string */CHECKM(setoptstring(server, &server->server_id, obj), "strdup");} else {result = setstring(server, &server->server_id, NULL);RUNTIME_CHECK(result == ISC_R_SUCCESS);}obj = NULL;result = ns_config_get(maps, "flush-zones-on-shutdown", &obj);if (result == ISC_R_SUCCESS) {server->flushonshutdown = cfg_obj_asboolean(obj);} else {server->flushonshutdown = ISC_FALSE;}result = ISC_R_SUCCESS;cleanup:if (v4portset != NULL)isc_portset_destroy(ns_g_mctx, &v4portset);if (v6portset != NULL)isc_portset_destroy(ns_g_mctx, &v6portset);cfg_aclconfctx_destroy(&aclconfctx);if (parser != NULL) {if (config != NULL)cfg_obj_destroy(parser, &config);cfg_parser_destroy(&parser);}if (view != NULL)dns_view_detach(&view);/** This cleans up either the old production view list* or our temporary list depending on whether they* were swapped above or not.*/for (view = ISC_LIST_HEAD(viewlist);view != NULL;view = view_next) {view_next = ISC_LIST_NEXT(view, link);ISC_LIST_UNLINK(viewlist, view, link);if (result == ISC_R_SUCCESS &&strcmp(view->name, "_bind") != 0)(void)dns_zt_apply(view->zonetable, ISC_FALSE,removed, view);dns_view_detach(&view);}/** Adjust the listening interfaces in accordance with the source* addresses specified in views and zones.*/if (isc_net_probeipv6() == ISC_R_SUCCESS)adjust_interfaces(server, ns_g_mctx);/* Relinquish exclusive access to configuration data. */isc_task_endexclusive(server->task);isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,ISC_LOG_DEBUG(1), "load_configuration: %s",isc_result_totext(result));return (result);
}
bind server.c相关推荐
- Proxy Server源码及分析(TCP Proxy源码 Socket实现端口映射)
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u014530704/article/d ...
- DNS BIND之运维管理脚本
为了方便管理bind,编写shell脚本,实现bind的start.stop.restart.status操作,并可以将脚本复制到/etc/rc.d/init.d/,添加以服务启动,并设置bind服务 ...
- boost::asio异步模式的C/S客户端源码实现
异步模式的服务器源码 //g++ -g async_tcp_server.cpp -o async_tcp_server -lboost_system //#include <iostream& ...
- dubbo学习过程、使用经验分享及实现原理简单介绍
一.前言 部门去年年中开始各种改造,第一步是模块服务化,这边初选dubbo试用在一些非重要模块上,慢慢引入到一些稍微重要的功能上,半年时间,学习过程及线上使用遇到的些问题在此总结下. 整理这篇文章差不 ...
- 了解黑客的关键工具---揭开Shellcode的神秘面纱
2019独角兽企业重金招聘Python工程师标准>>> ref: http://zhaisj.blog.51cto.com/219066/61428/ 了解黑客的关键工具---揭开 ...
- 类似ngnix的多进程监听用例
2019独角兽企业重金招聘Python工程师标准>>> 多进程监听适合于短连接,且连接间无交集的应用. 前两天简单写了一个,在这里保存一下. #include <sys/typ ...
- centos 6.8 搭建svn服务器
1. yum remove subversion #卸载 svn服务 2.下载svn服务器安装包 yum -y install subversion 3.创建SVN版本库 mkdir -p /opt/ ...
- linux通信机制总结
目录 1. Linux通信机制分类简介 2. Inter-Process Communication (IPC) mechanisms: 进程间通信机制0x1: 信号量(Signals)0x2: 管道 ...
- 为RHEL5安装JDK和配置tomcat
http://www.linuxdiyf.com/viewarticle.php?id=120575 为RHEL5安装JDK和配置tomcat ericLi发布于 2008-12-19 | 515次阅 ...
最新文章
- 学术青年如何克服拖延症——5条技巧助你前进
- benchmarksql测试mysql_数据库压力测试工具 -- BenchmarkSQL 使用说明
- 好雨云帮近期问答集锦(1.16~2.5)
- oracle查询两列合并成一列_MySQL复合索引和单列索引的单表查询分析
- mysql 类似oracle,mysql – 制作类似于Oracle的seqences的机制
- 如何用SPSS做协方差分析?超详细图文教程
- centos7完全卸载删除nginx
- React中级学习(第一天)
- drools6.5_Drools 6.2.0.Final发布
- php编译支持mysql,编译php支持curl和pdo_mysql
- html页面之间传参乱码,急求教,在两个htm页面传参数时中文出现了乱码,试了网上的方法不管用。_html/css_WEB-ITnose...
- Windows 2003安全事件ID分析(1)
- A*寻路算法基于C#实现
- nodemcu http get无法使用IP的问题
- BaKoMa Tex Word 的使用
- 为什么边缘概率密度是联合概率密度的积分_5.27005柏林联合VS美因茨
- 魔抓编程_编程中的魔数是什么?
- PS软件Photoshop设置使用鼠标进行放大缩小设置
- 什么是IPFS?(三)
- 干货分享|Compare essay的写作方法