1/* 2 * Copyright (C) 2004-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 <stdlib.h> 25 26#include <isc/buffer.h> 27#include <isc/mem.h> 28#include <isc/random.h> 29#include <isc/util.h> 30 31#include <dns/name.h> 32#include <dns/ncache.h> 33#include <dns/rdata.h> 34#include <dns/rdataset.h> 35#include <dns/compress.h> 36 37static const char *trustnames[] = { 38 "none", 39 "pending-additional", 40 "pending-answer", 41 "additional", 42 "glue", 43 "answer", 44 "authauthority", 45 "authanswer", 46 "secure", 47 "local" /* aka ultimate */ 48}; 49 50const char * 51dns_trust_totext(dns_trust_t trust) { 52 if (trust >= sizeof(trustnames)/sizeof(*trustnames)) 53 return ("bad"); 54 return (trustnames[trust]); 55} 56 57void 58dns_rdataset_init(dns_rdataset_t *rdataset) { 59 60 /* 61 * Make 'rdataset' a valid, disassociated rdataset. 62 */ 63 64 REQUIRE(rdataset != NULL); 65 66 rdataset->magic = DNS_RDATASET_MAGIC; 67 rdataset->methods = NULL; 68 ISC_LINK_INIT(rdataset, link); 69 rdataset->rdclass = 0; 70 rdataset->type = 0; 71 rdataset->ttl = 0; 72 rdataset->trust = 0; 73 rdataset->covers = 0; 74 rdataset->attributes = 0; 75 rdataset->count = ISC_UINT32_MAX; 76 rdataset->private1 = NULL; 77 rdataset->private2 = NULL; 78 rdataset->private3 = NULL; 79 rdataset->privateuint4 = 0; 80 rdataset->private5 = NULL; 81 rdataset->private6 = NULL; 82 rdataset->resign = 0; 83} 84 85void 86dns_rdataset_invalidate(dns_rdataset_t *rdataset) { 87 88 /* 89 * Invalidate 'rdataset'. 90 */ 91 92 REQUIRE(DNS_RDATASET_VALID(rdataset)); 93 REQUIRE(rdataset->methods == NULL); 94 95 rdataset->magic = 0; 96 ISC_LINK_INIT(rdataset, link); 97 rdataset->rdclass = 0; 98 rdataset->type = 0; 99 rdataset->ttl = 0; 100 rdataset->trust = 0; 101 rdataset->covers = 0; 102 rdataset->attributes = 0; 103 rdataset->count = ISC_UINT32_MAX; 104 rdataset->private1 = NULL; 105 rdataset->private2 = NULL; 106 rdataset->private3 = NULL; 107 rdataset->privateuint4 = 0; 108 rdataset->private5 = NULL; 109} 110 111void 112dns_rdataset_disassociate(dns_rdataset_t *rdataset) { 113 114 /* 115 * Disassociate 'rdataset' from its rdata, allowing it to be reused. 116 */ 117 118 REQUIRE(DNS_RDATASET_VALID(rdataset)); 119 REQUIRE(rdataset->methods != NULL); 120 121 (rdataset->methods->disassociate)(rdataset); 122 rdataset->methods = NULL; 123 ISC_LINK_INIT(rdataset, link); 124 rdataset->rdclass = 0; 125 rdataset->type = 0; 126 rdataset->ttl = 0; 127 rdataset->trust = 0; 128 rdataset->covers = 0; 129 rdataset->attributes = 0; 130 rdataset->count = ISC_UINT32_MAX; 131 rdataset->private1 = NULL; 132 rdataset->private2 = NULL; 133 rdataset->private3 = NULL; 134 rdataset->privateuint4 = 0; 135 rdataset->private5 = NULL; 136 rdataset->private6 = NULL; 137} 138 139isc_boolean_t 140dns_rdataset_isassociated(dns_rdataset_t *rdataset) { 141 /* 142 * Is 'rdataset' associated? 143 */ 144 145 REQUIRE(DNS_RDATASET_VALID(rdataset)); 146 147 if (rdataset->methods != NULL) 148 return (ISC_TRUE); 149 150 return (ISC_FALSE); 151} 152 153static void 154question_disassociate(dns_rdataset_t *rdataset) { 155 UNUSED(rdataset); 156} 157 158static isc_result_t 159question_cursor(dns_rdataset_t *rdataset) { 160 UNUSED(rdataset); 161 162 return (ISC_R_NOMORE); 163} 164 165static void 166question_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 167 /* 168 * This routine should never be called. 169 */ 170 UNUSED(rdataset); 171 UNUSED(rdata); 172 173 REQUIRE(0); 174} 175 176static void 177question_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 178 *target = *source; 179} 180 181static unsigned int 182question_count(dns_rdataset_t *rdataset) { 183 /* 184 * This routine should never be called. 185 */ 186 UNUSED(rdataset); 187 REQUIRE(0); 188 189 return (0); 190} 191 192static dns_rdatasetmethods_t question_methods = { 193 question_disassociate, 194 question_cursor, 195 question_cursor, 196 question_current, 197 question_clone, 198 question_count, 199 NULL, 200 NULL, 201 NULL, 202 NULL, 203 NULL, 204 NULL, 205 NULL, 206 NULL, 207 NULL 208}; 209 210void 211dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass, 212 dns_rdatatype_t type) 213{ 214 215 /* 216 * Make 'rdataset' a valid, associated, question rdataset, with a 217 * question class of 'rdclass' and type 'type'. 218 */ 219 220 REQUIRE(DNS_RDATASET_VALID(rdataset)); 221 REQUIRE(rdataset->methods == NULL); 222 223 rdataset->methods = &question_methods; 224 rdataset->rdclass = rdclass; 225 rdataset->type = type; 226 rdataset->attributes |= DNS_RDATASETATTR_QUESTION; 227} 228 229unsigned int 230dns_rdataset_count(dns_rdataset_t *rdataset) { 231 232 /* 233 * Return the number of records in 'rdataset'. 234 */ 235 236 REQUIRE(DNS_RDATASET_VALID(rdataset)); 237 REQUIRE(rdataset->methods != NULL); 238 239 return ((rdataset->methods->count)(rdataset)); 240} 241 242void 243dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 244 245 /* 246 * Make 'target' refer to the same rdataset as 'source'. 247 */ 248 249 REQUIRE(DNS_RDATASET_VALID(source)); 250 REQUIRE(source->methods != NULL); 251 REQUIRE(DNS_RDATASET_VALID(target)); 252 REQUIRE(target->methods == NULL); 253 254 (source->methods->clone)(source, target); 255} 256 257isc_result_t 258dns_rdataset_first(dns_rdataset_t *rdataset) { 259 260 /* 261 * Move the rdata cursor to the first rdata in the rdataset (if any). 262 */ 263 264 REQUIRE(DNS_RDATASET_VALID(rdataset)); 265 REQUIRE(rdataset->methods != NULL); 266 267 return ((rdataset->methods->first)(rdataset)); 268} 269 270isc_result_t 271dns_rdataset_next(dns_rdataset_t *rdataset) { 272 273 /* 274 * Move the rdata cursor to the next rdata in the rdataset (if any). 275 */ 276 277 REQUIRE(DNS_RDATASET_VALID(rdataset)); 278 REQUIRE(rdataset->methods != NULL); 279 280 return ((rdataset->methods->next)(rdataset)); 281} 282 283void 284dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 285 286 /* 287 * Make 'rdata' refer to the current rdata. 288 */ 289 290 REQUIRE(DNS_RDATASET_VALID(rdataset)); 291 REQUIRE(rdataset->methods != NULL); 292 293 (rdataset->methods->current)(rdataset, rdata); 294} 295 296#define MAX_SHUFFLE 32 297#define WANT_FIXED(r) (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0) 298#define WANT_RANDOM(r) (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0) 299 300struct towire_sort { 301 int key; 302 dns_rdata_t *rdata; 303}; 304 305static int 306towire_compare(const void *av, const void *bv) { 307 const struct towire_sort *a = (const struct towire_sort *) av; 308 const struct towire_sort *b = (const struct towire_sort *) bv; 309 return (a->key - b->key); 310} 311 312static isc_result_t 313towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, 314 dns_compress_t *cctx, isc_buffer_t *target, 315 dns_rdatasetorderfunc_t order, const void *order_arg, 316 isc_boolean_t partial, unsigned int options, 317 unsigned int *countp, void **state) 318{ 319 dns_rdata_t rdata = DNS_RDATA_INIT; 320 isc_region_t r; 321 isc_result_t result; 322 unsigned int i, count = 0, added, choice; 323 isc_buffer_t savedbuffer, rdlen, rrbuffer; 324 unsigned int headlen; 325 isc_boolean_t question = ISC_FALSE; 326 isc_boolean_t shuffle = ISC_FALSE; 327 dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE]; 328 struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE]; 329 330 UNUSED(state); 331 332 /* 333 * Convert 'rdataset' to wire format, compressing names as specified 334 * in cctx, and storing the result in 'target'. 335 */ 336 337 REQUIRE(DNS_RDATASET_VALID(rdataset)); 338 REQUIRE(countp != NULL); 339 REQUIRE((order == NULL) == (order_arg == NULL)); 340 REQUIRE(cctx != NULL && cctx->mctx != NULL); 341 342 if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) { 343 question = ISC_TRUE; 344 count = 1; 345 result = dns_rdataset_first(rdataset); 346 INSIST(result == ISC_R_NOMORE); 347 } else if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { 348 /* 349 * This is a negative caching rdataset. 350 */ 351 unsigned int ncache_opts = 0; 352 if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0) 353 ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC; 354 return (dns_ncache_towire(rdataset, cctx, target, ncache_opts, 355 countp)); 356 } else { 357 count = (rdataset->methods->count)(rdataset); 358 result = dns_rdataset_first(rdataset); 359 if (result == ISC_R_NOMORE) 360 return (ISC_R_SUCCESS); 361 if (result != ISC_R_SUCCESS) 362 return (result); 363 } 364 365 /* 366 * Do we want to shuffle this answer? 367 */ 368 if (!question && count > 1 && 369 (!WANT_FIXED(rdataset) || order != NULL) && 370 rdataset->type != dns_rdatatype_rrsig) 371 shuffle = ISC_TRUE; 372 373 if (shuffle && count > MAX_SHUFFLE) { 374 shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled)); 375 sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted)); 376 if (shuffled == NULL || sorted == NULL) 377 shuffle = ISC_FALSE; 378 } else { 379 shuffled = shuffled_fixed; 380 sorted = sorted_fixed; 381 } 382 383 if (shuffle) { 384 /* 385 * First we get handles to all of the rdata. 386 */ 387 i = 0; 388 do { 389 INSIST(i < count); 390 dns_rdata_init(&shuffled[i]); 391 dns_rdataset_current(rdataset, &shuffled[i]); 392 i++; 393 result = dns_rdataset_next(rdataset); 394 } while (result == ISC_R_SUCCESS); 395 if (result != ISC_R_NOMORE) 396 goto cleanup; 397 INSIST(i == count); 398 399 /* 400 * Now we shuffle. 401 */ 402 if (WANT_FIXED(rdataset)) { 403 /* 404 * 'Fixed' order. 405 */ 406 INSIST(order != NULL); 407 for (i = 0; i < count; i++) { 408 sorted[i].key = (*order)(&shuffled[i], 409 order_arg); 410 sorted[i].rdata = &shuffled[i]; 411 } 412 } else if (WANT_RANDOM(rdataset)) { 413 /* 414 * 'Random' order. 415 */ 416 for (i = 0; i < count; i++) { 417 dns_rdata_t rdata; 418 isc_uint32_t val; 419 420 isc_random_get(&val); 421 choice = i + (val % (count - i)); 422 rdata = shuffled[i]; 423 shuffled[i] = shuffled[choice]; 424 shuffled[choice] = rdata; 425 if (order != NULL) 426 sorted[i].key = (*order)(&shuffled[i], 427 order_arg); 428 else 429 sorted[i].key = 0; /* Unused */ 430 sorted[i].rdata = &shuffled[i]; 431 } 432 } else { 433 /* 434 * "Cyclic" order. 435 */ 436 isc_uint32_t val; 437 unsigned int j; 438 439 val = rdataset->count; 440 if (val == ISC_UINT32_MAX) 441 isc_random_get(&val); 442 j = val % count; 443 for (i = 0; i < count; i++) { 444 if (order != NULL) 445 sorted[i].key = (*order)(&shuffled[j], 446 order_arg); 447 else 448 sorted[i].key = 0; /* Unused */ 449 sorted[i].rdata = &shuffled[j]; 450 j++; 451 if (j == count) 452 j = 0; /* Wrap around. */ 453 } 454 } 455 456 /* 457 * Sorted order. 458 */ 459 if (order != NULL) 460 qsort(sorted, count, sizeof(sorted[0]), 461 towire_compare); 462 } 463 464 savedbuffer = *target; 465 i = 0; 466 added = 0; 467 468 do { 469 /* 470 * Copy out the name, type, class, ttl. 471 */ 472 473 rrbuffer = *target; 474 dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); 475 result = dns_name_towire(owner_name, cctx, target); 476 if (result != ISC_R_SUCCESS) 477 goto rollback; 478 headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t); 479 if (!question) 480 headlen += sizeof(dns_ttl_t) 481 + 2; /* XXX 2 for rdata len */ 482 isc_buffer_availableregion(target, &r); 483 if (r.length < headlen) { 484 result = ISC_R_NOSPACE; 485 goto rollback; 486 } 487 isc_buffer_putuint16(target, rdataset->type); 488 isc_buffer_putuint16(target, rdataset->rdclass); 489 if (!question) { 490 isc_buffer_putuint32(target, rdataset->ttl); 491 492 /* 493 * Save space for rdlen. 494 */ 495 rdlen = *target; 496 isc_buffer_add(target, 2); 497 498 /* 499 * Copy out the rdata 500 */ 501 if (shuffle) 502 rdata = *(sorted[i].rdata); 503 else { 504 dns_rdata_reset(&rdata); 505 dns_rdataset_current(rdataset, &rdata); 506 } 507 result = dns_rdata_towire(&rdata, cctx, target); 508 if (result != ISC_R_SUCCESS) 509 goto rollback; 510 INSIST((target->used >= rdlen.used + 2) && 511 (target->used - rdlen.used - 2 < 65536)); 512 isc_buffer_putuint16(&rdlen, 513 (isc_uint16_t)(target->used - 514 rdlen.used - 2)); 515 added++; 516 } 517 518 if (shuffle) { 519 i++; 520 if (i == count) 521 result = ISC_R_NOMORE; 522 else 523 result = ISC_R_SUCCESS; 524 } else { 525 result = dns_rdataset_next(rdataset); 526 } 527 } while (result == ISC_R_SUCCESS); 528 529 if (result != ISC_R_NOMORE) 530 goto rollback; 531 532 *countp += count; 533 534 result = ISC_R_SUCCESS; 535 goto cleanup; 536 537 rollback: 538 if (partial && result == ISC_R_NOSPACE) { 539 INSIST(rrbuffer.used < 65536); 540 dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used); 541 *countp += added; 542 *target = rrbuffer; 543 goto cleanup; 544 } 545 INSIST(savedbuffer.used < 65536); 546 dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used); 547 *countp = 0; 548 *target = savedbuffer; 549 550 cleanup: 551 if (sorted != NULL && sorted != sorted_fixed) 552 isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted)); 553 if (shuffled != NULL && shuffled != shuffled_fixed) 554 isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled)); 555 return (result); 556} 557 558isc_result_t 559dns_rdataset_towiresorted(dns_rdataset_t *rdataset, 560 const dns_name_t *owner_name, 561 dns_compress_t *cctx, 562 isc_buffer_t *target, 563 dns_rdatasetorderfunc_t order, 564 const void *order_arg, 565 unsigned int options, 566 unsigned int *countp) 567{ 568 return (towiresorted(rdataset, owner_name, cctx, target, 569 order, order_arg, ISC_FALSE, options, 570 countp, NULL)); 571} 572 573isc_result_t 574dns_rdataset_towirepartial(dns_rdataset_t *rdataset, 575 const dns_name_t *owner_name, 576 dns_compress_t *cctx, 577 isc_buffer_t *target, 578 dns_rdatasetorderfunc_t order, 579 const void *order_arg, 580 unsigned int options, 581 unsigned int *countp, 582 void **state) 583{ 584 REQUIRE(state == NULL); /* XXX remove when implemented */ 585 return (towiresorted(rdataset, owner_name, cctx, target, 586 order, order_arg, ISC_TRUE, options, 587 countp, state)); 588} 589 590isc_result_t 591dns_rdataset_towire(dns_rdataset_t *rdataset, 592 dns_name_t *owner_name, 593 dns_compress_t *cctx, 594 isc_buffer_t *target, 595 unsigned int options, 596 unsigned int *countp) 597{ 598 return (towiresorted(rdataset, owner_name, cctx, target, 599 NULL, NULL, ISC_FALSE, options, countp, NULL)); 600} 601 602isc_result_t 603dns_rdataset_additionaldata(dns_rdataset_t *rdataset, 604 dns_additionaldatafunc_t add, void *arg) 605{ 606 dns_rdata_t rdata = DNS_RDATA_INIT; 607 isc_result_t result; 608 609 /* 610 * For each rdata in rdataset, call 'add' for each name and type in the 611 * rdata which is subject to additional section processing. 612 */ 613 614 REQUIRE(DNS_RDATASET_VALID(rdataset)); 615 REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0); 616 617 result = dns_rdataset_first(rdataset); 618 if (result != ISC_R_SUCCESS) 619 return (result); 620 621 do { 622 dns_rdataset_current(rdataset, &rdata); 623 result = dns_rdata_additionaldata(&rdata, add, arg); 624 if (result == ISC_R_SUCCESS) 625 result = dns_rdataset_next(rdataset); 626 dns_rdata_reset(&rdata); 627 } while (result == ISC_R_SUCCESS); 628 629 if (result != ISC_R_NOMORE) 630 return (result); 631 632 return (ISC_R_SUCCESS); 633} 634 635isc_result_t 636dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) { 637 638 REQUIRE(DNS_RDATASET_VALID(rdataset)); 639 REQUIRE(rdataset->methods != NULL); 640 if (rdataset->methods->addnoqname == NULL) 641 return (ISC_R_NOTIMPLEMENTED); 642 return((rdataset->methods->addnoqname)(rdataset, name)); 643} 644 645isc_result_t 646dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name, 647 dns_rdataset_t *neg, dns_rdataset_t *negsig) 648{ 649 REQUIRE(DNS_RDATASET_VALID(rdataset)); 650 REQUIRE(rdataset->methods != NULL); 651 652 if (rdataset->methods->getnoqname == NULL) 653 return (ISC_R_NOTIMPLEMENTED); 654 return((rdataset->methods->getnoqname)(rdataset, name, neg, negsig)); 655} 656 657isc_result_t 658dns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) { 659 660 REQUIRE(DNS_RDATASET_VALID(rdataset)); 661 REQUIRE(rdataset->methods != NULL); 662 if (rdataset->methods->addclosest == NULL) 663 return (ISC_R_NOTIMPLEMENTED); 664 return((rdataset->methods->addclosest)(rdataset, name)); 665} 666 667isc_result_t 668dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name, 669 dns_rdataset_t *neg, dns_rdataset_t *negsig) 670{ 671 REQUIRE(DNS_RDATASET_VALID(rdataset)); 672 REQUIRE(rdataset->methods != NULL); 673 674 if (rdataset->methods->getclosest == NULL) 675 return (ISC_R_NOTIMPLEMENTED); 676 return((rdataset->methods->getclosest)(rdataset, name, neg, negsig)); 677} 678 679/* 680 * Additional cache stuff 681 */ 682isc_result_t 683dns_rdataset_getadditional(dns_rdataset_t *rdataset, 684 dns_rdatasetadditional_t type, 685 dns_rdatatype_t qtype, 686 dns_acache_t *acache, 687 dns_zone_t **zonep, 688 dns_db_t **dbp, 689 dns_dbversion_t **versionp, 690 dns_dbnode_t **nodep, 691 dns_name_t *fname, 692 dns_message_t *msg, 693 isc_stdtime_t now) 694{ 695 REQUIRE(DNS_RDATASET_VALID(rdataset)); 696 REQUIRE(rdataset->methods != NULL); 697 REQUIRE(zonep == NULL || *zonep == NULL); 698 REQUIRE(dbp != NULL && *dbp == NULL); 699 REQUIRE(versionp != NULL && *versionp == NULL); 700 REQUIRE(nodep != NULL && *nodep == NULL); 701 REQUIRE(fname != NULL); 702 REQUIRE(msg != NULL); 703 704 if (acache != NULL && rdataset->methods->getadditional != NULL) { 705 return ((rdataset->methods->getadditional)(rdataset, type, 706 qtype, acache, 707 zonep, dbp, 708 versionp, nodep, 709 fname, msg, now)); 710 } 711 712 return (ISC_R_FAILURE); 713} 714 715isc_result_t 716dns_rdataset_setadditional(dns_rdataset_t *rdataset, 717 dns_rdatasetadditional_t type, 718 dns_rdatatype_t qtype, 719 dns_acache_t *acache, 720 dns_zone_t *zone, 721 dns_db_t *db, 722 dns_dbversion_t *version, 723 dns_dbnode_t *node, 724 dns_name_t *fname) 725{ 726 REQUIRE(DNS_RDATASET_VALID(rdataset)); 727 REQUIRE(rdataset->methods != NULL); 728 729 if (acache != NULL && rdataset->methods->setadditional != NULL) { 730 return ((rdataset->methods->setadditional)(rdataset, type, 731 qtype, acache, zone, 732 db, version, 733 node, fname)); 734 } 735 736 return (ISC_R_FAILURE); 737} 738 739isc_result_t 740dns_rdataset_putadditional(dns_acache_t *acache, 741 dns_rdataset_t *rdataset, 742 dns_rdatasetadditional_t type, 743 dns_rdatatype_t qtype) 744{ 745 REQUIRE(DNS_RDATASET_VALID(rdataset)); 746 REQUIRE(rdataset->methods != NULL); 747 748 if (acache != NULL && rdataset->methods->putadditional != NULL) { 749 return ((rdataset->methods->putadditional)(acache, rdataset, 750 type, qtype)); 751 } 752 753 return (ISC_R_FAILURE); 754} 755 756void 757dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { 758 REQUIRE(DNS_RDATASET_VALID(rdataset)); 759 REQUIRE(rdataset->methods != NULL); 760 761 if (rdataset->methods->settrust != NULL) 762 (rdataset->methods->settrust)(rdataset, trust); 763 else 764 rdataset->trust = trust; 765} 766 767void 768dns_rdataset_expire(dns_rdataset_t *rdataset) { 769 REQUIRE(DNS_RDATASET_VALID(rdataset)); 770 REQUIRE(rdataset->methods != NULL); 771 772 if (rdataset->methods->expire != NULL) 773 (rdataset->methods->expire)(rdataset); 774} 775