--- bin/named/statschannel.c.isc	2010-02-04 18:48:30.000000000 -0500
+++ bin/named/statschannel.c	2010-09-12 08:33:18.000000000 -0400
@@ -72,10 +72,18 @@
 	int		*counterindices; /* used for general statistics */
 	isc_uint64_t	*countervalues;	 /* used for general statistics */
 	isc_result_t	result;
 } stats_dumparg_t;
 
+typedef struct
+stats_zonearg {
+	int		include;	/* What to include */
+#define X_STATS		1		/* Include statistics/dynamic data */
+					/* Otherwise, just configuration elements */
+	void		*arg;		/* General argument */
+} stats_zonearg_t;
+
 static isc_once_t once = ISC_ONCE_INIT;
 
 /*%
  * Statistics descriptions.  These could be statistically initialized at
  * compile time, but we configure them run time in the init_desc() function
@@ -693,11 +701,13 @@
 static isc_result_t
 zone_xmlrender(dns_zone_t *zone, void *arg) {
 	char buf[1024 + 32];	/* sufficiently large for zone name and class */
 	dns_rdataclass_t rdclass;
 	isc_uint32_t serial;
-	xmlTextWriterPtr writer = arg;
+	isc_result_t serialvalid;
+	stats_zonearg_t *zonearg = arg;
+	xmlTextWriterPtr writer = zonearg->arg;
 	isc_stats_t *zonestats;
 	isc_uint64_t nsstat_values[dns_nsstatscounter_max];
 	int xmlrc;
 	isc_result_t result;
 
@@ -712,38 +722,48 @@
 	dns_rdataclass_format(rdclass, buf, sizeof(buf));
 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "rdataclass"));
 	TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf));
 	TRY0(xmlTextWriterEndElement(writer));
 
-	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "serial"));
-	if (dns_zone_getserial2(zone, &serial) == ISC_R_SUCCESS)
-		TRY0(xmlTextWriterWriteFormatString(writer, "%u", serial));
+	/* Flag built-in vs. user zones.  There should be a better test... */
+	serialvalid = dns_zone_getserial2(zone, &serial) == ISC_R_SUCCESS;
+	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "type"));
+	if (serialvalid)
+		TRY0(xmlTextWriterWriteString(writer, (serial? ISC_XMLCHAR "user" : ISC_XMLCHAR "builtin")));
 	else
 		TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
 	TRY0(xmlTextWriterEndElement(writer));
 
-	zonestats = dns_zone_getrequeststats(zone);
-	if (zonestats != NULL) {
-		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
-		result = dump_counters(zonestats, statsformat_xml, writer, NULL,
-				      nsstats_xmldesc, dns_nsstatscounter_max,
-				      nsstats_index, nsstat_values,
-				      ISC_STATSDUMP_VERBOSE);
-		if (result != ISC_R_SUCCESS)
-			goto error;
-		TRY0(xmlTextWriterEndElement(writer)); /* counters */
-	}
+	if (zonearg->include & X_STATS) {
+		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "serial"));
+		if (serialvalid)
+			TRY0(xmlTextWriterWriteFormatString(writer, "%u", serial));
+		else
+			TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
+		TRY0(xmlTextWriterEndElement(writer));
 
+		zonestats = dns_zone_getrequeststats(zone);
+		if (zonestats != NULL) {
+			TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+			result = dump_counters(zonestats, statsformat_xml, writer, NULL,
+					      nsstats_xmldesc, dns_nsstatscounter_max,
+					      nsstats_index, nsstat_values,
+					      ISC_STATSDUMP_VERBOSE);
+			if (result != ISC_R_SUCCESS)
+				goto error;
+			TRY0(xmlTextWriterEndElement(writer)); /* counters */
+		}
+	}
 	TRY0(xmlTextWriterEndElement(writer)); /* zone */
 
 	return (ISC_R_SUCCESS);
  error:
 	return (ISC_R_FAILURE);
 }
 
 static isc_result_t
-generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
+generatexml(ns_server_t *server, int include, int *buflen, xmlChar **buf) {
 	char boottime[sizeof "yyyy-mm-ddThh:mm:ssZ"];
 	char nowstr[sizeof "yyyy-mm-ddThh:mm:ssZ"];
 	isc_time_t now;
 	xmlTextWriterPtr writer = NULL;
 	xmlDocPtr doc = NULL;
@@ -754,10 +774,11 @@
 	isc_uint64_t nsstat_values[dns_nsstatscounter_max];
 	isc_uint64_t resstat_values[dns_resstatscounter_max];
 	isc_uint64_t zonestat_values[dns_zonestatscounter_max];
 	isc_uint64_t sockstat_values[isc_sockstatscounter_max];
 	isc_result_t result;
+	stats_zonearg_t zonearg;
 
 	isc_time_now(&now);
 	isc_time_formatISO8601(&ns_g_boottime, boottime, sizeof boottime);
 	isc_time_formatISO8601(&now, nowstr, sizeof nowstr);
 
@@ -778,10 +799,13 @@
 
 	/* Set common fields for statistics dump */
 	dumparg.type = statsformat_xml;
 	dumparg.arg = writer;
 
+	zonearg.include = include;
+	zonearg.arg = writer;
+
 	/*
 	 * Start by rendering the views we know of here.  For each view we
 	 * know of, call its rendering function.
 	 */
 	view = ISC_LIST_HEAD(server->viewlist);
@@ -793,127 +817,129 @@
 		TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR view->name));
 		TRY0(xmlTextWriterEndElement(writer));
 
 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "zones"));
 		result = dns_zt_apply(view->zonetable, ISC_TRUE, zone_xmlrender,
-				      writer);
+				      &zonearg);
 		if (result != ISC_R_SUCCESS)
 			goto error;
 		TRY0(xmlTextWriterEndElement(writer));
 
-		if (view->resquerystats != NULL) {
-			dumparg.result = ISC_R_SUCCESS;
-			dns_rdatatypestats_dump(view->resquerystats,
-						rdtypestat_dump, &dumparg, 0);
-			if (dumparg.result != ISC_R_SUCCESS)
-				goto error;
-		}
+		if (include & X_STATS) {
+			if (view->resquerystats != NULL) {
+				dumparg.result = ISC_R_SUCCESS;
+				dns_rdatatypestats_dump(view->resquerystats,
+							rdtypestat_dump, &dumparg, 0);
+				if (dumparg.result != ISC_R_SUCCESS)
+					goto error;
+			}
 
-		if (view->resstats != NULL) {
-			result = dump_counters(view->resstats, statsformat_xml,
-					       writer, "resstat",
-					       resstats_xmldesc,
-					       dns_resstatscounter_max,
-					       resstats_index, resstat_values,
-					       ISC_STATSDUMP_VERBOSE);
-			if (result != ISC_R_SUCCESS)
-				goto error;
-		}
+			if (view->resstats != NULL) {
+				result = dump_counters(view->resstats, statsformat_xml,
+						       writer, "resstat",
+						       resstats_xmldesc,
+						       dns_resstatscounter_max,
+						       resstats_index, resstat_values,
+						       ISC_STATSDUMP_VERBOSE);
+				if (result != ISC_R_SUCCESS)
+					goto error;
+			}
 
-		cachestats = dns_db_getrrsetstats(view->cachedb);
-		if (cachestats != NULL) {
-			TRY0(xmlTextWriterStartElement(writer,
-						       ISC_XMLCHAR "cache"));
-			TRY0(xmlTextWriterWriteAttribute(writer,
-					 ISC_XMLCHAR "name",
-					 ISC_XMLCHAR
-					 dns_cache_getname(view->cache)));
-			dumparg.result = ISC_R_SUCCESS;
-			dns_rdatasetstats_dump(cachestats, rdatasetstats_dump,
-					       &dumparg, 0);
-			if (dumparg.result != ISC_R_SUCCESS)
-				goto error;
-			TRY0(xmlTextWriterEndElement(writer)); /* cache */
+			cachestats = dns_db_getrrsetstats(view->cachedb);
+			if (cachestats != NULL) {
+				TRY0(xmlTextWriterStartElement(writer,
+							       ISC_XMLCHAR "cache"));
+				TRY0(xmlTextWriterWriteAttribute(writer,
+						 ISC_XMLCHAR "name",
+						 ISC_XMLCHAR
+						 dns_cache_getname(view->cache)));
+				dumparg.result = ISC_R_SUCCESS;
+				dns_rdatasetstats_dump(cachestats, rdatasetstats_dump,
+						       &dumparg, 0);
+				if (dumparg.result != ISC_R_SUCCESS)
+					goto error;
+				TRY0(xmlTextWriterEndElement(writer)); /* cache */
+			}
 		}
-
 		TRY0(xmlTextWriterEndElement(writer)); /* view */
 
 		view = ISC_LIST_NEXT(view, link);
 	}
 	TRY0(xmlTextWriterEndElement(writer)); /* views */
 
