aboutsummaryrefslogtreecommitdiff
path: root/contrib/bind9/bin/named/server.c
diff options
context:
space:
mode:
authorDoug Barton <dougb@FreeBSD.org>2009-05-31 05:42:58 +0000
committerDoug Barton <dougb@FreeBSD.org>2009-05-31 05:42:58 +0000
commit6318052d9e161cbc69e4085125ef824d94de16ef (patch)
tree21a5399cf53ce4f1ffedece1c1700a317f190f2e /contrib/bind9/bin/named/server.c
parentb6d434fc28de9fa7b453178184bdcc767035f5af (diff)
parentb0e69f719c1db2c19fcfba96f0dac9a5a2277350 (diff)
Update BIND to version 9.6.1rc1. This version has better performance and
lots of new features compared to 9.4.x, including: Full NSEC3 support Automatic zone re-signing New update-policy methods tcp-self and 6to4-self DHCID support. More detailed statistics counters including those supported in BIND 8. Faster ACL processing. Efficient LRU cache-cleaning mechanism. NSID support.
Notes
Notes: svn path=/head/; revision=193149
Diffstat (limited to 'contrib/bind9/bin/named/server.c')
-rw-r--r--contrib/bind9/bin/named/server.c905
1 files changed, 711 insertions, 194 deletions
diff --git a/contrib/bind9/bin/named/server.c b/contrib/bind9/bin/named/server.c
index 784ff94d3414..e685e18dc336 100644
--- a/contrib/bind9/bin/named/server.c
+++ b/contrib/bind9/bin/named/server.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 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.419.18.68 2008/09/04 23:46:08 tbox Exp $ */
+/* $Id: server.c,v 1.520.12.7 2009/01/30 03:53:38 marka Exp $ */
/*! \file */
@@ -30,17 +30,20 @@
#include <isc/entropy.h>
#include <isc/file.h>
#include <isc/hash.h>
+#include <isc/httpd.h>
#include <isc/lex.h>
#include <isc/parseint.h>
#include <isc/portset.h>
#include <isc/print.h>
#include <isc/resource.h>
#include <isc/socket.h>
+#include <isc/stats.h>
#include <isc/stdio.h>
#include <isc/string.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/util.h>
+#include <isc/xml.h>
#include <isccfg/namedconf.h>
@@ -63,6 +66,7 @@
#include <dns/order.h>
#include <dns/peer.h>
#include <dns/portlist.h>
+#include <dns/rbt.h>
#include <dns/rdataclass.h>
#include <dns/rdataset.h>
#include <dns/rdatastruct.h>
@@ -71,6 +75,7 @@
#include <dns/secalg.h>
#include <dns/stats.h>
#include <dns/tkey.h>
+#include <dns/tsig.h>
#include <dns/view.h>
#include <dns/zone.h>
#include <dns/zt.h>
@@ -88,6 +93,7 @@
#include <named/main.h>
#include <named/os.h>
#include <named/server.h>
+#include <named/statschannel.h>
#include <named/tkeyconf.h>
#include <named/tsigconf.h>
#include <named/zoneconf.h>
@@ -101,12 +107,12 @@
* using it has a 'result' variable and a 'cleanup' label.
*/
#define CHECK(op) \
- do { result = (op); \
- if (result != ISC_R_SUCCESS) goto cleanup; \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto cleanup; \
} while (0)
#define CHECKM(op, msg) \
- do { result = (op); \
+ do { result = (op); \
if (result != ISC_R_SUCCESS) { \
isc_log_write(ns_g_lctx, \
NS_LOGCATEGORY_GENERAL, \
@@ -119,7 +125,7 @@
} while (0) \
#define CHECKMF(op, msg, file) \
- do { result = (op); \
+ do { result = (op); \
if (result != ISC_R_SUCCESS) { \
isc_log_write(ns_g_lctx, \
NS_LOGCATEGORY_GENERAL, \
@@ -132,7 +138,7 @@
} while (0) \
#define CHECKFATAL(op, msg) \
- do { result = (op); \
+ do { result = (op); \
if (result != ISC_R_SUCCESS) \
fatal(msg, result); \
} while (0) \
@@ -209,7 +215,7 @@ static const struct {
/* Local IPv6 Unicast Addresses */
{ "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE },
{ "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE },
- /* LOCALLY ASSIGNED LOCAL ADDRES S SCOPE */
+ /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */
{ "D.F.IP6.ARPA", ISC_FALSE },
{ "8.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
{ "9.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
@@ -251,9 +257,8 @@ static void
end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
/*%
- * Configure a single view ACL at '*aclp'. Get its configuration by
- * calling 'getvcacl' (for per-view configuration) and maybe 'getscacl'
- * (for a global default).
+ * Configure a single view ACL at '*aclp'. Get its configuration from
+ * 'vconfig' (for per-view configuration) and maybe from 'config'
*/
static isc_result_t
configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
@@ -280,12 +285,56 @@ configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
(void)ns_config_get(maps, aclname, &aclobj);
if (aclobj == NULL)
/*
- * No value available. *aclp == NULL.
+ * No value available. *aclp == NULL.
*/
return (ISC_R_SUCCESS);
result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
- actx, mctx, aclp);
+ actx, mctx, 0, aclp);
+
+ return (result);
+}
+
+
+/*%
+ * Configure a sortlist at '*aclp'. Essentially the same as
+ * configure_view_acl() except it calls cfg_acl_fromconfig with a
+ * nest_level value of 2.
+ */
+static isc_result_t
+configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx, isc_mem_t *mctx,
+ dns_acl_t **aclp)
+{
+ isc_result_t result;
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *aclobj = NULL;
+ int i = 0;
+
+ if (*aclp != NULL)
+ dns_acl_detach(aclp);
+ if (vconfig != NULL)
+ maps[i++] = cfg_tuple_get(vconfig, "options");
+ if (config != NULL) {
+ const cfg_obj_t *options = NULL;
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ maps[i++] = options;
+ }
+ maps[i] = NULL;
+
+ (void)ns_config_get(maps, "sortlist", &aclobj);
+ if (aclobj == NULL)
+ return (ISC_R_SUCCESS);
+
+ /*
+ * Use a nest level of 3 for the "top level" of the sortlist;
+ * this means each entry in the top three levels will be stored
+ * as lists of separate, nested ACLs, rather than merged together
+ * into IP tables as is usually done with ACLs.
+ */
+ result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
+ actx, mctx, 3, aclp);
return (result);
}
@@ -398,7 +447,7 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
* the security roots.
*
* The per-view configuration values and the server-global defaults are read
- * from 'vconfig' and 'config'. The variable to be configured is '*target'.
+ * from 'vconfig' and 'config'. The variable to be configured is '*target'.
*/
static isc_result_t
configure_view_dnsseckeys(const cfg_obj_t *vconfig, const cfg_obj_t *config,
@@ -694,6 +743,11 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)));
obj = NULL;
+ (void)cfg_map_get(cpeer, "request-nsid", &obj);
+ if (obj != NULL)
+ CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj)));
+
+ obj = NULL;
(void)cfg_map_get(cpeer, "edns", &obj);
if (obj != NULL)
CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj)));
@@ -901,6 +955,41 @@ check_dbtype(dns_zone_t **zonep, unsigned int dbtypec, const char **dbargv,
isc_mem_free(mctx, argv);
}
+static isc_result_t
+setquerystats(dns_zone_t *zone, isc_mem_t *mctx, isc_boolean_t on) {
+ isc_result_t result;
+ isc_stats_t *zoneqrystats;
+
+ zoneqrystats = NULL;
+ if (on) {
+ result = isc_stats_create(mctx, &zoneqrystats,
+ dns_nsstatscounter_max);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ dns_zone_setrequeststats(zone, zoneqrystats);
+ if (zoneqrystats != NULL)
+ isc_stats_detach(&zoneqrystats);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+cache_reusable(dns_view_t *originview, dns_view_t *view,
+ isc_boolean_t new_zero_no_soattl)
+{
+ if (originview->checknames != view->checknames ||
+ dns_resolver_getzeronosoattl(originview->resolver) !=
+ new_zero_no_soattl ||
+ originview->acceptexpired != view->acceptexpired ||
+ originview->enablevalidation != view->enablevalidation ||
+ originview->maxcachettl != view->maxcachettl ||
+ originview->maxncachettl != view->maxncachettl) {
+ return (ISC_FALSE);
+ }
+
+ return (ISC_TRUE);
+}
/*
* Configure 'view' according to 'vconfig', taking defaults from 'config'
@@ -947,7 +1036,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
const char *str;
dns_order_t *order = NULL;
isc_uint32_t udpsize;
- unsigned int check = 0;
+ unsigned int resopts = 0;
dns_zone_t *zone = NULL;
isc_uint32_t max_clients_per_query;
const char *sep = ": view ";
@@ -956,6 +1045,9 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
isc_boolean_t rfc1918;
isc_boolean_t empty_zones_enable;
const cfg_obj_t *disablelist = NULL;
+ isc_stats_t *resstats = NULL;
+ dns_stats_t *resquerystats = NULL;
+ isc_boolean_t zero_no_soattl;
REQUIRE(DNS_VIEW_VALID(view));
@@ -1005,6 +1097,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
CHECK(isc_mem_create(0, 0, &cmctx));
CHECK(dns_acache_create(&view->acache, cmctx, ns_g_taskmgr,
ns_g_timermgr));
+ isc_mem_setname(cmctx, "acache", NULL);
isc_mem_detach(&cmctx);
}
if (view->acache != NULL) {
@@ -1096,17 +1189,70 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
#endif
/*
+ * Obtain configuration parameters that affect the decision of whether
+ * we can reuse/share an existing cache.
+ */
+ /* Check-names. */
+ obj = NULL;
+ result = ns_checknames_get(maps, "response", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+
+ str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "fail") == 0) {
+ resopts |= DNS_RESOLVER_CHECKNAMES |
+ DNS_RESOLVER_CHECKNAMESFAIL;
+ view->checknames = ISC_TRUE;
+ } else if (strcasecmp(str, "warn") == 0) {
+ resopts |= DNS_RESOLVER_CHECKNAMES;
+ view->checknames = ISC_FALSE;
+ } else if (strcasecmp(str, "ignore") == 0) {
+ view->checknames = ISC_FALSE;
+ } else
+ INSIST(0);
+
+ obj = NULL;
+ result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ zero_no_soattl = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "dnssec-accept-expired", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->acceptexpired = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "dnssec-validation", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->enablevalidation = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-cache-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->maxcachettl = cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-ncache-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->maxncachettl = cfg_obj_asuint32(obj);
+ if (view->maxncachettl > 7 * 24 * 3600)
+ view->maxncachettl = 7 * 24 * 3600;
+
+ /*
* Configure the view's cache. Try to reuse an existing
* cache if possible, otherwise create a new cache.
* Note that the ADB is not preserved in either case.
+ * When a matching view is found, the associated statistics are
+ * also retrieved and reused.
*
- * XXX Determining when it is safe to reuse a cache is
- * tricky. When the view's configuration changes, the cached
- * data may become invalid because it reflects our old
- * view of the world. As more view attributes become
- * configurable, we will have to add code here to check
- * whether they have changed in ways that could
- * invalidate the cache.
+ * XXX Determining when it is safe to reuse a cache is tricky.
+ * When the view's configuration changes, the cached data may become
+ * invalid because it reflects our old view of the world. We check
+ * some of the configuration parameters that could invalidate the cache,
+ * but there are other configuration options that should be checked.
+ * For example, if a view uses a forwarder, changes in the forwarder
+ * configuration may invalidate the cache. At the moment, it's the
+ * administrator's responsibility to ensure these configuration options
+ * don't invalidate reusing.
*/
result = dns_viewlist_find(&ns_g_server->viewlist,
view->name, view->rdclass,
@@ -1114,17 +1260,29 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
goto cleanup;
if (pview != NULL) {
- INSIST(pview->cache != NULL);
- isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
- NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3),
- "reusing existing cache");
- reused_cache = ISC_TRUE;
- dns_cache_attach(pview->cache, &cache);
+ if (cache_reusable(pview, view, zero_no_soattl)) {
+ INSIST(pview->cache != NULL);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3),
+ "reusing existing cache");
+ reused_cache = ISC_TRUE;
+ dns_cache_attach(pview->cache, &cache);
+ } else {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
+ "cache cannot be reused for view %s "
+ "due to configuration parameter mismatch",
+ view->name);
+ }
+ dns_view_getresstats(pview, &resstats);
+ dns_view_getresquerystats(pview, &resquerystats);
dns_view_detach(&pview);
- } else {
+ }
+ if (cache == NULL) {
CHECK(isc_mem_create(0, 0, &cmctx));
CHECK(dns_cache_create(cmctx, ns_g_taskmgr, ns_g_timermgr,
view->rdclass, "rbt", 0, NULL, &cache));
+ isc_mem_setname(cmctx, "cache", NULL);
}
dns_view_setcache(view, cache);
@@ -1170,27 +1328,6 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
dns_cache_detach(&cache);
/*
- * Check-names.
- */
- obj = NULL;
- result = ns_checknames_get(maps, "response", &obj);
- INSIST(result == ISC_R_SUCCESS);
-
- str = cfg_obj_asstring(obj);
- if (strcasecmp(str, "fail") == 0) {
- check = DNS_RESOLVER_CHECKNAMES |
- DNS_RESOLVER_CHECKNAMESFAIL;
- view->checknames = ISC_TRUE;
- } else if (strcasecmp(str, "warn") == 0) {
- check = DNS_RESOLVER_CHECKNAMES;
- view->checknames = ISC_FALSE;
- } else if (strcasecmp(str, "ignore") == 0) {
- check = 0;
- view->checknames = ISC_FALSE;
- } else
- INSIST(0);
-
- /*
* Resolver.
*
* XXXRTH Hardwired number of tasks.
@@ -1210,9 +1347,18 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
}
CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31,
ns_g_socketmgr, ns_g_timermgr,
- check, ns_g_dispatchmgr,
+ resopts, ns_g_dispatchmgr,
dispatch4, dispatch6));
+ if (resstats == NULL) {
+ CHECK(isc_stats_create(mctx, &resstats,
+ dns_resstatscounter_max));
+ }
+ dns_view_setresstats(view, resstats);
+ if (resquerystats == NULL)
+ CHECK(dns_rdatatypestats_create(mctx, &resquerystats));
+ dns_view_setresquerystats(view, resquerystats);
+
/*
* Set the ADB cache size to 1/8th of the max-cache-size.
*/
@@ -1235,11 +1381,6 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
lame_ttl = 1800;
dns_resolver_setlamettl(view->resolver, lame_ttl);
- obj = NULL;
- result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj);
- INSIST(result == ISC_R_SUCCESS);
- dns_resolver_setzeronosoattl(view->resolver, cfg_obj_asboolean(obj));
-
/*
* Set the resolver's EDNS UDP size.
*/
@@ -1460,28 +1601,26 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
}
/*
- * Set "allow-query-cache" and "allow-recursion" acls if
+ * Set "allow-query-cache", "allow-query-cache-on",
+ * "allow-recursion", and "allow-recursion-on" acls if
* configured in named.conf.
*/
CHECK(configure_view_acl(vconfig, config, "allow-query-cache",
actx, ns_g_mctx, &view->queryacl));
-
- if (strcmp(view->name, "_bind") != 0)
+ CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on",
+ actx, ns_g_mctx, &view->queryonacl));
+ if (view->queryonacl == NULL)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-query-cache-on", actx,
+ ns_g_mctx, &view->queryonacl));
+ if (strcmp(view->name, "_bind") != 0) {
CHECK(configure_view_acl(vconfig, config, "allow-recursion",
- actx, ns_g_mctx, &view->recursionacl));
-
- /*
- * Warning if both "recursion no;" and allow-recursion are active
- * except for "allow-recursion { none; };".
- */
- if (!view->recursion && view->recursionacl != NULL &&
- (view->recursionacl->length != 1 ||
- view->recursionacl->elements[0].type != dns_aclelementtype_any ||
- view->recursionacl->elements[0].negative != ISC_TRUE))
- isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
- NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
- "both \"recursion no;\" and \"allow-recursion\" "
- "active%s%s", forview, viewname);
+ actx, ns_g_mctx,
+ &view->recursionacl));
+ CHECK(configure_view_acl(vconfig, config, "allow-recursion-on",
+ actx, ns_g_mctx,
+ &view->recursiononacl));
+ }
/*
* "allow-query-cache" inherits from "allow-recursion" if set,
@@ -1491,25 +1630,66 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
*/
if (view->queryacl == NULL && view->recursionacl != NULL)
dns_acl_attach(view->recursionacl, &view->queryacl);
- if (view->queryacl == NULL)
+ if (view->queryacl == NULL && view->recursion)
CHECK(configure_view_acl(vconfig, config, "allow-query",
actx, ns_g_mctx, &view->queryacl));
- if (view->recursionacl == NULL && view->queryacl != NULL)
+ if (view->recursion &&
+ view->recursionacl == NULL && view->queryacl != NULL)
dns_acl_attach(view->queryacl, &view->recursionacl);
/*
- * Set default "allow-recursion" and "allow-query-cache" acls.
+ * Set default "allow-recursion", "allow-recursion-on" and
+ * "allow-query-cache" acls.
*/
if (view->recursionacl == NULL && view->recursion)
- CHECK(configure_view_acl(NULL, ns_g_config, "allow-recursion",
- actx, ns_g_mctx, &view->recursionacl));
- if (view->queryacl == NULL)
CHECK(configure_view_acl(NULL, ns_g_config,
- "allow-query-cache", actx,
- ns_g_mctx, &view->queryacl));
+ "allow-recursion",
+ actx, ns_g_mctx,
+ &view->recursionacl));
+ if (view->recursiononacl == NULL && view->recursion)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-recursion-on",
+ actx, ns_g_mctx,
+ &view->recursiononacl));
+ if (view->queryacl == NULL) {
+ if (view->recursion)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-query-cache", actx,
+ ns_g_mctx, &view->queryacl));
+ else {
+ if (view->queryacl != NULL)
+ dns_acl_detach(&view->queryacl);
+ CHECK(dns_acl_none(ns_g_mctx, &view->queryacl));
+ }
+ }
+
+ /*
+ * Configure sortlist, if set
+ */
+ CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx,
+ &view->sortlist));
- CHECK(configure_view_acl(vconfig, config, "sortlist",
- actx, ns_g_mctx, &view->sortlist));
+ /*
+ * Configure default allow-transfer, allow-notify, allow-update
+ * and allow-update-forwarding ACLs, if set, so they can be
+ * inherited by zones.
+ */
+ if (view->notifyacl == NULL)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-notify", actx,
+ ns_g_mctx, &view->notifyacl));
+ if (view->transferacl == NULL)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-transfer", actx,
+ ns_g_mctx, &view->transferacl));
+ if (view->updateacl == NULL)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-update", actx,
+ ns_g_mctx, &view->updateacl));
+ if (view->upfwdacl == NULL)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-update-forwarding", actx,
+ ns_g_mctx, &view->upfwdacl));
obj = NULL;
result = ns_config_get(maps, "request-ixfr", &obj);
@@ -1522,6 +1702,11 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
view->provideixfr = cfg_obj_asboolean(obj);
obj = NULL;
+ result = ns_config_get(maps, "request-nsid", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->requestnsid = cfg_obj_asboolean(obj);
+
+ obj = NULL;
result = ns_config_get(maps, "max-clients-per-query", &obj);
INSIST(result == ISC_R_SUCCESS);
max_clients_per_query = cfg_obj_asuint32(obj);
@@ -1539,16 +1724,6 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
view->enablednssec = cfg_obj_asboolean(obj);
obj = NULL;
- result = ns_config_get(maps, "dnssec-accept-expired", &obj);
- INSIST(result == ISC_R_SUCCESS);
- view->acceptexpired = cfg_obj_asboolean(obj);
-
- obj = NULL;
- result = ns_config_get(maps, "dnssec-validation", &obj);
- INSIST(result == ISC_R_SUCCESS);
- view->enablevalidation = cfg_obj_asboolean(obj);
-
- obj = NULL;
result = ns_config_get(maps, "dnssec-lookaside", &obj);
if (result == ISC_R_SUCCESS) {
for (element = cfg_list_first(obj);
@@ -1603,18 +1778,6 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
CHECK(mustbesecure(obj, view->resolver));
obj = NULL;
- result = ns_config_get(maps, "max-cache-ttl", &obj);
- INSIST(result == ISC_R_SUCCESS);
- view->maxcachettl = cfg_obj_asuint32(obj);
-
- obj = NULL;
- result = ns_config_get(maps, "max-ncache-ttl", &obj);
- INSIST(result == ISC_R_SUCCESS);
- view->maxncachettl = cfg_obj_asuint32(obj);
- if (view->maxncachettl > 7 * 24 * 3600)
- view->maxncachettl = 7 * 24 * 3600;
-
- obj = NULL;
result = ns_config_get(maps, "preferred-glue", &obj);
if (result == ISC_R_SUCCESS) {
str = cfg_obj_asstring(obj);
@@ -1690,6 +1853,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
const char *empty_dbtype[4] =
{ "_builtin", "empty", NULL, NULL };
int empty_dbtypec = 4;
+ isc_boolean_t zonestats_on;
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
@@ -1724,6 +1888,11 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
} else
empty_dbtype[3] = ".";
+ obj = NULL;
+ result = ns_config_get(maps, "zone-statistics", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ zonestats_on = cfg_obj_asboolean(obj);
+
logit = ISC_TRUE;
for (empty = empty_zones[empty_zone].zone;
empty != NULL;
@@ -1748,6 +1917,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
*/
(void)dns_view_findzone(view, name, &zone);
if (zone != NULL) {
+ CHECK(setquerystats(zone, mctx, zonestats_on));
dns_zone_detach(&zone);
continue;
}
@@ -1798,6 +1968,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
if (zone != NULL) {
dns_zone_setview(zone, view);
CHECK(dns_view_addzone(view, zone));
+ CHECK(setquerystats(zone, mctx,
+ zonestats_on));
dns_zone_detach(&zone);
continue;
}
@@ -1809,14 +1981,18 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
dns_zone_setclass(zone, view->rdclass);
dns_zone_settype(zone, dns_zone_master);
+ dns_zone_setstats(zone, ns_g_server->zonestats);
CHECK(dns_zone_setdbtype(zone, empty_dbtypec,
empty_dbtype));
if (view->queryacl != NULL)
dns_zone_setqueryacl(zone, view->queryacl);
+ if (view->queryonacl != NULL)
+ dns_zone_setqueryonacl(zone, view->queryonacl);
dns_zone_setdialup(zone, dns_dialuptype_no);
dns_zone_setnotifytype(zone, dns_notifytype_no);
dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS,
ISC_TRUE);
+ CHECK(setquerystats(zone, mctx, zonestats_on));
CHECK(dns_view_addzone(view, zone));
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_INFO,
@@ -1835,6 +2011,10 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
dns_dispatch_detach(&dispatch4);
if (dispatch6 != NULL)
dns_dispatch_detach(&dispatch6);
+ if (resstats != NULL)
+ isc_stats_detach(&resstats);
+ if (resquerystats != NULL)
+ dns_stats_detach(&resquerystats);
if (order != NULL)
dns_order_detach(&order);
if (cmctx != NULL)
@@ -1959,6 +2139,8 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
isc_result_t result;
in_port_t port;
+ ISC_LIST_INIT(addresses);
+
/*
* Determine which port to send forwarded requests to.
*/
@@ -1984,8 +2166,6 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
if (forwarders != NULL)
faddresses = cfg_tuple_get(forwarders, "addresses");
- ISC_LIST_INIT(addresses);
-
for (element = cfg_list_first(faddresses);
element != NULL;
element = cfg_list_next(element))
@@ -2283,6 +2463,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
if (view->acache != NULL)
dns_zone_setacache(zone, view->acache);
CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
+ dns_zone_setstats(zone, ns_g_server->zonestats);
}
/*
@@ -2398,25 +2579,23 @@ add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr,
{
ns_listenelt_t *lelt = NULL;
dns_acl_t *src_acl = NULL;
- dns_aclelement_t aelt;
isc_result_t result;
isc_sockaddr_t any_sa6;
+ isc_netaddr_t netaddr;
REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
isc_sockaddr_any6(&any_sa6);
if (!isc_sockaddr_equal(&any_sa6, addr) &&
(wcardport_ok || isc_sockaddr_getport(addr) != 0)) {
- aelt.type = dns_aclelementtype_ipprefix;
- aelt.negative = ISC_FALSE;
- aelt.u.ip_prefix.prefixlen = 128;
- isc_netaddr_fromin6(&aelt.u.ip_prefix.address,
- &addr->type.sin6.sin6_addr);
+ isc_netaddr_fromin6(&netaddr, &addr->type.sin6.sin6_addr);
- result = dns_acl_create(mctx, 1, &src_acl);
+ result = dns_acl_create(mctx, 0, &src_acl);
if (result != ISC_R_SUCCESS)
return (result);
- result = dns_acl_appendelement(src_acl, &aelt);
+
+ result = dns_iptable_addprefix(src_acl->iptable,
+ &netaddr, 128, ISC_TRUE);
if (result != ISC_R_SUCCESS)
goto clean;
@@ -2900,6 +3079,9 @@ load_configuration(const char *filename, ns_server_t *server,
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.
*/
@@ -3059,11 +3241,13 @@ load_configuration(const char *filename, ns_server_t *server,
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,
- ISC_FALSE, &listenon));
+ enable, &listenon));
}
if (listenon != NULL) {
ns_interfacemgr_setlistenon6(server->interfacemgr,
@@ -3370,8 +3554,17 @@ load_configuration(const char *filename, ns_server_t *server,
obj = NULL;
if (options != NULL &&
- cfg_map_get(options, "memstatistics-file", &obj) == ISC_R_SUCCESS)
+ cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS)
+ ns_g_memstatistics = cfg_obj_asboolean(obj);
+ else
+ ns_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");
else
ns_main_setmemstats(NULL);
@@ -3415,8 +3608,12 @@ load_configuration(const char *filename, ns_server_t *server,
result = ns_config_get(maps, "server-id", &obj);
server->server_usehostname = ISC_FALSE;
if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
- server->server_usehostname = ISC_TRUE;
+ /* 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);
@@ -3555,6 +3752,8 @@ run_server(isc_task_t *task, isc_event_t *event) {
&ns_g_dispatchmgr),
"creating dispatch manager");
+ dns_dispatchmgr_setstats(ns_g_dispatchmgr, server->resolverstats);
+
CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr,
ns_g_socketmgr, ns_g_dispatchmgr,
&server->interfacemgr),
@@ -3622,6 +3821,7 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
ISC_LOG_INFO, "shutting down%s",
flush ? ": flushing changes" : "");
+ ns_statschannels_shutdown(server);
ns_controls_shutdown(server->controls);
end_reserved_dispatches(server, ISC_TRUE);
@@ -3742,7 +3942,16 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
server->statsfile = isc_mem_strdup(server->mctx, "named.stats");
CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
"isc_mem_strdup");
- server->querystats = NULL;
+ server->nsstats = NULL;
+ server->rcvquerystats = NULL;
+ server->opcodestats = NULL;
+ server->zonestats = NULL;
+ server->resolverstats = NULL;
+ server->sockstats = NULL;
+ CHECKFATAL(isc_stats_create(server->mctx, &server->sockstats,
+ isc_sockstatscounter_max),
+ "isc_stats_create");
+ isc_socketmgr_setstats(ns_g_socketmgr, server->sockstats);
server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");
CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
@@ -3759,8 +3968,24 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
server->server_usehostname = ISC_FALSE;
server->server_id = NULL;
- CHECKFATAL(dns_stats_alloccounters(ns_g_mctx, &server->querystats),
- "dns_stats_alloccounters");
+ CHECKFATAL(isc_stats_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(isc_stats_create(ns_g_mctx, &server->zonestats,
+ dns_zonestatscounter_max),
+ "dns_stats_create (zone)");
+
+ CHECKFATAL(isc_stats_create(ns_g_mctx, &server->resolverstats,
+ dns_resstatscounter_max),
+ "dns_stats_create (resolver)");
server->flushonshutdown = ISC_FALSE;
server->log_queries = ISC_FALSE;
@@ -3771,6 +3996,8 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
server->dispatchgen = 0;
ISC_LIST_INIT(server->dispatches);
+ ISC_LIST_INIT(server->statschannels);
+
server->magic = NS_SERVER_MAGIC;
*serverp = server;
}
@@ -3782,7 +4009,12 @@ ns_server_destroy(ns_server_t **serverp) {
ns_controls_destroy(&server->controls);
- dns_stats_freecounters(server->mctx, &server->querystats);
+ isc_stats_detach(&server->nsstats);
+ dns_stats_detach(&server->rcvquerystats);
+ dns_stats_detach(&server->opcodestats);
+ isc_stats_detach(&server->zonestats);
+ isc_stats_detach(&server->resolverstats);
+ isc_stats_detach(&server->sockstats);
isc_mem_free(server->mctx, server->statsfile);
isc_mem_free(server->mctx, server->dumpfile);
@@ -3936,13 +4168,17 @@ loadconfig(ns_server_t *server) {
result = load_configuration(ns_g_lwresdonly ?
lwresd_g_conffile : ns_g_conffile,
server, ISC_FALSE);
- if (result == ISC_R_SUCCESS)
+ if (result == ISC_R_SUCCESS) {
end_reserved_dispatches(server, ISC_FALSE);
- else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "reloading configuration succeeded");
+ } else {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"reloading configuration failed: %s",
isc_result_totext(result));
+ }
return (result);
}
@@ -3952,12 +4188,16 @@ reload(ns_server_t *server) {
CHECK(loadconfig(server));
result = load_zones(server, ISC_FALSE);
- if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "reloading zones succeeded");
+ else
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"reloading zones failed: %s",
isc_result_totext(result));
- }
+
cleanup:
return (result);
}
@@ -3968,12 +4208,16 @@ reconfig(ns_server_t *server) {
CHECK(loadconfig(server));
result = load_new_zones(server, ISC_FALSE);
- if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "any newly configured zones are now loaded");
+ else
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"loading new zones failed: %s",
isc_result_totext(result));
- }
+
cleanup: ;
}
@@ -3987,6 +4231,9 @@ ns_server_reload(isc_task_t *task, isc_event_t *event) {
INSIST(task = server->task);
UNUSED(task);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "received SIGHUP signal to reload zones");
(void)reload(server);
LOCK(&server->reload_event_lock);
@@ -4068,23 +4315,28 @@ zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) {
result = dns_rdataclass_fromtext(&rdclass, &r);
if (result != ISC_R_SUCCESS)
goto fail1;
- } else {
+ } else
rdclass = dns_rdataclass_in;
- }
- if (viewtxt == NULL)
- viewtxt = "_default";
- result = dns_viewlist_find(&server->viewlist, viewtxt,
- rdclass, &view);
- if (result != ISC_R_SUCCESS)
- goto fail1;
+ if (viewtxt == NULL) {
+ result = dns_viewlist_findzone(&server->viewlist,
+ dns_fixedname_name(&name),
+ ISC_TF(classtxt == NULL),
+ rdclass, zonep);
+ } else {
+ result = dns_viewlist_find(&server->viewlist, viewtxt,
+ rdclass, &view);
+ if (result != ISC_R_SUCCESS)
+ goto fail1;
+
+ result = dns_zt_find(view->zonetable, dns_fixedname_name(&name),
+ 0, NULL, zonep);
+ dns_view_detach(&view);
+ }
- result = dns_zt_find(view->zonetable, dns_fixedname_name(&name),
- 0, NULL, zonep);
/* Partial match? */
if (result != ISC_R_SUCCESS && *zonep != NULL)
dns_zone_detach(zonep);
- dns_view_detach(&view);
fail1:
return (result);
}
@@ -4313,7 +4565,8 @@ ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
return (result);
result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"),
- config, ns_g_lctx, actx, mctx, &delt->acl);
+ config, ns_g_lctx, actx, mctx, 0,
+ &delt->acl);
if (result != ISC_R_SUCCESS) {
ns_listenelt_destroy(delt);
return (result);
@@ -4325,61 +4578,26 @@ ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
isc_result_t
ns_server_dumpstats(ns_server_t *server) {
isc_result_t result;
- dns_zone_t *zone, *next;
- isc_stdtime_t now;
FILE *fp = NULL;
- int i;
- int ncounters;
-
- isc_stdtime_get(&now);
CHECKMF(isc_stdio_open(server->statsfile, "a", &fp),
"could not open statistics dump file", server->statsfile);
- ncounters = DNS_STATS_NCOUNTERS;
- fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now);
-
- for (i = 0; i < ncounters; i++)
- fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT "u\n",
- dns_statscounter_names[i],
- server->querystats[i]);
-
- zone = NULL;
- for (result = dns_zone_first(server->zonemgr, &zone);
- result == ISC_R_SUCCESS;
- next = NULL, result = dns_zone_next(zone, &next), zone = next)
- {
- isc_uint64_t *zonestats = dns_zone_getstatscounters(zone);
- if (zonestats != NULL) {
- char zonename[DNS_NAME_FORMATSIZE];
- dns_view_t *view;
- char *viewname;
-
- dns_name_format(dns_zone_getorigin(zone),
- zonename, sizeof(zonename));
- view = dns_zone_getview(zone);
- viewname = view->name;
- for (i = 0; i < ncounters; i++) {
- fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT
- "u %s",
- dns_statscounter_names[i],
- zonestats[i],
- zonename);
- if (strcmp(viewname, "_default") != 0)
- fprintf(fp, " %s", viewname);
- fprintf(fp, "\n");
- }
- }
- }
- if (result == ISC_R_NOMORE)
- result = ISC_R_SUCCESS;
+ result = ns_stats_dump(server, fp);
CHECK(result);
- fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now);
-
cleanup:
if (fp != NULL)
(void)isc_stdio_close(fp);
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumpstats complete");
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumpstats failed: %s",
+ dns_result_totext(result));
return (result);
}
@@ -4564,7 +4782,7 @@ dumpdone(void *arg, isc_result_t result) {
cleanup:
if (result != ISC_R_SUCCESS)
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
- NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"dumpdb failed: %s", dns_result_totext(result));
dumpcontext_destroy(dctx);
}
@@ -4661,6 +4879,15 @@ ns_server_dumprecursing(ns_server_t *server) {
cleanup:
if (fp != NULL)
result = isc_stdio_close(fp);
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumprecursing complete");
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumprecursing failed: %s",
+ dns_result_totext(result));
return (result);
}
@@ -4690,6 +4917,9 @@ ns_server_setdebuglevel(ns_server_t *server, char *args) {
ns_g_debuglevel = (unsigned int)newlevel;
}
isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "debug level is now %d", ns_g_debuglevel);
return (ISC_R_SUCCESS);
}
@@ -4774,15 +5004,33 @@ ns_server_flushcache(ns_server_t *server, char *args) {
continue;
found = ISC_TRUE;
result = dns_view_flushcache(view);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
flushed = ISC_FALSE;
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "flushing cache in view '%s' failed: %s",
+ view->name, isc_result_totext(result));
+ }
}
if (flushed && found) {
+ if (viewname != NULL)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing cache in view '%s' succeeded",
+ viewname);
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing caches in all views succeeded");
result = ISC_R_SUCCESS;
} else {
- if (!found)
+ if (!found) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "flushing cache in view '%s' failed: "
+ "view not found", viewname);
result = ISC_R_NOTFOUND;
- else
+ } else
result = ISC_R_FAILURE;
}
isc_task_endexclusive(server->task);
@@ -4833,15 +5081,36 @@ ns_server_flushname(ns_server_t *server, char *args) {
continue;
found = ISC_TRUE;
result = dns_view_flushname(view, name);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
flushed = ISC_FALSE;
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "flushing name '%s' in cache view '%s' "
+ "failed: %s", target, view->name,
+ isc_result_totext(result));
+ }
}
- if (flushed && found)
+ if (flushed && found) {
+ if (viewname != NULL)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing name '%s' in cache view '%s' "
+ "succeeded", target, viewname);
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing name '%s' in all cache views "
+ "succeeded", target);
result = ISC_R_SUCCESS;
- else if (!found)
- result = ISC_R_NOTFOUND;
- else
+ } else {
+ if (!found)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "flushing name '%s' in cache view '%s' "
+ "failed: view not found", target,
+ viewname);
result = ISC_R_FAILURE;
+ }
isc_task_endexclusive(server->task);
return (result);
}
@@ -4850,7 +5119,16 @@ isc_result_t
ns_server_status(ns_server_t *server, isc_buffer_t *text) {
int zonecount, xferrunning, xferdeferred, soaqueries;
unsigned int n;
+ const char *ob = "", *cb = "", *alt = "";
+ if (ns_g_server->version_set) {
+ ob = " (";
+ cb = ")";
+ if (ns_g_server->version == NULL)
+ alt = "version.bind/txt/ch disabled";
+ else
+ alt = ns_g_server->version;
+ }
zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY);
xferrunning = dns_zonemgr_getcount(server->zonemgr,
DNS_ZONESTATE_XFERRUNNING);
@@ -4858,8 +5136,14 @@ ns_server_status(ns_server_t *server, isc_buffer_t *text) {
DNS_ZONESTATE_XFERDEFERRED);
soaqueries = dns_zonemgr_getcount(server->zonemgr,
DNS_ZONESTATE_SOAQUERY);
+
n = snprintf((char *)isc_buffer_used(text),
isc_buffer_availablelength(text),
+ "version: %s%s%s%s\n"
+#ifdef ISC_PLATFORM_USETHREADS
+ "CPUs found: %u\n"
+ "worker threads: %u\n"
+#endif
"number of zones: %u\n"
"debug level: %d\n"
"xfers running: %u\n"
@@ -4869,6 +5153,10 @@ ns_server_status(ns_server_t *server, isc_buffer_t *text) {
"recursive clients: %d/%d/%d\n"
"tcp clients: %d/%d\n"
"server is up and running",
+ ns_g_version, ob, alt, cb,
+#ifdef ISC_PLATFORM_USETHREADS
+ ns_g_cpus_detected, ns_g_cpus,
+#endif
zonecount, ns_g_debuglevel, xferrunning, xferdeferred,
soaqueries, server->log_queries ? "ON" : "OFF",
server->recursionquota.used, server->recursionquota.soft,
@@ -4880,6 +5168,235 @@ ns_server_status(ns_server_t *server, isc_buffer_t *text) {
return (ISC_R_SUCCESS);
}
+static isc_result_t
+delete_keynames(dns_tsig_keyring_t *ring, char *target,
+ unsigned int *foundkeys)
+{
+ char namestr[DNS_NAME_FORMATSIZE];
+ isc_result_t result;
+ dns_rbtnodechain_t chain;
+ dns_name_t foundname;
+ dns_fixedname_t fixedorigin;
+ dns_name_t *origin;
+ dns_rbtnode_t *node;
+ dns_tsigkey_t *tkey;
+
+ dns_name_init(&foundname, NULL);
+ dns_fixedname_init(&fixedorigin);
+ origin = dns_fixedname_name(&fixedorigin);
+
+ again:
+ dns_rbtnodechain_init(&chain, ring->mctx);
+ result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
+ origin);
+ if (result == ISC_R_NOTFOUND) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (result);
+ }
+
+ for (;;) {
+ node = NULL;
+ dns_rbtnodechain_current(&chain, &foundname, origin, &node);
+ tkey = node->data;
+
+ if (tkey != NULL) {
+ if (!tkey->generated)
+ goto nextkey;
+
+ dns_name_format(&tkey->name, namestr, sizeof(namestr));
+ if (strcmp(namestr, target) == 0) {
+ (*foundkeys)++;
+ dns_rbtnodechain_invalidate(&chain);
+ (void)dns_rbt_deletename(ring->keys,
+ &tkey->name,
+ ISC_FALSE);
+ goto again;
+ }
+ }
+
+ nextkey:
+ result = dns_rbtnodechain_next(&chain, &foundname, origin);
+ if (result == ISC_R_NOMORE)
+ break;
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (result);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text) {
+ isc_result_t result;
+ unsigned int n;
+ dns_view_t *view;
+ unsigned int foundkeys = 0;
+ char *target;
+ char *viewname;
+
+ (void)next_token(&command, " \t"); /* skip command name */
+ target = next_token(&command, " \t");
+ if (target == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+ viewname = next_token(&command, " \t");
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ if (viewname == NULL || strcmp(view->name, viewname) == 0) {
+ RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_write);
+ result = delete_keynames(view->dynamickeys, target,
+ &foundkeys);
+ RWUNLOCK(&view->dynamickeys->lock,
+ isc_rwlocktype_write);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_endexclusive(server->task);
+ return (result);
+ }
+ }
+ }
+ isc_task_endexclusive(server->task);
+
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "%d tsig keys deleted.\n", foundkeys);
+ if (n >= isc_buffer_availablelength(text)) {
+ isc_task_endexclusive(server->task);
+ return (ISC_R_NOSPACE);
+ }
+ isc_buffer_add(text, n);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t *text,
+ unsigned int *foundkeys)
+{
+ char namestr[DNS_NAME_FORMATSIZE];
+ char creatorstr[DNS_NAME_FORMATSIZE];
+ isc_result_t result;
+ dns_rbtnodechain_t chain;
+ dns_name_t foundname;
+ dns_fixedname_t fixedorigin;
+ dns_name_t *origin;
+ dns_rbtnode_t *node;
+ dns_tsigkey_t *tkey;
+ unsigned int n;
+ const char *viewname;
+
+ if (view != NULL)
+ viewname = view->name;
+ else
+ viewname = "(global)";
+
+ dns_name_init(&foundname, NULL);
+ dns_fixedname_init(&fixedorigin);
+ origin = dns_fixedname_name(&fixedorigin);
+ dns_rbtnodechain_init(&chain, ring->mctx);
+ result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
+ origin);
+ if (result == ISC_R_NOTFOUND) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (result);
+ }
+
+ for (;;) {
+ node = NULL;
+ dns_rbtnodechain_current(&chain, &foundname, origin, &node);
+ tkey = node->data;
+
+ if (tkey != NULL) {
+ (*foundkeys)++;
+ dns_name_format(&tkey->name, namestr, sizeof(namestr));
+ if (tkey->generated) {
+ dns_name_format(tkey->creator, creatorstr,
+ sizeof(creatorstr));
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "view \"%s\"; type \"dynamic\"; key \"%s\"; creator \"%s\";\n",
+ viewname, namestr, creatorstr);
+ } else {
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "view \"%s\"; type \"static\"; key \"%s\";\n",
+ viewname, namestr);
+ }
+ if (n >= isc_buffer_availablelength(text)) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (ISC_R_NOSPACE);
+ }
+ isc_buffer_add(text, n);
+ }
+ result = dns_rbtnodechain_next(&chain, &foundname, origin);
+ if (result == ISC_R_NOMORE)
+ break;
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (result);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) {
+ isc_result_t result;
+ unsigned int n;
+ dns_view_t *view;
+ unsigned int foundkeys = 0;
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ RWLOCK(&view->statickeys->lock, isc_rwlocktype_read);
+ result = list_keynames(view, view->statickeys, text,
+ &foundkeys);
+ RWUNLOCK(&view->statickeys->lock, isc_rwlocktype_read);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_endexclusive(server->task);
+ return (result);
+ }
+ RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
+ result = list_keynames(view, view->dynamickeys, text,
+ &foundkeys);
+ RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_endexclusive(server->task);
+ return (result);
+ }
+ }
+ isc_task_endexclusive(server->task);
+
+ if (foundkeys == 0) {
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "no tsig keys found.\n");
+ if (n >= isc_buffer_availablelength(text)) {
+ isc_task_endexclusive(server->task);
+ return (ISC_R_NOSPACE);
+ }
+ isc_buffer_add(text, n);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
/*
* Act on a "freeze" or "thaw" command from the command channel.
*/