"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/lib/dns/stats.c" (4 Sep 2020, 17224 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stats.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*! \file */
   13 
   14 #include <inttypes.h>
   15 #include <stdbool.h>
   16 
   17 #include <isc/magic.h>
   18 #include <isc/mem.h>
   19 #include <isc/refcount.h>
   20 #include <isc/stats.h>
   21 #include <isc/util.h>
   22 
   23 #include <dns/log.h>
   24 #include <dns/opcode.h>
   25 #include <dns/rdatatype.h>
   26 #include <dns/stats.h>
   27 
   28 #define DNS_STATS_MAGIC    ISC_MAGIC('D', 's', 't', 't')
   29 #define DNS_STATS_VALID(x) ISC_MAGIC_VALID(x, DNS_STATS_MAGIC)
   30 
   31 /*%
   32  * Statistics types.
   33  */
   34 typedef enum {
   35     dns_statstype_general = 0,
   36     dns_statstype_rdtype = 1,
   37     dns_statstype_rdataset = 2,
   38     dns_statstype_opcode = 3,
   39     dns_statstype_rcode = 4,
   40     dns_statstype_dnssec = 5
   41 } dns_statstype_t;
   42 
   43 /*%
   44  * It doesn't make sense to have 2^16 counters for all possible types since
   45  * most of them won't be used.  We have counters for the first 256 types.
   46  *
   47  * A rdtypecounter is now 8 bits for RRtypes and 3 bits for flags:
   48  *
   49  *       0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
   50  *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   51  *     |  |  |  |  |  |  S  |NX|         RRType        |
   52  *     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   53  *
   54  * If the 8 bits for RRtype are all zero, this is an Other RRtype.
   55  */
   56 #define RDTYPECOUNTER_MAXTYPE 0x00ff
   57 
   58 /*
   59  *
   60  * Bit 7 is the NXRRSET (NX) flag and indicates whether this is a
   61  * positive (0) or a negative (1) RRset.
   62  */
   63 #define RDTYPECOUNTER_NXRRSET 0x0100
   64 
   65 /*
   66  * Then bit 5 and 6 mostly tell you if this counter is for an active,
   67  * stale, or ancient RRtype:
   68  *
   69  *     S = 0 (0b00) means Active
   70  *     S = 1 (0b01) means Stale
   71  *     S = 2 (0b10) means Ancient
   72  *
   73  * Since a counter cannot be stale and ancient at the same time, we
   74  * treat S = 0x11 as a special case to deal with NXDOMAIN counters.
   75  */
   76 #define RDTYPECOUNTER_STALE    (1 << 9)
   77 #define RDTYPECOUNTER_ANCIENT  (1 << 10)
   78 #define RDTYPECOUNTER_NXDOMAIN ((1 << 9) | (1 << 10))
   79 
   80 /*
   81  * S = 0x11 indicates an NXDOMAIN counter and in this case the RRtype
   82  * field signals the expiry of this cached item:
   83  *
   84  *     RRType = 0 (0b00) means Active
   85  *     RRType = 1 (0b01) means Stale
   86  *     RRType = 2 (0b02) means Ancient
   87  *
   88  */
   89 #define RDTYPECOUNTER_NXDOMAIN_STALE   1
   90 #define RDTYPECOUNTER_NXDOMAIN_ANCIENT 2
   91 
   92 /*
   93  * The maximum value for rdtypecounter is for an ancient NXDOMAIN.
   94  */
   95 #define RDTYPECOUNTER_MAXVAL 0x0602
   96 
   97 /*
   98  * DNSSEC sign statistics.
   99  *
  100  * Per key we maintain 3 counters. The first is actually no counter but
  101  * a key id reference. The second is the number of signatures the key created.
  102  * The third is the number of signatures refreshed by the key.
  103  */
  104 
  105 /* Maximum number of keys to keep track of for DNSSEC signing statistics. */
  106 static int dnssecsign_max_keys = 4;
  107 static int dnssecsign_block_size = 3;
  108 /* Key id mask */
  109 #define DNSSECSIGNSTATS_KEY_ID_MASK 0x0000FFFF
  110 
  111 struct dns_stats {
  112     unsigned int magic;
  113     dns_statstype_t type;
  114     isc_mem_t *mctx;
  115     isc_stats_t *counters;
  116     isc_refcount_t references;
  117 };
  118 
  119 typedef struct rdatadumparg {
  120     dns_rdatatypestats_dumper_t fn;
  121     void *arg;
  122 } rdatadumparg_t;
  123 
  124 typedef struct opcodedumparg {
  125     dns_opcodestats_dumper_t fn;
  126     void *arg;
  127 } opcodedumparg_t;
  128 
  129 typedef struct rcodedumparg {
  130     dns_rcodestats_dumper_t fn;
  131     void *arg;
  132 } rcodedumparg_t;
  133 typedef struct dnssecsigndumparg {
  134     dns_dnssecsignstats_dumper_t fn;
  135     void *arg;
  136 } dnssecsigndumparg_t;
  137 
  138 void
  139 dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp) {
  140     REQUIRE(DNS_STATS_VALID(stats));
  141     REQUIRE(statsp != NULL && *statsp == NULL);
  142 
  143     isc_refcount_increment(&stats->references);
  144 
  145     *statsp = stats;
  146 }
  147 
  148 void
  149 dns_stats_detach(dns_stats_t **statsp) {
  150     dns_stats_t *stats;
  151 
  152     REQUIRE(statsp != NULL && DNS_STATS_VALID(*statsp));
  153 
  154     stats = *statsp;
  155     *statsp = NULL;
  156 
  157     if (isc_refcount_decrement(&stats->references) == 1) {
  158         isc_refcount_destroy(&stats->references);
  159         isc_stats_detach(&stats->counters);
  160         isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
  161     }
  162 }
  163 
  164 /*%
  165  * Create methods
  166  */
  167 static isc_result_t
  168 create_stats(isc_mem_t *mctx, dns_statstype_t type, int ncounters,
  169          dns_stats_t **statsp) {
  170     dns_stats_t *stats;
  171     isc_result_t result;
  172 
  173     stats = isc_mem_get(mctx, sizeof(*stats));
  174 
  175     stats->counters = NULL;
  176     isc_refcount_init(&stats->references, 1);
  177 
  178     result = isc_stats_create(mctx, &stats->counters, ncounters);
  179     if (result != ISC_R_SUCCESS) {
  180         goto clean_mutex;
  181     }
  182 
  183     stats->magic = DNS_STATS_MAGIC;
  184     stats->type = type;
  185     stats->mctx = NULL;
  186     isc_mem_attach(mctx, &stats->mctx);
  187     *statsp = stats;
  188 
  189     return (ISC_R_SUCCESS);
  190 
  191 clean_mutex:
  192     isc_mem_put(mctx, stats, sizeof(*stats));
  193 
  194     return (result);
  195 }
  196 
  197 isc_result_t
  198 dns_generalstats_create(isc_mem_t *mctx, dns_stats_t **statsp, int ncounters) {
  199     REQUIRE(statsp != NULL && *statsp == NULL);
  200 
  201     return (create_stats(mctx, dns_statstype_general, ncounters, statsp));
  202 }
  203 
  204 isc_result_t
  205 dns_rdatatypestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
  206     REQUIRE(statsp != NULL && *statsp == NULL);
  207 
  208     /*
  209      * Create rdtype statistics for the first 255 RRtypes,
  210      * plus one additional for other RRtypes.
  211      */
  212     return (create_stats(mctx, dns_statstype_rdtype,
  213                  (RDTYPECOUNTER_MAXTYPE + 1), statsp));
  214 }
  215 
  216 isc_result_t
  217 dns_rdatasetstats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
  218     REQUIRE(statsp != NULL && *statsp == NULL);
  219 
  220     return (create_stats(mctx, dns_statstype_rdataset,
  221                  (RDTYPECOUNTER_MAXVAL + 1), statsp));
  222 }
  223 
  224 isc_result_t
  225 dns_opcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
  226     REQUIRE(statsp != NULL && *statsp == NULL);
  227 
  228     return (create_stats(mctx, dns_statstype_opcode, 16, statsp));
  229 }
  230 
  231 isc_result_t
  232 dns_rcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
  233     REQUIRE(statsp != NULL && *statsp == NULL);
  234 
  235     return (create_stats(mctx, dns_statstype_rcode, dns_rcode_badcookie + 1,
  236                  statsp));
  237 }
  238 
  239 isc_result_t
  240 dns_dnssecsignstats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
  241     REQUIRE(statsp != NULL && *statsp == NULL);
  242 
  243     /*
  244      * Create two counters per key, one is the key id, the other two are
  245      * the actual counters for creating and refreshing signatures.
  246      */
  247     return (create_stats(mctx, dns_statstype_dnssec,
  248                  dnssecsign_max_keys * 3, statsp));
  249 }
  250 
  251 /*%
  252  * Increment/Decrement methods
  253  */
  254 void
  255 dns_generalstats_increment(dns_stats_t *stats, isc_statscounter_t counter) {
  256     REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
  257 
  258     isc_stats_increment(stats->counters, counter);
  259 }
  260 
  261 inline static isc_statscounter_t
  262 rdatatype2counter(dns_rdatatype_t type) {
  263     if (type > (dns_rdatatype_t)RDTYPECOUNTER_MAXTYPE) {
  264         return (0);
  265     }
  266     return ((isc_statscounter_t)type);
  267 }
  268 
  269 void
  270 dns_rdatatypestats_increment(dns_stats_t *stats, dns_rdatatype_t type) {
  271     isc_statscounter_t counter;
  272 
  273     REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
  274 
  275     counter = rdatatype2counter(type);
  276     isc_stats_increment(stats->counters, counter);
  277 }
  278 
  279 static inline void
  280 update_rdatasetstats(dns_stats_t *stats, dns_rdatastatstype_t rrsettype,
  281              bool increment) {
  282     isc_statscounter_t counter;
  283 
  284     if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
  285          DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) != 0)
  286     {
  287         counter = RDTYPECOUNTER_NXDOMAIN;
  288 
  289         /*
  290          * This is an NXDOMAIN counter, save the expiry value
  291          * (active, stale, or ancient) value in the RRtype part.
  292          */
  293         if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
  294              DNS_RDATASTATSTYPE_ATTR_ANCIENT) != 0) {
  295             counter |= RDTYPECOUNTER_NXDOMAIN_ANCIENT;
  296         } else if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
  297                 DNS_RDATASTATSTYPE_ATTR_STALE) != 0)
  298         {
  299             counter += RDTYPECOUNTER_NXDOMAIN_STALE;
  300         }
  301     } else {
  302         counter = rdatatype2counter(DNS_RDATASTATSTYPE_BASE(rrsettype));
  303 
  304         if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
  305              DNS_RDATASTATSTYPE_ATTR_NXRRSET) != 0) {
  306             counter |= RDTYPECOUNTER_NXRRSET;
  307         }
  308 
  309         if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
  310              DNS_RDATASTATSTYPE_ATTR_ANCIENT) != 0) {
  311             counter |= RDTYPECOUNTER_ANCIENT;
  312         } else if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
  313                 DNS_RDATASTATSTYPE_ATTR_STALE) != 0)
  314         {
  315             counter |= RDTYPECOUNTER_STALE;
  316         }
  317     }
  318 
  319     if (increment) {
  320         isc_stats_increment(stats->counters, counter);
  321     } else {
  322         isc_stats_decrement(stats->counters, counter);
  323     }
  324 }
  325 
  326 void
  327 dns_rdatasetstats_increment(dns_stats_t *stats,
  328                 dns_rdatastatstype_t rrsettype) {
  329     REQUIRE(DNS_STATS_VALID(stats) &&
  330         stats->type == dns_statstype_rdataset);
  331 
  332     update_rdatasetstats(stats, rrsettype, true);
  333 }
  334 
  335 void
  336 dns_rdatasetstats_decrement(dns_stats_t *stats,
  337                 dns_rdatastatstype_t rrsettype) {
  338     REQUIRE(DNS_STATS_VALID(stats) &&
  339         stats->type == dns_statstype_rdataset);
  340 
  341     update_rdatasetstats(stats, rrsettype, false);
  342 }
  343 
  344 void
  345 dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code) {
  346     REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
  347 
  348     isc_stats_increment(stats->counters, (isc_statscounter_t)code);
  349 }
  350 
  351 void
  352 dns_rcodestats_increment(dns_stats_t *stats, dns_rcode_t code) {
  353     REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rcode);
  354 
  355     if (code <= dns_rcode_badcookie) {
  356         isc_stats_increment(stats->counters, (isc_statscounter_t)code);
  357     }
  358 }
  359 
  360 void
  361 dns_dnssecsignstats_increment(dns_stats_t *stats, dns_keytag_t id, uint8_t alg,
  362                   dnssecsignstats_type_t operation) {
  363     uint32_t kval;
  364 
  365     REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_dnssec);
  366 
  367     /* Shift algorithm in front of key tag, which is 16 bits */
  368     kval = (uint32_t)(alg << 16 | id);
  369 
  370     /* Look up correct counter. */
  371     for (int i = 0; i < dnssecsign_max_keys; i++) {
  372         int idx = i * dnssecsign_block_size;
  373         uint32_t counter = isc_stats_get_counter(stats->counters, idx);
  374         if (counter == kval) {
  375             /* Match */
  376             isc_stats_increment(stats->counters, (idx + operation));
  377             return;
  378         }
  379     }
  380 
  381     /* No match found. Store key in unused slot. */
  382     for (int i = 0; i < dnssecsign_max_keys; i++) {
  383         int idx = i * dnssecsign_block_size;
  384         uint32_t counter = isc_stats_get_counter(stats->counters, idx);
  385         if (counter == 0) {
  386             isc_stats_set(stats->counters, kval, idx);
  387             isc_stats_increment(stats->counters, (idx + operation));
  388             return;
  389         }
  390     }
  391 
  392     /* No room, rotate keys. */
  393     for (int i = 1; i < dnssecsign_max_keys; i++) {
  394         int gidx = i * dnssecsign_block_size; /* Get key (get index,
  395                              gidx) */
  396         uint32_t keyv = isc_stats_get_counter(stats->counters, gidx);
  397         uint32_t sign = isc_stats_get_counter(
  398             stats->counters, (gidx + dns_dnssecsignstats_sign));
  399         uint32_t refr = isc_stats_get_counter(
  400             stats->counters, (gidx + dns_dnssecsignstats_refresh));
  401 
  402         int sidx = (i - 1) * dnssecsign_block_size; /* Set key, (set
  403                                    index, sidx) */
  404         isc_stats_set(stats->counters, keyv, sidx);
  405         isc_stats_set(stats->counters, sign,
  406                   (sidx + dns_dnssecsignstats_sign));
  407         isc_stats_set(stats->counters, refr,
  408                   (sidx + dns_dnssecsignstats_refresh));
  409     }
  410 
  411     /* Reset counters for new key (new index, nidx). */
  412     int nidx = (dnssecsign_max_keys - 1) * dnssecsign_block_size;
  413     isc_stats_set(stats->counters, kval, nidx);
  414     isc_stats_set(stats->counters, 0, (nidx + dns_dnssecsignstats_sign));
  415     isc_stats_set(stats->counters, 0, (nidx + dns_dnssecsignstats_refresh));
  416 
  417     /* And increment the counter for the given operation. */
  418     isc_stats_increment(stats->counters, (nidx + operation));
  419 }
  420 
  421 /*%
  422  * Dump methods
  423  */
  424 void
  425 dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn,
  426               void *arg, unsigned int options) {
  427     REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
  428 
  429     isc_stats_dump(stats->counters, (isc_stats_dumper_t)dump_fn, arg,
  430                options);
  431 }
  432 
  433 static void
  434 dump_rdentry(int rdcounter, uint64_t value, dns_rdatastatstype_t attributes,
  435          dns_rdatatypestats_dumper_t dump_fn, void *arg) {
  436     dns_rdatatype_t rdtype = dns_rdatatype_none; /* sentinel */
  437     dns_rdatastatstype_t type;
  438 
  439     if ((rdcounter & RDTYPECOUNTER_MAXTYPE) == 0) {
  440         attributes |= DNS_RDATASTATSTYPE_ATTR_OTHERTYPE;
  441     } else {
  442         rdtype = (dns_rdatatype_t)(rdcounter & RDTYPECOUNTER_MAXTYPE);
  443     }
  444     type = DNS_RDATASTATSTYPE_VALUE((dns_rdatastatstype_t)rdtype,
  445                     attributes);
  446     dump_fn(type, value, arg);
  447 }
  448 
  449 static void
  450 rdatatype_dumpcb(isc_statscounter_t counter, uint64_t value, void *arg) {
  451     rdatadumparg_t *rdatadumparg = arg;
  452 
  453     dump_rdentry(counter, value, 0, rdatadumparg->fn, rdatadumparg->arg);
  454 }
  455 
  456 void
  457 dns_rdatatypestats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
  458             void *arg0, unsigned int options) {
  459     rdatadumparg_t arg;
  460     REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
  461 
  462     arg.fn = dump_fn;
  463     arg.arg = arg0;
  464     isc_stats_dump(stats->counters, rdatatype_dumpcb, &arg, options);
  465 }
  466 
  467 static void
  468 rdataset_dumpcb(isc_statscounter_t counter, uint64_t value, void *arg) {
  469     rdatadumparg_t *rdatadumparg = arg;
  470     unsigned int attributes = 0;
  471 
  472     if ((counter & RDTYPECOUNTER_NXDOMAIN) == RDTYPECOUNTER_NXDOMAIN) {
  473         attributes |= DNS_RDATASTATSTYPE_ATTR_NXDOMAIN;
  474 
  475         /*
  476          * This is an NXDOMAIN counter, check the RRtype part for the
  477          * expiry value (active, stale, or ancient).
  478          */
  479         if ((counter & RDTYPECOUNTER_MAXTYPE) ==
  480             RDTYPECOUNTER_NXDOMAIN_STALE) {
  481             attributes |= DNS_RDATASTATSTYPE_ATTR_STALE;
  482         } else if ((counter & RDTYPECOUNTER_MAXTYPE) ==
  483                RDTYPECOUNTER_NXDOMAIN_ANCIENT) {
  484             attributes |= DNS_RDATASTATSTYPE_ATTR_ANCIENT;
  485         }
  486     } else {
  487         if ((counter & RDTYPECOUNTER_MAXTYPE) == 0) {
  488             attributes |= DNS_RDATASTATSTYPE_ATTR_OTHERTYPE;
  489         }
  490         if ((counter & RDTYPECOUNTER_NXRRSET) != 0) {
  491             attributes |= DNS_RDATASTATSTYPE_ATTR_NXRRSET;
  492         }
  493 
  494         if ((counter & RDTYPECOUNTER_STALE) != 0) {
  495             attributes |= DNS_RDATASTATSTYPE_ATTR_STALE;
  496         } else if ((counter & RDTYPECOUNTER_ANCIENT) != 0) {
  497             attributes |= DNS_RDATASTATSTYPE_ATTR_ANCIENT;
  498         }
  499     }
  500 
  501     dump_rdentry(counter, value, attributes, rdatadumparg->fn,
  502              rdatadumparg->arg);
  503 }
  504 
  505 void
  506 dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
  507                void *arg0, unsigned int options) {
  508     rdatadumparg_t arg;
  509 
  510     REQUIRE(DNS_STATS_VALID(stats) &&
  511         stats->type == dns_statstype_rdataset);
  512 
  513     arg.fn = dump_fn;
  514     arg.arg = arg0;
  515     isc_stats_dump(stats->counters, rdataset_dumpcb, &arg, options);
  516 }
  517 
  518 static void
  519 dnssec_dumpcb(isc_statscounter_t counter, uint64_t value, void *arg) {
  520     dnssecsigndumparg_t *dnssecarg = arg;
  521 
  522     dnssecarg->fn((dns_keytag_t)counter, value, dnssecarg->arg);
  523 }
  524 
  525 static void
  526 dnssec_statsdump(isc_stats_t *stats, dnssecsignstats_type_t operation,
  527          isc_stats_dumper_t dump_fn, void *arg, unsigned int options) {
  528     int i;
  529 
  530     for (i = 0; i < dnssecsign_max_keys; i++) {
  531         int idx = dnssecsign_block_size * i;
  532         uint32_t kval, val;
  533         dns_keytag_t id;
  534 
  535         kval = isc_stats_get_counter(stats, idx);
  536         if (kval == 0) {
  537             continue;
  538         }
  539 
  540         val = isc_stats_get_counter(stats, (idx + operation));
  541         if ((options & ISC_STATSDUMP_VERBOSE) == 0 && val == 0) {
  542             continue;
  543         }
  544 
  545         id = (dns_keytag_t)kval & DNSSECSIGNSTATS_KEY_ID_MASK;
  546 
  547         dump_fn((isc_statscounter_t)id, val, arg);
  548     }
  549 }
  550 
  551 void
  552 dns_dnssecsignstats_dump(dns_stats_t *stats, dnssecsignstats_type_t operation,
  553              dns_dnssecsignstats_dumper_t dump_fn, void *arg0,
  554              unsigned int options) {
  555     dnssecsigndumparg_t arg;
  556 
  557     REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_dnssec);
  558 
  559     arg.fn = dump_fn;
  560     arg.arg = arg0;
  561 
  562     dnssec_statsdump(stats->counters, operation, dnssec_dumpcb, &arg,
  563              options);
  564 }
  565 
  566 static void
  567 opcode_dumpcb(isc_statscounter_t counter, uint64_t value, void *arg) {
  568     opcodedumparg_t *opcodearg = arg;
  569 
  570     opcodearg->fn((dns_opcode_t)counter, value, opcodearg->arg);
  571 }
  572 
  573 static void
  574 rcode_dumpcb(isc_statscounter_t counter, uint64_t value, void *arg) {
  575     rcodedumparg_t *rcodearg = arg;
  576 
  577     rcodearg->fn((dns_rcode_t)counter, value, rcodearg->arg);
  578 }
  579 
  580 void
  581 dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn,
  582              void *arg0, unsigned int options) {
  583     opcodedumparg_t arg;
  584 
  585     REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
  586 
  587     arg.fn = dump_fn;
  588     arg.arg = arg0;
  589     isc_stats_dump(stats->counters, opcode_dumpcb, &arg, options);
  590 }
  591 
  592 void
  593 dns_rcodestats_dump(dns_stats_t *stats, dns_rcodestats_dumper_t dump_fn,
  594             void *arg0, unsigned int options) {
  595     rcodedumparg_t arg;
  596 
  597     REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rcode);
  598 
  599     arg.fn = dump_fn;
  600     arg.arg = arg0;
  601     isc_stats_dump(stats->counters, rcode_dumpcb, &arg, options);
  602 }
  603 
  604 /***
  605  *** Obsolete variables and functions follow:
  606  ***/
  607 LIBDNS_EXTERNAL_DATA const char *dns_statscounter_names[DNS_STATS_NCOUNTERS] = {
  608     "success",   "referral", "nxrrset",   "nxdomain",
  609     "recursion", "failure",  "duplicate", "dropped"
  610 };
  611 
  612 isc_result_t
  613 dns_stats_alloccounters(isc_mem_t *mctx, uint64_t **ctrp) {
  614     int i;
  615     uint64_t *p = isc_mem_get(mctx, DNS_STATS_NCOUNTERS * sizeof(uint64_t));
  616     if (p == NULL) {
  617         return (ISC_R_NOMEMORY);
  618     }
  619     for (i = 0; i < DNS_STATS_NCOUNTERS; i++) {
  620         p[i] = 0;
  621     }
  622     *ctrp = p;
  623     return (ISC_R_SUCCESS);
  624 }
  625 
  626 void
  627 dns_stats_freecounters(isc_mem_t *mctx, uint64_t **ctrp) {
  628     isc_mem_put(mctx, *ctrp, DNS_STATS_NCOUNTERS * sizeof(uint64_t));
  629     *ctrp = NULL;
  630 }