diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c index bd6df21caa..3e3802fa76 100644 --- a/bin/named/statschannel.c +++ b/bin/named/statschannel.c @@ -1444,6 +1444,60 @@ rcodestat_dump(dns_rcode_t code, uint64_t val, void *arg) { #endif } +static void +dnssecsignstat_dump(dns_keytag_t tag, uint64_t val, void *arg) { + FILE *fp; + char tagbuf[64]; + stats_dumparg_t *dumparg = arg; +#ifdef HAVE_LIBXML2 + xmlTextWriterPtr writer; + int xmlrc; +#endif +#ifdef HAVE_JSON + json_object *zoneobj, *obj; +#endif + + snprintf(tagbuf, sizeof(tagbuf), "%u", tag); + + switch (dumparg->type) { + case isc_statsformat_file: + fp = dumparg->arg; + fprintf(fp, "%20" PRIu64 " %s\n", val, tagbuf); + 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 tagbuf )); + TRY0(xmlTextWriterWriteFormatString(writer, + "%" PRIu64, + 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, tagbuf, obj); +#endif + break; + } + return; +#ifdef HAVE_LIBXML2 + error: + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed at dnssecsignstat_dump()"); + dumparg->result = ISC_R_FAILURE; + return; +#endif +} + #ifdef HAVE_LIBXML2 /* * Which statistics to include when rendering to XML @@ -1506,6 +1560,7 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { isc_stats_t *zonestats; isc_stats_t *gluecachestats; dns_stats_t *rcvquerystats; + dns_stats_t *dnssecsignstats; uint64_t nsstat_values[ns_statscounter_max]; uint64_t gluecachestats_values[dns_gluecachestatscounter_max]; @@ -1567,6 +1622,26 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { /* counters type="qtype"*/ TRY0(xmlTextWriterEndElement(writer)); } + + dnssecsignstats = dns_zone_getdnssecsignstats(zone); + if (dnssecsignstats != NULL) { + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, + ISC_XMLCHAR "type", + ISC_XMLCHAR "dnssec")); + + dumparg.result = ISC_R_SUCCESS; + dns_dnssecsignstats_dump(dnssecsignstats, + dnssecsignstat_dump, + &dumparg, 0); + if(dumparg.result != ISC_R_SUCCESS) { + goto error; + } + + /* counters type="dnssec"*/ + TRY0(xmlTextWriterEndElement(writer)); + } } TRY0(xmlTextWriterEndElement(writer)); /* zone */ @@ -2287,6 +2362,7 @@ zone_jsonrender(dns_zone_t *zone, void *arg) { isc_stats_t *zonestats; isc_stats_t *gluecachestats; dns_stats_t *rcvquerystats; + dns_stats_t *dnssecsignstats; uint64_t nsstat_values[ns_statscounter_max]; uint64_t gluecachestats_values[dns_gluecachestatscounter_max]; @@ -2364,6 +2440,30 @@ zone_jsonrender(dns_zone_t *zone, void *arg) { else json_object_put(counters); } + + dnssecsignstats = dns_zone_getdnssecsignstats(zone); + if (dnssecsignstats != NULL) { + stats_dumparg_t dumparg; + json_object *counters = json_object_new_object(); + CHECKMEM(counters); + + dumparg.type = isc_statsformat_json; + dumparg.arg = counters; + dumparg.result = ISC_R_SUCCESS; + dns_dnssecsignstats_dump(dnssecsignstats, + dnssecsignstat_dump, + &dumparg, 0); + if (dumparg.result != ISC_R_SUCCESS) { + json_object_put(counters); + goto error; + } + + if (json_object_get_object(counters)->count != 0) + json_object_object_add(zoneobj, + "dnssec", counters); + else + json_object_put(counters); + } } json_object_array_add(zonearray, zoneobj); diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index c644989e32..1495b12c94 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -904,6 +904,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, const dns_master_style_t *masterstyle = &dns_master_style_default; isc_stats_t *zoneqrystats; dns_stats_t *rcvquerystats; + dns_stats_t *dnssecsignstats; dns_zonestat_level_t statlevel = dns_zonestat_none; int seconds; dns_zone_t *mayberaw = (raw != NULL) ? raw : zone; @@ -1188,14 +1189,16 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, zoneqrystats = NULL; rcvquerystats = NULL; + dnssecsignstats = NULL; if (statlevel == dns_zonestat_full) { RETERR(isc_stats_create(mctx, &zoneqrystats, ns_statscounter_max)); - RETERR(dns_rdatatypestats_create(mctx, - &rcvquerystats)); + RETERR(dns_rdatatypestats_create(mctx, &rcvquerystats)); + RETERR(dns_dnssecsignstats_create(mctx, &dnssecsignstats)); } dns_zone_setrequeststats(zone, zoneqrystats); dns_zone_setrcvquerystats(zone, rcvquerystats); + dns_zone_setdnssecsignstats(zone, dnssecsignstats); if (zoneqrystats != NULL) isc_stats_detach(&zoneqrystats); @@ -1203,6 +1206,10 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, if(rcvquerystats != NULL) dns_stats_detach(&rcvquerystats); + if(dnssecsignstats != NULL) { + dns_stats_detach(&dnssecsignstats); + } + /* * Configure master functionality. This applies * to primary masters (type "master") and slaves diff --git a/lib/dns/include/dns/stats.h b/lib/dns/include/dns/stats.h index 6b7c423976..52bab5378e 100644 --- a/lib/dns/include/dns/stats.h +++ b/lib/dns/include/dns/stats.h @@ -499,8 +499,8 @@ typedef void (*dns_generalstats_dumper_t)(isc_statscounter_t, uint64_t, void *); typedef void (*dns_rdatatypestats_dumper_t)(dns_rdatastatstype_t, uint64_t, void *); +typedef void (*dns_dnssecsignstats_dumper_t)(dns_keytag_t, uint64_t, void *); typedef void (*dns_opcodestats_dumper_t)(dns_opcode_t, uint64_t, void *); - typedef void (*dns_rcodestats_dumper_t)(dns_rcode_t, uint64_t, void *); ISC_LANG_BEGINDECLS @@ -588,6 +588,22 @@ dns_rcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp); *\li anything else -- failure */ +isc_result_t +dns_dnssecsignstats_create(isc_mem_t *mctx, dns_stats_t **statsp); +/*%< + * Create a statistics counter structure per assigned DNSKEY id. + * + * 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); /*%< @@ -669,6 +685,15 @@ dns_rcodestats_increment(dns_stats_t *stats, dns_opcode_t code); *\li 'stats' is a valid dns_stats_t created by dns_rcodestats_create(). */ +void +dns_dnssecsignstats_increment(dns_stats_t *stats, dns_keytag_t id); +/*%< + * Increment the statistics counter for the DNSKEY 'id'. + * + * Requires: + *\li 'stats' is a valid dns_stats_t created by dns_dnssecsignstats_create(). + */ + void dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn, void *arg, unsigned int options); @@ -713,6 +738,21 @@ dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn, *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create(). */ +void +dns_dnssecsignstats_dump(dns_stats_t *stats, + dns_dnssecsignstats_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 type in the form of + * dns_rdatastatstype_t, 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(). + */ + void dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn, void *arg, unsigned int options); diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index e2ad6314a5..cd5cc698dd 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -1925,6 +1925,9 @@ dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats); void dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats); + +void +dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats); /*%< * Set additional statistics sets to zone. These are attached to the zone * but are not counted in the zone module; only the caller updates the @@ -1941,6 +1944,9 @@ dns_zone_getrequeststats(dns_zone_t *zone); dns_stats_t * dns_zone_getrcvquerystats(dns_zone_t *zone); + +dns_stats_t * +dns_zone_getdnssecsignstats(dns_zone_t *zone); /*%< * Get the additional statistics for zone, if one is installed. * @@ -1952,6 +1958,17 @@ dns_zone_getrcvquerystats(dns_zone_t *zone); * otherwise NULL. */ +/*%< + * Set additional statistics sets to zone. These are attached to the zone + * but are not counted in the zone module; only the caller updates the + * counters. + * + * Requires: + * \li 'zone' to be a valid zone. + * + *\li stats is a valid statistics. + */ + void dns_zone_dialup(dns_zone_t *zone); /*%< diff --git a/lib/dns/stats.c b/lib/dns/stats.c index 65123ea198..c5f9121320 100644 --- a/lib/dns/stats.c +++ b/lib/dns/stats.c @@ -35,7 +35,8 @@ typedef enum { dns_statstype_rdtype = 1, dns_statstype_rdataset = 2, dns_statstype_opcode = 3, - dns_statstype_rcode = 4 + dns_statstype_rcode = 4, + dns_statstype_dnssec = 5 } dns_statstype_t; /*% @@ -58,7 +59,8 @@ enum { rdtypecounter_nxdomain = rdtypenxcounter_max, /* stale counters offset */ rdtypecounter_stale = rdtypecounter_nxdomain + 1, - rdatasettypecounter_max = rdtypecounter_stale * 2 + rdatasettypecounter_max = rdtypecounter_stale * 2, + dnssec_keyid_max = 65535 }; struct dns_stats { @@ -84,9 +86,13 @@ typedef struct opcodedumparg { } opcodedumparg_t; typedef struct rcodedumparg { - dns_rcodestats_dumper_t fn; + dns_rcodestats_dumper_t fn; void *arg; } rcodedumparg_t; +typedef struct dnssecsigndumparg { + dns_dnssecsignstats_dumper_t fn; + void *arg; +} dnssecsigndumparg_t; void dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp) { @@ -196,6 +202,14 @@ dns_rcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp) { dns_rcode_badcookie + 1, statsp)); } +isc_result_t +dns_dnssecsignstats_create(isc_mem_t *mctx, dns_stats_t **statsp) { + REQUIRE(statsp != NULL && *statsp == NULL); + + return (create_stats(mctx, dns_statstype_dnssec, + dnssec_keyid_max, statsp)); +} + /*% * Increment/Decrement methods */ @@ -294,6 +308,13 @@ dns_rcodestats_increment(dns_stats_t *stats, dns_rcode_t code) { isc_stats_increment(stats->counters, (isc_statscounter_t)code); } +void +dns_dnssecsignstats_increment(dns_stats_t *stats, dns_keytag_t id) { + REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_dnssec); + + isc_stats_increment(stats->counters, (isc_statscounter_t)id); +} + /*% * Dump methods */ @@ -395,6 +416,28 @@ dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn, isc_stats_dump(stats->counters, rdataset_dumpcb, &arg, options); } +static void +dnssec_dumpcb(isc_statscounter_t counter, uint64_t value, void *arg) { + dnssecsigndumparg_t *dnssecarg = arg; + + dnssecarg->fn((dns_keytag_t)counter, value, dnssecarg->arg); +} + +void +dns_dnssecsignstats_dump(dns_stats_t *stats, + dns_dnssecsignstats_dumper_t dump_fn, + void *arg0, unsigned int options) +{ + dnssecsigndumparg_t arg; + + REQUIRE(DNS_STATS_VALID(stats) && + stats->type == dns_statstype_dnssec); + + arg.fn = dump_fn; + arg.arg = arg0; + isc_stats_dump(stats->counters, dnssec_dumpcb, &arg, options); +} + static void opcode_dumpcb(isc_statscounter_t counter, uint64_t value, void *arg) { opcodedumparg_t *opcodearg = arg; diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index a178184060..10d4c132e7 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -331,6 +331,10 @@ dns_dnssec_verify dns_dnssec_verifymessage dns_dnsseckey_create dns_dnsseckey_destroy +dns_dnssecsignstats_create +dns_dnssecsignstats_decrement +dns_dnssecsignstats_dump +dns_dnssecsignstats_increment dns_ds_buildrdata dns_dsdigest_format dns_dsdigest_fromtext @@ -1137,6 +1141,7 @@ dns_zone_getchecknames dns_zone_getclass dns_zone_getdb dns_zone_getdbtype +dns_zone_getdnssecsignstats dns_zone_getexpiretime dns_zone_getfile dns_zone_getforwardacl @@ -1237,6 +1242,7 @@ dns_zone_setclass dns_zone_setdb dns_zone_setdbtype dns_zone_setdialup +dns_zone_setdnssecsignstats dns_zone_setfile dns_zone_setflag dns_zone_setforwardacl diff --git a/lib/dns/zone.c b/lib/dns/zone.c index f4de17f0a0..9aadab363d 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -323,9 +323,10 @@ struct dns_zone { * module. */ dns_zonestat_level_t statlevel; - bool requeststats_on; + bool requeststats_on; isc_stats_t *requeststats; dns_stats_t *rcvquerystats; + dns_stats_t *dnssecsignstats; uint32_t notifydelay; dns_isselffunc_t isself; void *isselfarg; @@ -1022,6 +1023,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->statlevel = dns_zonestat_none; zone->requeststats = NULL; zone->rcvquerystats = NULL; + zone->dnssecsignstats = NULL; zone->notifydelay = 5; zone->isself = NULL; zone->isselfarg = NULL; @@ -1195,6 +1197,9 @@ zone_free(dns_zone_t *zone) { if (zone->rcvquerystats != NULL){ dns_stats_detach(&zone->rcvquerystats); } + if (zone->dnssecsignstats != NULL){ + dns_stats_detach(&zone->dnssecsignstats); + } if (zone->db != NULL) { zone_detachdb(zone); } @@ -6623,6 +6628,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, /* XXX inefficient - will cause dataset merging */ CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name, rdataset.ttl, &sig_rdata)); + dns_rdata_reset(&sig_rdata); isc_buffer_init(&buffer, data, sizeof(data)); } @@ -17521,6 +17527,24 @@ dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) { UNLOCK_ZONE(zone); } +void +dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) { + + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + if (stats != NULL && zone->dnssecsignstats == NULL) { + dns_stats_attach(stats, &zone->dnssecsignstats); + } + UNLOCK_ZONE(zone); +} + +dns_stats_t* +dns_zone_getdnssecsignstats(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (zone->dnssecsignstats); +} + isc_stats_t * dns_zone_getrequeststats(dns_zone_t *zone) { /* @@ -18019,8 +18043,7 @@ rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, */ static isc_result_t add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype, - dns_dbversion_t *ver, dns_diff_t *diff, - bool sign_all) + dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) { dns_difftuple_t *tuple, *newtuple = NULL; dns_rdata_dnskey_t dnskey; @@ -18486,9 +18509,8 @@ zone_rekey(dns_zone_t *zone) { { CHECK(dns_diff_apply(&diff, db, ver)); CHECK(clean_nsec3param(zone, db, ver, &diff)); - CHECK(add_signing_records(db, zone->privatetype, - ver, &diff, - (newalg || fullsign))); + CHECK(add_signing_records(db, zone->privatetype, ver, + &diff, (newalg || fullsign))); CHECK(update_soa_serial(db, ver, &diff, mctx, zone->updatemethod)); CHECK(add_chains(zone, db, ver, &diff));