1 /* $NetBSD: ncache.c,v 1.10 2025/01/26 16:25:23 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/buffer.h> 22 #include <isc/util.h> 23 24 #include <dns/db.h> 25 #include <dns/message.h> 26 #include <dns/ncache.h> 27 #include <dns/rdata.h> 28 #include <dns/rdatalist.h> 29 #include <dns/rdataset.h> 30 #include <dns/rdatastruct.h> 31 32 #define DNS_NCACHE_RDATA 100U 33 34 /* 35 * The format of an ncache rdata is a sequence of zero or more records 36 * of the following format: 37 * 38 * owner name 39 * type 40 * trust 41 * rdata count 42 * rdata length These two occur 'rdata 43 * rdata count' times. 44 * 45 */ 46 47 static uint8_t 48 atomic_getuint8(isc_buffer_t *b) { 49 atomic_uchar *cp = isc_buffer_current(b); 50 uint8_t ret = atomic_load_relaxed(cp); 51 isc_buffer_forward(b, 1); 52 return ret; 53 } 54 55 static isc_result_t 56 addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, 57 dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl, 58 dns_ttl_t maxttl, bool optout, bool secure, 59 dns_rdataset_t *addedrdataset); 60 61 static isc_result_t 62 copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) { 63 isc_result_t result; 64 unsigned int count; 65 isc_region_t ar, r; 66 dns_rdata_t rdata = DNS_RDATA_INIT; 67 68 /* 69 * Copy the rdataset count to the buffer. 70 */ 71 isc_buffer_availableregion(buffer, &ar); 72 if (ar.length < 2) { 73 return ISC_R_NOSPACE; 74 } 75 count = dns_rdataset_count(rdataset); 76 INSIST(count <= 65535); 77 isc_buffer_putuint16(buffer, (uint16_t)count); 78 79 result = dns_rdataset_first(rdataset); 80 while (result == ISC_R_SUCCESS) { 81 dns_rdataset_current(rdataset, &rdata); 82 dns_rdata_toregion(&rdata, &r); 83 INSIST(r.length <= 65535); 84 isc_buffer_availableregion(buffer, &ar); 85 if (ar.length < 2) { 86 return ISC_R_NOSPACE; 87 } 88 /* 89 * Copy the rdata length to the buffer. 90 */ 91 isc_buffer_putuint16(buffer, (uint16_t)r.length); 92 /* 93 * Copy the rdata to the buffer. 94 */ 95 result = isc_buffer_copyregion(buffer, &r); 96 if (result != ISC_R_SUCCESS) { 97 return result; 98 } 99 dns_rdata_reset(&rdata); 100 result = dns_rdataset_next(rdataset); 101 } 102 if (result != ISC_R_NOMORE) { 103 return result; 104 } 105 106 return ISC_R_SUCCESS; 107 } 108 109 isc_result_t 110 dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, 111 dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl, 112 dns_ttl_t maxttl, dns_rdataset_t *addedrdataset) { 113 return addoptout(message, cache, node, covers, now, minttl, maxttl, 114 false, false, addedrdataset); 115 } 116 117 isc_result_t 118 dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache, 119 dns_dbnode_t *node, dns_rdatatype_t covers, 120 isc_stdtime_t now, dns_ttl_t minttl, dns_ttl_t maxttl, 121 bool optout, dns_rdataset_t *addedrdataset) { 122 return addoptout(message, cache, node, covers, now, minttl, maxttl, 123 optout, true, addedrdataset); 124 } 125 126 static isc_result_t 127 addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, 128 dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl, 129 dns_ttl_t maxttl, bool optout, bool secure, 130 dns_rdataset_t *addedrdataset) { 131 isc_result_t result; 132 isc_buffer_t buffer; 133 isc_region_t r; 134 dns_rdataset_t *rdataset; 135 dns_rdatatype_t type; 136 dns_name_t *name; 137 dns_ttl_t ttl; 138 dns_trust_t trust; 139 dns_rdata_t rdata[DNS_NCACHE_RDATA]; 140 dns_rdataset_t ncrdataset; 141 dns_rdatalist_t ncrdatalist; 142 unsigned char data[65536]; 143 unsigned int next = 0; 144 145 /* 146 * Convert the authority data from 'message' into a negative cache 147 * rdataset, and store it in 'cache' at 'node'. 148 */ 149 150 REQUIRE(message != NULL); 151 152 /* 153 * We assume that all data in the authority section has been 154 * validated by the caller. 155 */ 156 157 /* 158 * Initialize the list. 159 */ 160 dns_rdatalist_init(&ncrdatalist); 161 ncrdatalist.rdclass = dns_db_class(cache); 162 ncrdatalist.covers = covers; 163 ncrdatalist.ttl = maxttl; 164 165 /* 166 * Build an ncache rdatas into buffer. 167 */ 168 ttl = maxttl; 169 trust = 0xffff; 170 isc_buffer_init(&buffer, data, sizeof(data)); 171 if (message->counts[DNS_SECTION_AUTHORITY]) { 172 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); 173 } else { 174 result = ISC_R_NOMORE; 175 } 176 while (result == ISC_R_SUCCESS) { 177 name = NULL; 178 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name); 179 if (name->attributes.ncache) { 180 for (rdataset = ISC_LIST_HEAD(name->list); 181 rdataset != NULL; 182 rdataset = ISC_LIST_NEXT(rdataset, link)) 183 { 184 if ((rdataset->attributes & 185 DNS_RDATASETATTR_NCACHE) == 0) 186 { 187 continue; 188 } 189 type = rdataset->type; 190 if (type == dns_rdatatype_rrsig) { 191 type = rdataset->covers; 192 } 193 if (type == dns_rdatatype_soa || 194 type == dns_rdatatype_nsec || 195 type == dns_rdatatype_nsec3) 196 { 197 if (ttl > rdataset->ttl) { 198 ttl = rdataset->ttl; 199 } 200 if (ttl < minttl) { 201 ttl = minttl; 202 } 203 if (trust > rdataset->trust) { 204 trust = rdataset->trust; 205 } 206 /* 207 * Copy the owner name to the buffer. 208 */ 209 dns_name_toregion(name, &r); 210 result = isc_buffer_copyregion(&buffer, 211 &r); 212 if (result != ISC_R_SUCCESS) { 213 return result; 214 } 215 /* 216 * Copy the type to the buffer. 217 */ 218 isc_buffer_availableregion(&buffer, &r); 219 if (r.length < 3) { 220 return ISC_R_NOSPACE; 221 } 222 isc_buffer_putuint16(&buffer, 223 rdataset->type); 224 isc_buffer_putuint8( 225 &buffer, 226 (unsigned char)rdataset->trust); 227 /* 228 * Copy the rdataset into the buffer. 229 */ 230 result = copy_rdataset(rdataset, 231 &buffer); 232 if (result != ISC_R_SUCCESS) { 233 return result; 234 } 235 236 if (next >= DNS_NCACHE_RDATA) { 237 return ISC_R_NOSPACE; 238 } 239 dns_rdata_init(&rdata[next]); 240 isc_buffer_remainingregion(&buffer, &r); 241 rdata[next].data = r.base; 242 rdata[next].length = r.length; 243 rdata[next].rdclass = 244 ncrdatalist.rdclass; 245 rdata[next].type = 0; 246 rdata[next].flags = 0; 247 ISC_LIST_APPEND(ncrdatalist.rdata, 248 &rdata[next], link); 249 isc_buffer_forward(&buffer, r.length); 250 next++; 251 } 252 } 253 } 254 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY); 255 } 256 if (result != ISC_R_NOMORE) { 257 return result; 258 } 259 260 if (trust == 0xffff) { 261 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 && 262 message->counts[DNS_SECTION_ANSWER] == 0) 263 { 264 /* 265 * The response has aa set and we haven't followed 266 * any CNAME or DNAME chains. 267 */ 268 trust = dns_trust_authauthority; 269 } else { 270 trust = dns_trust_additional; 271 } 272 ttl = 0; 273 } 274 275 INSIST(trust != 0xffff); 276 277 ncrdatalist.ttl = ttl; 278 279 dns_rdataset_init(&ncrdataset); 280 dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset); 281 if (!secure && trust > dns_trust_answer) { 282 trust = dns_trust_answer; 283 } 284 ncrdataset.trust = trust; 285 ncrdataset.attributes |= DNS_RDATASETATTR_NEGATIVE; 286 if (message->rcode == dns_rcode_nxdomain) { 287 ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN; 288 } 289 if (optout) { 290 ncrdataset.attributes |= DNS_RDATASETATTR_OPTOUT; 291 } 292 293 return dns_db_addrdataset(cache, node, NULL, now, &ncrdataset, 0, 294 addedrdataset); 295 } 296 297 isc_result_t 298 dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx, 299 isc_buffer_t *target, unsigned int options, 300 unsigned int *countp) { 301 dns_rdata_t rdata = DNS_RDATA_INIT; 302 isc_result_t result; 303 isc_region_t remaining, tavailable; 304 isc_buffer_t source, savedbuffer, rdlen; 305 dns_name_t name; 306 dns_rdatatype_t type; 307 unsigned int i, rcount, count; 308 309 /* 310 * Convert the negative caching rdataset 'rdataset' to wire format, 311 * compressing names as specified in 'cctx', and storing the result in 312 * 'target'. 313 */ 314 315 REQUIRE(rdataset != NULL); 316 REQUIRE(rdataset->type == 0); 317 REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); 318 319 savedbuffer = *target; 320 count = 0; 321 322 result = dns_rdataset_first(rdataset); 323 while (result == ISC_R_SUCCESS) { 324 dns_rdataset_current(rdataset, &rdata); 325 isc_buffer_init(&source, rdata.data, rdata.length); 326 isc_buffer_add(&source, rdata.length); 327 dns_name_init(&name, NULL); 328 isc_buffer_remainingregion(&source, &remaining); 329 dns_name_fromregion(&name, &remaining); 330 INSIST(remaining.length >= name.length); 331 isc_buffer_forward(&source, name.length); 332 remaining.length -= name.length; 333 334 INSIST(remaining.length >= 5); 335 type = isc_buffer_getuint16(&source); 336 isc_buffer_forward(&source, 1); 337 rcount = isc_buffer_getuint16(&source); 338 339 for (i = 0; i < rcount; i++) { 340 /* 341 * Get the length of this rdata and set up an 342 * rdata structure for it. 343 */ 344 isc_buffer_remainingregion(&source, &remaining); 345 INSIST(remaining.length >= 2); 346 dns_rdata_reset(&rdata); 347 rdata.length = isc_buffer_getuint16(&source); 348 isc_buffer_remainingregion(&source, &remaining); 349 rdata.data = remaining.base; 350 rdata.type = type; 351 rdata.rdclass = rdataset->rdclass; 352 INSIST(remaining.length >= rdata.length); 353 isc_buffer_forward(&source, rdata.length); 354 355 if ((options & DNS_NCACHETOWIRE_OMITDNSSEC) != 0 && 356 dns_rdatatype_isdnssec(type)) 357 { 358 continue; 359 } 360 361 /* 362 * Write the name. 363 */ 364 dns_compress_setpermitted(cctx, true); 365 result = dns_name_towire(&name, cctx, target, NULL); 366 if (result != ISC_R_SUCCESS) { 367 goto rollback; 368 } 369 370 /* 371 * See if we have space for type, class, ttl, and 372 * rdata length. Write the type, class, and ttl. 373 */ 374 isc_buffer_availableregion(target, &tavailable); 375 if (tavailable.length < 10) { 376 result = ISC_R_NOSPACE; 377 goto rollback; 378 } 379 isc_buffer_putuint16(target, type); 380 isc_buffer_putuint16(target, rdataset->rdclass); 381 isc_buffer_putuint32(target, rdataset->ttl); 382 383 /* 384 * Save space for rdata length. 385 */ 386 rdlen = *target; 387 isc_buffer_add(target, 2); 388 389 /* 390 * Write the rdata. 391 */ 392 result = dns_rdata_towire(&rdata, cctx, target); 393 if (result != ISC_R_SUCCESS) { 394 goto rollback; 395 } 396 397 /* 398 * Set the rdata length field to the compressed 399 * length. 400 */ 401 INSIST((target->used >= rdlen.used + 2) && 402 (target->used - rdlen.used - 2 < 65536)); 403 isc_buffer_putuint16( 404 &rdlen, 405 (uint16_t)(target->used - rdlen.used - 2)); 406 407 count++; 408 } 409 INSIST(isc_buffer_remaininglength(&source) == 0); 410 result = dns_rdataset_next(rdataset); 411 dns_rdata_reset(&rdata); 412 } 413 if (result != ISC_R_NOMORE) { 414 goto rollback; 415 } 416 417 *countp = count; 418 419 return ISC_R_SUCCESS; 420 421 rollback: 422 dns_compress_rollback(cctx, savedbuffer.used); 423 *countp = 0; 424 *target = savedbuffer; 425 426 return result; 427 } 428 429 static void 430 rdataset_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) { 431 UNUSED(rdataset); 432 } 433 434 static isc_result_t 435 rdataset_first(dns_rdataset_t *rdataset) { 436 unsigned char *raw; 437 unsigned int count; 438 439 raw = rdataset->ncache.raw; 440 count = raw[0] * 256 + raw[1]; 441 if (count == 0) { 442 rdataset->ncache.iter_pos = NULL; 443 return ISC_R_NOMORE; 444 } 445 /* 446 * iter_count is the number of rdata beyond the cursor position, 447 * so we decrement the total count by one before storing it. 448 */ 449 rdataset->ncache.iter_pos = raw + 2; 450 rdataset->ncache.iter_count = count - 1; 451 return ISC_R_SUCCESS; 452 } 453 454 static isc_result_t 455 rdataset_next(dns_rdataset_t *rdataset) { 456 unsigned int count; 457 unsigned int length; 458 unsigned char *raw; 459 460 raw = rdataset->ncache.iter_pos; 461 count = rdataset->ncache.iter_count; 462 if (count == 0) { 463 rdataset->ncache.iter_pos = NULL; 464 return ISC_R_NOMORE; 465 } 466 467 length = raw[0] * 256 + raw[1]; 468 rdataset->ncache.iter_pos = raw + 2 + length; 469 rdataset->ncache.iter_count = count - 1; 470 return ISC_R_SUCCESS; 471 } 472 473 static void 474 rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 475 unsigned char *raw; 476 isc_region_t r; 477 478 raw = rdataset->ncache.iter_pos; 479 REQUIRE(raw != NULL); 480 481 r.length = raw[0] * 256 + raw[1]; 482 r.base = raw + 2; 483 dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r); 484 } 485 486 static void 487 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG) { 488 *target = *source; 489 target->ncache.iter_pos = NULL; 490 target->ncache.iter_count = 0; 491 } 492 493 static unsigned int 494 rdataset_count(dns_rdataset_t *rdataset) { 495 unsigned char *raw; 496 unsigned int count; 497 498 raw = rdataset->ncache.raw; 499 count = raw[0] * 256 + raw[1]; 500 501 return count; 502 } 503 504 static void 505 rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { 506 atomic_uchar *raw; 507 508 raw = (atomic_uchar *)rdataset->ncache.raw; 509 atomic_store_relaxed(&raw[-1], (unsigned char)trust); 510 rdataset->trust = trust; 511 } 512 513 static dns_rdatasetmethods_t rdataset_methods = { 514 .disassociate = rdataset_disassociate, 515 .first = rdataset_first, 516 .next = rdataset_next, 517 .current = rdataset_current, 518 .clone = rdataset_clone, 519 .count = rdataset_count, 520 .settrust = rdataset_settrust, 521 }; 522 523 isc_result_t 524 dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name, 525 dns_rdatatype_t type, dns_rdataset_t *rdataset) { 526 isc_result_t result; 527 dns_rdata_t rdata = DNS_RDATA_INIT; 528 isc_region_t remaining; 529 isc_buffer_t source; 530 dns_name_t tname; 531 dns_rdatatype_t ttype; 532 dns_trust_t trust = dns_trust_none; 533 dns_rdataset_t rclone; 534 535 REQUIRE(ncacherdataset != NULL); 536 REQUIRE(DNS_RDATASET_VALID(ncacherdataset)); 537 REQUIRE(ncacherdataset->type == 0); 538 REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); 539 REQUIRE(name != NULL); 540 REQUIRE(!dns_rdataset_isassociated(rdataset)); 541 REQUIRE(type != dns_rdatatype_rrsig); 542 543 dns_rdataset_init(&rclone); 544 dns_rdataset_clone(ncacherdataset, &rclone); 545 result = dns_rdataset_first(&rclone); 546 while (result == ISC_R_SUCCESS) { 547 dns_rdataset_current(&rclone, &rdata); 548 isc_buffer_init(&source, rdata.data, rdata.length); 549 isc_buffer_add(&source, rdata.length); 550 dns_name_init(&tname, NULL); 551 isc_buffer_remainingregion(&source, &remaining); 552 dns_name_fromregion(&tname, &remaining); 553 INSIST(remaining.length >= tname.length); 554 isc_buffer_forward(&source, tname.length); 555 remaining.length -= tname.length; 556 557 INSIST(remaining.length >= 3); 558 ttype = isc_buffer_getuint16(&source); 559 560 if (ttype == type && dns_name_equal(&tname, name)) { 561 trust = atomic_getuint8(&source); 562 INSIST(trust <= dns_trust_ultimate); 563 isc_buffer_remainingregion(&source, &remaining); 564 break; 565 } 566 result = dns_rdataset_next(&rclone); 567 dns_rdata_reset(&rdata); 568 } 569 dns_rdataset_disassociate(&rclone); 570 if (result == ISC_R_NOMORE) { 571 return ISC_R_NOTFOUND; 572 } 573 if (result != ISC_R_SUCCESS) { 574 return result; 575 } 576 577 INSIST(remaining.length != 0); 578 579 rdataset->methods = &rdataset_methods; 580 rdataset->rdclass = ncacherdataset->rdclass; 581 rdataset->type = type; 582 rdataset->covers = 0; 583 rdataset->ttl = ncacherdataset->ttl; 584 rdataset->trust = trust; 585 rdataset->ncache.raw = remaining.base; 586 rdataset->ncache.iter_pos = NULL; 587 rdataset->ncache.iter_count = 0; 588 589 return ISC_R_SUCCESS; 590 } 591 592 isc_result_t 593 dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name, 594 dns_rdatatype_t covers, dns_rdataset_t *rdataset) { 595 dns_name_t tname; 596 dns_rdata_rrsig_t rrsig; 597 dns_rdata_t rdata = DNS_RDATA_INIT; 598 dns_rdataset_t rclone; 599 dns_rdatatype_t type; 600 dns_trust_t trust = dns_trust_none; 601 isc_buffer_t source; 602 isc_region_t remaining, sigregion; 603 isc_result_t result; 604 unsigned char *raw; 605 unsigned int count; 606 607 REQUIRE(ncacherdataset != NULL); 608 REQUIRE(ncacherdataset->type == 0); 609 REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); 610 REQUIRE(name != NULL); 611 REQUIRE(!dns_rdataset_isassociated(rdataset)); 612 613 dns_rdataset_init(&rclone); 614 dns_rdataset_clone(ncacherdataset, &rclone); 615 result = dns_rdataset_first(&rclone); 616 while (result == ISC_R_SUCCESS) { 617 dns_rdataset_current(&rclone, &rdata); 618 isc_buffer_init(&source, rdata.data, rdata.length); 619 isc_buffer_add(&source, rdata.length); 620 dns_name_init(&tname, NULL); 621 isc_buffer_remainingregion(&source, &remaining); 622 dns_name_fromregion(&tname, &remaining); 623 INSIST(remaining.length >= tname.length); 624 isc_buffer_forward(&source, tname.length); 625 isc_region_consume(&remaining, tname.length); 626 627 INSIST(remaining.length >= 2); 628 type = isc_buffer_getuint16(&source); 629 isc_region_consume(&remaining, 2); 630 631 if (type != dns_rdatatype_rrsig || 632 !dns_name_equal(&tname, name)) 633 { 634 result = dns_rdataset_next(&rclone); 635 dns_rdata_reset(&rdata); 636 continue; 637 } 638 639 INSIST(remaining.length >= 1); 640 trust = atomic_getuint8(&source); 641 INSIST(trust <= dns_trust_ultimate); 642 isc_region_consume(&remaining, 1); 643 644 raw = remaining.base; 645 count = raw[0] * 256 + raw[1]; 646 INSIST(count > 0); 647 raw += 2; 648 sigregion.length = raw[0] * 256 + raw[1]; 649 raw += 2; 650 sigregion.base = raw; 651 dns_rdata_reset(&rdata); 652 dns_rdata_fromregion(&rdata, rdataset->rdclass, 653 dns_rdatatype_rrsig, &sigregion); 654 (void)dns_rdata_tostruct(&rdata, &rrsig, NULL); 655 if (rrsig.covered == covers) { 656 isc_buffer_remainingregion(&source, &remaining); 657 break; 658 } 659 660 result = dns_rdataset_next(&rclone); 661 dns_rdata_reset(&rdata); 662 } 663 dns_rdataset_disassociate(&rclone); 664 if (result == ISC_R_NOMORE) { 665 return ISC_R_NOTFOUND; 666 } 667 if (result != ISC_R_SUCCESS) { 668 return result; 669 } 670 671 INSIST(remaining.length != 0); 672 673 rdataset->methods = &rdataset_methods; 674 rdataset->rdclass = ncacherdataset->rdclass; 675 rdataset->type = dns_rdatatype_rrsig; 676 rdataset->covers = covers; 677 rdataset->ttl = ncacherdataset->ttl; 678 rdataset->trust = trust; 679 rdataset->ncache.raw = remaining.base; 680 rdataset->ncache.iter_pos = NULL; 681 rdataset->ncache.iter_count = 0; 682 683 return ISC_R_SUCCESS; 684 } 685 686 void 687 dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found, 688 dns_rdataset_t *rdataset) { 689 dns_rdata_t rdata = DNS_RDATA_INIT; 690 dns_trust_t trust; 691 isc_region_t remaining, sigregion; 692 isc_buffer_t source; 693 dns_name_t tname; 694 dns_rdatatype_t type, covers; 695 unsigned int count; 696 dns_rdata_rrsig_t rrsig; 697 unsigned char *raw; 698 699 REQUIRE(ncacherdataset != NULL); 700 REQUIRE(ncacherdataset->type == 0); 701 REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); 702 REQUIRE(found != NULL); 703 REQUIRE(!dns_rdataset_isassociated(rdataset)); 704 705 dns_rdataset_current(ncacherdataset, &rdata); 706 isc_buffer_init(&source, rdata.data, rdata.length); 707 isc_buffer_add(&source, rdata.length); 708 709 dns_name_init(&tname, NULL); 710 isc_buffer_remainingregion(&source, &remaining); 711 dns_name_fromregion(found, &remaining); 712 INSIST(remaining.length >= found->length); 713 isc_buffer_forward(&source, found->length); 714 remaining.length -= found->length; 715 716 INSIST(remaining.length >= 5); 717 type = isc_buffer_getuint16(&source); 718 trust = atomic_getuint8(&source); 719 INSIST(trust <= dns_trust_ultimate); 720 isc_buffer_remainingregion(&source, &remaining); 721 722 covers = 0; 723 if (type == dns_rdatatype_rrsig) { 724 /* 725 * Extract covers from RRSIG. 726 */ 727 raw = remaining.base; 728 count = raw[0] * 256 + raw[1]; 729 INSIST(count > 0); 730 raw += 2; 731 sigregion.length = raw[0] * 256 + raw[1]; 732 raw += 2; 733 sigregion.base = raw; 734 dns_rdata_reset(&rdata); 735 dns_rdata_fromregion(&rdata, ncacherdataset->rdclass, type, 736 &sigregion); 737 (void)dns_rdata_tostruct(&rdata, &rrsig, NULL); 738 covers = rrsig.covered; 739 } 740 741 rdataset->methods = &rdataset_methods; 742 rdataset->rdclass = ncacherdataset->rdclass; 743 rdataset->type = type; 744 rdataset->covers = covers; 745 rdataset->ttl = ncacherdataset->ttl; 746 rdataset->trust = trust; 747 rdataset->ncache.raw = remaining.base; 748 rdataset->ncache.iter_pos = NULL; 749 rdataset->ncache.iter_count = 0; 750 } 751