整体功能分析

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相关推荐

  1. Proxy Server源码及分析(TCP Proxy源码 Socket实现端口映射)

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u014530704/article/d ...

  2. DNS BIND之运维管理脚本

    为了方便管理bind,编写shell脚本,实现bind的start.stop.restart.status操作,并可以将脚本复制到/etc/rc.d/init.d/,添加以服务启动,并设置bind服务 ...

  3. boost::asio异步模式的C/S客户端源码实现

    异步模式的服务器源码 //g++ -g async_tcp_server.cpp -o async_tcp_server -lboost_system //#include <iostream& ...

  4. dubbo学习过程、使用经验分享及实现原理简单介绍

    一.前言 部门去年年中开始各种改造,第一步是模块服务化,这边初选dubbo试用在一些非重要模块上,慢慢引入到一些稍微重要的功能上,半年时间,学习过程及线上使用遇到的些问题在此总结下. 整理这篇文章差不 ...

  5. 了解黑客的关键工具---揭开Shellcode的神秘面纱

    2019独角兽企业重金招聘Python工程师标准>>> ref:  http://zhaisj.blog.51cto.com/219066/61428/ 了解黑客的关键工具---揭开 ...

  6. 类似ngnix的多进程监听用例

    2019独角兽企业重金招聘Python工程师标准>>> 多进程监听适合于短连接,且连接间无交集的应用. 前两天简单写了一个,在这里保存一下. #include <sys/typ ...

  7. centos 6.8 搭建svn服务器

    1. yum remove subversion #卸载 svn服务 2.下载svn服务器安装包 yum -y install subversion 3.创建SVN版本库 mkdir -p /opt/ ...

  8. linux通信机制总结

    目录 1. Linux通信机制分类简介 2. Inter-Process Communication (IPC) mechanisms: 进程间通信机制0x1: 信号量(Signals)0x2: 管道 ...

  9. 为RHEL5安装JDK和配置tomcat

    http://www.linuxdiyf.com/viewarticle.php?id=120575 为RHEL5安装JDK和配置tomcat ericLi发布于 2008-12-19 | 515次阅 ...

最新文章

  1. 学术青年如何克服拖延症——5条技巧助你前进
  2. benchmarksql测试mysql_数据库压力测试工具 -- BenchmarkSQL 使用说明
  3. 好雨云帮近期问答集锦(1.16~2.5)
  4. oracle查询两列合并成一列_MySQL复合索引和单列索引的单表查询分析
  5. mysql 类似oracle,mysql – 制作类似于Oracle的seqences的机制
  6. 如何用SPSS做协方差分析?超详细图文教程
  7. centos7完全卸载删除nginx
  8. React中级学习(第一天)
  9. drools6.5_Drools 6.2.0.Final发布
  10. php编译支持mysql,编译php支持curl和pdo_mysql
  11. html页面之间传参乱码,急求教,在两个htm页面传参数时中文出现了乱码,试了网上的方法不管用。_html/css_WEB-ITnose...
  12. Windows 2003安全事件ID分析(1)
  13. A*寻路算法基于C#实现
  14. nodemcu http get无法使用IP的问题
  15. BaKoMa Tex Word 的使用
  16. 为什么边缘概率密度是联合概率密度的积分_5.27005柏林联合VS美因茨
  17. 魔抓编程_编程中的魔数是什么?
  18. PS软件Photoshop设置使用鼠标进行放大缩小设置
  19. 什么是IPFS?(三)
  20. 干货分享|Compare essay的写作方法

热门文章

  1. Linux系统磁盘高级应用适合初学者
  2. android 时间颜色,android修改状态栏时间和日期颜色.docx
  3. C语言程序设计(二)基础内容
  4. gym库的基本使用方法
  5. 《Generating Question Relevant Captions to Aid Visual Question Answering》(生成问题相关标题,以帮助视觉回答问题)论文解读
  6. 下一代智能扫码报修系统介绍
  7. 蓝桥杯scratch编程题(2)
  8. 1024 程序员节狂欢盛会,等了一年终于来了(内附大会日程)
  9. Zabbix 配置钉钉告警
  10. Python爬取百度翻译及有道翻译