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 https://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 = 0b11 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 = 0b11 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_num_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
dns_stats_attach(dns_stats_t * stats,dns_stats_t ** statsp)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
dns_stats_detach(dns_stats_t ** statsp)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
create_stats(isc_mem_t * mctx,dns_statstype_t type,int ncounters,dns_stats_t ** statsp)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
dns_generalstats_create(isc_mem_t * mctx,dns_stats_t ** statsp,int ncounters)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
dns_rdatatypestats_create(isc_mem_t * mctx,dns_stats_t ** statsp)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
dns_rdatasetstats_create(isc_mem_t * mctx,dns_stats_t ** statsp)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
dns_opcodestats_create(isc_mem_t * mctx,dns_stats_t ** statsp)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
dns_rcodestats_create(isc_mem_t * mctx,dns_stats_t ** statsp)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
dns_dnssecsignstats_create(isc_mem_t * mctx,dns_stats_t ** statsp)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_num_keys * dnssecsign_block_size,
249 statsp));
250 }
251
252 /*%
253 * Increment/Decrement methods
254 */
255 void
dns_generalstats_increment(dns_stats_t * stats,isc_statscounter_t counter)256 dns_generalstats_increment(dns_stats_t *stats, isc_statscounter_t counter) {
257 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
258
259 isc_stats_increment(stats->counters, counter);
260 }
261
262 inline static isc_statscounter_t
rdatatype2counter(dns_rdatatype_t type)263 rdatatype2counter(dns_rdatatype_t type) {
264 if (type > (dns_rdatatype_t)RDTYPECOUNTER_MAXTYPE) {
265 return (0);
266 }
267 return ((isc_statscounter_t)type);
268 }
269
270 void
dns_rdatatypestats_increment(dns_stats_t * stats,dns_rdatatype_t type)271 dns_rdatatypestats_increment(dns_stats_t *stats, dns_rdatatype_t type) {
272 isc_statscounter_t counter;
273
274 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
275
276 counter = rdatatype2counter(type);
277 isc_stats_increment(stats->counters, counter);
278 }
279
280 static inline void
update_rdatasetstats(dns_stats_t * stats,dns_rdatastatstype_t rrsettype,bool increment)281 update_rdatasetstats(dns_stats_t *stats, dns_rdatastatstype_t rrsettype,
282 bool increment) {
283 isc_statscounter_t counter;
284
285 if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
286 DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) != 0)
287 {
288 counter = RDTYPECOUNTER_NXDOMAIN;
289
290 /*
291 * This is an NXDOMAIN counter, save the expiry value
292 * (active, stale, or ancient) value in the RRtype part.
293 */
294 if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
295 DNS_RDATASTATSTYPE_ATTR_ANCIENT) != 0) {
296 counter |= RDTYPECOUNTER_NXDOMAIN_ANCIENT;
297 } else if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
298 DNS_RDATASTATSTYPE_ATTR_STALE) != 0)
299 {
300 counter += RDTYPECOUNTER_NXDOMAIN_STALE;
301 }
302 } else {
303 counter = rdatatype2counter(DNS_RDATASTATSTYPE_BASE(rrsettype));
304
305 if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
306 DNS_RDATASTATSTYPE_ATTR_NXRRSET) != 0) {
307 counter |= RDTYPECOUNTER_NXRRSET;
308 }
309
310 if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
311 DNS_RDATASTATSTYPE_ATTR_ANCIENT) != 0) {
312 counter |= RDTYPECOUNTER_ANCIENT;
313 } else if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
314 DNS_RDATASTATSTYPE_ATTR_STALE) != 0)
315 {
316 counter |= RDTYPECOUNTER_STALE;
317 }
318 }
319
320 if (increment) {
321 isc_stats_increment(stats->counters, counter);
322 } else {
323 isc_stats_decrement(stats->counters, counter);
324 }
325 }
326
327 void
dns_rdatasetstats_increment(dns_stats_t * stats,dns_rdatastatstype_t rrsettype)328 dns_rdatasetstats_increment(dns_stats_t *stats,
329 dns_rdatastatstype_t rrsettype) {
330 REQUIRE(DNS_STATS_VALID(stats) &&
331 stats->type == dns_statstype_rdataset);
332
333 update_rdatasetstats(stats, rrsettype, true);
334 }
335
336 void
dns_rdatasetstats_decrement(dns_stats_t * stats,dns_rdatastatstype_t rrsettype)337 dns_rdatasetstats_decrement(dns_stats_t *stats,
338 dns_rdatastatstype_t rrsettype) {
339 REQUIRE(DNS_STATS_VALID(stats) &&
340 stats->type == dns_statstype_rdataset);
341
342 update_rdatasetstats(stats, rrsettype, false);
343 }
344
345 void
dns_opcodestats_increment(dns_stats_t * stats,dns_opcode_t code)346 dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code) {
347 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
348
349 isc_stats_increment(stats->counters, (isc_statscounter_t)code);
350 }
351
352 void
dns_rcodestats_increment(dns_stats_t * stats,dns_rcode_t code)353 dns_rcodestats_increment(dns_stats_t *stats, dns_rcode_t code) {
354 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rcode);
355
356 if (code <= dns_rcode_badcookie) {
357 isc_stats_increment(stats->counters, (isc_statscounter_t)code);
358 }
359 }
360
361 void
dns_dnssecsignstats_increment(dns_stats_t * stats,dns_keytag_t id,uint8_t alg,dnssecsignstats_type_t operation)362 dns_dnssecsignstats_increment(dns_stats_t *stats, dns_keytag_t id, uint8_t alg,
363 dnssecsignstats_type_t operation) {
364 uint32_t kval;
365 int num_keys = isc_stats_ncounters(stats->counters) /
366 dnssecsign_block_size;
367
368 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_dnssec);
369
370 /* Shift algorithm in front of key tag, which is 16 bits */
371 kval = (uint32_t)(alg << 16 | id);
372
373 /* Look up correct counter. */
374 for (int i = 0; i < num_keys; i++) {
375 int idx = i * dnssecsign_block_size;
376 uint32_t counter = isc_stats_get_counter(stats->counters, idx);
377 if (counter == kval) {
378 /* Match */
379 isc_stats_increment(stats->counters, (idx + operation));
380 return;
381 }
382 }
383
384 /* No match found. Store key in unused slot. */
385 for (int i = 0; i < num_keys; i++) {
386 int idx = i * dnssecsign_block_size;
387 uint32_t counter = isc_stats_get_counter(stats->counters, idx);
388 if (counter == 0) {
389 isc_stats_set(stats->counters, kval, idx);
390 isc_stats_increment(stats->counters, (idx + operation));
391 return;
392 }
393 }
394
395 /* No room, grow stats storage. */
396 isc_stats_resize(&stats->counters,
397 (num_keys * dnssecsign_block_size * 2));
398
399 /* Reset counters for new key (new index, nidx). */
400 int nidx = num_keys * dnssecsign_block_size;
401 isc_stats_set(stats->counters, kval, nidx);
402 isc_stats_set(stats->counters, 0, (nidx + dns_dnssecsignstats_sign));
403 isc_stats_set(stats->counters, 0, (nidx + dns_dnssecsignstats_refresh));
404
405 /* And increment the counter for the given operation. */
406 isc_stats_increment(stats->counters, (nidx + operation));
407 }
408
409 void
dns_dnssecsignstats_clear(dns_stats_t * stats,dns_keytag_t id,uint8_t alg)410 dns_dnssecsignstats_clear(dns_stats_t *stats, dns_keytag_t id, uint8_t alg) {
411 uint32_t kval;
412 int num_keys = isc_stats_ncounters(stats->counters) /
413 dnssecsign_block_size;
414
415 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_dnssec);
416
417 /* Shift algorithm in front of key tag, which is 16 bits */
418 kval = (uint32_t)(alg << 16 | id);
419
420 /* Look up correct counter. */
421 for (int i = 0; i < num_keys; i++) {
422 int idx = i * dnssecsign_block_size;
423 uint32_t counter = isc_stats_get_counter(stats->counters, idx);
424 if (counter == kval) {
425 /* Match */
426 isc_stats_set(stats->counters, 0, idx);
427 isc_stats_set(stats->counters, 0,
428 (idx + dns_dnssecsignstats_sign));
429 isc_stats_set(stats->counters, 0,
430 (idx + dns_dnssecsignstats_refresh));
431 return;
432 }
433 }
434 }
435
436 /*%
437 * Dump methods
438 */
439 void
dns_generalstats_dump(dns_stats_t * stats,dns_generalstats_dumper_t dump_fn,void * arg,unsigned int options)440 dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn,
441 void *arg, unsigned int options) {
442 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
443
444 isc_stats_dump(stats->counters, (isc_stats_dumper_t)dump_fn, arg,
445 options);
446 }
447
448 static void
dump_rdentry(int rdcounter,uint64_t value,dns_rdatastatstype_t attributes,dns_rdatatypestats_dumper_t dump_fn,void * arg)449 dump_rdentry(int rdcounter, uint64_t value, dns_rdatastatstype_t attributes,
450 dns_rdatatypestats_dumper_t dump_fn, void *arg) {
451 dns_rdatatype_t rdtype = dns_rdatatype_none; /* sentinel */
452 dns_rdatastatstype_t type;
453
454 if ((rdcounter & RDTYPECOUNTER_MAXTYPE) == 0) {
455 attributes |= DNS_RDATASTATSTYPE_ATTR_OTHERTYPE;
456 } else {
457 rdtype = (dns_rdatatype_t)(rdcounter & RDTYPECOUNTER_MAXTYPE);
458 }
459 type = DNS_RDATASTATSTYPE_VALUE((dns_rdatastatstype_t)rdtype,
460 attributes);
461 dump_fn(type, value, arg);
462 }
463
464 static void
rdatatype_dumpcb(isc_statscounter_t counter,uint64_t value,void * arg)465 rdatatype_dumpcb(isc_statscounter_t counter, uint64_t value, void *arg) {
466 rdatadumparg_t *rdatadumparg = arg;
467
468 dump_rdentry(counter, value, 0, rdatadumparg->fn, rdatadumparg->arg);
469 }
470
471 void
dns_rdatatypestats_dump(dns_stats_t * stats,dns_rdatatypestats_dumper_t dump_fn,void * arg0,unsigned int options)472 dns_rdatatypestats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
473 void *arg0, unsigned int options) {
474 rdatadumparg_t arg;
475 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
476
477 arg.fn = dump_fn;
478 arg.arg = arg0;
479 isc_stats_dump(stats->counters, rdatatype_dumpcb, &arg, options);
480 }
481
482 static void
rdataset_dumpcb(isc_statscounter_t counter,uint64_t value,void * arg)483 rdataset_dumpcb(isc_statscounter_t counter, uint64_t value, void *arg) {
484 rdatadumparg_t *rdatadumparg = arg;
485 unsigned int attributes = 0;
486
487 if ((counter & RDTYPECOUNTER_NXDOMAIN) == RDTYPECOUNTER_NXDOMAIN) {
488 attributes |= DNS_RDATASTATSTYPE_ATTR_NXDOMAIN;
489
490 /*
491 * This is an NXDOMAIN counter, check the RRtype part for the
492 * expiry value (active, stale, or ancient).
493 */
494 if ((counter & RDTYPECOUNTER_MAXTYPE) ==
495 RDTYPECOUNTER_NXDOMAIN_STALE) {
496 attributes |= DNS_RDATASTATSTYPE_ATTR_STALE;
497 } else if ((counter & RDTYPECOUNTER_MAXTYPE) ==
498 RDTYPECOUNTER_NXDOMAIN_ANCIENT) {
499 attributes |= DNS_RDATASTATSTYPE_ATTR_ANCIENT;
500 }
501 } else {
502 if ((counter & RDTYPECOUNTER_MAXTYPE) == 0) {
503 attributes |= DNS_RDATASTATSTYPE_ATTR_OTHERTYPE;
504 }
505 if ((counter & RDTYPECOUNTER_NXRRSET) != 0) {
506 attributes |= DNS_RDATASTATSTYPE_ATTR_NXRRSET;
507 }
508
509 if ((counter & RDTYPECOUNTER_STALE) != 0) {
510 attributes |= DNS_RDATASTATSTYPE_ATTR_STALE;
511 } else if ((counter & RDTYPECOUNTER_ANCIENT) != 0) {
512 attributes |= DNS_RDATASTATSTYPE_ATTR_ANCIENT;
513 }
514 }
515
516 dump_rdentry(counter, value, attributes, rdatadumparg->fn,
517 rdatadumparg->arg);
518 }
519
520 void
dns_rdatasetstats_dump(dns_stats_t * stats,dns_rdatatypestats_dumper_t dump_fn,void * arg0,unsigned int options)521 dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
522 void *arg0, unsigned int options) {
523 rdatadumparg_t arg;
524
525 REQUIRE(DNS_STATS_VALID(stats) &&
526 stats->type == dns_statstype_rdataset);
527
528 arg.fn = dump_fn;
529 arg.arg = arg0;
530 isc_stats_dump(stats->counters, rdataset_dumpcb, &arg, options);
531 }
532
533 static void
dnssec_dumpcb(isc_statscounter_t counter,uint64_t value,void * arg)534 dnssec_dumpcb(isc_statscounter_t counter, uint64_t value, void *arg) {
535 dnssecsigndumparg_t *dnssecarg = arg;
536
537 dnssecarg->fn((dns_keytag_t)counter, value, dnssecarg->arg);
538 }
539
540 static void
dnssec_statsdump(isc_stats_t * stats,dnssecsignstats_type_t operation,isc_stats_dumper_t dump_fn,void * arg,unsigned int options)541 dnssec_statsdump(isc_stats_t *stats, dnssecsignstats_type_t operation,
542 isc_stats_dumper_t dump_fn, void *arg, unsigned int options) {
543 int i, num_keys;
544
545 num_keys = isc_stats_ncounters(stats) / dnssecsign_block_size;
546 for (i = 0; i < num_keys; i++) {
547 int idx = dnssecsign_block_size * i;
548 uint32_t kval, val;
549 dns_keytag_t id;
550
551 kval = isc_stats_get_counter(stats, idx);
552 if (kval == 0) {
553 continue;
554 }
555
556 val = isc_stats_get_counter(stats, (idx + operation));
557 if ((options & ISC_STATSDUMP_VERBOSE) == 0 && val == 0) {
558 continue;
559 }
560
561 id = (dns_keytag_t)kval & DNSSECSIGNSTATS_KEY_ID_MASK;
562
563 dump_fn((isc_statscounter_t)id, val, arg);
564 }
565 }
566
567 void
dns_dnssecsignstats_dump(dns_stats_t * stats,dnssecsignstats_type_t operation,dns_dnssecsignstats_dumper_t dump_fn,void * arg0,unsigned int options)568 dns_dnssecsignstats_dump(dns_stats_t *stats, dnssecsignstats_type_t operation,
569 dns_dnssecsignstats_dumper_t dump_fn, void *arg0,
570 unsigned int options) {
571 dnssecsigndumparg_t arg;
572
573 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_dnssec);
574
575 arg.fn = dump_fn;
576 arg.arg = arg0;
577
578 dnssec_statsdump(stats->counters, operation, dnssec_dumpcb, &arg,
579 options);
580 }
581
582 static void
opcode_dumpcb(isc_statscounter_t counter,uint64_t value,void * arg)583 opcode_dumpcb(isc_statscounter_t counter, uint64_t value, void *arg) {
584 opcodedumparg_t *opcodearg = arg;
585
586 opcodearg->fn((dns_opcode_t)counter, value, opcodearg->arg);
587 }
588
589 static void
rcode_dumpcb(isc_statscounter_t counter,uint64_t value,void * arg)590 rcode_dumpcb(isc_statscounter_t counter, uint64_t value, void *arg) {
591 rcodedumparg_t *rcodearg = arg;
592
593 rcodearg->fn((dns_rcode_t)counter, value, rcodearg->arg);
594 }
595
596 void
dns_opcodestats_dump(dns_stats_t * stats,dns_opcodestats_dumper_t dump_fn,void * arg0,unsigned int options)597 dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn,
598 void *arg0, unsigned int options) {
599 opcodedumparg_t arg;
600
601 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
602
603 arg.fn = dump_fn;
604 arg.arg = arg0;
605 isc_stats_dump(stats->counters, opcode_dumpcb, &arg, options);
606 }
607
608 void
dns_rcodestats_dump(dns_stats_t * stats,dns_rcodestats_dumper_t dump_fn,void * arg0,unsigned int options)609 dns_rcodestats_dump(dns_stats_t *stats, dns_rcodestats_dumper_t dump_fn,
610 void *arg0, unsigned int options) {
611 rcodedumparg_t arg;
612
613 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rcode);
614
615 arg.fn = dump_fn;
616 arg.arg = arg0;
617 isc_stats_dump(stats->counters, rcode_dumpcb, &arg, options);
618 }
619
620 /***
621 *** Obsolete variables and functions follow:
622 ***/
623 const char *dns_statscounter_names[DNS_STATS_NCOUNTERS] = {
624 "success", "referral", "nxrrset", "nxdomain",
625 "recursion", "failure", "duplicate", "dropped"
626 };
627
628 isc_result_t
dns_stats_alloccounters(isc_mem_t * mctx,uint64_t ** ctrp)629 dns_stats_alloccounters(isc_mem_t *mctx, uint64_t **ctrp) {
630 int i;
631 uint64_t *p = isc_mem_get(mctx, DNS_STATS_NCOUNTERS * sizeof(uint64_t));
632 if (p == NULL) {
633 return (ISC_R_NOMEMORY);
634 }
635 for (i = 0; i < DNS_STATS_NCOUNTERS; i++) {
636 p[i] = 0;
637 }
638 *ctrp = p;
639 return (ISC_R_SUCCESS);
640 }
641
642 void
dns_stats_freecounters(isc_mem_t * mctx,uint64_t ** ctrp)643 dns_stats_freecounters(isc_mem_t *mctx, uint64_t **ctrp) {
644 isc_mem_put(mctx, *ctrp, DNS_STATS_NCOUNTERS * sizeof(uint64_t));
645 *ctrp = NULL;
646 }
647