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