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