]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add DNSSEC sign operations statistics channel
authorMatthijs Mekking <matthijs@isc.org>
Wed, 19 Jun 2019 14:02:50 +0000 (16:02 +0200)
committerMatthijs Mekking <github@pletterpet.nl>
Tue, 25 Jun 2019 09:40:01 +0000 (11:40 +0200)
Add a new statistics structure to record how many sign operations
a key has made within a zone.

bin/named/statschannel.c
bin/named/zoneconf.c
lib/dns/include/dns/stats.h
lib/dns/include/dns/zone.h
lib/dns/stats.c
lib/dns/win32/libdns.def.in
lib/dns/zone.c

index bd6df21caa7e5326268c8a4362e1988b847b0d21..3e3802fa76ec66068d49966dc5705b831db62a10 100644 (file)
@@ -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);
index c644989e32a0157fd8be267595541525d0a84a97..1495b12c94afcbce4afa3d08cf74c65e85d87671 100644 (file)
@@ -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
index 6b7c42397692a1510fce3f0465eb9e84a8f02647..52bab5378e527ad271f2a53130c8520dbe7bb0f1 100644 (file)
@@ -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);
index e2ad6314a5bbf8562307121c9c2d685554610f91..cd5cc698ddea204c6f9b79fb8331b3527ca3e3a7 100644 (file)
@@ -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);
 /*%<
index 65123ea198e897cf954f6db479c4c81dad03c35f..c5f91213205298e5ece419e57b050ef9ddce8d3f 100644 (file)
@@ -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;
index a17818406079ad7fe740317e613477a0d99eb672..10d4c132e77aa10f799450605f6b409fc90ec26a 100644 (file)
@@ -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
index f4de17f0a04a4b04771346ee5d01210ecd8e4bd5..9aadab363d7891ae23246e50a592d4f60867a471 100644 (file)
@@ -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));