diff options
Diffstat (limited to 'bin/named/server.c')
-rw-r--r-- | bin/named/server.c | 191 |
1 files changed, 158 insertions, 33 deletions
diff --git a/bin/named/server.c b/bin/named/server.c index 3aeaf27e098d3..6853f5c6a1116 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.520.12.23 2011-03-11 10:49:51 marka Exp $ */ +/* $Id$ */ /*! \file */ @@ -183,7 +183,6 @@ static const struct { const char *zone; isc_boolean_t rfc1918; } empty_zones[] = { -#ifdef notyet /* RFC 1918 */ { "10.IN-ADDR.ARPA", ISC_TRUE }, { "16.172.IN-ADDR.ARPA", ISC_TRUE }, @@ -203,7 +202,6 @@ static const struct { { "30.172.IN-ADDR.ARPA", ISC_TRUE }, { "31.172.IN-ADDR.ARPA", ISC_TRUE }, { "168.192.IN-ADDR.ARPA", ISC_TRUE }, -#endif /* RFC 5735 and RFC 5737 */ { "0.IN-ADDR.ARPA", ISC_FALSE }, /* THIS NETWORK */ @@ -230,8 +228,8 @@ static const struct { { NULL, ISC_FALSE } }; -static void -fatal(const char *msg, isc_result_t result); +ISC_PLATFORM_NORETURN_POST static void +fatal(const char *msg, isc_result_t result) ISC_PLATFORM_NORETURN_POST; static void ns_server_reload(isc_task_t *task, isc_event_t *event); @@ -1026,7 +1024,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, isc_uint32_t max_cache_size; isc_uint32_t max_acache_size; isc_uint32_t lame_ttl; - dns_tsig_keyring_t *ring; + dns_tsig_keyring_t *ring = NULL; dns_view_t *pview = NULL; /* Production view */ isc_mem_t *cmctx = NULL, *hmctx = NULL; dns_dispatch_t *dispatch4 = NULL; @@ -1147,6 +1145,10 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, (void)cfg_map_get(voptions, "zone", &zonelist); else (void)cfg_map_get(config, "zone", &zonelist); + + /* + * Load zone configuration + */ for (element = cfg_list_first(zonelist); element != NULL; element = cfg_list_next(element)) @@ -1490,9 +1492,9 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, /* * Configure the view's TSIG keys. */ - ring = NULL; CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); dns_view_setkeyring(view, ring); + ring = NULL; /* ownership transferred */ /* * Configure the view's peer list. @@ -1856,7 +1858,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, rfc1918 = ISC_FALSE; empty_zones_enable = ISC_FALSE; } - if (empty_zones_enable) { + if (empty_zones_enable && !lwresd_g_useresolvconf) { const char *empty; int empty_zone = 0; dns_fixedname_t fixed; @@ -2021,6 +2023,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, result = ISC_R_SUCCESS; cleanup: + if (ring != NULL) + dns_tsigkeyring_destroy(&ring); if (zone != NULL) dns_zone_detach(&zone); if (dispatch4 != NULL) @@ -2245,21 +2249,16 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, return (result); } -/* - * Create a new view and add it to the list. - * - * If 'vconfig' is NULL, create the default view. - * - * The view created is attached to '*viewp'. - */ static isc_result_t -create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, - dns_view_t **viewp) +get_viewinfo(const cfg_obj_t *vconfig, const char **namep, + dns_rdataclass_t *classp) { - isc_result_t result; + isc_result_t result = ISC_R_SUCCESS; const char *viewname; dns_rdataclass_t viewclass; - dns_view_t *view = NULL; + + REQUIRE(namep != NULL && *namep == NULL); + REQUIRE(classp != NULL); if (vconfig != NULL) { const cfg_obj_t *classobj = NULL; @@ -2268,11 +2267,63 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, classobj = cfg_tuple_get(vconfig, "class"); result = ns_config_getclass(classobj, dns_rdataclass_in, &viewclass); - INSIST(result == ISC_R_SUCCESS); } else { viewname = "_default"; viewclass = dns_rdataclass_in; } + + *namep = viewname; + *classp = viewclass; + + return (result); +} + +/* + * Find a view based on its configuration info and attach to it. + * + * If 'vconfig' is NULL, attach to the default view. + */ +static isc_result_t +find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, + dns_view_t **viewp) +{ + isc_result_t result; + const char *viewname = NULL; + dns_rdataclass_t viewclass; + dns_view_t *view = NULL; + + result = get_viewinfo(vconfig, &viewname, &viewclass); + if (result != ISC_R_SUCCESS) + return (result); + + result = dns_viewlist_find(viewlist, viewname, viewclass, &view); + if (result != ISC_R_SUCCESS) + return (result); + + *viewp = view; + return (ISC_R_SUCCESS); +} + +/* + * Create a new view and add it to the list. + * + * If 'vconfig' is NULL, create the default view. + * + * The view created is attached to '*viewp'. + */ +static isc_result_t +create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, + dns_view_t **viewp) +{ + isc_result_t result; + const char *viewname = NULL; + dns_rdataclass_t viewclass; + dns_view_t *view = NULL; + + result = get_viewinfo(vconfig, &viewname, &viewclass); + if (result != ISC_R_SUCCESS) + return (result); + result = dns_viewlist_find(viewlist, viewname, viewclass, &view); if (result == ISC_R_SUCCESS) return (ISC_R_EXISTS); @@ -2923,6 +2974,23 @@ removed(dns_zone_t *zone, void *uap) { return (ISC_R_SUCCESS); } +static int +count_zones(const cfg_obj_t *conf) { + const cfg_obj_t *zonelist = NULL; + const cfg_listelt_t *element; + int n = 0; + + REQUIRE(conf != NULL); + + cfg_map_get(conf, "zone", &zonelist); + for (element = cfg_list_first(zonelist); + element != NULL; + element = cfg_list_next(element)) + n++; + + return (n); +} + static isc_result_t load_configuration(const char *filename, ns_server_t *server, isc_boolean_t first_time) @@ -2953,14 +3021,12 @@ load_configuration(const char *filename, ns_server_t *server, isc_uint32_t reserved; isc_uint32_t udpsize; unsigned int maxsocks; + int num_zones = 0; + isc_boolean_t exclusive = ISC_FALSE; 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. */ @@ -3027,6 +3093,13 @@ load_configuration(const char *filename, ns_server_t *server, maps[i++] = ns_g_defaults; maps[i] = NULL; + /* Ensure exclusive access to configuration data. */ + if (!exclusive) { + result = isc_task_beginexclusive(server->task); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + exclusive = ISC_TRUE; + } + /* * Set process limits, which (usually) needs to be done as root. */ @@ -3324,24 +3397,72 @@ load_configuration(const char *filename, ns_server_t *server, 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); + + /* + * Create the views and count all the configured zones in + * order to correctly size the zone manager's task table. + * (We only count zones for configured views; the built-in + * "bind" view can be ignored as it only adds a negligible + * number of zones.) + * + * If we're allowing new zones, we need to be able to find the + * new zone file and count those as well. So we setup the new + * zone configuration context, but otherwise view configuration + * waits until after the zone manager's task list has been sized. + */ for (element = cfg_list_first(views); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *vconfig = cfg_listelt_value(element); + const cfg_obj_t *voptions = cfg_tuple_get(vconfig, "options"); view = NULL; CHECK(create_view(vconfig, &viewlist, &view)); INSIST(view != NULL); + + num_zones += count_zones(voptions); + dns_view_detach(&view); + } + + /* + * If there were no explicit views then we do the default + * view here. + */ + if (views == NULL) { + CHECK(create_view(NULL, &viewlist, &view)); + INSIST(view != NULL); + + num_zones = count_zones(config); + dns_view_detach(&view); + } + + /* + * Zones have been counted; set the zone manager task pool size. + */ + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "sizing zone task pool based on %d zones", num_zones); + CHECK(dns_zonemgr_setsize(ns_g_server->zonemgr, num_zones)); + + /* + * 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. + */ + 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(find_view(vconfig, &viewlist, &view)); CHECK(configure_view(view, config, vconfig, ns_g_mctx, &aclconfctx, ISC_TRUE)); + dns_view_freeze(view); dns_view_detach(&view); } @@ -3357,7 +3478,7 @@ load_configuration(const char *filename, ns_server_t *server, * 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(find_view(NULL, &viewlist, &view)); CHECK(configure_view(view, config, NULL, ns_g_mctx, &aclconfctx, ISC_TRUE)); dns_view_freeze(view); @@ -3690,7 +3811,8 @@ load_configuration(const char *filename, ns_server_t *server, adjust_interfaces(server, ns_g_mctx); /* Relinquish exclusive access to configuration data. */ - isc_task_endexclusive(server->task); + if (exclusive) + isc_task_endexclusive(server->task); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), "load_configuration: %s", @@ -3955,6 +4077,8 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr, ns_g_socketmgr, &server->zonemgr), "dns_zonemgr_create"); + CHECKFATAL(dns_zonemgr_setsize(server->zonemgr, 1000), + "dns_zonemgr_setsize"); server->statsfile = isc_mem_strdup(server->mctx, "named.stats"); CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, @@ -4044,7 +4168,8 @@ ns_server_destroy(ns_server_t **serverp) { if (server->server_id != NULL) isc_mem_free(server->mctx, server->server_id); - dns_zonemgr_detach(&server->zonemgr); + if (server->zonemgr != NULL) + dns_zonemgr_detach(&server->zonemgr); if (server->tkeyctx != NULL) dns_tkeyctx_destroy(&server->tkeyctx); |