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