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