4 * Copyright (C) 2008, 2009 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.24 2009/10/20 03:30:07 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>
34 #include <dns/cache.h>
36 #include <dns/opcode.h>
37 #include <dns/resolver.h>
38 #include <dns/rdataclass.h>
39 #include <dns/rdatatype.h>
40 #include <dns/stats.h>
44 #include <named/log.h>
45 #include <named/server.h>
46 #include <named/statschannel.h>
48 #include "bind9.xsl.h"
50 struct ns_statschannel
{
52 isc_httpdmgr_t
*httpdmgr
;
53 isc_sockaddr_t address
;
57 * Locked by channel lock: can be referenced and modified by both
58 * the server task and the channel task.
63 /* Locked by server task */
64 ISC_LINK(struct ns_statschannel
) link
;
67 typedef enum { statsformat_file
, statsformat_xml
} statsformat_t
;
72 void *arg
; /* type dependent argument */
73 int ncounters
; /* used for general statistics */
74 int *counterindices
; /* used for general statistics */
75 isc_uint64_t
*countervalues
; /* used for general statistics */
78 static isc_once_t once
= ISC_ONCE_INIT
;
81 * Statistics descriptions. These could be statistically initialized at
82 * compile time, but we configure them run time in the init_desc() function
83 * below so that they'll be less susceptible to counter name changes.
85 static const char *nsstats_desc
[dns_nsstatscounter_max
];
86 static const char *resstats_desc
[dns_resstatscounter_max
];
87 static const char *zonestats_desc
[dns_zonestatscounter_max
];
88 static const char *sockstats_desc
[isc_sockstatscounter_max
];
90 static const char *nsstats_xmldesc
[dns_nsstatscounter_max
];
91 static const char *resstats_xmldesc
[dns_resstatscounter_max
];
92 static const char *zonestats_xmldesc
[dns_zonestatscounter_max
];
93 static const char *sockstats_xmldesc
[isc_sockstatscounter_max
];
95 #define nsstats_xmldesc NULL
96 #define resstats_xmldesc NULL
97 #define zonestats_xmldesc NULL
98 #define sockstats_xmldesc NULL
99 #endif /* HAVE_LIBXML2 */
102 * Mapping arrays to represent statistics counters in the order of our
103 * preference, regardless of the order of counter indices. For example,
104 * nsstats_desc[nsstats_index[0]] will be the description that is shown first.
106 static int nsstats_index
[dns_nsstatscounter_max
];
107 static int resstats_index
[dns_resstatscounter_max
];
108 static int zonestats_index
[dns_zonestatscounter_max
];
109 static int sockstats_index
[isc_sockstatscounter_max
];
112 set_desc(int counter
, int maxcounter
, const char *fdesc
, const char **fdescs
,
113 const char *xdesc
, const char **xdescs
)
115 REQUIRE(counter
< maxcounter
);
116 REQUIRE(fdescs
[counter
] == NULL
);
118 REQUIRE(xdescs
[counter
] == NULL
);
121 fdescs
[counter
] = fdesc
;
123 xdescs
[counter
] = xdesc
;
134 /* Initialize name server statistics */
135 for (i
= 0; i
< dns_nsstatscounter_max
; i
++)
136 nsstats_desc
[i
] = NULL
;
138 for (i
= 0; i
< dns_nsstatscounter_max
; i
++)
139 nsstats_xmldesc
[i
] = NULL
;
142 #define SET_NSSTATDESC(counterid, desc, xmldesc) \
144 set_desc(dns_nsstatscounter_ ## counterid, \
145 dns_nsstatscounter_max, \
146 desc, nsstats_desc, xmldesc, nsstats_xmldesc); \
147 nsstats_index[i++] = dns_nsstatscounter_ ## counterid; \
151 SET_NSSTATDESC(requestv4
, "IPv4 requests received", "Requestv4");
152 SET_NSSTATDESC(requestv6
, "IPv6 requests received", "Requestv6");
153 SET_NSSTATDESC(edns0in
, "requests with EDNS(0) received", "ReqEdns0");
154 SET_NSSTATDESC(badednsver
,
155 "requests with unsupported EDNS version received",
157 SET_NSSTATDESC(tsigin
, "requests with TSIG received", "ReqTSIG");
158 SET_NSSTATDESC(sig0in
, "requests with SIG(0) received", "ReqSIG0");
159 SET_NSSTATDESC(invalidsig
, "requests with invalid signature",
161 SET_NSSTATDESC(tcp
, "TCP requests received", "ReqTCP");
162 SET_NSSTATDESC(authrej
, "auth queries rejected", "AuthQryRej");
163 SET_NSSTATDESC(recurserej
, "recursive queries rejected", "RecQryRej");
164 SET_NSSTATDESC(xfrrej
, "transfer requests rejected", "XfrRej");
165 SET_NSSTATDESC(updaterej
, "update requests rejected", "UpdateRej");
166 SET_NSSTATDESC(response
, "responses sent", "Response");
167 SET_NSSTATDESC(truncatedresp
, "truncated responses sent",
169 SET_NSSTATDESC(edns0out
, "responses with EDNS(0) sent", "RespEDNS0");
170 SET_NSSTATDESC(tsigout
, "responses with TSIG sent", "RespTSIG");
171 SET_NSSTATDESC(sig0out
, "responses with SIG(0) sent", "RespSIG0");
172 SET_NSSTATDESC(success
, "queries resulted in successful answer",
174 SET_NSSTATDESC(authans
, "queries resulted in authoritative answer",
176 SET_NSSTATDESC(nonauthans
,
177 "queries resulted in non authoritative answer",
179 SET_NSSTATDESC(referral
, "queries resulted in referral answer",
181 SET_NSSTATDESC(nxrrset
, "queries resulted in nxrrset", "QryNxrrset");
182 SET_NSSTATDESC(servfail
, "queries resulted in SERVFAIL", "QrySERVFAIL");
183 SET_NSSTATDESC(formerr
, "queries resulted in FORMERR", "QryFORMERR");
184 SET_NSSTATDESC(nxdomain
, "queries resulted in NXDOMAIN", "QryNXDOMAIN");
185 SET_NSSTATDESC(recursion
, "queries caused recursion","QryRecursion");
186 SET_NSSTATDESC(duplicate
, "duplicate queries received", "QryDuplicate");
187 SET_NSSTATDESC(dropped
, "queries dropped", "QryDropped");
188 SET_NSSTATDESC(failure
, "other query failures", "QryFailure");
189 SET_NSSTATDESC(xfrdone
, "requested transfers completed", "XfrReqDone");
190 SET_NSSTATDESC(updatereqfwd
, "update requests forwarded",
192 SET_NSSTATDESC(updaterespfwd
, "update responses forwarded",
194 SET_NSSTATDESC(updatefwdfail
, "update forward failed", "UpdateFwdFail");
195 SET_NSSTATDESC(updatedone
, "updates completed", "UpdateDone");
196 SET_NSSTATDESC(updatefail
, "updates failed", "UpdateFail");
197 SET_NSSTATDESC(updatebadprereq
,
198 "updates rejected due to prerequisite failure",
200 INSIST(i
== dns_nsstatscounter_max
);
202 /* Initialize resolver statistics */
203 for (i
= 0; i
< dns_resstatscounter_max
; i
++)
204 resstats_desc
[i
] = NULL
;
206 for (i
= 0; i
< dns_resstatscounter_max
; i
++)
207 resstats_xmldesc
[i
] = NULL
;
210 #define SET_RESSTATDESC(counterid, desc, xmldesc) \
212 set_desc(dns_resstatscounter_ ## counterid, \
213 dns_resstatscounter_max, \
214 desc, resstats_desc, xmldesc, resstats_xmldesc); \
215 resstats_index[i++] = dns_resstatscounter_ ## counterid; \
219 SET_RESSTATDESC(queryv4
, "IPv4 queries sent", "Queryv4");
220 SET_RESSTATDESC(queryv6
, "IPv6 queries sent", "Queryv6");
221 SET_RESSTATDESC(responsev4
, "IPv4 responses received", "Responsev4");
222 SET_RESSTATDESC(responsev6
, "IPv6 responses received", "Responsev6");
223 SET_RESSTATDESC(nxdomain
, "NXDOMAIN received", "NXDOMAIN");
224 SET_RESSTATDESC(servfail
, "SERVFAIL received", "SERVFAIL");
225 SET_RESSTATDESC(formerr
, "FORMERR received", "FORMERR");
226 SET_RESSTATDESC(othererror
, "other errors received", "OtherError");
227 SET_RESSTATDESC(edns0fail
, "EDNS(0) query failures", "EDNS0Fail");
228 SET_RESSTATDESC(mismatch
, "mismatch responses received", "Mismatch");
229 SET_RESSTATDESC(truncated
, "truncated responses received", "Truncated");
230 SET_RESSTATDESC(lame
, "lame delegations received", "Lame");
231 SET_RESSTATDESC(retry
, "query retries", "Retry");
232 SET_RESSTATDESC(dispabort
, "queries aborted due to quota",
234 SET_RESSTATDESC(dispsockfail
, "failures in opening query sockets",
236 SET_RESSTATDESC(querytimeout
, "query timeouts", "QueryTimeout");
237 SET_RESSTATDESC(gluefetchv4
, "IPv4 NS address fetches", "GlueFetchv4");
238 SET_RESSTATDESC(gluefetchv6
, "IPv6 NS address fetches", "GlueFetchv6");
239 SET_RESSTATDESC(gluefetchv4fail
, "IPv4 NS address fetch failed",
241 SET_RESSTATDESC(gluefetchv6fail
, "IPv6 NS address fetch failed",
243 SET_RESSTATDESC(val
, "DNSSEC validation attempted", "ValAttempt");
244 SET_RESSTATDESC(valsuccess
, "DNSSEC validation succeeded", "ValOk");
245 SET_RESSTATDESC(valnegsuccess
, "DNSSEC NX validation succeeded",
247 SET_RESSTATDESC(valfail
, "DNSSEC validation failed", "ValFail");
248 SET_RESSTATDESC(queryrtt0
, "queries with RTT < "
249 DNS_RESOLVER_QRYRTTCLASS0STR
"ms",
250 "QryRTT" DNS_RESOLVER_QRYRTTCLASS0STR
);
251 SET_RESSTATDESC(queryrtt1
, "queries with RTT "
252 DNS_RESOLVER_QRYRTTCLASS0STR
"-"
253 DNS_RESOLVER_QRYRTTCLASS1STR
"ms",
254 "QryRTT" DNS_RESOLVER_QRYRTTCLASS1STR
);
255 SET_RESSTATDESC(queryrtt2
, "queries with RTT "
256 DNS_RESOLVER_QRYRTTCLASS1STR
"-"
257 DNS_RESOLVER_QRYRTTCLASS2STR
"ms",
258 "QryRTT" DNS_RESOLVER_QRYRTTCLASS2STR
);
259 SET_RESSTATDESC(queryrtt3
, "queries with RTT "
260 DNS_RESOLVER_QRYRTTCLASS2STR
"-"
261 DNS_RESOLVER_QRYRTTCLASS3STR
"ms",
262 "QryRTT" DNS_RESOLVER_QRYRTTCLASS3STR
);
263 SET_RESSTATDESC(queryrtt4
, "queries with RTT "
264 DNS_RESOLVER_QRYRTTCLASS3STR
"-"
265 DNS_RESOLVER_QRYRTTCLASS4STR
"ms",
266 "QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR
);
267 SET_RESSTATDESC(queryrtt5
, "queries with RTT > "
268 DNS_RESOLVER_QRYRTTCLASS4STR
"ms",
269 "QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR
"+");
270 INSIST(i
== dns_resstatscounter_max
);
272 /* Initialize zone statistics */
273 for (i
= 0; i
< dns_zonestatscounter_max
; i
++)
274 zonestats_desc
[i
] = NULL
;
276 for (i
= 0; i
< dns_zonestatscounter_max
; i
++)
277 zonestats_xmldesc
[i
] = NULL
;
280 #define SET_ZONESTATDESC(counterid, desc, xmldesc) \
282 set_desc(dns_zonestatscounter_ ## counterid, \
283 dns_zonestatscounter_max, \
284 desc, zonestats_desc, xmldesc, zonestats_xmldesc); \
285 zonestats_index[i++] = dns_zonestatscounter_ ## counterid; \
289 SET_ZONESTATDESC(notifyoutv4
, "IPv4 notifies sent", "NotifyOutv4");
290 SET_ZONESTATDESC(notifyoutv6
, "IPv6 notifies sent", "NotifyOutv6");
291 SET_ZONESTATDESC(notifyinv4
, "IPv4 notifies received", "NotifyInv4");
292 SET_ZONESTATDESC(notifyinv6
, "IPv6 notifies received", "NotifyInv6");
293 SET_ZONESTATDESC(notifyrej
, "notifies rejected", "NotifyRej");
294 SET_ZONESTATDESC(soaoutv4
, "IPv4 SOA queries sent", "SOAOutv4");
295 SET_ZONESTATDESC(soaoutv6
, "IPv6 SOA queries sent", "SOAOutv6");
296 SET_ZONESTATDESC(axfrreqv4
, "IPv4 AXFR requested", "AXFRReqv4");
297 SET_ZONESTATDESC(axfrreqv6
, "IPv6 AXFR requested", "AXFRReqv6");
298 SET_ZONESTATDESC(ixfrreqv4
, "IPv4 IXFR requested", "IXFRReqv4");
299 SET_ZONESTATDESC(ixfrreqv6
, "IPv6 IXFR requested", "IXFRReqv6");
300 SET_ZONESTATDESC(xfrsuccess
, "transfer requests succeeded","XfrSuccess");
301 SET_ZONESTATDESC(xfrfail
, "transfer requests failed", "XfrFail");
302 INSIST(i
== dns_zonestatscounter_max
);
304 /* Initialize socket statistics */
305 for (i
= 0; i
< isc_sockstatscounter_max
; i
++)
306 sockstats_desc
[i
] = NULL
;
308 for (i
= 0; i
< isc_sockstatscounter_max
; i
++)
309 sockstats_xmldesc
[i
] = NULL
;
312 #define SET_SOCKSTATDESC(counterid, desc, xmldesc) \
314 set_desc(isc_sockstatscounter_ ## counterid, \
315 isc_sockstatscounter_max, \
316 desc, sockstats_desc, xmldesc, sockstats_xmldesc); \
317 sockstats_index[i++] = isc_sockstatscounter_ ## counterid; \
321 SET_SOCKSTATDESC(udp4open
, "UDP/IPv4 sockets opened", "UDP4Open");
322 SET_SOCKSTATDESC(udp6open
, "UDP/IPv6 sockets opened", "UDP6Open");
323 SET_SOCKSTATDESC(tcp4open
, "TCP/IPv4 sockets opened", "TCP4Open");
324 SET_SOCKSTATDESC(tcp6open
, "TCP/IPv6 sockets opened", "TCP6Open");
325 SET_SOCKSTATDESC(unixopen
, "Unix domain sockets opened", "UnixOpen");
326 SET_SOCKSTATDESC(udp4openfail
, "UDP/IPv4 socket open failures",
328 SET_SOCKSTATDESC(udp6openfail
, "UDP/IPv6 socket open failures",
330 SET_SOCKSTATDESC(tcp4openfail
, "TCP/IPv4 socket open failures",
332 SET_SOCKSTATDESC(tcp6openfail
, "TCP/IPv6 socket open failures",
334 SET_SOCKSTATDESC(unixopenfail
, "Unix domain socket open failures",
336 SET_SOCKSTATDESC(udp4close
, "UDP/IPv4 sockets closed", "UDP4Close");
337 SET_SOCKSTATDESC(udp6close
, "UDP/IPv6 sockets closed", "UDP6Close");
338 SET_SOCKSTATDESC(tcp4close
, "TCP/IPv4 sockets closed", "TCP4Close");
339 SET_SOCKSTATDESC(tcp6close
, "TCP/IPv6 sockets closed", "TCP6Close");
340 SET_SOCKSTATDESC(unixclose
, "Unix domain sockets closed", "UnixClose");
341 SET_SOCKSTATDESC(fdwatchclose
, "FDwatch sockets closed",
343 SET_SOCKSTATDESC(udp4bindfail
, "UDP/IPv4 socket bind failures",
345 SET_SOCKSTATDESC(udp6bindfail
, "UDP/IPv6 socket bind failures",
347 SET_SOCKSTATDESC(tcp4bindfail
, "TCP/IPv4 socket bind failures",
349 SET_SOCKSTATDESC(tcp6bindfail
, "TCP/IPv6 socket bind failures",
351 SET_SOCKSTATDESC(unixbindfail
, "Unix domain socket bind failures",
353 SET_SOCKSTATDESC(fdwatchbindfail
, "FDwatch socket bind failures",
355 SET_SOCKSTATDESC(udp4connectfail
, "UDP/IPv4 socket connect failures",
357 SET_SOCKSTATDESC(udp6connectfail
, "UDP/IPv6 socket connect failures",
359 SET_SOCKSTATDESC(tcp4connectfail
, "TCP/IPv4 socket connect failures",
361 SET_SOCKSTATDESC(tcp6connectfail
, "TCP/IPv6 socket connect failures",
363 SET_SOCKSTATDESC(unixconnectfail
, "Unix domain socket connect failures",
365 SET_SOCKSTATDESC(fdwatchconnectfail
, "FDwatch socket connect failures",
367 SET_SOCKSTATDESC(udp4connect
, "UDP/IPv4 connections established",
369 SET_SOCKSTATDESC(udp6connect
, "UDP/IPv6 connections established",
371 SET_SOCKSTATDESC(tcp4connect
, "TCP/IPv4 connections established",
373 SET_SOCKSTATDESC(tcp6connect
, "TCP/IPv6 connections established",
375 SET_SOCKSTATDESC(unixconnect
, "Unix domain connections established",
377 SET_SOCKSTATDESC(fdwatchconnect
,
378 "FDwatch domain connections established",
380 SET_SOCKSTATDESC(tcp4acceptfail
, "TCP/IPv4 connection accept failures",
382 SET_SOCKSTATDESC(tcp6acceptfail
, "TCP/IPv6 connection accept failures",
384 SET_SOCKSTATDESC(unixacceptfail
,
385 "Unix domain connection accept failures",
387 SET_SOCKSTATDESC(tcp4accept
, "TCP/IPv4 connections accepted",
389 SET_SOCKSTATDESC(tcp6accept
, "TCP/IPv6 connections accepted",
391 SET_SOCKSTATDESC(unixaccept
, "Unix domain connections accepted",
393 SET_SOCKSTATDESC(udp4sendfail
, "UDP/IPv4 send errors", "UDP4SendErr");
394 SET_SOCKSTATDESC(udp6sendfail
, "UDP/IPv6 send errors", "UDP6SendErr");
395 SET_SOCKSTATDESC(tcp4sendfail
, "TCP/IPv4 send errors", "TCP4SendErr");
396 SET_SOCKSTATDESC(tcp6sendfail
, "TCP/IPv6 send errors", "TCP6SendErr");
397 SET_SOCKSTATDESC(unixsendfail
, "Unix domain send errors",
399 SET_SOCKSTATDESC(fdwatchsendfail
, "FDwatch send errors",
401 SET_SOCKSTATDESC(udp4recvfail
, "UDP/IPv4 recv errors", "UDP4RecvErr");
402 SET_SOCKSTATDESC(udp6recvfail
, "UDP/IPv6 recv errors", "UDP6RecvErr");
403 SET_SOCKSTATDESC(tcp4recvfail
, "TCP/IPv4 recv errors", "TCP4RecvErr");
404 SET_SOCKSTATDESC(tcp6recvfail
, "TCP/IPv6 recv errors", "TCP6RecvErr");
405 SET_SOCKSTATDESC(unixrecvfail
, "Unix domain recv errors",
407 SET_SOCKSTATDESC(fdwatchrecvfail
, "FDwatch recv errors",
409 INSIST(i
== isc_sockstatscounter_max
);
412 for (i
= 0; i
< dns_nsstatscounter_max
; i
++)
413 INSIST(nsstats_desc
[i
] != NULL
);
414 for (i
= 0; i
< dns_resstatscounter_max
; i
++)
415 INSIST(resstats_desc
[i
] != NULL
);
416 for (i
= 0; i
< dns_zonestatscounter_max
; i
++)
417 INSIST(zonestats_desc
[i
] != NULL
);
418 for (i
= 0; i
< isc_sockstatscounter_max
; i
++)
419 INSIST(sockstats_desc
[i
] != NULL
);
421 for (i
= 0; i
< dns_nsstatscounter_max
; i
++)
422 INSIST(nsstats_xmldesc
[i
] != NULL
);
423 for (i
= 0; i
< dns_resstatscounter_max
; i
++)
424 INSIST(resstats_xmldesc
[i
] != NULL
);
425 for (i
= 0; i
< dns_zonestatscounter_max
; i
++)
426 INSIST(zonestats_xmldesc
[i
] != NULL
);
427 for (i
= 0; i
< isc_sockstatscounter_max
; i
++)
428 INSIST(sockstats_xmldesc
[i
] != NULL
);
433 * Dump callback functions.
436 generalstat_dump(isc_statscounter_t counter
, isc_uint64_t val
, void *arg
) {
437 stats_dumparg_t
*dumparg
= arg
;
439 REQUIRE(counter
< dumparg
->ncounters
);
440 dumparg
->countervalues
[counter
] = val
;
444 dump_counters(isc_stats_t
*stats
, statsformat_t type
, void *arg
,
445 const char *category
, const char **desc
, int ncounters
,
446 int *indices
, isc_uint64_t
*values
, int options
)
450 stats_dumparg_t dumparg
;
453 xmlTextWriterPtr writer
;
461 dumparg
.ncounters
= ncounters
;
462 dumparg
.counterindices
= indices
;
463 dumparg
.countervalues
= values
;
465 memset(values
, 0, sizeof(values
[0]) * ncounters
);
466 isc_stats_dump(stats
, generalstat_dump
, &dumparg
, options
);
468 for (i
= 0; i
< ncounters
; i
++) {
470 value
= values
[index
];
472 if (value
== 0 && (options
& ISC_STATSDUMP_VERBOSE
) == 0)
475 switch (dumparg
.type
) {
476 case statsformat_file
:
478 fprintf(fp
, "%20" ISC_PRINT_QUADFORMAT
"u %s\n",
481 case statsformat_xml
:
485 if (category
!= NULL
) {
486 xmlTextWriterStartElement(writer
,
489 xmlTextWriterStartElement(writer
,
491 xmlTextWriterWriteString(writer
, ISC_XMLCHAR
493 xmlTextWriterEndElement(writer
); /* name */
495 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
498 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
501 xmlTextWriterWriteFormatString(writer
,
502 "%" ISC_PRINT_QUADFORMAT
504 xmlTextWriterEndElement(writer
); /* counter */
505 if (category
!= NULL
)
506 xmlTextWriterEndElement(writer
); /* category */
514 rdtypestat_dump(dns_rdatastatstype_t type
, isc_uint64_t val
, void *arg
) {
517 stats_dumparg_t
*dumparg
= arg
;
520 xmlTextWriterPtr writer
;
523 if ((DNS_RDATASTATSTYPE_ATTR(type
) & DNS_RDATASTATSTYPE_ATTR_OTHERTYPE
)
525 dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type
), typebuf
,
531 switch (dumparg
->type
) {
532 case statsformat_file
:
534 fprintf(fp
, "%20" ISC_PRINT_QUADFORMAT
"u %s\n", val
, typestr
);
536 case statsformat_xml
:
538 writer
= dumparg
->arg
;
540 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"rdtype");
542 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"name");
543 xmlTextWriterWriteString(writer
, ISC_XMLCHAR typestr
);
544 xmlTextWriterEndElement(writer
); /* name */
546 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counter");
547 xmlTextWriterWriteFormatString(writer
,
548 "%" ISC_PRINT_QUADFORMAT
"u",
550 xmlTextWriterEndElement(writer
); /* counter */
552 xmlTextWriterEndElement(writer
); /* rdtype */
559 rdatasetstats_dump(dns_rdatastatstype_t type
, isc_uint64_t val
, void *arg
) {
560 stats_dumparg_t
*dumparg
= arg
;
564 isc_boolean_t nxrrset
= ISC_FALSE
;
566 xmlTextWriterPtr writer
;
569 if ((DNS_RDATASTATSTYPE_ATTR(type
) & DNS_RDATASTATSTYPE_ATTR_NXDOMAIN
)
571 typestr
= "NXDOMAIN";
572 } else if ((DNS_RDATASTATSTYPE_ATTR(type
) &
573 DNS_RDATASTATSTYPE_ATTR_OTHERTYPE
) != 0) {
576 dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type
), typebuf
,
581 if ((DNS_RDATASTATSTYPE_ATTR(type
) & DNS_RDATASTATSTYPE_ATTR_NXRRSET
)
585 switch (dumparg
->type
) {
586 case statsformat_file
:
588 fprintf(fp
, "%20" ISC_PRINT_QUADFORMAT
"u %s%s\n", val
,
589 nxrrset
? "!" : "", typestr
);
591 case statsformat_xml
:
593 writer
= dumparg
->arg
;
595 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"rrset");
596 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"name");
597 xmlTextWriterWriteFormatString(writer
, "%s%s",
598 nxrrset
? "!" : "", typestr
);
599 xmlTextWriterEndElement(writer
); /* name */
601 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counter");
602 xmlTextWriterWriteFormatString(writer
,
603 "%" ISC_PRINT_QUADFORMAT
"u",
605 xmlTextWriterEndElement(writer
); /* counter */
607 xmlTextWriterEndElement(writer
); /* rrset */
614 opcodestat_dump(dns_opcode_t code
, isc_uint64_t val
, void *arg
) {
618 stats_dumparg_t
*dumparg
= arg
;
620 xmlTextWriterPtr writer
;
623 isc_buffer_init(&b
, codebuf
, sizeof(codebuf
) - 1);
624 dns_opcode_totext(code
, &b
);
625 codebuf
[isc_buffer_usedlength(&b
)] = '\0';
627 switch (dumparg
->type
) {
628 case statsformat_file
:
630 fprintf(fp
, "%20" ISC_PRINT_QUADFORMAT
"u %s\n", val
, codebuf
);
632 case statsformat_xml
:
634 writer
= dumparg
->arg
;
636 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"opcode");
638 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"name");
639 xmlTextWriterWriteString(writer
, ISC_XMLCHAR codebuf
);
640 xmlTextWriterEndElement(writer
); /* name */
642 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counter");
643 xmlTextWriterWriteFormatString(writer
,
644 "%" ISC_PRINT_QUADFORMAT
"u",
646 xmlTextWriterEndElement(writer
); /* counter */
648 xmlTextWriterEndElement(writer
); /* opcode */
656 /* XXXMLG below here sucks. */
658 #define TRY(a) do { result = (a); INSIST(result == ISC_R_SUCCESS); } while(0);
659 #define TRY0(a) do { xmlrc = (a); INSIST(xmlrc >= 0); } while(0);
662 zone_xmlrender(dns_zone_t
*zone
, void *arg
) {
663 char buf
[1024 + 32]; /* sufficiently large for zone name and class */
664 dns_rdataclass_t rdclass
;
666 xmlTextWriterPtr writer
= arg
;
667 isc_stats_t
*zonestats
;
668 isc_uint64_t nsstat_values
[dns_nsstatscounter_max
];
670 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"zone");
672 dns_zone_name(zone
, buf
, sizeof(buf
));
673 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"name");
674 xmlTextWriterWriteString(writer
, ISC_XMLCHAR buf
);
675 xmlTextWriterEndElement(writer
);
677 rdclass
= dns_zone_getclass(zone
);
678 dns_rdataclass_format(rdclass
, buf
, sizeof(buf
));
679 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"rdataclass");
680 xmlTextWriterWriteString(writer
, ISC_XMLCHAR buf
);
681 xmlTextWriterEndElement(writer
);
683 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"serial");
684 if (dns_zone_getserial2(zone
, &serial
) == ISC_R_SUCCESS
)
685 xmlTextWriterWriteFormatString(writer
, "%u", serial
);
687 xmlTextWriterWriteString(writer
, ISC_XMLCHAR
"-");
688 xmlTextWriterEndElement(writer
);
690 zonestats
= dns_zone_getrequeststats(zone
);
691 if (zonestats
!= NULL
) {
692 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"counters");
693 dump_counters(zonestats
, statsformat_xml
, writer
, NULL
,
694 nsstats_xmldesc
, dns_nsstatscounter_max
,
695 nsstats_index
, nsstat_values
,
696 ISC_STATSDUMP_VERBOSE
);
697 xmlTextWriterEndElement(writer
); /* counters */
700 xmlTextWriterEndElement(writer
); /* zone */
702 return (ISC_R_SUCCESS
);
706 generatexml(ns_server_t
*server
, int *buflen
, xmlChar
**buf
) {
707 char boottime
[sizeof "yyyy-mm-ddThh:mm:ssZ"];
708 char nowstr
[sizeof "yyyy-mm-ddThh:mm:ssZ"];
710 xmlTextWriterPtr writer
;
714 stats_dumparg_t dumparg
;
715 dns_stats_t
*cachestats
;
716 isc_uint64_t nsstat_values
[dns_nsstatscounter_max
];
717 isc_uint64_t resstat_values
[dns_resstatscounter_max
];
718 isc_uint64_t zonestat_values
[dns_zonestatscounter_max
];
719 isc_uint64_t sockstat_values
[isc_sockstatscounter_max
];
722 isc_time_formatISO8601(&ns_g_boottime
, boottime
, sizeof boottime
);
723 isc_time_formatISO8601(&now
, nowstr
, sizeof nowstr
);
725 writer
= xmlNewTextWriterDoc(&doc
, 0);
726 TRY0(xmlTextWriterStartDocument(writer
, NULL
, "UTF-8", NULL
));
727 TRY0(xmlTextWriterWritePI(writer
, ISC_XMLCHAR
"xml-stylesheet",
728 ISC_XMLCHAR
"type=\"text/xsl\" href=\"/bind9.xsl\""));
729 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"isc"));
730 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"version",
733 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"bind"));
734 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"statistics"));
735 TRY0(xmlTextWriterWriteAttribute(writer
, ISC_XMLCHAR
"version",
738 /* Set common fields for statistics dump */
739 dumparg
.type
= statsformat_xml
;
740 dumparg
.arg
= writer
;
743 * Start by rendering the views we know of here. For each view we
744 * know of, call its rendering function.
746 view
= ISC_LIST_HEAD(server
->viewlist
);
747 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"views"));
748 while (view
!= NULL
) {
749 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"view");
751 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"name");
752 xmlTextWriterWriteString(writer
, ISC_XMLCHAR view
->name
);
753 xmlTextWriterEndElement(writer
);
755 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"zones");
756 dns_zt_apply(view
->zonetable
, ISC_FALSE
, zone_xmlrender
,
758 xmlTextWriterEndElement(writer
);
760 if (view
->resquerystats
!= NULL
) {
761 dns_rdatatypestats_dump(view
->resquerystats
,
762 rdtypestat_dump
, &dumparg
, 0);
765 if (view
->resstats
!= NULL
) {
766 dump_counters(view
->resstats
, statsformat_xml
, writer
,
767 "resstat", resstats_xmldesc
,
768 dns_resstatscounter_max
, resstats_index
,
769 resstat_values
, ISC_STATSDUMP_VERBOSE
);
772 cachestats
= dns_db_getrrsetstats(view
->cachedb
);
773 if (cachestats
!= NULL
) {
774 TRY0(xmlTextWriterStartElement(writer
,
775 ISC_XMLCHAR
"cache"));
776 TRY0(xmlTextWriterWriteAttribute(writer
,
779 dns_cache_getname(view
->cache
)));
780 dns_rdatasetstats_dump(cachestats
, rdatasetstats_dump
,
782 TRY0(xmlTextWriterEndElement(writer
)); /* cache */
785 xmlTextWriterEndElement(writer
); /* view */
787 view
= ISC_LIST_NEXT(view
, link
);
789 TRY0(xmlTextWriterEndElement(writer
)); /* views */
791 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"socketmgr"));
792 isc_socketmgr_renderxml(ns_g_socketmgr
, writer
);
793 TRY0(xmlTextWriterEndElement(writer
)); /* socketmgr */
795 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"taskmgr"));
796 isc_taskmgr_renderxml(ns_g_taskmgr
, writer
);
797 TRY0(xmlTextWriterEndElement(writer
)); /* taskmgr */
799 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"server"));
800 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"boot-time");
801 xmlTextWriterWriteString(writer
, ISC_XMLCHAR boottime
);
802 xmlTextWriterEndElement(writer
);
803 xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"current-time");
804 xmlTextWriterWriteString(writer
, ISC_XMLCHAR nowstr
);
805 xmlTextWriterEndElement(writer
);
807 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"requests"));
808 dns_opcodestats_dump(server
->opcodestats
, opcodestat_dump
, &dumparg
,
810 xmlTextWriterEndElement(writer
); /* requests */
812 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"queries-in"));
813 dns_rdatatypestats_dump(server
->rcvquerystats
, rdtypestat_dump
,
815 xmlTextWriterEndElement(writer
); /* queries-in */
817 dump_counters(server
->nsstats
, statsformat_xml
, writer
,
818 "nsstat", nsstats_xmldesc
, dns_nsstatscounter_max
,
819 nsstats_index
, nsstat_values
, ISC_STATSDUMP_VERBOSE
);
821 dump_counters(server
->zonestats
, statsformat_xml
, writer
, "zonestat",
822 zonestats_xmldesc
, dns_zonestatscounter_max
,
823 zonestats_index
, zonestat_values
, ISC_STATSDUMP_VERBOSE
);
826 * Most of the common resolver statistics entries are 0, so we don't
827 * use the verbose dump here.
829 dump_counters(server
->resolverstats
, statsformat_xml
, writer
, "resstat",
830 resstats_xmldesc
, dns_resstatscounter_max
, resstats_index
,
833 dump_counters(server
->sockstats
, statsformat_xml
, writer
, "sockstat",
834 sockstats_xmldesc
, isc_sockstatscounter_max
,
835 sockstats_index
, sockstat_values
, ISC_STATSDUMP_VERBOSE
);
837 xmlTextWriterEndElement(writer
); /* server */
839 TRY0(xmlTextWriterStartElement(writer
, ISC_XMLCHAR
"memory"));
840 isc_mem_renderxml(writer
);
841 TRY0(xmlTextWriterEndElement(writer
)); /* memory */
843 TRY0(xmlTextWriterEndElement(writer
)); /* statistics */
844 TRY0(xmlTextWriterEndElement(writer
)); /* bind */
845 TRY0(xmlTextWriterEndElement(writer
)); /* isc */
847 TRY0(xmlTextWriterEndDocument(writer
));
849 xmlFreeTextWriter(writer
);
851 xmlDocDumpFormatMemoryEnc(doc
, buf
, buflen
, "UTF-8", 1);
856 wrap_xmlfree(isc_buffer_t
*buffer
, void *arg
) {
859 xmlFree(isc_buffer_base(buffer
));
863 render_index(const char *url
, const char *querystring
, void *arg
,
864 unsigned int *retcode
, const char **retmsg
, const char **mimetype
,
865 isc_buffer_t
*b
, isc_httpdfree_t
**freecb
,
870 ns_server_t
*server
= arg
;
875 generatexml(server
, &msglen
, &msg
);
879 *mimetype
= "text/xml";
880 isc_buffer_reinit(b
, msg
, msglen
);
881 isc_buffer_add(b
, msglen
);
882 *freecb
= wrap_xmlfree
;
885 return (ISC_R_SUCCESS
);
888 #endif /* HAVE_LIBXML2 */
891 render_xsl(const char *url
, const char *querystring
, void *args
,
892 unsigned int *retcode
, const char **retmsg
, const char **mimetype
,
893 isc_buffer_t
*b
, isc_httpdfree_t
**freecb
,
902 *mimetype
= "text/xslt+xml";
903 isc_buffer_reinit(b
, xslmsg
, strlen(xslmsg
));
904 isc_buffer_add(b
, strlen(xslmsg
));
908 return (ISC_R_SUCCESS
);
912 shutdown_listener(ns_statschannel_t
*listener
) {
913 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
914 isc_sockaddr_format(&listener
->address
, socktext
, sizeof(socktext
));
915 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,NS_LOGMODULE_SERVER
,
916 ISC_LOG_NOTICE
, "stopping statistics channel on %s",
919 isc_httpdmgr_shutdown(&listener
->httpdmgr
);
923 client_ok(const isc_sockaddr_t
*fromaddr
, void *arg
) {
924 ns_statschannel_t
*listener
= arg
;
925 isc_netaddr_t netaddr
;
926 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
929 REQUIRE(listener
!= NULL
);
931 isc_netaddr_fromsockaddr(&netaddr
, fromaddr
);
933 LOCK(&listener
->lock
);
934 if (dns_acl_match(&netaddr
, NULL
, listener
->acl
, &ns_g_server
->aclenv
,
935 &match
, NULL
) == ISC_R_SUCCESS
&& match
> 0) {
936 UNLOCK(&listener
->lock
);
939 UNLOCK(&listener
->lock
);
941 isc_sockaddr_format(fromaddr
, socktext
, sizeof(socktext
));
942 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
943 NS_LOGMODULE_SERVER
, ISC_LOG_WARNING
,
944 "rejected statistics connection from %s", socktext
);
950 destroy_listener(void *arg
) {
951 ns_statschannel_t
*listener
= arg
;
953 REQUIRE(listener
!= NULL
);
954 REQUIRE(!ISC_LINK_LINKED(listener
, link
));
956 /* We don't have to acquire the lock here since it's already unlinked */
957 dns_acl_detach(&listener
->acl
);
959 DESTROYLOCK(&listener
->lock
);
960 isc_mem_putanddetach(&listener
->mctx
, listener
, sizeof(*listener
));
964 add_listener(ns_server_t
*server
, ns_statschannel_t
**listenerp
,
965 const cfg_obj_t
*listen_params
, const cfg_obj_t
*config
,
966 isc_sockaddr_t
*addr
, cfg_aclconfctx_t
*aclconfctx
,
967 const char *socktext
)
970 ns_statschannel_t
*listener
;
971 isc_task_t
*task
= NULL
;
972 isc_socket_t
*sock
= NULL
;
973 const cfg_obj_t
*allow
;
974 dns_acl_t
*new_acl
= NULL
;
976 listener
= isc_mem_get(server
->mctx
, sizeof(*listener
));
977 if (listener
== NULL
)
978 return (ISC_R_NOMEMORY
);
980 listener
->httpdmgr
= NULL
;
981 listener
->address
= *addr
;
982 listener
->acl
= NULL
;
983 listener
->mctx
= NULL
;
984 ISC_LINK_INIT(listener
, link
);
986 result
= isc_mutex_init(&listener
->lock
);
987 if (result
!= ISC_R_SUCCESS
) {
988 isc_mem_put(server
->mctx
, listener
, sizeof(*listener
));
989 return (ISC_R_FAILURE
);
992 isc_mem_attach(server
->mctx
, &listener
->mctx
);
994 allow
= cfg_tuple_get(listen_params
, "allow");
995 if (allow
!= NULL
&& cfg_obj_islist(allow
)) {
996 result
= cfg_acl_fromconfig(allow
, config
, ns_g_lctx
,
997 aclconfctx
, listener
->mctx
, 0,
1000 result
= dns_acl_any(listener
->mctx
, &new_acl
);
1001 if (result
!= ISC_R_SUCCESS
)
1003 dns_acl_attach(new_acl
, &listener
->acl
);
1004 dns_acl_detach(&new_acl
);
1006 result
= isc_task_create(ns_g_taskmgr
, 0, &task
);
1007 if (result
!= ISC_R_SUCCESS
)
1009 isc_task_setname(task
, "statchannel", NULL
);
1011 result
= isc_socket_create(ns_g_socketmgr
, isc_sockaddr_pf(addr
),
1012 isc_sockettype_tcp
, &sock
);
1013 if (result
!= ISC_R_SUCCESS
)
1015 isc_socket_setname(sock
, "statchannel", NULL
);
1017 #ifndef ISC_ALLOW_MAPPED
1018 isc_socket_ipv6only(sock
, ISC_TRUE
);
1021 result
= isc_socket_bind(sock
, addr
, ISC_SOCKET_REUSEADDRESS
);
1022 if (result
!= ISC_R_SUCCESS
)
1025 result
= isc_httpdmgr_create(server
->mctx
, sock
, task
, client_ok
,
1026 destroy_listener
, listener
, ns_g_timermgr
,
1027 &listener
->httpdmgr
);
1028 if (result
!= ISC_R_SUCCESS
)
1032 isc_httpdmgr_addurl(listener
->httpdmgr
, "/", render_index
, server
);
1034 isc_httpdmgr_addurl(listener
->httpdmgr
, "/bind9.xsl", render_xsl
,
1037 *listenerp
= listener
;
1038 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
1039 NS_LOGMODULE_SERVER
, ISC_LOG_NOTICE
,
1040 "statistics channel listening on %s", socktext
);
1043 if (result
!= ISC_R_SUCCESS
) {
1044 if (listener
->acl
!= NULL
)
1045 dns_acl_detach(&listener
->acl
);
1046 DESTROYLOCK(&listener
->lock
);
1047 isc_mem_putanddetach(&listener
->mctx
, listener
,
1051 isc_task_detach(&task
);
1053 isc_socket_detach(&sock
);
1059 update_listener(ns_server_t
*server
, ns_statschannel_t
**listenerp
,
1060 const cfg_obj_t
*listen_params
, const cfg_obj_t
*config
,
1061 isc_sockaddr_t
*addr
, cfg_aclconfctx_t
*aclconfctx
,
1062 const char *socktext
)
1064 ns_statschannel_t
*listener
;
1065 const cfg_obj_t
*allow
= NULL
;
1066 dns_acl_t
*new_acl
= NULL
;
1067 isc_result_t result
= ISC_R_SUCCESS
;
1069 for (listener
= ISC_LIST_HEAD(server
->statschannels
);
1071 listener
= ISC_LIST_NEXT(listener
, link
))
1072 if (isc_sockaddr_equal(addr
, &listener
->address
))
1075 if (listener
== NULL
) {
1081 * Now, keep the old access list unless a new one can be made.
1083 allow
= cfg_tuple_get(listen_params
, "allow");
1084 if (allow
!= NULL
&& cfg_obj_islist(allow
)) {
1085 result
= cfg_acl_fromconfig(allow
, config
, ns_g_lctx
,
1086 aclconfctx
, listener
->mctx
, 0,
1089 result
= dns_acl_any(listener
->mctx
, &new_acl
);
1091 if (result
== ISC_R_SUCCESS
) {
1092 LOCK(&listener
->lock
);
1094 dns_acl_detach(&listener
->acl
);
1095 dns_acl_attach(new_acl
, &listener
->acl
);
1096 dns_acl_detach(&new_acl
);
1098 UNLOCK(&listener
->lock
);
1100 cfg_obj_log(listen_params
, ns_g_lctx
, ISC_LOG_WARNING
,
1101 "couldn't install new acl for "
1102 "statistics channel %s: %s",
1103 socktext
, isc_result_totext(result
));
1106 *listenerp
= listener
;
1110 ns_statschannels_configure(ns_server_t
*server
, const cfg_obj_t
*config
,
1111 cfg_aclconfctx_t
*aclconfctx
)
1113 ns_statschannel_t
*listener
, *listener_next
;
1114 ns_statschannellist_t new_listeners
;
1115 const cfg_obj_t
*statschannellist
= NULL
;
1116 const cfg_listelt_t
*element
, *element2
;
1117 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
1119 RUNTIME_CHECK(isc_once_do(&once
, init_desc
) == ISC_R_SUCCESS
);
1121 ISC_LIST_INIT(new_listeners
);
1124 * Get the list of named.conf 'statistics-channels' statements.
1126 (void)cfg_map_get(config
, "statistics-channels", &statschannellist
);
1129 * Run through the new address/port list, noting sockets that are
1130 * already being listened on and moving them to the new list.
1132 * Identifying duplicate addr/port combinations is left to either
1133 * the underlying config code, or to the bind attempt getting an
1134 * address-in-use error.
1136 if (statschannellist
!= NULL
) {
1137 #ifndef HAVE_LIBXML2
1138 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
1139 NS_LOGMODULE_SERVER
, ISC_LOG_WARNING
,
1140 "statistics-channels specified but not effective "
1141 "due to missing XML library");
1144 for (element
= cfg_list_first(statschannellist
);
1146 element
= cfg_list_next(element
)) {
1147 const cfg_obj_t
*statschannel
;
1148 const cfg_obj_t
*listenercfg
= NULL
;
1150 statschannel
= cfg_listelt_value(element
);
1151 (void)cfg_map_get(statschannel
, "inet",
1153 if (listenercfg
== NULL
)
1156 for (element2
= cfg_list_first(listenercfg
);
1158 element2
= cfg_list_next(element2
)) {
1159 const cfg_obj_t
*listen_params
;
1160 const cfg_obj_t
*obj
;
1161 isc_sockaddr_t addr
;
1163 listen_params
= cfg_listelt_value(element2
);
1165 obj
= cfg_tuple_get(listen_params
, "address");
1166 addr
= *cfg_obj_assockaddr(obj
);
1167 if (isc_sockaddr_getport(&addr
) == 0)
1168 isc_sockaddr_setport(&addr
, NS_STATSCHANNEL_HTTPPORT
);
1170 isc_sockaddr_format(&addr
, socktext
,
1173 isc_log_write(ns_g_lctx
,
1174 NS_LOGCATEGORY_GENERAL
,
1175 NS_LOGMODULE_SERVER
,
1177 "processing statistics "
1181 update_listener(server
, &listener
,
1182 listen_params
, config
, &addr
,
1183 aclconfctx
, socktext
);
1185 if (listener
!= NULL
) {
1187 * Remove the listener from the old
1188 * list, so it won't be shut down.
1190 ISC_LIST_UNLINK(server
->statschannels
,
1194 * This is a new listener.
1198 r
= add_listener(server
, &listener
,
1199 listen_params
, config
,
1202 if (r
!= ISC_R_SUCCESS
) {
1203 cfg_obj_log(listen_params
,
1206 "couldn't allocate "
1207 "statistics channel"
1210 isc_result_totext(r
));
1214 if (listener
!= NULL
)
1215 ISC_LIST_APPEND(new_listeners
, listener
,
1221 for (listener
= ISC_LIST_HEAD(server
->statschannels
);
1223 listener
= listener_next
) {
1224 listener_next
= ISC_LIST_NEXT(listener
, link
);
1225 ISC_LIST_UNLINK(server
->statschannels
, listener
, link
);
1226 shutdown_listener(listener
);
1229 ISC_LIST_APPENDLIST(server
->statschannels
, new_listeners
, link
);
1230 return (ISC_R_SUCCESS
);
1234 ns_statschannels_shutdown(ns_server_t
*server
) {
1235 ns_statschannel_t
*listener
;
1237 while ((listener
= ISC_LIST_HEAD(server
->statschannels
)) != NULL
) {
1238 ISC_LIST_UNLINK(server
->statschannels
, listener
, link
);
1239 shutdown_listener(listener
);
1244 ns_stats_dump(ns_server_t
*server
, FILE *fp
) {
1246 isc_result_t result
;
1248 dns_zone_t
*zone
, *next
;
1249 stats_dumparg_t dumparg
;
1250 isc_uint64_t nsstat_values
[dns_nsstatscounter_max
];
1251 isc_uint64_t resstat_values
[dns_resstatscounter_max
];
1252 isc_uint64_t zonestat_values
[dns_zonestatscounter_max
];
1253 isc_uint64_t sockstat_values
[isc_sockstatscounter_max
];
1255 RUNTIME_CHECK(isc_once_do(&once
, init_desc
) == ISC_R_SUCCESS
);
1257 /* Set common fields */
1258 dumparg
.type
= statsformat_file
;
1261 isc_stdtime_get(&now
);
1262 fprintf(fp
, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now
);
1264 fprintf(fp
, "++ Incoming Requests ++\n");
1265 dns_opcodestats_dump(server
->opcodestats
, opcodestat_dump
, &dumparg
, 0);
1267 fprintf(fp
, "++ Incoming Queries ++\n");
1268 dns_rdatatypestats_dump(server
->rcvquerystats
, rdtypestat_dump
,
1271 fprintf(fp
, "++ Outgoing Queries ++\n");
1272 for (view
= ISC_LIST_HEAD(server
->viewlist
);
1274 view
= ISC_LIST_NEXT(view
, link
)) {
1275 if (view
->resquerystats
== NULL
)
1277 if (strcmp(view
->name
, "_default") == 0)
1278 fprintf(fp
, "[View: default]\n");
1280 fprintf(fp
, "[View: %s]\n", view
->name
);
1281 dns_rdatatypestats_dump(view
->resquerystats
, rdtypestat_dump
,
1285 fprintf(fp
, "++ Name Server Statistics ++\n");
1286 dump_counters(server
->nsstats
, statsformat_file
, fp
, NULL
,
1287 nsstats_desc
, dns_nsstatscounter_max
, nsstats_index
,
1290 fprintf(fp
, "++ Zone Maintenance Statistics ++\n");
1291 dump_counters(server
->zonestats
, statsformat_file
, fp
, NULL
,
1292 zonestats_desc
, dns_zonestatscounter_max
,
1293 zonestats_index
, zonestat_values
, 0);
1295 fprintf(fp
, "++ Resolver Statistics ++\n");
1296 fprintf(fp
, "[Common]\n");
1297 dump_counters(server
->resolverstats
, statsformat_file
, fp
, NULL
,
1298 resstats_desc
, dns_resstatscounter_max
, resstats_index
,
1300 for (view
= ISC_LIST_HEAD(server
->viewlist
);
1302 view
= ISC_LIST_NEXT(view
, link
)) {
1303 if (view
->resstats
== NULL
)
1305 if (strcmp(view
->name
, "_default") == 0)
1306 fprintf(fp
, "[View: default]\n");
1308 fprintf(fp
, "[View: %s]\n", view
->name
);
1309 dump_counters(view
->resstats
, statsformat_file
, fp
, NULL
,
1310 resstats_desc
, dns_resstatscounter_max
,
1311 resstats_index
, resstat_values
, 0);
1314 fprintf(fp
, "++ Cache DB RRsets ++\n");
1315 for (view
= ISC_LIST_HEAD(server
->viewlist
);
1317 view
= ISC_LIST_NEXT(view
, link
)) {
1318 dns_stats_t
*cachestats
;
1320 cachestats
= dns_db_getrrsetstats(view
->cachedb
);
1321 if (cachestats
== NULL
)
1323 if (strcmp(view
->name
, "_default") == 0)
1324 fprintf(fp
, "[View: default]\n");
1326 fprintf(fp
, "[View: %s (Cache: %s)]\n", view
->name
,
1327 dns_cache_getname(view
->cache
));
1328 if (dns_view_iscacheshared(view
)) {
1330 * Avoid dumping redundant statistics when the cache is
1335 dns_rdatasetstats_dump(cachestats
, rdatasetstats_dump
, &dumparg
,
1339 fprintf(fp
, "++ Socket I/O Statistics ++\n");
1340 dump_counters(server
->sockstats
, statsformat_file
, fp
, NULL
,
1341 sockstats_desc
, isc_sockstatscounter_max
, sockstats_index
,
1342 sockstat_values
, 0);
1344 fprintf(fp
, "++ Per Zone Query Statistics ++\n");
1346 for (result
= dns_zone_first(server
->zonemgr
, &zone
);
1347 result
== ISC_R_SUCCESS
;
1348 next
= NULL
, result
= dns_zone_next(zone
, &next
), zone
= next
)
1350 isc_stats_t
*zonestats
= dns_zone_getrequeststats(zone
);
1351 if (zonestats
!= NULL
) {
1352 char zonename
[DNS_NAME_FORMATSIZE
];
1354 dns_name_format(dns_zone_getorigin(zone
),
1355 zonename
, sizeof(zonename
));
1356 view
= dns_zone_getview(zone
);
1358 fprintf(fp
, "[%s", zonename
);
1359 if (strcmp(view
->name
, "_default") != 0)
1360 fprintf(fp
, " (view: %s)", view
->name
);
1363 dump_counters(zonestats
, statsformat_file
, fp
, NULL
,
1364 nsstats_desc
, dns_nsstatscounter_max
,
1365 nsstats_index
, nsstat_values
, 0);
1369 fprintf(fp
, "--- Statistics Dump --- (%lu)\n", (unsigned long)now
);
1371 return (ISC_R_SUCCESS
); /* this function currently always succeeds */