statschannel.c revision 9e0d0a279b956cc2eae41c00a6846b0ca8c617c6
/*
* Copyright (C) 2008, 2009 Internet Systems Consortium, Inc. ("ISC")
*
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: statschannel.c,v 1.17 2009/01/09 23:47:45 tbox Exp $ */
/*! \file */
#include <config.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
#include <named/statschannel.h>
#include "bind9.xsl.h"
struct ns_statschannel {
/* Unlocked */
/*
* Locked by channel lock: can be refererenced and modified by both
* the server task and the channel task.
*/
/* Locked by server task */
};
typedef struct
void *arg; /* type dependent argument */
const char *category; /* used for general statistics */
const char **desc; /* used for general statistics */
int ncounters; /* used for general statistics */
/*%
* Statistics descriptions. These could be statistically initialized at
* compile time, but we configure them run time in the init_desc() function
* below so that they'll be less susceptible to counter name changes.
*/
static const char *nsstats_desc[dns_nsstatscounter_max];
static const char *resstats_desc[dns_resstatscounter_max];
static const char *zonestats_desc[dns_zonestatscounter_max];
#ifdef HAVE_LIBXML2
static const char *nsstats_xmldesc[dns_nsstatscounter_max];
static const char *resstats_xmldesc[dns_resstatscounter_max];
static const char *zonestats_xmldesc[dns_zonestatscounter_max];
#else
#define nsstats_xmldesc NULL
#define resstats_xmldesc NULL
#define zonestats_xmldesc NULL
#endif /* HAVE_LIBXML2 */
static inline void
{
#ifdef HAVE_LIBXML2
#endif
#ifdef HAVE_LIBXML2
#else
#endif
}
static void
init_desc(void) {
int i;
/* Initialize name server statistics */
memset(nsstats_desc, 0,
dns_nsstatscounter_max * sizeof(nsstats_desc[0]));
#ifdef HAVE_LIBXML2
dns_nsstatscounter_max * sizeof(nsstats_xmldesc[0]));
#endif
"IPv4 requests received", nsstats_desc,
"Requestv4", nsstats_xmldesc);
"IPv6 requests received", nsstats_desc,
"Requestv6", nsstats_xmldesc);
"requests with EDNS(0) received", nsstats_desc,
"ReqEdns0", nsstats_xmldesc);
"requests with unsupported EDNS version received",
"ReqBadEDNSVer", nsstats_xmldesc);
"requests with TSIG received", nsstats_desc,
"ReqTSIG", nsstats_xmldesc);
"requests with SIG(0) received", nsstats_desc,
"ReqSIG0", nsstats_xmldesc);
"requests with invalid signature", nsstats_desc,
"ReqBadSIG", nsstats_xmldesc);
"TCP requests received", nsstats_desc,
"ReqTCP", nsstats_xmldesc);
"auth queries rejected", nsstats_desc,
"AuthQryRej", nsstats_xmldesc);
"recursive queries rejected", nsstats_desc,
"RecQryRej", nsstats_xmldesc);
"transfer requests rejected", nsstats_desc,
"XfrRej", nsstats_xmldesc);
"update requests rejected", nsstats_desc,
"UpdateRej", nsstats_xmldesc);
"responses sent", nsstats_desc,
"Response", nsstats_xmldesc);
"truncated responses sent", nsstats_desc,
"TruncatedResp", nsstats_xmldesc);
"responses with EDNS(0) sent", nsstats_desc,
"RespEDNS0", nsstats_xmldesc);
"responses with TSIG sent", nsstats_desc,
"RespTSIG", nsstats_xmldesc);
"responses with SIG(0) sent", nsstats_desc,
"RespSIG0", nsstats_xmldesc);
"queries resulted in successful answer", nsstats_desc,
"QrySuccess", nsstats_xmldesc);
"queries resulted in authoritative answer", nsstats_desc,
"QryAuthAns", nsstats_xmldesc);
"queries resulted in non authoritative answer", nsstats_desc,
"QryNoauthAns", nsstats_xmldesc);
"queries resulted in referral answer", nsstats_desc,
"QryReferral", nsstats_xmldesc);
"queries resulted in nxrrset", nsstats_desc,
"QryNxrrset", nsstats_xmldesc);
"queries resulted in SERVFAIL", nsstats_desc,
"QrySERVFAIL", nsstats_xmldesc);
"queries resulted in FORMERR", nsstats_desc,
"QryFORMERR", nsstats_xmldesc);
"queries resulted in NXDOMAIN", nsstats_desc,
"QryNXDOMAIN", nsstats_xmldesc);
"queries caused recursion", nsstats_desc,
"QryRecursion", nsstats_xmldesc);
"duplicate queries received", nsstats_desc,
"QryDuplicate", nsstats_xmldesc);
"queries dropped", nsstats_desc,
"QryDropped", nsstats_xmldesc);
"other query failures", nsstats_desc,
"QryFailure", nsstats_xmldesc);
"requested transfers completed", nsstats_desc,
"XfrReqDone", nsstats_xmldesc);
"update requests forwarded", nsstats_desc,
"UpdateReqFwd", nsstats_xmldesc);
"update responses forwarded", nsstats_desc,
"UpdateRespFwd", nsstats_xmldesc);
"update forward failed", nsstats_desc,
"UpdateFwdFail", nsstats_xmldesc);
"updates completed", nsstats_desc,
"UpdateDone", nsstats_xmldesc);
"updates failed", nsstats_desc,
"UpdateFail", nsstats_xmldesc);
"updates rejected due to prerequisite failure", nsstats_desc,
"UpdateBadPrereq", nsstats_xmldesc);
/* Initialize resolver statistics */
memset(resstats_desc, 0,
dns_resstatscounter_max * sizeof(resstats_desc[0]));
#ifdef HAVE_LIBXML2
dns_resstatscounter_max * sizeof(resstats_xmldesc[0]));
#endif
"IPv4 queries sent", resstats_desc,
"Queryv4", resstats_xmldesc);
"IPv6 queries sent", resstats_desc,
"Queryv6", resstats_xmldesc);
"IPv4 responses received", resstats_desc,
"Responsev4", resstats_xmldesc);
"IPv6 responses received", resstats_desc,
"Responsev6", resstats_xmldesc);
"NXDOMAIN received", resstats_desc,
"NXDOMAIN", resstats_xmldesc);
"SERVFAIL received", resstats_desc,
"SERVFAIL", resstats_xmldesc);
"FORMERR received", resstats_desc,
"FORMERR", resstats_xmldesc);
"other errors received", resstats_desc,
"OtherError", resstats_xmldesc);
"EDNS(0) query failures", resstats_desc,
"EDNS0Fail", resstats_xmldesc);
"mismatch responses received", resstats_desc,
"Mismatch", resstats_xmldesc);
"truncated responses received", resstats_desc,
"Truncated", resstats_xmldesc);
"lame delegations received", resstats_desc,
"Lame", resstats_xmldesc);
"query retries", resstats_desc,
"Retry", resstats_xmldesc);
"IPv4 NS address fetches", resstats_desc,
"GlueFetchv4", resstats_xmldesc);
"IPv6 NS address fetches", resstats_desc,
"GlueFetchv6", resstats_xmldesc);
"IPv4 NS address fetch failed", resstats_desc,
"GlueFetchv4Fail", resstats_xmldesc);
"IPv6 NS address fetch failed", resstats_desc,
"GlueFetchv6Fail", resstats_xmldesc);
"DNSSEC validation attempted", resstats_desc,
"ValAttempt", resstats_xmldesc);
"DNSSEC validation succeeded", resstats_desc,
"ValOk", resstats_xmldesc);
"DNSSEC NX validation succeeded", resstats_desc,
"ValNegOk", resstats_xmldesc);
"DNSSEC validation failed", resstats_desc,
"ValFail", resstats_xmldesc);
/* Initialize zone statistics */
memset(zonestats_desc, 0,
dns_zonestatscounter_max * sizeof(zonestats_desc[0]));
#ifdef HAVE_LIBXML2
dns_zonestatscounter_max * sizeof(zonestats_xmldesc[0]));
#endif
"IPv4 notifies sent", zonestats_desc,
"NotifyOutv4", zonestats_xmldesc);
"IPv6 notifies sent", zonestats_desc,
"NotifyOutv6", zonestats_xmldesc);
"IPv4 notifies received", zonestats_desc,
"NotifyInv4", zonestats_xmldesc);
"IPv6 notifies received", zonestats_desc,
"NotifyInv6", zonestats_xmldesc);
"notifies rejected", zonestats_desc,
"NotifyRej", zonestats_xmldesc);
"IPv4 SOA queries sent", zonestats_desc,
"SOAOutv4", zonestats_xmldesc);
"IPv6 SOA queries sent", zonestats_desc,
"SOAOutv6", zonestats_xmldesc);
"IPv4 AXFR requested", zonestats_desc,
"AXFRReqv4", zonestats_xmldesc);
"IPv6 AXFR requested", zonestats_desc,
"AXFRReqv6", zonestats_xmldesc);
"IPv4 IXFR requested", zonestats_desc,
"IXFRReqv4", zonestats_xmldesc);
"IPv6 IXFR requested", zonestats_desc,
"IXFRReqv6", zonestats_xmldesc);
"transfer requests succeeded", zonestats_desc,
"XfrSuccess", zonestats_xmldesc);
"transfer requests failed", zonestats_desc,
"XfrFail", zonestats_xmldesc);
/* Sanity check */
for (i = 0; i < dns_nsstatscounter_max; i++)
for (i = 0; i < dns_resstatscounter_max; i++)
for (i = 0; i < dns_zonestatscounter_max; i++)
#ifdef HAVE_LIBXML2
for (i = 0; i < dns_nsstatscounter_max; i++)
for (i = 0; i < dns_resstatscounter_max; i++)
for (i = 0; i < dns_zonestatscounter_max; i++)
#endif
}
/*%
* Dump callback functions.
*/
static void
#ifdef HAVE_LIBXML2
#endif
case statsformat_file:
break;
case statsformat_xml:
#ifdef HAVE_LIBXML2
"counter");
} else {
}
val);
#endif
break;
}
}
static void
char typebuf[64];
const char *typestr;
#ifdef HAVE_LIBXML2
#endif
== 0) {
sizeof(typebuf));
} else
typestr = "Others";
case statsformat_file:
break;
case statsformat_xml:
#ifdef HAVE_LIBXML2
val);
#endif
break;
}
}
static void
char typebuf[64];
const char *typestr;
#ifdef HAVE_LIBXML2
#endif
!= 0) {
typestr = "NXDOMAIN";
} else if ((DNS_RDATASTATSTYPE_ATTR(type) &
DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) != 0) {
typestr = "Others";
} else {
sizeof(typebuf));
}
!= 0)
case statsformat_file:
break;
case statsformat_xml:
#ifdef HAVE_LIBXML2
val);
#endif
break;
}
}
static void
isc_buffer_t b;
char codebuf[64];
#ifdef HAVE_LIBXML2
#endif
dns_opcode_totext(code, &b);
case statsformat_file:
break;
case statsformat_xml:
#ifdef HAVE_LIBXML2
val);
#endif
break;
}
}
#ifdef HAVE_LIBXML2
/* XXXMLG below here sucks. */
static isc_result_t
}
return (ISC_R_SUCCESS);
}
static void
char boottime[sizeof "yyyy-mm-ddThh:mm:ssZ"];
char nowstr[sizeof "yyyy-mm-ddThh:mm:ssZ"];
int xmlrc;
isc_time_now(&now);
ISC_XMLCHAR "type=\"text/xsl\" href=\"/bind9.xsl\""));
ISC_XMLCHAR "1.0"));
ISC_XMLCHAR "2.1"));
/* Set common fields for statistics dump */
/*
* Start by rendering the views we know of here. For each view we
* know of, call its rendering function.
*/
writer);
rdtypestat_dump, &dumparg, 0);
}
}
if (cachestats != NULL) {
ISC_XMLCHAR "cache"));
ISC_XMLCHAR "name",
&dumparg, 0);
}
}
0);
&dumparg, 0);
/*
* Most of the common resolver statistics entries are 0, so we don't
* use the verbose dump here.
*/
&dumparg, 0);
}
static void
}
static isc_result_t
void **freecb_args)
{
unsigned char *msg;
int msglen;
*retcode = 200;
*retmsg = "OK";
isc_buffer_add(b, msglen);
*freecb = wrap_xmlfree;
*freecb_args = NULL;
return (ISC_R_SUCCESS);
}
#endif /* HAVE_LIBXML2 */
static isc_result_t
void **freecb_args)
{
*retcode = 200;
*retmsg = "OK";
*freecb_args = NULL;
return (ISC_R_SUCCESS);
}
static void
char socktext[ISC_SOCKADDR_FORMATSIZE];
ISC_LOG_NOTICE, "stopping statistics channel on %s",
socktext);
}
static isc_boolean_t
char socktext[ISC_SOCKADDR_FORMATSIZE];
int match;
return (ISC_TRUE);
}
"rejected statistics connection from %s", socktext);
return (ISC_FALSE);
}
static void
destroy_listener(void *arg) {
/* We don't have to acquire the lock here since it's already unlinked */
}
static isc_result_t
const char *socktext)
{
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS) {
return (ISC_R_FAILURE);
}
&new_acl);
} else
if (result != ISC_R_SUCCESS)
goto cleanup;
if (result != ISC_R_SUCCESS)
goto cleanup;
if (result != ISC_R_SUCCESS)
goto cleanup;
#ifndef ISC_ALLOW_MAPPED
#endif
if (result != ISC_R_SUCCESS)
goto cleanup;
if (result != ISC_R_SUCCESS)
goto cleanup;
#ifdef HAVE_LIBXML2
#endif
server);
"statistics channel listening on %s", socktext);
if (result != ISC_R_SUCCESS) {
sizeof(*listener));
}
return (result);
}
static void
const char *socktext)
{
break;
return;
}
/*
* Now, keep the old access list unless a new one can be made.
*/
&new_acl);
} else
if (result == ISC_R_SUCCESS) {
} else {
"couldn't install new acl for "
"statistics channel %s: %s",
}
}
{
char socktext[ISC_SOCKADDR_FORMATSIZE];
/*
* Get the list of named.conf 'statistics-channels' statements.
*/
/*
* already being listened on and moving them to the new list.
*
* the underlying config code, or to the bind attempt getting an
* address-in-use error.
*/
if (statschannellist != NULL) {
#ifndef HAVE_LIBXML2
"statistics-channels specified but not effective "
"due to missing XML library");
#endif
const cfg_obj_t *statschannel;
&listenercfg);
if (listenercfg == NULL)
continue;
const cfg_obj_t *listen_params;
if (isc_sockaddr_getport(&addr) == 0)
sizeof(socktext));
ISC_LOG_DEBUG(9),
"processing statistics "
"channel %s",
socktext);
/*
* Remove the listener from the old
* list, so it won't be shut down.
*/
} else {
/*
* This is a new listener.
*/
isc_result_t r;
&addr, aclconfctx,
socktext);
if (r != ISC_R_SUCCESS) {
"couldn't allocate "
"statistics channel"
" %s: %s",
isc_result_totext(r));
}
}
link);
}
}
}
listener = listener_next) {
}
return (ISC_R_SUCCESS);
}
void
}
}
/* Set common fields */
&dumparg, 0);
continue;
else
&dumparg, 0);
}
0);
continue;
else
&dumparg, 0);
}
if (cachestats == NULL)
continue;
else
if (dns_view_iscacheshared(view)) {
/*
* Avoid dumping redundant statistics when the cache is
* shared.
*/
continue;
}
0);
}
result == ISC_R_SUCCESS;
{
char zonename[DNS_NAME_FORMATSIZE];
&dumparg, 0);
}
}
return (ISC_R_SUCCESS); /* this function currently always succeeds */
}