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