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