21482911 Upgrade Solaris to BIND 9.6-ESV-R11-P2 s11-update
authorBen Chang <Benjamin.Chang@Oracle.COM>
Tue, 28 Jul 2015 00:04:43 -0700
branchs11-update
changeset 4708 038a91551a91
parent 4683 d5b9967c8e4c
child 4734 574105b56fc9
21482911 Upgrade Solaris to BIND 9.6-ESV-R11-P2 21482422 problem in SERVICE/DNS-SERVER
components/bind/Makefile
components/bind/bind.license
components/bind/patches/001-reclimit-v96.patch
components/bind/patches/002-RT40046.patch
components/bind/patches/reclimit-v96.patch
--- a/components/bind/Makefile	Mon Jul 20 23:01:54 2015 -0700
+++ b/components/bind/Makefile	Tue Jul 28 00:04:43 2015 -0700
@@ -24,8 +24,8 @@
 
 COMPONENT_NAME=		bind
 COMPONENT_VERSION=	9.6-ESV-R11
-HUMAN_VERSION=		$(COMPONENT_VERSION)-P1
-IPS_COMPONENT_VERSION=	9.6.3.11.1
+HUMAN_VERSION=		$(COMPONENT_VERSION)-P2
+IPS_COMPONENT_VERSION=	9.6.3.11.2
 COMPONENT_SRC=		$(COMPONENT_NAME)-$(COMPONENT_VERSION)
 COMPONENT_ARCHIVE=	$(COMPONENT_SRC).tar.gz
 COMPONENT_PROJECT_URL=	http://www.isc.org/software/bind/
@@ -37,7 +37,7 @@
 	http://ftp.isc.org/isc/bind9/$(COMPONENT_VERSION)/$(COMPONENT_ARCHIVE)
 COMPONENT_BUGDB=	service/dns-server
 
-TPNO=			20537
+TPNO=			23687
 
 include $(WS_MAKE_RULES)/prep.mk
 include $(WS_MAKE_RULES)/configure.mk