-	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "socketmgr"));
-	isc_socketmgr_renderxml(ns_g_socketmgr, writer);
-	TRY0(xmlTextWriterEndElement(writer)); /* socketmgr */
-
-	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "taskmgr"));
-	isc_taskmgr_renderxml(ns_g_taskmgr, writer);
-	TRY0(xmlTextWriterEndElement(writer)); /* taskmgr */
-
-	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "server"));
-	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "boot-time"));
-	TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR boottime));
-	TRY0(xmlTextWriterEndElement(writer));
-	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "current-time"));
-	TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR nowstr));
-	TRY0(xmlTextWriterEndElement(writer));
-
-	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "requests"));
-	dumparg.result = ISC_R_SUCCESS;
-	dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg,
-			     0);
-	if (dumparg.result != ISC_R_SUCCESS)
-		goto error;
-	TRY0(xmlTextWriterEndElement(writer)); /* requests */
+	if (include & X_STATS) {
+		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "socketmgr"));
+		isc_socketmgr_renderxml(ns_g_socketmgr, writer);
+		TRY0(xmlTextWriterEndElement(writer)); /* socketmgr */
+
+		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "taskmgr"));
+		isc_taskmgr_renderxml(ns_g_taskmgr, writer);
+		TRY0(xmlTextWriterEndElement(writer)); /* taskmgr */
+
+		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "server"));
+		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "boot-time"));
+		TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR boottime));
+		TRY0(xmlTextWriterEndElement(writer));
+		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "current-time"));
+		TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR nowstr));
+		TRY0(xmlTextWriterEndElement(writer));
 
-	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "queries-in"));
-	dumparg.result = ISC_R_SUCCESS;
-	dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump,
-				&dumparg, 0);
-	if (dumparg.result != ISC_R_SUCCESS)
-		goto error;
-	TRY0(xmlTextWriterEndElement(writer)); /* queries-in */
+		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "requests"));
+		dumparg.result = ISC_R_SUCCESS;
+		dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg,
+				     0);
+		if (dumparg.result != ISC_R_SUCCESS)
+			goto error;
+		TRY0(xmlTextWriterEndElement(writer)); /* requests */
 
-	result = dump_counters(server->nsstats, statsformat_xml, writer,
-			       "nsstat", nsstats_xmldesc,
-				dns_nsstatscounter_max,
-				nsstats_index, nsstat_values,
-				ISC_STATSDUMP_VERBOSE);
-	if (result != ISC_R_SUCCESS)
-		goto error;
+		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "queries-in"));
+		dumparg.result = ISC_R_SUCCESS;
+		dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump,
+					&dumparg, 0);
+		if (dumparg.result != ISC_R_SUCCESS)
+			goto error;
+		TRY0(xmlTextWriterEndElement(writer)); /* queries-in */
 
-	result = dump_counters(server->zonestats, statsformat_xml, writer,
-			       "zonestat", zonestats_xmldesc,
-			       dns_zonestatscounter_max, zonestats_index,
-			       zonestat_values, ISC_STATSDUMP_VERBOSE);
-	if (result != ISC_R_SUCCESS)
-		goto error;
+		result = dump_counters(server->nsstats, statsformat_xml, writer,
+				       "nsstat", nsstats_xmldesc,
+					dns_nsstatscounter_max,
+					nsstats_index, nsstat_values,
+					ISC_STATSDUMP_VERBOSE);
+		if (result != ISC_R_SUCCESS)
+			goto error;
 
