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