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