-	/*
-	 * Most of the common resolver statistics entries are 0, so we don't
-	 * use the verbose dump here.
-	 */
-	result = dump_counters(server->resolverstats, statsformat_xml, writer,
-			       "resstat", resstats_xmldesc,
-			       dns_resstatscounter_max, resstats_index,
-			       resstat_values, 0);
-	if (result != ISC_R_SUCCESS)
-		goto error;
+		result = dump_counters(server->zonestats, statsformat_xml, writer,
+				       "zonestat", zonestats_xmldesc,
+				       dns_zonestatscounter_max, zonestats_index,
+				       zonestat_values, ISC_STATSDUMP_VERBOSE);
+		if (result != ISC_R_SUCCESS)
+			goto error;
 
-	result = dump_counters(server->sockstats, statsformat_xml, writer,
-			       "sockstat", sockstats_xmldesc,
-			       isc_sockstatscounter_max, sockstats_index,
-			       sockstat_values, ISC_STATSDUMP_VERBOSE);
-	if (result != ISC_R_SUCCESS)
-		goto error;
+		/*
+		 * Most of the common resolver statistics entries are 0, so we don't
+		 * use the verbose dump here.
+		 */
+		result = dump_counters(server->resolverstats, statsformat_xml, writer,
+				       "resstat", resstats_xmldesc,
+				       dns_resstatscounter_max, resstats_index,
+				       resstat_values, 0);
+		if (result != ISC_R_SUCCESS)
+			goto error;
 
-	TRY0(xmlTextWriterEndElement(writer)); /* server */
+		result = dump_counters(server->sockstats, statsformat_xml, writer,
+				       "sockstat", sockstats_xmldesc,
+				       isc_sockstatscounter_max, sockstats_index,
+				       sockstat_values, ISC_STATSDUMP_VERBOSE);
+		if (result != ISC_R_SUCCESS)
+			goto error;
 
-	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "memory"));
-	isc_mem_renderxml(writer);
-	TRY0(xmlTextWriterEndElement(writer)); /* memory */
+		TRY0(xmlTextWriterEndElement(writer)); /* server */
 
+		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "memory"));
+		isc_mem_renderxml(writer);
+		TRY0(xmlTextWriterEndElement(writer)); /* memory */
+	}
 	TRY0(xmlTextWriterEndElement(writer)); /* statistics */
 	TRY0(xmlTextWriterEndElement(writer)); /* bind */
 	TRY0(xmlTextWriterEndElement(writer)); /* isc */
 
 	TRY0(xmlTextWriterEndDocument(writer));
@@ -948,14 +974,17 @@
 	unsigned char *msg;
 	int msglen;
 	ns_server_t *server = arg;
 	isc_result_t result;
 
-	UNUSED(url);
 	UNUSED(querystring);
 
-	result = generatexml(server, &msglen, &msg);
+	if( strcmp( url, "/config") == 0 ) {
+		result = generatexml(server, 0, &msglen, &msg); /* Config-only */
+	} else {
+	 	result = generatexml(server, X_STATS, &msglen, &msg); /* With statistics */
+	}
 
 	if (result == ISC_R_SUCCESS) {
 		*retcode = 200;
 		*retmsg = "OK";
 		*mimetype = "text/xml";
@@ -965,11 +994,10 @@
 		*freecb_args = NULL;
 	}
 
 	return (result);
 }
-
 #endif	/* HAVE_LIBXML2 */
 
 static isc_result_t
 render_xsl(const char *url, const char *querystring, void *args,
 	   unsigned int *retcode, const char **retmsg, const char **mimetype,
@@ -1111,10 +1139,11 @@
 	if (result != ISC_R_SUCCESS)
 		goto cleanup;
 
 #ifdef HAVE_LIBXML2
 	isc_httpdmgr_addurl(listener->httpdmgr, "/", render_index, server);
+	isc_httpdmgr_addurl(listener->httpdmgr, "/config", render_index, server);
 #endif
 	isc_httpdmgr_addurl(listener->httpdmgr, "/bind9.xsl", render_xsl,
 			    server);
 
 	*listenerp = listener;