--- a/components/bind/bind.license	Mon Jul 20 23:01:54 2015 -0700
+++ b/components/bind/bind.license	Tue Jul 28 00:04:43 2015 -0700
@@ -1,4 +1,4 @@
-Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
 Copyright (C) 1996-2003  Internet Software Consortium.
 
 Permission to use, copy, modify, and/or distribute this software for any
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/bind/patches/001-reclimit-v96.patch	Tue Jul 28 00:04:43 2015 -0700
@@ -0,0 +1,1064 @@
+This patch was obtained from ISC for 9.6-ESV-R11-P1. The patch can
+only be obtained from [email protected] on an as needed
+basis.
+
+diff --git a/CHANGES b/CHANGES
+index 178f73d..8ace4fb 100644
+--- a/CHANGES
++++ b/CHANGES
[email protected]@ -1,3 +1,17 @@
++	--- 9.6-ESV-R11-P1 released ---
++
++4006.	[security]	A flaw in delegation handling could be exploited
++			to put named into an infinite loop.  This has
++			been addressed by placing limits on the number
++			of levels of recursion named will allow (default 7),
++			and the number of iterative queries that it will
++			send (default 50) before terminating a recursive
++			query (CVE-2014-8500).
++
++			The recursion depth limit is configured via the
++			"max-recursion-depth" option, and the query limit
++			via the "max-recursion-queries" option.  [RT #37580]
++
+ 	--- 9.6-ESV-R11 released ---
+ 
+ 	--- 9.6-ESV-R11rc2 released ---
+diff --git a/bin/named/config.c b/bin/named/config.c
+index d85afa7..823d101 100644
+--- a/bin/named/config.c
++++ b/bin/named/config.c
[email protected]@ -15,8 +15,6 @@
+  * PERFORMANCE OF THIS SOFTWARE.
+  */
+ 
+-/* $Id$ */
+-
+ /*! \file */
+ 
+ #include <config.h>
[email protected]@ -145,6 +143,8 @@ options {\n\
+ 	dnssec-accept-expired no;\n\
+ 	clients-per-query 10;\n\
+ 	max-clients-per-query 100;\n\
++	max-recursion-depth 7;\n\
++	max-recursion-queries 50;\n\
+ 	zero-no-soa-ttl-cache no;\n\
+ 	nsec3-test-zone no;\n\
+ "
+diff --git a/bin/named/include/named/query.h b/bin/named/include/named/query.h
+index 20aff40..771345e 100644
+--- a/bin/named/include/named/query.h
++++ b/bin/named/include/named/query.h
[email protected]@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2004, 2005, 2007, 2010, 2012  Internet Systems Consortium, Inc. ("ISC")
++ * Copyright (C) 2004, 2005, 2007, 2010, 2011, 2013, 2014  Internet Systems Consortium, Inc. ("ISC")
+  * Copyright (C) 1999-2002  Internet Software Consortium.
+  *
+  * Permission to use, copy, modify, and/or distribute this software for any
[email protected]@ -15,8 +15,6 @@
+  * PERFORMANCE OF THIS SOFTWARE.
+  */
+ 
+-/* $Id$ */
+-
+ #ifndef NAMED_QUERY_H
+ #define NAMED_QUERY_H 1
+ 
+diff --git a/bin/named/query.c b/bin/named/query.c
+index 10a7d9a..48e4822 100644
+--- a/bin/named/query.c
++++ b/bin/named/query.c
[email protected]@ -3343,13 +3343,12 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
+ 		peeraddr = &client->peeraddr;
+ 	else
+ 		peeraddr = NULL;
+-	result = dns_resolver_createfetch2(client->view->resolver,
++	result = dns_resolver_createfetch3(client->view->resolver,
+ 					   client->query.qname,
+ 					   qtype, qdomain, nameservers,
+ 					   NULL, peeraddr, client->message->id,
+-					   client->query.fetchoptions,
+-					   client->task,
+-					   query_resume, client,
++					   client->query.fetchoptions, 0, NULL,
++					   client->task, query_resume, client,
+ 					   rdataset, sigrdataset,
+ 					   &client->query.fetch);
+ 
+diff --git a/bin/named/server.c b/bin/named/server.c
+index af53b48..4d48074 100644
+--- a/bin/named/server.c
++++ b/bin/named/server.c
[email protected]@ -15,8 +15,6 @@
+  * PERFORMANCE OF THIS SOFTWARE.
+  */
+ 
+-/* $Id$ */
+-
+ /*! \file */
+ 
+ #include <config.h>
[email protected]@ -2048,6 +2046,16 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
+ 					max_clients_per_query);
+ 
+ 	obj = NULL;
++	result = ns_config_get(maps, "max-recursion-depth", &obj);
++	INSIST(result == ISC_R_SUCCESS);
++	dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj));
++
++	obj = NULL;
++	result = ns_config_get(maps, "max-recursion-queries", &obj);
++	INSIST(result == ISC_R_SUCCESS);
++	dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj));
++
++	obj = NULL;
+ 	result = ns_config_get(maps, "dnssec-enable", &obj);
+ 	INSIST(result == ISC_R_SUCCESS);
+ 	view->enablednssec = cfg_obj_asboolean(obj);
+diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml
+index f894aab..b823dc4 100644
+--- a/doc/arm/Bv9ARM-book.xml
++++ b/doc/arm/Bv9ARM-book.xml
[email protected]@ -4652,6 +4652,8 @@ category notify { null; };
+     <optional> max-acache-size <replaceable>size_spec</replaceable> ; </optional>
+     <optional> clients-per-query <replaceable>number</replaceable> ; </optional>
+     <optional> max-clients-per-query <replaceable>number</replaceable> ; </optional>
++    <optional> max-recursion-depth <replaceable>number</replaceable> ; </optional>
++    <optional> max-recursion-queries <replaceable>number</replaceable> ; </optional>
+     <optional> masterfile-format (<constant>text</constant>|<constant>raw</constant>) ; </optional>
+     <optional> empty-server <replaceable>name</replaceable> ; </optional>
+     <optional> empty-contact <replaceable>name</replaceable> ; </optional>
[email protected]@ -4729,6 +4731,35 @@ category notify { null; };
+ 	    </listitem>
+ 	  </varlistentry>
+ 
++	  <varlistentry id="max-recursion-depth">
++	    <term><command>max-recursion-depth</command></term>
++	    <listitem>
++	      <para>
++		Sets the maximum number of levels of recursion
++		that are permitted at any one time while servicing
++		a recursive query. Resolving a name may require
++		looking up a name server address, which in turn
++		requires resolving another name, etc; if the number
++		of indirections exceeds this value, the recursive
++		query is terminated and returns SERVFAIL.  The
++		default is 7.
++	      </para>
++	    </listitem>
++	  </varlistentry>
++
++	  <varlistentry id="max-recursion-queries">
++	    <term><command>max-recursion-queries</command></term>
++	    <listitem>
++	      <para>
++		Sets the maximum number of iterative queries that
++		may be sent while servicing a recursive query.
++		If more queries are sent, the recursive query
++		is terminated and returns SERVFAIL. The default
++		is 50.
++	      </para>
++	    </listitem>
++	  </varlistentry>
++
+ 	  <varlistentry>
+ 	    <term><command>tkey-gssapi-credential</command></term>
+ 	    <listitem>
+diff --git a/lib/dns/adb.c b/lib/dns/adb.c
+index 2d7b904..422e59c 100644
+--- a/lib/dns/adb.c
++++ b/lib/dns/adb.c
[email protected]@ -200,6 +200,7 @@ struct dns_adbfetch {
+ 	unsigned int                    magic;
+ 	dns_fetch_t                    *fetch;
+ 	dns_rdataset_t                  rdataset;
++	unsigned int			depth;
+ };
+ 
+ /*%
[email protected]@ -298,8 +299,7 @@ static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t,
+ static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
+ static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
+ static void clean_target(dns_adb_t *, dns_name_t *);
+-static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
+-				unsigned int);
++static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int);
+ static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
+ static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **,
+ 					isc_stdtime_t);
[email protected]@ -307,6 +307,7 @@ static void cancel_fetches_at_name(dns_adbname_t *);
+ static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
+ 				dns_rdatatype_t);
+ static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
++			       unsigned int, isc_counter_t *qc,
+ 			       dns_rdatatype_t);
+ static inline void check_exit(dns_adb_t *);
+ static void destroy(dns_adb_t *);
[email protected]@ -2282,6 +2283,19 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
+ 		   isc_stdtime_t now, dns_name_t *target,
+ 		   in_port_t port, dns_adbfind_t **findp)
+ {
++	return (dns_adb_createfind2(adb, task, action, arg, name,
++				    qname, qtype, options, now,
++				    target, port, 0, NULL, findp));
++}
++
++isc_result_t
++dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
++		    void *arg, dns_name_t *name, dns_name_t *qname,
++		    dns_rdatatype_t qtype, unsigned int options,
++		    isc_stdtime_t now, dns_name_t *target,
++		    in_port_t port, unsigned int depth, isc_counter_t *qc,
++		    dns_adbfind_t **findp)
++{
+ 	dns_adbfind_t *find;
+ 	dns_adbname_t *adbname;
+ 	int bucket;
[email protected]@ -2512,7 +2526,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
+ 		 * Start V4.
+ 		 */
+ 		if (WANT_INET(wanted_fetches) &&
+-		    fetch_name(adbname, start_at_zone,
++		    fetch_name(adbname, start_at_zone, depth, qc,
+ 			       dns_rdatatype_a) == ISC_R_SUCCESS) {
+ 			DP(DEF_LEVEL,
+ 			   "dns_adb_createfind: started A fetch for name %p",
[email protected]@ -2523,7 +2537,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
+ 		 * Start V6.
+ 		 */
+ 		if (WANT_INET6(wanted_fetches) &&
+-		    fetch_name(adbname, start_at_zone,
++		    fetch_name(adbname, start_at_zone, depth, qc,
+ 			       dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
+ 			DP(DEF_LEVEL,
+ 			   "dns_adb_createfind: "
[email protected]@ -3256,6 +3270,12 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
+ 		DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s",
+ 		   buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA",
+ 		   dns_result_totext(dev->result));
++		/*
++		 * Don't record a failure unless this is the initial
++		 * fetch of a chain.
++		 */
++		if (fetch->depth > 1)
++			goto out;
+ 		/* XXXMLG Don't pound on bad servers. */
+ 		if (address_type == DNS_ADBFIND_INET) {
+ 			name->expire_v4 = ISC_MIN(name->expire_v4, now + 300);
[email protected]@ -3293,9 +3313,8 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
+ }
+ 
+ static isc_result_t
+-fetch_name(dns_adbname_t *adbname,
+-	   isc_boolean_t start_at_zone,
+-	   dns_rdatatype_t type)
++fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone,
++	   unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type)
+ {
+ 	isc_result_t result;
+ 	dns_adbfetch_t *fetch = NULL;
[email protected]@ -3340,12 +3359,14 @@ fetch_name(dns_adbname_t *adbname,
+ 		result = ISC_R_NOMEMORY;
+ 		goto cleanup;
+ 	}
++	fetch->depth = depth;
+ 
+-	result = dns_resolver_createfetch(adb->view->resolver, &adbname->name,
+-					  type, name, nameservers, NULL,
+-					  options, adb->task, fetch_callback,
+-					  adbname, &fetch->rdataset, NULL,
+-					  &fetch->fetch);
++	result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name,
++					   type, name, nameservers, NULL,
++					   NULL, 0, options, depth, qc,
++					   adb->task, fetch_callback, adbname,
++					   &fetch->rdataset, NULL,
++					   &fetch->fetch);
+ 	if (result != ISC_R_SUCCESS)
+ 		goto cleanup;
+ 
+diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h
+index d4d1b05..556fcc2 100644
+--- a/lib/dns/include/dns/adb.h
++++ b/lib/dns/include/dns/adb.h
[email protected]@ -334,6 +334,13 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
+ 		   dns_rdatatype_t qtype, unsigned int options,
+ 		   isc_stdtime_t now, dns_name_t *target,
+ 		   in_port_t port, dns_adbfind_t **find);
++isc_result_t
++dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
++		    void *arg, dns_name_t *name, dns_name_t *qname,
++		    dns_rdatatype_t qtype, unsigned int options,
++		    isc_stdtime_t now, dns_name_t *target, in_port_t port,
++		    unsigned int depth, isc_counter_t *qc,
++		    dns_adbfind_t **find);
+ /*%<
+  * Main interface for clients. The adb will look up the name given in
+  * "name" and will build up a list of found addresses, and perhaps start
+diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h
+index d293daa..10c3a3a 100644
+--- a/lib/dns/include/dns/resolver.h
++++ b/lib/dns/include/dns/resolver.h
[email protected]@ -270,6 +270,18 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
+ 			  dns_rdataset_t *rdataset,
+ 			  dns_rdataset_t *sigrdataset,
+ 			  dns_fetch_t **fetchp);
++isc_result_t
++dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
++			  dns_rdatatype_t type,
++			  dns_name_t *domain, dns_rdataset_t *nameservers,
++			  dns_forwarders_t *forwarders,
++			  isc_sockaddr_t *client, isc_uint16_t id,
++			  unsigned int options, unsigned int depth,
++			  isc_counter_t *qc, isc_task_t *task,
++			  isc_taskaction_t action, void *arg,
++			  dns_rdataset_t *rdataset,
++			  dns_rdataset_t *sigrdataset,
++			  dns_fetch_t **fetchp);
+ /*%<
+  * Recurse to answer a question.
+  *
[email protected]@ -550,6 +562,30 @@ dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp);
+  * \li	resolver to be valid.
+  */
+ 
++void
++dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth);
++unsigned int
++dns_resolver_getmaxdepth(dns_resolver_t *resolver);
++/*%
++ * Get and set how many NS indirections will be followed when looking for
++ * nameserver addresses.
++ *
++ * Requires:
++ * \li	resolver to be valid.
++ */
++
++void
++dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries);
++unsigned int
++dns_resolver_getmaxqueries(dns_resolver_t *resolver);
++/*%
++ * Get and set how many iterative queries will be allowed before
++ * terminating a recursive query.
++ *
++ * Requires:
++ * \li	resolver to be valid.
++ */
++
+ ISC_LANG_ENDDECLS
+ 
+ #endif /* DNS_RESOLVER_H */
+diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
+index 7dcea6d..bd3d9fd 100644
+--- a/lib/dns/resolver.c
++++ b/lib/dns/resolver.c
[email protected]@ -21,6 +21,7 @@
+ 
+ #include <config.h>
+ 
++#include <isc/counter.h>
+ #include <isc/log.h>
+ #include <isc/platform.h>
+ #include <isc/print.h>
[email protected]@ -109,6 +110,16 @@
+ #define QTRACE(m)
+ #endif
+ 
++/* The default maximum number of recursions to follow before giving up. */
++#ifndef DEFAULT_RECURSION_DEPTH
++#define DEFAULT_RECURSION_DEPTH 7
++#endif
++
++/* The default maximum number of iterative queries to allow before giving up. */
++#ifndef DEFAULT_MAX_QUERIES
++#define DEFAULT_MAX_QUERIES 50
++#endif
++
+ /*%
+  * Maximum EDNS0 input packet size.
+  */
[email protected]@ -211,12 +222,13 @@ struct fetchctx {
+ 	isc_sockaddrlist_t		edns;
+ 	isc_sockaddrlist_t		edns512;
+ 	isc_sockaddrlist_t		bad_edns;
+-	dns_validator_t			*validator;
++	dns_validator_t *		validator;
+ 	ISC_LIST(dns_validator_t)       validators;
+ 	dns_db_t *			cache;
+ 	dns_adb_t *			adb;
+ 	isc_boolean_t			ns_ttl_ok;
+ 	isc_uint32_t			ns_ttl;
++	isc_counter_t *			qc;
+ 
+ 	/*%
+ 	 * The number of events we're waiting for.
[email protected]@ -283,6 +295,7 @@ struct fetchctx {
+ 	unsigned int			valfail;
+ 	isc_boolean_t			timeout;
+ 	dns_adbaddrinfo_t 		*addrinfo;
++	unsigned int			depth;
+ };
+ 
+ #define FCTX_MAGIC			ISC_MAGIC('F', '!', '!', '!')
[email protected]@ -394,6 +407,8 @@ struct dns_resolver {
+ 	unsigned int			spillatmin;
+ 	isc_timer_t *			spillattimer;
+ 	isc_boolean_t			zero_no_soa_ttl;
++	unsigned int			maxdepth;
++	unsigned int			maxqueries;
+ 
+ 	/* Locked by lock. */
+ 	unsigned int			references;
[email protected]@ -1495,6 +1510,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
+ 		if (result != ISC_R_SUCCESS)
+ 			goto cleanup_dispatch;
+ 	}
++
+ 	fctx->querysent++;
+ 
+ 	ISC_LIST_APPEND(fctx->queries, query, link);
[email protected]@ -2146,9 +2162,9 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
+ 		 */
+ 		INSIST(!SHUTTINGDOWN(fctx));
+ 		fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+-		if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES)
++		if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) {
+ 			want_try = ISC_TRUE;
+-		else {
++		} else {
+ 			fctx->findfail++;
+ 			if (fctx->pending == 0) {
+ 				/*
[email protected]@ -2177,7 +2193,7 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
+ 	else if (want_done)
+ 		fctx_done(fctx, ISC_R_FAILURE, __LINE__);
+ 	else if (destroy) {
+-			fctx_destroy(fctx);
++		fctx_destroy(fctx);
+ 		if (bucket_empty)
+ 			empty_bucket(res);
+ 	}
[email protected]@ -2499,12 +2515,13 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
+ 	 * See what we know about this address.
+ 	 */
+ 	find = NULL;
+-	result = dns_adb_createfind(fctx->adb,
+-				    res->buckets[fctx->bucketnum].task,
+-				    fctx_finddone, fctx, name,
+-				    &fctx->name, fctx->type,
+-				    options, now, NULL,
+-				    res->view->dstport, &find);
++	result = dns_adb_createfind2(fctx->adb,
++				     res->buckets[fctx->bucketnum].task,
++				     fctx_finddone, fctx, name,
++				     &fctx->name, fctx->type,
++				     options, now, NULL,
++				     res->view->dstport,
++				     fctx->depth + 1, fctx->qc, &find);
+ 	if (result != ISC_R_SUCCESS) {
+ 		if (result == DNS_R_ALIAS) {
+ 			/*
[email protected]@ -2612,6 +2629,14 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
+ 
+ 	res = fctx->res;
+ 
++	if (fctx->depth > res->maxdepth) {
++		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
++			      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
++			      "too much NS indirection resolving '%s'",
++			      fctx->info);
++		return (DNS_R_SERVFAIL);
++	}
++
+ 	/*
+ 	 * Forwarders.
+ 	 */
[email protected]@ -3087,6 +3112,16 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
+ 		}
+ 	}
+ 
++	result = isc_counter_increment(fctx->qc);
++	if (result != ISC_R_SUCCESS) {
++		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
++			      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
++			      "exceeded max queries resolving '%s'",
++			      fctx->info);
++		fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
++		return;
++	}
++
+ 	result = fctx_query(fctx, addrinfo, fctx->options);
+ 	if (result != ISC_R_SUCCESS)
+ 		fctx_done(fctx, result, __LINE__);
[email protected]@ -3185,6 +3220,7 @@ fctx_destroy(fetchctx_t *fctx) {
+ 		isc_mem_put(fctx->mctx, sa, sizeof(*sa));
+ 	}
+ 
++	isc_counter_detach(&fctx->qc);
+ 	isc_timer_detach(&fctx->timer);
+ 	dns_message_destroy(&fctx->rmessage);
+ 	dns_message_destroy(&fctx->qmessage);
[email protected]@ -3512,7 +3548,8 @@ log_ns_ttl(fetchctx_t *fctx, const char *where) {
+ static isc_result_t
+ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
+ 	    dns_name_t *domain, dns_rdataset_t *nameservers,
+-	    unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp)
++	    unsigned int options, unsigned int bucketnum, unsigned int depth,
++	    isc_counter_t *qc, fetchctx_t **fctxp)
+ {
+ 	fetchctx_t *fctx;
+ 	isc_result_t result;
[email protected]@ -3534,6 +3571,21 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
+ 	fctx = isc_mem_get(mctx, sizeof(*fctx));
+ 	if (fctx == NULL)
+ 		return (ISC_R_NOMEMORY);
++
++	fctx->qc = NULL;
++	if (qc != NULL) {
++		isc_counter_attach(qc, &fctx->qc);
++	} else {
++		result = isc_counter_create(res->mctx,
++					    res->maxqueries, &fctx->qc);
++		if (result != ISC_R_SUCCESS)
++			goto cleanup_fetch;
++	}
++
++	/*
++	 * Make fctx->info point to a copy of a formatted string
++	 * "name/type".
++	 */
+ 	dns_name_format(name, buf, sizeof(buf));
+ 	dns_rdatatype_format(type, typebuf, sizeof(typebuf));
+ 	strcat(buf, "/");       /* checked */
[email protected]@ -3541,7 +3593,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
+ 	fctx->info = isc_mem_strdup(mctx, buf);
+ 	if (fctx->info == NULL) {
+ 		result = ISC_R_NOMEMORY;
+-		goto cleanup_fetch;
++		goto cleanup_counter;
+ 	}
+ 	FCTXTRACE("create");
+ 	dns_name_init(&fctx->name, NULL);
[email protected]@ -3564,6 +3616,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
+ 	fctx->state = fetchstate_init;
+ 	fctx->want_shutdown = ISC_FALSE;
+ 	fctx->cloned = ISC_FALSE;
++	fctx->depth = depth;
+ 	ISC_LIST_INIT(fctx->queries);
+ 	ISC_LIST_INIT(fctx->finds);
+ 	ISC_LIST_INIT(fctx->altfinds);
[email protected]@ -3768,6 +3821,9 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
+  cleanup_info:
+ 	isc_mem_free(mctx, fctx->info);
+ 
++ cleanup_counter:
++	isc_counter_detach(&fctx->qc);
++
+  cleanup_fetch:
+ 	isc_mem_put(mctx, fctx, sizeof(*fctx));
+ 
[email protected]@ -7339,6 +7395,8 @@ dns_resolver_create(dns_view_t *view,
+ 	res->zero_no_soa_ttl = ISC_FALSE;
+ 	res->ndisps = 0;
+ 	res->nextdisp = 0; /* meaningless at this point, but init it */
++	res->maxdepth = DEFAULT_RECURSION_DEPTH;
++	res->maxqueries = DEFAULT_MAX_QUERIES;
+ 	res->nbuckets = ntasks;
+ 	res->activebuckets = ntasks;
+ 	res->buckets = isc_mem_get(view->mctx,
[email protected]@ -7778,9 +7836,9 @@ dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
+ 			 dns_rdataset_t *sigrdataset,
+ 			 dns_fetch_t **fetchp)
+ {
+-	return (dns_resolver_createfetch2(res, name, type, domain,
++	return (dns_resolver_createfetch3(res, name, type, domain,
+ 					  nameservers, forwarders, NULL, 0,
+-					  options, task, action, arg,
++					  options, 0, NULL, task, action, arg,
+ 					  rdataset, sigrdataset, fetchp));
+ }
+ 
[email protected]@ -7796,6 +7854,25 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
+ 			  dns_rdataset_t *sigrdataset,
+ 			  dns_fetch_t **fetchp)
+ {
++	return (dns_resolver_createfetch3(res, name, type, domain,
++					  nameservers, forwarders, client, id,
++					  options, 0, NULL, task, action, arg,
++					  rdataset, sigrdataset, fetchp));
++}
++
++isc_result_t
++dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
++			  dns_rdatatype_t type,
++			  dns_name_t *domain, dns_rdataset_t *nameservers,
++			  dns_forwarders_t *forwarders,
++			  isc_sockaddr_t *client, dns_messageid_t id,
++			  unsigned int options, unsigned int depth,
++			  isc_counter_t *qc, isc_task_t *task,
++			  isc_taskaction_t action, void *arg,
++			  dns_rdataset_t *rdataset,
++			  dns_rdataset_t *sigrdataset,
++			  dns_fetch_t **fetchp)
++{
+ 	dns_fetch_t *fetch;
+ 	fetchctx_t *fctx = NULL;
+ 	isc_result_t result = ISC_R_SUCCESS;
[email protected]@ -7882,11 +7959,12 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
+ 
+ 	if (fctx == NULL) {
+ 		result = fctx_create(res, name, type, domain, nameservers,
+-				     options, bucketnum, &fctx);
++				     options, bucketnum, depth, qc, &fctx);
+ 		if (result != ISC_R_SUCCESS)
+ 			goto unlock;
+ 		new_fctx = ISC_TRUE;
+-	}
++	} else if (fctx->depth > depth)
++		fctx->depth = depth;
+ 
+ 	result = fctx_join(fctx, task, client, id, action, arg,
+ 			   rdataset, sigrdataset, fetch);
[email protected]@ -8637,3 +8715,27 @@ dns_resolver_getoptions(dns_resolver_t *resolver) {
+ 
+ 	return (resolver->options);
+ }
++
++void
++dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) {
++	REQUIRE(VALID_RESOLVER(resolver));
++	resolver->maxdepth = maxdepth;
++}
++
++unsigned int
++dns_resolver_getmaxdepth(dns_resolver_t *resolver) {
++	REQUIRE(VALID_RESOLVER(resolver));
++	return (resolver->maxdepth);
++}
++
++void
++dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) {
++	REQUIRE(VALID_RESOLVER(resolver));
++	resolver->maxqueries = queries;
++}
++
++unsigned int
++dns_resolver_getmaxqueries(dns_resolver_t *resolver) {
++	REQUIRE(VALID_RESOLVER(resolver));
++	return (resolver->maxqueries);
++}
+diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in
+index 0b4020b..afc19ee 100644
+--- a/lib/isc/Makefile.in
++++ b/lib/isc/Makefile.in
[email protected]@ -13,8 +13,6 @@
+ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ # PERFORMANCE OF THIS SOFTWARE.
+ 
+-# $Id$
+-
+ srcdir =	@[email protected]
+ VPATH =		@[email protected]
+ top_srcdir =	@[email protected]
[email protected]@ -53,7 +51,7 @@ WIN32OBJS = 	win32/[email protected]@ win32/[email protected]@ win32/[email protected]@ \
+ # Alphabetically
+ OBJS =		@[email protected] \
+ 		[email protected]@ [email protected]@ [email protected]@ [email protected]@ [email protected]@ \
+-		[email protected]@ [email protected]@ [email protected]@ [email protected]@ \
++		[email protected]@ [email protected]@ [email protected]@ [email protected]@ [email protected]@ \
+ 		[email protected]@ [email protected]@ [email protected]@ [email protected]@ [email protected]@ \
+ 		[email protected]@ [email protected]@ [email protected]@ \
+ 		[email protected]@ [email protected]@ [email protected]@ [email protected]@ \
[email protected]@ -68,7 +66,7 @@ OBJS =		@[email protected] \
+ # Alphabetically
+ SRCS =		@[email protected] \
+ 		assertions.c base32.c base64.c bitstring.c buffer.c \
+-		bufferlist.c commandline.c error.c event.c \
++		bufferlist.c commandline.c counter.c error.c event.c \
+ 		heap.c hex.c hmacmd5.c hmacsha.c \
+ 		httpd.c inet_aton.c iterated_hash.c \
+ 		lex.c lfsr.c lib.c log.c \
+diff --git a/lib/isc/include/isc/Makefile.in b/lib/isc/include/isc/Makefile.in
+index 9adca3e..1cfbbd1 100644
+--- a/lib/isc/include/isc/Makefile.in
++++ b/lib/isc/include/isc/Makefile.in
[email protected]@ -13,8 +13,6 @@
+ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ # PERFORMANCE OF THIS SOFTWARE.
+ 
+-# $Id$
+-
+ srcdir =	@[email protected]
+ VPATH =		@[email protected]
+ top_srcdir =	@[email protected]
[email protected]@ -27,7 +25,7 @@ top_srcdir =	@[email protected]
+ # install target below.
+ #
+ HEADERS =	app.h assertions.h base64.h bitstring.h boolean.h buffer.h \
+-		bufferlist.h commandline.h entropy.h error.h event.h \
++		bufferlist.h commandline.h counter.h entropy.h error.h event.h \
+ 		eventclass.h file.h formatcheck.h fsaccess.h \
+ 		hash.h heap.h hex.h hmacmd5.h hmacsha.h \
+ 		httpd.h \
+diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h
+index 8e8b08f..a646b8b 100644
+--- a/lib/isc/include/isc/types.h
++++ b/lib/isc/include/isc/types.h
[email protected]@ -45,6 +45,7 @@ typedef struct isc_buffer		isc_buffer_t;		/*%< Buffer */
+ typedef ISC_LIST(isc_buffer_t)		isc_bufferlist_t;	/*%< Buffer List */
+ typedef struct isc_constregion		isc_constregion_t;	/*%< Const region */
+ typedef struct isc_consttextregion	isc_consttextregion_t;	/*%< Const Text Region */
++typedef struct isc_counter		isc_counter_t;		/*%< Counter */
+ typedef struct isc_entropy		isc_entropy_t;		/*%< Entropy */
+ typedef struct isc_entropysource	isc_entropysource_t;	/*%< Entropy Source */
+ typedef struct isc_event		isc_event_t;		/*%< Event */
+diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
+index fac2633..3023dcc 100644
+--- a/lib/isccfg/namedconf.c
++++ b/lib/isccfg/namedconf.c
[email protected]@ -15,8 +15,6 @@
+  * PERFORMANCE OF THIS SOFTWARE.
+  */
+ 
+-/* $Id$ */
+-
+ /*! \file */
+ 
+ #include <config.h>
[email protected]@ -830,6 +828,8 @@ view_clauses[] = {
+ 	{ "max-cache-ttl", &cfg_type_uint32, 0 },
+ 	{ "max-clients-per-query", &cfg_type_uint32, 0 },
+ 	{ "max-ncache-ttl", &cfg_type_uint32, 0 },
++	{ "max-recursion-depth", &cfg_type_uint32, 0 },
++	{ "max-recursion-queries", &cfg_type_uint32, 0 },
+ 	{ "max-udp-size", &cfg_type_uint32, 0 },
+ 	{ "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
+ 	{ "minimal-responses", &cfg_type_boolean, 0 },
+diff --git a/version b/version
+index 1be3c16..2058444 100644
+--- a/version
++++ b/version
[email protected]@ -10,4 +10,4 @@ MINORVER=6
+ PATCHVER=
+ RELEASETYPE=-ESV
+ RELEASEVER=-R11
+-EXTENSIONS=
++EXTENSIONS=-P1
+diff --git a/lib/isc/counter.c b/lib/isc/counter.c
+new file mode 100644
+index 0000000..d7d187b
+--- /dev/null
++++ b/lib/isc/counter.c
[email protected]@ -0,0 +1,138 @@
++/*
++ * Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/*! \file */
++
++#include <config.h>
++
++#include <stddef.h>
++
++#include <isc/counter.h>
++#include <isc/magic.h>
++#include <isc/mem.h>
++#include <isc/util.h>
++
++#define COUNTER_MAGIC			ISC_MAGIC('C', 'n', 't', 'r')
++#define VALID_COUNTER(r)		ISC_MAGIC_VALID(r, COUNTER_MAGIC)
++
++struct isc_counter {
++	unsigned int	magic;
++	isc_mem_t	*mctx;
++	isc_mutex_t	lock;
++	unsigned int	references;
++	unsigned int	limit;
++	unsigned int	used;
++};
++
++isc_result_t
++isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) {
++	isc_result_t result;
++	isc_counter_t *counter;
++
++	REQUIRE(counterp != NULL && *counterp == NULL);
++
++	counter = isc_mem_get(mctx, sizeof(*counter));
++	if (counter == NULL)
++		return (ISC_R_NOMEMORY);
++
++	result = isc_mutex_init(&counter->lock);
++	if (result != ISC_R_SUCCESS) {
++		isc_mem_put(mctx, counter, sizeof(*counter));
++		return (result);
++	}
++
++	counter->mctx = NULL;
++	isc_mem_attach(mctx, &counter->mctx);
++
++	counter->references = 1;
++	counter->limit = limit;
++	counter->used = 0;
++
++	counter->magic = COUNTER_MAGIC;
++	*counterp = counter;
++	return (ISC_R_SUCCESS);
++}
++
++isc_result_t
++isc_counter_increment(isc_counter_t *counter) {
++	isc_result_t result = ISC_R_SUCCESS;
++
++	LOCK(&counter->lock);
++	counter->used++;
++	if (counter->limit != 0 && counter->used >= counter->limit)
++		result = ISC_R_QUOTA;
++	UNLOCK(&counter->lock);
++
++	return (result);
++}
++
++unsigned int
++isc_counter_used(isc_counter_t *counter) {
++	REQUIRE(VALID_COUNTER(counter));
++
++	return (counter->used);
++}
++
++void
++isc_counter_setlimit(isc_counter_t *counter, int limit) {
++	REQUIRE(VALID_COUNTER(counter));
++
++	LOCK(&counter->lock);
++	counter->limit = limit;
++	UNLOCK(&counter->lock);
++}
++
++void
++isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp) {
++	REQUIRE(VALID_COUNTER(source));
++	REQUIRE(targetp != NULL && *targetp == NULL);
++
++	LOCK(&source->lock);
++	source->references++;
++	INSIST(source->references > 0);
++	UNLOCK(&source->lock);
++
++	*targetp = source;
++}
++
++static void
++destroy(isc_counter_t *counter) {
++	counter->magic = 0;
++	isc_mutex_destroy(&counter->lock);
++	isc_mem_putanddetach(&counter->mctx, counter, sizeof(*counter));
++}
++
++void
++isc_counter_detach(isc_counter_t **counterp) {
++	isc_counter_t *counter;
++	isc_boolean_t want_destroy = ISC_FALSE;
++
++	REQUIRE(counterp != NULL && *counterp != NULL);
++	counter = *counterp;
++	REQUIRE(VALID_COUNTER(counter));
++
++	*counterp = NULL;
++
++	LOCK(&counter->lock);
++	INSIST(counter->references > 0);
++	counter->references--;
++	if (counter->references == 0)
++		want_destroy = ISC_TRUE;
++	UNLOCK(&counter->lock);
++
++	if (want_destroy)
++		destroy(counter);
++}
+diff --git a/lib/isc/include/isc/counter.h b/lib/isc/include/isc/counter.h
+new file mode 100644
+index 0000000..e7ebd25
+--- /dev/null
++++ b/lib/isc/include/isc/counter.h
[email protected]@ -0,0 +1,90 @@
++/*
++ * Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef ISC_COUNTER_H
++#define ISC_COUNTER_H 1
++
++/*****
++ ***** Module Info
++ *****/
++
++/*! \file isc/counter.h
++ *
++ * \brief The isc_counter_t object is a simplified version of the
++ * isc_quota_t object; it tracks the consumption of limited
++ * resources, returning an error condition when the quota is
++ * exceeded.  However, unlike isc_quota_t, attaching and detaching
++ * from a counter object does not increment or decrement the counter.
++ */
++
++/***
++ *** Imports.
++ ***/
++
++#include <isc/lang.h>
++#include <isc/mutex.h>
++#include <isc/types.h>
++
++/*****
++ ***** Types.
++ *****/
++
++ISC_LANG_BEGINDECLS
++
++isc_result_t
++isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp);
++/*%<
++ * Allocate and initialize a counter object.
++ */
++
++isc_result_t
++isc_counter_increment(isc_counter_t *counter);
++/*%<
++ * Increment the counter.
++ *
++ * If the counter limit is nonzero and has been reached, then
++ * return ISC_R_QUOTA, otherwise ISC_R_SUCCESS. (The counter is
++ * incremented regardless of return value.)
++ */
++
++unsigned int
++isc_counter_used(isc_counter_t *counter);
++/*%<
++ * Return the current counter value.
++ */
++
++void
++isc_counter_setlimit(isc_counter_t *counter, int limit);
++/*%<
++ * Set the counter limit.
++ */
++
++void
++isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp);
++/*%<
++ * Attach to a counter object, increasing its reference counter.
++ */
++
++void
++isc_counter_detach(isc_counter_t **counterp);
++/*%<
++ * Detach (and destroy if reference counter has dropped to zero)
++ * a counter object.
++ */
++
++ISC_LANG_ENDDECLS
++
++#endif /* ISC_COUNTER_H */
+diff --git a/lib/isc/tests/counter_test.c b/lib/isc/tests/counter_test.c
+new file mode 100644
+index 0000000..a7a1997
+--- /dev/null
++++ b/lib/isc/tests/counter_test.c
[email protected]@ -0,0 +1,69 @@
++/*
++ * Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#include <config.h>
++#include <stdlib.h>
++
++#include <atf-c.h>
++
++#include <isc/counter.h>
++#include <isc/result.h>
++
++#include "isctest.h"
++
++ATF_TC(isc_counter);
++ATF_TC_HEAD(isc_counter, tc) {
++	atf_tc_set_md_var(tc, "descr", "isc counter object");
++}
++ATF_TC_BODY(isc_counter, tc) {
++	isc_result_t result;
++	isc_counter_t *counter = NULL;
++	int i;
++
++	result = isc_test_begin(NULL, ISC_TRUE);
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++
++	result = isc_counter_create(mctx, 0, &counter);
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++
++	for (i = 0; i < 10; i++) {
++		result = isc_counter_increment(counter);
++		ATF_CHECK_EQ(result, ISC_R_SUCCESS);
++	}
++
++	ATF_CHECK_EQ(isc_counter_used(counter), 10);
++
++	isc_counter_setlimit(counter, 15);
++	for (i = 0; i < 10; i++) {
++		result = isc_counter_increment(counter);
++		if (result != ISC_R_SUCCESS)
++			break;
++	}
++
++	ATF_CHECK_EQ(isc_counter_used(counter), 15);
++
++	isc_counter_detach(&counter);
++	isc_test_end();
++}
++
++/*
++ * Main
++ */
++ATF_TP_ADD_TCS(tp) {
++	ATF_TP_ADD_TC(tp, isc_counter);
++	return (atf_no_error());
++}
++
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/bind/patches/002-RT40046.patch	Tue Jul 28 00:04:43 2015 -0700
@@ -0,0 +1,38 @@
+This patch was obtained from ISC for 9.6-ESV-R11-P2. The patch can
+only be obtained from [email protected] on an as needed
+basis.
+
+--- a/CHANGES	Thu Jul 23 10:45:58 2015
++++ b/CHANGES	Thu Jul 23 10:45:58 2015
[email protected]@ -1,3 +1,9 @@
++	--- 9.6-ESV-R11-P2 released ---
++
++4165.	[security]	A failure to reset a value to NULL in tkey.c could
++			result in an assertion failure. (CVE-2015-5477)
++			[RT #40046]
++
+ 	--- 9.6-ESV-R11-P1 released ---
+ 
+ 4006.	[security]	A flaw in delegation handling could be exploited
+diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c
+index 66210d5..34ad90b 100644
+--- a/lib/dns/tkey.c
++++ b/lib/dns/tkey.c
[email protected]@ -654,6 +654,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
+ 		 * Try the answer section, since that's where Win2000
+ 		 * puts it.
+ 		 */
++		name = NULL;
+ 		if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
+ 					 dns_rdatatype_tkey, 0, &name,
+ 					 &tkeyset) != ISC_R_SUCCESS) {
+diff --git version version
+index 1be3c16..2058444 100644
+--- a/version
++++ b/version
[email protected]@ -10,4 +10,4 @@ MINORVER=6
+ PATCHVER=
+ RELEASETYPE=-ESV
+ RELEASEVER=-R11
+-EXTENSIONS=-P1
++EXTENSIONS=-P2
--- a/components/bind/patches/reclimit-v96.patch	Mon Jul 20 23:01:54 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1064 +0,0 @@
-This patch was obtained from ISC for 9.6-ESV-R11-P1. The patch can
-only be obtained from [email protected] on an as needed
-basis.
-
-diff --git a/CHANGES b/CHANGES
-index 178f73d..8ace4fb 100644
---- a/CHANGES
-+++ b/CHANGES
[email protected]@ -1,3 +1,17 @@
-+	--- 9.6-ESV-R11-P1 released ---
-+
-+4006.	[security]	A flaw in delegation handling could be exploited
-+			to put named into an infinite loop.  This has
-+			been addressed by placing limits on the number
-+			of levels of recursion named will allow (default 7),
-+			and the number of iterative queries that it will
-+			send (default 50) before terminating a recursive
-+			query (CVE-2014-8500).
-+
-+			The recursion depth limit is configured via the
-+			"max-recursion-depth" option, and the query limit
-+			via the "max-recursion-queries" option.  [RT #37580]
-+
- 	--- 9.6-ESV-R11 released ---
- 
- 	--- 9.6-ESV-R11rc2 released ---
-diff --git a/bin/named/config.c b/bin/named/config.c
-index d85afa7..823d101 100644
---- a/bin/named/config.c
-+++ b/bin/named/config.c
[email protected]@ -15,8 +15,6 @@
-  * PERFORMANCE OF THIS SOFTWARE.
-  */
- 
--/* $Id$ */
--
- /*! \file */
- 
- #include <config.h>
[email protected]@ -145,6 +143,8 @@ options {\n\
- 	dnssec-accept-expired no;\n\
- 	clients-per-query 10;\n\
- 	max-clients-per-query 100;\n\
-+	max-recursion-depth 7;\n\
-+	max-recursion-queries 50;\n\
- 	zero-no-soa-ttl-cache no;\n\
- 	nsec3-test-zone no;\n\
- "
-diff --git a/bin/named/include/named/query.h b/bin/named/include/named/query.h
-index 20aff40..771345e 100644
---- a/bin/named/include/named/query.h
-+++ b/bin/named/include/named/query.h
[email protected]@ -1,5 +1,5 @@
- /*
-- * Copyright (C) 2004, 2005, 2007, 2010, 2012  Internet Systems Consortium, Inc. ("ISC")
-+ * Copyright (C) 2004, 2005, 2007, 2010, 2011, 2013, 2014  Internet Systems Consortium, Inc. ("ISC")
-  * Copyright (C) 1999-2002  Internet Software Consortium.
-  *
-  * Permission to use, copy, modify, and/or distribute this software for any
[email protected]@ -15,8 +15,6 @@
-  * PERFORMANCE OF THIS SOFTWARE.
-  */
- 
--/* $Id$ */
--
- #ifndef NAMED_QUERY_H
- #define NAMED_QUERY_H 1
- 
-diff --git a/bin/named/query.c b/bin/named/query.c
-index 10a7d9a..48e4822 100644
---- a/bin/named/query.c
-+++ b/bin/named/query.c
[email protected]@ -3343,13 +3343,12 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
- 		peeraddr = &client->peeraddr;
- 	else
- 		peeraddr = NULL;
--	result = dns_resolver_createfetch2(client->view->resolver,
-+	result = dns_resolver_createfetch3(client->view->resolver,
- 					   client->query.qname,
- 					   qtype, qdomain, nameservers,
- 					   NULL, peeraddr, client->message->id,
--					   client->query.fetchoptions,
--					   client->task,
--					   query_resume, client,
-+					   client->query.fetchoptions, 0, NULL,
-+					   client->task, query_resume, client,
- 					   rdataset, sigrdataset,
- 					   &client->query.fetch);
- 
-diff --git a/bin/named/server.c b/bin/named/server.c
-index af53b48..4d48074 100644
---- a/bin/named/server.c
-+++ b/bin/named/server.c
[email protected]@ -15,8 +15,6 @@
-  * PERFORMANCE OF THIS SOFTWARE.
-  */
- 
--/* $Id$ */
--
- /*! \file */
- 
- #include <config.h>
[email protected]@ -2048,6 +2046,16 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
- 					max_clients_per_query);
- 
- 	obj = NULL;
-+	result = ns_config_get(maps, "max-recursion-depth", &obj);
-+	INSIST(result == ISC_R_SUCCESS);
-+	dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj));
-+
-+	obj = NULL;
-+	result = ns_config_get(maps, "max-recursion-queries", &obj);
-+	INSIST(result == ISC_R_SUCCESS);
-+	dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj));
-+
-+	obj = NULL;
- 	result = ns_config_get(maps, "dnssec-enable", &obj);
- 	INSIST(result == ISC_R_SUCCESS);
- 	view->enablednssec = cfg_obj_asboolean(obj);
-diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml
-index f894aab..b823dc4 100644
---- a/doc/arm/Bv9ARM-book.xml
-+++ b/doc/arm/Bv9ARM-book.xml
[email protected]@ -4652,6 +4652,8 @@ category notify { null; };
-     <optional> max-acache-size <replaceable>size_spec</replaceable> ; </optional>
-     <optional> clients-per-query <replaceable>number</replaceable> ; </optional>
-     <optional> max-clients-per-query <replaceable>number</replaceable> ; </optional>
-+    <optional> max-recursion-depth <replaceable>number</replaceable> ; </optional>
-+    <optional> max-recursion-queries <replaceable>number</replaceable> ; </optional>
-     <optional> masterfile-format (<constant>text</constant>|<constant>raw</constant>) ; </optional>
-     <optional> empty-server <replaceable>name</replaceable> ; </optional>
-     <optional> empty-contact <replaceable>name</replaceable> ; </optional>
[email protected]@ -4729,6 +4731,35 @@ category notify { null; };
- 	    </listitem>
- 	  </varlistentry>
- 
-+	  <varlistentry id="max-recursion-depth">
-+	    <term><command>max-recursion-depth</command></term>
-+	    <listitem>
-+	      <para>
-+		Sets the maximum number of levels of recursion
-+		that are permitted at any one time while servicing
-+		a recursive query. Resolving a name may require
-+		looking up a name server address, which in turn
-+		requires resolving another name, etc; if the number
-+		of indirections exceeds this value, the recursive
-+		query is terminated and returns SERVFAIL.  The
-+		default is 7.
-+	      </para>
-+	    </listitem>
-+	  </varlistentry>
-+
-+	  <varlistentry id="max-recursion-queries">
-+	    <term><command>max-recursion-queries</command></term>
-+	    <listitem>
-+	      <para>
-+		Sets the maximum number of iterative queries that
-+		may be sent while servicing a recursive query.
-+		If more queries are sent, the recursive query
-+		is terminated and returns SERVFAIL. The default
-+		is 50.
-+	      </para>
-+	    </listitem>
-+	  </varlistentry>
-+
- 	  <varlistentry>
- 	    <term><command>tkey-gssapi-credential</command></term>
- 	    <listitem>
-diff --git a/lib/dns/adb.c b/lib/dns/adb.c
-index 2d7b904..422e59c 100644
---- a/lib/dns/adb.c
-+++ b/lib/dns/adb.c
[email protected]@ -200,6 +200,7 @@ struct dns_adbfetch {
- 	unsigned int                    magic;
- 	dns_fetch_t                    *fetch;
- 	dns_rdataset_t                  rdataset;
-+	unsigned int			depth;
- };
- 
- /*%
[email protected]@ -298,8 +299,7 @@ static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t,
- static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
- static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
- static void clean_target(dns_adb_t *, dns_name_t *);
--static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
--				unsigned int);
-+static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int);
- static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
- static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **,
- 					isc_stdtime_t);
[email protected]@ -307,6 +307,7 @@ static void cancel_fetches_at_name(dns_adbname_t *);
- static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
- 				dns_rdatatype_t);
- static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
-+			       unsigned int, isc_counter_t *qc,
- 			       dns_rdatatype_t);
- static inline void check_exit(dns_adb_t *);
- static void destroy(dns_adb_t *);
[email protected]@ -2282,6 +2283,19 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
- 		   isc_stdtime_t now, dns_name_t *target,
- 		   in_port_t port, dns_adbfind_t **findp)
- {
-+	return (dns_adb_createfind2(adb, task, action, arg, name,
-+				    qname, qtype, options, now,
-+				    target, port, 0, NULL, findp));
-+}
-+
-+isc_result_t
-+dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
-+		    void *arg, dns_name_t *name, dns_name_t *qname,
-+		    dns_rdatatype_t qtype, unsigned int options,
-+		    isc_stdtime_t now, dns_name_t *target,
-+		    in_port_t port, unsigned int depth, isc_counter_t *qc,
-+		    dns_adbfind_t **findp)
-+{
- 	dns_adbfind_t *find;
- 	dns_adbname_t *adbname;
- 	int bucket;
[email protected]@ -2512,7 +2526,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
- 		 * Start V4.
- 		 */
- 		if (WANT_INET(wanted_fetches) &&
--		    fetch_name(adbname, start_at_zone,
-+		    fetch_name(adbname, start_at_zone, depth, qc,
- 			       dns_rdatatype_a) == ISC_R_SUCCESS) {
- 			DP(DEF_LEVEL,
- 			   "dns_adb_createfind: started A fetch for name %p",
[email protected]@ -2523,7 +2537,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
- 		 * Start V6.
- 		 */
- 		if (WANT_INET6(wanted_fetches) &&
--		    fetch_name(adbname, start_at_zone,
-+		    fetch_name(adbname, start_at_zone, depth, qc,
- 			       dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
- 			DP(DEF_LEVEL,
- 			   "dns_adb_createfind: "
[email protected]@ -3256,6 +3270,12 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
- 		DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s",
- 		   buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA",
- 		   dns_result_totext(dev->result));
-+		/*
-+		 * Don't record a failure unless this is the initial
-+		 * fetch of a chain.
-+		 */
-+		if (fetch->depth > 1)
-+			goto out;
- 		/* XXXMLG Don't pound on bad servers. */
- 		if (address_type == DNS_ADBFIND_INET) {
- 			name->expire_v4 = ISC_MIN(name->expire_v4, now + 300);
[email protected]@ -3293,9 +3313,8 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
- }
- 
- static isc_result_t
--fetch_name(dns_adbname_t *adbname,
--	   isc_boolean_t start_at_zone,
--	   dns_rdatatype_t type)
-+fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone,
-+	   unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type)
- {
- 	isc_result_t result;
- 	dns_adbfetch_t *fetch = NULL;
[email protected]@ -3340,12 +3359,14 @@ fetch_name(dns_adbname_t *adbname,
- 		result = ISC_R_NOMEMORY;
- 		goto cleanup;
- 	}
-+	fetch->depth = depth;
- 
--	result = dns_resolver_createfetch(adb->view->resolver, &adbname->name,
--					  type, name, nameservers, NULL,
--					  options, adb->task, fetch_callback,
--					  adbname, &fetch->rdataset, NULL,
--					  &fetch->fetch);
-+	result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name,
-+					   type, name, nameservers, NULL,
-+					   NULL, 0, options, depth, qc,
-+					   adb->task, fetch_callback, adbname,
-+					   &fetch->rdataset, NULL,
-+					   &fetch->fetch);
- 	if (result != ISC_R_SUCCESS)
- 		goto cleanup;
- 
-diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h
-index d4d1b05..556fcc2 100644
---- a/lib/dns/include/dns/adb.h
-+++ b/lib/dns/include/dns/adb.h
[email protected]@ -334,6 +334,13 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
- 		   dns_rdatatype_t qtype, unsigned int options,
- 		   isc_stdtime_t now, dns_name_t *target,
- 		   in_port_t port, dns_adbfind_t **find);
-+isc_result_t
-+dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
-+		    void *arg, dns_name_t *name, dns_name_t *qname,
-+		    dns_rdatatype_t qtype, unsigned int options,
-+		    isc_stdtime_t now, dns_name_t *target, in_port_t port,
-+		    unsigned int depth, isc_counter_t *qc,
-+		    dns_adbfind_t **find);
- /*%<
-  * Main interface for clients. The adb will look up the name given in
-  * "name" and will build up a list of found addresses, and perhaps start
-diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h
-index d293daa..10c3a3a 100644
---- a/lib/dns/include/dns/resolver.h
-+++ b/lib/dns/include/dns/resolver.h
[email protected]@ -270,6 +270,18 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
- 			  dns_rdataset_t *rdataset,
- 			  dns_rdataset_t *sigrdataset,
- 			  dns_fetch_t **fetchp);
-+isc_result_t
-+dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
-+			  dns_rdatatype_t type,
-+			  dns_name_t *domain, dns_rdataset_t *nameservers,
-+			  dns_forwarders_t *forwarders,
-+			  isc_sockaddr_t *client, isc_uint16_t id,
-+			  unsigned int options, unsigned int depth,
-+			  isc_counter_t *qc, isc_task_t *task,
-+			  isc_taskaction_t action, void *arg,
-+			  dns_rdataset_t *rdataset,
-+			  dns_rdataset_t *sigrdataset,
-+			  dns_fetch_t **fetchp);
- /*%<
-  * Recurse to answer a question.
-  *
[email protected]@ -550,6 +562,30 @@ dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp);
-  * \li	resolver to be valid.
-  */
- 
-+void
-+dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth);
-+unsigned int
-+dns_resolver_getmaxdepth(dns_resolver_t *resolver);
-+/*%
-+ * Get and set how many NS indirections will be followed when looking for
-+ * nameserver addresses.
-+ *
-+ * Requires:
-+ * \li	resolver to be valid.
-+ */
-+
-+void
-+dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries);
-+unsigned int
-+dns_resolver_getmaxqueries(dns_resolver_t *resolver);
-+/*%
-+ * Get and set how many iterative queries will be allowed before
-+ * terminating a recursive query.
-+ *
-+ * Requires:
-+ * \li	resolver to be valid.
-+ */
-+
- ISC_LANG_ENDDECLS
- 
- #endif /* DNS_RESOLVER_H */
-diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
-index 7dcea6d..bd3d9fd 100644
---- a/lib/dns/resolver.c
-+++ b/lib/dns/resolver.c
[email protected]@ -21,6 +21,7 @@
- 
- #include <config.h>
- 
-+#include <isc/counter.h>
- #include <isc/log.h>
- #include <isc/platform.h>
- #include <isc/print.h>
[email protected]@ -109,6 +110,16 @@
- #define QTRACE(m)
- #endif
- 
-+/* The default maximum number of recursions to follow before giving up. */
-+#ifndef DEFAULT_RECURSION_DEPTH
-+#define DEFAULT_RECURSION_DEPTH 7
-+#endif
-+
-+/* The default maximum number of iterative queries to allow before giving up. */
-+#ifndef DEFAULT_MAX_QUERIES
-+#define DEFAULT_MAX_QUERIES 50
-+#endif
-+
- /*%
-  * Maximum EDNS0 input packet size.
-  */
[email protected]@ -211,12 +222,13 @@ struct fetchctx {
- 	isc_sockaddrlist_t		edns;
- 	isc_sockaddrlist_t		edns512;
- 	isc_sockaddrlist_t		bad_edns;
--	dns_validator_t			*validator;
-+	dns_validator_t *		validator;
- 	ISC_LIST(dns_validator_t)       validators;
- 	dns_db_t *			cache;
- 	dns_adb_t *			adb;
- 	isc_boolean_t			ns_ttl_ok;
- 	isc_uint32_t			ns_ttl;
-+	isc_counter_t *			qc;
- 
- 	/*%
- 	 * The number of events we're waiting for.
[email protected]@ -283,6 +295,7 @@ struct fetchctx {
- 	unsigned int			valfail;
- 	isc_boolean_t			timeout;
- 	dns_adbaddrinfo_t 		*addrinfo;
-+	unsigned int			depth;
- };
- 
- #define FCTX_MAGIC			ISC_MAGIC('F', '!', '!', '!')
[email protected]@ -394,6 +407,8 @@ struct dns_resolver {
- 	unsigned int			spillatmin;
- 	isc_timer_t *			spillattimer;
- 	isc_boolean_t			zero_no_soa_ttl;
-+	unsigned int			maxdepth;
-+	unsigned int			maxqueries;
- 
- 	/* Locked by lock. */
- 	unsigned int			references;
[email protected]@ -1495,6 +1510,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
- 		if (result != ISC_R_SUCCESS)
- 			goto cleanup_dispatch;
- 	}
-+
- 	fctx->querysent++;
- 
- 	ISC_LIST_APPEND(fctx->queries, query, link);
[email protected]@ -2146,9 +2162,9 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
- 		 */
- 		INSIST(!SHUTTINGDOWN(fctx));
- 		fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
--		if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES)
-+		if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) {
- 			want_try = ISC_TRUE;
--		else {
-+		} else {
- 			fctx->findfail++;
- 			if (fctx->pending == 0) {
- 				/*
[email protected]@ -2177,7 +2193,7 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
- 	else if (want_done)
- 		fctx_done(fctx, ISC_R_FAILURE, __LINE__);
- 	else if (destroy) {
--			fctx_destroy(fctx);
-+		fctx_destroy(fctx);
- 		if (bucket_empty)
- 			empty_bucket(res);
- 	}
[email protected]@ -2499,12 +2515,13 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
- 	 * See what we know about this address.
- 	 */
- 	find = NULL;
--	result = dns_adb_createfind(fctx->adb,
--				    res->buckets[fctx->bucketnum].task,
--				    fctx_finddone, fctx, name,
--				    &fctx->name, fctx->type,
--				    options, now, NULL,
--				    res->view->dstport, &find);
-+	result = dns_adb_createfind2(fctx->adb,
-+				     res->buckets[fctx->bucketnum].task,
-+				     fctx_finddone, fctx, name,
-+				     &fctx->name, fctx->type,
-+				     options, now, NULL,
-+				     res->view->dstport,
-+				     fctx->depth + 1, fctx->qc, &find);
- 	if (result != ISC_R_SUCCESS) {
- 		if (result == DNS_R_ALIAS) {
- 			/*
[email protected]@ -2612,6 +2629,14 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
- 
- 	res = fctx->res;
- 
-+	if (fctx->depth > res->maxdepth) {
-+		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
-+			      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
-+			      "too much NS indirection resolving '%s'",
-+			      fctx->info);
-+		return (DNS_R_SERVFAIL);
-+	}
-+
- 	/*
- 	 * Forwarders.
- 	 */
[email protected]@ -3087,6 +3112,16 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
- 		}
- 	}
- 
-+	result = isc_counter_increment(fctx->qc);
-+	if (result != ISC_R_SUCCESS) {
-+		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
-+			      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
-+			      "exceeded max queries resolving '%s'",
-+			      fctx->info);
-+		fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
-+		return;
-+	}
-+
- 	result = fctx_query(fctx, addrinfo, fctx->options);
- 	if (result != ISC_R_SUCCESS)
- 		fctx_done(fctx, result, __LINE__);
[email protected]@ -3185,6 +3220,7 @@ fctx_destroy(fetchctx_t *fctx) {
- 		isc_mem_put(fctx->mctx, sa, sizeof(*sa));
- 	}
- 
-+	isc_counter_detach(&fctx->qc);
- 	isc_timer_detach(&fctx->timer);
- 	dns_message_destroy(&fctx->rmessage);
- 	dns_message_destroy(&fctx->qmessage);
[email protected]@ -3512,7 +3548,8 @@ log_ns_ttl(fetchctx_t *fctx, const char *where) {
- static isc_result_t
- fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
- 	    dns_name_t *domain, dns_rdataset_t *nameservers,
--	    unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp)
-+	    unsigned int options, unsigned int bucketnum, unsigned int depth,
-+	    isc_counter_t *qc, fetchctx_t **fctxp)
- {
- 	fetchctx_t *fctx;
- 	isc_result_t result;
[email protected]@ -3534,6 +3571,21 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
- 	fctx = isc_mem_get(mctx, sizeof(*fctx));
- 	if (fctx == NULL)
- 		return (ISC_R_NOMEMORY);
-+
-+	fctx->qc = NULL;
-+	if (qc != NULL) {
-+		isc_counter_attach(qc, &fctx->qc);
-+	} else {
-+		result = isc_counter_create(res->mctx,
-+					    res->maxqueries, &fctx->qc);
-+		if (result != ISC_R_SUCCESS)
-+			goto cleanup_fetch;
-+	}
-+
-+	/*
-+	 * Make fctx->info point to a copy of a formatted string
-+	 * "name/type".
-+	 */
- 	dns_name_format(name, buf, sizeof(buf));
- 	dns_rdatatype_format(type, typebuf, sizeof(typebuf));
- 	strcat(buf, "/");       /* checked */
[email protected]@ -3541,7 +3593,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
- 	fctx->info = isc_mem_strdup(mctx, buf);
- 	if (fctx->info == NULL) {
- 		result = ISC_R_NOMEMORY;
--		goto cleanup_fetch;
-+		goto cleanup_counter;
- 	}
- 	FCTXTRACE("create");
- 	dns_name_init(&fctx->name, NULL);
[email protected]@ -3564,6 +3616,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
- 	fctx->state = fetchstate_init;
- 	fctx->want_shutdown = ISC_FALSE;
- 	fctx->cloned = ISC_FALSE;
-+	fctx->depth = depth;
- 	ISC_LIST_INIT(fctx->queries);
- 	ISC_LIST_INIT(fctx->finds);
- 	ISC_LIST_INIT(fctx->altfinds);
[email protected]@ -3768,6 +3821,9 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
-  cleanup_info:
- 	isc_mem_free(mctx, fctx->info);
- 
-+ cleanup_counter:
-+	isc_counter_detach(&fctx->qc);
-+
-  cleanup_fetch:
- 	isc_mem_put(mctx, fctx, sizeof(*fctx));
- 
[email protected]@ -7339,6 +7395,8 @@ dns_resolver_create(dns_view_t *view,
- 	res->zero_no_soa_ttl = ISC_FALSE;
- 	res->ndisps = 0;
- 	res->nextdisp = 0; /* meaningless at this point, but init it */
-+	res->maxdepth = DEFAULT_RECURSION_DEPTH;
-+	res->maxqueries = DEFAULT_MAX_QUERIES;
- 	res->nbuckets = ntasks;
- 	res->activebuckets = ntasks;
- 	res->buckets = isc_mem_get(view->mctx,
[email protected]@ -7778,9 +7836,9 @@ dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
- 			 dns_rdataset_t *sigrdataset,
- 			 dns_fetch_t **fetchp)
- {
--	return (dns_resolver_createfetch2(res, name, type, domain,
-+	return (dns_resolver_createfetch3(res, name, type, domain,
- 					  nameservers, forwarders, NULL, 0,
--					  options, task, action, arg,
-+					  options, 0, NULL, task, action, arg,
- 					  rdataset, sigrdataset, fetchp));
- }
- 
[email protected]@ -7796,6 +7854,25 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
- 			  dns_rdataset_t *sigrdataset,
- 			  dns_fetch_t **fetchp)
- {
-+	return (dns_resolver_createfetch3(res, name, type, domain,
-+					  nameservers, forwarders, client, id,
-+					  options, 0, NULL, task, action, arg,
-+					  rdataset, sigrdataset, fetchp));
-+}
-+
-+isc_result_t
-+dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
-+			  dns_rdatatype_t type,
-+			  dns_name_t *domain, dns_rdataset_t *nameservers,
-+			  dns_forwarders_t *forwarders,
-+			  isc_sockaddr_t *client, dns_messageid_t id,
-+			  unsigned int options, unsigned int depth,
-+			  isc_counter_t *qc, isc_task_t *task,
-+			  isc_taskaction_t action, void *arg,
-+			  dns_rdataset_t *rdataset,
-+			  dns_rdataset_t *sigrdataset,
-+			  dns_fetch_t **fetchp)
-+{
- 	dns_fetch_t *fetch;
- 	fetchctx_t *fctx = NULL;
- 	isc_result_t result = ISC_R_SUCCESS;
[email protected]@ -7882,11 +7959,12 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
- 
- 	if (fctx == NULL) {
- 		result = fctx_create(res, name, type, domain, nameservers,
--				     options, bucketnum, &fctx);
-+				     options, bucketnum, depth, qc, &fctx);
- 		if (result != ISC_R_SUCCESS)
- 			goto unlock;
- 		new_fctx = ISC_TRUE;
--	}
-+	} else if (fctx->depth > depth)
-+		fctx->depth = depth;
- 
- 	result = fctx_join(fctx, task, client, id, action, arg,
- 			   rdataset, sigrdataset, fetch);
[email protected]@ -8637,3 +8715,27 @@ dns_resolver_getoptions(dns_resolver_t *resolver) {
- 
- 	return (resolver->options);
- }
-+
-+void
-+dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) {
-+	REQUIRE(VALID_RESOLVER(resolver));
-+	resolver->maxdepth = maxdepth;
-+}
-+
-+unsigned int
-+dns_resolver_getmaxdepth(dns_resolver_t *resolver) {
-+	REQUIRE(VALID_RESOLVER(resolver));
-+	return (resolver->maxdepth);
-+}
-+
-+void
-+dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) {
-+	REQUIRE(VALID_RESOLVER(resolver));
-+	resolver->maxqueries = queries;
-+}
-+
-+unsigned int
-+dns_resolver_getmaxqueries(dns_resolver_t *resolver) {
-+	REQUIRE(VALID_RESOLVER(resolver));
-+	return (resolver->maxqueries);
-+}
-diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in
-index 0b4020b..afc19ee 100644
---- a/lib/isc/Makefile.in
-+++ b/lib/isc/Makefile.in
[email protected]@ -13,8 +13,6 @@
- # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- # PERFORMANCE OF THIS SOFTWARE.
- 
--# $Id$
--
- srcdir =	@[email protected]
- VPATH =		@[email protected]
- top_srcdir =	@[email protected]
[email protected]@ -53,7 +51,7 @@ WIN32OBJS = 	win32/[email protected]@ win32/[email protected]@ win32/[email protected]@ \
- # Alphabetically
- OBJS =		@[email protected] \
- 		[email protected]@ [email protected]@ [email protected]@ [email protected]@ [email protected]@ \
--		[email protected]@ [email protected]@ [email protected]@ [email protected]@ \
-+		[email protected]@ [email protected]@ [email protected]@ [email protected]@ [email protected]@ \
- 		[email protected]@ [email protected]@ [email protected]@ [email protected]@ [email protected]@ \
- 		[email protected]@ [email protected]@ [email protected]@ \
- 		[email protected]@ [email protected]@ [email protected]@ [email protected]@ \
[email protected]@ -68,7 +66,7 @@ OBJS =		@[email protected] \
- # Alphabetically
- SRCS =		@[email protected] \
- 		assertions.c base32.c base64.c bitstring.c buffer.c \
--		bufferlist.c commandline.c error.c event.c \
-+		bufferlist.c commandline.c counter.c error.c event.c \
- 		heap.c hex.c hmacmd5.c hmacsha.c \
- 		httpd.c inet_aton.c iterated_hash.c \
- 		lex.c lfsr.c lib.c log.c \
-diff --git a/lib/isc/include/isc/Makefile.in b/lib/isc/include/isc/Makefile.in
-index 9adca3e..1cfbbd1 100644
---- a/lib/isc/include/isc/Makefile.in
-+++ b/lib/isc/include/isc/Makefile.in
[email protected]@ -13,8 +13,6 @@
- # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- # PERFORMANCE OF THIS SOFTWARE.
- 
--# $Id$
--
- srcdir =	@[email protected]
- VPATH =		@[email protected]
- top_srcdir =	@[email protected]
[email protected]@ -27,7 +25,7 @@ top_srcdir =	@[email protected]
- # install target below.
- #
- HEADERS =	app.h assertions.h base64.h bitstring.h boolean.h buffer.h \
--		bufferlist.h commandline.h entropy.h error.h event.h \
-+		bufferlist.h commandline.h counter.h entropy.h error.h event.h \
- 		eventclass.h file.h formatcheck.h fsaccess.h \
- 		hash.h heap.h hex.h hmacmd5.h hmacsha.h \
- 		httpd.h \
-diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h
-index 8e8b08f..a646b8b 100644
---- a/lib/isc/include/isc/types.h
-+++ b/lib/isc/include/isc/types.h
[email protected]@ -45,6 +45,7 @@ typedef struct isc_buffer		isc_buffer_t;		/*%< Buffer */
- typedef ISC_LIST(isc_buffer_t)		isc_bufferlist_t;	/*%< Buffer List */
- typedef struct isc_constregion		isc_constregion_t;	/*%< Const region */
- typedef struct isc_consttextregion	isc_consttextregion_t;	/*%< Const Text Region */
-+typedef struct isc_counter		isc_counter_t;		/*%< Counter */
- typedef struct isc_entropy		isc_entropy_t;		/*%< Entropy */
- typedef struct isc_entropysource	isc_entropysource_t;	/*%< Entropy Source */
- typedef struct isc_event		isc_event_t;		/*%< Event */
-diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
-index fac2633..3023dcc 100644
---- a/lib/isccfg/namedconf.c
-+++ b/lib/isccfg/namedconf.c
[email protected]@ -15,8 +15,6 @@
-  * PERFORMANCE OF THIS SOFTWARE.
-  */
- 
--/* $Id$ */
--
- /*! \file */
- 
- #include <config.h>
[email protected]@ -830,6 +828,8 @@ view_clauses[] = {
- 	{ "max-cache-ttl", &cfg_type_uint32, 0 },
- 	{ "max-clients-per-query", &cfg_type_uint32, 0 },
- 	{ "max-ncache-ttl", &cfg_type_uint32, 0 },
-+	{ "max-recursion-depth", &cfg_type_uint32, 0 },
-+	{ "max-recursion-queries", &cfg_type_uint32, 0 },
- 	{ "max-udp-size", &cfg_type_uint32, 0 },
- 	{ "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
- 	{ "minimal-responses", &cfg_type_boolean, 0 },
-diff --git a/version b/version
-index 1be3c16..2058444 100644
---- a/version
-+++ b/version
[email protected]@ -10,4 +10,4 @@ MINORVER=6
- PATCHVER=
- RELEASETYPE=-ESV
- RELEASEVER=-R11
--EXTENSIONS=
-+EXTENSIONS=-P1
-diff --git a/lib/isc/counter.c b/lib/isc/counter.c
-new file mode 100644
-index 0000000..d7d187b
---- /dev/null
-+++ b/lib/isc/counter.c
[email protected]@ -0,0 +1,138 @@
-+/*
-+ * Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
-+ *
-+ * Permission to use, copy, modify, and/or distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-+ * PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+/*! \file */
-+
-+#include <config.h>
-+
-+#include <stddef.h>
-+
-+#include <isc/counter.h>
-+#include <isc/magic.h>
-+#include <isc/mem.h>
-+#include <isc/util.h>
-+
-+#define COUNTER_MAGIC			ISC_MAGIC('C', 'n', 't', 'r')
-+#define VALID_COUNTER(r)		ISC_MAGIC_VALID(r, COUNTER_MAGIC)
-+
-+struct isc_counter {
-+	unsigned int	magic;
-+	isc_mem_t	*mctx;
-+	isc_mutex_t	lock;
-+	unsigned int	references;
-+	unsigned int	limit;
-+	unsigned int	used;
-+};
-+
-+isc_result_t
-+isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) {
-+	isc_result_t result;
-+	isc_counter_t *counter;
-+
-+	REQUIRE(counterp != NULL && *counterp == NULL);
-+
-+	counter = isc_mem_get(mctx, sizeof(*counter));
-+	if (counter == NULL)
-+		return (ISC_R_NOMEMORY);
-+
-+	result = isc_mutex_init(&counter->lock);
-+	if (result != ISC_R_SUCCESS) {
-+		isc_mem_put(mctx, counter, sizeof(*counter));
-+		return (result);
-+	}
-+
-+	counter->mctx = NULL;
-+	isc_mem_attach(mctx, &counter->mctx);
-+
-+	counter->references = 1;
-+	counter->limit = limit;
-+	counter->used = 0;
-+
-+	counter->magic = COUNTER_MAGIC;
-+	*counterp = counter;
-+	return (ISC_R_SUCCESS);
-+}
-+
-+isc_result_t
-+isc_counter_increment(isc_counter_t *counter) {
-+	isc_result_t result = ISC_R_SUCCESS;
-+
-+	LOCK(&counter->lock);
-+	counter->used++;
-+	if (counter->limit != 0 && counter->used >= counter->limit)
-+		result = ISC_R_QUOTA;
-+	UNLOCK(&counter->lock);
-+
-+	return (result);
-+}
-+
-+unsigned int
-+isc_counter_used(isc_counter_t *counter) {
-+	REQUIRE(VALID_COUNTER(counter));
-+
-+	return (counter->used);
-+}
-+
-+void
-+isc_counter_setlimit(isc_counter_t *counter, int limit) {
-+	REQUIRE(VALID_COUNTER(counter));
-+
-+	LOCK(&counter->lock);
-+	counter->limit = limit;
-+	UNLOCK(&counter->lock);
-+}
-+
-+void
-+isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp) {
-+	REQUIRE(VALID_COUNTER(source));
-+	REQUIRE(targetp != NULL && *targetp == NULL);
-+
-+	LOCK(&source->lock);
-+	source->references++;
-+	INSIST(source->references > 0);
-+	UNLOCK(&source->lock);
-+
-+	*targetp = source;
-+}
-+
-+static void
-+destroy(isc_counter_t *counter) {
-+	counter->magic = 0;
-+	isc_mutex_destroy(&counter->lock);
-+	isc_mem_putanddetach(&counter->mctx, counter, sizeof(*counter));
-+}
-+
-+void
-+isc_counter_detach(isc_counter_t **counterp) {
-+	isc_counter_t *counter;
-+	isc_boolean_t want_destroy = ISC_FALSE;
-+
-+	REQUIRE(counterp != NULL && *counterp != NULL);
-+	counter = *counterp;
-+	REQUIRE(VALID_COUNTER(counter));
-+
-+	*counterp = NULL;
-+
-+	LOCK(&counter->lock);
-+	INSIST(counter->references > 0);
-+	counter->references--;
-+	if (counter->references == 0)
-+		want_destroy = ISC_TRUE;
-+	UNLOCK(&counter->lock);
-+
-+	if (want_destroy)
-+		destroy(counter);
-+}
-diff --git a/lib/isc/include/isc/counter.h b/lib/isc/include/isc/counter.h
-new file mode 100644
-index 0000000..e7ebd25
---- /dev/null
-+++ b/lib/isc/include/isc/counter.h
[email protected]@ -0,0 +1,90 @@
-+/*
-+ * Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
-+ *
-+ * Permission to use, copy, modify, and/or distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-+ * PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+#ifndef ISC_COUNTER_H
-+#define ISC_COUNTER_H 1
-+
-+/*****
-+ ***** Module Info
-+ *****/
-+
-+/*! \file isc/counter.h
-+ *
-+ * \brief The isc_counter_t object is a simplified version of the
-+ * isc_quota_t object; it tracks the consumption of limited
-+ * resources, returning an error condition when the quota is
-+ * exceeded.  However, unlike isc_quota_t, attaching and detaching
-+ * from a counter object does not increment or decrement the counter.
-+ */
-+
-+/***
-+ *** Imports.
-+ ***/
-+
-+#include <isc/lang.h>
-+#include <isc/mutex.h>
-+#include <isc/types.h>
-+
-+/*****
-+ ***** Types.
-+ *****/
-+
-+ISC_LANG_BEGINDECLS
-+
-+isc_result_t
-+isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp);
-+/*%<
-+ * Allocate and initialize a counter object.
-+ */
-+
-+isc_result_t
-+isc_counter_increment(isc_counter_t *counter);
-+/*%<
-+ * Increment the counter.
-+ *
-+ * If the counter limit is nonzero and has been reached, then
-+ * return ISC_R_QUOTA, otherwise ISC_R_SUCCESS. (The counter is
-+ * incremented regardless of return value.)
-+ */
-+
-+unsigned int
-+isc_counter_used(isc_counter_t *counter);
-+/*%<
-+ * Return the current counter value.
-+ */
-+
-+void
-+isc_counter_setlimit(isc_counter_t *counter, int limit);
-+/*%<
-+ * Set the counter limit.
-+ */
-+
-+void
-+isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp);
-+/*%<
-+ * Attach to a counter object, increasing its reference counter.
-+ */
-+
-+void
-+isc_counter_detach(isc_counter_t **counterp);
-+/*%<
-+ * Detach (and destroy if reference counter has dropped to zero)
-+ * a counter object.
-+ */
-+
-+ISC_LANG_ENDDECLS
-+
-+#endif /* ISC_COUNTER_H */
-diff --git a/lib/isc/tests/counter_test.c b/lib/isc/tests/counter_test.c
-new file mode 100644
-index 0000000..a7a1997
---- /dev/null
-+++ b/lib/isc/tests/counter_test.c
[email protected]@ -0,0 +1,69 @@
-+/*
-+ * Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
-+ *
-+ * Permission to use, copy, modify, and/or distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-+ * PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+#include <config.h>
-+#include <stdlib.h>
-+
-+#include <atf-c.h>
-+
-+#include <isc/counter.h>
-+#include <isc/result.h>
-+
-+#include "isctest.h"
-+
-+ATF_TC(isc_counter);
-+ATF_TC_HEAD(isc_counter, tc) {
-+	atf_tc_set_md_var(tc, "descr", "isc counter object");
-+}
-+ATF_TC_BODY(isc_counter, tc) {
-+	isc_result_t result;
-+	isc_counter_t *counter = NULL;
-+	int i;
-+
-+	result = isc_test_begin(NULL, ISC_TRUE);
-+	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
-+
-+	result = isc_counter_create(mctx, 0, &counter);
-+	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
-+
-+	for (i = 0; i < 10; i++) {
-+		result = isc_counter_increment(counter);
-+		ATF_CHECK_EQ(result, ISC_R_SUCCESS);
-+	}
-+
-+	ATF_CHECK_EQ(isc_counter_used(counter), 10);
-+
-+	isc_counter_setlimit(counter, 15);
-+	for (i = 0; i < 10; i++) {
-+		result = isc_counter_increment(counter);
-+		if (result != ISC_R_SUCCESS)
-+			break;
-+	}
-+
-+	ATF_CHECK_EQ(isc_counter_used(counter), 15);
-+
-+	isc_counter_detach(&counter);
-+	isc_test_end();
-+}
-+
-+/*
-+ * Main
-+ */
-+ATF_TP_ADD_TCS(tp) {
-+	ATF_TP_ADD_TC(tp, isc_counter);
-+	return (atf_no_error());
-+}
-+