diff --git a/CHANGES b/CHANGES index 294e787056..9e99532111 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4402. [func] Collect statistics for RSSAC02v3 traffic-volume, + traffic-sizes and rcode-volume reporting. [RT #41475] + 4401. [bug] Fix leaks in contrib DLZ code. [RT #42707] 4400. [doc] Description of masters with TSIG, allow-query and diff --git a/bin/named/client.c b/bin/named/client.c index 5a74e818ed..850d318165 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -1199,8 +1199,20 @@ client_send(ns_client_t *client) { } #endif /* HAVE_DNSTAP */ - isc_stats_increment(ns_g_server->tcpoutstats, - ISC_MIN((int)respsize / 16, 256)); + + switch (isc_sockaddr_pf(&client->peeraddr)) { + case AF_INET: + isc_stats_increment(ns_g_server->tcpoutstats4, + ISC_MIN((int)respsize / 16, 256)); + break; + case AF_INET6: + isc_stats_increment(ns_g_server->tcpoutstats6, + ISC_MIN((int)respsize / 16, 256)); + break; + default: + INSIST(0); + break; + } } else { respsize = isc_buffer_usedlength(&buffer); result = client_sendpkg(client, &buffer); @@ -1213,13 +1225,26 @@ client_send(ns_client_t *client) { } #endif /* HAVE_DNSTAP */ - isc_stats_increment(ns_g_server->udpoutstats, - ISC_MIN((int)respsize / 16, 256)); + switch (isc_sockaddr_pf(&client->peeraddr)) { + case AF_INET: + isc_stats_increment(ns_g_server->udpoutstats4, + ISC_MIN((int)respsize / 16, 256)); + break; + case AF_INET6: + isc_stats_increment(ns_g_server->udpoutstats6, + ISC_MIN((int)respsize / 16, 256)); + break; + default: + INSIST(0); + break; + } } /* update statistics (XXXJT: is it okay to access message->xxxkey?) */ isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_response); + dns_rcodestats_increment(ns_g_server->rcodestats, + client->message->rcode); if (opt_included) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_edns0out); @@ -2332,11 +2357,33 @@ client_request(isc_task_t *task, isc_event_t *event) { if (TCP_CLIENT(client)) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_requesttcp); - isc_stats_increment(ns_g_server->tcpinstats, - ISC_MIN((int)reqsize / 16, 18)); + switch (isc_sockaddr_pf(&client->peeraddr)) { + case AF_INET: + isc_stats_increment(ns_g_server->tcpinstats4, + ISC_MIN((int)reqsize / 16, 18)); + break; + case AF_INET6: + isc_stats_increment(ns_g_server->tcpinstats6, + ISC_MIN((int)reqsize / 16, 18)); + break; + default: + INSIST(0); + break; + } } else { - isc_stats_increment(ns_g_server->udpinstats, - ISC_MIN((int)reqsize / 16, 18)); + switch (isc_sockaddr_pf(&client->peeraddr)) { + case AF_INET: + isc_stats_increment(ns_g_server->udpinstats4, + ISC_MIN((int)reqsize / 16, 18)); + break; + case AF_INET6: + isc_stats_increment(ns_g_server->udpinstats6, + ISC_MIN((int)reqsize / 16, 18)); + break; + default: + INSIST(0); + break; + } } /* diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index 3f2943fac0..8cdfe79b31 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -101,10 +101,15 @@ struct ns_server { isc_stats_t * zonestats; /*% Zone management stats */ isc_stats_t * resolverstats; /*% Resolver stats */ isc_stats_t * sockstats; /*%< Socket stats */ - isc_stats_t * udpinstats; /*%< Traffic size: UDP in */ - isc_stats_t * udpoutstats; /*%< Traffic size: UDP out */ - isc_stats_t * tcpinstats; /*%< Traffic size: TCP in */ - isc_stats_t * tcpoutstats; /*%< Traffic size: TCP out */ + isc_stats_t * udpinstats4; /*%< Traffic size: UDPv4 in */ + isc_stats_t * udpoutstats4; /*%< Traffic size: UDPv4 out */ + isc_stats_t * udpinstats6; /*%< Traffic size: UDPv6 in */ + isc_stats_t * udpoutstats6; /*%< Traffic size: UDPv6 out */ + isc_stats_t * tcpinstats4; /*%< Traffic size: TCPv4 in */ + isc_stats_t * tcpoutstats4; /*%< Traffic size: TCPv4 out */ + isc_stats_t * tcpinstats6; /*%< Traffic size: TCPv6 in */ + isc_stats_t * tcpoutstats6; /*%< Traffic size: TCPv6 out */ + dns_stats_t * rcodestats; /*%< Sent Response code stats */ ns_controls_t * controls; /*%< Control channels */ unsigned int dispatchgen; diff --git a/bin/named/server.c b/bin/named/server.c index 8fc8ff6df4..61433dab17 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -7834,13 +7834,18 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { server->nsstats = NULL; server->rcvquerystats = NULL; server->opcodestats = NULL; + server->rcodestats = NULL; server->zonestats = NULL; server->resolverstats = NULL; server->sockstats = NULL; - server->udpinstats = NULL; - server->udpoutstats = NULL; - server->tcpinstats = NULL; - server->tcpoutstats = NULL; + server->udpinstats4 = NULL; + server->udpoutstats4 = NULL; + server->udpinstats6 = NULL; + server->udpoutstats6 = NULL; + server->tcpinstats4 = NULL; + server->tcpoutstats4 = NULL; + server->tcpinstats6 = NULL; + server->tcpoutstats6 = NULL; CHECKFATAL(isc_stats_create(server->mctx, &server->sockstats, isc_sockstatscounter_max), "isc_stats_create"); @@ -7882,6 +7887,9 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { CHECKFATAL(dns_opcodestats_create(ns_g_mctx, &server->opcodestats), "dns_stats_create (opcode)"); + CHECKFATAL(dns_rcodestats_create(ns_g_mctx, &server->rcodestats), + "dns_stats_create (rcode)"); + CHECKFATAL(isc_stats_create(ns_g_mctx, &server->zonestats, dns_zonestatscounter_max), "dns_stats_create (zone)"); @@ -7890,21 +7898,37 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { dns_resstatscounter_max), "dns_stats_create (resolver)"); - CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpinstats, + CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpinstats4, dns_sizecounter_in_max), - "dns_stats_create (inbound UDP traffic size)"); + "dns_stats_create (inbound UDP IPv4 traffic size)"); - CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpoutstats, + CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpoutstats4, dns_sizecounter_out_max), - "dns_stats_create (outbound UDP traffic size)"); + "dns_stats_create (outbound UDP IPv4 traffic size)"); - CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpinstats, + CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpinstats6, dns_sizecounter_in_max), - "dns_stats_create (inbound TCP traffic size)"); + "dns_stats_create (inbound UDP IPv6 traffic size)"); - CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpoutstats, + CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpoutstats6, dns_sizecounter_out_max), - "dns_stats_create (outbound TCP traffic size)"); + "dns_stats_create (outbound UDP IPv6 traffic size)"); + + CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpinstats4, + dns_sizecounter_in_max), + "dns_stats_create (inbound TCP IPv4 traffic size)"); + + CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpoutstats4, + dns_sizecounter_out_max), + "dns_stats_create (outbound TCP IPv4 traffic size)"); + + CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpinstats6, + dns_sizecounter_in_max), + "dns_stats_create (inbound TCP IPv6 traffic size)"); + + CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpoutstats6, + dns_sizecounter_out_max), + "dns_stats_create (outbound TCP IPv6 traffic size)"); server->flushonshutdown = ISC_FALSE; server->log_queries = ISC_FALSE; @@ -7948,13 +7972,18 @@ ns_server_destroy(ns_server_t **serverp) { isc_stats_detach(&server->nsstats); dns_stats_detach(&server->rcvquerystats); dns_stats_detach(&server->opcodestats); + dns_stats_detach(&server->rcodestats); isc_stats_detach(&server->zonestats); isc_stats_detach(&server->resolverstats); isc_stats_detach(&server->sockstats); - isc_stats_detach(&server->udpinstats); - isc_stats_detach(&server->udpoutstats); - isc_stats_detach(&server->tcpinstats); - isc_stats_detach(&server->tcpoutstats); + isc_stats_detach(&server->udpinstats4); + isc_stats_detach(&server->udpoutstats4); + isc_stats_detach(&server->udpinstats6); + isc_stats_detach(&server->udpoutstats6); + isc_stats_detach(&server->tcpinstats4); + isc_stats_detach(&server->tcpoutstats4); + isc_stats_detach(&server->tcpinstats6); + isc_stats_detach(&server->tcpoutstats6); isc_mem_free(server->mctx, server->statsfile); isc_mem_free(server->mctx, server->bindkeysfile); diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c index 5bc2f21967..8d507761e6 100644 --- a/bin/named/statschannel.c +++ b/bin/named/statschannel.c @@ -32,9 +32,10 @@ #include #include #include -#include +#include #include #include +#include #include #include #include @@ -1279,8 +1280,8 @@ opcodestat_dump(dns_opcode_t code, isc_uint64_t val, void *arg) { TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", ISC_XMLCHAR codebuf )); TRY0(xmlTextWriterWriteFormatString(writer, - "%" ISC_PRINT_QUADFORMAT "u", - val)); + "%" ISC_PRINT_QUADFORMAT "u", + val)); TRY0(xmlTextWriterEndElement(writer)); /* counter */ #endif break; @@ -1305,6 +1306,62 @@ opcodestat_dump(dns_opcode_t code, isc_uint64_t val, void *arg) { #endif } +static void +rcodestat_dump(dns_rcode_t code, isc_uint64_t val, void *arg) { + FILE *fp; + isc_buffer_t b; + char codebuf[64]; + stats_dumparg_t *dumparg = arg; +#ifdef HAVE_LIBXML2 + xmlTextWriterPtr writer; + int xmlrc; +#endif +#ifdef HAVE_JSON + json_object *zoneobj, *obj; +#endif + + isc_buffer_init(&b, codebuf, sizeof(codebuf) - 1); + dns_rcode_totext(code, &b); + codebuf[isc_buffer_usedlength(&b)] = '\0'; + + switch (dumparg->type) { + case isc_statsformat_file: + fp = dumparg->arg; + fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", val, codebuf); + break; + case isc_statsformat_xml: +#ifdef HAVE_LIBXML2 + writer = dumparg->arg; + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", + ISC_XMLCHAR codebuf )); + TRY0(xmlTextWriterWriteFormatString(writer, + "%" ISC_PRINT_QUADFORMAT "u", + val)); + TRY0(xmlTextWriterEndElement(writer)); /* counter */ +#endif + break; + case isc_statsformat_json: +#ifdef HAVE_JSON + zoneobj = (json_object *) dumparg->arg; + obj = json_object_new_int64(val); + if (obj == NULL) + return; + json_object_object_add(zoneobj, codebuf, obj); +#endif + break; + } + return; + +#ifdef HAVE_LIBXML2 + error: + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_ERROR, "failed at rcodestat_dump()"); + dumparg->result = ISC_R_FAILURE; + return; +#endif +} + #ifdef HAVE_LIBXML2 /* * Which statistics to include when rendering to XML @@ -1480,6 +1537,17 @@ generatexml(ns_server_t *server, isc_uint32_t flags, TRY0(xmlTextWriterEndElement(writer)); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "rcode")); + + dns_rcodestats_dump(server->rcodestats, rcodestat_dump, + &dumparg, ISC_STATSDUMP_VERBOSE); + if (dumparg.result != ISC_R_SUCCESS) + goto error; + + TRY0(xmlTextWriterEndElement(writer)); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "qtype")); @@ -1555,12 +1623,13 @@ generatexml(ns_server_t *server, isc_uint32_t flags, if ((flags & STATS_XML_TRAFFIC) != 0) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "traffic")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ipv4")); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "udp")); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "request-size")); - result = dump_counters(server->udpinstats, + result = dump_counters(server->udpinstats4, isc_statsformat_xml, writer, NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max, @@ -1575,7 +1644,7 @@ generatexml(ns_server_t *server, isc_uint32_t flags, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "response-size")); - result = dump_counters(server->udpoutstats, + result = dump_counters(server->udpoutstats4, isc_statsformat_xml, writer, NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max, @@ -1592,7 +1661,7 @@ generatexml(ns_server_t *server, isc_uint32_t flags, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "request-size")); - result = dump_counters(server->tcpinstats, + result = dump_counters(server->tcpinstats4, isc_statsformat_xml, writer, NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max, @@ -1607,7 +1676,7 @@ generatexml(ns_server_t *server, isc_uint32_t flags, TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "response-size")); - result = dump_counters(server->tcpoutstats, + result = dump_counters(server->tcpoutstats4, isc_statsformat_xml, writer, NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max, @@ -1618,10 +1687,76 @@ generatexml(ns_server_t *server, isc_uint32_t flags, TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ + TRY0(xmlTextWriterEndElement(writer)); /* */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ipv6")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "udp")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "request-size")); + + result = dump_counters(server->udpinstats6, + isc_statsformat_xml, writer, + NULL, udpinsizestats_xmldesc, + dns_sizecounter_in_max, + udpinsizestats_index, + udpinsizestat_values, 0); + if (result != ISC_R_SUCCESS) + goto error; + + TRY0(xmlTextWriterEndElement(writer)); /* */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "response-size")); + + result = dump_counters(server->udpoutstats6, + isc_statsformat_xml, writer, + NULL, udpoutsizestats_xmldesc, + dns_sizecounter_out_max, + udpoutsizestats_index, + udpoutsizestat_values, 0); + if (result != ISC_R_SUCCESS) + goto error; + + TRY0(xmlTextWriterEndElement(writer)); /* */ + TRY0(xmlTextWriterEndElement(writer)); /* */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tcp")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "request-size")); + + result = dump_counters(server->tcpinstats6, + isc_statsformat_xml, writer, + NULL, tcpinsizestats_xmldesc, + dns_sizecounter_in_max, + tcpinsizestats_index, + tcpinsizestat_values, 0); + if (result != ISC_R_SUCCESS) + goto error; + + TRY0(xmlTextWriterEndElement(writer)); /* */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "response-size")); + + result = dump_counters(server->tcpoutstats6, + isc_statsformat_xml, writer, + NULL, tcpoutsizestats_xmldesc, + dns_sizecounter_out_max, + tcpoutsizestats_index, + tcpoutsizestat_values, 0); + if (result != ISC_R_SUCCESS) + goto error; + + TRY0(xmlTextWriterEndElement(writer)); /* */ + TRY0(xmlTextWriterEndElement(writer)); /* */ + TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ } - /* * Render views. For each view we know of, call its * rendering function. @@ -1928,6 +2063,12 @@ render_xml_traffic(const char *url, isc_httpdurl_t *urlinfo, #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;\ @@ -2061,6 +2202,11 @@ generatejson(ns_server_t *server, size_t *msglen, dns_view_t *view; isc_result_t result = ISC_R_SUCCESS; json_object *bindstats, *viewlist, *counters, *obj; + json_object *traffic = NULL; + json_object *udpreq4 = NULL, *udpresp4 = NULL; + json_object *tcpreq4 = NULL, *tcpresp4 = NULL; + json_object *udpreq6 = NULL, *udpresp6 = NULL; + json_object *tcpreq6 = NULL, *tcpresp6 = NULL; isc_uint64_t nsstat_values[dns_nsstatscounter_max]; isc_uint64_t resstat_values[dns_resstatscounter_max]; isc_uint64_t adbstat_values[dns_adbstats_max]; @@ -2134,6 +2280,24 @@ generatejson(ns_server_t *server, size_t *msglen, else json_object_put(counters); + /* OPCODE counters */ + counters = json_object_new_object(); + + dumparg.type = isc_statsformat_json; + dumparg.arg = counters; + + dns_rcodestats_dump(server->rcodestats, rcodestat_dump, + &dumparg, ISC_STATSDUMP_VERBOSE); + if (dumparg.result != ISC_R_SUCCESS) { + json_object_put(counters); + goto error; + } + + if (json_object_get_object(counters)->count != 0) + json_object_object_add(bindstats, "rcodes", counters); + else + json_object_put(counters); + /* QTYPE counters */ counters = json_object_new_object(); @@ -2419,76 +2583,124 @@ generatejson(ns_server_t *server, size_t *msglen, } if ((flags & STATS_JSON_TRAFFIC) != 0) { - json_object *traffic, *udpreq, *udpresp, *tcpreq, *tcpresp; traffic = json_object_new_object(); CHECKMEM(traffic); - udpreq = json_object_new_object(); - CHECKMEM(udpreq); + udpreq4 = json_object_new_object(); + CHECKMEM(udpreq4); - udpresp = json_object_new_object(); - CHECKMEM(udpresp); + udpresp4 = json_object_new_object(); + CHECKMEM(udpresp4); - tcpreq = json_object_new_object(); - CHECKMEM(tcpreq); + tcpreq4 = json_object_new_object(); + CHECKMEM(tcpreq4); - tcpresp = json_object_new_object(); - CHECKMEM(tcpresp); + tcpresp4 = json_object_new_object(); + CHECKMEM(tcpresp4); - result = dump_counters(server->udpinstats, - isc_statsformat_json, udpreq, NULL, - udpinsizestats_xmldesc, - dns_sizecounter_in_max, - udpinsizestats_index, - udpinsizestat_values, 0); - if (result != ISC_R_SUCCESS) { - json_object_put(traffic); - goto error; - } + udpreq6 = json_object_new_object(); + CHECKMEM(udpreq6); - result = dump_counters(server->udpoutstats, - isc_statsformat_json, udpresp, NULL, - udpoutsizestats_xmldesc, - dns_sizecounter_out_max, - udpoutsizestats_index, - udpoutsizestat_values, 0); - if (result != ISC_R_SUCCESS) { - json_object_put(traffic); - goto error; - } + udpresp6 = json_object_new_object(); + CHECKMEM(udpresp6); - result = dump_counters(server->tcpinstats, - isc_statsformat_json, tcpreq, NULL, - tcpinsizestats_xmldesc, - dns_sizecounter_in_max, - tcpinsizestats_index, - tcpinsizestat_values, 0); - if (result != ISC_R_SUCCESS) { - json_object_put(traffic); - goto error; - } + tcpreq6 = json_object_new_object(); + CHECKMEM(tcpreq6); - result = dump_counters(server->tcpoutstats, - isc_statsformat_json, tcpresp, NULL, - tcpoutsizestats_xmldesc, - dns_sizecounter_out_max, - tcpoutsizestats_index, - tcpoutsizestat_values, 0); - if (result != ISC_R_SUCCESS) { - json_object_put(traffic); - goto error; - } + tcpresp6 = json_object_new_object(); + CHECKMEM(tcpresp6); + + CHECK(dump_counters(server->udpinstats4, + isc_statsformat_json, udpreq4, NULL, + udpinsizestats_xmldesc, + dns_sizecounter_in_max, + udpinsizestats_index, + udpinsizestat_values, 0)); + + CHECK(dump_counters(server->udpoutstats4, + isc_statsformat_json, udpresp4, NULL, + udpoutsizestats_xmldesc, + dns_sizecounter_out_max, + udpoutsizestats_index, + udpoutsizestat_values, 0)); + + CHECK(dump_counters(server->tcpinstats4, + isc_statsformat_json, tcpreq4, NULL, + tcpinsizestats_xmldesc, + dns_sizecounter_in_max, + tcpinsizestats_index, + tcpinsizestat_values, 0)); + + CHECK(dump_counters(server->tcpoutstats4, + isc_statsformat_json, tcpresp4, NULL, + tcpoutsizestats_xmldesc, + dns_sizecounter_out_max, + tcpoutsizestats_index, + tcpoutsizestat_values, 0)); + + CHECK(dump_counters(server->udpinstats6, + isc_statsformat_json, udpreq6, NULL, + udpinsizestats_xmldesc, + dns_sizecounter_in_max, + udpinsizestats_index, + udpinsizestat_values, 0)); + + CHECK(dump_counters(server->udpoutstats6, + isc_statsformat_json, udpresp6, NULL, + udpoutsizestats_xmldesc, + dns_sizecounter_out_max, + udpoutsizestats_index, + udpoutsizestat_values, 0)); + + CHECK(dump_counters(server->tcpinstats6, + isc_statsformat_json, tcpreq6, NULL, + tcpinsizestats_xmldesc, + dns_sizecounter_in_max, + tcpinsizestats_index, + tcpinsizestat_values, 0)); + + CHECK(dump_counters(server->tcpoutstats6, + isc_statsformat_json, tcpresp6, NULL, + tcpoutsizestats_xmldesc, + dns_sizecounter_out_max, + tcpoutsizestats_index, + tcpoutsizestat_values, 0)); json_object_object_add(traffic, - "udp-requests-received", udpreq); + "dns-udp-requests-sizes-received-ipv4", + udpreq4); json_object_object_add(traffic, - "udp-responses-sent", udpresp); + "dns-udp-responses-sizes-sent-ipv4", + udpresp4); json_object_object_add(traffic, - "tcp-requests-received", tcpreq); + "dns-tcp-requests-sizes-received-ipv4", + tcpreq4); json_object_object_add(traffic, - "tcp-responses-sent", tcpresp); + "dns-tcp-responses-sizes-sent-ipv4", + tcpresp4); + json_object_object_add(traffic, + "dns-udp-requests-sizes-received-ipv6", + udpreq6); + json_object_object_add(traffic, + "dns-udp-responses-sizes-sent-ipv6", + udpresp6); + json_object_object_add(traffic, + "dns-tcp-requests-sizes-received-ipv6", + tcpreq6); + json_object_object_add(traffic, + "dns-tcp-responses-sizes-sent-ipv6", + tcpresp6); json_object_object_add(bindstats, "traffic", traffic); + udpreq4 = NULL; + udpresp4 = NULL; + tcpreq4 = NULL; + tcpresp4 = NULL; + udpreq6 = NULL; + udpresp6 = NULL; + tcpreq6 = NULL; + tcpresp6 = NULL; + traffic = NULL; } *msg = json_object_to_json_string_ext(bindstats, @@ -2503,6 +2715,24 @@ generatejson(ns_server_t *server, size_t *msglen, result = ISC_R_SUCCESS; error: + if (udpreq4 != NULL) + json_object_put(udpreq4); + if (udpresp4 != NULL) + json_object_put(udpresp4); + if (tcpreq4 != NULL) + json_object_put(tcpreq4); + if (tcpresp4 != NULL) + json_object_put(tcpresp4); + if (udpreq6 != NULL) + json_object_put(udpreq6); + if (udpresp6 != NULL) + json_object_put(udpresp6); + if (tcpreq6 != NULL) + json_object_put(tcpreq6); + if (tcpresp6 != NULL) + json_object_put(tcpresp6); + if (traffic != NULL) + json_object_put(traffic); if (bindstats != NULL) json_object_put(bindstats); @@ -3122,6 +3352,9 @@ ns_stats_dump(ns_server_t *server, FILE *fp) { dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump, &dumparg, 0); + fprintf(fp, "++ Outgoing Rcodes ++\n"); + dns_rcodestats_dump(server->rcodestats, rcodestat_dump, &dumparg, 0); + fprintf(fp, "++ Outgoing Queries ++\n"); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in index 3963447ed4..3d5e9c04bb 100644 --- a/bin/tests/system/conf.sh.in +++ b/bin/tests/system/conf.sh.in @@ -77,7 +77,7 @@ SUBDIRS="acl additional allow_query addzone autosign builtin pending pipelined @PKCS11_TEST@ reclimit redirect resolver rndc rpz rpzrecurse rrl rrchecker rrsetorder rsabigexponent runtime sfcache smartsign sortlist spf staticstub statistics - stub tcp tkey tsig tsiggss unknown upforwd verify views + statschannel stub tcp tkey tsig tsiggss unknown upforwd verify views wildcard xfer xferquota zero zonechecks" # Use the CONFIG_SHELL detected by configure for tests diff --git a/bin/tests/system/statschannel/server-json.pl b/bin/tests/system/statschannel/server-json.pl index 4c81edea1a..4ffe767d8e 100644 --- a/bin/tests/system/statschannel/server-json.pl +++ b/bin/tests/system/statschannel/server-json.pl @@ -27,6 +27,9 @@ my $ref = decode_json($text); foreach $key (keys $ref->{opcodes}) { print "opcode " . $key . ": " . $ref->{opcodes}->{$key} . "\n"; } +foreach $key (keys $ref->{rcodes}) { + print "rcode " . $key . ": " . $ref->{rcodes}->{$key} . "\n"; +} foreach $key (keys $ref->{qtypes}) { print "qtype " . $key . ": " . $ref->{qtypes}->{$key} . "\n"; } diff --git a/bin/tests/system/statschannel/tests.sh b/bin/tests/system/statschannel/tests.sh index f4933f9a25..320a0a0071 100644 --- a/bin/tests/system/statschannel/tests.sh +++ b/bin/tests/system/statschannel/tests.sh @@ -147,6 +147,7 @@ $DIGCMD +tcp example ns > dig.out.$n || ret=1 $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 stats 2>&1 | sed 's/^/I:ns1 /' query_count=`awk '/QUERY/ {print $1}' ns2/named.stats` txt_count=`awk '/TXT/ {print $1}' ns2/named.stats` +noerror_count=`awk '/NOERROR/ {print $1}' ns2/named.stats` if [ $PERL_XML ]; then file=`$PERL fetch.pl xml/v3/server` mv $file xml.stats @@ -157,6 +158,9 @@ if [ $PERL_XML ]; then xml_txt_count=`awk '/qtype TXT/ { print $NF }' xml.fmtstats` xml_txt_count=${xml_txt_count:-0} [ "$txt_count" -eq "$xml_txt_count" ] || ret=1 + xml_noerror_count=`awk '/rcode NOERROR/ { print $NF }' xml.fmtstats` + xml_noerror_count=${xml_noerror_count:-0} + [ "$noerror_count" -eq "$xml_noerror_count" ] || ret=1 fi if [ $PERL_JSON ]; then file=`$PERL fetch.pl json/v1/server` @@ -168,6 +172,9 @@ if [ $PERL_JSON ]; then json_txt_count=`awk '/qtype TXT/ { print $NF }' json.fmtstats` json_txt_count=${json_txt_count:-0} [ "$txt_count" -eq "$json_txt_count" ] || ret=1 + json_noerror_count=`awk '/rcode NOERROR/ { print $NF }' json.fmtstats` + json_noerror_count=${json_noerror_count:-0} + [ "$noerror_count" -eq "$json_noerror_count" ] || ret=1 fi if [ $ret != 0 ]; then echo "I: failed"; fi status=`expr $status + $ret` diff --git a/bin/tests/system/statschannel/traffic-json.pl b/bin/tests/system/statschannel/traffic-json.pl index ed15571397..a56929e51c 100644 --- a/bin/tests/system/statschannel/traffic-json.pl +++ b/bin/tests/system/statschannel/traffic-json.pl @@ -27,25 +27,25 @@ close(INPUT); my $ref = decode_json($text); -my $tcprcvd = $ref->{traffic}->{"tcp-requests-received"}; +my $tcprcvd = $ref->{traffic}->{"dns-tcp-requests-sizes-received-ipv4"}; my $type = "tcp request-size "; foreach $key (keys $tcprcvd) { print $type . $key . ": ". $tcprcvd->{$key} ."\n"; } -my $tcpsent = $ref->{traffic}->{"tcp-responses-sent"}; +my $tcpsent = $ref->{traffic}->{"dns-tcp-responses-sizes-sent-ipv4"}; my $type = "tcp response-size "; foreach $key (keys $tcpsent) { print $type . $key . ": ". $tcpsent->{$key} ."\n"; } -my $udprcvd = $ref->{traffic}->{"udp-requests-received"}; +my $udprcvd = $ref->{traffic}->{"dns-udp-requests-sizes-received-ipv4"}; my $type = "udp request-size "; foreach $key (keys $udprcvd) { print $type . $key . ": ". $udprcvd->{$key} ."\n"; } -my $udpsent = $ref->{traffic}->{"udp-responses-sent"}; +my $udpsent = $ref->{traffic}->{"dns-udp-responses-sizes-sent-ipv4"}; my $type = "udp response-size "; foreach $key (keys $udpsent) { print $type . $key . ": ". $udpsent->{$key} ."\n"; diff --git a/bin/tests/system/statschannel/traffic-xml.pl b/bin/tests/system/statschannel/traffic-xml.pl index e86ca79391..81281b2ed6 100644 --- a/bin/tests/system/statschannel/traffic-xml.pl +++ b/bin/tests/system/statschannel/traffic-xml.pl @@ -24,7 +24,7 @@ my $file = $ARGV[0]; my $ref = XMLin($file); -my $udp = $ref->{traffic}->{udp}->{counters}; +my $udp = $ref->{traffic}->{ipv4}->{udp}->{counters}; foreach $group (@$udp) { my $type = "udp " . $group->{type} . " "; if (exists $group->{counter}->{name}) { @@ -36,7 +36,7 @@ foreach $group (@$udp) { } } -my $tcp = $ref->{traffic}->{tcp}->{counters}; +my $tcp = $ref->{traffic}->{ipv4}->{tcp}->{counters}; foreach $group (@$tcp) { my $type = "tcp " . $group->{type} . " "; if (exists $group->{counter}->{name}) { diff --git a/lib/dns/include/dns/stats.h b/lib/dns/include/dns/stats.h index bba92670ab..eb31af77d8 100644 --- a/lib/dns/include/dns/stats.h +++ b/lib/dns/include/dns/stats.h @@ -199,6 +199,8 @@ typedef void (*dns_rdatatypestats_dumper_t)(dns_rdatastatstype_t, isc_uint64_t, void *); typedef void (*dns_opcodestats_dumper_t)(dns_opcode_t, isc_uint64_t, void *); +typedef void (*dns_rcodestats_dumper_t)(dns_rcode_t, isc_uint64_t, void *); + ISC_LANG_BEGINDECLS isc_result_t @@ -268,6 +270,22 @@ dns_opcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp); *\li anything else -- failure */ +isc_result_t +dns_rcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp); +/*%< + * Create a statistics counter structure per assigned rcode. + * + * Requires: + *\li 'mctx' must be a valid memory context. + * + *\li 'statsp' != NULL && '*statsp' == NULL. + * + * Returns: + *\li ISC_R_SUCCESS -- all ok + * + *\li anything else -- failure + */ + void dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp); /*%< @@ -340,6 +358,15 @@ dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code); *\li 'stats' is a valid dns_stats_t created by dns_opcodestats_create(). */ +void +dns_rcodestats_increment(dns_stats_t *stats, dns_opcode_t code); +/*%< + * Increment the statistics counter for 'code'. + * + * Requires: + *\li 'stats' is a valid dns_stats_t created by dns_rcodestats_create(). + */ + void dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn, void *arg, unsigned int options); @@ -398,6 +425,20 @@ dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn, *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create(). */ +void +dns_rcodestats_dump(dns_stats_t *stats, dns_rcodestats_dumper_t dump_fn, + void *arg, unsigned int options); +/*%< + * Dump the current statistics counters in a specified way. For each counter + * in stats, dump_fn is called with the corresponding rcode, the current + * counter value and the given argument arg. By default counters that have a + * value of 0 is skipped; if options has the ISC_STATSDUMP_VERBOSE flag, even + * such counters are dumped. + * + * Requires: + *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create(). + */ + isc_result_t dns_stats_alloccounters(isc_mem_t *mctx, isc_uint64_t **ctrp); /*%< diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index c07905de5b..094d335d33 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -261,6 +261,10 @@ enum { #define dns_rcode_badvers ((dns_rcode_t)dns_rcode_badvers) dns_rcode_badcookie = 23 #define dns_rcode_badcookie ((dns_rcode_t)dns_rcode_badcookie) + /* + * Update dns_rcodestats_create() and dns_rcodestats_increment() + * and this comment if a rcode > dns_rcode_badcookie is assigned. + */ /* Private space [3841..4095] */ }; diff --git a/lib/dns/stats.c b/lib/dns/stats.c index ed1692a654..1f2ff849ff 100644 --- a/lib/dns/stats.c +++ b/lib/dns/stats.c @@ -40,7 +40,8 @@ typedef enum { dns_statstype_general = 0, dns_statstype_rdtype = 1, dns_statstype_rdataset = 2, - dns_statstype_opcode = 3 + dns_statstype_opcode = 3, + dns_statstype_rcode = 4 } dns_statstype_t; /*% @@ -88,6 +89,11 @@ typedef struct opcodedumparg { void *arg; } opcodedumparg_t; +typedef struct rcodedumparg { + dns_rcodestats_dumper_t fn; + void *arg; +} rcodedumparg_t; + void dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp) { REQUIRE(DNS_STATS_VALID(stats)); @@ -191,6 +197,14 @@ dns_opcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp) { return (create_stats(mctx, dns_statstype_opcode, 16, statsp)); } +isc_result_t +dns_rcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp) { + REQUIRE(statsp != NULL && *statsp == NULL); + + return (create_stats(mctx, dns_statstype_rcode, + dns_rcode_badcookie + 1, statsp)); +} + /*% * Increment/Decrement methods */ @@ -281,6 +295,14 @@ dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code) { isc_stats_increment(stats->counters, (isc_statscounter_t)code); } +void +dns_rcodestats_increment(dns_stats_t *stats, dns_rcode_t code) { + REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rcode); + + if (code <= dns_rcode_badcookie) + isc_stats_increment(stats->counters, (isc_statscounter_t)code); +} + /*% * Dump methods */ @@ -389,6 +411,13 @@ opcode_dumpcb(isc_statscounter_t counter, isc_uint64_t value, void *arg) { opcodearg->fn((dns_opcode_t)counter, value, opcodearg->arg); } +static void +rcode_dumpcb(isc_statscounter_t counter, isc_uint64_t value, void *arg) { + rcodedumparg_t *rcodearg = arg; + + rcodearg->fn((dns_rcode_t)counter, value, rcodearg->arg); +} + void dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn, void *arg0, unsigned int options) @@ -402,6 +431,19 @@ dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn, isc_stats_dump(stats->counters, opcode_dumpcb, &arg, options); } +void +dns_rcodestats_dump(dns_stats_t *stats, dns_rcodestats_dumper_t dump_fn, + void *arg0, unsigned int options) +{ + rcodedumparg_t arg; + + REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rcode); + + arg.fn = dump_fn; + arg.arg = arg0; + isc_stats_dump(stats->counters, rcode_dumpcb, &arg, options); +} + /*** *** Obsolete variables and functions follow: ***/ diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index f5545fff4a..2c67bfd7ee 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -753,6 +753,9 @@ dns_rbtnodechain_prev dns_rbtnodechain_reset dns_rcode_fromtext dns_rcode_totext +dns_rcodestats_create +dns_rcodestats_dump +dns_rcodestats_increment dns_rdata_additionaldata dns_rdata_apl_current dns_rdata_apl_first