xref: /netbsd-src/external/mpl/bind/dist/bin/named/statschannel.c (revision aef5eb5f59cdfe8314f1b5f78ac04eb144e44010)
1 /*	$NetBSD: statschannel.c,v 1.12 2022/09/23 12:15:21 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 /*! \file */
17 
18 #include <inttypes.h>
19 #include <stdbool.h>
20 
21 #include <isc/buffer.h>
22 #include <isc/httpd.h>
23 #include <isc/mem.h>
24 #include <isc/once.h>
25 #include <isc/print.h>
26 #include <isc/socket.h>
27 #include <isc/stats.h>
28 #include <isc/string.h>
29 #include <isc/task.h>
30 #include <isc/util.h>
31 
32 #include <dns/cache.h>
33 #include <dns/db.h>
34 #include <dns/opcode.h>
35 #include <dns/rcode.h>
36 #include <dns/rdataclass.h>
37 #include <dns/rdatatype.h>
38 #include <dns/resolver.h>
39 #include <dns/stats.h>
40 #include <dns/view.h>
41 #include <dns/zt.h>
42 
43 #include <ns/stats.h>
44 
45 #include <named/log.h>
46 #include <named/server.h>
47 #include <named/statschannel.h>
48 
49 #if HAVE_JSON_C
50 #include <json_object.h>
51 #include <linkhash.h>
52 #endif /* HAVE_JSON_C */
53 
54 #if HAVE_LIBXML2
55 #include <libxml/xmlwriter.h>
56 #define ISC_XMLCHAR (const xmlChar *)
57 #endif /* HAVE_LIBXML2 */
58 
59 #include "bind9.xsl.h"
60 
61 struct named_statschannel {
62 	/* Unlocked */
63 	isc_httpdmgr_t *httpdmgr;
64 	isc_sockaddr_t address;
65 	isc_mem_t *mctx;
66 
67 	/*
68 	 * Locked by channel lock: can be referenced and modified by both
69 	 * the server task and the channel task.
70 	 */
71 	isc_mutex_t lock;
72 	dns_acl_t *acl;
73 
74 	/* Locked by server task */
75 	ISC_LINK(struct named_statschannel) link;
76 };
77 
78 typedef struct stats_dumparg {
79 	isc_statsformat_t type;
80 	void *arg;		 /* type dependent argument */
81 	int ncounters;		 /* for general statistics */
82 	int *counterindices;	 /* for general statistics */
83 	uint64_t *countervalues; /* for general statistics */
84 	isc_result_t result;
85 } stats_dumparg_t;
86 
87 static isc_once_t once = ISC_ONCE_INIT;
88 
89 #if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C)
90 #define EXTENDED_STATS
91 #else /* if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C) */
92 #undef EXTENDED_STATS
93 #endif /* if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C) */
94 
95 #ifdef EXTENDED_STATS
96 static const char *
97 user_zonetype(dns_zone_t *zone) {
98 	dns_zonetype_t ztype;
99 	dns_view_t *view;
100 	static const struct zt {
101 		const dns_zonetype_t type;
102 		const char *const string;
103 	} typemap[] = { { dns_zone_none, "none" },
104 			{ dns_zone_primary, "master" },
105 			{ dns_zone_secondary, "slave" },
106 			{ dns_zone_mirror, "mirror" },
107 			{ dns_zone_stub, "stub" },
108 			{ dns_zone_staticstub, "static-stub" },
109 			{ dns_zone_key, "key" },
110 			{ dns_zone_dlz, "dlz" },
111 			{ dns_zone_redirect, "redirect" },
112 			{ 0, NULL } };
113 	const struct zt *tp;
114 
115 	if ((dns_zone_getoptions(zone) & DNS_ZONEOPT_AUTOEMPTY) != 0) {
116 		return ("builtin");
117 	}
118 
119 	view = dns_zone_getview(zone);
120 	if (view != NULL && strcmp(view->name, "_bind") == 0) {
121 		return ("builtin");
122 	}
123 
124 	ztype = dns_zone_gettype(zone);
125 	for (tp = typemap; tp->string != NULL && tp->type != ztype; tp++) {
126 		/* empty */
127 	}
128 	return (tp->string);
129 }
130 #endif /* ifdef EXTENDED_STATS */
131 
132 /*%
133  * Statistics descriptions.  These could be statistically initialized at
134  * compile time, but we configure them run time in the init_desc() function
135  * below so that they'll be less susceptible to counter name changes.
136  */
137 static const char *nsstats_desc[ns_statscounter_max];
138 static const char *resstats_desc[dns_resstatscounter_max];
139 static const char *adbstats_desc[dns_adbstats_max];
140 static const char *zonestats_desc[dns_zonestatscounter_max];
141 static const char *sockstats_desc[isc_sockstatscounter_max];
142 static const char *dnssecstats_desc[dns_dnssecstats_max];
143 static const char *udpinsizestats_desc[dns_sizecounter_in_max];
144 static const char *udpoutsizestats_desc[dns_sizecounter_out_max];
145 static const char *tcpinsizestats_desc[dns_sizecounter_in_max];
146 static const char *tcpoutsizestats_desc[dns_sizecounter_out_max];
147 static const char *dnstapstats_desc[dns_dnstapcounter_max];
148 static const char *gluecachestats_desc[dns_gluecachestatscounter_max];
149 #if defined(EXTENDED_STATS)
150 static const char *nsstats_xmldesc[ns_statscounter_max];
151 static const char *resstats_xmldesc[dns_resstatscounter_max];
152 static const char *adbstats_xmldesc[dns_adbstats_max];
153 static const char *zonestats_xmldesc[dns_zonestatscounter_max];
154 static const char *sockstats_xmldesc[isc_sockstatscounter_max];
155 static const char *dnssecstats_xmldesc[dns_dnssecstats_max];
156 static const char *udpinsizestats_xmldesc[dns_sizecounter_in_max];
157 static const char *udpoutsizestats_xmldesc[dns_sizecounter_out_max];
158 static const char *tcpinsizestats_xmldesc[dns_sizecounter_in_max];
159 static const char *tcpoutsizestats_xmldesc[dns_sizecounter_out_max];
160 static const char *dnstapstats_xmldesc[dns_dnstapcounter_max];
161 static const char *gluecachestats_xmldesc[dns_gluecachestatscounter_max];
162 #else /* if defined(EXTENDED_STATS) */
163 #define nsstats_xmldesc		NULL
164 #define resstats_xmldesc	NULL
165 #define adbstats_xmldesc	NULL
166 #define zonestats_xmldesc	NULL
167 #define sockstats_xmldesc	NULL
168 #define dnssecstats_xmldesc	NULL
169 #define udpinsizestats_xmldesc	NULL
170 #define udpoutsizestats_xmldesc NULL
171 #define tcpinsizestats_xmldesc	NULL
172 #define tcpoutsizestats_xmldesc NULL
173 #define dnstapstats_xmldesc	NULL
174 #define gluecachestats_xmldesc	NULL
175 #endif /* EXTENDED_STATS */
176 
177 #define TRY0(a)                     \
178 	do {                        \
179 		xmlrc = (a);        \
180 		if (xmlrc < 0)      \
181 			goto error; \
182 	} while (0)
183 
184 /*%
185  * Mapping arrays to represent statistics counters in the order of our
186  * preference, regardless of the order of counter indices.  For example,
187  * nsstats_desc[nsstats_index[0]] will be the description that is shown first.
188  */
189 static int nsstats_index[ns_statscounter_max];
190 static int resstats_index[dns_resstatscounter_max];
191 static int adbstats_index[dns_adbstats_max];
192 static int zonestats_index[dns_zonestatscounter_max];
193 static int sockstats_index[isc_sockstatscounter_max];
194 static int dnssecstats_index[dns_dnssecstats_max];
195 static int udpinsizestats_index[dns_sizecounter_in_max];
196 static int udpoutsizestats_index[dns_sizecounter_out_max];
197 static int tcpinsizestats_index[dns_sizecounter_in_max];
198 static int tcpoutsizestats_index[dns_sizecounter_out_max];
199 static int dnstapstats_index[dns_dnstapcounter_max];
200 static int gluecachestats_index[dns_gluecachestatscounter_max];
201 
202 static void
203 set_desc(int counter, int maxcounter, const char *fdesc, const char **fdescs,
204 	 const char *xdesc, const char **xdescs) {
205 	REQUIRE(counter < maxcounter);
206 	REQUIRE(fdescs != NULL && fdescs[counter] == NULL);
207 #if defined(EXTENDED_STATS)
208 	REQUIRE(xdescs != NULL && xdescs[counter] == NULL);
209 #endif /* if defined(EXTENDED_STATS) */
210 
211 	fdescs[counter] = fdesc;
212 #if defined(EXTENDED_STATS)
213 	xdescs[counter] = xdesc;
214 #else  /* if defined(EXTENDED_STATS) */
215 	UNUSED(xdesc);
216 	UNUSED(xdescs);
217 #endif /* if defined(EXTENDED_STATS) */
218 }
219 
220 static void
221 init_desc(void) {
222 	int i;
223 
224 	/* Initialize name server statistics */
225 	for (i = 0; i < ns_statscounter_max; i++) {
226 		nsstats_desc[i] = NULL;
227 	}
228 #if defined(EXTENDED_STATS)
229 	for (i = 0; i < ns_statscounter_max; i++) {
230 		nsstats_xmldesc[i] = NULL;
231 	}
232 #endif /* if defined(EXTENDED_STATS) */
233 
234 #define SET_NSSTATDESC(counterid, desc, xmldesc)                           \
235 	do {                                                               \
236 		set_desc(ns_statscounter_##counterid, ns_statscounter_max, \
237 			 desc, nsstats_desc, xmldesc, nsstats_xmldesc);    \
238 		nsstats_index[i++] = ns_statscounter_##counterid;          \
239 	} while (0)
240 
241 	i = 0;
242 	SET_NSSTATDESC(requestv4, "IPv4 requests received", "Requestv4");
243 	SET_NSSTATDESC(requestv6, "IPv6 requests received", "Requestv6");
244 	SET_NSSTATDESC(edns0in, "requests with EDNS(0) received", "ReqEdns0");
245 	SET_NSSTATDESC(badednsver,
246 		       "requests with unsupported EDNS version received",
247 		       "ReqBadEDNSVer");
248 	SET_NSSTATDESC(tsigin, "requests with TSIG received", "ReqTSIG");
249 	SET_NSSTATDESC(sig0in, "requests with SIG(0) received", "ReqSIG0");
250 	SET_NSSTATDESC(invalidsig, "requests with invalid signature",
251 		       "ReqBadSIG");
252 	SET_NSSTATDESC(requesttcp, "TCP requests received", "ReqTCP");
253 	SET_NSSTATDESC(tcphighwater, "TCP connection high-water",
254 		       "TCPConnHighWater");
255 	SET_NSSTATDESC(authrej, "auth queries rejected", "AuthQryRej");
256 	SET_NSSTATDESC(recurserej, "recursive queries rejected", "RecQryRej");
257 	SET_NSSTATDESC(xfrrej, "transfer requests rejected", "XfrRej");
258 	SET_NSSTATDESC(updaterej, "update requests rejected", "UpdateRej");
259 	SET_NSSTATDESC(response, "responses sent", "Response");
260 	SET_NSSTATDESC(truncatedresp, "truncated responses sent",
261 		       "TruncatedResp");
262 	SET_NSSTATDESC(edns0out, "responses with EDNS(0) sent", "RespEDNS0");
263 	SET_NSSTATDESC(tsigout, "responses with TSIG sent", "RespTSIG");
264 	SET_NSSTATDESC(sig0out, "responses with SIG(0) sent", "RespSIG0");
265 	SET_NSSTATDESC(success, "queries resulted in successful answer",
266 		       "QrySuccess");
267 	SET_NSSTATDESC(authans, "queries resulted in authoritative answer",
268 		       "QryAuthAns");
269 	SET_NSSTATDESC(nonauthans,
270 		       "queries resulted in non authoritative answer",
271 		       "QryNoauthAns");
272 	SET_NSSTATDESC(referral, "queries resulted in referral answer",
273 		       "QryReferral");
274 	SET_NSSTATDESC(nxrrset, "queries resulted in nxrrset", "QryNxrrset");
275 	SET_NSSTATDESC(servfail, "queries resulted in SERVFAIL", "QrySERVFAIL");
276 	SET_NSSTATDESC(formerr, "queries resulted in FORMERR", "QryFORMERR");
277 	SET_NSSTATDESC(nxdomain, "queries resulted in NXDOMAIN", "QryNXDOMAIN");
278 	SET_NSSTATDESC(recursion, "queries caused recursion", "QryRecursion");
279 	SET_NSSTATDESC(duplicate, "duplicate queries received", "QryDuplicate");
280 	SET_NSSTATDESC(dropped, "queries dropped", "QryDropped");
281 	SET_NSSTATDESC(failure, "other query failures", "QryFailure");
282 	SET_NSSTATDESC(xfrdone, "requested transfers completed", "XfrReqDone");
283 	SET_NSSTATDESC(updatereqfwd, "update requests forwarded",
284 		       "UpdateReqFwd");
285 	SET_NSSTATDESC(updaterespfwd, "update responses forwarded",
286 		       "UpdateRespFwd");
287 	SET_NSSTATDESC(updatefwdfail, "update forward failed", "UpdateFwdFail");
288 	SET_NSSTATDESC(updatedone, "updates completed", "UpdateDone");
289 	SET_NSSTATDESC(updatefail, "updates failed", "UpdateFail");
290 	SET_NSSTATDESC(updatebadprereq,
291 		       "updates rejected due to prerequisite failure",
292 		       "UpdateBadPrereq");
293 	SET_NSSTATDESC(recursclients, "recursing clients", "RecursClients");
294 	SET_NSSTATDESC(dns64, "queries answered by DNS64", "DNS64");
295 	SET_NSSTATDESC(ratedropped, "responses dropped for rate limits",
296 		       "RateDropped");
297 	SET_NSSTATDESC(rateslipped, "responses truncated for rate limits",
298 		       "RateSlipped");
299 	SET_NSSTATDESC(rpz_rewrites, "response policy zone rewrites",
300 		       "RPZRewrites");
301 	SET_NSSTATDESC(udp, "UDP queries received", "QryUDP");
302 	SET_NSSTATDESC(tcp, "TCP queries received", "QryTCP");
303 	SET_NSSTATDESC(nsidopt, "NSID option received", "NSIDOpt");
304 	SET_NSSTATDESC(expireopt, "Expire option received", "ExpireOpt");
305 	SET_NSSTATDESC(keepaliveopt, "EDNS TCP keepalive option received",
306 		       "KeepAliveOpt");
307 	SET_NSSTATDESC(padopt, "EDNS padding option received", "PadOpt");
308 	SET_NSSTATDESC(otheropt, "Other EDNS option received", "OtherOpt");
309 	SET_NSSTATDESC(cookiein, "COOKIE option received", "CookieIn");
310 	SET_NSSTATDESC(cookienew, "COOKIE - client only", "CookieNew");
311 	SET_NSSTATDESC(cookiebadsize, "COOKIE - bad size", "CookieBadSize");
312 	SET_NSSTATDESC(cookiebadtime, "COOKIE - bad time", "CookieBadTime");
313 	SET_NSSTATDESC(cookienomatch, "COOKIE - no match", "CookieNoMatch");
314 	SET_NSSTATDESC(cookiematch, "COOKIE - match", "CookieMatch");
315 	SET_NSSTATDESC(ecsopt, "EDNS client subnet option received", "ECSOpt");
316 	SET_NSSTATDESC(nxdomainredirect,
317 		       "queries resulted in NXDOMAIN that were redirected",
318 		       "QryNXRedir");
319 	SET_NSSTATDESC(nxdomainredirect_rlookup,
320 		       "queries resulted in NXDOMAIN that were redirected and "
321 		       "resulted in a successful remote lookup",
322 		       "QryNXRedirRLookup");
323 	SET_NSSTATDESC(badcookie, "sent badcookie response", "QryBADCOOKIE");
324 	SET_NSSTATDESC(nxdomainsynth, "synthesized a NXDOMAIN response",
325 		       "SynthNXDOMAIN");
326 	SET_NSSTATDESC(nodatasynth, "syththesized a no-data response",
327 		       "SynthNODATA");
328 	SET_NSSTATDESC(wildcardsynth, "synthesized a wildcard response",
329 		       "SynthWILDCARD");
330 	SET_NSSTATDESC(trystale,
331 		       "attempts to use stale cache data after lookup failure",
332 		       "QryTryStale");
333 	SET_NSSTATDESC(usedstale,
334 		       "successful uses of stale cache data after lookup "
335 		       "failure",
336 		       "QryUsedStale");
337 	SET_NSSTATDESC(prefetch, "queries triggered prefetch", "Prefetch");
338 	SET_NSSTATDESC(keytagopt, "Keytag option received", "KeyTagOpt");
339 	SET_NSSTATDESC(reclimitdropped,
340 		       "queries dropped due to recursive client limit",
341 		       "RecLimitDropped");
342 
343 	INSIST(i == ns_statscounter_max);
344 
345 	/* Initialize resolver statistics */
346 	for (i = 0; i < dns_resstatscounter_max; i++) {
347 		resstats_desc[i] = NULL;
348 	}
349 #if defined(EXTENDED_STATS)
350 	for (i = 0; i < dns_resstatscounter_max; i++) {
351 		resstats_xmldesc[i] = NULL;
352 	}
353 #endif /* if defined(EXTENDED_STATS) */
354 
355 #define SET_RESSTATDESC(counterid, desc, xmldesc)                      \
356 	do {                                                           \
357 		set_desc(dns_resstatscounter_##counterid,              \
358 			 dns_resstatscounter_max, desc, resstats_desc, \
359 			 xmldesc, resstats_xmldesc);                   \
360 		resstats_index[i++] = dns_resstatscounter_##counterid; \
361 	} while (0)
362 
363 	i = 0;
364 	SET_RESSTATDESC(queryv4, "IPv4 queries sent", "Queryv4");
365 	SET_RESSTATDESC(queryv6, "IPv6 queries sent", "Queryv6");
366 	SET_RESSTATDESC(responsev4, "IPv4 responses received", "Responsev4");
367 	SET_RESSTATDESC(responsev6, "IPv6 responses received", "Responsev6");
368 	SET_RESSTATDESC(nxdomain, "NXDOMAIN received", "NXDOMAIN");
369 	SET_RESSTATDESC(servfail, "SERVFAIL received", "SERVFAIL");
370 	SET_RESSTATDESC(formerr, "FORMERR received", "FORMERR");
371 	SET_RESSTATDESC(othererror, "other errors received", "OtherError");
372 	SET_RESSTATDESC(edns0fail, "EDNS(0) query failures", "EDNS0Fail");
373 	SET_RESSTATDESC(mismatch, "mismatch responses received", "Mismatch");
374 	SET_RESSTATDESC(truncated, "truncated responses received", "Truncated");
375 	SET_RESSTATDESC(lame, "lame delegations received", "Lame");
376 	SET_RESSTATDESC(retry, "query retries", "Retry");
377 	SET_RESSTATDESC(dispabort, "queries aborted due to quota",
378 			"QueryAbort");
379 	SET_RESSTATDESC(dispsockfail, "failures in opening query sockets",
380 			"QuerySockFail");
381 	SET_RESSTATDESC(disprequdp, "UDP queries in progress", "QueryCurUDP");
382 	SET_RESSTATDESC(dispreqtcp, "TCP queries in progress", "QueryCurTCP");
383 	SET_RESSTATDESC(querytimeout, "query timeouts", "QueryTimeout");
384 	SET_RESSTATDESC(gluefetchv4, "IPv4 NS address fetches", "GlueFetchv4");
385 	SET_RESSTATDESC(gluefetchv6, "IPv6 NS address fetches", "GlueFetchv6");
386 	SET_RESSTATDESC(gluefetchv4fail, "IPv4 NS address fetch failed",
387 			"GlueFetchv4Fail");
388 	SET_RESSTATDESC(gluefetchv6fail, "IPv6 NS address fetch failed",
389 			"GlueFetchv6Fail");
390 	SET_RESSTATDESC(val, "DNSSEC validation attempted", "ValAttempt");
391 	SET_RESSTATDESC(valsuccess, "DNSSEC validation succeeded", "ValOk");
392 	SET_RESSTATDESC(valnegsuccess, "DNSSEC NX validation succeeded",
393 			"ValNegOk");
394 	SET_RESSTATDESC(valfail, "DNSSEC validation failed", "ValFail");
395 	SET_RESSTATDESC(queryrtt0,
396 			"queries with RTT < " DNS_RESOLVER_QRYRTTCLASS0STR "ms",
397 			"QryRTT" DNS_RESOLVER_QRYRTTCLASS0STR);
398 	SET_RESSTATDESC(queryrtt1,
399 			"queries with RTT " DNS_RESOLVER_QRYRTTCLASS0STR
400 			"-" DNS_RESOLVER_QRYRTTCLASS1STR "ms",
401 			"QryRTT" DNS_RESOLVER_QRYRTTCLASS1STR);
402 	SET_RESSTATDESC(queryrtt2,
403 			"queries with RTT " DNS_RESOLVER_QRYRTTCLASS1STR
404 			"-" DNS_RESOLVER_QRYRTTCLASS2STR "ms",
405 			"QryRTT" DNS_RESOLVER_QRYRTTCLASS2STR);
406 	SET_RESSTATDESC(queryrtt3,
407 			"queries with RTT " DNS_RESOLVER_QRYRTTCLASS2STR
408 			"-" DNS_RESOLVER_QRYRTTCLASS3STR "ms",
409 			"QryRTT" DNS_RESOLVER_QRYRTTCLASS3STR);
410 	SET_RESSTATDESC(queryrtt4,
411 			"queries with RTT " DNS_RESOLVER_QRYRTTCLASS3STR
412 			"-" DNS_RESOLVER_QRYRTTCLASS4STR "ms",
413 			"QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR);
414 	SET_RESSTATDESC(queryrtt5,
415 			"queries with RTT > " DNS_RESOLVER_QRYRTTCLASS4STR "ms",
416 			"QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR "+");
417 	SET_RESSTATDESC(nfetch, "active fetches", "NumFetch");
418 	SET_RESSTATDESC(buckets, "bucket size", "BucketSize");
419 	SET_RESSTATDESC(refused, "REFUSED received", "REFUSED");
420 	SET_RESSTATDESC(cookienew, "COOKIE send with client cookie only",
421 			"ClientCookieOut");
422 	SET_RESSTATDESC(cookieout, "COOKIE sent with client and server cookie",
423 			"ServerCookieOut");
424 	SET_RESSTATDESC(cookiein, "COOKIE replies received", "CookieIn");
425 	SET_RESSTATDESC(cookieok, "COOKIE client ok", "CookieClientOk");
426 	SET_RESSTATDESC(badvers, "bad EDNS version", "BadEDNSVersion");
427 	SET_RESSTATDESC(badcookie, "bad cookie rcode", "BadCookieRcode");
428 	SET_RESSTATDESC(zonequota, "spilled due to zone quota", "ZoneQuota");
429 	SET_RESSTATDESC(serverquota, "spilled due to server quota",
430 			"ServerQuota");
431 	SET_RESSTATDESC(nextitem, "waited for next item", "NextItem");
432 	SET_RESSTATDESC(priming, "priming queries", "Priming");
433 
434 	INSIST(i == dns_resstatscounter_max);
435 
436 	/* Initialize adb statistics */
437 	for (i = 0; i < dns_adbstats_max; i++) {
438 		adbstats_desc[i] = NULL;
439 	}
440 #if defined(EXTENDED_STATS)
441 	for (i = 0; i < dns_adbstats_max; i++) {
442 		adbstats_xmldesc[i] = NULL;
443 	}
444 #endif /* if defined(EXTENDED_STATS) */
445 
446 #define SET_ADBSTATDESC(id, desc, xmldesc)                          \
447 	do {                                                        \
448 		set_desc(dns_adbstats_##id, dns_adbstats_max, desc, \
449 			 adbstats_desc, xmldesc, adbstats_xmldesc); \
450 		adbstats_index[i++] = dns_adbstats_##id;            \
451 	} while (0)
452 	i = 0;
453 	SET_ADBSTATDESC(nentries, "Address hash table size", "nentries");
454 	SET_ADBSTATDESC(entriescnt, "Addresses in hash table", "entriescnt");
455 	SET_ADBSTATDESC(nnames, "Name hash table size", "nnames");
456 	SET_ADBSTATDESC(namescnt, "Names in hash table", "namescnt");
457 
458 	INSIST(i == dns_adbstats_max);
459 
460 	/* Initialize zone statistics */
461 	for (i = 0; i < dns_zonestatscounter_max; i++) {
462 		zonestats_desc[i] = NULL;
463 	}
464 #if defined(EXTENDED_STATS)
465 	for (i = 0; i < dns_zonestatscounter_max; i++) {
466 		zonestats_xmldesc[i] = NULL;
467 	}
468 #endif /* if defined(EXTENDED_STATS) */
469 
470 #define SET_ZONESTATDESC(counterid, desc, xmldesc)                       \
471 	do {                                                             \
472 		set_desc(dns_zonestatscounter_##counterid,               \
473 			 dns_zonestatscounter_max, desc, zonestats_desc, \
474 			 xmldesc, zonestats_xmldesc);                    \
475 		zonestats_index[i++] = dns_zonestatscounter_##counterid; \
476 	} while (0)
477 
478 	i = 0;
479 	SET_ZONESTATDESC(notifyoutv4, "IPv4 notifies sent", "NotifyOutv4");
480 	SET_ZONESTATDESC(notifyoutv6, "IPv6 notifies sent", "NotifyOutv6");
481 	SET_ZONESTATDESC(notifyinv4, "IPv4 notifies received", "NotifyInv4");
482 	SET_ZONESTATDESC(notifyinv6, "IPv6 notifies received", "NotifyInv6");
483 	SET_ZONESTATDESC(notifyrej, "notifies rejected", "NotifyRej");
484 	SET_ZONESTATDESC(soaoutv4, "IPv4 SOA queries sent", "SOAOutv4");
485 	SET_ZONESTATDESC(soaoutv6, "IPv6 SOA queries sent", "SOAOutv6");
486 	SET_ZONESTATDESC(axfrreqv4, "IPv4 AXFR requested", "AXFRReqv4");
487 	SET_ZONESTATDESC(axfrreqv6, "IPv6 AXFR requested", "AXFRReqv6");
488 	SET_ZONESTATDESC(ixfrreqv4, "IPv4 IXFR requested", "IXFRReqv4");
489 	SET_ZONESTATDESC(ixfrreqv6, "IPv6 IXFR requested", "IXFRReqv6");
490 	SET_ZONESTATDESC(xfrsuccess, "transfer requests succeeded",
491 			 "XfrSuccess");
492 	SET_ZONESTATDESC(xfrfail, "transfer requests failed", "XfrFail");
493 	INSIST(i == dns_zonestatscounter_max);
494 
495 	/* Initialize socket statistics */
496 	for (i = 0; i < isc_sockstatscounter_max; i++) {
497 		sockstats_desc[i] = NULL;
498 	}
499 #if defined(EXTENDED_STATS)
500 	for (i = 0; i < isc_sockstatscounter_max; i++) {
501 		sockstats_xmldesc[i] = NULL;
502 	}
503 #endif /* if defined(EXTENDED_STATS) */
504 
505 #define SET_SOCKSTATDESC(counterid, desc, xmldesc)                       \
506 	do {                                                             \
507 		set_desc(isc_sockstatscounter_##counterid,               \
508 			 isc_sockstatscounter_max, desc, sockstats_desc, \
509 			 xmldesc, sockstats_xmldesc);                    \
510 		sockstats_index[i++] = isc_sockstatscounter_##counterid; \
511 	} while (0)
512 
513 	i = 0;
514 	SET_SOCKSTATDESC(udp4open, "UDP/IPv4 sockets opened", "UDP4Open");
515 	SET_SOCKSTATDESC(udp6open, "UDP/IPv6 sockets opened", "UDP6Open");
516 	SET_SOCKSTATDESC(tcp4open, "TCP/IPv4 sockets opened", "TCP4Open");
517 	SET_SOCKSTATDESC(tcp6open, "TCP/IPv6 sockets opened", "TCP6Open");
518 	SET_SOCKSTATDESC(unixopen, "Unix domain sockets opened", "UnixOpen");
519 	SET_SOCKSTATDESC(rawopen, "Raw sockets opened", "RawOpen");
520 	SET_SOCKSTATDESC(udp4openfail, "UDP/IPv4 socket open failures",
521 			 "UDP4OpenFail");
522 	SET_SOCKSTATDESC(udp6openfail, "UDP/IPv6 socket open failures",
523 			 "UDP6OpenFail");
524 	SET_SOCKSTATDESC(tcp4openfail, "TCP/IPv4 socket open failures",
525 			 "TCP4OpenFail");
526 	SET_SOCKSTATDESC(tcp6openfail, "TCP/IPv6 socket open failures",
527 			 "TCP6OpenFail");
528 	SET_SOCKSTATDESC(unixopenfail, "Unix domain socket open failures",
529 			 "UnixOpenFail");
530 	SET_SOCKSTATDESC(rawopenfail, "Raw socket open failures",
531 			 "RawOpenFail");
532 	SET_SOCKSTATDESC(udp4close, "UDP/IPv4 sockets closed", "UDP4Close");
533 	SET_SOCKSTATDESC(udp6close, "UDP/IPv6 sockets closed", "UDP6Close");
534 	SET_SOCKSTATDESC(tcp4close, "TCP/IPv4 sockets closed", "TCP4Close");
535 	SET_SOCKSTATDESC(tcp6close, "TCP/IPv6 sockets closed", "TCP6Close");
536 	SET_SOCKSTATDESC(unixclose, "Unix domain sockets closed", "UnixClose");
537 	SET_SOCKSTATDESC(fdwatchclose, "FDwatch sockets closed",
538 			 "FDWatchClose");
539 	SET_SOCKSTATDESC(rawclose, "Raw sockets closed", "RawClose");
540 	SET_SOCKSTATDESC(udp4bindfail, "UDP/IPv4 socket bind failures",
541 			 "UDP4BindFail");
542 	SET_SOCKSTATDESC(udp6bindfail, "UDP/IPv6 socket bind failures",
543 			 "UDP6BindFail");
544 	SET_SOCKSTATDESC(tcp4bindfail, "TCP/IPv4 socket bind failures",
545 			 "TCP4BindFail");
546 	SET_SOCKSTATDESC(tcp6bindfail, "TCP/IPv6 socket bind failures",
547 			 "TCP6BindFail");
548 	SET_SOCKSTATDESC(unixbindfail, "Unix domain socket bind failures",
549 			 "UnixBindFail");
550 	SET_SOCKSTATDESC(fdwatchbindfail, "FDwatch socket bind failures",
551 			 "FdwatchBindFail");
552 	SET_SOCKSTATDESC(udp4connectfail, "UDP/IPv4 socket connect failures",
553 			 "UDP4ConnFail");
554 	SET_SOCKSTATDESC(udp6connectfail, "UDP/IPv6 socket connect failures",
555 			 "UDP6ConnFail");
556 	SET_SOCKSTATDESC(tcp4connectfail, "TCP/IPv4 socket connect failures",
557 			 "TCP4ConnFail");
558 	SET_SOCKSTATDESC(tcp6connectfail, "TCP/IPv6 socket connect failures",
559 			 "TCP6ConnFail");
560 	SET_SOCKSTATDESC(unixconnectfail, "Unix domain socket connect failures",
561 			 "UnixConnFail");
562 	SET_SOCKSTATDESC(fdwatchconnectfail, "FDwatch socket connect failures",
563 			 "FDwatchConnFail");
564 	SET_SOCKSTATDESC(udp4connect, "UDP/IPv4 connections established",
565 			 "UDP4Conn");
566 	SET_SOCKSTATDESC(udp6connect, "UDP/IPv6 connections established",
567 			 "UDP6Conn");
568 	SET_SOCKSTATDESC(tcp4connect, "TCP/IPv4 connections established",
569 			 "TCP4Conn");
570 	SET_SOCKSTATDESC(tcp6connect, "TCP/IPv6 connections established",
571 			 "TCP6Conn");
572 	SET_SOCKSTATDESC(unixconnect, "Unix domain connections established",
573 			 "UnixConn");
574 	SET_SOCKSTATDESC(fdwatchconnect,
575 			 "FDwatch domain connections established",
576 			 "FDwatchConn");
577 	SET_SOCKSTATDESC(tcp4acceptfail, "TCP/IPv4 connection accept failures",
578 			 "TCP4AcceptFail");
579 	SET_SOCKSTATDESC(tcp6acceptfail, "TCP/IPv6 connection accept failures",
580 			 "TCP6AcceptFail");
581 	SET_SOCKSTATDESC(unixacceptfail,
582 			 "Unix domain connection accept failures",
583 			 "UnixAcceptFail");
584 	SET_SOCKSTATDESC(tcp4accept, "TCP/IPv4 connections accepted",
585 			 "TCP4Accept");
586 	SET_SOCKSTATDESC(tcp6accept, "TCP/IPv6 connections accepted",
587 			 "TCP6Accept");
588 	SET_SOCKSTATDESC(unixaccept, "Unix domain connections accepted",
589 			 "UnixAccept");
590 	SET_SOCKSTATDESC(udp4sendfail, "UDP/IPv4 send errors", "UDP4SendErr");
591 	SET_SOCKSTATDESC(udp6sendfail, "UDP/IPv6 send errors", "UDP6SendErr");
592 	SET_SOCKSTATDESC(tcp4sendfail, "TCP/IPv4 send errors", "TCP4SendErr");
593 	SET_SOCKSTATDESC(tcp6sendfail, "TCP/IPv6 send errors", "TCP6SendErr");
594 	SET_SOCKSTATDESC(unixsendfail, "Unix domain send errors",
595 			 "UnixSendErr");
596 	SET_SOCKSTATDESC(fdwatchsendfail, "FDwatch send errors",
597 			 "FDwatchSendErr");
598 	SET_SOCKSTATDESC(udp4recvfail, "UDP/IPv4 recv errors", "UDP4RecvErr");
599 	SET_SOCKSTATDESC(udp6recvfail, "UDP/IPv6 recv errors", "UDP6RecvErr");
600 	SET_SOCKSTATDESC(tcp4recvfail, "TCP/IPv4 recv errors", "TCP4RecvErr");
601 	SET_SOCKSTATDESC(tcp6recvfail, "TCP/IPv6 recv errors", "TCP6RecvErr");
602 	SET_SOCKSTATDESC(unixrecvfail, "Unix domain recv errors",
603 			 "UnixRecvErr");
604 	SET_SOCKSTATDESC(fdwatchrecvfail, "FDwatch recv errors",
605 			 "FDwatchRecvErr");
606 	SET_SOCKSTATDESC(rawrecvfail, "Raw recv errors", "RawRecvErr");
607 	SET_SOCKSTATDESC(udp4active, "UDP/IPv4 sockets active", "UDP4Active");
608 	SET_SOCKSTATDESC(udp6active, "UDP/IPv6 sockets active", "UDP6Active");
609 	SET_SOCKSTATDESC(tcp4active, "TCP/IPv4 sockets active", "TCP4Active");
610 	SET_SOCKSTATDESC(tcp6active, "TCP/IPv6 sockets active", "TCP6Active");
611 	SET_SOCKSTATDESC(unixactive, "Unix domain sockets active",
612 			 "UnixActive");
613 	SET_SOCKSTATDESC(rawactive, "Raw sockets active", "RawActive");
614 	INSIST(i == isc_sockstatscounter_max);
615 
616 	/* Initialize DNSSEC statistics */
617 	for (i = 0; i < dns_dnssecstats_max; i++) {
618 		dnssecstats_desc[i] = NULL;
619 	}
620 #if defined(EXTENDED_STATS)
621 	for (i = 0; i < dns_dnssecstats_max; i++) {
622 		dnssecstats_xmldesc[i] = NULL;
623 	}
624 #endif /* if defined(EXTENDED_STATS) */
625 
626 #define SET_DNSSECSTATDESC(counterid, desc, xmldesc)                       \
627 	do {                                                               \
628 		set_desc(dns_dnssecstats_##counterid, dns_dnssecstats_max, \
629 			 desc, dnssecstats_desc, xmldesc,                  \
630 			 dnssecstats_xmldesc);                             \
631 		dnssecstats_index[i++] = dns_dnssecstats_##counterid;      \
632 	} while (0)
633 
634 	i = 0;
635 	SET_DNSSECSTATDESC(asis,
636 			   "dnssec validation success with signer "
637 			   "\"as is\"",
638 			   "DNSSECasis");
639 	SET_DNSSECSTATDESC(downcase,
640 			   "dnssec validation success with signer "
641 			   "lower cased",
642 			   "DNSSECdowncase");
643 	SET_DNSSECSTATDESC(wildcard, "dnssec validation of wildcard signature",
644 			   "DNSSECwild");
645 	SET_DNSSECSTATDESC(fail, "dnssec validation failures", "DNSSECfail");
646 	INSIST(i == dns_dnssecstats_max);
647 
648 	/* Initialize dnstap statistics */
649 	for (i = 0; i < dns_dnstapcounter_max; i++) {
650 		dnstapstats_desc[i] = NULL;
651 	}
652 #if defined(EXTENDED_STATS)
653 	for (i = 0; i < dns_dnstapcounter_max; i++) {
654 		dnstapstats_xmldesc[i] = NULL;
655 	}
656 #endif /* if defined(EXTENDED_STATS) */
657 
658 #define SET_DNSTAPSTATDESC(counterid, desc, xmldesc)                           \
659 	do {                                                                   \
660 		set_desc(dns_dnstapcounter_##counterid, dns_dnstapcounter_max, \
661 			 desc, dnstapstats_desc, xmldesc,                      \
662 			 dnstapstats_xmldesc);                                 \
663 		dnstapstats_index[i++] = dns_dnstapcounter_##counterid;        \
664 	} while (0)
665 	i = 0;
666 	SET_DNSTAPSTATDESC(success, "dnstap messages written", "DNSTAPsuccess");
667 	SET_DNSTAPSTATDESC(drop, "dnstap messages dropped", "DNSTAPdropped");
668 	INSIST(i == dns_dnstapcounter_max);
669 
670 #define SET_GLUECACHESTATDESC(counterid, desc, xmldesc)         \
671 	do {                                                    \
672 		set_desc(dns_gluecachestatscounter_##counterid, \
673 			 dns_gluecachestatscounter_max, desc,   \
674 			 gluecachestats_desc, xmldesc,          \
675 			 gluecachestats_xmldesc);               \
676 		gluecachestats_index[i++] =                     \
677 			dns_gluecachestatscounter_##counterid;  \
678 	} while (0)
679 	i = 0;
680 	SET_GLUECACHESTATDESC(hits_present, "Hits for present glue (cached)",
681 			      "GLUECACHEhitspresent");
682 	SET_GLUECACHESTATDESC(hits_absent,
683 			      "Hits for non-existent glue (cached)",
684 			      "GLUECACHEhitsabsent");
685 	SET_GLUECACHESTATDESC(inserts_present,
686 			      "Miss-plus-cache-inserts for present glue",
687 			      "GLUECACHEinsertspresent");
688 	SET_GLUECACHESTATDESC(inserts_absent,
689 			      "Miss-plus-cache-inserts for non-existent glue",
690 			      "GLUECACHEinsertsabsent");
691 	INSIST(i == dns_gluecachestatscounter_max);
692 
693 	/* Sanity check */
694 	for (i = 0; i < ns_statscounter_max; i++) {
695 		INSIST(nsstats_desc[i] != NULL);
696 	}
697 	for (i = 0; i < dns_resstatscounter_max; i++) {
698 		INSIST(resstats_desc[i] != NULL);
699 	}
700 	for (i = 0; i < dns_adbstats_max; i++) {
701 		INSIST(adbstats_desc[i] != NULL);
702 	}
703 	for (i = 0; i < dns_zonestatscounter_max; i++) {
704 		INSIST(zonestats_desc[i] != NULL);
705 	}
706 	for (i = 0; i < isc_sockstatscounter_max; i++) {
707 		INSIST(sockstats_desc[i] != NULL);
708 	}
709 	for (i = 0; i < dns_dnssecstats_max; i++) {
710 		INSIST(dnssecstats_desc[i] != NULL);
711 	}
712 	for (i = 0; i < dns_dnstapcounter_max; i++) {
713 		INSIST(dnstapstats_desc[i] != NULL);
714 	}
715 	for (i = 0; i < dns_gluecachestatscounter_max; i++) {
716 		INSIST(gluecachestats_desc[i] != NULL);
717 	}
718 #if defined(EXTENDED_STATS)
719 	for (i = 0; i < ns_statscounter_max; i++) {
720 		INSIST(nsstats_xmldesc[i] != NULL);
721 	}
722 	for (i = 0; i < dns_resstatscounter_max; i++) {
723 		INSIST(resstats_xmldesc[i] != NULL);
724 	}
725 	for (i = 0; i < dns_adbstats_max; i++) {
726 		INSIST(adbstats_xmldesc[i] != NULL);
727 	}
728 	for (i = 0; i < dns_zonestatscounter_max; i++) {
729 		INSIST(zonestats_xmldesc[i] != NULL);
730 	}
731 	for (i = 0; i < isc_sockstatscounter_max; i++) {
732 		INSIST(sockstats_xmldesc[i] != NULL);
733 	}
734 	for (i = 0; i < dns_dnssecstats_max; i++) {
735 		INSIST(dnssecstats_xmldesc[i] != NULL);
736 	}
737 	for (i = 0; i < dns_dnstapcounter_max; i++) {
738 		INSIST(dnstapstats_xmldesc[i] != NULL);
739 	}
740 	for (i = 0; i < dns_gluecachestatscounter_max; i++) {
741 		INSIST(gluecachestats_xmldesc[i] != NULL);
742 	}
743 #endif /* if defined(EXTENDED_STATS) */
744 
745 	/* Initialize traffic size statistics */
746 	for (i = 0; i < dns_sizecounter_in_max; i++) {
747 		udpinsizestats_desc[i] = NULL;
748 		tcpinsizestats_desc[i] = NULL;
749 #if defined(EXTENDED_STATS)
750 		udpinsizestats_xmldesc[i] = NULL;
751 		tcpinsizestats_xmldesc[i] = NULL;
752 #endif /* if defined(EXTENDED_STATS) */
753 	}
754 	for (i = 0; i < dns_sizecounter_out_max; i++) {
755 		udpoutsizestats_desc[i] = NULL;
756 		tcpoutsizestats_desc[i] = NULL;
757 #if defined(EXTENDED_STATS)
758 		udpoutsizestats_xmldesc[i] = NULL;
759 		tcpoutsizestats_xmldesc[i] = NULL;
760 #endif /* if defined(EXTENDED_STATS) */
761 	}
762 
763 #define SET_SIZESTATDESC(counterid, desc, xmldesc, inout)       \
764 	do {                                                    \
765 		set_desc(dns_sizecounter_##inout##_##counterid, \
766 			 dns_sizecounter_##inout##_max, desc,   \
767 			 udp##inout##sizestats_desc, xmldesc,   \
768 			 udp##inout##sizestats_xmldesc);        \
769 		set_desc(dns_sizecounter_##inout##_##counterid, \
770 			 dns_sizecounter_##inout##_max, desc,   \
771 			 tcp##inout##sizestats_desc, xmldesc,   \
772 			 tcp##inout##sizestats_xmldesc);        \
773 		udp##inout##sizestats_index[i] =                \
774 			dns_sizecounter_##inout##_##counterid;  \
775 		tcp##inout##sizestats_index[i] =                \
776 			dns_sizecounter_##inout##_##counterid;  \
777 		i++;                                            \
778 	} while (0)
779 
780 	i = 0;
781 	SET_SIZESTATDESC(0, "requests received 0-15 bytes", "0-15", in);
782 	SET_SIZESTATDESC(16, "requests received 16-31 bytes", "16-31", in);
783 	SET_SIZESTATDESC(32, "requests received 32-47 bytes", "32-47", in);
784 	SET_SIZESTATDESC(48, "requests received 48-63 bytes", "48-63", in);
785 	SET_SIZESTATDESC(64, "requests received 64-79 bytes", "64-79", in);
786 	SET_SIZESTATDESC(80, "requests received 80-95 bytes", "80-95", in);
787 	SET_SIZESTATDESC(96, "requests received 96-111 bytes", "96-111", in);
788 	SET_SIZESTATDESC(112, "requests received 112-127 bytes", "112-127", in);
789 	SET_SIZESTATDESC(128, "requests received 128-143 bytes", "128-143", in);
790 	SET_SIZESTATDESC(144, "requests received 144-159 bytes", "144-159", in);
791 	SET_SIZESTATDESC(160, "requests received 160-175 bytes", "160-175", in);
792 	SET_SIZESTATDESC(176, "requests received 176-191 bytes", "176-191", in);
793 	SET_SIZESTATDESC(192, "requests received 192-207 bytes", "192-207", in);
794 	SET_SIZESTATDESC(208, "requests received 208-223 bytes", "208-223", in);
795 	SET_SIZESTATDESC(224, "requests received 224-239 bytes", "224-239", in);
796 	SET_SIZESTATDESC(240, "requests received 240-255 bytes", "240-255", in);
797 	SET_SIZESTATDESC(256, "requests received 256-271 bytes", "256-271", in);
798 	SET_SIZESTATDESC(272, "requests received 272-287 bytes", "272-287", in);
799 	SET_SIZESTATDESC(288, "requests received 288+ bytes", "288+", in);
800 	INSIST(i == dns_sizecounter_in_max);
801 
802 	i = 0;
803 	SET_SIZESTATDESC(0, "responses sent 0-15 bytes", "0-15", out);
804 	SET_SIZESTATDESC(16, "responses sent 16-31 bytes", "16-31", out);
805 	SET_SIZESTATDESC(32, "responses sent 32-47 bytes", "32-47", out);
806 	SET_SIZESTATDESC(48, "responses sent 48-63 bytes", "48-63", out);
807 	SET_SIZESTATDESC(64, "responses sent 64-79 bytes", "64-79", out);
808 	SET_SIZESTATDESC(80, "responses sent 80-95 bytes", "80-95", out);
809 	SET_SIZESTATDESC(96, "responses sent 96-111 bytes", "96-111", out);
810 	SET_SIZESTATDESC(112, "responses sent 112-127 bytes", "112-127", out);
811 	SET_SIZESTATDESC(128, "responses sent 128-143 bytes", "128-143", out);
812 	SET_SIZESTATDESC(144, "responses sent 144-159 bytes", "144-159", out);
813 	SET_SIZESTATDESC(160, "responses sent 160-175 bytes", "160-175", out);
814 	SET_SIZESTATDESC(176, "responses sent 176-191 bytes", "176-191", out);
815 	SET_SIZESTATDESC(192, "responses sent 192-207 bytes", "192-207", out);
816 	SET_SIZESTATDESC(208, "responses sent 208-223 bytes", "208-223", out);
817 	SET_SIZESTATDESC(224, "responses sent 224-239 bytes", "224-239", out);
818 	SET_SIZESTATDESC(240, "responses sent 240-255 bytes", "240-255", out);
819 	SET_SIZESTATDESC(256, "responses sent 256-271 bytes", "256-271", out);
820 	SET_SIZESTATDESC(272, "responses sent 272-287 bytes", "272-287", out);
821 	SET_SIZESTATDESC(288, "responses sent 288-303 bytes", "288-303", out);
822 	SET_SIZESTATDESC(304, "responses sent 304-319 bytes", "304-319", out);
823 	SET_SIZESTATDESC(320, "responses sent 320-335 bytes", "320-335", out);
824 	SET_SIZESTATDESC(336, "responses sent 336-351 bytes", "336-351", out);
825 	SET_SIZESTATDESC(352, "responses sent 352-367 bytes", "352-367", out);
826 	SET_SIZESTATDESC(368, "responses sent 368-383 bytes", "368-383", out);
827 	SET_SIZESTATDESC(384, "responses sent 384-399 bytes", "384-399", out);
828 	SET_SIZESTATDESC(400, "responses sent 400-415 bytes", "400-415", out);
829 	SET_SIZESTATDESC(416, "responses sent 416-431 bytes", "416-431", out);
830 	SET_SIZESTATDESC(432, "responses sent 432-447 bytes", "432-447", out);
831 	SET_SIZESTATDESC(448, "responses sent 448-463 bytes", "448-463", out);
832 	SET_SIZESTATDESC(464, "responses sent 464-479 bytes", "464-479", out);
833 	SET_SIZESTATDESC(480, "responses sent 480-495 bytes", "480-495", out);
834 	SET_SIZESTATDESC(496, "responses sent 496-511 bytes", "496-511", out);
835 	SET_SIZESTATDESC(512, "responses sent 512-527 bytes", "512-527", out);
836 	SET_SIZESTATDESC(528, "responses sent 528-543 bytes", "528-543", out);
837 	SET_SIZESTATDESC(544, "responses sent 544-559 bytes", "544-559", out);
838 	SET_SIZESTATDESC(560, "responses sent 560-575 bytes", "560-575", out);
839 	SET_SIZESTATDESC(576, "responses sent 576-591 bytes", "576-591", out);
840 	SET_SIZESTATDESC(592, "responses sent 592-607 bytes", "592-607", out);
841 	SET_SIZESTATDESC(608, "responses sent 608-623 bytes", "608-623", out);
842 	SET_SIZESTATDESC(624, "responses sent 624-639 bytes", "624-639", out);
843 	SET_SIZESTATDESC(640, "responses sent 640-655 bytes", "640-655", out);
844 	SET_SIZESTATDESC(656, "responses sent 656-671 bytes", "656-671", out);
845 	SET_SIZESTATDESC(672, "responses sent 672-687 bytes", "672-687", out);
846 	SET_SIZESTATDESC(688, "responses sent 688-703 bytes", "688-703", out);
847 	SET_SIZESTATDESC(704, "responses sent 704-719 bytes", "704-719", out);
848 	SET_SIZESTATDESC(720, "responses sent 720-735 bytes", "720-735", out);
849 	SET_SIZESTATDESC(736, "responses sent 736-751 bytes", "736-751", out);
850 	SET_SIZESTATDESC(752, "responses sent 752-767 bytes", "752-767", out);
851 	SET_SIZESTATDESC(768, "responses sent 768-783 bytes", "768-783", out);
852 	SET_SIZESTATDESC(784, "responses sent 784-799 bytes", "784-799", out);
853 	SET_SIZESTATDESC(800, "responses sent 800-815 bytes", "800-815", out);
854 	SET_SIZESTATDESC(816, "responses sent 816-831 bytes", "816-831", out);
855 	SET_SIZESTATDESC(832, "responses sent 832-847 bytes", "832-847", out);
856 	SET_SIZESTATDESC(848, "responses sent 848-863 bytes", "848-863", out);
857 	SET_SIZESTATDESC(864, "responses sent 864-879 bytes", "864-879", out);
858 	SET_SIZESTATDESC(880, "responses sent 880-895 bytes", "880-895", out);
859 	SET_SIZESTATDESC(896, "responses sent 896-911 bytes", "896-911", out);
860 	SET_SIZESTATDESC(912, "responses sent 912-927 bytes", "912-927", out);
861 	SET_SIZESTATDESC(928, "responses sent 928-943 bytes", "928-943", out);
862 	SET_SIZESTATDESC(944, "responses sent 944-959 bytes", "944-959", out);
863 	SET_SIZESTATDESC(960, "responses sent 960-975 bytes", "960-975", out);
864 	SET_SIZESTATDESC(976, "responses sent 976-991 bytes", "976-991", out);
865 	SET_SIZESTATDESC(992, "responses sent 992-1007 bytes", "992-1007", out);
866 	SET_SIZESTATDESC(1008, "responses sent 1008-1023 bytes", "1008-1023",
867 			 out);
868 	SET_SIZESTATDESC(1024, "responses sent 1024-1039 bytes", "1024-1039",
869 			 out);
870 	SET_SIZESTATDESC(1040, "responses sent 1040-1055 bytes", "1040-1055",
871 			 out);
872 	SET_SIZESTATDESC(1056, "responses sent 1056-1071 bytes", "1056-1071",
873 			 out);
874 	SET_SIZESTATDESC(1072, "responses sent 1072-1087 bytes", "1072-1087",
875 			 out);
876 	SET_SIZESTATDESC(1088, "responses sent 1088-1103 bytes", "1088-1103",
877 			 out);
878 	SET_SIZESTATDESC(1104, "responses sent 1104-1119 bytes", "1104-1119",
879 			 out);
880 	SET_SIZESTATDESC(1120, "responses sent 1120-1135 bytes", "1120-1135",
881 			 out);
882 	SET_SIZESTATDESC(1136, "responses sent 1136-1151 bytes", "1136-1151",
883 			 out);
884 	SET_SIZESTATDESC(1152, "responses sent 1152-1167 bytes", "1152-1167",
885 			 out);
886 	SET_SIZESTATDESC(1168, "responses sent 1168-1183 bytes", "1168-1183",
887 			 out);
888 	SET_SIZESTATDESC(1184, "responses sent 1184-1199 bytes", "1184-1199",
889 			 out);
890 	SET_SIZESTATDESC(1200, "responses sent 1200-1215 bytes", "1200-1215",
891 			 out);
892 	SET_SIZESTATDESC(1216, "responses sent 1216-1231 bytes", "1216-1231",
893 			 out);
894 	SET_SIZESTATDESC(1232, "responses sent 1232-1247 bytes", "1232-1247",
895 			 out);
896 	SET_SIZESTATDESC(1248, "responses sent 1248-1263 bytes", "1248-1263",
897 			 out);
898 	SET_SIZESTATDESC(1264, "responses sent 1264-1279 bytes", "1264-1279",
899 			 out);
900 	SET_SIZESTATDESC(1280, "responses sent 1280-1295 bytes", "1280-1295",
901 			 out);
902 	SET_SIZESTATDESC(1296, "responses sent 1296-1311 bytes", "1296-1311",
903 			 out);
904 	SET_SIZESTATDESC(1312, "responses sent 1312-1327 bytes", "1312-1327",
905 			 out);
906 	SET_SIZESTATDESC(1328, "responses sent 1328-1343 bytes", "1328-1343",
907 			 out);
908 	SET_SIZESTATDESC(1344, "responses sent 1344-1359 bytes", "1344-1359",
909 			 out);
910 	SET_SIZESTATDESC(1360, "responses sent 1360-1375 bytes", "1360-1375",
911 			 out);
912 	SET_SIZESTATDESC(1376, "responses sent 1376-1391 bytes", "1376-1391",
913 			 out);
914 	SET_SIZESTATDESC(1392, "responses sent 1392-1407 bytes", "1392-1407",
915 			 out);
916 	SET_SIZESTATDESC(1408, "responses sent 1408-1423 bytes", "1408-1423",
917 			 out);
918 	SET_SIZESTATDESC(1424, "responses sent 1424-1439 bytes", "1424-1439",
919 			 out);
920 	SET_SIZESTATDESC(1440, "responses sent 1440-1455 bytes", "1440-1455",
921 			 out);
922 	SET_SIZESTATDESC(1456, "responses sent 1456-1471 bytes", "1456-1471",
923 			 out);
924 	SET_SIZESTATDESC(1472, "responses sent 1472-1487 bytes", "1472-1487",
925 			 out);
926 	SET_SIZESTATDESC(1488, "responses sent 1488-1503 bytes", "1488-1503",
927 			 out);
928 	SET_SIZESTATDESC(1504, "responses sent 1504-1519 bytes", "1504-1519",
929 			 out);
930 	SET_SIZESTATDESC(1520, "responses sent 1520-1535 bytes", "1520-1535",
931 			 out);
932 	SET_SIZESTATDESC(1536, "responses sent 1536-1551 bytes", "1536-1551",
933 			 out);
934 	SET_SIZESTATDESC(1552, "responses sent 1552-1567 bytes", "1552-1567",
935 			 out);
936 	SET_SIZESTATDESC(1568, "responses sent 1568-1583 bytes", "1568-1583",
937 			 out);
938 	SET_SIZESTATDESC(1584, "responses sent 1584-1599 bytes", "1584-1599",
939 			 out);
940 	SET_SIZESTATDESC(1600, "responses sent 1600-1615 bytes", "1600-1615",
941 			 out);
942 	SET_SIZESTATDESC(1616, "responses sent 1616-1631 bytes", "1616-1631",
943 			 out);
944 	SET_SIZESTATDESC(1632, "responses sent 1632-1647 bytes", "1632-1647",
945 			 out);
946 	SET_SIZESTATDESC(1648, "responses sent 1648-1663 bytes", "1648-1663",
947 			 out);
948 	SET_SIZESTATDESC(1664, "responses sent 1664-1679 bytes", "1664-1679",
949 			 out);
950 	SET_SIZESTATDESC(1680, "responses sent 1680-1695 bytes", "1680-1695",
951 			 out);
952 	SET_SIZESTATDESC(1696, "responses sent 1696-1711 bytes", "1696-1711",
953 			 out);
954 	SET_SIZESTATDESC(1712, "responses sent 1712-1727 bytes", "1712-1727",
955 			 out);
956 	SET_SIZESTATDESC(1728, "responses sent 1728-1743 bytes", "1728-1743",
957 			 out);
958 	SET_SIZESTATDESC(1744, "responses sent 1744-1759 bytes", "1744-1759",
959 			 out);
960 	SET_SIZESTATDESC(1760, "responses sent 1760-1775 bytes", "1760-1775",
961 			 out);
962 	SET_SIZESTATDESC(1776, "responses sent 1776-1791 bytes", "1776-1791",
963 			 out);
964 	SET_SIZESTATDESC(1792, "responses sent 1792-1807 bytes", "1792-1807",
965 			 out);
966 	SET_SIZESTATDESC(1808, "responses sent 1808-1823 bytes", "1808-1823",
967 			 out);
968 	SET_SIZESTATDESC(1824, "responses sent 1824-1839 bytes", "1824-1839",
969 			 out);
970 	SET_SIZESTATDESC(1840, "responses sent 1840-1855 bytes", "1840-1855",
971 			 out);
972 	SET_SIZESTATDESC(1856, "responses sent 1856-1871 bytes", "1856-1871",
973 			 out);
974 	SET_SIZESTATDESC(1872, "responses sent 1872-1887 bytes", "1872-1887",
975 			 out);
976 	SET_SIZESTATDESC(1888, "responses sent 1888-1903 bytes", "1888-1903",
977 			 out);
978 	SET_SIZESTATDESC(1904, "responses sent 1904-1919 bytes", "1904-1919",
979 			 out);
980 	SET_SIZESTATDESC(1920, "responses sent 1920-1935 bytes", "1920-1935",
981 			 out);
982 	SET_SIZESTATDESC(1936, "responses sent 1936-1951 bytes", "1936-1951",
983 			 out);
984 	SET_SIZESTATDESC(1952, "responses sent 1952-1967 bytes", "1952-1967",
985 			 out);
986 	SET_SIZESTATDESC(1968, "responses sent 1968-1983 bytes", "1968-1983",
987 			 out);
988 	SET_SIZESTATDESC(1984, "responses sent 1984-1999 bytes", "1984-1999",
989 			 out);
990 	SET_SIZESTATDESC(2000, "responses sent 2000-2015 bytes", "2000-2015",
991 			 out);
992 	SET_SIZESTATDESC(2016, "responses sent 2016-2031 bytes", "2016-2031",
993 			 out);
994 	SET_SIZESTATDESC(2032, "responses sent 2032-2047 bytes", "2032-2047",
995 			 out);
996 	SET_SIZESTATDESC(2048, "responses sent 2048-2063 bytes", "2048-2063",
997 			 out);
998 	SET_SIZESTATDESC(2064, "responses sent 2064-2079 bytes", "2064-2079",
999 			 out);
1000 	SET_SIZESTATDESC(2080, "responses sent 2080-2095 bytes", "2080-2095",
1001 			 out);
1002 	SET_SIZESTATDESC(2096, "responses sent 2096-2111 bytes", "2096-2111",
1003 			 out);
1004 	SET_SIZESTATDESC(2112, "responses sent 2112-2127 bytes", "2112-2127",
1005 			 out);
1006 	SET_SIZESTATDESC(2128, "responses sent 2128-2143 bytes", "2128-2143",
1007 			 out);
1008 	SET_SIZESTATDESC(2144, "responses sent 2144-2159 bytes", "2144-2159",
1009 			 out);
1010 	SET_SIZESTATDESC(2160, "responses sent 2160-2175 bytes", "2160-2175",
1011 			 out);
1012 	SET_SIZESTATDESC(2176, "responses sent 2176-2191 bytes", "2176-2191",
1013 			 out);
1014 	SET_SIZESTATDESC(2192, "responses sent 2192-2207 bytes", "2192-2207",
1015 			 out);
1016 	SET_SIZESTATDESC(2208, "responses sent 2208-2223 bytes", "2208-2223",
1017 			 out);
1018 	SET_SIZESTATDESC(2224, "responses sent 2224-2239 bytes", "2224-2239",
1019 			 out);
1020 	SET_SIZESTATDESC(2240, "responses sent 2240-2255 bytes", "2240-2255",
1021 			 out);
1022 	SET_SIZESTATDESC(2256, "responses sent 2256-2271 bytes", "2256-2271",
1023 			 out);
1024 	SET_SIZESTATDESC(2272, "responses sent 2272-2287 bytes", "2272-2287",
1025 			 out);
1026 	SET_SIZESTATDESC(2288, "responses sent 2288-2303 bytes", "2288-2303",
1027 			 out);
1028 	SET_SIZESTATDESC(2304, "responses sent 2304-2319 bytes", "2304-2319",
1029 			 out);
1030 	SET_SIZESTATDESC(2320, "responses sent 2320-2335 bytes", "2320-2335",
1031 			 out);
1032 	SET_SIZESTATDESC(2336, "responses sent 2336-2351 bytes", "2336-2351",
1033 			 out);
1034 	SET_SIZESTATDESC(2352, "responses sent 2352-2367 bytes", "2352-2367",
1035 			 out);
1036 	SET_SIZESTATDESC(2368, "responses sent 2368-2383 bytes", "2368-2383",
1037 			 out);
1038 	SET_SIZESTATDESC(2384, "responses sent 2384-2399 bytes", "2384-2399",
1039 			 out);
1040 	SET_SIZESTATDESC(2400, "responses sent 2400-2415 bytes", "2400-2415",
1041 			 out);
1042 	SET_SIZESTATDESC(2416, "responses sent 2416-2431 bytes", "2416-2431",
1043 			 out);
1044 	SET_SIZESTATDESC(2432, "responses sent 2432-2447 bytes", "2432-2447",
1045 			 out);
1046 	SET_SIZESTATDESC(2448, "responses sent 2448-2463 bytes", "2448-2463",
1047 			 out);
1048 	SET_SIZESTATDESC(2464, "responses sent 2464-2479 bytes", "2464-2479",
1049 			 out);
1050 	SET_SIZESTATDESC(2480, "responses sent 2480-2495 bytes", "2480-2495",
1051 			 out);
1052 	SET_SIZESTATDESC(2496, "responses sent 2496-2511 bytes", "2496-2511",
1053 			 out);
1054 	SET_SIZESTATDESC(2512, "responses sent 2512-2527 bytes", "2512-2527",
1055 			 out);
1056 	SET_SIZESTATDESC(2528, "responses sent 2528-2543 bytes", "2528-2543",
1057 			 out);
1058 	SET_SIZESTATDESC(2544, "responses sent 2544-2559 bytes", "2544-2559",
1059 			 out);
1060 	SET_SIZESTATDESC(2560, "responses sent 2560-2575 bytes", "2560-2575",
1061 			 out);
1062 	SET_SIZESTATDESC(2576, "responses sent 2576-2591 bytes", "2576-2591",
1063 			 out);
1064 	SET_SIZESTATDESC(2592, "responses sent 2592-2607 bytes", "2592-2607",
1065 			 out);
1066 	SET_SIZESTATDESC(2608, "responses sent 2608-2623 bytes", "2608-2623",
1067 			 out);
1068 	SET_SIZESTATDESC(2624, "responses sent 2624-2639 bytes", "2624-2639",
1069 			 out);
1070 	SET_SIZESTATDESC(2640, "responses sent 2640-2655 bytes", "2640-2655",
1071 			 out);
1072 	SET_SIZESTATDESC(2656, "responses sent 2656-2671 bytes", "2656-2671",
1073 			 out);
1074 	SET_SIZESTATDESC(2672, "responses sent 2672-2687 bytes", "2672-2687",
1075 			 out);
1076 	SET_SIZESTATDESC(2688, "responses sent 2688-2703 bytes", "2688-2703",
1077 			 out);
1078 	SET_SIZESTATDESC(2704, "responses sent 2704-2719 bytes", "2704-2719",
1079 			 out);
1080 	SET_SIZESTATDESC(2720, "responses sent 2720-2735 bytes", "2720-2735",
1081 			 out);
1082 	SET_SIZESTATDESC(2736, "responses sent 2736-2751 bytes", "2736-2751",
1083 			 out);
1084 	SET_SIZESTATDESC(2752, "responses sent 2752-2767 bytes", "2752-2767",
1085 			 out);
1086 	SET_SIZESTATDESC(2768, "responses sent 2768-2783 bytes", "2768-2783",
1087 			 out);
1088 	SET_SIZESTATDESC(2784, "responses sent 2784-2799 bytes", "2784-2799",
1089 			 out);
1090 	SET_SIZESTATDESC(2800, "responses sent 2800-2815 bytes", "2800-2815",
1091 			 out);
1092 	SET_SIZESTATDESC(2816, "responses sent 2816-2831 bytes", "2816-2831",
1093 			 out);
1094 	SET_SIZESTATDESC(2832, "responses sent 2832-2847 bytes", "2832-2847",
1095 			 out);
1096 	SET_SIZESTATDESC(2848, "responses sent 2848-2863 bytes", "2848-2863",
1097 			 out);
1098 	SET_SIZESTATDESC(2864, "responses sent 2864-2879 bytes", "2864-2879",
1099 			 out);
1100 	SET_SIZESTATDESC(2880, "responses sent 2880-2895 bytes", "2880-2895",
1101 			 out);
1102 	SET_SIZESTATDESC(2896, "responses sent 2896-2911 bytes", "2896-2911",
1103 			 out);
1104 	SET_SIZESTATDESC(2912, "responses sent 2912-2927 bytes", "2912-2927",
1105 			 out);
1106 	SET_SIZESTATDESC(2928, "responses sent 2928-2943 bytes", "2928-2943",
1107 			 out);
1108 	SET_SIZESTATDESC(2944, "responses sent 2944-2959 bytes", "2944-2959",
1109 			 out);
1110 	SET_SIZESTATDESC(2960, "responses sent 2960-2975 bytes", "2960-2975",
1111 			 out);
1112 	SET_SIZESTATDESC(2976, "responses sent 2976-2991 bytes", "2976-2991",
1113 			 out);
1114 	SET_SIZESTATDESC(2992, "responses sent 2992-3007 bytes", "2992-3007",
1115 			 out);
1116 	SET_SIZESTATDESC(3008, "responses sent 3008-3023 bytes", "3008-3023",
1117 			 out);
1118 	SET_SIZESTATDESC(3024, "responses sent 3024-3039 bytes", "3024-3039",
1119 			 out);
1120 	SET_SIZESTATDESC(3040, "responses sent 3040-3055 bytes", "3040-3055",
1121 			 out);
1122 	SET_SIZESTATDESC(3056, "responses sent 3056-3071 bytes", "3056-3071",
1123 			 out);
1124 	SET_SIZESTATDESC(3072, "responses sent 3072-3087 bytes", "3072-3087",
1125 			 out);
1126 	SET_SIZESTATDESC(3088, "responses sent 3088-3103 bytes", "3088-3103",
1127 			 out);
1128 	SET_SIZESTATDESC(3104, "responses sent 3104-3119 bytes", "3104-3119",
1129 			 out);
1130 	SET_SIZESTATDESC(3120, "responses sent 3120-3135 bytes", "3120-3135",
1131 			 out);
1132 	SET_SIZESTATDESC(3136, "responses sent 3136-3151 bytes", "3136-3151",
1133 			 out);
1134 	SET_SIZESTATDESC(3152, "responses sent 3152-3167 bytes", "3152-3167",
1135 			 out);
1136 	SET_SIZESTATDESC(3168, "responses sent 3168-3183 bytes", "3168-3183",
1137 			 out);
1138 	SET_SIZESTATDESC(3184, "responses sent 3184-3199 bytes", "3184-3199",
1139 			 out);
1140 	SET_SIZESTATDESC(3200, "responses sent 3200-3215 bytes", "3200-3215",
1141 			 out);
1142 	SET_SIZESTATDESC(3216, "responses sent 3216-3231 bytes", "3216-3231",
1143 			 out);
1144 	SET_SIZESTATDESC(3232, "responses sent 3232-3247 bytes", "3232-3247",
1145 			 out);
1146 	SET_SIZESTATDESC(3248, "responses sent 3248-3263 bytes", "3248-3263",
1147 			 out);
1148 	SET_SIZESTATDESC(3264, "responses sent 3264-3279 bytes", "3264-3279",
1149 			 out);
1150 	SET_SIZESTATDESC(3280, "responses sent 3280-3295 bytes", "3280-3295",
1151 			 out);
1152 	SET_SIZESTATDESC(3296, "responses sent 3296-3311 bytes", "3296-3311",
1153 			 out);
1154 	SET_SIZESTATDESC(3312, "responses sent 3312-3327 bytes", "3312-3327",
1155 			 out);
1156 	SET_SIZESTATDESC(3328, "responses sent 3328-3343 bytes", "3328-3343",
1157 			 out);
1158 	SET_SIZESTATDESC(3344, "responses sent 3344-3359 bytes", "3344-3359",
1159 			 out);
1160 	SET_SIZESTATDESC(3360, "responses sent 3360-3375 bytes", "3360-3375",
1161 			 out);
1162 	SET_SIZESTATDESC(3376, "responses sent 3376-3391 bytes", "3376-3391",
1163 			 out);
1164 	SET_SIZESTATDESC(3392, "responses sent 3392-3407 bytes", "3392-3407",
1165 			 out);
1166 	SET_SIZESTATDESC(3408, "responses sent 3408-3423 bytes", "3408-3423",
1167 			 out);
1168 	SET_SIZESTATDESC(3424, "responses sent 3424-3439 bytes", "3424-3439",
1169 			 out);
1170 	SET_SIZESTATDESC(3440, "responses sent 3440-3455 bytes", "3440-3455",
1171 			 out);
1172 	SET_SIZESTATDESC(3456, "responses sent 3456-3471 bytes", "3456-3471",
1173 			 out);
1174 	SET_SIZESTATDESC(3472, "responses sent 3472-3487 bytes", "3472-3487",
1175 			 out);
1176 	SET_SIZESTATDESC(3488, "responses sent 3488-3503 bytes", "3488-3503",
1177 			 out);
1178 	SET_SIZESTATDESC(3504, "responses sent 3504-3519 bytes", "3504-3519",
1179 			 out);
1180 	SET_SIZESTATDESC(3520, "responses sent 3520-3535 bytes", "3520-3535",
1181 			 out);
1182 	SET_SIZESTATDESC(3536, "responses sent 3536-3551 bytes", "3536-3551",
1183 			 out);
1184 	SET_SIZESTATDESC(3552, "responses sent 3552-3567 bytes", "3552-3567",
1185 			 out);
1186 	SET_SIZESTATDESC(3568, "responses sent 3568-3583 bytes", "3568-3583",
1187 			 out);
1188 	SET_SIZESTATDESC(3584, "responses sent 3584-3599 bytes", "3584-3599",
1189 			 out);
1190 	SET_SIZESTATDESC(3600, "responses sent 3600-3615 bytes", "3600-3615",
1191 			 out);
1192 	SET_SIZESTATDESC(3616, "responses sent 3616-3631 bytes", "3616-3631",
1193 			 out);
1194 	SET_SIZESTATDESC(3632, "responses sent 3632-3647 bytes", "3632-3647",
1195 			 out);
1196 	SET_SIZESTATDESC(3648, "responses sent 3648-3663 bytes", "3648-3663",
1197 			 out);
1198 	SET_SIZESTATDESC(3664, "responses sent 3664-3679 bytes", "3664-3679",
1199 			 out);
1200 	SET_SIZESTATDESC(3680, "responses sent 3680-3695 bytes", "3680-3695",
1201 			 out);
1202 	SET_SIZESTATDESC(3696, "responses sent 3696-3711 bytes", "3696-3711",
1203 			 out);
1204 	SET_SIZESTATDESC(3712, "responses sent 3712-3727 bytes", "3712-3727",
1205 			 out);
1206 	SET_SIZESTATDESC(3728, "responses sent 3728-3743 bytes", "3728-3743",
1207 			 out);
1208 	SET_SIZESTATDESC(3744, "responses sent 3744-3759 bytes", "3744-3759",
1209 			 out);
1210 	SET_SIZESTATDESC(3760, "responses sent 3760-3775 bytes", "3760-3775",
1211 			 out);
1212 	SET_SIZESTATDESC(3776, "responses sent 3776-3791 bytes", "3776-3791",
1213 			 out);
1214 	SET_SIZESTATDESC(3792, "responses sent 3792-3807 bytes", "3792-3807",
1215 			 out);
1216 	SET_SIZESTATDESC(3808, "responses sent 3808-3823 bytes", "3808-3823",
1217 			 out);
1218 	SET_SIZESTATDESC(3824, "responses sent 3824-3839 bytes", "3824-3839",
1219 			 out);
1220 	SET_SIZESTATDESC(3840, "responses sent 3840-3855 bytes", "3840-3855",
1221 			 out);
1222 	SET_SIZESTATDESC(3856, "responses sent 3856-3871 bytes", "3856-3871",
1223 			 out);
1224 	SET_SIZESTATDESC(3872, "responses sent 3872-3887 bytes", "3872-3887",
1225 			 out);
1226 	SET_SIZESTATDESC(3888, "responses sent 3888-3903 bytes", "3888-3903",
1227 			 out);
1228 	SET_SIZESTATDESC(3904, "responses sent 3904-3919 bytes", "3904-3919",
1229 			 out);
1230 	SET_SIZESTATDESC(3920, "responses sent 3920-3935 bytes", "3920-3935",
1231 			 out);
1232 	SET_SIZESTATDESC(3936, "responses sent 3936-3951 bytes", "3936-3951",
1233 			 out);
1234 	SET_SIZESTATDESC(3952, "responses sent 3952-3967 bytes", "3952-3967",
1235 			 out);
1236 	SET_SIZESTATDESC(3968, "responses sent 3968-3983 bytes", "3968-3983",
1237 			 out);
1238 	SET_SIZESTATDESC(3984, "responses sent 3984-3999 bytes", "3984-3999",
1239 			 out);
1240 	SET_SIZESTATDESC(4000, "responses sent 4000-4015 bytes", "4000-4015",
1241 			 out);
1242 	SET_SIZESTATDESC(4016, "responses sent 4016-4031 bytes", "4016-4031",
1243 			 out);
1244 	SET_SIZESTATDESC(4032, "responses sent 4032-4047 bytes", "4032-4047",
1245 			 out);
1246 	SET_SIZESTATDESC(4048, "responses sent 4048-4063 bytes", "4048-4063",
1247 			 out);
1248 	SET_SIZESTATDESC(4064, "responses sent 4064-4079 bytes", "4064-4079",
1249 			 out);
1250 	SET_SIZESTATDESC(4080, "responses sent 4080-4095 bytes", "4080-4095",
1251 			 out);
1252 	SET_SIZESTATDESC(4096, "responses sent 4096+ bytes", "4096+", out);
1253 	INSIST(i == dns_sizecounter_out_max);
1254 
1255 	/* Sanity check */
1256 	for (i = 0; i < ns_statscounter_max; i++) {
1257 		INSIST(nsstats_desc[i] != NULL);
1258 	}
1259 	for (i = 0; i < dns_resstatscounter_max; i++) {
1260 		INSIST(resstats_desc[i] != NULL);
1261 	}
1262 	for (i = 0; i < dns_adbstats_max; i++) {
1263 		INSIST(adbstats_desc[i] != NULL);
1264 	}
1265 	for (i = 0; i < dns_zonestatscounter_max; i++) {
1266 		INSIST(zonestats_desc[i] != NULL);
1267 	}
1268 	for (i = 0; i < isc_sockstatscounter_max; i++) {
1269 		INSIST(sockstats_desc[i] != NULL);
1270 	}
1271 	for (i = 0; i < dns_dnssecstats_max; i++) {
1272 		INSIST(dnssecstats_desc[i] != NULL);
1273 	}
1274 	for (i = 0; i < dns_sizecounter_in_max; i++) {
1275 		INSIST(udpinsizestats_desc[i] != NULL);
1276 		INSIST(tcpinsizestats_desc[i] != NULL);
1277 	}
1278 	for (i = 0; i < dns_sizecounter_out_max; i++) {
1279 		INSIST(udpoutsizestats_desc[i] != NULL);
1280 		INSIST(tcpoutsizestats_desc[i] != NULL);
1281 	}
1282 #if defined(EXTENDED_STATS)
1283 	for (i = 0; i < ns_statscounter_max; i++) {
1284 		INSIST(nsstats_xmldesc[i] != NULL);
1285 	}
1286 	for (i = 0; i < dns_resstatscounter_max; i++) {
1287 		INSIST(resstats_xmldesc[i] != NULL);
1288 	}
1289 	for (i = 0; i < dns_adbstats_max; i++) {
1290 		INSIST(adbstats_xmldesc[i] != NULL);
1291 	}
1292 	for (i = 0; i < dns_zonestatscounter_max; i++) {
1293 		INSIST(zonestats_xmldesc[i] != NULL);
1294 	}
1295 	for (i = 0; i < isc_sockstatscounter_max; i++) {
1296 		INSIST(sockstats_xmldesc[i] != NULL);
1297 	}
1298 	for (i = 0; i < dns_dnssecstats_max; i++) {
1299 		INSIST(dnssecstats_xmldesc[i] != NULL);
1300 	}
1301 	for (i = 0; i < dns_sizecounter_in_max; i++) {
1302 		INSIST(udpinsizestats_xmldesc[i] != NULL);
1303 		INSIST(tcpinsizestats_xmldesc[i] != NULL);
1304 	}
1305 	for (i = 0; i < dns_sizecounter_out_max; i++) {
1306 		INSIST(udpoutsizestats_xmldesc[i] != NULL);
1307 		INSIST(tcpoutsizestats_xmldesc[i] != NULL);
1308 	}
1309 #endif /* if defined(EXTENDED_STATS) */
1310 }
1311 
1312 /*%
1313  * Dump callback functions.
1314  */
1315 static void
1316 generalstat_dump(isc_statscounter_t counter, uint64_t val, void *arg) {
1317 	stats_dumparg_t *dumparg = arg;
1318 
1319 	REQUIRE(counter < dumparg->ncounters);
1320 	dumparg->countervalues[counter] = val;
1321 }
1322 
1323 static isc_result_t
1324 dump_counters(isc_stats_t *stats, isc_statsformat_t type, void *arg,
1325 	      const char *category, const char **desc, int ncounters,
1326 	      int *indices, uint64_t *values, int options) {
1327 	int i, idx;
1328 	uint64_t value;
1329 	stats_dumparg_t dumparg;
1330 	FILE *fp;
1331 #ifdef HAVE_LIBXML2
1332 	void *writer;
1333 	int xmlrc;
1334 #endif /* ifdef HAVE_LIBXML2 */
1335 #ifdef HAVE_JSON_C
1336 	json_object *job, *cat, *counter;
1337 #endif /* ifdef HAVE_JSON_C */
1338 
1339 #if !defined(EXTENDED_STATS)
1340 	UNUSED(category);
1341 #endif /* if !defined(EXTENDED_STATS) */
1342 
1343 	dumparg.type = type;
1344 	dumparg.ncounters = ncounters;
1345 	dumparg.counterindices = indices;
1346 	dumparg.countervalues = values;
1347 
1348 	memset(values, 0, sizeof(values[0]) * ncounters);
1349 	isc_stats_dump(stats, generalstat_dump, &dumparg, options);
1350 
1351 #ifdef HAVE_JSON_C
1352 	cat = job = (json_object *)arg;
1353 	if (ncounters > 0 && type == isc_statsformat_json) {
1354 		if (category != NULL) {
1355 			cat = json_object_new_object();
1356 			if (cat == NULL) {
1357 				return (ISC_R_NOMEMORY);
1358 			}
1359 			json_object_object_add(job, category, cat);
1360 		}
1361 	}
1362 #endif /* ifdef HAVE_JSON_C */
1363 
1364 	for (i = 0; i < ncounters; i++) {
1365 		idx = indices[i];
1366 		value = values[idx];
1367 
1368 		if (value == 0 && (options & ISC_STATSDUMP_VERBOSE) == 0) {
1369 			continue;
1370 		}
1371 
1372 		switch (dumparg.type) {
1373 		case isc_statsformat_file:
1374 			fp = arg;
1375 			fprintf(fp, "%20" PRIu64 " %s\n", value, desc[idx]);
1376 			break;
1377 		case isc_statsformat_xml:
1378 #ifdef HAVE_LIBXML2
1379 			writer = arg;
1380 
1381 			if (category != NULL) {
1382 				/* <NameOfCategory> */
1383 				TRY0(xmlTextWriterStartElement(
1384 					writer, ISC_XMLCHAR category));
1385 
1386 				/* <name> inside category */
1387 				TRY0(xmlTextWriterStartElement(
1388 					writer, ISC_XMLCHAR "name"));
1389 				TRY0(xmlTextWriterWriteString(
1390 					writer, ISC_XMLCHAR desc[idx]));
1391 				TRY0(xmlTextWriterEndElement(writer));
1392 				/* </name> */
1393 
1394 				/* <counter> */
1395 				TRY0(xmlTextWriterStartElement(
1396 					writer, ISC_XMLCHAR "counter"));
1397 				TRY0(xmlTextWriterWriteFormatString(
1398 					writer, "%" PRIu64, value));
1399 
1400 				TRY0(xmlTextWriterEndElement(writer));
1401 				/* </counter> */
1402 				TRY0(xmlTextWriterEndElement(writer));
1403 				/* </NameOfCategory> */
1404 			} else {
1405 				TRY0(xmlTextWriterStartElement(
1406 					writer, ISC_XMLCHAR "counter"));
1407 				TRY0(xmlTextWriterWriteAttribute(
1408 					writer, ISC_XMLCHAR "name",
1409 					ISC_XMLCHAR desc[idx]));
1410 				TRY0(xmlTextWriterWriteFormatString(
1411 					writer, "%" PRIu64, value));
1412 				TRY0(xmlTextWriterEndElement(writer));
1413 				/* counter */
1414 			}
1415 
1416 #endif /* ifdef HAVE_LIBXML2 */
1417 			break;
1418 		case isc_statsformat_json:
1419 #ifdef HAVE_JSON_C
1420 			counter = json_object_new_int64(value);
1421 			if (counter == NULL) {
1422 				return (ISC_R_NOMEMORY);
1423 			}
1424 			json_object_object_add(cat, desc[idx], counter);
1425 #endif /* ifdef HAVE_JSON_C */
1426 			break;
1427 		}
1428 	}
1429 	return (ISC_R_SUCCESS);
1430 #ifdef HAVE_LIBXML2
1431 error:
1432 	isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
1433 		      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
1434 		      "failed at dump_counters()");
1435 	return (ISC_R_FAILURE);
1436 #endif /* ifdef HAVE_LIBXML2 */
1437 }
1438 
1439 static void
1440 rdtypestat_dump(dns_rdatastatstype_t type, uint64_t val, void *arg) {
1441 	char typebuf[64];
1442 	const char *typestr;
1443 	stats_dumparg_t *dumparg = arg;
1444 	FILE *fp;
1445 #ifdef HAVE_LIBXML2
1446 	void *writer;
1447 	int xmlrc;
1448 #endif /* ifdef HAVE_LIBXML2 */
1449 #ifdef HAVE_JSON_C
1450 	json_object *zoneobj, *obj;
1451 #endif /* ifdef HAVE_JSON_C */
1452 
1453 	if ((DNS_RDATASTATSTYPE_ATTR(type) &
1454 	     DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) == 0) {
1455 		dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf,
1456 				     sizeof(typebuf));
1457 		typestr = typebuf;
1458 	} else {
1459 		typestr = "Others";
1460 	}
1461 
1462 	switch (dumparg->type) {
1463 	case isc_statsformat_file:
1464 		fp = dumparg->arg;
1465 		fprintf(fp, "%20" PRIu64 " %s\n", val, typestr);
1466 		break;
1467 	case isc_statsformat_xml:
1468 #ifdef HAVE_LIBXML2
1469 		writer = dumparg->arg;
1470 
1471 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter"));
1472 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
1473 						 ISC_XMLCHAR typestr));
1474 
1475 		TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val));
1476 
1477 		TRY0(xmlTextWriterEndElement(writer)); /* type */
1478 #endif						       /* ifdef HAVE_LIBXML2 */
1479 		break;
1480 	case isc_statsformat_json:
1481 #ifdef HAVE_JSON_C
1482 		zoneobj = (json_object *)dumparg->arg;
1483 		obj = json_object_new_int64(val);
1484 		if (obj == NULL) {
1485 			return;
1486 		}
1487 		json_object_object_add(zoneobj, typestr, obj);
1488 #endif /* ifdef HAVE_JSON_C */
1489 		break;
1490 	}
1491 	return;
1492 #ifdef HAVE_LIBXML2
1493 error:
1494 	isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
1495 		      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
1496 		      "failed at rdtypestat_dump()");
1497 	dumparg->result = ISC_R_FAILURE;
1498 	return;
1499 #endif /* ifdef HAVE_LIBXML2 */
1500 }
1501 
1502 static bool
1503 rdatastatstype_attr(dns_rdatastatstype_t type, unsigned int attr) {
1504 	return ((DNS_RDATASTATSTYPE_ATTR(type) & attr) != 0);
1505 }
1506 
1507 static void
1508 rdatasetstats_dump(dns_rdatastatstype_t type, uint64_t val, void *arg) {
1509 	stats_dumparg_t *dumparg = arg;
1510 	FILE *fp;
1511 	char typebuf[64];
1512 	const char *typestr;
1513 	bool nxrrset = false;
1514 	bool stale = false;
1515 	bool ancient = false;
1516 #ifdef HAVE_LIBXML2
1517 	void *writer;
1518 	int xmlrc;
1519 #endif /* ifdef HAVE_LIBXML2 */
1520 #ifdef HAVE_JSON_C
1521 	json_object *zoneobj, *obj;
1522 	char buf[1024];
1523 #endif /* ifdef HAVE_JSON_C */
1524 
1525 	if ((DNS_RDATASTATSTYPE_ATTR(type) &
1526 	     DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) != 0) {
1527 		typestr = "NXDOMAIN";
1528 	} else if ((DNS_RDATASTATSTYPE_ATTR(type) &
1529 		    DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) != 0)
1530 	{
1531 		typestr = "Others";
1532 	} else {
1533 		dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf,
1534 				     sizeof(typebuf));
1535 		typestr = typebuf;
1536 	}
1537 
1538 	nxrrset = rdatastatstype_attr(type, DNS_RDATASTATSTYPE_ATTR_NXRRSET);
1539 	stale = rdatastatstype_attr(type, DNS_RDATASTATSTYPE_ATTR_STALE);
1540 	ancient = rdatastatstype_attr(type, DNS_RDATASTATSTYPE_ATTR_ANCIENT);
1541 
1542 	switch (dumparg->type) {
1543 	case isc_statsformat_file:
1544 		fp = dumparg->arg;
1545 		fprintf(fp, "%20" PRIu64 " %s%s%s%s\n", val, ancient ? "~" : "",
1546 			stale ? "#" : "", nxrrset ? "!" : "", typestr);
1547 		break;
1548 	case isc_statsformat_xml:
1549 #ifdef HAVE_LIBXML2
1550 		writer = dumparg->arg;
1551 
1552 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "rrset"));
1553 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "name"));
1554 		TRY0(xmlTextWriterWriteFormatString(
1555 			writer, "%s%s%s%s", ancient ? "~" : "",
1556 			stale ? "#" : "", nxrrset ? "!" : "", typestr));
1557 		TRY0(xmlTextWriterEndElement(writer)); /* name */
1558 
1559 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter"));
1560 		TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val));
1561 		TRY0(xmlTextWriterEndElement(writer)); /* counter */
1562 
1563 		TRY0(xmlTextWriterEndElement(writer)); /* rrset */
1564 #endif						       /* ifdef HAVE_LIBXML2 */
1565 		break;
1566 	case isc_statsformat_json:
1567 #ifdef HAVE_JSON_C
1568 		zoneobj = (json_object *)dumparg->arg;
1569 		snprintf(buf, sizeof(buf), "%s%s%s%s", ancient ? "~" : "",
1570 			 stale ? "#" : "", nxrrset ? "!" : "", typestr);
1571 		obj = json_object_new_int64(val);
1572 		if (obj == NULL) {
1573 			return;
1574 		}
1575 		json_object_object_add(zoneobj, buf, obj);
1576 #endif /* ifdef HAVE_JSON_C */
1577 		break;
1578 	}
1579 	return;
1580 #ifdef HAVE_LIBXML2
1581 error:
1582 	isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
1583 		      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
1584 		      "failed at rdatasetstats_dump()");
1585 	dumparg->result = ISC_R_FAILURE;
1586 #endif /* ifdef HAVE_LIBXML2 */
1587 }
1588 
1589 static void
1590 opcodestat_dump(dns_opcode_t code, uint64_t val, void *arg) {
1591 	FILE *fp;
1592 	isc_buffer_t b;
1593 	char codebuf[64];
1594 	stats_dumparg_t *dumparg = arg;
1595 #ifdef HAVE_LIBXML2
1596 	void *writer;
1597 	int xmlrc;
1598 #endif /* ifdef HAVE_LIBXML2 */
1599 #ifdef HAVE_JSON_C
1600 	json_object *zoneobj, *obj;
1601 #endif /* ifdef HAVE_JSON_C */
1602 
1603 	isc_buffer_init(&b, codebuf, sizeof(codebuf) - 1);
1604 	dns_opcode_totext(code, &b);
1605 	codebuf[isc_buffer_usedlength(&b)] = '\0';
1606 
1607 	switch (dumparg->type) {
1608 	case isc_statsformat_file:
1609 		fp = dumparg->arg;
1610 		fprintf(fp, "%20" PRIu64 " %s\n", val, codebuf);
1611 		break;
1612 	case isc_statsformat_xml:
1613 #ifdef HAVE_LIBXML2
1614 		writer = dumparg->arg;
1615 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter"));
1616 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
1617 						 ISC_XMLCHAR codebuf));
1618 		TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val));
1619 		TRY0(xmlTextWriterEndElement(writer)); /* counter */
1620 #endif						       /* ifdef HAVE_LIBXML2 */
1621 		break;
1622 	case isc_statsformat_json:
1623 #ifdef HAVE_JSON_C
1624 		zoneobj = (json_object *)dumparg->arg;
1625 		obj = json_object_new_int64(val);
1626 		if (obj == NULL) {
1627 			return;
1628 		}
1629 		json_object_object_add(zoneobj, codebuf, obj);
1630 #endif /* ifdef HAVE_JSON_C */
1631 		break;
1632 	}
1633 	return;
1634 
1635 #ifdef HAVE_LIBXML2
1636 error:
1637 	isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
1638 		      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
1639 		      "failed at opcodestat_dump()");
1640 	dumparg->result = ISC_R_FAILURE;
1641 	return;
1642 #endif /* ifdef HAVE_LIBXML2 */
1643 }
1644 
1645 static void
1646 rcodestat_dump(dns_rcode_t code, uint64_t val, void *arg) {
1647 	FILE *fp;
1648 	isc_buffer_t b;
1649 	char codebuf[64];
1650 	stats_dumparg_t *dumparg = arg;
1651 #ifdef HAVE_LIBXML2
1652 	void *writer;
1653 	int xmlrc;
1654 #endif /* ifdef HAVE_LIBXML2 */
1655 #ifdef HAVE_JSON_C
1656 	json_object *zoneobj, *obj;
1657 #endif /* ifdef HAVE_JSON_C */
1658 
1659 	isc_buffer_init(&b, codebuf, sizeof(codebuf) - 1);
1660 	dns_rcode_totext(code, &b);
1661 	codebuf[isc_buffer_usedlength(&b)] = '\0';
1662 
1663 	switch (dumparg->type) {
1664 	case isc_statsformat_file:
1665 		fp = dumparg->arg;
1666 		fprintf(fp, "%20" PRIu64 " %s\n", val, codebuf);
1667 		break;
1668 	case isc_statsformat_xml:
1669 #ifdef HAVE_LIBXML2
1670 		writer = dumparg->arg;
1671 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter"));
1672 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
1673 						 ISC_XMLCHAR codebuf));
1674 		TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val));
1675 		TRY0(xmlTextWriterEndElement(writer)); /* counter */
1676 #endif						       /* ifdef HAVE_LIBXML2 */
1677 		break;
1678 	case isc_statsformat_json:
1679 #ifdef HAVE_JSON_C
1680 		zoneobj = (json_object *)dumparg->arg;
1681 		obj = json_object_new_int64(val);
1682 		if (obj == NULL) {
1683 			return;
1684 		}
1685 		json_object_object_add(zoneobj, codebuf, obj);
1686 #endif /* ifdef HAVE_JSON_C */
1687 		break;
1688 	}
1689 	return;
1690 
1691 #ifdef HAVE_LIBXML2
1692 error:
1693 	isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
1694 		      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
1695 		      "failed at rcodestat_dump()");
1696 	dumparg->result = ISC_R_FAILURE;
1697 	return;
1698 #endif /* ifdef HAVE_LIBXML2 */
1699 }
1700 
1701 #if defined(EXTENDED_STATS)
1702 static void
1703 dnssecsignstat_dump(dns_keytag_t tag, uint64_t val, void *arg) {
1704 	FILE *fp;
1705 	char tagbuf[64];
1706 	stats_dumparg_t *dumparg = arg;
1707 #ifdef HAVE_LIBXML2
1708 	xmlTextWriterPtr writer;
1709 	int xmlrc;
1710 #endif /* ifdef HAVE_LIBXML2 */
1711 #ifdef HAVE_JSON_C
1712 	json_object *zoneobj, *obj;
1713 #endif /* ifdef HAVE_JSON_C */
1714 
1715 	snprintf(tagbuf, sizeof(tagbuf), "%u", tag);
1716 
1717 	switch (dumparg->type) {
1718 	case isc_statsformat_file:
1719 		fp = dumparg->arg;
1720 		fprintf(fp, "%20" PRIu64 " %s\n", val, tagbuf);
1721 		break;
1722 	case isc_statsformat_xml:
1723 #ifdef HAVE_LIBXML2
1724 		writer = dumparg->arg;
1725 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter"));
1726 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
1727 						 ISC_XMLCHAR tagbuf));
1728 		TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val));
1729 		TRY0(xmlTextWriterEndElement(writer)); /* counter */
1730 #endif						       /* ifdef HAVE_LIBXML2 */
1731 		break;
1732 	case isc_statsformat_json:
1733 #ifdef HAVE_JSON_C
1734 		zoneobj = (json_object *)dumparg->arg;
1735 		obj = json_object_new_int64(val);
1736 		if (obj == NULL) {
1737 			return;
1738 		}
1739 		json_object_object_add(zoneobj, tagbuf, obj);
1740 #endif /* ifdef HAVE_JSON_C */
1741 		break;
1742 	}
1743 	return;
1744 #ifdef HAVE_LIBXML2
1745 error:
1746 	isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
1747 		      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
1748 		      "failed at dnssecsignstat_dump()");
1749 	dumparg->result = ISC_R_FAILURE;
1750 	return;
1751 #endif /* ifdef HAVE_LIBXML2 */
1752 }
1753 #endif /* defined(EXTENDED_STATS) */
1754 
1755 #ifdef HAVE_LIBXML2
1756 /*
1757  * Which statistics to include when rendering to XML
1758  */
1759 #define STATS_XML_STATUS  0x00 /* display only common statistics */
1760 #define STATS_XML_SERVER  0x01
1761 #define STATS_XML_ZONES	  0x02
1762 #define STATS_XML_TASKS	  0x04
1763 #define STATS_XML_NET	  0x08
1764 #define STATS_XML_MEM	  0x10
1765 #define STATS_XML_TRAFFIC 0x20
1766 #define STATS_XML_ALL	  0xff
1767 
1768 static isc_result_t
1769 zone_xmlrender(dns_zone_t *zone, void *arg) {
1770 	isc_result_t result;
1771 	char buf[1024 + 32]; /* sufficiently large for zone name and class */
1772 	dns_rdataclass_t rdclass;
1773 	uint32_t serial;
1774 	xmlTextWriterPtr writer = arg;
1775 	dns_zonestat_level_t statlevel;
1776 	int xmlrc;
1777 	stats_dumparg_t dumparg;
1778 	const char *ztype;
1779 
1780 	statlevel = dns_zone_getstatlevel(zone);
1781 	if (statlevel == dns_zonestat_none) {
1782 		return (ISC_R_SUCCESS);
1783 	}
1784 
1785 	dumparg.type = isc_statsformat_xml;
1786 	dumparg.arg = writer;
1787 
1788 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "zone"));
1789 
1790 	dns_zone_nameonly(zone, buf, sizeof(buf));
1791 	TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
1792 					 ISC_XMLCHAR buf));
1793 
1794 	rdclass = dns_zone_getclass(zone);
1795 	dns_rdataclass_format(rdclass, buf, sizeof(buf));
1796 	TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "rdataclass",
1797 					 ISC_XMLCHAR buf));
1798 
1799 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "type"));
1800 	ztype = user_zonetype(zone);
1801 	if (ztype != NULL) {
1802 		TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR ztype));
1803 	} else {
1804 		TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "unknown"));
1805 	}
1806 	TRY0(xmlTextWriterEndElement(writer)); /* type */
1807 
1808 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "serial"));
1809 	if (dns_zone_getserial(zone, &serial) == ISC_R_SUCCESS) {
1810 		TRY0(xmlTextWriterWriteFormatString(writer, "%u", serial));
1811 	} else {
1812 		TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
1813 	}
1814 	TRY0(xmlTextWriterEndElement(writer)); /* serial */
1815 
1816 	/*
1817 	 * Export zone timers to the statistics channel in XML format.  For
1818 	 * master zones, only include the loaded time.  For slave zones, also
1819 	 * include the expires and refresh times.
1820 	 */
1821 	isc_time_t timestamp;
1822 
1823 	result = dns_zone_getloadtime(zone, &timestamp);
1824 	if (result != ISC_R_SUCCESS) {
1825 		goto error;
1826 	}
1827 
1828 	isc_time_formatISO8601(&timestamp, buf, 64);
1829 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "loaded"));
1830 	TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf));
1831 	TRY0(xmlTextWriterEndElement(writer));
1832 
1833 	if (dns_zone_gettype(zone) == dns_zone_secondary) {
1834 		result = dns_zone_getexpiretime(zone, &timestamp);
1835 		if (result != ISC_R_SUCCESS) {
1836 			goto error;
1837 		}
1838 		isc_time_formatISO8601(&timestamp, buf, 64);
1839 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "expires"));
1840 		TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf));
1841 		TRY0(xmlTextWriterEndElement(writer));
1842 
1843 		result = dns_zone_getrefreshtime(zone, &timestamp);
1844 		if (result != ISC_R_SUCCESS) {
1845 			goto error;
1846 		}
1847 		isc_time_formatISO8601(&timestamp, buf, 64);
1848 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "refresh"));
1849 		TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf));
1850 		TRY0(xmlTextWriterEndElement(writer));
1851 	}
1852 
1853 	if (statlevel == dns_zonestat_full) {
1854 		isc_stats_t *zonestats;
1855 		isc_stats_t *gluecachestats;
1856 		dns_stats_t *rcvquerystats;
1857 		dns_stats_t *dnssecsignstats;
1858 		uint64_t nsstat_values[ns_statscounter_max];
1859 		uint64_t gluecachestats_values[dns_gluecachestatscounter_max];
1860 
1861 		zonestats = dns_zone_getrequeststats(zone);
1862 		if (zonestats != NULL) {
1863 			TRY0(xmlTextWriterStartElement(writer,
1864 						       ISC_XMLCHAR "counters"));
1865 			TRY0(xmlTextWriterWriteAttribute(writer,
1866 							 ISC_XMLCHAR "type",
1867 							 ISC_XMLCHAR "rcode"));
1868 
1869 			result = dump_counters(zonestats, isc_statsformat_xml,
1870 					       writer, NULL, nsstats_xmldesc,
1871 					       ns_statscounter_max,
1872 					       nsstats_index, nsstat_values,
1873 					       ISC_STATSDUMP_VERBOSE);
1874 			if (result != ISC_R_SUCCESS) {
1875 				goto error;
1876 			}
1877 			/* counters type="rcode"*/
1878 			TRY0(xmlTextWriterEndElement(writer));
1879 		}
1880 
1881 		gluecachestats = dns_zone_getgluecachestats(zone);
1882 		if (gluecachestats != NULL) {
1883 			TRY0(xmlTextWriterStartElement(writer,
1884 						       ISC_XMLCHAR "counters"));
1885 			TRY0(xmlTextWriterWriteAttribute(
1886 				writer, ISC_XMLCHAR "type",
1887 				ISC_XMLCHAR "gluecache"));
1888 
1889 			result = dump_counters(
1890 				gluecachestats, isc_statsformat_xml, writer,
1891 				NULL, gluecachestats_xmldesc,
1892 				dns_gluecachestatscounter_max,
1893 				gluecachestats_index, gluecachestats_values,
1894 				ISC_STATSDUMP_VERBOSE);
1895 			if (result != ISC_R_SUCCESS) {
1896 				goto error;
1897 			}
1898 			/* counters type="rcode"*/
1899 			TRY0(xmlTextWriterEndElement(writer));
1900 		}
1901 
1902 		rcvquerystats = dns_zone_getrcvquerystats(zone);
1903 		if (rcvquerystats != NULL) {
1904 			TRY0(xmlTextWriterStartElement(writer,
1905 						       ISC_XMLCHAR "counters"));
1906 			TRY0(xmlTextWriterWriteAttribute(writer,
1907 							 ISC_XMLCHAR "type",
1908 							 ISC_XMLCHAR "qtype"));
1909 
1910 			dumparg.result = ISC_R_SUCCESS;
1911 			dns_rdatatypestats_dump(rcvquerystats, rdtypestat_dump,
1912 						&dumparg, 0);
1913 			if (dumparg.result != ISC_R_SUCCESS) {
1914 				goto error;
1915 			}
1916 
1917 			/* counters type="qtype"*/
1918 			TRY0(xmlTextWriterEndElement(writer));
1919 		}
1920 
1921 		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
1922 		if (dnssecsignstats != NULL) {
1923 			/* counters type="dnssec-sign"*/
1924 			TRY0(xmlTextWriterStartElement(writer,
1925 						       ISC_XMLCHAR "counters"));
1926 			TRY0(xmlTextWriterWriteAttribute(
1927 				writer, ISC_XMLCHAR "type",
1928 				ISC_XMLCHAR "dnssec-sign"));
1929 
1930 			dumparg.result = ISC_R_SUCCESS;
1931 			dns_dnssecsignstats_dump(
1932 				dnssecsignstats, dns_dnssecsignstats_sign,
1933 				dnssecsignstat_dump, &dumparg, 0);
1934 			if (dumparg.result != ISC_R_SUCCESS) {
1935 				goto error;
1936 			}
1937 
1938 			/* counters type="dnssec-sign"*/
1939 			TRY0(xmlTextWriterEndElement(writer));
1940 
1941 			/* counters type="dnssec-refresh"*/
1942 			TRY0(xmlTextWriterStartElement(writer,
1943 						       ISC_XMLCHAR "counters"));
1944 			TRY0(xmlTextWriterWriteAttribute(
1945 				writer, ISC_XMLCHAR "type",
1946 				ISC_XMLCHAR "dnssec-refresh"));
1947 
1948 			dumparg.result = ISC_R_SUCCESS;
1949 			dns_dnssecsignstats_dump(
1950 				dnssecsignstats, dns_dnssecsignstats_refresh,
1951 				dnssecsignstat_dump, &dumparg, 0);
1952 			if (dumparg.result != ISC_R_SUCCESS) {
1953 				goto error;
1954 			}
1955 
1956 			/* counters type="dnssec-refresh"*/
1957 			TRY0(xmlTextWriterEndElement(writer));
1958 		}
1959 	}
1960 
1961 	TRY0(xmlTextWriterEndElement(writer)); /* zone */
1962 
1963 	return (ISC_R_SUCCESS);
1964 error:
1965 	isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
1966 		      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
1967 		      "Failed at zone_xmlrender()");
1968 	return (ISC_R_FAILURE);
1969 }
1970 
1971 static isc_result_t
1972 generatexml(named_server_t *server, uint32_t flags, int *buflen,
1973 	    xmlChar **buf) {
1974 	char boottime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
1975 	char configtime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
1976 	char nowstr[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
1977 	isc_time_t now;
1978 	xmlTextWriterPtr writer = NULL;
1979 	xmlDocPtr doc = NULL;
1980 	int xmlrc;
1981 	dns_view_t *view;
1982 	stats_dumparg_t dumparg;
1983 	dns_stats_t *cacherrstats;
1984 	uint64_t nsstat_values[ns_statscounter_max];
1985 	uint64_t resstat_values[dns_resstatscounter_max];
1986 	uint64_t adbstat_values[dns_adbstats_max];
1987 	uint64_t zonestat_values[dns_zonestatscounter_max];
1988 	uint64_t sockstat_values[isc_sockstatscounter_max];
1989 	uint64_t udpinsizestat_values[dns_sizecounter_in_max];
1990 	uint64_t udpoutsizestat_values[dns_sizecounter_out_max];
1991 	uint64_t tcpinsizestat_values[dns_sizecounter_in_max];
1992 	uint64_t tcpoutsizestat_values[dns_sizecounter_out_max];
1993 #ifdef HAVE_DNSTAP
1994 	uint64_t dnstapstat_values[dns_dnstapcounter_max];
1995 #endif /* ifdef HAVE_DNSTAP */
1996 	isc_result_t result;
1997 
1998 	isc_time_now(&now);
1999 	isc_time_formatISO8601ms(&named_g_boottime, boottime, sizeof boottime);
2000 	isc_time_formatISO8601ms(&named_g_configtime, configtime,
2001 				 sizeof configtime);
2002 	isc_time_formatISO8601ms(&now, nowstr, sizeof nowstr);
2003 
2004 	writer = xmlNewTextWriterDoc(&doc, 0);
2005 	if (writer == NULL) {
2006 		goto error;
2007 	}
2008 	TRY0(xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL));
2009 	TRY0(xmlTextWriterWritePI(writer, ISC_XMLCHAR "xml-stylesheet",
2010 				  ISC_XMLCHAR "type=\"text/xsl\" "
2011 					      "href=\"/bind9.xsl\""));
2012 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics"));
2013 	TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
2014 					 ISC_XMLCHAR "3.11"));
2015 
2016 	/* Set common fields for statistics dump */
2017 	dumparg.type = isc_statsformat_xml;
2018 	dumparg.arg = writer;
2019 
2020 	/* Render server information */
2021 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "server"));
2022 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "boot-time"));
2023 	TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR boottime));
2024 	TRY0(xmlTextWriterEndElement(writer)); /* boot-time */
2025 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "config-time"));
2026 	TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR configtime));
2027 	TRY0(xmlTextWriterEndElement(writer)); /* config-time */
2028 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "current-time"));
2029 	TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR nowstr));
2030 	TRY0(xmlTextWriterEndElement(writer)); /* current-time */
2031 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "version"));
2032 	TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR named_g_version));
2033 	TRY0(xmlTextWriterEndElement(writer)); /* version */
2034 
2035 	if ((flags & STATS_XML_SERVER) != 0) {
2036 		dumparg.result = ISC_R_SUCCESS;
2037 
2038 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2039 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2040 						 ISC_XMLCHAR "opcode"));
2041 
2042 		dns_opcodestats_dump(server->sctx->opcodestats, opcodestat_dump,
2043 				     &dumparg, ISC_STATSDUMP_VERBOSE);
2044 		if (dumparg.result != ISC_R_SUCCESS) {
2045 			goto error;
2046 		}
2047 
2048 		TRY0(xmlTextWriterEndElement(writer));
2049 
2050 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2051 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2052 						 ISC_XMLCHAR "rcode"));
2053 
2054 		dns_rcodestats_dump(server->sctx->rcodestats, rcodestat_dump,
2055 				    &dumparg, ISC_STATSDUMP_VERBOSE);
2056 		if (dumparg.result != ISC_R_SUCCESS) {
2057 			goto error;
2058 		}
2059 
2060 		TRY0(xmlTextWriterEndElement(writer));
2061 
2062 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2063 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2064 						 ISC_XMLCHAR "qtype"));
2065 
2066 		dumparg.result = ISC_R_SUCCESS;
2067 		dns_rdatatypestats_dump(server->sctx->rcvquerystats,
2068 					rdtypestat_dump, &dumparg, 0);
2069 		if (dumparg.result != ISC_R_SUCCESS) {
2070 			goto error;
2071 		}
2072 		TRY0(xmlTextWriterEndElement(writer)); /* counters */
2073 
2074 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2075 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2076 						 ISC_XMLCHAR "nsstat"));
2077 
2078 		result = dump_counters(ns_stats_get(server->sctx->nsstats),
2079 				       isc_statsformat_xml, writer, NULL,
2080 				       nsstats_xmldesc, ns_statscounter_max,
2081 				       nsstats_index, nsstat_values,
2082 				       ISC_STATSDUMP_VERBOSE);
2083 		if (result != ISC_R_SUCCESS) {
2084 			goto error;
2085 		}
2086 
2087 		TRY0(xmlTextWriterEndElement(writer)); /* /nsstat */
2088 
2089 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2090 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2091 						 ISC_XMLCHAR "zonestat"));
2092 
2093 		result = dump_counters(server->zonestats, isc_statsformat_xml,
2094 				       writer, NULL, zonestats_xmldesc,
2095 				       dns_zonestatscounter_max,
2096 				       zonestats_index, zonestat_values,
2097 				       ISC_STATSDUMP_VERBOSE);
2098 		if (result != ISC_R_SUCCESS) {
2099 			goto error;
2100 		}
2101 
2102 		TRY0(xmlTextWriterEndElement(writer)); /* /zonestat */
2103 
2104 		/*
2105 		 * Most of the common resolver statistics entries are 0, so
2106 		 * we don't use the verbose dump here.
2107 		 */
2108 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2109 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2110 						 ISC_XMLCHAR "resstat"));
2111 		result = dump_counters(
2112 			server->resolverstats, isc_statsformat_xml, writer,
2113 			NULL, resstats_xmldesc, dns_resstatscounter_max,
2114 			resstats_index, resstat_values, 0);
2115 		if (result != ISC_R_SUCCESS) {
2116 			goto error;
2117 		}
2118 		TRY0(xmlTextWriterEndElement(writer)); /* resstat */
2119 
2120 #ifdef HAVE_DNSTAP
2121 		if (server->dtenv != NULL) {
2122 			isc_stats_t *dnstapstats = NULL;
2123 			TRY0(xmlTextWriterStartElement(writer,
2124 						       ISC_XMLCHAR "counters"));
2125 			TRY0(xmlTextWriterWriteAttribute(writer,
2126 							 ISC_XMLCHAR "type",
2127 							 ISC_XMLCHAR "dnstap"));
2128 			dns_dt_getstats(named_g_server->dtenv, &dnstapstats);
2129 			result = dump_counters(
2130 				dnstapstats, isc_statsformat_xml, writer, NULL,
2131 				dnstapstats_xmldesc, dns_dnstapcounter_max,
2132 				dnstapstats_index, dnstapstat_values, 0);
2133 			isc_stats_detach(&dnstapstats);
2134 			if (result != ISC_R_SUCCESS) {
2135 				goto error;
2136 			}
2137 			TRY0(xmlTextWriterEndElement(writer)); /* dnstap */
2138 		}
2139 #endif /* ifdef HAVE_DNSTAP */
2140 	}
2141 
2142 	if ((flags & STATS_XML_NET) != 0) {
2143 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2144 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2145 						 ISC_XMLCHAR "sockstat"));
2146 
2147 		result = dump_counters(server->sockstats, isc_statsformat_xml,
2148 				       writer, NULL, sockstats_xmldesc,
2149 				       isc_sockstatscounter_max,
2150 				       sockstats_index, sockstat_values,
2151 				       ISC_STATSDUMP_VERBOSE);
2152 		if (result != ISC_R_SUCCESS) {
2153 			goto error;
2154 		}
2155 
2156 		TRY0(xmlTextWriterEndElement(writer)); /* /sockstat */
2157 	}
2158 	TRY0(xmlTextWriterEndElement(writer)); /* /server */
2159 
2160 	if ((flags & STATS_XML_TRAFFIC) != 0) {
2161 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "traffic"));
2162 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ipv4"));
2163 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "udp"));
2164 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2165 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2166 						 ISC_XMLCHAR "request-size"));
2167 
2168 		result = dump_counters(
2169 			server->sctx->udpinstats4, isc_statsformat_xml, writer,
2170 			NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max,
2171 			udpinsizestats_index, udpinsizestat_values, 0);
2172 		if (result != ISC_R_SUCCESS) {
2173 			goto error;
2174 		}
2175 
2176 		TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
2177 
2178 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2179 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2180 						 ISC_XMLCHAR "response-size"));
2181 
2182 		result = dump_counters(
2183 			server->sctx->udpoutstats4, isc_statsformat_xml, writer,
2184 			NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max,
2185 			udpoutsizestats_index, udpoutsizestat_values, 0);
2186 		if (result != ISC_R_SUCCESS) {
2187 			goto error;
2188 		}
2189 
2190 		TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
2191 		TRY0(xmlTextWriterEndElement(writer)); /* </udp> */
2192 
2193 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tcp"));
2194 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2195 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2196 						 ISC_XMLCHAR "request-size"));
2197 
2198 		result = dump_counters(
2199 			server->sctx->tcpinstats4, isc_statsformat_xml, writer,
2200 			NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max,
2201 			tcpinsizestats_index, tcpinsizestat_values, 0);
2202 		if (result != ISC_R_SUCCESS) {
2203 			goto error;
2204 		}
2205 
2206 		TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
2207 
2208 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2209 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2210 						 ISC_XMLCHAR "response-size"));
2211 
2212 		result = dump_counters(
2213 			server->sctx->tcpoutstats4, isc_statsformat_xml, writer,
2214 			NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max,
2215 			tcpoutsizestats_index, tcpoutsizestat_values, 0);
2216 		if (result != ISC_R_SUCCESS) {
2217 			goto error;
2218 		}
2219 
2220 		TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
2221 		TRY0(xmlTextWriterEndElement(writer)); /* </tcp> */
2222 		TRY0(xmlTextWriterEndElement(writer)); /* </ipv4> */
2223 
2224 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ipv6"));
2225 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "udp"));
2226 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2227 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2228 						 ISC_XMLCHAR "request-size"));
2229 
2230 		result = dump_counters(
2231 			server->sctx->udpinstats6, isc_statsformat_xml, writer,
2232 			NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max,
2233 			udpinsizestats_index, udpinsizestat_values, 0);
2234 		if (result != ISC_R_SUCCESS) {
2235 			goto error;
2236 		}
2237 
2238 		TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
2239 
2240 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2241 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2242 						 ISC_XMLCHAR "response-size"));
2243 
2244 		result = dump_counters(
2245 			server->sctx->udpoutstats6, isc_statsformat_xml, writer,
2246 			NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max,
2247 			udpoutsizestats_index, udpoutsizestat_values, 0);
2248 		if (result != ISC_R_SUCCESS) {
2249 			goto error;
2250 		}
2251 
2252 		TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
2253 		TRY0(xmlTextWriterEndElement(writer)); /* </udp> */
2254 
2255 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tcp"));
2256 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2257 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2258 						 ISC_XMLCHAR "request-size"));
2259 
2260 		result = dump_counters(
2261 			server->sctx->tcpinstats6, isc_statsformat_xml, writer,
2262 			NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max,
2263 			tcpinsizestats_index, tcpinsizestat_values, 0);
2264 		if (result != ISC_R_SUCCESS) {
2265 			goto error;
2266 		}
2267 
2268 		TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
2269 
2270 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2271 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2272 						 ISC_XMLCHAR "response-size"));
2273 
2274 		result = dump_counters(
2275 			server->sctx->tcpoutstats6, isc_statsformat_xml, writer,
2276 			NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max,
2277 			tcpoutsizestats_index, tcpoutsizestat_values, 0);
2278 		if (result != ISC_R_SUCCESS) {
2279 			goto error;
2280 		}
2281 
2282 		TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
2283 		TRY0(xmlTextWriterEndElement(writer)); /* </tcp> */
2284 		TRY0(xmlTextWriterEndElement(writer)); /* </ipv6> */
2285 		TRY0(xmlTextWriterEndElement(writer)); /* </traffic> */
2286 	}
2287 
2288 	/*
2289 	 * Render views.  For each view we know of, call its
2290 	 * rendering function.
2291 	 */
2292 	view = ISC_LIST_HEAD(server->viewlist);
2293 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "views"));
2294 	while (view != NULL &&
2295 	       ((flags & (STATS_XML_SERVER | STATS_XML_ZONES)) != 0)) {
2296 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "view"));
2297 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
2298 						 ISC_XMLCHAR view->name));
2299 
2300 		if ((flags & STATS_XML_ZONES) != 0) {
2301 			TRY0(xmlTextWriterStartElement(writer,
2302 						       ISC_XMLCHAR "zones"));
2303 			result = dns_zt_apply(view->zonetable, true, NULL,
2304 					      zone_xmlrender, writer);
2305 			if (result != ISC_R_SUCCESS) {
2306 				goto error;
2307 			}
2308 			TRY0(xmlTextWriterEndElement(writer)); /* /zones */
2309 		}
2310 
2311 		if ((flags & STATS_XML_SERVER) == 0) {
2312 			TRY0(xmlTextWriterEndElement(writer)); /* /view */
2313 			view = ISC_LIST_NEXT(view, link);
2314 			continue;
2315 		}
2316 
2317 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2318 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2319 						 ISC_XMLCHAR "resqtype"));
2320 
2321 		if (view->resquerystats != NULL) {
2322 			dumparg.result = ISC_R_SUCCESS;
2323 			dns_rdatatypestats_dump(view->resquerystats,
2324 						rdtypestat_dump, &dumparg, 0);
2325 			if (dumparg.result != ISC_R_SUCCESS) {
2326 				goto error;
2327 			}
2328 		}
2329 		TRY0(xmlTextWriterEndElement(writer));
2330 
2331 		/* <resstats> */
2332 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2333 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2334 						 ISC_XMLCHAR "resstats"));
2335 		if (view->resstats != NULL) {
2336 			result = dump_counters(
2337 				view->resstats, isc_statsformat_xml, writer,
2338 				NULL, resstats_xmldesc, dns_resstatscounter_max,
2339 				resstats_index, resstat_values,
2340 				ISC_STATSDUMP_VERBOSE);
2341 			if (result != ISC_R_SUCCESS) {
2342 				goto error;
2343 			}
2344 		}
2345 		TRY0(xmlTextWriterEndElement(writer)); /* </resstats> */
2346 
2347 		cacherrstats = dns_db_getrrsetstats(view->cachedb);
2348 		if (cacherrstats != NULL) {
2349 			TRY0(xmlTextWriterStartElement(writer,
2350 						       ISC_XMLCHAR "cache"));
2351 			TRY0(xmlTextWriterWriteAttribute(
2352 				writer, ISC_XMLCHAR "name",
2353 				ISC_XMLCHAR dns_cache_getname(view->cache)));
2354 			dumparg.result = ISC_R_SUCCESS;
2355 			dns_rdatasetstats_dump(cacherrstats, rdatasetstats_dump,
2356 					       &dumparg, 0);
2357 			if (dumparg.result != ISC_R_SUCCESS) {
2358 				goto error;
2359 			}
2360 			TRY0(xmlTextWriterEndElement(writer)); /* cache */
2361 		}
2362 
2363 		/* <adbstats> */
2364 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2365 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2366 						 ISC_XMLCHAR "adbstat"));
2367 		if (view->adbstats != NULL) {
2368 			result = dump_counters(
2369 				view->adbstats, isc_statsformat_xml, writer,
2370 				NULL, adbstats_xmldesc, dns_adbstats_max,
2371 				adbstats_index, adbstat_values,
2372 				ISC_STATSDUMP_VERBOSE);
2373 			if (result != ISC_R_SUCCESS) {
2374 				goto error;
2375 			}
2376 		}
2377 		TRY0(xmlTextWriterEndElement(writer)); /* </adbstats> */
2378 
2379 		/* <cachestats> */
2380 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
2381 		TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
2382 						 ISC_XMLCHAR "cachestats"));
2383 		TRY0(dns_cache_renderxml(view->cache, writer));
2384 		TRY0(xmlTextWriterEndElement(writer)); /* </cachestats> */
2385 
2386 		TRY0(xmlTextWriterEndElement(writer)); /* view */
2387 
2388 		view = ISC_LIST_NEXT(view, link);
2389 	}
2390 	TRY0(xmlTextWriterEndElement(writer)); /* /views */
2391 
2392 	if ((flags & STATS_XML_NET) != 0) {
2393 		TRY0(xmlTextWriterStartElement(writer,
2394 					       ISC_XMLCHAR "socketmgr"));
2395 		TRY0(isc_socketmgr_renderxml(named_g_socketmgr, writer));
2396 		TRY0(xmlTextWriterEndElement(writer)); /* /socketmgr */
2397 	}
2398 
2399 	if ((flags & STATS_XML_TASKS) != 0) {
2400 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "taskmgr"));
2401 		TRY0(isc_taskmgr_renderxml(named_g_taskmgr, writer));
2402 		TRY0(xmlTextWriterEndElement(writer)); /* /taskmgr */
2403 	}
2404 
2405 	if ((flags & STATS_XML_MEM) != 0) {
2406 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "memory"));
2407 		TRY0(isc_mem_renderxml(writer));
2408 		TRY0(xmlTextWriterEndElement(writer)); /* /memory */
2409 	}
2410 
2411 	TRY0(xmlTextWriterEndElement(writer)); /* /statistics */
2412 	TRY0(xmlTextWriterEndDocument(writer));
2413 
2414 	xmlDocDumpFormatMemoryEnc(doc, buf, buflen, "UTF-8", 0);
2415 	if (*buf == NULL) {
2416 		goto error;
2417 	}
2418 
2419 	xmlFreeTextWriter(writer);
2420 	xmlFreeDoc(doc);
2421 	return (ISC_R_SUCCESS);
2422 
2423 error:
2424 	isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
2425 		      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
2426 		      "failed generating XML response");
2427 	if (writer != NULL) {
2428 		xmlFreeTextWriter(writer);
2429 	}
2430 	if (doc != NULL) {
2431 		xmlFreeDoc(doc);
2432 	}
2433 	return (ISC_R_FAILURE);
2434 }
2435 
2436 static void
2437 wrap_xmlfree(isc_buffer_t *buffer, void *arg) {
2438 	UNUSED(arg);
2439 
2440 	xmlFree(isc_buffer_base(buffer));
2441 }
2442 
2443 static isc_result_t
2444 render_xml(uint32_t flags, const char *url, isc_httpdurl_t *urlinfo,
2445 	   const char *querystring, const char *headers, void *arg,
2446 	   unsigned int *retcode, const char **retmsg, const char **mimetype,
2447 	   isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) {
2448 	unsigned char *msg = NULL;
2449 	int msglen;
2450 	named_server_t *server = arg;
2451 	isc_result_t result;
2452 
2453 	UNUSED(url);
2454 	UNUSED(urlinfo);
2455 	UNUSED(headers);
2456 	UNUSED(querystring);
2457 
2458 	result = generatexml(server, flags, &msglen, &msg);
2459 
2460 	if (result == ISC_R_SUCCESS) {
2461 		*retcode = 200;
2462 		*retmsg = "OK";
2463 		*mimetype = "text/xml";
2464 		isc_buffer_reinit(b, msg, msglen);
2465 		isc_buffer_add(b, msglen);
2466 		*freecb = wrap_xmlfree;
2467 		*freecb_args = NULL;
2468 	} else {
2469 		isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
2470 			      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
2471 			      "failed at rendering XML()");
2472 	}
2473 
2474 	return (result);
2475 }
2476 
2477 static isc_result_t
2478 render_xml_all(const char *url, isc_httpdurl_t *urlinfo,
2479 	       const char *querystring, const char *headers, void *arg,
2480 	       unsigned int *retcode, const char **retmsg,
2481 	       const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb,
2482 	       void **freecb_args) {
2483 	return (render_xml(STATS_XML_ALL, url, urlinfo, querystring, headers,
2484 			   arg, retcode, retmsg, mimetype, b, freecb,
2485 			   freecb_args));
2486 }
2487 
2488 static isc_result_t
2489 render_xml_status(const char *url, isc_httpdurl_t *urlinfo,
2490 		  const char *querystring, const char *headers, void *arg,
2491 		  unsigned int *retcode, const char **retmsg,
2492 		  const char **mimetype, isc_buffer_t *b,
2493 		  isc_httpdfree_t **freecb, void **freecb_args) {
2494 	return (render_xml(STATS_XML_STATUS, url, urlinfo, querystring, headers,
2495 			   arg, retcode, retmsg, mimetype, b, freecb,
2496 			   freecb_args));
2497 }
2498 
2499 static isc_result_t
2500 render_xml_server(const char *url, isc_httpdurl_t *urlinfo,
2501 		  const char *querystring, const char *headers, void *arg,
2502 		  unsigned int *retcode, const char **retmsg,
2503 		  const char **mimetype, isc_buffer_t *b,
2504 		  isc_httpdfree_t **freecb, void **freecb_args) {
2505 	return (render_xml(STATS_XML_SERVER, url, urlinfo, querystring, headers,
2506 			   arg, retcode, retmsg, mimetype, b, freecb,
2507 			   freecb_args));
2508 }
2509 
2510 static isc_result_t
2511 render_xml_zones(const char *url, isc_httpdurl_t *urlinfo,
2512 		 const char *querystring, const char *headers, void *arg,
2513 		 unsigned int *retcode, const char **retmsg,
2514 		 const char **mimetype, isc_buffer_t *b,
2515 		 isc_httpdfree_t **freecb, void **freecb_args) {
2516 	return (render_xml(STATS_XML_ZONES, url, urlinfo, querystring, headers,
2517 			   arg, retcode, retmsg, mimetype, b, freecb,
2518 			   freecb_args));
2519 }
2520 
2521 static isc_result_t
2522 render_xml_net(const char *url, isc_httpdurl_t *urlinfo,
2523 	       const char *querystring, const char *headers, void *arg,
2524 	       unsigned int *retcode, const char **retmsg,
2525 	       const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb,
2526 	       void **freecb_args) {
2527 	return (render_xml(STATS_XML_NET, url, urlinfo, querystring, headers,
2528 			   arg, retcode, retmsg, mimetype, b, freecb,
2529 			   freecb_args));
2530 }
2531 
2532 static isc_result_t
2533 render_xml_tasks(const char *url, isc_httpdurl_t *urlinfo,
2534 		 const char *querystring, const char *headers, void *arg,
2535 		 unsigned int *retcode, const char **retmsg,
2536 		 const char **mimetype, isc_buffer_t *b,
2537 		 isc_httpdfree_t **freecb, void **freecb_args) {
2538 	return (render_xml(STATS_XML_TASKS, url, urlinfo, querystring, headers,
2539 			   arg, retcode, retmsg, mimetype, b, freecb,
2540 			   freecb_args));
2541 }
2542 
2543 static isc_result_t
2544 render_xml_mem(const char *url, isc_httpdurl_t *urlinfo,
2545 	       const char *querystring, const char *headers, void *arg,
2546 	       unsigned int *retcode, const char **retmsg,
2547 	       const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb,
2548 	       void **freecb_args) {
2549 	return (render_xml(STATS_XML_MEM, url, urlinfo, querystring, headers,
2550 			   arg, retcode, retmsg, mimetype, b, freecb,
2551 			   freecb_args));
2552 }
2553 
2554 static isc_result_t
2555 render_xml_traffic(const char *url, isc_httpdurl_t *urlinfo,
2556 		   const char *querystring, const char *headers, void *arg,
2557 		   unsigned int *retcode, const char **retmsg,
2558 		   const char **mimetype, isc_buffer_t *b,
2559 		   isc_httpdfree_t **freecb, void **freecb_args) {
2560 	return (render_xml(STATS_XML_TRAFFIC, url, urlinfo, querystring,
2561 			   headers, arg, retcode, retmsg, mimetype, b, freecb,
2562 			   freecb_args));
2563 }
2564 
2565 #endif /* HAVE_LIBXML2 */
2566 
2567 #ifdef HAVE_JSON_C
2568 /*
2569  * Which statistics to include when rendering to JSON
2570  */
2571 #define STATS_JSON_STATUS  0x00 /* display only common statistics */
2572 #define STATS_JSON_SERVER  0x01
2573 #define STATS_JSON_ZONES   0x02
2574 #define STATS_JSON_TASKS   0x04
2575 #define STATS_JSON_NET	   0x08
2576 #define STATS_JSON_MEM	   0x10
2577 #define STATS_JSON_TRAFFIC 0x20
2578 #define STATS_JSON_ALL	   0xff
2579 
2580 #define CHECK(m)                             \
2581 	do {                                 \
2582 		result = (m);                \
2583 		if (result != ISC_R_SUCCESS) \
2584 			goto error;          \
2585 	} while (0)
2586 
2587 #define CHECKMEM(m)                              \
2588 	do {                                     \
2589 		if (m == NULL) {                 \
2590 			result = ISC_R_NOMEMORY; \
2591 			goto error;              \
2592 		}                                \
2593 	} while (0)
2594 
2595 static void
2596 wrap_jsonfree(isc_buffer_t *buffer, void *arg) {
2597 	json_object_put(isc_buffer_base(buffer));
2598 	if (arg != NULL) {
2599 		json_object_put((json_object *)arg);
2600 	}
2601 }
2602 
2603 static json_object *
2604 addzone(char *name, char *classname, const char *ztype, uint32_t serial,
2605 	bool add_serial) {
2606 	json_object *node = json_object_new_object();
2607 
2608 	if (node == NULL) {
2609 		return (NULL);
2610 	}
2611 
2612 	json_object_object_add(node, "name", json_object_new_string(name));
2613 	json_object_object_add(node, "class",
2614 			       json_object_new_string(classname));
2615 	if (add_serial) {
2616 		json_object_object_add(node, "serial",
2617 				       json_object_new_int64(serial));
2618 	}
2619 	if (ztype != NULL) {
2620 		json_object_object_add(node, "type",
2621 				       json_object_new_string(ztype));
2622 	}
2623 	return (node);
2624 }
2625 
2626 static isc_result_t
2627 zone_jsonrender(dns_zone_t *zone, void *arg) {
2628 	isc_result_t result = ISC_R_SUCCESS;
2629 	char buf[1024 + 32]; /* sufficiently large for zone name and class */
2630 	char classbuf[64];   /* sufficiently large for class */
2631 	char *zone_name_only = NULL;
2632 	char *class_only = NULL;
2633 	dns_rdataclass_t rdclass;
2634 	uint32_t serial;
2635 	json_object *zonearray = (json_object *)arg;
2636 	json_object *zoneobj = NULL;
2637 	dns_zonestat_level_t statlevel;
2638 
2639 	statlevel = dns_zone_getstatlevel(zone);
2640 	if (statlevel == dns_zonestat_none) {
2641 		return (ISC_R_SUCCESS);
2642 	}
2643 
2644 	dns_zone_nameonly(zone, buf, sizeof(buf));
2645 	zone_name_only = buf;
2646 
2647 	rdclass = dns_zone_getclass(zone);
2648 	dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2649 	class_only = classbuf;
2650 
2651 	if (dns_zone_getserial(zone, &serial) != ISC_R_SUCCESS) {
2652 		zoneobj = addzone(zone_name_only, class_only,
2653 				  user_zonetype(zone), 0, false);
2654 	} else {
2655 		zoneobj = addzone(zone_name_only, class_only,
2656 				  user_zonetype(zone), serial, true);
2657 	}
2658 
2659 	if (zoneobj == NULL) {
2660 		return (ISC_R_NOMEMORY);
2661 	}
2662 
2663 	/*
2664 	 * Export zone timers to the statistics channel in JSON format.  For
2665 	 * master zones, only include the loaded time.  For slave zones, also
2666 	 * include the expires and refresh times.
2667 	 */
2668 
2669 	isc_time_t timestamp;
2670 
2671 	result = dns_zone_getloadtime(zone, &timestamp);
2672 	if (result != ISC_R_SUCCESS) {
2673 		goto error;
2674 	}
2675 
2676 	isc_time_formatISO8601(&timestamp, buf, 64);
2677 	json_object_object_add(zoneobj, "loaded", json_object_new_string(buf));
2678 
2679 	if (dns_zone_gettype(zone) == dns_zone_secondary) {
2680 		result = dns_zone_getexpiretime(zone, &timestamp);
2681 		if (result != ISC_R_SUCCESS) {
2682 			goto error;
2683 		}
2684 		isc_time_formatISO8601(&timestamp, buf, 64);
2685 		json_object_object_add(zoneobj, "expires",
2686 				       json_object_new_string(buf));
2687 
2688 		result = dns_zone_getrefreshtime(zone, &timestamp);
2689 		if (result != ISC_R_SUCCESS) {
2690 			goto error;
2691 		}
2692 		isc_time_formatISO8601(&timestamp, buf, 64);
2693 		json_object_object_add(zoneobj, "refresh",
2694 				       json_object_new_string(buf));
2695 	}
2696 
2697 	if (statlevel == dns_zonestat_full) {
2698 		isc_stats_t *zonestats;
2699 		isc_stats_t *gluecachestats;
2700 		dns_stats_t *rcvquerystats;
2701 		dns_stats_t *dnssecsignstats;
2702 		uint64_t nsstat_values[ns_statscounter_max];
2703 		uint64_t gluecachestats_values[dns_gluecachestatscounter_max];
2704 
2705 		zonestats = dns_zone_getrequeststats(zone);
2706 		if (zonestats != NULL) {
2707 			json_object *counters = json_object_new_object();
2708 			if (counters == NULL) {
2709 				result = ISC_R_NOMEMORY;
2710 				goto error;
2711 			}
2712 
2713 			result = dump_counters(zonestats, isc_statsformat_json,
2714 					       counters, NULL, nsstats_xmldesc,
2715 					       ns_statscounter_max,
2716 					       nsstats_index, nsstat_values, 0);
2717 			if (result != ISC_R_SUCCESS) {
2718 				json_object_put(counters);
2719 				goto error;
2720 			}
2721 
2722 			if (json_object_get_object(counters)->count != 0) {
2723 				json_object_object_add(zoneobj, "rcodes",
2724 						       counters);
2725 			} else {
2726 				json_object_put(counters);
2727 			}
2728 		}
2729 
2730 		gluecachestats = dns_zone_getgluecachestats(zone);
2731 		if (gluecachestats != NULL) {
2732 			json_object *counters = json_object_new_object();
2733 			if (counters == NULL) {
2734 				result = ISC_R_NOMEMORY;
2735 				goto error;
2736 			}
2737 
2738 			result = dump_counters(
2739 				gluecachestats, isc_statsformat_json, counters,
2740 				NULL, gluecachestats_xmldesc,
2741 				dns_gluecachestatscounter_max,
2742 				gluecachestats_index, gluecachestats_values, 0);
2743 			if (result != ISC_R_SUCCESS) {
2744 				json_object_put(counters);
2745 				goto error;
2746 			}
2747 
2748 			if (json_object_get_object(counters)->count != 0) {
2749 				json_object_object_add(zoneobj, "gluecache",
2750 						       counters);
2751 			} else {
2752 				json_object_put(counters);
2753 			}
2754 		}
2755 
2756 		rcvquerystats = dns_zone_getrcvquerystats(zone);
2757 		if (rcvquerystats != NULL) {
2758 			stats_dumparg_t dumparg;
2759 			json_object *counters = json_object_new_object();
2760 			CHECKMEM(counters);
2761 
2762 			dumparg.type = isc_statsformat_json;
2763 			dumparg.arg = counters;
2764 			dumparg.result = ISC_R_SUCCESS;
2765 			dns_rdatatypestats_dump(rcvquerystats, rdtypestat_dump,
2766 						&dumparg, 0);
2767 			if (dumparg.result != ISC_R_SUCCESS) {
2768 				json_object_put(counters);
2769 				goto error;
2770 			}
2771 
2772 			if (json_object_get_object(counters)->count != 0) {
2773 				json_object_object_add(zoneobj, "qtypes",
2774 						       counters);
2775 			} else {
2776 				json_object_put(counters);
2777 			}
2778 		}
2779 
2780 		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
2781 		if (dnssecsignstats != NULL) {
2782 			stats_dumparg_t dumparg;
2783 			json_object *sign_counters = json_object_new_object();
2784 			CHECKMEM(sign_counters);
2785 
2786 			dumparg.type = isc_statsformat_json;
2787 			dumparg.arg = sign_counters;
2788 			dumparg.result = ISC_R_SUCCESS;
2789 			dns_dnssecsignstats_dump(
2790 				dnssecsignstats, dns_dnssecsignstats_sign,
2791 				dnssecsignstat_dump, &dumparg, 0);
2792 			if (dumparg.result != ISC_R_SUCCESS) {
2793 				json_object_put(sign_counters);
2794 				goto error;
2795 			}
2796 
2797 			if (json_object_get_object(sign_counters)->count != 0) {
2798 				json_object_object_add(zoneobj, "dnssec-sign",
2799 						       sign_counters);
2800 			} else {
2801 				json_object_put(sign_counters);
2802 			}
2803 
2804 			json_object *refresh_counters =
2805 				json_object_new_object();
2806 			CHECKMEM(refresh_counters);
2807 
2808 			dumparg.type = isc_statsformat_json;
2809 			dumparg.arg = refresh_counters;
2810 			dumparg.result = ISC_R_SUCCESS;
2811 			dns_dnssecsignstats_dump(
2812 				dnssecsignstats, dns_dnssecsignstats_refresh,
2813 				dnssecsignstat_dump, &dumparg, 0);
2814 			if (dumparg.result != ISC_R_SUCCESS) {
2815 				json_object_put(refresh_counters);
2816 				goto error;
2817 			}
2818 
2819 			if (json_object_get_object(refresh_counters)->count !=
2820 			    0) {
2821 				json_object_object_add(zoneobj,
2822 						       "dnssec-refresh",
2823 						       refresh_counters);
2824 			} else {
2825 				json_object_put(refresh_counters);
2826 			}
2827 		}
2828 	}
2829 
2830 	json_object_array_add(zonearray, zoneobj);
2831 	zoneobj = NULL;
2832 	result = ISC_R_SUCCESS;
2833 
2834 error:
2835 	if (zoneobj != NULL) {
2836 		json_object_put(zoneobj);
2837 	}
2838 	return (result);
2839 }
2840 
2841 static isc_result_t
2842 generatejson(named_server_t *server, size_t *msglen, const char **msg,
2843 	     json_object **rootp, uint32_t flags) {
2844 	dns_view_t *view;
2845 	isc_result_t result = ISC_R_SUCCESS;
2846 	json_object *bindstats, *viewlist, *counters, *obj;
2847 	json_object *traffic = NULL;
2848 	json_object *udpreq4 = NULL, *udpresp4 = NULL;
2849 	json_object *tcpreq4 = NULL, *tcpresp4 = NULL;
2850 	json_object *udpreq6 = NULL, *udpresp6 = NULL;
2851 	json_object *tcpreq6 = NULL, *tcpresp6 = NULL;
2852 	uint64_t nsstat_values[ns_statscounter_max];
2853 	uint64_t resstat_values[dns_resstatscounter_max];
2854 	uint64_t adbstat_values[dns_adbstats_max];
2855 	uint64_t zonestat_values[dns_zonestatscounter_max];
2856 	uint64_t sockstat_values[isc_sockstatscounter_max];
2857 	uint64_t udpinsizestat_values[dns_sizecounter_in_max];
2858 	uint64_t udpoutsizestat_values[dns_sizecounter_out_max];
2859 	uint64_t tcpinsizestat_values[dns_sizecounter_in_max];
2860 	uint64_t tcpoutsizestat_values[dns_sizecounter_out_max];
2861 #ifdef HAVE_DNSTAP
2862 	uint64_t dnstapstat_values[dns_dnstapcounter_max];
2863 #endif /* ifdef HAVE_DNSTAP */
2864 	stats_dumparg_t dumparg;
2865 	char boottime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
2866 	char configtime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
2867 	char nowstr[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
2868 	isc_time_t now;
2869 
2870 	REQUIRE(msglen != NULL);
2871 	REQUIRE(msg != NULL && *msg == NULL);
2872 	REQUIRE(rootp == NULL || *rootp == NULL);
2873 
2874 	bindstats = json_object_new_object();
2875 	if (bindstats == NULL) {
2876 		return (ISC_R_NOMEMORY);
2877 	}
2878 
2879 	/*
2880 	 * These statistics are included no matter which URL we use.
2881 	 */
2882 	obj = json_object_new_string("1.5");
2883 	CHECKMEM(obj);
2884 	json_object_object_add(bindstats, "json-stats-version", obj);
2885 
2886 	isc_time_now(&now);
2887 	isc_time_formatISO8601ms(&named_g_boottime, boottime, sizeof(boottime));
2888 	isc_time_formatISO8601ms(&named_g_configtime, configtime,
2889 				 sizeof configtime);
2890 	isc_time_formatISO8601ms(&now, nowstr, sizeof(nowstr));
2891 
2892 	obj = json_object_new_string(boottime);
2893 	CHECKMEM(obj);
2894 	json_object_object_add(bindstats, "boot-time", obj);
2895 
2896 	obj = json_object_new_string(configtime);
2897 	CHECKMEM(obj);
2898 	json_object_object_add(bindstats, "config-time", obj);
2899 
2900 	obj = json_object_new_string(nowstr);
2901 	CHECKMEM(obj);
2902 	json_object_object_add(bindstats, "current-time", obj);
2903 	obj = json_object_new_string(named_g_version);
2904 	CHECKMEM(obj);
2905 	json_object_object_add(bindstats, "version", obj);
2906 
2907 	if ((flags & STATS_JSON_SERVER) != 0) {
2908 		/* OPCODE counters */
2909 		counters = json_object_new_object();
2910 
2911 		dumparg.result = ISC_R_SUCCESS;
2912 		dumparg.type = isc_statsformat_json;
2913 		dumparg.arg = counters;
2914 
2915 		dns_opcodestats_dump(server->sctx->opcodestats, opcodestat_dump,
2916 				     &dumparg, ISC_STATSDUMP_VERBOSE);
2917 		if (dumparg.result != ISC_R_SUCCESS) {
2918 			json_object_put(counters);
2919 			goto error;
2920 		}
2921 
2922 		if (json_object_get_object(counters)->count != 0) {
2923 			json_object_object_add(bindstats, "opcodes", counters);
2924 		} else {
2925 			json_object_put(counters);
2926 		}
2927 
2928 		/* OPCODE counters */
2929 		counters = json_object_new_object();
2930 
2931 		dumparg.type = isc_statsformat_json;
2932 		dumparg.arg = counters;
2933 
2934 		dns_rcodestats_dump(server->sctx->rcodestats, rcodestat_dump,
2935 				    &dumparg, ISC_STATSDUMP_VERBOSE);
2936 		if (dumparg.result != ISC_R_SUCCESS) {
2937 			json_object_put(counters);
2938 			goto error;
2939 		}
2940 
2941 		if (json_object_get_object(counters)->count != 0) {
2942 			json_object_object_add(bindstats, "rcodes", counters);
2943 		} else {
2944 			json_object_put(counters);
2945 		}
2946 
2947 		/* QTYPE counters */
2948 		counters = json_object_new_object();
2949 
2950 		dumparg.result = ISC_R_SUCCESS;
2951 		dumparg.arg = counters;
2952 
2953 		dns_rdatatypestats_dump(server->sctx->rcvquerystats,
2954 					rdtypestat_dump, &dumparg, 0);
2955 		if (dumparg.result != ISC_R_SUCCESS) {
2956 			json_object_put(counters);
2957 			goto error;
2958 		}
2959 
2960 		if (json_object_get_object(counters)->count != 0) {
2961 			json_object_object_add(bindstats, "qtypes", counters);
2962 		} else {
2963 			json_object_put(counters);
2964 		}
2965 
2966 		/* server stat counters */
2967 		counters = json_object_new_object();
2968 
2969 		dumparg.result = ISC_R_SUCCESS;
2970 		dumparg.arg = counters;
2971 
2972 		result = dump_counters(ns_stats_get(server->sctx->nsstats),
2973 				       isc_statsformat_json, counters, NULL,
2974 				       nsstats_xmldesc, ns_statscounter_max,
2975 				       nsstats_index, nsstat_values, 0);
2976 		if (result != ISC_R_SUCCESS) {
2977 			json_object_put(counters);
2978 			goto error;
2979 		}
2980 
2981 		if (json_object_get_object(counters)->count != 0) {
2982 			json_object_object_add(bindstats, "nsstats", counters);
2983 		} else {
2984 			json_object_put(counters);
2985 		}
2986 
2987 		/* zone stat counters */
2988 		counters = json_object_new_object();
2989 
2990 		dumparg.result = ISC_R_SUCCESS;
2991 		dumparg.arg = counters;
2992 
2993 		result = dump_counters(server->zonestats, isc_statsformat_json,
2994 				       counters, NULL, zonestats_xmldesc,
2995 				       dns_zonestatscounter_max,
2996 				       zonestats_index, zonestat_values, 0);
2997 		if (result != ISC_R_SUCCESS) {
2998 			json_object_put(counters);
2999 			goto error;
3000 		}
3001 
3002 		if (json_object_get_object(counters)->count != 0) {
3003 			json_object_object_add(bindstats, "zonestats",
3004 					       counters);
3005 		} else {
3006 			json_object_put(counters);
3007 		}
3008 
3009 		/* resolver stat counters */
3010 		counters = json_object_new_object();
3011 
3012 		dumparg.result = ISC_R_SUCCESS;
3013 		dumparg.arg = counters;
3014 
3015 		result = dump_counters(
3016 			server->resolverstats, isc_statsformat_json, counters,
3017 			NULL, resstats_xmldesc, dns_resstatscounter_max,
3018 			resstats_index, resstat_values, 0);
3019 		if (result != ISC_R_SUCCESS) {
3020 			json_object_put(counters);
3021 			goto error;
3022 		}
3023 
3024 		if (json_object_get_object(counters)->count != 0) {
3025 			json_object_object_add(bindstats, "resstats", counters);
3026 		} else {
3027 			json_object_put(counters);
3028 		}
3029 
3030 #ifdef HAVE_DNSTAP
3031 		/* dnstap stat counters */
3032 		if (named_g_server->dtenv != NULL) {
3033 			isc_stats_t *dnstapstats = NULL;
3034 			dns_dt_getstats(named_g_server->dtenv, &dnstapstats);
3035 			counters = json_object_new_object();
3036 			dumparg.result = ISC_R_SUCCESS;
3037 			dumparg.arg = counters;
3038 			result = dump_counters(
3039 				dnstapstats, isc_statsformat_json, counters,
3040 				NULL, dnstapstats_xmldesc,
3041 				dns_dnstapcounter_max, dnstapstats_index,
3042 				dnstapstat_values, 0);
3043 			isc_stats_detach(&dnstapstats);
3044 			if (result != ISC_R_SUCCESS) {
3045 				json_object_put(counters);
3046 				goto error;
3047 			}
3048 
3049 			if (json_object_get_object(counters)->count != 0) {
3050 				json_object_object_add(bindstats, "dnstapstats",
3051 						       counters);
3052 			} else {
3053 				json_object_put(counters);
3054 			}
3055 		}
3056 #endif /* ifdef HAVE_DNSTAP */
3057 	}
3058 
3059 	if ((flags & (STATS_JSON_ZONES | STATS_JSON_SERVER)) != 0) {
3060 		viewlist = json_object_new_object();
3061 		CHECKMEM(viewlist);
3062 
3063 		json_object_object_add(bindstats, "views", viewlist);
3064 
3065 		view = ISC_LIST_HEAD(server->viewlist);
3066 		while (view != NULL) {
3067 			json_object *za, *v = json_object_new_object();
3068 
3069 			CHECKMEM(v);
3070 			json_object_object_add(viewlist, view->name, v);
3071 
3072 			za = json_object_new_array();
3073 			CHECKMEM(za);
3074 
3075 			if ((flags & STATS_JSON_ZONES) != 0) {
3076 				result = dns_zt_apply(view->zonetable, true,
3077 						      NULL, zone_jsonrender,
3078 						      za);
3079 				if (result != ISC_R_SUCCESS) {
3080 					goto error;
3081 				}
3082 			}
3083 
3084 			if (json_object_array_length(za) != 0) {
3085 				json_object_object_add(v, "zones", za);
3086 			} else {
3087 				json_object_put(za);
3088 			}
3089 
3090 			if ((flags & STATS_JSON_SERVER) != 0) {
3091 				json_object *res;
3092 				dns_stats_t *dstats;
3093 				isc_stats_t *istats;
3094 
3095 				res = json_object_new_object();
3096 				CHECKMEM(res);
3097 				json_object_object_add(v, "resolver", res);
3098 
3099 				istats = view->resstats;
3100 				if (istats != NULL) {
3101 					counters = json_object_new_object();
3102 					CHECKMEM(counters);
3103 
3104 					result = dump_counters(
3105 						istats, isc_statsformat_json,
3106 						counters, NULL,
3107 						resstats_xmldesc,
3108 						dns_resstatscounter_max,
3109 						resstats_index, resstat_values,
3110 						0);
3111 					if (result != ISC_R_SUCCESS) {
3112 						json_object_put(counters);
3113 						result = dumparg.result;
3114 						goto error;
3115 					}
3116 
3117 					json_object_object_add(res, "stats",
3118 							       counters);
3119 				}
3120 
3121 				dstats = view->resquerystats;
3122 				if (dstats != NULL) {
3123 					counters = json_object_new_object();
3124 					CHECKMEM(counters);
3125 
3126 					dumparg.arg = counters;
3127 					dumparg.result = ISC_R_SUCCESS;
3128 					dns_rdatatypestats_dump(dstats,
3129 								rdtypestat_dump,
3130 								&dumparg, 0);
3131 					if (dumparg.result != ISC_R_SUCCESS) {
3132 						json_object_put(counters);
3133 						result = dumparg.result;
3134 						goto error;
3135 					}
3136 
3137 					json_object_object_add(res, "qtypes",
3138 							       counters);
3139 				}
3140 
3141 				dstats = dns_db_getrrsetstats(view->cachedb);
3142 				if (dstats != NULL) {
3143 					counters = json_object_new_object();
3144 					CHECKMEM(counters);
3145 
3146 					dumparg.arg = counters;
3147 					dumparg.result = ISC_R_SUCCESS;
3148 					dns_rdatasetstats_dump(
3149 						dstats, rdatasetstats_dump,
3150 						&dumparg, 0);
3151 					if (dumparg.result != ISC_R_SUCCESS) {
3152 						json_object_put(counters);
3153 						result = dumparg.result;
3154 						goto error;
3155 					}
3156 
3157 					json_object_object_add(res, "cache",
3158 							       counters);
3159 				}
3160 
3161 				counters = json_object_new_object();
3162 				CHECKMEM(counters);
3163 
3164 				result = dns_cache_renderjson(view->cache,
3165 							      counters);
3166 				if (result != ISC_R_SUCCESS) {
3167 					json_object_put(counters);
3168 					goto error;
3169 				}
3170 
3171 				json_object_object_add(res, "cachestats",
3172 						       counters);
3173 
3174 				istats = view->adbstats;
3175 				if (istats != NULL) {
3176 					counters = json_object_new_object();
3177 					CHECKMEM(counters);
3178 
3179 					result = dump_counters(
3180 						istats, isc_statsformat_json,
3181 						counters, NULL,
3182 						adbstats_xmldesc,
3183 						dns_adbstats_max,
3184 						adbstats_index, adbstat_values,
3185 						0);
3186 					if (result != ISC_R_SUCCESS) {
3187 						json_object_put(counters);
3188 						result = dumparg.result;
3189 						goto error;
3190 					}
3191 
3192 					json_object_object_add(res, "adb",
3193 							       counters);
3194 				}
3195 			}
3196 
3197 			view = ISC_LIST_NEXT(view, link);
3198 		}
3199 	}
3200 
3201 	if ((flags & STATS_JSON_NET) != 0) {
3202 		/* socket stat counters */
3203 		json_object *sockets;
3204 		counters = json_object_new_object();
3205 
3206 		dumparg.result = ISC_R_SUCCESS;
3207 		dumparg.arg = counters;
3208 
3209 		result = dump_counters(server->sockstats, isc_statsformat_json,
3210 				       counters, NULL, sockstats_xmldesc,
3211 				       isc_sockstatscounter_max,
3212 				       sockstats_index, sockstat_values, 0);
3213 		if (result != ISC_R_SUCCESS) {
3214 			json_object_put(counters);
3215 			goto error;
3216 		}
3217 
3218 		if (json_object_get_object(counters)->count != 0) {
3219 			json_object_object_add(bindstats, "sockstats",
3220 					       counters);
3221 		} else {
3222 			json_object_put(counters);
3223 		}
3224 
3225 		sockets = json_object_new_object();
3226 		CHECKMEM(sockets);
3227 
3228 		result = isc_socketmgr_renderjson(named_g_socketmgr, sockets);
3229 		if (result != ISC_R_SUCCESS) {
3230 			json_object_put(sockets);
3231 			goto error;
3232 		}
3233 
3234 		json_object_object_add(bindstats, "socketmgr", sockets);
3235 	}
3236 
3237 	if ((flags & STATS_JSON_TASKS) != 0) {
3238 		json_object *tasks = json_object_new_object();
3239 		CHECKMEM(tasks);
3240 
3241 		result = isc_taskmgr_renderjson(named_g_taskmgr, tasks);
3242 		if (result != ISC_R_SUCCESS) {
3243 			json_object_put(tasks);
3244 			goto error;
3245 		}
3246 
3247 		json_object_object_add(bindstats, "taskmgr", tasks);
3248 	}
3249 
3250 	if ((flags & STATS_JSON_MEM) != 0) {
3251 		json_object *memory = json_object_new_object();
3252 		CHECKMEM(memory);
3253 
3254 		result = isc_mem_renderjson(memory);
3255 		if (result != ISC_R_SUCCESS) {
3256 			json_object_put(memory);
3257 			goto error;
3258 		}
3259 
3260 		json_object_object_add(bindstats, "memory", memory);
3261 	}
3262 
3263 	if ((flags & STATS_JSON_TRAFFIC) != 0) {
3264 		traffic = json_object_new_object();
3265 		CHECKMEM(traffic);
3266 
3267 		udpreq4 = json_object_new_object();
3268 		CHECKMEM(udpreq4);
3269 
3270 		udpresp4 = json_object_new_object();
3271 		CHECKMEM(udpresp4);
3272 
3273 		tcpreq4 = json_object_new_object();
3274 		CHECKMEM(tcpreq4);
3275 
3276 		tcpresp4 = json_object_new_object();
3277 		CHECKMEM(tcpresp4);
3278 
3279 		udpreq6 = json_object_new_object();
3280 		CHECKMEM(udpreq6);
3281 
3282 		udpresp6 = json_object_new_object();
3283 		CHECKMEM(udpresp6);
3284 
3285 		tcpreq6 = json_object_new_object();
3286 		CHECKMEM(tcpreq6);
3287 
3288 		tcpresp6 = json_object_new_object();
3289 		CHECKMEM(tcpresp6);
3290 
3291 		CHECK(dump_counters(
3292 			server->sctx->udpinstats4, isc_statsformat_json,
3293 			udpreq4, NULL, udpinsizestats_xmldesc,
3294 			dns_sizecounter_in_max, udpinsizestats_index,
3295 			udpinsizestat_values, 0));
3296 
3297 		CHECK(dump_counters(
3298 			server->sctx->udpoutstats4, isc_statsformat_json,
3299 			udpresp4, NULL, udpoutsizestats_xmldesc,
3300 			dns_sizecounter_out_max, udpoutsizestats_index,
3301 			udpoutsizestat_values, 0));
3302 
3303 		CHECK(dump_counters(
3304 			server->sctx->tcpinstats4, isc_statsformat_json,
3305 			tcpreq4, NULL, tcpinsizestats_xmldesc,
3306 			dns_sizecounter_in_max, tcpinsizestats_index,
3307 			tcpinsizestat_values, 0));
3308 
3309 		CHECK(dump_counters(
3310 			server->sctx->tcpoutstats4, isc_statsformat_json,
3311 			tcpresp4, NULL, tcpoutsizestats_xmldesc,
3312 			dns_sizecounter_out_max, tcpoutsizestats_index,
3313 			tcpoutsizestat_values, 0));
3314 
3315 		CHECK(dump_counters(
3316 			server->sctx->udpinstats6, isc_statsformat_json,
3317 			udpreq6, NULL, udpinsizestats_xmldesc,
3318 			dns_sizecounter_in_max, udpinsizestats_index,
3319 			udpinsizestat_values, 0));
3320 
3321 		CHECK(dump_counters(
3322 			server->sctx->udpoutstats6, isc_statsformat_json,
3323 			udpresp6, NULL, udpoutsizestats_xmldesc,
3324 			dns_sizecounter_out_max, udpoutsizestats_index,
3325 			udpoutsizestat_values, 0));
3326 
3327 		CHECK(dump_counters(
3328 			server->sctx->tcpinstats6, isc_statsformat_json,
3329 			tcpreq6, NULL, tcpinsizestats_xmldesc,
3330 			dns_sizecounter_in_max, tcpinsizestats_index,
3331 			tcpinsizestat_values, 0));
3332 
3333 		CHECK(dump_counters(
3334 			server->sctx->tcpoutstats6, isc_statsformat_json,
3335 			tcpresp6, NULL, tcpoutsizestats_xmldesc,
3336 			dns_sizecounter_out_max, tcpoutsizestats_index,
3337 			tcpoutsizestat_values, 0));
3338 
3339 		json_object_object_add(traffic,
3340 				       "dns-udp-requests-sizes-received-ipv4",
3341 				       udpreq4);
3342 		json_object_object_add(
3343 			traffic, "dns-udp-responses-sizes-sent-ipv4", udpresp4);
3344 		json_object_object_add(traffic,
3345 				       "dns-tcp-requests-sizes-received-ipv4",
3346 				       tcpreq4);
3347 		json_object_object_add(
3348 			traffic, "dns-tcp-responses-sizes-sent-ipv4", tcpresp4);
3349 		json_object_object_add(traffic,
3350 				       "dns-udp-requests-sizes-received-ipv6",
3351 				       udpreq6);
3352 		json_object_object_add(
3353 			traffic, "dns-udp-responses-sizes-sent-ipv6", udpresp6);
3354 		json_object_object_add(traffic,
3355 				       "dns-tcp-requests-sizes-received-ipv6",
3356 				       tcpreq6);
3357 		json_object_object_add(
3358 			traffic, "dns-tcp-responses-sizes-sent-ipv6", tcpresp6);
3359 		json_object_object_add(bindstats, "traffic", traffic);
3360 		udpreq4 = NULL;
3361 		udpresp4 = NULL;
3362 		tcpreq4 = NULL;
3363 		tcpresp4 = NULL;
3364 		udpreq6 = NULL;
3365 		udpresp6 = NULL;
3366 		tcpreq6 = NULL;
3367 		tcpresp6 = NULL;
3368 		traffic = NULL;
3369 	}
3370 
3371 	*msg = json_object_to_json_string_ext(bindstats,
3372 					      JSON_C_TO_STRING_PRETTY);
3373 	*msglen = strlen(*msg);
3374 
3375 	if (rootp != NULL) {
3376 		*rootp = bindstats;
3377 		bindstats = NULL;
3378 	}
3379 
3380 	result = ISC_R_SUCCESS;
3381 
3382 error:
3383 	if (udpreq4 != NULL) {
3384 		json_object_put(udpreq4);
3385 	}
3386 	if (udpresp4 != NULL) {
3387 		json_object_put(udpresp4);
3388 	}
3389 	if (tcpreq4 != NULL) {
3390 		json_object_put(tcpreq4);
3391 	}
3392 	if (tcpresp4 != NULL) {
3393 		json_object_put(tcpresp4);
3394 	}
3395 	if (udpreq6 != NULL) {
3396 		json_object_put(udpreq6);
3397 	}
3398 	if (udpresp6 != NULL) {
3399 		json_object_put(udpresp6);
3400 	}
3401 	if (tcpreq6 != NULL) {
3402 		json_object_put(tcpreq6);
3403 	}
3404 	if (tcpresp6 != NULL) {
3405 		json_object_put(tcpresp6);
3406 	}
3407 	if (traffic != NULL) {
3408 		json_object_put(traffic);
3409 	}
3410 	if (bindstats != NULL) {
3411 		json_object_put(bindstats);
3412 	}
3413 
3414 	return (result);
3415 }
3416 
3417 static isc_result_t
3418 render_json(uint32_t flags, const char *url, isc_httpdurl_t *urlinfo,
3419 	    const char *querystring, const char *headers, void *arg,
3420 	    unsigned int *retcode, const char **retmsg, const char **mimetype,
3421 	    isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) {
3422 	isc_result_t result;
3423 	json_object *bindstats = NULL;
3424 	named_server_t *server = arg;
3425 	const char *msg = NULL;
3426 	size_t msglen = 0;
3427 	char *p;
3428 
3429 	UNUSED(url);
3430 	UNUSED(urlinfo);
3431 	UNUSED(headers);
3432 	UNUSED(querystring);
3433 
3434 	result = generatejson(server, &msglen, &msg, &bindstats, flags);
3435 	if (result == ISC_R_SUCCESS) {
3436 		*retcode = 200;
3437 		*retmsg = "OK";
3438 		*mimetype = "application/json";
3439 		DE_CONST(msg, p);
3440 		isc_buffer_reinit(b, p, msglen);
3441 		isc_buffer_add(b, msglen);
3442 		*freecb = wrap_jsonfree;
3443 		*freecb_args = bindstats;
3444 	} else {
3445 		isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
3446 			      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
3447 			      "failed at rendering JSON()");
3448 	}
3449 
3450 	return (result);
3451 }
3452 
3453 static isc_result_t
3454 render_json_all(const char *url, isc_httpdurl_t *urlinfo,
3455 		const char *querystring, const char *headers, void *arg,
3456 		unsigned int *retcode, const char **retmsg,
3457 		const char **mimetype, isc_buffer_t *b,
3458 		isc_httpdfree_t **freecb, void **freecb_args) {
3459 	return (render_json(STATS_JSON_ALL, url, urlinfo, querystring, headers,
3460 			    arg, retcode, retmsg, mimetype, b, freecb,
3461 			    freecb_args));
3462 }
3463 
3464 static isc_result_t
3465 render_json_status(const char *url, isc_httpdurl_t *urlinfo,
3466 		   const char *querystring, const char *headers, void *arg,
3467 		   unsigned int *retcode, const char **retmsg,
3468 		   const char **mimetype, isc_buffer_t *b,
3469 		   isc_httpdfree_t **freecb, void **freecb_args) {
3470 	return (render_json(STATS_JSON_STATUS, url, urlinfo, querystring,
3471 			    headers, arg, retcode, retmsg, mimetype, b, freecb,
3472 			    freecb_args));
3473 }
3474 
3475 static isc_result_t
3476 render_json_server(const char *url, isc_httpdurl_t *urlinfo,
3477 		   const char *querystring, const char *headers, void *arg,
3478 		   unsigned int *retcode, const char **retmsg,
3479 		   const char **mimetype, isc_buffer_t *b,
3480 		   isc_httpdfree_t **freecb, void **freecb_args) {
3481 	return (render_json(STATS_JSON_SERVER, url, urlinfo, querystring,
3482 			    headers, arg, retcode, retmsg, mimetype, b, freecb,
3483 			    freecb_args));
3484 }
3485 
3486 static isc_result_t
3487 render_json_zones(const char *url, isc_httpdurl_t *urlinfo,
3488 		  const char *querystring, const char *headers, void *arg,
3489 		  unsigned int *retcode, const char **retmsg,
3490 		  const char **mimetype, isc_buffer_t *b,
3491 		  isc_httpdfree_t **freecb, void **freecb_args) {
3492 	return (render_json(STATS_JSON_ZONES, url, urlinfo, querystring,
3493 			    headers, arg, retcode, retmsg, mimetype, b, freecb,
3494 			    freecb_args));
3495 }
3496 
3497 static isc_result_t
3498 render_json_mem(const char *url, isc_httpdurl_t *urlinfo,
3499 		const char *querystring, const char *headers, void *arg,
3500 		unsigned int *retcode, const char **retmsg,
3501 		const char **mimetype, isc_buffer_t *b,
3502 		isc_httpdfree_t **freecb, void **freecb_args) {
3503 	return (render_json(STATS_JSON_MEM, url, urlinfo, querystring, headers,
3504 			    arg, retcode, retmsg, mimetype, b, freecb,
3505 			    freecb_args));
3506 }
3507 
3508 static isc_result_t
3509 render_json_tasks(const char *url, isc_httpdurl_t *urlinfo,
3510 		  const char *querystring, const char *headers, void *arg,
3511 		  unsigned int *retcode, const char **retmsg,
3512 		  const char **mimetype, isc_buffer_t *b,
3513 		  isc_httpdfree_t **freecb, void **freecb_args) {
3514 	return (render_json(STATS_JSON_TASKS, url, urlinfo, querystring,
3515 			    headers, arg, retcode, retmsg, mimetype, b, freecb,
3516 			    freecb_args));
3517 }
3518 
3519 static isc_result_t
3520 render_json_net(const char *url, isc_httpdurl_t *urlinfo,
3521 		const char *querystring, const char *headers, void *arg,
3522 		unsigned int *retcode, const char **retmsg,
3523 		const char **mimetype, isc_buffer_t *b,
3524 		isc_httpdfree_t **freecb, void **freecb_args) {
3525 	return (render_json(STATS_JSON_NET, url, urlinfo, querystring, headers,
3526 			    arg, retcode, retmsg, mimetype, b, freecb,
3527 			    freecb_args));
3528 }
3529 
3530 static isc_result_t
3531 render_json_traffic(const char *url, isc_httpdurl_t *urlinfo,
3532 		    const char *querystring, const char *headers, void *arg,
3533 		    unsigned int *retcode, const char **retmsg,
3534 		    const char **mimetype, isc_buffer_t *b,
3535 		    isc_httpdfree_t **freecb, void **freecb_args) {
3536 	return (render_json(STATS_JSON_TRAFFIC, url, urlinfo, querystring,
3537 			    headers, arg, retcode, retmsg, mimetype, b, freecb,
3538 			    freecb_args));
3539 }
3540 
3541 #endif /* HAVE_JSON_C */
3542 
3543 static isc_result_t
3544 render_xsl(const char *url, isc_httpdurl_t *urlinfo, const char *querystring,
3545 	   const char *headers, void *args, unsigned int *retcode,
3546 	   const char **retmsg, const char **mimetype, isc_buffer_t *b,
3547 	   isc_httpdfree_t **freecb, void **freecb_args) {
3548 	isc_result_t result;
3549 	char *_headers = NULL;
3550 
3551 	UNUSED(url);
3552 	UNUSED(querystring);
3553 	UNUSED(args);
3554 
3555 	*freecb = NULL;
3556 	*freecb_args = NULL;
3557 	*mimetype = "text/xslt+xml";
3558 
3559 	if (urlinfo->isstatic) {
3560 		isc_time_t when;
3561 		char *line, *saveptr;
3562 		const char *if_modified_since = "If-Modified-Since: ";
3563 		_headers = strdup(headers);
3564 
3565 		if (_headers == NULL) {
3566 			goto send;
3567 		}
3568 
3569 		saveptr = NULL;
3570 		for (line = strtok_r(_headers, "\n", &saveptr); line;
3571 		     line = strtok_r(NULL, "\n", &saveptr))
3572 		{
3573 			if (strncasecmp(line, if_modified_since,
3574 					strlen(if_modified_since)) == 0) {
3575 				time_t t1, t2;
3576 				line += strlen(if_modified_since);
3577 				result = isc_time_parsehttptimestamp(line,
3578 								     &when);
3579 				if (result != ISC_R_SUCCESS) {
3580 					goto send;
3581 				}
3582 
3583 				result = isc_time_secondsastimet(&when, &t1);
3584 				if (result != ISC_R_SUCCESS) {
3585 					goto send;
3586 				}
3587 
3588 				result = isc_time_secondsastimet(
3589 					&urlinfo->loadtime, &t2);
3590 				if (result != ISC_R_SUCCESS) {
3591 					goto send;
3592 				}
3593 
3594 				if (t1 < t2) {
3595 					goto send;
3596 				}
3597 
3598 				*retcode = 304;
3599 				*retmsg = "Not modified";
3600 				goto end;
3601 			}
3602 		}
3603 	}
3604 
3605 send:
3606 	*retcode = 200;
3607 	*retmsg = "OK";
3608 	isc_buffer_reinit(b, xslmsg, strlen(xslmsg));
3609 	isc_buffer_add(b, strlen(xslmsg));
3610 end:
3611 	free(_headers);
3612 	return (ISC_R_SUCCESS);
3613 }
3614 
3615 static void
3616 shutdown_listener(named_statschannel_t *listener) {
3617 	char socktext[ISC_SOCKADDR_FORMATSIZE];
3618 	isc_sockaddr_format(&listener->address, socktext, sizeof(socktext));
3619 	isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
3620 		      NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE,
3621 		      "stopping statistics channel on %s", socktext);
3622 
3623 	isc_httpdmgr_shutdown(&listener->httpdmgr);
3624 }
3625 
3626 static bool
3627 client_ok(const isc_sockaddr_t *fromaddr, void *arg) {
3628 	named_statschannel_t *listener = arg;
3629 	dns_aclenv_t *env =
3630 		ns_interfacemgr_getaclenv(named_g_server->interfacemgr);
3631 	isc_netaddr_t netaddr;
3632 	char socktext[ISC_SOCKADDR_FORMATSIZE];
3633 	int match;
3634 
3635 	REQUIRE(listener != NULL);
3636 
3637 	isc_netaddr_fromsockaddr(&netaddr, fromaddr);
3638 
3639 	LOCK(&listener->lock);
3640 	if ((dns_acl_match(&netaddr, NULL, listener->acl, env, &match, NULL) ==
3641 	     ISC_R_SUCCESS) &&
3642 	    match > 0)
3643 	{
3644 		UNLOCK(&listener->lock);
3645 		return (true);
3646 	}
3647 	UNLOCK(&listener->lock);
3648 
3649 	isc_sockaddr_format(fromaddr, socktext, sizeof(socktext));
3650 	isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
3651 		      NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
3652 		      "rejected statistics connection from %s", socktext);
3653 
3654 	return (false);
3655 }
3656 
3657 static void
3658 destroy_listener(void *arg) {
3659 	named_statschannel_t *listener = arg;
3660 
3661 	REQUIRE(listener != NULL);
3662 	REQUIRE(!ISC_LINK_LINKED(listener, link));
3663 
3664 	/* We don't have to acquire the lock here since it's already unlinked */
3665 	dns_acl_detach(&listener->acl);
3666 
3667 	isc_mutex_destroy(&listener->lock);
3668 	isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener));
3669 }
3670 
3671 static isc_result_t
3672 add_listener(named_server_t *server, named_statschannel_t **listenerp,
3673 	     const cfg_obj_t *listen_params, const cfg_obj_t *config,
3674 	     isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
3675 	     const char *socktext) {
3676 	isc_result_t result;
3677 	named_statschannel_t *listener;
3678 	isc_task_t *task = NULL;
3679 	isc_socket_t *sock = NULL;
3680 	const cfg_obj_t *allow;
3681 	dns_acl_t *new_acl = NULL;
3682 
3683 	listener = isc_mem_get(server->mctx, sizeof(*listener));
3684 
3685 	listener->httpdmgr = NULL;
3686 	listener->address = *addr;
3687 	listener->acl = NULL;
3688 	listener->mctx = NULL;
3689 	ISC_LINK_INIT(listener, link);
3690 
3691 	isc_mutex_init(&listener->lock);
3692 
3693 	isc_mem_attach(server->mctx, &listener->mctx);
3694 
3695 	allow = cfg_tuple_get(listen_params, "allow");
3696 	if (allow != NULL && cfg_obj_islist(allow)) {
3697 		result = cfg_acl_fromconfig(allow, config, named_g_lctx,
3698 					    aclconfctx, listener->mctx, 0,
3699 					    &new_acl);
3700 	} else {
3701 		result = dns_acl_any(listener->mctx, &new_acl);
3702 	}
3703 	if (result != ISC_R_SUCCESS) {
3704 		goto cleanup;
3705 	}
3706 	dns_acl_attach(new_acl, &listener->acl);
3707 	dns_acl_detach(&new_acl);
3708 
3709 	result = isc_task_create(named_g_taskmgr, 0, &task);
3710 	if (result != ISC_R_SUCCESS) {
3711 		goto cleanup;
3712 	}
3713 	isc_task_setname(task, "statchannel", NULL);
3714 
3715 	result = isc_socket_create(named_g_socketmgr, isc_sockaddr_pf(addr),
3716 				   isc_sockettype_tcp, &sock);
3717 	if (result != ISC_R_SUCCESS) {
3718 		goto cleanup;
3719 	}
3720 	isc_socket_setname(sock, "statchannel", NULL);
3721 
3722 #ifndef ISC_ALLOW_MAPPED
3723 	isc_socket_ipv6only(sock, true);
3724 #endif /* ifndef ISC_ALLOW_MAPPED */
3725 
3726 	result = isc_socket_bind(sock, addr, ISC_SOCKET_REUSEADDRESS);
3727 	if (result != ISC_R_SUCCESS) {
3728 		goto cleanup;
3729 	}
3730 
3731 	result = isc_httpdmgr_create(server->mctx, sock, task, client_ok,
3732 				     destroy_listener, listener,
3733 				     named_g_timermgr, &listener->httpdmgr);
3734 	if (result != ISC_R_SUCCESS) {
3735 		goto cleanup;
3736 	}
3737 
3738 #ifdef HAVE_LIBXML2
3739 	isc_httpdmgr_addurl(listener->httpdmgr, "/", render_xml_all, server);
3740 	isc_httpdmgr_addurl(listener->httpdmgr, "/xml", render_xml_all, server);
3741 	isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3", render_xml_all,
3742 			    server);
3743 	isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/status",
3744 			    render_xml_status, server);
3745 	isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/server",
3746 			    render_xml_server, server);
3747 	isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/zones",
3748 			    render_xml_zones, server);
3749 	isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/net", render_xml_net,
3750 			    server);
3751 	isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/tasks",
3752 			    render_xml_tasks, server);
3753 	isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/mem", render_xml_mem,
3754 			    server);
3755 	isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/traffic",
3756 			    render_xml_traffic, server);
3757 #endif /* ifdef HAVE_LIBXML2 */
3758 #ifdef HAVE_JSON_C
3759 	isc_httpdmgr_addurl(listener->httpdmgr, "/json", render_json_all,
3760 			    server);
3761 	isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1", render_json_all,
3762 			    server);
3763 	isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/status",
3764 			    render_json_status, server);
3765 	isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/server",
3766 			    render_json_server, server);
3767 	isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/zones",
3768 			    render_json_zones, server);
3769 	isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/tasks",
3770 			    render_json_tasks, server);
3771 	isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/net", render_json_net,
3772 			    server);
3773 	isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/mem", render_json_mem,
3774 			    server);
3775 	isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/traffic",
3776 			    render_json_traffic, server);
3777 #endif /* ifdef HAVE_JSON_C */
3778 	isc_httpdmgr_addurl2(listener->httpdmgr, "/bind9.xsl", true, render_xsl,
3779 			     server);
3780 
3781 	*listenerp = listener;
3782 	isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
3783 		      NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE,
3784 		      "statistics channel listening on %s", socktext);
3785 
3786 cleanup:
3787 	if (result != ISC_R_SUCCESS) {
3788 		if (listener->acl != NULL) {
3789 			dns_acl_detach(&listener->acl);
3790 		}
3791 		isc_mutex_destroy(&listener->lock);
3792 		isc_mem_putanddetach(&listener->mctx, listener,
3793 				     sizeof(*listener));
3794 	}
3795 	if (task != NULL) {
3796 		isc_task_detach(&task);
3797 	}
3798 	if (sock != NULL) {
3799 		isc_socket_detach(&sock);
3800 	}
3801 
3802 	return (result);
3803 }
3804 
3805 static void
3806 update_listener(named_server_t *server, named_statschannel_t **listenerp,
3807 		const cfg_obj_t *listen_params, const cfg_obj_t *config,
3808 		isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
3809 		const char *socktext) {
3810 	named_statschannel_t *listener;
3811 	const cfg_obj_t *allow = NULL;
3812 	dns_acl_t *new_acl = NULL;
3813 	isc_result_t result = ISC_R_SUCCESS;
3814 
3815 	for (listener = ISC_LIST_HEAD(server->statschannels); listener != NULL;
3816 	     listener = ISC_LIST_NEXT(listener, link))
3817 	{
3818 		if (isc_sockaddr_equal(addr, &listener->address)) {
3819 			break;
3820 		}
3821 	}
3822 
3823 	if (listener == NULL) {
3824 		*listenerp = NULL;
3825 		return;
3826 	}
3827 
3828 	/*
3829 	 * Now, keep the old access list unless a new one can be made.
3830 	 */
3831 	allow = cfg_tuple_get(listen_params, "allow");
3832 	if (allow != NULL && cfg_obj_islist(allow)) {
3833 		result = cfg_acl_fromconfig(allow, config, named_g_lctx,
3834 					    aclconfctx, listener->mctx, 0,
3835 					    &new_acl);
3836 	} else {
3837 		result = dns_acl_any(listener->mctx, &new_acl);
3838 	}
3839 
3840 	if (result == ISC_R_SUCCESS) {
3841 		LOCK(&listener->lock);
3842 
3843 		dns_acl_detach(&listener->acl);
3844 		dns_acl_attach(new_acl, &listener->acl);
3845 		dns_acl_detach(&new_acl);
3846 
3847 		UNLOCK(&listener->lock);
3848 	} else {
3849 		cfg_obj_log(listen_params, named_g_lctx, ISC_LOG_WARNING,
3850 			    "couldn't install new acl for "
3851 			    "statistics channel %s: %s",
3852 			    socktext, isc_result_totext(result));
3853 	}
3854 
3855 	*listenerp = listener;
3856 }
3857 
3858 isc_result_t
3859 named_statschannels_configure(named_server_t *server, const cfg_obj_t *config,
3860 			      cfg_aclconfctx_t *aclconfctx) {
3861 	named_statschannel_t *listener, *listener_next;
3862 	named_statschannellist_t new_listeners;
3863 	const cfg_obj_t *statschannellist = NULL;
3864 	const cfg_listelt_t *element, *element2;
3865 	char socktext[ISC_SOCKADDR_FORMATSIZE];
3866 
3867 	RUNTIME_CHECK(isc_once_do(&once, init_desc) == ISC_R_SUCCESS);
3868 
3869 	ISC_LIST_INIT(new_listeners);
3870 
3871 	/*
3872 	 * Get the list of named.conf 'statistics-channels' statements.
3873 	 */
3874 	(void)cfg_map_get(config, "statistics-channels", &statschannellist);
3875 
3876 	/*
3877 	 * Run through the new address/port list, noting sockets that are
3878 	 * already being listened on and moving them to the new list.
3879 	 *
3880 	 * Identifying duplicate addr/port combinations is left to either
3881 	 * the underlying config code, or to the bind attempt getting an
3882 	 * address-in-use error.
3883 	 */
3884 	if (statschannellist != NULL) {
3885 #ifndef EXTENDED_STATS
3886 		isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
3887 			      NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
3888 			      "statistics-channels specified but not effective "
3889 			      "due to missing XML and/or JSON library");
3890 #else /* EXTENDED_STATS */
3891 #ifndef HAVE_LIBXML2
3892 		isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
3893 			      NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
3894 			      "statistics-channels: XML library missing, "
3895 			      "only JSON stats will be available");
3896 #endif /* !HAVE_LIBXML2 */
3897 #ifndef HAVE_JSON_C
3898 		isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
3899 			      NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
3900 			      "statistics-channels: JSON library missing, "
3901 			      "only XML stats will be available");
3902 #endif /* !HAVE_JSON_C */
3903 #endif /* EXTENDED_STATS */
3904 
3905 		for (element = cfg_list_first(statschannellist);
3906 		     element != NULL; element = cfg_list_next(element))
3907 		{
3908 			const cfg_obj_t *statschannel;
3909 			const cfg_obj_t *listenercfg = NULL;
3910 
3911 			statschannel = cfg_listelt_value(element);
3912 			(void)cfg_map_get(statschannel, "inet", &listenercfg);
3913 			if (listenercfg == NULL) {
3914 				continue;
3915 			}
3916 
3917 			for (element2 = cfg_list_first(listenercfg);
3918 			     element2 != NULL;
3919 			     element2 = cfg_list_next(element2))
3920 			{
3921 				const cfg_obj_t *listen_params;
3922 				const cfg_obj_t *obj;
3923 				isc_sockaddr_t addr;
3924 
3925 				listen_params = cfg_listelt_value(element2);
3926 
3927 				obj = cfg_tuple_get(listen_params, "address");
3928 				addr = *cfg_obj_assockaddr(obj);
3929 				if (isc_sockaddr_getport(&addr) == 0) {
3930 					isc_sockaddr_setport(
3931 						&addr,
3932 						NAMED_STATSCHANNEL_HTTPPORT);
3933 				}
3934 
3935 				isc_sockaddr_format(&addr, socktext,
3936 						    sizeof(socktext));
3937 
3938 				isc_log_write(named_g_lctx,
3939 					      NAMED_LOGCATEGORY_GENERAL,
3940 					      NAMED_LOGMODULE_SERVER,
3941 					      ISC_LOG_DEBUG(9),
3942 					      "processing statistics "
3943 					      "channel %s",
3944 					      socktext);
3945 
3946 				update_listener(server, &listener,
3947 						listen_params, config, &addr,
3948 						aclconfctx, socktext);
3949 
3950 				if (listener != NULL) {
3951 					/*
3952 					 * Remove the listener from the old
3953 					 * list, so it won't be shut down.
3954 					 */
3955 					ISC_LIST_UNLINK(server->statschannels,
3956 							listener, link);
3957 				} else {
3958 					/*
3959 					 * This is a new listener.
3960 					 */
3961 					isc_result_t r;
3962 
3963 					r = add_listener(server, &listener,
3964 							 listen_params, config,
3965 							 &addr, aclconfctx,
3966 							 socktext);
3967 					if (r != ISC_R_SUCCESS) {
3968 						cfg_obj_log(
3969 							listen_params,
3970 							named_g_lctx,
3971 							ISC_LOG_WARNING,
3972 							"couldn't allocate "
3973 							"statistics channel"
3974 							" %s: %s",
3975 							socktext,
3976 							isc_result_totext(r));
3977 					}
3978 				}
3979 
3980 				if (listener != NULL) {
3981 					ISC_LIST_APPEND(new_listeners, listener,
3982 							link);
3983 				}
3984 			}
3985 		}
3986 	}
3987 
3988 	for (listener = ISC_LIST_HEAD(server->statschannels); listener != NULL;
3989 	     listener = listener_next)
3990 	{
3991 		listener_next = ISC_LIST_NEXT(listener, link);
3992 		ISC_LIST_UNLINK(server->statschannels, listener, link);
3993 		shutdown_listener(listener);
3994 	}
3995 
3996 	ISC_LIST_APPENDLIST(server->statschannels, new_listeners, link);
3997 	return (ISC_R_SUCCESS);
3998 }
3999 
4000 void
4001 named_statschannels_shutdown(named_server_t *server) {
4002 	named_statschannel_t *listener;
4003 
4004 	while ((listener = ISC_LIST_HEAD(server->statschannels)) != NULL) {
4005 		ISC_LIST_UNLINK(server->statschannels, listener, link);
4006 		shutdown_listener(listener);
4007 	}
4008 }
4009 
4010 isc_result_t
4011 named_stats_dump(named_server_t *server, FILE *fp) {
4012 	isc_stdtime_t now;
4013 	isc_result_t result;
4014 	dns_view_t *view;
4015 	dns_zone_t *zone, *next;
4016 	stats_dumparg_t dumparg;
4017 	uint64_t nsstat_values[ns_statscounter_max];
4018 	uint64_t resstat_values[dns_resstatscounter_max];
4019 	uint64_t adbstat_values[dns_adbstats_max];
4020 	uint64_t zonestat_values[dns_zonestatscounter_max];
4021 	uint64_t sockstat_values[isc_sockstatscounter_max];
4022 	uint64_t gluecachestats_values[dns_gluecachestatscounter_max];
4023 
4024 	RUNTIME_CHECK(isc_once_do(&once, init_desc) == ISC_R_SUCCESS);
4025 
4026 	/* Set common fields */
4027 	dumparg.type = isc_statsformat_file;
4028 	dumparg.arg = fp;
4029 
4030 	isc_stdtime_get(&now);
4031 	fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now);
4032 
4033 	fprintf(fp, "++ Incoming Requests ++\n");
4034 	dns_opcodestats_dump(server->sctx->opcodestats, opcodestat_dump,
4035 			     &dumparg, 0);
4036 
4037 	fprintf(fp, "++ Incoming Queries ++\n");
4038 	dns_rdatatypestats_dump(server->sctx->rcvquerystats, rdtypestat_dump,
4039 				&dumparg, 0);
4040 
4041 	fprintf(fp, "++ Outgoing Rcodes ++\n");
4042 	dns_rcodestats_dump(server->sctx->rcodestats, rcodestat_dump, &dumparg,
4043 			    0);
4044 
4045 	fprintf(fp, "++ Outgoing Queries ++\n");
4046 	for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
4047 	     view = ISC_LIST_NEXT(view, link))
4048 	{
4049 		if (view->resquerystats == NULL) {
4050 			continue;
4051 		}
4052 		if (strcmp(view->name, "_default") == 0) {
4053 			fprintf(fp, "[View: default]\n");
4054 		} else {
4055 			fprintf(fp, "[View: %s]\n", view->name);
4056 		}
4057 		dns_rdatatypestats_dump(view->resquerystats, rdtypestat_dump,
4058 					&dumparg, 0);
4059 	}
4060 
4061 	fprintf(fp, "++ Name Server Statistics ++\n");
4062 	(void)dump_counters(ns_stats_get(server->sctx->nsstats),
4063 			    isc_statsformat_file, fp, NULL, nsstats_desc,
4064 			    ns_statscounter_max, nsstats_index, nsstat_values,
4065 			    0);
4066 
4067 	fprintf(fp, "++ Zone Maintenance Statistics ++\n");
4068 	(void)dump_counters(server->zonestats, isc_statsformat_file, fp, NULL,
4069 			    zonestats_desc, dns_zonestatscounter_max,
4070 			    zonestats_index, zonestat_values, 0);
4071 
4072 	fprintf(fp, "++ Resolver Statistics ++\n");
4073 	fprintf(fp, "[Common]\n");
4074 	(void)dump_counters(server->resolverstats, isc_statsformat_file, fp,
4075 			    NULL, resstats_desc, dns_resstatscounter_max,
4076 			    resstats_index, resstat_values, 0);
4077 	for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
4078 	     view = ISC_LIST_NEXT(view, link))
4079 	{
4080 		if (view->resstats == NULL) {
4081 			continue;
4082 		}
4083 		if (strcmp(view->name, "_default") == 0) {
4084 			fprintf(fp, "[View: default]\n");
4085 		} else {
4086 			fprintf(fp, "[View: %s]\n", view->name);
4087 		}
4088 		(void)dump_counters(view->resstats, isc_statsformat_file, fp,
4089 				    NULL, resstats_desc,
4090 				    dns_resstatscounter_max, resstats_index,
4091 				    resstat_values, 0);
4092 	}
4093 
4094 	fprintf(fp, "++ Cache Statistics ++\n");
4095 	for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
4096 	     view = ISC_LIST_NEXT(view, link))
4097 	{
4098 		if (strcmp(view->name, "_default") == 0) {
4099 			fprintf(fp, "[View: default]\n");
4100 		} else {
4101 			fprintf(fp, "[View: %s (Cache: %s)]\n", view->name,
4102 				dns_cache_getname(view->cache));
4103 		}
4104 		/*
4105 		 * Avoid dumping redundant statistics when the cache is shared.
4106 		 */
4107 		if (dns_view_iscacheshared(view)) {
4108 			continue;
4109 		}
4110 		dns_cache_dumpstats(view->cache, fp);
4111 	}
4112 
4113 	fprintf(fp, "++ Cache DB RRsets ++\n");
4114 	for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
4115 	     view = ISC_LIST_NEXT(view, link))
4116 	{
4117 		dns_stats_t *cacherrstats;
4118 
4119 		cacherrstats = dns_db_getrrsetstats(view->cachedb);
4120 		if (cacherrstats == NULL) {
4121 			continue;
4122 		}
4123 		if (strcmp(view->name, "_default") == 0) {
4124 			fprintf(fp, "[View: default]\n");
4125 		} else {
4126 			fprintf(fp, "[View: %s (Cache: %s)]\n", view->name,
4127 				dns_cache_getname(view->cache));
4128 		}
4129 		if (dns_view_iscacheshared(view)) {
4130 			/*
4131 			 * Avoid dumping redundant statistics when the cache is
4132 			 * shared.
4133 			 */
4134 			continue;
4135 		}
4136 		dns_rdatasetstats_dump(cacherrstats, rdatasetstats_dump,
4137 				       &dumparg, 0);
4138 	}
4139 
4140 	fprintf(fp, "++ ADB stats ++\n");
4141 	for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
4142 	     view = ISC_LIST_NEXT(view, link))
4143 	{
4144 		if (view->adbstats == NULL) {
4145 			continue;
4146 		}
4147 		if (strcmp(view->name, "_default") == 0) {
4148 			fprintf(fp, "[View: default]\n");
4149 		} else {
4150 			fprintf(fp, "[View: %s]\n", view->name);
4151 		}
4152 		(void)dump_counters(view->adbstats, isc_statsformat_file, fp,
4153 				    NULL, adbstats_desc, dns_adbstats_max,
4154 				    adbstats_index, adbstat_values, 0);
4155 	}
4156 
4157 	fprintf(fp, "++ Socket I/O Statistics ++\n");
4158 	(void)dump_counters(server->sockstats, isc_statsformat_file, fp, NULL,
4159 			    sockstats_desc, isc_sockstatscounter_max,
4160 			    sockstats_index, sockstat_values, 0);
4161 
4162 	fprintf(fp, "++ Per Zone Query Statistics ++\n");
4163 	zone = NULL;
4164 	for (result = dns_zone_first(server->zonemgr, &zone);
4165 	     result == ISC_R_SUCCESS;
4166 	     next = NULL, result = dns_zone_next(zone, &next), zone = next)
4167 	{
4168 		isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
4169 		if (zonestats != NULL) {
4170 			char zonename[DNS_NAME_FORMATSIZE];
4171 
4172 			view = dns_zone_getview(zone);
4173 			if (view == NULL) {
4174 				continue;
4175 			}
4176 
4177 			dns_name_format(dns_zone_getorigin(zone), zonename,
4178 					sizeof(zonename));
4179 			fprintf(fp, "[%s", zonename);
4180 			if (strcmp(view->name, "_default") != 0) {
4181 				fprintf(fp, " (view: %s)", view->name);
4182 			}
4183 			fprintf(fp, "]\n");
4184 
4185 			(void)dump_counters(zonestats, isc_statsformat_file, fp,
4186 					    NULL, nsstats_desc,
4187 					    ns_statscounter_max, nsstats_index,
4188 					    nsstat_values, 0);
4189 		}
4190 	}
4191 
4192 	fprintf(fp, "++ Per Zone Glue Cache Statistics ++\n");
4193 	zone = NULL;
4194 	for (result = dns_zone_first(server->zonemgr, &zone);
4195 	     result == ISC_R_SUCCESS;
4196 	     next = NULL, result = dns_zone_next(zone, &next), zone = next)
4197 	{
4198 		isc_stats_t *gluecachestats = dns_zone_getgluecachestats(zone);
4199 		if (gluecachestats != NULL) {
4200 			char zonename[DNS_NAME_FORMATSIZE];
4201 
4202 			view = dns_zone_getview(zone);
4203 			if (view == NULL) {
4204 				continue;
4205 			}
4206 
4207 			dns_name_format(dns_zone_getorigin(zone), zonename,
4208 					sizeof(zonename));
4209 			fprintf(fp, "[%s", zonename);
4210 			if (strcmp(view->name, "_default") != 0) {
4211 				fprintf(fp, " (view: %s)", view->name);
4212 			}
4213 			fprintf(fp, "]\n");
4214 
4215 			(void)dump_counters(
4216 				gluecachestats, isc_statsformat_file, fp, NULL,
4217 				gluecachestats_desc,
4218 				dns_gluecachestatscounter_max,
4219 				gluecachestats_index, gluecachestats_values, 0);
4220 		}
4221 	}
4222 
4223 	fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now);
4224 
4225 	return (ISC_R_SUCCESS); /* this function currently always succeeds */
4226 }
4227