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