1 /* $NetBSD: statschannel.c,v 1.10 2014/12/10 04:37:52 christos Exp $ */
4 * Copyright (C) 2008-2014 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id: statschannel.c,v 1.28.224.1 2011/12/22 07:48:27 marka Exp */
25 #include <isc/buffer.h>
26 #include <isc/httpd.h>
29 #include <isc/print.h>
30 #include <isc/socket.h>
31 #include <isc/stats.h>
32 #include <isc/string.h>
35 #include <dns/cache.h>
37 #include <dns/opcode.h>
38 #include <dns/resolver.h>
39 #include <dns/rdataclass.h>
40 #include <dns/rdatatype.h>
41 #include <dns/stats.h>
45 #include <named/log.h>
46 #include <named/server.h>
47 #include <named/statschannel.h>
50 #include <json/json.h>
53 #include "bind9.xsl.h"
55 struct ns_statschannel
{
57 isc_httpdmgr_t
*httpdmgr
;
58 isc_sockaddr_t address
;
62 * Locked by channel lock: can be referenced and modified by both
63 * the server task and the channel task.
68 /* Locked by server task */
69 ISC_LINK(struct ns_statschannel
) link
;
74 isc_statsformat_t type
;
75 void *arg
; /* type dependent argument */
76 int ncounters
; /* for general statistics */
77 int *counterindices
; /* for general statistics */
78 isc_uint64_t
*countervalues
; /* for general statistics */
82 static isc_once_t once
= ISC_ONCE_INIT
;
84 #if defined(HAVE_LIBXML2) || defined(HAVE_JSON)
85 #define EXTENDED_STATS
91 * Statistics descriptions. These could be statistically initialized at
92 * compile time, but we configure them run time in the init_desc() function
93 * below so that they'll be less susceptible to counter name changes.
95 static const char *nsstats_desc
[dns_nsstatscounter_max
];
96 static const char *resstats_desc
[dns_resstatscounter_max
];
97 static const char *adbstats_desc
[dns_adbstats_max
];
98 static const char *zonestats_desc
[dns_zonestatscounter_max
];
99 static const char *sockstats_desc
[isc_sockstatscounter_max
];
100 static const char *dnssecstats_desc
[dns_dnssecstats_max
];
101 #if defined(EXTENDED_STATS)
102 static const char *nsstats_xmldesc
[dns_nsstatscounter_max
];
103 static const char *resstats_xmldesc
[dns_resstatscounter_max
];
104 static const char *adbstats_xmldesc
[dns_adbstats_max
];
105 static const char *zonestats_xmldesc
[dns_zonestatscounter_max
];
106 static const char *sockstats_xmldesc
[isc_sockstatscounter_max
];
107 static const char *dnssecstats_xmldesc
[dns_dnssecstats_max
];
109 #define nsstats_xmldesc NULL
110 #define resstats_xmldesc NULL
111 #define adbstats_xmldesc NULL
112 #define zonestats_xmldesc NULL
113 #define sockstats_xmldesc NULL
114 #define dnssecstats_xmldesc NULL
115 #endif /* EXTENDED_STATS */
117 #define TRY0(a) do { xmlrc = (a); if (xmlrc < 0) goto error; } while(/*CONSTCOND*/0)
120 * Mapping arrays to represent statistics counters in the order of our
121 * preference, regardless of the order of counter indices. For example,
122 * nsstats_desc[nsstats_index[0]] will be the description that is shown first.
124 static int nsstats_index
[dns_nsstatscounter_max
];
125 static int resstats_index
[dns_resstatscounter_max
];
126 static int adbstats_index
[dns_adbstats_max
];
127 static int zonestats_index
[dns_zonestatscounter_max
];
128 static int sockstats_index
[isc_sockstatscounter_max
];
129 static int dnssecstats_index
[dns_dnssecstats_max
];
132 set_desc(int counter
, int maxcounter
, const char *fdesc
, const char **fdescs
,
133 const char *xdesc
, const char **xdescs
)
135 REQUIRE(counter
< maxcounter
);
136 REQUIRE(fdescs
!= NULL
&& fdescs
[counter
] == NULL
);
137 #if defined(EXTENDED_STATS)
138 REQUIRE(xdescs
!= NULL
&& xdescs
[counter
] == NULL
);
141 fdescs
[counter
] = fdesc
;
142 #if defined(EXTENDED_STATS)
143 xdescs
[counter
] = xdesc
;
154 /* Initialize name server statistics */
155 for (i
= 0; i
< dns_nsstatscounter_max
; i
++)
156 nsstats_desc
[i
] = NULL
;
157 #if defined(EXTENDED_STATS)
158 for (i
= 0; i
< dns_nsstatscounter_max
; i
++)
159 nsstats_xmldesc
[i
] = NULL
;
162 #define SET_NSSTATDESC(counterid, desc, xmldesc) \
164 set_desc(dns_nsstatscounter_ ## counterid, \
165 dns_nsstatscounter_max, \
166 desc, nsstats_desc, xmldesc, nsstats_xmldesc); \
167 nsstats_index[i++] = dns_nsstatscounter_ ## counterid; \
168 } while (/*CONSTCOND*/0)
171 SET_NSSTATDESC(requestv4
, "IPv4 requests received", "Requestv4");
172 SET_NSSTATDESC(requestv6
, "IPv6 requests received", "Requestv6");
173 SET_NSSTATDESC(edns0in
, "requests with EDNS(0) received", "ReqEdns0");
174 SET_NSSTATDESC(badednsver
,
175 "requests with unsupported EDNS version received",
177 SET_NSSTATDESC(tsigin
, "requests with TSIG received", "ReqTSIG");
178 SET_NSSTATDESC(sig0in
, "requests with SIG(0) received", "ReqSIG0");
179 SET_NSSTATDESC(invalidsig
, "requests with invalid signature",
181 SET_NSSTATDESC(requesttcp
, "TCP requests received", "ReqTCP");
182 SET_NSSTATDESC(authrej
, "auth queries rejected", "AuthQryRej");
183 SET_NSSTATDESC(recurserej
, "recursive queries rejected", "RecQryRej");
184 SET_NSSTATDESC(xfrrej
, "transfer requests rejected", "XfrRej");
185 SET_NSSTATDESC(updaterej
, "update requests rejected", "UpdateRej");
186 SET_NSSTATDESC(response
, "responses sent", "Response");
187 SET_NSSTATDESC(truncatedresp
, "truncated responses sent",
189 SET_NSSTATDESC(edns0out
, "responses with EDNS(0) sent", "RespEDNS0");
190 SET_NSSTATDESC(tsigout
, "responses with TSIG sent", "RespTSIG");
191 SET_NSSTATDESC(sig0out
, "responses with SIG(0) sent", "RespSIG0");
192 SET_NSSTATDESC(success
, "queries resulted in successful answer",
194 SET_NSSTATDESC(authans
, "queries resulted in authoritative answer",
196 SET_NSSTATDESC(nonauthans
,
197 "queries resulted in non authoritative answer",
199 SET_NSSTATDESC(referral
, "queries resulted in referral answer",
201 SET_NSSTATDESC(nxrrset
, "queries resulted in nxrrset", "QryNxrrset");
202 SET_NSSTATDESC(servfail
, "queries resulted in SERVFAIL", "QrySERVFAIL");
203 SET_NSSTATDESC(formerr
, "queries resulted in FORMERR", "QryFORMERR");
204 SET_NSSTATDESC(nxdomain
, "queries resulted in NXDOMAIN", "QryNXDOMAIN");
205 SET_NSSTATDESC(recursion
, "queries caused recursion", "QryRecursion");
206 SET_NSSTATDESC(duplicate
, "duplicate queries received", "QryDuplicate");
207 SET_NSSTATDESC(dropped
, "queries dropped", "QryDropped");
208 SET_NSSTATDESC(failure
, "other query failures", "QryFailure");
209 SET_NSSTATDESC(xfrdone
, "requested transfers completed", "XfrReqDone");
210 SET_NSSTATDESC(updatereqfwd
, "update requests forwarded",
212 SET_NSSTATDESC(updaterespfwd
, "update responses forwarded",
214 SET_NSSTATDESC(updatefwdfail
, "update forward failed", "UpdateFwdFail");
215 SET_NSSTATDESC(updatedone
, "updates completed", "UpdateDone");
216 SET_NSSTATDESC(updatefail
, "updates failed", "UpdateFail");
217 SET_NSSTATDESC(updatebadprereq
,
218 "updates rejected due to prerequisite failure",
220 SET_NSSTATDESC(recursclients
, "recursing clients",
222 SET_NSSTATDESC(dns64
, "queries answered by DNS64", "DNS64");
223 SET_NSSTATDESC(ratedropped
, "responses dropped for rate limits",
225 SET_NSSTATDESC(rateslipped
, "responses truncated for rate limits",
227 SET_NSSTATDESC(rpz_rewrites
, "response policy zone rewrites",
229 SET_NSSTATDESC(udp
, "UDP queries received", "QryUDP");
230 SET_NSSTATDESC(tcp
, "TCP queries received", "QryTCP");
231 SET_NSSTATDESC(nsidopt
, "NSID option received", "NSIDOpt");
232 SET_NSSTATDESC(expireopt
, "Expire option recieved", "ExpireOpt");
233 SET_NSSTATDESC(otheropt
, "Other EDNS option recieved", "OtherOpt");
234 #ifdef ISC_PLATFORM_USESIT
235 SET_NSSTATDESC(sitopt
, "source identity token option received",
237 SET_NSSTATDESC(sitnew
, "new source identity token requested",
239 SET_NSSTATDESC(sitbadsize
, "source identity token - bad size",
241 SET_NSSTATDESC(sitbadtime
, "source identity token - bad time",
243 SET_NSSTATDESC(sitnomatch
, "source identity token - no match",
245 SET_NSSTATDESC(sitmatch
, "source identity token - match", "SitMatch");
247 INSIST(i
== dns_nsstatscounter_max
);
249 /* Initialize resolver statistics */
250 for (i
= 0; i
< dns_resstatscounter_max
; i
++)
251 resstats_desc
[i
] = NULL
;
252 #if defined(EXTENDED_STATS)
253 for (i
= 0; i
< dns_resstatscounter_max
; i
++)
254 resstats_xmldesc
[i
] = NULL
;
257 #define SET_RESSTATDESC(counterid, desc, xmldesc) \
259 set_desc(dns_resstatscounter_ ## counterid, \
260 dns_resstatscounter_max, \
261 desc, resstats_desc, xmldesc, resstats_xmldesc); \
262 resstats_index[i++] = dns_resstatscounter_ ## counterid; \
263 } while (/*CONSTCOND*/0)
266 SET_RESSTATDESC(queryv4
, "IPv4 queries sent", "Queryv4");
267 SET_RESSTATDESC(queryv6
, "IPv6 queries sent", "Queryv6");
268 SET_RESSTATDESC(responsev4
, "IPv4 responses received", "Responsev4");
269 SET_RESSTATDESC(responsev6
, "IPv6 responses received", "Responsev6");
270 SET_RESSTATDESC(nxdomain
, "NXDOMAIN received", "NXDOMAIN");
271 SET_RESSTATDESC(servfail
, "SERVFAIL received", "SERVFAIL");
272 SET_RESSTATDESC(formerr
, "FORMERR received", "FORMERR");
273 SET_RESSTATDESC(othererror
, "other errors received", "OtherError");
274 SET_RESSTATDESC(edns0fail
, "EDNS(0) query failures", "EDNS0Fail");
275 SET_RESSTATDESC(mismatch
, "mismatch responses received", "Mismatch");
276 SET_RESSTATDESC(truncated
, "truncated responses received", "Truncated");
277 SET_RESSTATDESC(lame
, "lame delegations received", "Lame");
278 SET_RESSTATDESC(retry
, "query retries", "Retry");
279 SET_RESSTATDESC(dispabort
, "queries aborted due to quota",
281 SET_RESSTATDESC(dispsockfail
, "failures in opening query sockets",
283 SET_RESSTATDESC(disprequdp
, "UDP queries in progress", "QueryCurUDP");
284 SET_RESSTATDESC(dispreqtcp
, "TCP queries in progress", "QueryCurTCP");
285 SET_RESSTATDESC(querytimeout
, "query timeouts", "QueryTimeout");
286 SET_RESSTATDESC(gluefetchv4
, "IPv4 NS address fetches", "GlueFetchv4");
287 SET_RESSTATDESC(gluefetchv6
, "IPv6 NS address fetches", "GlueFetchv6");
288 SET_RESSTATDESC(gluefetchv4fail
, "IPv4 NS address fetch failed",
290 SET_RESSTATDESC(gluefetchv6fail
, "IPv6 NS address fetch failed",
292 SET_RESSTATDESC(val
, "DNSSEC validation attempted", "ValAttempt");
293 SET_RESSTATDESC(valsuccess
, "DNSSEC validation succeeded", "ValOk");
294 SET_RESSTATDESC(valnegsuccess
, "DNSSEC NX validation succeeded",
296 SET_RESSTATDESC(valfail
, "DNSSEC validation failed", "ValFail");
297 SET_RESSTATDESC(queryrtt0
, "queries with RTT < "
298 DNS_RESOLVER_QRYRTTCLASS0STR
"ms",
299 "QryRTT" DNS_RESOLVER_QRYRTTCLASS0STR
);
300 SET_RESSTATDESC(queryrtt1
, "queries with RTT "
301 DNS_RESOLVER_QRYRTTCLASS0STR
"-"
302 DNS_RESOLVER_QRYRTTCLASS1STR
"ms",
303 "QryRTT" DNS_RESOLVER_QRYRTTCLASS1STR
);
304 SET_RESSTATDESC(queryrtt2
, "queries with RTT "
305 DNS_RESOLVER_QRYRTTCLASS1STR
"-"
306 DNS_RESOLVER_QRYRTTCLASS2STR
"ms",
307 "QryRTT" DNS_RESOLVER_QRYRTTCLASS2STR
);
308 SET_RESSTATDESC(queryrtt3
, "queries with RTT "
309 DNS_RESOLVER_QRYRTTCLASS2STR
"-"
310 DNS_RESOLVER_QRYRTTCLASS3STR
"ms",
311 "QryRTT" DNS_RESOLVER_QRYRTTCLASS3STR
);
312 SET_RESSTATDESC(queryrtt4
, "queries with RTT "
313 DNS_RESOLVER_QRYRTTCLASS3STR
"-"
314 DNS_RESOLVER_QRYRTTCLASS4STR
"ms",
315 "QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR
);
316 SET_RESSTATDESC(queryrtt5
, "queries with RTT > "
317 DNS_RESOLVER_QRYRTTCLASS4STR
"ms",
318 "QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR
"+");
319 SET_RESSTATDESC(nfetch
, "active fetches", "NumFetch");
320 SET_RESSTATDESC(buckets
, "bucket size", "BucketSize");
321 SET_RESSTATDESC(refused
, "REFUSED received", "REFUSED");
322 #ifdef ISC_PLATFORM_USESIT
323 SET_RESSTATDESC(sitcc
, "SIT sent client cookie only",
325 SET_RESSTATDESC(sitout
, "SIT sent with client and server cookie",
327 SET_RESSTATDESC(sitin
, "SIT replies received", "SitIn");
328 SET_RESSTATDESC(sitok
, "SIT client cookie ok", "SitClientOk");
330 SET_RESSTATDESC(badvers
, "bad EDNS version", "BadEDNSVersion");
332 INSIST(i
== dns_resstatscounter_max
);
334 /* Initialize adb statistics */
335 for (i
= 0; i
< dns_adbstats_max
; i
++)
336 adbstats_desc
[i
] = NULL
;
337 #if defined(EXTENDED_STATS)
338 for (i
= 0; i
< dns_adbstats_max
; i
++)
339 adbstats_xmldesc
[i
] = NULL
;
342 #define SET_ADBSTATDESC(id, desc, xmldesc) \
344 set_desc(dns_adbstats_ ## id, dns_adbstats_max, \
345 desc, adbstats_desc, xmldesc, adbstats_xmldesc); \
346 adbstats_index[i++] = dns_adbstats_ ## id; \
347 } while (/*CONSTCOND*/0)
349 SET_ADBSTATDESC(nentries
, "Address hash table size", "nentries");
350 SET_ADBSTATDESC(entriescnt
, "Addresses in hash table", "entriescnt");
351 SET_ADBSTATDESC(nnames
, "Name hash table size", "nnames");
352 SET_ADBSTATDESC(namescnt
, "Names in hash table", "namescnt");
354 INSIST(i
== dns_adbstats_max
);
356 /* Initialize zone statistics */
357 for (i
= 0; i
< dns_zonestatscounter_max
; i
++)
358 zonestats_desc
[i
] = NULL
;
359 #if defined(EXTENDED_STATS)
360 for (i
= 0; i
< dns_zonestatscounter_max
; i
++)
361 zonestats_xmldesc
[i
] = NULL
;
364 #define SET_ZONESTATDESC(counterid, desc, xmldesc) \
366 set_desc(dns_zonestatscounter_ ## counterid, \
367 dns_zonestatscounter_max, \
368 desc, zonestats_desc, xmldesc, zonestats_xmldesc); \
369 zonestats_index[i++] = dns_zonestatscounter_ ## counterid; \
370 } while (/*CONSTCOND*/0)
373 SET_ZONESTATDESC(notifyoutv4
, "IPv4 notifies sent", "NotifyOutv4");
374 SET_ZONESTATDESC(notifyoutv6
, "IPv6 notifies sent", "NotifyOutv6");
375 SET_ZONESTATDESC(notifyinv4
, "IPv4 notifies received", "NotifyInv4");
376 SET_ZONESTATDESC(notifyinv6
, "IPv6 notifies received", "NotifyInv6");
377 SET_ZONESTATDESC(notifyrej
, "notifies rejected", "NotifyRej");
378 SET_ZONESTATDESC(soaoutv4
, "IPv4 SOA queries sent", "SOAOutv4");
379 SET_ZONESTATDESC(soaoutv6
, "IPv6 SOA queries sent", "SOAOutv6");
380 SET_ZONESTATDESC(axfrreqv4
, "IPv4 AXFR requested", "AXFRReqv4");
381 SET_ZONESTATDESC(axfrreqv6
, "IPv6 AXFR requested", "AXFRReqv6");
382 SET_ZONESTATDESC(ixfrreqv4
, "IPv4 IXFR requested", "IXFRReqv4");
383 SET_ZONESTATDESC(ixfrreqv6
, "IPv6 IXFR requested", "IXFRReqv6");
384 SET_ZONESTATDESC(xfrsuccess
, "transfer requests succeeded",
386 SET_ZONESTATDESC(xfrfail
, "transfer requests failed", "XfrFail");
387 INSIST(i
== dns_zonestatscounter_max
);
389 /* Initialize socket statistics */
390 for (i
= 0; i
< isc_sockstatscounter_max
; i
++)
391 sockstats_desc
[i
] = NULL
;
392 #if defined(EXTENDED_STATS)
393 for (i
= 0; i
< isc_sockstatscounter_max
; i
++)
394 sockstats_xmldesc
[i
] = NULL
;
397 #define SET_SOCKSTATDESC(counterid, desc, xmldesc) \
399 set_desc(isc_sockstatscounter_ ## counterid, \
400 isc_sockstatscounter_max, \
401 desc, sockstats_desc, xmldesc, sockstats_xmldesc); \
402 sockstats_index[i++] = isc_sockstatscounter_ ## counterid; \
403 } while (/*CONSTCOND*/0)
406 SET_SOCKSTATDESC(udp4open
, "UDP/IPv4 sockets opened", "UDP4Open");
407 SET_SOCKSTATDESC(udp6open
, "UDP/IPv6 sockets opened", "UDP6Open");
408 SET_SOCKSTATDESC(tcp4open
, "TCP/IPv4 sockets opened", "TCP4Open");
409 SET_SOCKSTATDESC(tcp6open
, "TCP/IPv6 sockets opened", "TCP6Open");
410 SET_SOCKSTATDESC(unixopen
, "Unix domain sockets opened", "UnixOpen");
411 SET_SOCKSTATDESC(rawopen
, "Raw sockets opened", "RawOpen");
412 SET_SOCKSTATDESC(udp4openfail
, "UDP/IPv4 socket open failures",
414 SET_SOCKSTATDESC(udp6openfail
, "UDP/IPv6 socket open failures",
416 SET_SOCKSTATDESC(tcp4openfail
, "TCP/IPv4 socket open failures",
418 SET_SOCKSTATDESC(tcp6openfail
, "TCP/IPv6 socket open failures",
420 SET_SOCKSTATDESC(unixopenfail
, "Unix domain socket open failures",
422 SET_SOCKSTATDESC(rawopenfail
, "Raw socket open failures",
424 SET_SOCKSTATDESC(udp4close
, "UDP/IPv4 sockets closed", "UDP4Close");
425 SET_SOCKSTATDESC(udp6close
, "UDP/IPv6 sockets closed", "UDP6Close");
426 SET_SOCKSTATDESC(tcp4close
, "TCP/IPv4 sockets closed", "TCP4Close");
427 SET_SOCKSTATDESC(tcp6close
, "TCP/IPv6 sockets closed", "TCP6Close");
428 SET_SOCKSTATDESC(unixclose
, "Unix domain sockets closed", "UnixClose");
429 SET_SOCKSTATDESC(fdwatchclose
, "FDwatch sockets closed",
431 SET_SOCKSTATDESC(rawclose
, "Raw sockets closed", "RawClose");
432 SET_SOCKSTATDESC(udp4bindfail
, "UDP/IPv4 socket bind failures",
434 SET_SOCKSTATDESC(udp6bindfail
, "UDP/IPv6 socket bind failures",
436 SET_SOCKSTATDESC(tcp4bindfail
, "TCP/IPv4 socket bind failures",
438 SET_SOCKSTATDESC(tcp6bindfail
, "TCP/IPv6 socket bind failures",
440 SET_SOCKSTATDESC(unixbindfail
, "Unix domain socket bind failures",
442 SET_SOCKSTATDESC(fdwatchbindfail
, "FDwatch socket bind failures",
444 SET_SOCKSTATDESC(udp4connectfail
, "UDP/IPv4 socket connect failures",
446 SET_SOCKSTATDESC(udp6connectfail
, "UDP/IPv6 socket connect failures",
448 SET_SOCKSTATDESC(tcp4connectfail
, "TCP/IPv4 socket connect failures",
450 SET_SOCKSTATDESC(tcp6connectfail
, "TCP/IPv6 socket connect failures",
452 SET_SOCKSTATDESC(unixconnectfail
, "Unix domain socket connect failures",
454 SET_SOCKSTATDESC(fdwatchconnectfail
, "FDwatch socket connect failures",
456 SET_SOCKSTATDESC(udp4connect
, "UDP/IPv4 connections established",
458 SET_SOCKSTATDESC(udp6connect
, "UDP/IPv6 connections established",
460 SET_SOCKSTATDESC(tcp4connect
, "TCP/IPv4 connections established",
462 SET_SOCKSTATDESC(tcp6connect
, "TCP/IPv6 connections established",
464 SET_SOCKSTATDESC(unixconnect
, "Unix domain connections established",
466 SET_SOCKSTATDESC(fdwatchconnect
,
467 "FDwatch domain connections established",
469 SET_SOCKSTATDESC(tcp4acceptfail
, "TCP/IPv4 connection accept failures",
471 SET_SOCKSTATDESC(tcp6acceptfail
, "TCP/IPv6 connection accept failures",
473 SET_SOCKSTATDESC(unixacceptfail
,
474 "Unix domain connection accept failures",
476 SET_SOCKSTATDESC(tcp4accept
, "TCP/IPv4 connections accepted",
478 SET_SOCKSTATDESC(tcp6accept
, "TCP/IPv6 connections accepted",
480 SET_SOCKSTATDESC(unixaccept
, "Unix domain connections accepted",
482 SET_SOCKSTATDESC(udp4sendfail
, "UDP/IPv4 send errors", "UDP4SendErr");
483 SET_SOCKSTATDESC(udp6sendfail
, "UDP/IPv6 send errors", "UDP6SendErr");
484 SET_SOCKSTATDESC(tcp4sendfail
, "TCP/IPv4 send errors", "TCP4SendErr");
485 SET_SOCKSTATDESC(tcp6sendfail
, "TCP/IPv6 send errors", "TCP6SendErr");
486 SET_SOCKSTATDESC(unixsendfail
, "Unix domain send errors",
488 SET_SOCKSTATDESC(fdwatchsendfail
, "FDwatch send errors",
490 SET_SOCKSTATDESC(udp4recvfail
, "UDP/IPv4 recv errors", "UDP4RecvErr");
491 SET_SOCKSTATDESC(udp6recvfail
, "UDP/IPv6 recv errors", "UDP6RecvErr");
492 SET_SOCKSTATDESC(tcp4recvfail
, "TCP/IPv4 recv errors", "TCP4RecvErr");
493 SET_SOCKSTATDESC(tcp6recvfail
, "TCP/IPv6 recv errors", "TCP6RecvErr");
494 SET_SOCKSTATDESC(unixrecvfail
, "Unix domain recv errors",
496 SET_SOCKSTATDESC(fdwatchrecvfail
, "FDwatch recv errors",
498 SET_SOCKSTATDESC(rawrecvfail
, "Raw recv errors", "RawRecvErr");
499 SET_SOCKSTATDESC(udp4active
, "UDP/IPv4 sockets active", "UDP4Active");
500 SET_SOCKSTATDESC(udp6active
, "UDP/IPv6 sockets active", "UDP6Active");
501 SET_SOCKSTATDESC(tcp4active
, "TCP/IPv4 sockets active", "TCP4Active");
502 SET_SOCKSTATDESC(tcp6active
, "TCP/IPv6 sockets active", "TCP6Active");
503 SET_SOCKSTATDESC(unixactive
, "Unix domain sockets active",
505 SET_SOCKSTATDESC(rawactive
, "Raw sockets active", "RawActive");
506 INSIST(i
== isc_sockstatscounter_max
);
508 /* Initialize DNSSEC statistics */
509 for (i
= 0; i
< dns_dnssecstats_max
; i
++)
510 dnssecstats_desc
[i
] = NULL
;
511 #if defined(EXTENDED_STATS)
512 for (i
= 0; i
< dns_dnssecstats_max
; i
++)
513 dnssecstats_xmldesc
[i
] = NULL
;
516 #define SET_DNSSECSTATDESC(counterid, desc, xmldesc) \
518 set_desc(dns_dnssecstats_ ## counterid, \
519 dns_dnssecstats_max, \
520 desc, dnssecstats_desc, \
521 xmldesc, dnssecstats_xmldesc); \
522 dnssecstats_index[i++] = dns_dnssecstats_ ## counterid; \
523 } while (/*CONSTCOND*/0)
526 SET_DNSSECSTATDESC(asis
, "dnssec validation success with signer "
527 "\"as is\"", "DNSSECasis");
528 SET_DNSSECSTATDESC(downcase
, "dnssec validation success with signer "
529 "lower cased", "DNSSECdowncase");
530 SET_DNSSECSTATDESC(wildcard
, "dnssec validation of wildcard signature",
532 SET_DNSSECSTATDESC(fail
, "dnssec validation failures", "DNSSECfail");
533 INSIST(i
== dns_dnssecstats_max
);
536 for (i
= 0; i
< dns_nsstatscounter_max
; i
++)
537 INSIST(nsstats_desc
[i
] != NULL
);
538 for (i
= 0; i
< dns_resstatscounter_max
; i
++)
539 INSIST(resstats_desc
[i
] != NULL
);
540 for (i
= 0; i
< dns_adbstats_max
; i
++)
541 INSIST(adbstats_desc
[i
] != NULL
);
542 for (i
= 0; i
< dns_zonestatscounter_max
; i
++)
543 INSIST(zonestats_desc
[i
] != NULL
);
544 for (i
= 0; i
< isc_sockstatscounter_max
; i
++)
545 INSIST(sockstats_desc
[i
] != NULL
);
546 for (i
= 0; i
< dns_dnssecstats_max
; i
++)
547 INSIST(dnssecstats_desc
[i
] != NULL
);
548 #if defined(EXTENDED_STATS)
549 for (i
= 0; i
< dns_nsstatscounter_max
; i
++)
550 INSIST(nsstats_xmldesc
[i
] != NULL
);
551 for (i
= 0; i
< dns_resstatscounter_max
; i
++)
552 INSIST(resstats_xmldesc
[i
] != NULL
);
553 for (i
= 0; i
< dns_adbstats_max
; i
++)
554 INSIST(adbstats_xmldesc
[i
] != NULL
);
555 for (i
= 0; i
< dns_zonestatscounter_max
; i
++)
556 INSIST(zonestats_xmldesc
[i
] != NULL
);
557 for (i
= 0; i
< isc_sockstatscounter_max
; i
++)
558 INSIST(sockstats_xmldesc
[i
] != NULL
);
559 for (i
= 0; i
< dns_dnssecstats_max
; i
++)
560 INSIST(dnssecstats_xmldesc
[i
] != NULL
);
565 * Dump callback functions.
568 generalstat_dump(isc_statscounter_t counter
, isc_uint64_t val
, void *arg
) {
569 stats_dumparg_t
*dumparg
= arg
;
571 REQUIRE(counter
< dumparg
->ncounters
);
572 dumparg
->countervalues
[counter
] = val
;
576 dump_counters(isc_stats_t
*stats
, isc_statsformat_t type
, void *arg
,
577 const char *category
, const char **desc
, int ncounters
,
578 int *indices
, isc_uint64_t
*values
, int options
)
582 stats_dumparg_t dumparg
;
585 xmlTextWriterPtr writer
;
589 json_object
*job
, *cat
, *counter
;
592 #if !defined(EXTENDED_STATS)
597 dumparg
.ncounters
= ncounters
;
598 dumparg
.counterindices
= indices
;
599 dumparg
.countervalues
= values
;
601 memset(values
, 0, sizeof(values
[0]) * ncounters
);
602 isc_stats_dump(stats
, generalstat_dump
, &dumparg
, options
);
605 cat
= job
= (json_object
*) arg
;
606 if (ncounters
> 0 && type
== isc_statsformat_json
) {
607 if (category
!= NULL
) {
608 cat
= json_object_new_object();
610 return (ISC_R_NOMEMORY
);
611 json_object_object_add(job
, category
, cat
);
616 for (i
= 0; i
< ncounters
; i
++) {
618 value
= values
[index
];
620 if (value
== 0 && (options
& ISC_STATSDUMP_VERBOSE
) == 0)
623 switch (dumparg
.type
) {
624 case isc_statsformat_file
:
626 fprintf(fp
, "%20" ISC_PRINT_QUADFORMAT
"u %s\n",
629 case isc_statsformat_xml
:
631 writer
= (xmlTextWriterPtr
) arg
;
633 if (category
!= NULL
) {
634 /* <NameOfCategory> */
635 TRY0(xmlTextWriterStartElement(writer
,
639 /* <name> inside category */
640 TRY0(xmlTextWriterStartElement(writer
,
643 TRY0(xmlTextWriterWriteString(writer
,
646 TRY0(xmlTextWriterEndElement(writer
));
650 TRY0(xmlTextWriterStartElement(writer
,
653 TRY0(xmlTextWriterWriteFormatString(writer
,
654 "%" ISC_PRINT_QUADFORMAT
"u", value
));
656 TRY0(xmlTextWriterEndElement(writer
));
658 TRY0(xmlTextWriterEndElement(writer
));
659 /* </NameOfCategory> */
662 TRY0(xmlTextWriterStartElement(writer
,
665 TRY0(xmlTextWriterWriteAttribute(writer
,
670 TRY0(xmlTextWriterWriteFormatString(writer
,
671 "%" ISC_PRINT_QUADFORMAT
"u", value
));
672 TRY0(xmlTextWriterEndElement(writer
));
678 case isc_statsformat_json
:
680 counter
= json_object_new_int64(value
);
682 return (ISC_R_NOMEMORY
);
683 json_object_object_add(cat
, desc
[index
], counter
);
688 return (ISC_R_SUCCESS
);
691 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
692 ISC_LOG_ERROR
, "failed at dump_counters()");
693 return (ISC_R_FAILURE
);
698 rdtypestat_dump(dns_rdatastatstype_t type
, isc_uint64_t val
, void *arg
) {
701 stats_dumparg_t
*dumparg
= arg
;
704 xmlTextWriterPtr writer
;
708 json_object
*zoneobj
, *obj
;
711 if ((DNS_RDATASTATSTYPE_ATTR(type
) & DNS_RDATASTATSTYPE_ATTR_OTHERTYPE
)
713 dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type
), typebuf
,
719 switch (dumparg
->type
) {
720 case isc_statsformat_file
:
722 fprintf(fp
, "%20" ISC_PRINT_QUADFORMAT
"u %s\n", val
, typestr
);
724 case isc_statsformat_xml
:
726 writer
= dumparg
->arg
;
729 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counter"));
730 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"name",
731 ISC_XMLCHAR typestr
));
733 TRY0(xmlTextWriterWriteFormatString(writer
,
734 "%" ISC_PRINT_QUADFORMAT
"u",
737 TRY0(xmlTextWriterEndElement(writer
)); /* type */
740 case isc_statsformat_json
:
742 zoneobj
= (json_object
*) dumparg
->arg
;
743 obj
= json_object_new_int64(val
);
746 json_object_object_add(zoneobj
, typestr
, obj
);
753 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
754 ISC_LOG_ERROR
, "failed at rdtypestat_dump()");
755 dumparg
->result
= ISC_R_FAILURE
;
761 rdatasetstats_dump(dns_rdatastatstype_t type
, isc_uint64_t val
, void *arg
) {
762 stats_dumparg_t
*dumparg
= arg
;
766 isc_boolean_t nxrrset
= ISC_FALSE
;
767 isc_boolean_t stale
= ISC_FALSE
;
769 xmlTextWriterPtr writer
;
773 json_object
*zoneobj
, *obj
;
777 if ((DNS_RDATASTATSTYPE_ATTR(type
) & DNS_RDATASTATSTYPE_ATTR_NXDOMAIN
)
779 typestr
= "NXDOMAIN";
780 } else if ((DNS_RDATASTATSTYPE_ATTR(type
) &
781 DNS_RDATASTATSTYPE_ATTR_OTHERTYPE
) != 0) {
784 dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type
), typebuf
,
789 if ((DNS_RDATASTATSTYPE_ATTR(type
) & DNS_RDATASTATSTYPE_ATTR_NXRRSET
)
793 if ((DNS_RDATASTATSTYPE_ATTR(type
) & DNS_RDATASTATSTYPE_ATTR_STALE
)
797 switch (dumparg
->type
) {
798 case isc_statsformat_file
:
800 fprintf(fp
, "%20" ISC_PRINT_QUADFORMAT
"u %s%s%s\n", val
,
801 stale
? "#" : "", nxrrset
? "!" : "", typestr
);
803 case isc_statsformat_xml
:
805 writer
= dumparg
->arg
;
807 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"rrset"));
808 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"name"));
809 TRY0(xmlTextWriterWriteFormatString(writer
, "%s%s%s",
811 nxrrset
? "!" : "", typestr
));
812 TRY0(xmlTextWriterEndElement(writer
)); /* name */
814 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counter"));
815 TRY0(xmlTextWriterWriteFormatString(writer
,
816 "%" ISC_PRINT_QUADFORMAT
"u",
818 TRY0(xmlTextWriterEndElement(writer
)); /* counter */
820 TRY0(xmlTextWriterEndElement(writer
)); /* rrset */
823 case isc_statsformat_json
:
825 zoneobj
= (json_object
*) dumparg
->arg
;
826 sprintf(buf
, "%s%s%s", stale
? "#" : "",
827 nxrrset
? "!" : "", typestr
);
828 obj
= json_object_new_int64(val
);
831 json_object_object_add(zoneobj
, buf
, obj
);
838 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
839 ISC_LOG_ERROR
, "failed at rdatasetstats_dump()");
840 dumparg
->result
= ISC_R_FAILURE
;
846 opcodestat_dump(dns_opcode_t code
, isc_uint64_t val
, void *arg
) {
850 stats_dumparg_t
*dumparg
= arg
;
852 xmlTextWriterPtr writer
;
856 json_object
*zoneobj
, *obj
;
859 isc_buffer_init(&b
, codebuf
, sizeof(codebuf
) - 1);
860 dns_opcode_totext(code
, &b
);
861 codebuf
[isc_buffer_usedlength(&b
)] = '\0';
863 switch (dumparg
->type
) {
864 case isc_statsformat_file
:
866 fprintf(fp
, "%20" ISC_PRINT_QUADFORMAT
"u %s\n", val
, codebuf
);
868 case isc_statsformat_xml
:
870 writer
= dumparg
->arg
;
871 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counter"));
872 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"name",
873 ISC_XMLCHAR codebuf
));
874 TRY0(xmlTextWriterWriteFormatString(writer
,
875 "%" ISC_PRINT_QUADFORMAT
"u",
877 TRY0(xmlTextWriterEndElement(writer
)); /* counter */
880 case isc_statsformat_json
:
882 zoneobj
= (json_object
*) dumparg
->arg
;
883 obj
= json_object_new_int64(val
);
886 json_object_object_add(zoneobj
, codebuf
, obj
);
894 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
895 ISC_LOG_ERROR
, "failed at opcodestat_dump()");
896 dumparg
->result
= ISC_R_FAILURE
;
903 * Which statistics to include when rendering to XML
905 #define STATS_XML_STATUS 0x00 /* display only common statistics */
906 #define STATS_XML_SERVER 0x01
907 #define STATS_XML_ZONES 0x02
908 #define STATS_XML_TASKS 0x04
909 #define STATS_XML_NET 0x08
910 #define STATS_XML_MEM 0x10
911 #define STATS_XML_ALL 0xff
914 zone_xmlrender(dns_zone_t
*zone
, void *arg
) {
916 char buf
[1024 + 32]; /* sufficiently large for zone name and class */
917 char *zone_name_only
= NULL
;
918 dns_rdataclass_t rdclass
;
920 xmlTextWriterPtr writer
= arg
;
921 isc_stats_t
*zonestats
;
922 dns_stats_t
*rcvquerystats
;
923 dns_zonestat_level_t statlevel
;
924 isc_uint64_t nsstat_values
[dns_nsstatscounter_max
];
926 stats_dumparg_t dumparg
;
928 statlevel
= dns_zone_getstatlevel(zone
);
929 if (statlevel
== dns_zonestat_none
)
930 return (ISC_R_SUCCESS
);
932 dumparg
.type
= isc_statsformat_xml
;
933 dumparg
.arg
= writer
;
935 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"zone"));
936 dns_zone_name(zone
, buf
, sizeof(buf
));
937 zone_name_only
= strtok(buf
, "/");
938 if(zone_name_only
== NULL
)
939 zone_name_only
= buf
;
941 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"name",
942 ISC_XMLCHAR zone_name_only
));
943 rdclass
= dns_zone_getclass(zone
);
944 dns_rdataclass_format(rdclass
, buf
, sizeof(buf
));
945 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"rdataclass",
948 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"serial"));
949 if (dns_zone_getserial2(zone
, &serial
) == ISC_R_SUCCESS
)
950 TRY0(xmlTextWriterWriteFormatString(writer
, "%u", serial
));
952 TRY0(xmlTextWriterWriteString(writer
, ISC_XMLCHAR
"-"));
953 TRY0(xmlTextWriterEndElement(writer
)); /* serial */
955 zonestats
= dns_zone_getrequeststats(zone
);
956 rcvquerystats
= dns_zone_getrcvquerystats(zone
);
957 if (statlevel
== dns_zonestat_full
&& zonestats
!= NULL
) {
958 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counters"));
959 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"type",
960 ISC_XMLCHAR
"rcode"));
962 result
= dump_counters(zonestats
, isc_statsformat_xml
, writer
,
963 NULL
, nsstats_xmldesc
,
964 dns_nsstatscounter_max
, nsstats_index
,
965 nsstat_values
, ISC_STATSDUMP_VERBOSE
);
966 if (result
!= ISC_R_SUCCESS
)
968 /* counters type="rcode"*/
969 TRY0(xmlTextWriterEndElement(writer
));
972 if (statlevel
== dns_zonestat_full
&& rcvquerystats
!= NULL
) {
973 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counters"));
974 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"type",
975 ISC_XMLCHAR
"qtype"));
977 dumparg
.result
= ISC_R_SUCCESS
;
978 dns_rdatatypestats_dump(rcvquerystats
, rdtypestat_dump
,
980 if(dumparg
.result
!= ISC_R_SUCCESS
)
983 /* counters type="qtype"*/
984 TRY0(xmlTextWriterEndElement(writer
));
987 TRY0(xmlTextWriterEndElement(writer
)); /* zone */
989 return (ISC_R_SUCCESS
);
991 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
992 ISC_LOG_ERROR
, "Failed at zone_xmlrender()");
993 return (ISC_R_FAILURE
);
997 generatexml(ns_server_t
*server
, isc_uint32_t flags
,
998 int *buflen
, xmlChar
**buf
)
1000 char boottime
[sizeof "yyyy-mm-ddThh:mm:ssZ"];
1001 char configtime
[sizeof "yyyy-mm-ddThh:mm:ssZ"];
1002 char nowstr
[sizeof "yyyy-mm-ddThh:mm:ssZ"];
1004 xmlTextWriterPtr writer
= NULL
;
1005 xmlDocPtr doc
= NULL
;
1008 stats_dumparg_t dumparg
;
1009 dns_stats_t
*cacherrstats
;
1010 isc_uint64_t nsstat_values
[dns_nsstatscounter_max
];
1011 isc_uint64_t resstat_values
[dns_resstatscounter_max
];
1012 isc_uint64_t adbstat_values
[dns_adbstats_max
];
1013 isc_uint64_t zonestat_values
[dns_zonestatscounter_max
];
1014 isc_uint64_t sockstat_values
[isc_sockstatscounter_max
];
1015 isc_result_t result
;
1018 isc_time_formatISO8601(&ns_g_boottime
, boottime
, sizeof boottime
);
1019 isc_time_formatISO8601(&ns_g_configtime
, configtime
, sizeof configtime
);
1020 isc_time_formatISO8601(&now
, nowstr
, sizeof nowstr
);
1022 writer
= xmlNewTextWriterDoc(&doc
, 0);
1025 TRY0(xmlTextWriterStartDocument(writer
, NULL
, "UTF-8", NULL
));
1026 TRY0(xmlTextWriterWritePI(writer
, ISC_XMLCHAR
"xml-stylesheet",
1027 ISC_XMLCHAR
"type=\"text/xsl\" href=\"/bind9.xsl\""));
1028 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"statistics"));
1029 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"version",
1030 ISC_XMLCHAR
"3.5"));
1032 /* Set common fields for statistics dump */
1033 dumparg
.type
= isc_statsformat_xml
;
1034 dumparg
.arg
= writer
;
1036 /* Render server information */
1037 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"server"));
1038 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"boot-time"));
1039 TRY0(xmlTextWriterWriteString(writer
, ISC_XMLCHAR boottime
));
1040 TRY0(xmlTextWriterEndElement(writer
)); /* boot-time */
1041 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"config-time"));
1042 TRY0(xmlTextWriterWriteString(writer
, ISC_XMLCHAR configtime
));
1043 TRY0(xmlTextWriterEndElement(writer
)); /* config-time */
1044 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"current-time"));
1045 TRY0(xmlTextWriterWriteString(writer
, ISC_XMLCHAR nowstr
));
1046 TRY0(xmlTextWriterEndElement(writer
)); /* current-time */
1048 if ((flags
& STATS_XML_SERVER
) != 0) {
1049 dumparg
.result
= ISC_R_SUCCESS
;
1051 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counters"));
1052 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"type",
1053 ISC_XMLCHAR
"opcode"));
1055 dns_opcodestats_dump(server
->opcodestats
, opcodestat_dump
,
1056 &dumparg
, ISC_STATSDUMP_VERBOSE
);
1057 if (dumparg
.result
!= ISC_R_SUCCESS
)
1060 TRY0(xmlTextWriterEndElement(writer
));
1062 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counters"));
1063 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"type",
1064 ISC_XMLCHAR
"qtype"));
1066 dumparg
.result
= ISC_R_SUCCESS
;
1067 dns_rdatatypestats_dump(server
->rcvquerystats
, rdtypestat_dump
,
1069 if (dumparg
.result
!= ISC_R_SUCCESS
)
1071 TRY0(xmlTextWriterEndElement(writer
)); /* counters */
1073 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counters"));
1074 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"type",
1075 ISC_XMLCHAR
"nsstat"));
1077 result
= dump_counters(server
->nsstats
, isc_statsformat_xml
,
1078 writer
, NULL
, nsstats_xmldesc
,
1079 dns_nsstatscounter_max
,
1080 nsstats_index
, nsstat_values
,
1081 ISC_STATSDUMP_VERBOSE
);
1082 if (result
!= ISC_R_SUCCESS
)
1085 TRY0(xmlTextWriterEndElement(writer
)); /* /nsstat */
1087 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counters"));
1088 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"type",
1089 ISC_XMLCHAR
"zonestat"));
1091 result
= dump_counters(server
->zonestats
, isc_statsformat_xml
,
1092 writer
, NULL
, zonestats_xmldesc
,
1093 dns_zonestatscounter_max
,
1094 zonestats_index
, zonestat_values
,
1095 ISC_STATSDUMP_VERBOSE
);
1096 if (result
!= ISC_R_SUCCESS
)
1099 TRY0(xmlTextWriterEndElement(writer
)); /* /zonestat */
1102 * Most of the common resolver statistics entries are 0, so
1103 * we don't use the verbose dump here.
1105 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counters"));
1106 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"type",
1107 ISC_XMLCHAR
"resstat"));
1108 result
= dump_counters(server
->resolverstats
,
1109 isc_statsformat_xml
, writer
,
1110 NULL
, resstats_xmldesc
,
1111 dns_resstatscounter_max
,
1112 resstats_index
, resstat_values
, 0);
1113 if (result
!= ISC_R_SUCCESS
)
1115 TRY0(xmlTextWriterEndElement(writer
)); /* resstat */
1118 if ((flags
& STATS_XML_NET
) != 0) {
1119 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counters"));
1120 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"type",
1121 ISC_XMLCHAR
"sockstat"));
1123 result
= dump_counters(server
->sockstats
, isc_statsformat_xml
,
1124 writer
, NULL
, sockstats_xmldesc
,
1125 isc_sockstatscounter_max
,
1126 sockstats_index
, sockstat_values
,
1127 ISC_STATSDUMP_VERBOSE
);
1128 if (result
!= ISC_R_SUCCESS
)
1131 TRY0(xmlTextWriterEndElement(writer
)); /* /sockstat */
1133 TRY0(xmlTextWriterEndElement(writer
)); /* /server */
1136 * Render views. For each view we know of, call its
1137 * rendering function.
1139 view
= ISC_LIST_HEAD(server
->viewlist
);
1140 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"views"));
1141 while (view
!= NULL
&&
1142 ((flags
& (STATS_XML_SERVER
| STATS_XML_ZONES
)) != 0))
1144 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"view"));
1145 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"name",
1146 ISC_XMLCHAR view
->name
));
1148 if ((flags
& STATS_XML_ZONES
) != 0) {
1149 TRY0(xmlTextWriterStartElement(writer
,
1150 ISC_XMLCHAR
"zones"));
1151 result
= dns_zt_apply(view
->zonetable
, ISC_TRUE
,
1152 zone_xmlrender
, writer
);
1153 if (result
!= ISC_R_SUCCESS
)
1155 TRY0(xmlTextWriterEndElement(writer
)); /* /zones */
1158 if ((flags
& STATS_XML_SERVER
) == 0) {
1159 TRY0(xmlTextWriterEndElement(writer
)); /* /view */
1160 view
= ISC_LIST_NEXT(view
, link
);
1164 TRY0(xmlTextWriterStartElement(writer
,
1165 ISC_XMLCHAR
"counters"));
1166 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"type",
1167 ISC_XMLCHAR
"resqtype"));
1169 if (view
->resquerystats
!= NULL
) {
1170 dumparg
.result
= ISC_R_SUCCESS
;
1171 dns_rdatatypestats_dump(view
->resquerystats
,
1172 rdtypestat_dump
, &dumparg
, 0);
1173 if (dumparg
.result
!= ISC_R_SUCCESS
)
1176 TRY0(xmlTextWriterEndElement(writer
));
1179 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counters"));
1180 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"type",
1181 ISC_XMLCHAR
"resstats"));
1182 if (view
->resstats
!= NULL
) {
1183 result
= dump_counters(view
->resstats
,
1184 isc_statsformat_xml
, writer
,
1185 NULL
, resstats_xmldesc
,
1186 dns_resstatscounter_max
,
1187 resstats_index
, resstat_values
,
1188 ISC_STATSDUMP_VERBOSE
);
1189 if (result
!= ISC_R_SUCCESS
)
1192 TRY0(xmlTextWriterEndElement(writer
)); /* </resstats> */
1194 cacherrstats
= dns_db_getrrsetstats(view
->cachedb
);
1195 if (cacherrstats
!= NULL
) {
1196 TRY0(xmlTextWriterStartElement(writer
,
1197 ISC_XMLCHAR
"cache"));
1198 TRY0(xmlTextWriterWriteAttribute(writer
,
1201 dns_cache_getname(view
->cache
)));
1202 dumparg
.result
= ISC_R_SUCCESS
;
1203 dns_rdatasetstats_dump(cacherrstats
, rdatasetstats_dump
,
1205 if (dumparg
.result
!= ISC_R_SUCCESS
)
1207 TRY0(xmlTextWriterEndElement(writer
)); /* cache */
1211 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counters"));
1212 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"type",
1213 ISC_XMLCHAR
"adbstat"));
1214 if (view
->adbstats
!= NULL
) {
1215 result
= dump_counters(view
->adbstats
,
1216 isc_statsformat_xml
, writer
,
1217 NULL
, adbstats_xmldesc
,
1219 adbstats_index
, adbstat_values
,
1220 ISC_STATSDUMP_VERBOSE
);
1221 if (result
!= ISC_R_SUCCESS
)
1224 TRY0(xmlTextWriterEndElement(writer
)); /* </adbstats> */
1227 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counters"));
1228 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"type",
1229 ISC_XMLCHAR
"cachestats"));
1230 TRY0(dns_cache_renderxml(view
->cache
, writer
));
1231 TRY0(xmlTextWriterEndElement(writer
)); /* </cachestats> */
1233 TRY0(xmlTextWriterEndElement(writer
)); /* view */
1235 view
= ISC_LIST_NEXT(view
, link
);
1237 TRY0(xmlTextWriterEndElement(writer
)); /* /views */
1239 if ((flags
& STATS_XML_NET
) != 0) {
1240 TRY0(xmlTextWriterStartElement(writer
,
1241 ISC_XMLCHAR
"socketmgr"));
1242 TRY0(isc_socketmgr_renderxml(ns_g_socketmgr
, writer
));
1243 TRY0(xmlTextWriterEndElement(writer
)); /* /socketmgr */
1246 if ((flags
& STATS_XML_TASKS
) != 0) {
1247 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"taskmgr"));
1248 TRY0(isc_taskmgr_renderxml(ns_g_taskmgr
, writer
));
1249 TRY0(xmlTextWriterEndElement(writer
)); /* /taskmgr */
1252 if ((flags
& STATS_XML_MEM
) != 0) {
1253 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"memory"));
1254 TRY0(isc_mem_renderxml(writer
));
1255 TRY0(xmlTextWriterEndElement(writer
)); /* /memory */
1258 TRY0(xmlTextWriterEndElement(writer
)); /* /statistics */
1259 TRY0(xmlTextWriterEndDocument(writer
));
1261 xmlFreeTextWriter(writer
);
1263 xmlDocDumpFormatMemoryEnc(doc
, buf
, buflen
, "UTF-8", 0);
1267 return (ISC_R_SUCCESS
);
1270 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
1271 ISC_LOG_ERROR
, "failed generating XML response");
1273 xmlFreeTextWriter(writer
);
1276 return (ISC_R_FAILURE
);
1280 wrap_xmlfree(isc_buffer_t
*buffer
, void *arg
) {
1283 xmlFree(isc_buffer_base(buffer
));
1287 render_xml(isc_uint32_t flags
, const char *url
, isc_httpdurl_t
*urlinfo
,
1288 const char *querystring
, const char *headers
, void *arg
,
1289 unsigned int *retcode
, const char **retmsg
,
1290 const char **mimetype
, isc_buffer_t
*b
,
1291 isc_httpdfree_t
**freecb
, void **freecb_args
)
1293 unsigned char *msg
= NULL
;
1295 ns_server_t
*server
= arg
;
1296 isc_result_t result
;
1301 UNUSED(querystring
);
1303 result
= generatexml(server
, flags
, &msglen
, &msg
);
1305 if (result
== ISC_R_SUCCESS
) {
1308 *mimetype
= "text/xml";
1309 isc_buffer_reinit(b
, msg
, msglen
);
1310 isc_buffer_add(b
, msglen
);
1311 *freecb
= wrap_xmlfree
;
1312 *freecb_args
= NULL
;
1314 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
1315 NS_LOGMODULE_SERVER
, ISC_LOG_ERROR
,
1316 "failed at rendering XML()");
1322 render_xml_all(const char *url
, isc_httpdurl_t
*urlinfo
,
1323 const char *querystring
, const char *headers
, void *arg
,
1324 unsigned int *retcode
, const char **retmsg
,
1325 const char **mimetype
, isc_buffer_t
*b
,
1326 isc_httpdfree_t
**freecb
, void **freecb_args
)
1328 return (render_xml(STATS_XML_ALL
, url
, urlinfo
,
1329 querystring
, headers
, arg
,
1330 retcode
, retmsg
, mimetype
, b
,
1331 freecb
, freecb_args
));
1335 render_xml_status(const char *url
, isc_httpdurl_t
*urlinfo
,
1336 const char *querystring
, const char *headers
, void *arg
,
1337 unsigned int *retcode
, const char **retmsg
,
1338 const char **mimetype
, isc_buffer_t
*b
,
1339 isc_httpdfree_t
**freecb
, void **freecb_args
)
1341 return (render_xml(STATS_XML_STATUS
, url
, urlinfo
,
1342 querystring
, headers
, arg
,
1343 retcode
, retmsg
, mimetype
, b
,
1344 freecb
, freecb_args
));
1348 render_xml_server(const char *url
, isc_httpdurl_t
*urlinfo
,
1349 const char *querystring
, const char *headers
, void *arg
,
1350 unsigned int *retcode
, const char **retmsg
,
1351 const char **mimetype
, isc_buffer_t
*b
,
1352 isc_httpdfree_t
**freecb
, void **freecb_args
)
1354 return (render_xml(STATS_XML_SERVER
, url
, urlinfo
,
1355 querystring
, headers
, arg
,
1356 retcode
, retmsg
, mimetype
, b
,
1357 freecb
, freecb_args
));
1361 render_xml_zones(const char *url
, isc_httpdurl_t
*urlinfo
,
1362 const char *querystring
, const char *headers
, void *arg
,
1363 unsigned int *retcode
, const char **retmsg
,
1364 const char **mimetype
, isc_buffer_t
*b
,
1365 isc_httpdfree_t
**freecb
, void **freecb_args
)
1367 return (render_xml(STATS_XML_ZONES
, url
, urlinfo
,
1368 querystring
, headers
, arg
,
1369 retcode
, retmsg
, mimetype
, b
,
1370 freecb
, freecb_args
));
1374 render_xml_net(const char *url
, isc_httpdurl_t
*urlinfo
,
1375 const char *querystring
, const char *headers
, void *arg
,
1376 unsigned int *retcode
, const char **retmsg
,
1377 const char **mimetype
, isc_buffer_t
*b
,
1378 isc_httpdfree_t
**freecb
, void **freecb_args
)
1380 return (render_xml(STATS_XML_NET
, url
, urlinfo
,
1381 querystring
, headers
, arg
,
1382 retcode
, retmsg
, mimetype
, b
,
1383 freecb
, freecb_args
));
1387 render_xml_tasks(const char *url
, isc_httpdurl_t
*urlinfo
,
1388 const char *querystring
, const char *headers
, void *arg
,
1389 unsigned int *retcode
, const char **retmsg
,
1390 const char **mimetype
, isc_buffer_t
*b
,
1391 isc_httpdfree_t
**freecb
, void **freecb_args
)
1393 return (render_xml(STATS_XML_TASKS
, url
, urlinfo
,
1394 querystring
, headers
, arg
,
1395 retcode
, retmsg
, mimetype
, b
,
1396 freecb
, freecb_args
));
1400 render_xml_mem(const char *url
, isc_httpdurl_t
*urlinfo
,
1401 const char *querystring
, const char *headers
, void *arg
,
1402 unsigned int *retcode
, const char **retmsg
,
1403 const char **mimetype
, isc_buffer_t
*b
,
1404 isc_httpdfree_t
**freecb
, void **freecb_args
)
1406 return (render_xml(STATS_XML_MEM
, url
, urlinfo
,
1407 querystring
, headers
, arg
,
1408 retcode
, retmsg
, mimetype
, b
,
1409 freecb
, freecb_args
));
1412 #endif /* HAVE_LIBXML2 */
1416 * Which statistics to include when rendering to JSON
1418 #define STATS_JSON_STATUS 0x00 /* display only common statistics */
1419 #define STATS_JSON_SERVER 0x01
1420 #define STATS_JSON_ZONES 0x02
1421 #define STATS_JSON_TASKS 0x04
1422 #define STATS_JSON_NET 0x08
1423 #define STATS_JSON_MEM 0x10
1424 #define STATS_JSON_ALL 0xff
1426 #define CHECKMEM(m) do { \
1428 result = ISC_R_NOMEMORY;\
1431 } while(/*CONSTCOND*/0)
1434 wrap_jsonfree(isc_buffer_t
*buffer
, void *arg
) {
1435 json_object_put(isc_buffer_base(buffer
));
1437 json_object_put((json_object
*) arg
);
1440 static json_object
*
1441 addzone(char *name
, char *class, isc_uint32_t serial
) {
1442 json_object
*node
= json_object_new_object();
1447 json_object_object_add(node
, "name", json_object_new_string(name
));
1448 json_object_object_add(node
, "class", json_object_new_string(class));
1449 json_object_object_add(node
, "serial", json_object_new_int64(serial
));
1454 zone_jsonrender(dns_zone_t
*zone
, void *arg
) {
1455 isc_result_t result
= ISC_R_SUCCESS
;
1456 char buf
[1024 + 32]; /* sufficiently large for zone name and class */
1457 char class[1024 + 32]; /* sufficiently large for zone name and class */
1458 char *zone_name_only
= NULL
;
1459 char *class_only
= NULL
;
1460 dns_rdataclass_t rdclass
;
1461 isc_uint32_t serial
;
1462 isc_uint64_t nsstat_values
[dns_nsstatscounter_max
];
1463 isc_stats_t
*zonestats
;
1464 dns_stats_t
*rcvquerystats
;
1465 json_object
*zonearray
= (json_object
*) arg
;
1466 json_object
*zoneobj
= NULL
;
1467 dns_zonestat_level_t statlevel
;
1469 statlevel
= dns_zone_getstatlevel(zone
);
1470 if (statlevel
== dns_zonestat_none
)
1471 return (ISC_R_SUCCESS
);
1473 dns_zone_name(zone
, buf
, sizeof(buf
));
1474 zone_name_only
= strtok(buf
, "/");
1475 if(zone_name_only
== NULL
)
1476 zone_name_only
= buf
;
1478 rdclass
= dns_zone_getclass(zone
);
1479 dns_rdataclass_format(rdclass
, class, sizeof(class));
1482 if (dns_zone_getserial2(zone
, &serial
) != ISC_R_SUCCESS
)
1485 zoneobj
= addzone(zone_name_only
, class_only
, serial
);
1486 if (zoneobj
== NULL
)
1487 return (ISC_R_NOMEMORY
);
1489 zonestats
= dns_zone_getrequeststats(zone
);
1490 rcvquerystats
= dns_zone_getrcvquerystats(zone
);
1491 if (statlevel
== dns_zonestat_full
&& zonestats
!= NULL
) {
1492 json_object
*counters
= json_object_new_object();
1493 if (counters
== NULL
) {
1494 result
= ISC_R_NOMEMORY
;
1498 result
= dump_counters(zonestats
, isc_statsformat_json
,
1499 counters
, NULL
, nsstats_xmldesc
,
1500 dns_nsstatscounter_max
, nsstats_index
,
1502 if (result
!= ISC_R_SUCCESS
) {
1503 json_object_put(counters
);
1507 if (json_object_get_object(counters
)->count
!= 0)
1508 json_object_object_add(zoneobj
, "rcodes", counters
);
1510 json_object_put(counters
);
1513 if (statlevel
== dns_zonestat_full
&& rcvquerystats
!= NULL
) {
1514 stats_dumparg_t dumparg
;
1515 json_object
*counters
= json_object_new_object();
1518 dumparg
.type
= isc_statsformat_json
;
1519 dumparg
.arg
= counters
;
1520 dumparg
.result
= ISC_R_SUCCESS
;
1521 dns_rdatatypestats_dump(rcvquerystats
, rdtypestat_dump
,
1523 if (dumparg
.result
!= ISC_R_SUCCESS
) {
1524 json_object_put(counters
);
1528 if (json_object_get_object(counters
)->count
!= 0)
1529 json_object_object_add(zoneobj
, "qtypes", counters
);
1531 json_object_put(counters
);
1534 json_object_array_add(zonearray
, zoneobj
);
1536 result
= ISC_R_SUCCESS
;
1539 if (zoneobj
!= NULL
)
1540 json_object_put(zoneobj
);
1545 generatejson(ns_server_t
*server
, size_t *msglen
,
1546 const char **msg
, json_object
**rootp
, isc_uint32_t flags
)
1549 isc_result_t result
= ISC_R_SUCCESS
;
1550 json_object
*bindstats
, *viewlist
, *counters
, *obj
;
1551 isc_uint64_t nsstat_values
[dns_nsstatscounter_max
];
1552 isc_uint64_t resstat_values
[dns_resstatscounter_max
];
1553 isc_uint64_t adbstat_values
[dns_adbstats_max
];
1554 isc_uint64_t zonestat_values
[dns_zonestatscounter_max
];
1555 isc_uint64_t sockstat_values
[isc_sockstatscounter_max
];
1556 stats_dumparg_t dumparg
;
1557 char boottime
[sizeof "yyyy-mm-ddThh:mm:ssZ"];
1558 char configtime
[sizeof "yyyy-mm-ddThh:mm:ssZ"];
1559 char nowstr
[sizeof "yyyy-mm-ddThh:mm:ssZ"];
1562 REQUIRE(msglen
!= NULL
);
1563 REQUIRE(msg
!= NULL
&& *msg
== NULL
);
1564 REQUIRE(rootp
== NULL
|| *rootp
== NULL
);
1566 bindstats
= json_object_new_object();
1567 if (bindstats
== NULL
)
1568 return (ISC_R_NOMEMORY
);
1571 * These statistics are included no matter which URL we use.
1573 obj
= json_object_new_string("1.0");
1575 json_object_object_add(bindstats
, "json-stats-version", obj
);
1578 isc_time_formatISO8601(&ns_g_boottime
,
1579 boottime
, sizeof(boottime
));
1580 isc_time_formatISO8601(&ns_g_configtime
,
1581 configtime
, sizeof configtime
);
1582 isc_time_formatISO8601(&now
, nowstr
, sizeof(nowstr
));
1584 obj
= json_object_new_string(boottime
);
1586 json_object_object_add(bindstats
, "boot-time", obj
);
1588 obj
= json_object_new_string(configtime
);
1590 json_object_object_add(bindstats
, "config-time", obj
);
1592 obj
= json_object_new_string(nowstr
);
1594 json_object_object_add(bindstats
, "current-time", obj
);
1596 if ((flags
& STATS_JSON_SERVER
) != 0) {
1597 /* OPCODE counters */
1598 counters
= json_object_new_object();
1600 dumparg
.result
= ISC_R_SUCCESS
;
1601 dumparg
.type
= isc_statsformat_json
;
1602 dumparg
.arg
= counters
;
1604 dns_opcodestats_dump(server
->opcodestats
,
1605 opcodestat_dump
, &dumparg
,
1606 ISC_STATSDUMP_VERBOSE
);
1607 if (dumparg
.result
!= ISC_R_SUCCESS
) {
1608 json_object_put(counters
);
1612 if (json_object_get_object(counters
)->count
!= 0)
1613 json_object_object_add(bindstats
, "opcodes", counters
);
1615 json_object_put(counters
);
1617 /* QTYPE counters */
1618 counters
= json_object_new_object();
1620 dumparg
.result
= ISC_R_SUCCESS
;
1621 dumparg
.arg
= counters
;
1623 dns_rdatatypestats_dump(server
->rcvquerystats
,
1624 rdtypestat_dump
, &dumparg
, 0);
1625 if (dumparg
.result
!= ISC_R_SUCCESS
) {
1626 json_object_put(counters
);
1630 if (json_object_get_object(counters
)->count
!= 0)
1631 json_object_object_add(bindstats
, "qtypes", counters
);
1633 json_object_put(counters
);
1635 /* server stat counters */
1636 counters
= json_object_new_object();
1638 dumparg
.result
= ISC_R_SUCCESS
;
1639 dumparg
.arg
= counters
;
1641 result
= dump_counters(server
->nsstats
, isc_statsformat_json
,
1642 counters
, NULL
, nsstats_xmldesc
,
1643 dns_nsstatscounter_max
,
1644 nsstats_index
, nsstat_values
, 0);
1645 if (result
!= ISC_R_SUCCESS
) {
1646 json_object_put(counters
);
1650 if (json_object_get_object(counters
)->count
!= 0)
1651 json_object_object_add(bindstats
, "nsstats", counters
);
1653 json_object_put(counters
);
1655 /* zone stat counters */
1656 counters
= json_object_new_object();
1658 dumparg
.result
= ISC_R_SUCCESS
;
1659 dumparg
.arg
= counters
;
1661 result
= dump_counters(server
->zonestats
, isc_statsformat_json
,
1662 counters
, NULL
, zonestats_xmldesc
,
1663 dns_zonestatscounter_max
,
1664 zonestats_index
, zonestat_values
, 0);
1665 if (result
!= ISC_R_SUCCESS
) {
1666 json_object_put(counters
);
1670 if (json_object_get_object(counters
)->count
!= 0)
1671 json_object_object_add(bindstats
, "zonestats",
1674 json_object_put(counters
);
1676 /* resolver stat counters */
1677 counters
= json_object_new_object();
1679 dumparg
.result
= ISC_R_SUCCESS
;
1680 dumparg
.arg
= counters
;
1682 result
= dump_counters(server
->resolverstats
,
1683 isc_statsformat_json
, counters
, NULL
,
1685 dns_resstatscounter_max
,
1686 resstats_index
, resstat_values
, 0);
1687 if (result
!= ISC_R_SUCCESS
) {
1688 json_object_put(counters
);
1692 if (json_object_get_object(counters
)->count
!= 0)
1693 json_object_object_add(bindstats
, "resstats", counters
);
1695 json_object_put(counters
);
1698 if ((flags
& (STATS_JSON_ZONES
| STATS_JSON_SERVER
)) != 0) {
1699 viewlist
= json_object_new_object();
1702 json_object_object_add(bindstats
, "views", viewlist
);
1704 view
= ISC_LIST_HEAD(server
->viewlist
);
1705 while (view
!= NULL
) {
1706 json_object
*za
, *v
= json_object_new_object();
1709 json_object_object_add(viewlist
, view
->name
, v
);
1711 za
= json_object_new_array();
1714 if ((flags
& STATS_JSON_ZONES
) != 0) {
1715 result
= dns_zt_apply(view
->zonetable
, ISC_TRUE
,
1716 zone_jsonrender
, za
);
1717 if (result
!= ISC_R_SUCCESS
) {
1722 if (json_object_array_length(za
) != 0)
1723 json_object_object_add(v
, "zones", za
);
1725 json_object_put(za
);
1727 if ((flags
& STATS_JSON_SERVER
) != 0) {
1729 dns_stats_t
*dstats
;
1730 isc_stats_t
*istats
;
1732 res
= json_object_new_object();
1734 json_object_object_add(v
, "resolver", res
);
1736 istats
= view
->resstats
;
1737 if (istats
!= NULL
) {
1738 counters
= json_object_new_object();
1741 result
= dump_counters(istats
,
1742 isc_statsformat_json
,
1745 dns_resstatscounter_max
,
1748 if (result
!= ISC_R_SUCCESS
) {
1749 json_object_put(counters
);
1750 result
= dumparg
.result
;
1754 json_object_object_add(res
, "stats",
1758 dstats
= view
->resquerystats
;
1759 if (dstats
!= NULL
) {
1760 counters
= json_object_new_object();
1763 dumparg
.arg
= counters
;
1764 dumparg
.result
= ISC_R_SUCCESS
;
1765 dns_rdatatypestats_dump(dstats
,
1768 if (dumparg
.result
!= ISC_R_SUCCESS
) {
1769 json_object_put(counters
);
1770 result
= dumparg
.result
;
1774 json_object_object_add(res
, "qtypes",
1778 dstats
= dns_db_getrrsetstats(view
->cachedb
);
1779 if (dstats
!= NULL
) {
1780 counters
= json_object_new_object();
1783 dumparg
.arg
= counters
;
1784 dumparg
.result
= ISC_R_SUCCESS
;
1785 dns_rdatasetstats_dump(dstats
,
1788 if (dumparg
.result
!= ISC_R_SUCCESS
) {
1789 json_object_put(counters
);
1790 result
= dumparg
.result
;
1794 json_object_object_add(res
,
1799 counters
= json_object_new_object();
1802 result
= dns_cache_renderjson(view
->cache
,
1804 if (result
!= ISC_R_SUCCESS
) {
1805 json_object_put(counters
);
1809 json_object_object_add(res
, "cachestats",
1812 istats
= view
->adbstats
;
1813 if (istats
!= NULL
) {
1814 counters
= json_object_new_object();
1817 result
= dump_counters(istats
,
1818 isc_statsformat_json
,
1824 if (result
!= ISC_R_SUCCESS
) {
1825 json_object_put(counters
);
1826 result
= dumparg
.result
;
1830 json_object_object_add(res
, "adb",
1835 view
= ISC_LIST_NEXT(view
, link
);
1839 if ((flags
& STATS_JSON_NET
) != 0) {
1840 /* socket stat counters */
1841 json_object
*sockets
;
1842 counters
= json_object_new_object();
1844 dumparg
.result
= ISC_R_SUCCESS
;
1845 dumparg
.arg
= counters
;
1847 result
= dump_counters(server
->sockstats
,
1848 isc_statsformat_json
, counters
,
1849 NULL
, sockstats_xmldesc
,
1850 isc_sockstatscounter_max
,
1851 sockstats_index
, sockstat_values
, 0);
1852 if (result
!= ISC_R_SUCCESS
) {
1853 json_object_put(counters
);
1857 if (json_object_get_object(counters
)->count
!= 0)
1858 json_object_object_add(bindstats
, "sockstats",
1861 json_object_put(counters
);
1863 sockets
= json_object_new_object();
1866 result
= isc_socketmgr_renderjson(ns_g_socketmgr
, sockets
);
1867 if (result
!= ISC_R_SUCCESS
) {
1868 json_object_put(sockets
);
1872 json_object_object_add(bindstats
, "socketmgr", sockets
);
1875 if ((flags
& STATS_JSON_TASKS
) != 0) {
1876 json_object
*tasks
= json_object_new_object();
1879 result
= isc_taskmgr_renderjson(ns_g_taskmgr
, tasks
);
1880 if (result
!= ISC_R_SUCCESS
) {
1881 json_object_put(tasks
);
1885 json_object_object_add(bindstats
, "taskmgr", tasks
);
1888 if ((flags
& STATS_JSON_MEM
) != 0) {
1889 json_object
*memory
= json_object_new_object();
1892 result
= isc_mem_renderjson(memory
);
1893 if (result
!= ISC_R_SUCCESS
) {
1894 json_object_put(memory
);
1898 json_object_object_add(bindstats
, "memory", memory
);
1901 *msg
= json_object_to_json_string_ext(bindstats
,
1902 JSON_C_TO_STRING_PRETTY
);
1903 *msglen
= strlen(*msg
);
1905 if (rootp
!= NULL
) {
1910 result
= ISC_R_SUCCESS
;
1913 if (bindstats
!= NULL
)
1914 json_object_put(bindstats
);
1920 render_json(isc_uint32_t flags
,
1921 const char *url
, isc_httpdurl_t
*urlinfo
,
1922 const char *querystring
, const char *headers
,
1923 void *arg
, unsigned int *retcode
, const char **retmsg
,
1924 const char **mimetype
, isc_buffer_t
*b
,
1925 isc_httpdfree_t
**freecb
, void **freecb_args
)
1927 isc_result_t result
;
1928 json_object
*bindstats
= NULL
;
1929 ns_server_t
*server
= arg
;
1930 const char *msg
= NULL
;
1937 UNUSED(querystring
);
1939 result
= generatejson(server
, &msglen
, &msg
, &bindstats
, flags
);
1940 if (result
== ISC_R_SUCCESS
) {
1943 *mimetype
= "application/json";
1945 isc_buffer_reinit(b
, p
, msglen
);
1946 isc_buffer_add(b
, msglen
);
1947 *freecb
= wrap_jsonfree
;
1948 *freecb_args
= bindstats
;
1950 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
1951 NS_LOGMODULE_SERVER
, ISC_LOG_ERROR
,
1952 "failed at rendering JSON()");
1958 render_json_all(const char *url
, isc_httpdurl_t
*urlinfo
,
1959 const char *querystring
, const char *headers
, void *arg
,
1960 unsigned int *retcode
, const char **retmsg
,
1961 const char **mimetype
, isc_buffer_t
*b
,
1962 isc_httpdfree_t
**freecb
, void **freecb_args
)
1964 return (render_json(STATS_JSON_ALL
, url
, urlinfo
,
1965 querystring
, headers
, arg
,
1966 retcode
, retmsg
, mimetype
, b
,
1967 freecb
, freecb_args
));
1971 render_json_status(const char *url
, isc_httpdurl_t
*urlinfo
,
1972 const char *querystring
, const char *headers
, void *arg
,
1973 unsigned int *retcode
, const char **retmsg
,
1974 const char **mimetype
, isc_buffer_t
*b
,
1975 isc_httpdfree_t
**freecb
, void **freecb_args
)
1977 return (render_json(STATS_JSON_STATUS
, url
, urlinfo
,
1978 querystring
, headers
, arg
,
1979 retcode
, retmsg
, mimetype
, b
,
1980 freecb
, freecb_args
));
1984 render_json_server(const char *url
, isc_httpdurl_t
*urlinfo
,
1985 const char *querystring
, const char *headers
, void *arg
,
1986 unsigned int *retcode
, const char **retmsg
,
1987 const char **mimetype
, isc_buffer_t
*b
,
1988 isc_httpdfree_t
**freecb
, void **freecb_args
)
1990 return (render_json(STATS_JSON_SERVER
, url
, urlinfo
,
1991 querystring
, headers
, arg
,
1992 retcode
, retmsg
, mimetype
, b
,
1993 freecb
, freecb_args
));
1997 render_json_zones(const char *url
, isc_httpdurl_t
*urlinfo
,
1998 const char *querystring
, const char *headers
, void *arg
,
1999 unsigned int *retcode
, const char **retmsg
,
2000 const char **mimetype
, isc_buffer_t
*b
,
2001 isc_httpdfree_t
**freecb
, void **freecb_args
)
2003 return (render_json(STATS_JSON_ZONES
, url
, urlinfo
,
2004 querystring
, headers
, arg
,
2005 retcode
, retmsg
, mimetype
, b
,
2006 freecb
, freecb_args
));
2009 render_json_mem(const char *url
, isc_httpdurl_t
*urlinfo
,
2010 const char *querystring
, const char *headers
, void *arg
,
2011 unsigned int *retcode
, const char **retmsg
,
2012 const char **mimetype
, isc_buffer_t
*b
,
2013 isc_httpdfree_t
**freecb
, void **freecb_args
)
2015 return (render_json(STATS_JSON_MEM
, url
, urlinfo
,
2016 querystring
, headers
, arg
,
2017 retcode
, retmsg
, mimetype
, b
,
2018 freecb
, freecb_args
));
2022 render_json_tasks(const char *url
, isc_httpdurl_t
*urlinfo
,
2023 const char *querystring
, const char *headers
, void *arg
,
2024 unsigned int *retcode
, const char **retmsg
,
2025 const char **mimetype
, isc_buffer_t
*b
,
2026 isc_httpdfree_t
**freecb
, void **freecb_args
)
2028 return (render_json(STATS_JSON_TASKS
, url
, urlinfo
,
2029 querystring
, headers
, arg
,
2030 retcode
, retmsg
, mimetype
, b
,
2031 freecb
, freecb_args
));
2035 render_json_net(const char *url
, isc_httpdurl_t
*urlinfo
,
2036 const char *querystring
, const char *headers
, void *arg
,
2037 unsigned int *retcode
, const char **retmsg
,
2038 const char **mimetype
, isc_buffer_t
*b
,
2039 isc_httpdfree_t
**freecb
, void **freecb_args
)
2041 return (render_json(STATS_JSON_NET
, url
, urlinfo
,
2042 querystring
, headers
, arg
,
2043 retcode
, retmsg
, mimetype
, b
,
2044 freecb
, freecb_args
));
2046 #endif /* HAVE_JSON */
2049 render_xsl(const char *url
, isc_httpdurl_t
*urlinfo
,
2050 const char *querystring
, const char *headers
,
2051 void *args
, unsigned int *retcode
, const char **retmsg
,
2052 const char **mimetype
, isc_buffer_t
*b
,
2053 isc_httpdfree_t
**freecb
, void **freecb_args
)
2055 isc_result_t result
;
2058 UNUSED(querystring
);
2062 *freecb_args
= NULL
;
2063 *mimetype
= "text/xslt+xml";
2065 if (urlinfo
->isstatic
) {
2067 char *p
= strcasestr(headers
, "If-Modified-Since: ");
2071 p
+= strlen("If-Modified-Since: ");
2072 result
= isc_time_parsehttptimestamp(p
, &when
);
2073 if (result
!= ISC_R_SUCCESS
)
2076 result
= isc_time_secondsastimet(&when
, &t1
);
2077 if (result
!= ISC_R_SUCCESS
)
2080 result
= isc_time_secondsastimet(&urlinfo
->loadtime
,
2082 if (result
!= ISC_R_SUCCESS
)
2089 *retmsg
= "Not modified";
2090 return (ISC_R_SUCCESS
);
2097 isc_buffer_reinit(b
, xslmsg
, strlen(xslmsg
));
2098 isc_buffer_add(b
, strlen(xslmsg
));
2100 return (ISC_R_SUCCESS
);
2104 shutdown_listener(ns_statschannel_t
*listener
) {
2105 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
2106 isc_sockaddr_format(&listener
->address
, socktext
, sizeof(socktext
));
2107 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
2108 ISC_LOG_NOTICE
, "stopping statistics channel on %s",
2111 isc_httpdmgr_shutdown(&listener
->httpdmgr
);
2114 static isc_boolean_t
2115 client_ok(const isc_sockaddr_t
*fromaddr
, void *arg
) {
2116 ns_statschannel_t
*listener
= arg
;
2117 isc_netaddr_t netaddr
;
2118 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
2121 REQUIRE(listener
!= NULL
);
2123 isc_netaddr_fromsockaddr(&netaddr
, fromaddr
);
2125 LOCK(&listener
->lock
);
2126 if (dns_acl_match(&netaddr
, NULL
, listener
->acl
, &ns_g_server
->aclenv
,
2127 &match
, NULL
) == ISC_R_SUCCESS
&& match
> 0) {
2128 UNLOCK(&listener
->lock
);
2131 UNLOCK(&listener
->lock
);
2133 isc_sockaddr_format(fromaddr
, socktext
, sizeof(socktext
));
2134 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
2135 NS_LOGMODULE_SERVER
, ISC_LOG_WARNING
,
2136 "rejected statistics connection from %s", socktext
);
2142 destroy_listener(void *arg
) {
2143 ns_statschannel_t
*listener
= arg
;
2145 REQUIRE(listener
!= NULL
);
2146 REQUIRE(!ISC_LINK_LINKED(listener
, link
));
2148 /* We don't have to acquire the lock here since it's already unlinked */
2149 dns_acl_detach(&listener
->acl
);
2151 DESTROYLOCK(&listener
->lock
);
2152 isc_mem_putanddetach(&listener
->mctx
, listener
, sizeof(*listener
));
2156 add_listener(ns_server_t
*server
, ns_statschannel_t
**listenerp
,
2157 const cfg_obj_t
*listen_params
, const cfg_obj_t
*config
,
2158 isc_sockaddr_t
*addr
, cfg_aclconfctx_t
*aclconfctx
,
2159 const char *socktext
)
2161 isc_result_t result
;
2162 ns_statschannel_t
*listener
;
2163 isc_task_t
*task
= NULL
;
2164 isc_socket_t
*sock
= NULL
;
2165 const cfg_obj_t
*allow
;
2166 dns_acl_t
*new_acl
= NULL
;
2168 listener
= isc_mem_get(server
->mctx
, sizeof(*listener
));
2169 if (listener
== NULL
)
2170 return (ISC_R_NOMEMORY
);
2172 listener
->httpdmgr
= NULL
;
2173 listener
->address
= *addr
;
2174 listener
->acl
= NULL
;
2175 listener
->mctx
= NULL
;
2176 ISC_LINK_INIT(listener
, link
);
2178 result
= isc_mutex_init(&listener
->lock
);
2179 if (result
!= ISC_R_SUCCESS
) {
2180 isc_mem_put(server
->mctx
, listener
, sizeof(*listener
));
2181 return (ISC_R_FAILURE
);
2184 isc_mem_attach(server
->mctx
, &listener
->mctx
);
2186 allow
= cfg_tuple_get(listen_params
, "allow");
2187 if (allow
!= NULL
&& cfg_obj_islist(allow
)) {
2188 result
= cfg_acl_fromconfig(allow
, config
, ns_g_lctx
,
2189 aclconfctx
, listener
->mctx
, 0,
2192 result
= dns_acl_any(listener
->mctx
, &new_acl
);
2193 if (result
!= ISC_R_SUCCESS
)
2195 dns_acl_attach(new_acl
, &listener
->acl
);
2196 dns_acl_detach(&new_acl
);
2198 result
= isc_task_create(ns_g_taskmgr
, 0, &task
);
2199 if (result
!= ISC_R_SUCCESS
)
2201 isc_task_setname(task
, "statchannel", NULL
);
2203 result
= isc_socket_create(ns_g_socketmgr
, isc_sockaddr_pf(addr
),
2204 isc_sockettype_tcp
, &sock
);
2205 if (result
!= ISC_R_SUCCESS
)
2207 isc_socket_setname(sock
, "statchannel", NULL
);
2209 #ifndef ISC_ALLOW_MAPPED
2210 isc_socket_ipv6only(sock
, ISC_TRUE
);
2213 result
= isc_socket_bind(sock
, addr
, ISC_SOCKET_REUSEADDRESS
);
2214 if (result
!= ISC_R_SUCCESS
)
2217 result
= isc_httpdmgr_create(server
->mctx
, sock
, task
, client_ok
,
2218 destroy_listener
, listener
, ns_g_timermgr
,
2219 &listener
->httpdmgr
);
2220 if (result
!= ISC_R_SUCCESS
)
2224 isc_httpdmgr_addurl(listener
->httpdmgr
, "/",
2225 render_xml_all
, server
);
2226 isc_httpdmgr_addurl(listener
->httpdmgr
, "/xml",
2227 render_xml_all
, server
);
2228 isc_httpdmgr_addurl(listener
->httpdmgr
, "/xml/v3",
2229 render_xml_all
, server
);
2230 isc_httpdmgr_addurl(listener
->httpdmgr
, "/xml/v3/status",
2231 render_xml_status
, server
);
2232 isc_httpdmgr_addurl(listener
->httpdmgr
, "/xml/v3/server",
2233 render_xml_server
, server
);
2234 isc_httpdmgr_addurl(listener
->httpdmgr
, "/xml/v3/zones",
2235 render_xml_zones
, server
);
2236 isc_httpdmgr_addurl(listener
->httpdmgr
, "/xml/v3/net",
2237 render_xml_net
, server
);
2238 isc_httpdmgr_addurl(listener
->httpdmgr
, "/xml/v3/tasks",
2239 render_xml_tasks
, server
);
2240 isc_httpdmgr_addurl(listener
->httpdmgr
, "/xml/v3/mem",
2241 render_xml_mem
, server
);
2244 isc_httpdmgr_addurl(listener
->httpdmgr
, "/json",
2245 render_json_all
, server
);
2246 isc_httpdmgr_addurl(listener
->httpdmgr
, "/json/v1",
2247 render_json_all
, server
);
2248 isc_httpdmgr_addurl(listener
->httpdmgr
, "/json/v1/status",
2249 render_json_status
, server
);
2250 isc_httpdmgr_addurl(listener
->httpdmgr
, "/json/v1/server",
2251 render_json_server
, server
);
2252 isc_httpdmgr_addurl(listener
->httpdmgr
, "/json/v1/zones",
2253 render_json_zones
, server
);
2254 isc_httpdmgr_addurl(listener
->httpdmgr
, "/json/v1/tasks",
2255 render_json_tasks
, server
);
2256 isc_httpdmgr_addurl(listener
->httpdmgr
, "/json/v1/net",
2257 render_json_net
, server
);
2258 isc_httpdmgr_addurl(listener
->httpdmgr
, "/json/v1/mem",
2259 render_json_mem
, server
);
2261 isc_httpdmgr_addurl2(listener
->httpdmgr
, "/bind9.xsl", ISC_TRUE
,
2262 render_xsl
, server
);
2264 *listenerp
= listener
;
2265 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
2266 NS_LOGMODULE_SERVER
, ISC_LOG_NOTICE
,
2267 "statistics channel listening on %s", socktext
);
2270 if (result
!= ISC_R_SUCCESS
) {
2271 if (listener
->acl
!= NULL
)
2272 dns_acl_detach(&listener
->acl
);
2273 DESTROYLOCK(&listener
->lock
);
2274 isc_mem_putanddetach(&listener
->mctx
, listener
,
2278 isc_task_detach(&task
);
2280 isc_socket_detach(&sock
);
2286 update_listener(ns_server_t
*server
, ns_statschannel_t
**listenerp
,
2287 const cfg_obj_t
*listen_params
, const cfg_obj_t
*config
,
2288 isc_sockaddr_t
*addr
, cfg_aclconfctx_t
*aclconfctx
,
2289 const char *socktext
)
2291 ns_statschannel_t
*listener
;
2292 const cfg_obj_t
*allow
= NULL
;
2293 dns_acl_t
*new_acl
= NULL
;
2294 isc_result_t result
= ISC_R_SUCCESS
;
2296 for (listener
= ISC_LIST_HEAD(server
->statschannels
);
2298 listener
= ISC_LIST_NEXT(listener
, link
))
2299 if (isc_sockaddr_equal(addr
, &listener
->address
))
2302 if (listener
== NULL
) {
2308 * Now, keep the old access list unless a new one can be made.
2310 allow
= cfg_tuple_get(listen_params
, "allow");
2311 if (allow
!= NULL
&& cfg_obj_islist(allow
)) {
2312 result
= cfg_acl_fromconfig(allow
, config
, ns_g_lctx
,
2313 aclconfctx
, listener
->mctx
, 0,
2316 result
= dns_acl_any(listener
->mctx
, &new_acl
);
2318 if (result
== ISC_R_SUCCESS
) {
2319 LOCK(&listener
->lock
);
2321 dns_acl_detach(&listener
->acl
);
2322 dns_acl_attach(new_acl
, &listener
->acl
);
2323 dns_acl_detach(&new_acl
);
2325 UNLOCK(&listener
->lock
);
2327 cfg_obj_log(listen_params
, ns_g_lctx
, ISC_LOG_WARNING
,
2328 "couldn't install new acl for "
2329 "statistics channel %s: %s",
2330 socktext
, isc_result_totext(result
));
2333 *listenerp
= listener
;
2337 ns_statschannels_configure(ns_server_t
*server
, const cfg_obj_t
*config
,
2338 cfg_aclconfctx_t
*aclconfctx
)
2340 ns_statschannel_t
*listener
, *listener_next
;
2341 ns_statschannellist_t new_listeners
;
2342 const cfg_obj_t
*statschannellist
= NULL
;
2343 const cfg_listelt_t
*element
, *element2
;
2344 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
2346 RUNTIME_CHECK(isc_once_do(&once
, init_desc
) == ISC_R_SUCCESS
);
2348 ISC_LIST_INIT(new_listeners
);
2351 * Get the list of named.conf 'statistics-channels' statements.
2353 (void)cfg_map_get(config
, "statistics-channels", &statschannellist
);
2356 * Run through the new address/port list, noting sockets that are
2357 * already being listened on and moving them to the new list.
2359 * Identifying duplicate addr/port combinations is left to either
2360 * the underlying config code, or to the bind attempt getting an
2361 * address-in-use error.
2363 if (statschannellist
!= NULL
) {
2364 #ifndef EXTENDED_STATS
2365 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
2366 NS_LOGMODULE_SERVER
, ISC_LOG_WARNING
,
2367 "statistics-channels specified but not effective "
2368 "due to missing XML and/or JSON library");
2371 for (element
= cfg_list_first(statschannellist
);
2373 element
= cfg_list_next(element
)) {
2374 const cfg_obj_t
*statschannel
;
2375 const cfg_obj_t
*listenercfg
= NULL
;
2377 statschannel
= cfg_listelt_value(element
);
2378 (void)cfg_map_get(statschannel
, "inet",
2380 if (listenercfg
== NULL
)
2383 for (element2
= cfg_list_first(listenercfg
);
2385 element2
= cfg_list_next(element2
)) {
2386 const cfg_obj_t
*listen_params
;
2387 const cfg_obj_t
*obj
;
2388 isc_sockaddr_t addr
;
2390 listen_params
= cfg_listelt_value(element2
);
2392 obj
= cfg_tuple_get(listen_params
, "address");
2393 addr
= *cfg_obj_assockaddr(obj
);
2394 if (isc_sockaddr_getport(&addr
) == 0)
2395 isc_sockaddr_setport(&addr
,
2396 NS_STATSCHANNEL_HTTPPORT
);
2398 isc_sockaddr_format(&addr
, socktext
,
2401 isc_log_write(ns_g_lctx
,
2402 NS_LOGCATEGORY_GENERAL
,
2403 NS_LOGMODULE_SERVER
,
2405 "processing statistics "
2409 update_listener(server
, &listener
,
2410 listen_params
, config
, &addr
,
2411 aclconfctx
, socktext
);
2413 if (listener
!= NULL
) {
2415 * Remove the listener from the old
2416 * list, so it won't be shut down.
2418 ISC_LIST_UNLINK(server
->statschannels
,
2422 * This is a new listener.
2426 r
= add_listener(server
, &listener
,
2427 listen_params
, config
,
2430 if (r
!= ISC_R_SUCCESS
) {
2431 cfg_obj_log(listen_params
,
2434 "couldn't allocate "
2435 "statistics channel"
2438 isc_result_totext(r
));
2442 if (listener
!= NULL
)
2443 ISC_LIST_APPEND(new_listeners
, listener
,
2449 for (listener
= ISC_LIST_HEAD(server
->statschannels
);
2451 listener
= listener_next
) {
2452 listener_next
= ISC_LIST_NEXT(listener
, link
);
2453 ISC_LIST_UNLINK(server
->statschannels
, listener
, link
);
2454 shutdown_listener(listener
);
2457 ISC_LIST_APPENDLIST(server
->statschannels
, new_listeners
, link
);
2458 return (ISC_R_SUCCESS
);
2462 ns_statschannels_shutdown(ns_server_t
*server
) {
2463 ns_statschannel_t
*listener
;
2465 while ((listener
= ISC_LIST_HEAD(server
->statschannels
)) != NULL
) {
2466 ISC_LIST_UNLINK(server
->statschannels
, listener
, link
);
2467 shutdown_listener(listener
);
2472 ns_stats_dump(ns_server_t
*server
, FILE *fp
) {
2474 isc_result_t result
;
2476 dns_zone_t
*zone
, *next
;
2477 stats_dumparg_t dumparg
;
2478 isc_uint64_t nsstat_values
[dns_nsstatscounter_max
];
2479 isc_uint64_t resstat_values
[dns_resstatscounter_max
];
2480 isc_uint64_t adbstat_values
[dns_adbstats_max
];
2481 isc_uint64_t zonestat_values
[dns_zonestatscounter_max
];
2482 isc_uint64_t sockstat_values
[isc_sockstatscounter_max
];
2484 RUNTIME_CHECK(isc_once_do(&once
, init_desc
) == ISC_R_SUCCESS
);
2486 /* Set common fields */
2487 dumparg
.type
= isc_statsformat_file
;
2490 isc_stdtime_get(&now
);
2491 fprintf(fp
, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now
);
2493 fprintf(fp
, "++ Incoming Requests ++\n");
2494 dns_opcodestats_dump(server
->opcodestats
, opcodestat_dump
, &dumparg
, 0);
2496 fprintf(fp
, "++ Incoming Queries ++\n");
2497 dns_rdatatypestats_dump(server
->rcvquerystats
, rdtypestat_dump
,
2500 fprintf(fp
, "++ Outgoing Queries ++\n");
2501 for (view
= ISC_LIST_HEAD(server
->viewlist
);
2503 view
= ISC_LIST_NEXT(view
, link
)) {
2504 if (view
->resquerystats
== NULL
)
2506 if (strcmp(view
->name
, "_default") == 0)
2507 fprintf(fp
, "[View: default]\n");
2509 fprintf(fp
, "[View: %s]\n", view
->name
);
2510 dns_rdatatypestats_dump(view
->resquerystats
, rdtypestat_dump
,
2514 fprintf(fp
, "++ Name Server Statistics ++\n");
2515 (void) dump_counters(server
->nsstats
, isc_statsformat_file
, fp
, NULL
,
2516 nsstats_desc
, dns_nsstatscounter_max
,
2517 nsstats_index
, nsstat_values
, 0);
2519 fprintf(fp
, "++ Zone Maintenance Statistics ++\n");
2520 (void) dump_counters(server
->zonestats
, isc_statsformat_file
, fp
, NULL
,
2521 zonestats_desc
, dns_zonestatscounter_max
,
2522 zonestats_index
, zonestat_values
, 0);
2524 fprintf(fp
, "++ Resolver Statistics ++\n");
2525 fprintf(fp
, "[Common]\n");
2526 (void) dump_counters(server
->resolverstats
, isc_statsformat_file
, fp
,
2527 NULL
, resstats_desc
, dns_resstatscounter_max
,
2528 resstats_index
, resstat_values
, 0);
2529 for (view
= ISC_LIST_HEAD(server
->viewlist
);
2531 view
= ISC_LIST_NEXT(view
, link
)) {
2532 if (view
->resstats
== NULL
)
2534 if (strcmp(view
->name
, "_default") == 0)
2535 fprintf(fp
, "[View: default]\n");
2537 fprintf(fp
, "[View: %s]\n", view
->name
);
2538 (void) dump_counters(view
->resstats
, isc_statsformat_file
, fp
,
2539 NULL
, resstats_desc
,
2540 dns_resstatscounter_max
, resstats_index
,
2544 fprintf(fp
, "++ Cache Statistics ++\n");
2545 for (view
= ISC_LIST_HEAD(server
->viewlist
);
2547 view
= ISC_LIST_NEXT(view
, link
)) {
2548 if (strcmp(view
->name
, "_default") == 0)
2549 fprintf(fp
, "[View: default]\n");
2551 fprintf(fp
, "[View: %s (Cache: %s)]\n", view
->name
,
2552 dns_cache_getname(view
->cache
));
2554 * Avoid dumping redundant statistics when the cache is shared.
2556 if (dns_view_iscacheshared(view
))
2558 dns_cache_dumpstats(view
->cache
, fp
);
2561 fprintf(fp
, "++ Cache DB RRsets ++\n");
2562 for (view
= ISC_LIST_HEAD(server
->viewlist
);
2564 view
= ISC_LIST_NEXT(view
, link
)) {
2565 dns_stats_t
*cacherrstats
;
2567 cacherrstats
= dns_db_getrrsetstats(view
->cachedb
);
2568 if (cacherrstats
== NULL
)
2570 if (strcmp(view
->name
, "_default") == 0)
2571 fprintf(fp
, "[View: default]\n");
2573 fprintf(fp
, "[View: %s (Cache: %s)]\n", view
->name
,
2574 dns_cache_getname(view
->cache
));
2575 if (dns_view_iscacheshared(view
)) {
2577 * Avoid dumping redundant statistics when the cache is
2582 dns_rdatasetstats_dump(cacherrstats
, rdatasetstats_dump
,
2586 fprintf(fp
, "++ ADB stats ++\n");
2587 for (view
= ISC_LIST_HEAD(server
->viewlist
);
2589 view
= ISC_LIST_NEXT(view
, link
)) {
2590 if (view
->adbstats
== NULL
)
2592 if (strcmp(view
->name
, "_default") == 0)
2593 fprintf(fp
, "[View: default]\n");
2595 fprintf(fp
, "[View: %s]\n", view
->name
);
2596 (void) dump_counters(view
->adbstats
, isc_statsformat_file
, fp
,
2597 NULL
, adbstats_desc
, dns_adbstats_max
,
2598 adbstats_index
, adbstat_values
, 0);
2601 fprintf(fp
, "++ Socket I/O Statistics ++\n");
2602 (void) dump_counters(server
->sockstats
, isc_statsformat_file
, fp
, NULL
,
2603 sockstats_desc
, isc_sockstatscounter_max
,
2604 sockstats_index
, sockstat_values
, 0);
2606 fprintf(fp
, "++ Per Zone Query Statistics ++\n");
2608 for (result
= dns_zone_first(server
->zonemgr
, &zone
);
2609 result
== ISC_R_SUCCESS
;
2610 next
= NULL
, result
= dns_zone_next(zone
, &next
), zone
= next
)
2612 isc_stats_t
*zonestats
= dns_zone_getrequeststats(zone
);
2613 if (zonestats
!= NULL
) {
2614 char zonename
[DNS_NAME_FORMATSIZE
];
2616 dns_name_format(dns_zone_getorigin(zone
),
2617 zonename
, sizeof(zonename
));
2618 view
= dns_zone_getview(zone
);
2620 fprintf(fp
, "[%s", zonename
);
2621 if (strcmp(view
->name
, "_default") != 0)
2622 fprintf(fp
, " (view: %s)", view
->name
);
2625 (void) dump_counters(zonestats
, isc_statsformat_file
,
2626 fp
, NULL
, nsstats_desc
,
2627 dns_nsstatscounter_max
,
2628 nsstats_index
, nsstat_values
, 0);
2632 fprintf(fp
, "--- Statistics Dump --- (%lu)\n", (unsigned long)now
);
2634 return (ISC_R_SUCCESS
); /* this function currently always succeeds */