statschannel.c revision 0c27b3fe77ac1d5094ba3521e8142d9e7973133f
/*
* Copyright (C) 2008-2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*! \file */
#include <config.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
#include <dns/resolver.h>
#include <named/statschannel.h>
#include "bind9.xsl.h"
struct ns_statschannel {
/* Unlocked */
/*
* Locked by channel lock: can be referenced and modified by both
* the server task and the channel task.
*/
/* Locked by server task */
};
typedef struct
void *arg; /* type dependent argument */
int ncounters; /* for general statistics */
int *counterindices; /* for general statistics */
#if defined(HAVE_LIBXML2) || defined(HAVE_JSON)
#define EXTENDED_STATS
#else
#endif
#ifdef EXTENDED_STATS
static const char *
static const struct zt {
const dns_zonetype_t type;
const char *const string;
} typemap[] = {
{ dns_zone_none, "none" },
{ dns_zone_master, "master" },
{ dns_zone_slave, "slave" },
{ dns_zone_stub, "stub" },
{ dns_zone_staticstub, "static-stub" },
{ dns_zone_key, "key" },
{ dns_zone_dlz, "dlz" },
{ dns_zone_redirect, "redirect" },
{ 0, NULL }
};
return ("builtin");
return ("builtin");
/* empty */;
}
#endif
/*%
* 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 *adbstats_desc[dns_adbstats_max];
static const char *zonestats_desc[dns_zonestatscounter_max];
static const char *sockstats_desc[isc_sockstatscounter_max];
static const char *dnssecstats_desc[dns_dnssecstats_max];
static const char *udpinsizestats_desc[dns_sizecounter_in_max];
static const char *udpoutsizestats_desc[dns_sizecounter_out_max];
static const char *tcpinsizestats_desc[dns_sizecounter_in_max];
static const char *tcpoutsizestats_desc[dns_sizecounter_out_max];
#if defined(EXTENDED_STATS)
static const char *nsstats_xmldesc[dns_nsstatscounter_max];
static const char *resstats_xmldesc[dns_resstatscounter_max];
static const char *adbstats_xmldesc[dns_adbstats_max];
static const char *zonestats_xmldesc[dns_zonestatscounter_max];
static const char *sockstats_xmldesc[isc_sockstatscounter_max];
static const char *dnssecstats_xmldesc[dns_dnssecstats_max];
static const char *udpinsizestats_xmldesc[dns_sizecounter_in_max];
static const char *udpoutsizestats_xmldesc[dns_sizecounter_out_max];
static const char *tcpinsizestats_xmldesc[dns_sizecounter_in_max];
static const char *tcpoutsizestats_xmldesc[dns_sizecounter_out_max];
#else
#define nsstats_xmldesc NULL
#define resstats_xmldesc NULL
#define adbstats_xmldesc NULL
#define zonestats_xmldesc NULL
#define sockstats_xmldesc NULL
#define dnssecstats_xmldesc NULL
#define udpinsizestats_xmldesc NULL
#define udpoutsizestats_xmldesc NULL
#define tcpinsizestats_xmldesc NULL
#define tcpoutsizestats_xmldesc NULL
#endif /* EXTENDED_STATS */
/*%
* Mapping arrays to represent statistics counters in the order of our
* preference, regardless of the order of counter indices. For example,
* nsstats_desc[nsstats_index[0]] will be the description that is shown first.
*/
static int nsstats_index[dns_nsstatscounter_max];
static int resstats_index[dns_resstatscounter_max];
static int adbstats_index[dns_adbstats_max];
static int zonestats_index[dns_zonestatscounter_max];
static int sockstats_index[isc_sockstatscounter_max];
static int dnssecstats_index[dns_dnssecstats_max];
static int udpinsizestats_index[dns_sizecounter_in_max];
static int udpoutsizestats_index[dns_sizecounter_out_max];
static int tcpinsizestats_index[dns_sizecounter_in_max];
static int tcpoutsizestats_index[dns_sizecounter_out_max];
static inline void
{
#if defined(EXTENDED_STATS)
#endif
#if defined(EXTENDED_STATS)
#else
#endif
}
static void
init_desc(void) {
int i;
/* Initialize name server statistics */
for (i = 0; i < dns_nsstatscounter_max; i++)
nsstats_desc[i] = NULL;
#if defined(EXTENDED_STATS)
for (i = 0; i < dns_nsstatscounter_max; i++)
nsstats_xmldesc[i] = NULL;
#endif
do { \
} while (0)
i = 0;
"requests with unsupported EDNS version received",
"ReqBadEDNSVer");
"ReqBadSIG");
"TruncatedResp");
"QrySuccess");
"QryAuthAns");
"queries resulted in non authoritative answer",
"QryNoauthAns");
"QryReferral");
"UpdateReqFwd");
"UpdateRespFwd");
"updates rejected due to prerequisite failure",
"UpdateBadPrereq");
"RecursClients");
"RateDropped");
"RateSlipped");
"RPZRewrites");
"queries resulted in NXDOMAIN that were redirected",
"QryNXRedir");
"queries resulted in NXDOMAIN that were redirected and "
"resulted in a successful remote lookup",
"QryNXRedirRLookup");
INSIST(i == dns_nsstatscounter_max);
/* Initialize resolver statistics */
for (i = 0; i < dns_resstatscounter_max; i++)
resstats_desc[i] = NULL;
#if defined(EXTENDED_STATS)
for (i = 0; i < dns_resstatscounter_max; i++)
resstats_xmldesc[i] = NULL;
#endif
do { \
} while (0)
i = 0;
"QueryAbort");
"QuerySockFail");
"GlueFetchv4Fail");
"GlueFetchv6Fail");
"ValNegOk");
"QryRTT" DNS_RESOLVER_QRYRTTCLASS0STR);
"QryRTT" DNS_RESOLVER_QRYRTTCLASS1STR);
"QryRTT" DNS_RESOLVER_QRYRTTCLASS2STR);
"QryRTT" DNS_RESOLVER_QRYRTTCLASS3STR);
"QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR);
"ClientCookieOut");
"ServerCookieOut");
"ServerQuota");
INSIST(i == dns_resstatscounter_max);
/* Initialize adb statistics */
for (i = 0; i < dns_adbstats_max; i++)
adbstats_desc[i] = NULL;
#if defined(EXTENDED_STATS)
for (i = 0; i < dns_adbstats_max; i++)
adbstats_xmldesc[i] = NULL;
#endif
do { \
} while (0)
i = 0;
INSIST(i == dns_adbstats_max);
/* Initialize zone statistics */
for (i = 0; i < dns_zonestatscounter_max; i++)
zonestats_desc[i] = NULL;
#if defined(EXTENDED_STATS)
for (i = 0; i < dns_zonestatscounter_max; i++)
zonestats_xmldesc[i] = NULL;
#endif
do { \
} while (0)
i = 0;
"XfrSuccess");
INSIST(i == dns_zonestatscounter_max);
/* Initialize socket statistics */
for (i = 0; i < isc_sockstatscounter_max; i++)
sockstats_desc[i] = NULL;
#if defined(EXTENDED_STATS)
for (i = 0; i < isc_sockstatscounter_max; i++)
sockstats_xmldesc[i] = NULL;
#endif
do { \
} while (0)
i = 0;
"UDP4OpenFail");
"UDP6OpenFail");
"TCP4OpenFail");
"TCP6OpenFail");
"UnixOpenFail");
"RawOpenFail");
"FDWatchClose");
"UDP4BindFail");
"UDP6BindFail");
"TCP4BindFail");
"TCP6BindFail");
"UnixBindFail");
"FdwatchBindFail");
"UDP4ConnFail");
"UDP6ConnFail");
"TCP4ConnFail");
"TCP6ConnFail");
"UnixConnFail");
"FDwatchConnFail");
"UDP4Conn");
"UDP6Conn");
"TCP4Conn");
"TCP6Conn");
"UnixConn");
"FDwatch domain connections established",
"FDwatchConn");
"TCP4AcceptFail");
"TCP6AcceptFail");
"Unix domain connection accept failures",
"UnixAcceptFail");
"TCP4Accept");
"TCP6Accept");
"UnixAccept");
"UnixSendErr");
"FDwatchSendErr");
"UnixRecvErr");
"FDwatchRecvErr");
"UnixActive");
INSIST(i == isc_sockstatscounter_max);
/* Initialize DNSSEC statistics */
for (i = 0; i < dns_dnssecstats_max; i++)
dnssecstats_desc[i] = NULL;
#if defined(EXTENDED_STATS)
for (i = 0; i < dns_dnssecstats_max; i++)
dnssecstats_xmldesc[i] = NULL;
#endif
do { \
desc, dnssecstats_desc, \
} while (0)
i = 0;
"\"as is\"", "DNSSECasis");
"lower cased", "DNSSECdowncase");
"DNSSECwild");
INSIST(i == dns_dnssecstats_max);
/* Sanity check */
for (i = 0; i < dns_nsstatscounter_max; i++)
for (i = 0; i < dns_resstatscounter_max; i++)
for (i = 0; i < dns_adbstats_max; i++)
for (i = 0; i < dns_zonestatscounter_max; i++)
for (i = 0; i < isc_sockstatscounter_max; i++)
for (i = 0; i < dns_dnssecstats_max; i++)
#if defined(EXTENDED_STATS)
for (i = 0; i < dns_nsstatscounter_max; i++)
for (i = 0; i < dns_resstatscounter_max; i++)
for (i = 0; i < dns_adbstats_max; i++)
for (i = 0; i < dns_zonestatscounter_max; i++)
for (i = 0; i < isc_sockstatscounter_max; i++)
for (i = 0; i < dns_dnssecstats_max; i++)
#endif
/* Initialize traffic size statistics */
for (i = 0; i < dns_sizecounter_in_max; i++) {
udpinsizestats_desc[i] = NULL;
tcpinsizestats_desc[i] = NULL;
#if defined(EXTENDED_STATS)
udpinsizestats_xmldesc[i] = NULL;
tcpinsizestats_xmldesc[i] = NULL;
#endif
}
for (i = 0; i < dns_sizecounter_out_max; i++) {
udpoutsizestats_desc[i] = NULL;
tcpoutsizestats_desc[i] = NULL;
#if defined(EXTENDED_STATS)
udpoutsizestats_xmldesc[i] = NULL;
tcpoutsizestats_xmldesc[i] = NULL;
#endif
}
do { \
i++; \
} while (0)
i = 0;
INSIST(i == dns_sizecounter_in_max);
i = 0;
INSIST(i == dns_sizecounter_out_max);
/* Sanity check */
for (i = 0; i < dns_nsstatscounter_max; i++)
for (i = 0; i < dns_resstatscounter_max; i++)
for (i = 0; i < dns_adbstats_max; i++)
for (i = 0; i < dns_zonestatscounter_max; i++)
for (i = 0; i < isc_sockstatscounter_max; i++)
for (i = 0; i < dns_dnssecstats_max; i++)
for (i = 0; i < dns_sizecounter_in_max; i++) {
}
for (i = 0; i < dns_sizecounter_out_max; i++) {
}
#if defined(EXTENDED_STATS)
for (i = 0; i < dns_nsstatscounter_max; i++)
for (i = 0; i < dns_resstatscounter_max; i++)
for (i = 0; i < dns_adbstats_max; i++)
for (i = 0; i < dns_zonestatscounter_max; i++)
for (i = 0; i < isc_sockstatscounter_max; i++)
for (i = 0; i < dns_dnssecstats_max; i++)
for (i = 0; i < dns_sizecounter_in_max; i++) {
}
for (i = 0; i < dns_sizecounter_out_max; i++) {
}
#endif
}
/*%
* Dump callback functions.
*/
static void
}
static isc_result_t
{
int i, idx;
#ifdef HAVE_LIBXML2
int xmlrc;
#endif
#ifdef HAVE_JSON
#endif
#if !defined(EXTENDED_STATS)
#endif
#ifdef HAVE_JSON
return (ISC_R_NOMEMORY);
}
}
#endif
for (i = 0; i < ncounters; i++) {
continue;
case isc_statsformat_file:
break;
case isc_statsformat_xml:
#ifdef HAVE_LIBXML2
/* <NameOfCategory> */
category));
/* <name> inside category */
"name"));
/* </name> */
/* <counter> */
"counter"));
/* </counter> */
/* </NameOfCategory> */
} else {
"counter"));
"name",
/* counter */
}
#endif
break;
case isc_statsformat_json:
#ifdef HAVE_JSON
return (ISC_R_NOMEMORY);
#endif
break;
}
}
return (ISC_R_SUCCESS);
#ifdef HAVE_LIBXML2
ISC_LOG_ERROR, "failed at dump_counters()");
return (ISC_R_FAILURE);
#endif
}
static void
char typebuf[64];
const char *typestr;
#ifdef HAVE_LIBXML2
int xmlrc;
#endif
#ifdef HAVE_JSON
#endif
== 0) {
sizeof(typebuf));
} else
typestr = "Others";
case isc_statsformat_file:
break;
case isc_statsformat_xml:
#ifdef HAVE_LIBXML2
val));
#endif
break;
case isc_statsformat_json:
#ifdef HAVE_JSON
return;
#endif
break;
}
return;
#ifdef HAVE_LIBXML2
ISC_LOG_ERROR, "failed at rdtypestat_dump()");
return;
#endif
}
static void
char typebuf[64];
const char *typestr;
#ifdef HAVE_LIBXML2
int xmlrc;
#endif
#ifdef HAVE_JSON
char buf[1024];
#endif
!= 0) {
typestr = "NXDOMAIN";
} else if ((DNS_RDATASTATSTYPE_ATTR(type) &
DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) != 0) {
typestr = "Others";
} else {
sizeof(typebuf));
}
!= 0)
!= 0)
case isc_statsformat_file:
break;
case isc_statsformat_xml:
#ifdef HAVE_LIBXML2
val));
#endif
break;
case isc_statsformat_json:
#ifdef HAVE_JSON
return;
#endif
break;
}
return;
#ifdef HAVE_LIBXML2
ISC_LOG_ERROR, "failed at rdatasetstats_dump()");
#endif
}
static void
isc_buffer_t b;
char codebuf[64];
#ifdef HAVE_LIBXML2
int xmlrc;
#endif
#ifdef HAVE_JSON
#endif
dns_opcode_totext(code, &b);
case isc_statsformat_file:
break;
case isc_statsformat_xml:
#ifdef HAVE_LIBXML2
ISC_XMLCHAR codebuf ));
val));
#endif
break;
case isc_statsformat_json:
#ifdef HAVE_JSON
return;
#endif
break;
}
return;
#ifdef HAVE_LIBXML2
ISC_LOG_ERROR, "failed at opcodestat_dump()");
return;
#endif
}
static void
isc_buffer_t b;
char codebuf[64];
#ifdef HAVE_LIBXML2
int xmlrc;
#endif
#ifdef HAVE_JSON
#endif
dns_rcode_totext(code, &b);
case isc_statsformat_file:
break;
case isc_statsformat_xml:
#ifdef HAVE_LIBXML2
ISC_XMLCHAR codebuf ));
val));
#endif
break;
case isc_statsformat_json:
#ifdef HAVE_JSON
return;
#endif
break;
}
return;
#ifdef HAVE_LIBXML2
ISC_LOG_ERROR, "failed at rcodestat_dump()");
return;
#endif
}
#ifdef HAVE_LIBXML2
/*
* Which statistics to include when rendering to XML
*/
#define STATS_XML_SERVER 0x01
#define STATS_XML_ZONES 0x02
#define STATS_XML_TASKS 0x04
#define STATS_XML_NET 0x08
#define STATS_XML_MEM 0x10
#define STATS_XML_TRAFFIC 0x20
#define STATS_XML_ALL 0xff
static isc_result_t
int xmlrc;
const char *ztype;
if (statlevel == dns_zonestat_none)
return (ISC_R_SUCCESS);
ISC_XMLCHAR buf));
ISC_XMLCHAR buf));
else
else
ISC_XMLCHAR "rcode"));
if (result != ISC_R_SUCCESS)
goto error;
/* counters type="rcode"*/
}
ISC_XMLCHAR "qtype"));
&dumparg, 0);
goto error;
/* counters type="qtype"*/
}
return (ISC_R_SUCCESS);
ISC_LOG_ERROR, "Failed at zone_xmlrender()");
return (ISC_R_FAILURE);
}
static isc_result_t
{
char configtime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
int xmlrc;
isc_time_now(&now);
goto error;
ISC_XMLCHAR "type=\"text/xsl\" href=\"/bind9.xsl\""));
ISC_XMLCHAR "3.8"));
/* Set common fields for statistics dump */
/* Render server information */
if ((flags & STATS_XML_SERVER) != 0) {
ISC_XMLCHAR "opcode"));
goto error;
ISC_XMLCHAR "rcode"));
goto error;
ISC_XMLCHAR "qtype"));
&dumparg, 0);
goto error;
ISC_XMLCHAR "nsstat"));
if (result != ISC_R_SUCCESS)
goto error;
ISC_XMLCHAR "zonestat"));
if (result != ISC_R_SUCCESS)
goto error;
/*
* Most of the common resolver statistics entries are 0, so
* we don't use the verbose dump here.
*/
ISC_XMLCHAR "resstat"));
resstats_index, resstat_values, 0);
if (result != ISC_R_SUCCESS)
goto error;
}
if ((flags & STATS_XML_NET) != 0) {
ISC_XMLCHAR "sockstat"));
if (result != ISC_R_SUCCESS)
goto error;
}
if ((flags & STATS_XML_TRAFFIC) != 0) {
ISC_XMLCHAR "request-size"));
udpinsizestat_values, 0);
if (result != ISC_R_SUCCESS)
goto error;
ISC_XMLCHAR "response-size"));
if (result != ISC_R_SUCCESS)
goto error;
ISC_XMLCHAR "request-size"));
tcpinsizestat_values, 0);
if (result != ISC_R_SUCCESS)
goto error;
ISC_XMLCHAR "response-size"));
if (result != ISC_R_SUCCESS)
goto error;
ISC_XMLCHAR "request-size"));
udpinsizestat_values, 0);
if (result != ISC_R_SUCCESS)
goto error;
ISC_XMLCHAR "response-size"));
if (result != ISC_R_SUCCESS)
goto error;
ISC_XMLCHAR "request-size"));
tcpinsizestat_values, 0);
if (result != ISC_R_SUCCESS)
goto error;
ISC_XMLCHAR "response-size"));
if (result != ISC_R_SUCCESS)
goto error;
}
/*
* Render views. For each view we know of, call its
* rendering function.
*/
{
if ((flags & STATS_XML_ZONES) != 0) {
ISC_XMLCHAR "zones"));
if (result != ISC_R_SUCCESS)
goto error;
}
if ((flags & STATS_XML_SERVER) == 0) {
continue;
}
ISC_XMLCHAR "counters"));
ISC_XMLCHAR "resqtype"));
rdtypestat_dump, &dumparg, 0);
goto error;
}
/* <resstats> */
ISC_XMLCHAR "resstats"));
if (result != ISC_R_SUCCESS)
goto error;
}
if (cacherrstats != NULL) {
ISC_XMLCHAR "cache"));
ISC_XMLCHAR "name",
&dumparg, 0);
goto error;
}
/* <adbstats> */
ISC_XMLCHAR "adbstat"));
if (result != ISC_R_SUCCESS)
goto error;
}
/* <cachestats> */
ISC_XMLCHAR "cachestats"));
}
if ((flags & STATS_XML_NET) != 0) {
ISC_XMLCHAR "socketmgr"));
}
if ((flags & STATS_XML_TASKS) != 0) {
}
if ((flags & STATS_XML_MEM) != 0) {
}
goto error;
return (ISC_R_SUCCESS);
ISC_LOG_ERROR, "failed generating XML response");
return (ISC_R_FAILURE);
}
static void
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
int msglen;
if (result == ISC_R_SUCCESS) {
*retcode = 200;
*retmsg = "OK";
isc_buffer_add(b, msglen);
*freecb = wrap_xmlfree;
*freecb_args = NULL;
} else
"failed at rendering XML()");
return (result);
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
#endif /* HAVE_LIBXML2 */
#ifdef HAVE_JSON
/*
* Which statistics to include when rendering to JSON
*/
#define STATS_JSON_SERVER 0x01
#define STATS_JSON_ZONES 0x02
#define STATS_JSON_TASKS 0x04
#define STATS_JSON_NET 0x08
#define STATS_JSON_MEM 0x10
#define STATS_JSON_TRAFFIC 0x20
#define STATS_JSON_ALL 0xff
#define CHECK(m) do { \
result = (m); \
if (result != ISC_R_SUCCESS) \
goto error; \
} while (0)
#define CHECKMEM(m) do { \
if (m == NULL) { \
result = ISC_R_NOMEMORY;\
goto error;\
} \
} while(0)
static void
}
static json_object *
{
return (NULL);
if (add_serial)
return (node);
}
static isc_result_t
char *zone_name_only = NULL;
char *class_only = NULL;
if (statlevel == dns_zonestat_none)
return (ISC_R_SUCCESS);
class_only = class;
else
return (ISC_R_NOMEMORY);
goto error;
}
nsstat_values, 0);
if (result != ISC_R_SUCCESS) {
goto error;
}
else
}
&dumparg, 0);
goto error;
}
else
}
return (result);
}
static isc_result_t
{
char configtime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
return (ISC_R_NOMEMORY);
/*
* These statistics are included no matter which URL we use.
*/
isc_time_now(&now);
configtime, sizeof configtime);
if ((flags & STATS_JSON_SERVER) != 0) {
/* OPCODE counters */
goto error;
}
else
/* OPCODE counters */
goto error;
}
else
/* QTYPE counters */
rdtypestat_dump, &dumparg, 0);
goto error;
}
else
/* server stat counters */
nsstats_index, nsstat_values, 0);
if (result != ISC_R_SUCCESS) {
goto error;
}
else
/* zone stat counters */
if (result != ISC_R_SUCCESS) {
goto error;
}
counters);
else
/* resolver stat counters */
resstats_index, resstat_values, 0);
if (result != ISC_R_SUCCESS) {
goto error;
}
else
}
CHECKMEM(v);
za = json_object_new_array();
if ((flags & STATS_JSON_ZONES) != 0) {
if (result != ISC_R_SUCCESS) {
goto error;
}
}
if (json_object_array_length(za) != 0)
else
if ((flags & STATS_JSON_SERVER) != 0) {
resstat_values, 0);
if (result != ISC_R_SUCCESS) {
goto error;
}
counters);
}
&dumparg, 0);
goto error;
}
counters);
}
&dumparg, 0);
goto error;
}
"cache",
counters);
}
counters);
if (result != ISC_R_SUCCESS) {
goto error;
}
counters);
adbstat_values, 0);
if (result != ISC_R_SUCCESS) {
goto error;
}
counters);
}
}
}
}
if ((flags & STATS_JSON_NET) != 0) {
/* socket stat counters */
if (result != ISC_R_SUCCESS) {
goto error;
}
counters);
else
if (result != ISC_R_SUCCESS) {
goto error;
}
}
if ((flags & STATS_JSON_TASKS) != 0) {
if (result != ISC_R_SUCCESS) {
goto error;
}
}
if ((flags & STATS_JSON_MEM) != 0) {
if (result != ISC_R_SUCCESS) {
goto error;
}
}
if ((flags & STATS_JSON_TRAFFIC) != 0) {
udpinsizestat_values, 0));
udpoutsizestat_values, 0));
tcpinsizestat_values, 0));
tcpoutsizestat_values, 0));
udpinsizestat_values, 0));
udpoutsizestat_values, 0));
tcpinsizestat_values, 0));
tcpoutsizestat_values, 0));
"dns-udp-requests-sizes-received-ipv4",
udpreq4);
"dns-udp-responses-sizes-sent-ipv4",
udpresp4);
"dns-tcp-requests-sizes-received-ipv4",
tcpreq4);
"dns-tcp-responses-sizes-sent-ipv4",
tcpresp4);
"dns-udp-requests-sizes-received-ipv6",
udpreq6);
"dns-udp-responses-sizes-sent-ipv6",
udpresp6);
"dns-tcp-requests-sizes-received-ipv6",
tcpreq6);
"dns-tcp-responses-sizes-sent-ipv6",
tcpresp6);
}
}
return (result);
}
static isc_result_t
const char *querystring, const char *headers,
const char **mimetype, isc_buffer_t *b,
{
char *p;
if (result == ISC_R_SUCCESS) {
*retcode = 200;
*retmsg = "OK";
*mimetype = "application/json";
isc_buffer_reinit(b, p, msglen);
isc_buffer_add(b, msglen);
*freecb = wrap_jsonfree;
*freecb_args = bindstats;
} else
"failed at rendering JSON()");
return (result);
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
static isc_result_t
const char **mimetype, isc_buffer_t *b,
{
freecb, freecb_args));
}
#endif /* HAVE_JSON */
static isc_result_t
const char *querystring, const char *headers,
const char **mimetype, isc_buffer_t *b,
{
*freecb_args = NULL;
if (p != NULL) {
p += strlen("If-Modified-Since: ");
if (result != ISC_R_SUCCESS)
goto send;
if (result != ISC_R_SUCCESS)
goto send;
&t2);
if (result != ISC_R_SUCCESS)
goto send;
goto send;
*retcode = 304;
*retmsg = "Not modified";
return (ISC_R_SUCCESS);
}
}
send:
*retcode = 200;
*retmsg = "OK";
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
#ifdef HAVE_JSON
#endif
render_xsl, 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 EXTENDED_STATS
"statistics-channels specified but not effective "
#else /* EXTENDED_STATS */
#ifndef HAVE_LIBXML2
"statistics-channels: XML library missing, "
"only JSON stats will be available");
#endif /* !HAVE_LIBXML2 */
#ifndef HAVE_JSON
"statistics-channels: JSON library missing, "
"only XML stats will be available");
#endif /* !HAVE_JSON */
#endif /* EXTENDED_STATS */
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);
}
nsstats_index, nsstat_values, 0);
resstats_index, resstat_values, 0);
continue;
else
resstat_values, 0);
}
else
/*
* Avoid dumping redundant statistics when the cache is shared.
*/
if (dns_view_iscacheshared(view))
continue;
}
if (cacherrstats == NULL)
continue;
else
if (dns_view_iscacheshared(view)) {
/*
* Avoid dumping redundant statistics when the cache is
* shared.
*/
continue;
}
&dumparg, 0);
}
continue;
else
adbstats_index, adbstat_values, 0);
}
result == ISC_R_SUCCESS;
{
char zonename[DNS_NAME_FORMATSIZE];
continue;
nsstats_index, nsstat_values, 0);
}
}
return (ISC_R_SUCCESS); /* this function currently always succeeds */
}