1/* 2 * Copyright (C) 2009-2012 Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/* $Id$ */ 18 19#include "config.h" 20 21#include <isc/result.h> 22#include <isc/util.h> 23#include <isc/mutex.h> 24#include <isc/mem.h> 25 26#include <dns/db.h> 27#include <dns/ecdb.h> 28#include <dns/rdata.h> 29#include <dns/rdataset.h> 30#include <dns/rdatasetiter.h> 31#include <dns/rdataslab.h> 32 33#define ECDB_MAGIC ISC_MAGIC('E', 'C', 'D', 'B') 34#define VALID_ECDB(db) ((db) != NULL && \ 35 (db)->common.impmagic == ECDB_MAGIC) 36 37#define ECDBNODE_MAGIC ISC_MAGIC('E', 'C', 'D', 'N') 38#define VALID_ECDBNODE(ecdbn) ISC_MAGIC_VALID(ecdbn, ECDBNODE_MAGIC) 39 40/*% 41 * The 'ephemeral' cache DB (ecdb) implementation. An ecdb just provides 42 * temporary storage for ongoing name resolution with the common DB interfaces. 43 * It actually doesn't cache anything. The implementation expects any stored 44 * data is released within a short period, and does not care about the 45 * scalability in terms of the number of nodes. 46 */ 47 48typedef struct dns_ecdb { 49 /* Unlocked */ 50 dns_db_t common; 51 isc_mutex_t lock; 52 53 /* Locked */ 54 unsigned int references; 55 ISC_LIST(struct dns_ecdbnode) nodes; 56} dns_ecdb_t; 57 58typedef struct dns_ecdbnode { 59 /* Unlocked */ 60 unsigned int magic; 61 isc_mutex_t lock; 62 dns_ecdb_t *ecdb; 63 dns_name_t name; 64 ISC_LINK(struct dns_ecdbnode) link; 65 66 /* Locked */ 67 ISC_LIST(struct rdatasetheader) rdatasets; 68 unsigned int references; 69} dns_ecdbnode_t; 70 71typedef struct rdatasetheader { 72 dns_rdatatype_t type; 73 dns_ttl_t ttl; 74 dns_trust_t trust; 75 dns_rdatatype_t covers; 76 unsigned int attributes; 77 78 ISC_LINK(struct rdatasetheader) link; 79} rdatasetheader_t; 80 81/* Copied from rbtdb.c */ 82#define RDATASET_ATTR_NXDOMAIN 0x0010 83#define NXDOMAIN(header) \ 84 (((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0) 85 86static isc_result_t dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, 87 dns_dbtype_t type, 88 dns_rdataclass_t rdclass, 89 unsigned int argc, char *argv[], 90 void *driverarg, dns_db_t **dbp); 91 92static void rdataset_disassociate(dns_rdataset_t *rdataset); 93static isc_result_t rdataset_first(dns_rdataset_t *rdataset); 94static isc_result_t rdataset_next(dns_rdataset_t *rdataset); 95static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata); 96static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target); 97static unsigned int rdataset_count(dns_rdataset_t *rdataset); 98static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust); 99 100static dns_rdatasetmethods_t rdataset_methods = { 101 rdataset_disassociate, 102 rdataset_first, 103 rdataset_next, 104 rdataset_current, 105 rdataset_clone, 106 rdataset_count, 107 NULL, /* addnoqname */ 108 NULL, /* getnoqname */ 109 NULL, /* addclosest */ 110 NULL, /* getclosest */ 111 NULL, /* getadditional */ 112 NULL, /* setadditional */ 113 NULL, /* putadditional */ 114 rdataset_settrust, /* settrust */ 115 NULL /* expire */ 116}; 117 118typedef struct ecdb_rdatasetiter { 119 dns_rdatasetiter_t common; 120 rdatasetheader_t *current; 121} ecdb_rdatasetiter_t; 122 123static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp); 124static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator); 125static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator); 126static void rdatasetiter_current(dns_rdatasetiter_t *iterator, 127 dns_rdataset_t *rdataset); 128 129static dns_rdatasetitermethods_t rdatasetiter_methods = { 130 rdatasetiter_destroy, 131 rdatasetiter_first, 132 rdatasetiter_next, 133 rdatasetiter_current 134}; 135 136isc_result_t 137dns_ecdb_register(isc_mem_t *mctx, dns_dbimplementation_t **dbimp) { 138 REQUIRE(mctx != NULL); 139 REQUIRE(dbimp != NULL && *dbimp == NULL); 140 141 return (dns_db_register("ecdb", dns_ecdb_create, NULL, mctx, dbimp)); 142} 143 144void 145dns_ecdb_unregister(dns_dbimplementation_t **dbimp) { 146 REQUIRE(dbimp != NULL && *dbimp != NULL); 147 148 dns_db_unregister(dbimp); 149} 150 151/*% 152 * DB routines 153 */ 154 155static void 156attach(dns_db_t *source, dns_db_t **targetp) { 157 dns_ecdb_t *ecdb = (dns_ecdb_t *)source; 158 159 REQUIRE(VALID_ECDB(ecdb)); 160 REQUIRE(targetp != NULL && *targetp == NULL); 161 162 LOCK(&ecdb->lock); 163 ecdb->references++; 164 UNLOCK(&ecdb->lock); 165 166 *targetp = source; 167} 168 169static void 170destroy_ecdb(dns_ecdb_t **ecdbp) { 171 dns_ecdb_t *ecdb = *ecdbp; 172 isc_mem_t *mctx = ecdb->common.mctx; 173 174 if (dns_name_dynamic(&ecdb->common.origin)) 175 dns_name_free(&ecdb->common.origin, mctx); 176 177 DESTROYLOCK(&ecdb->lock); 178 179 ecdb->common.impmagic = 0; 180 ecdb->common.magic = 0; 181 182 isc_mem_putanddetach(&mctx, ecdb, sizeof(*ecdb)); 183 184 *ecdbp = NULL; 185} 186 187static void 188detach(dns_db_t **dbp) { 189 dns_ecdb_t *ecdb; 190 isc_boolean_t need_destroy = ISC_FALSE; 191 192 REQUIRE(dbp != NULL); 193 ecdb = (dns_ecdb_t *)*dbp; 194 REQUIRE(VALID_ECDB(ecdb)); 195 196 LOCK(&ecdb->lock); 197 ecdb->references--; 198 if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes)) 199 need_destroy = ISC_TRUE; 200 UNLOCK(&ecdb->lock); 201 202 if (need_destroy) 203 destroy_ecdb(&ecdb); 204 205 *dbp = NULL; 206} 207 208static void 209attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { 210 dns_ecdb_t *ecdb = (dns_ecdb_t *)db; 211 dns_ecdbnode_t *node = (dns_ecdbnode_t *)source; 212 213 REQUIRE(VALID_ECDB(ecdb)); 214 REQUIRE(VALID_ECDBNODE(node)); 215 REQUIRE(targetp != NULL && *targetp == NULL); 216 217 LOCK(&node->lock); 218 INSIST(node->references > 0); 219 node->references++; 220 INSIST(node->references != 0); /* Catch overflow. */ 221 UNLOCK(&node->lock); 222 223 *targetp = node; 224} 225 226static void 227destroynode(dns_ecdbnode_t *node) { 228 isc_mem_t *mctx; 229 dns_ecdb_t *ecdb = node->ecdb; 230 isc_boolean_t need_destroydb = ISC_FALSE; 231 rdatasetheader_t *header; 232 233 mctx = ecdb->common.mctx; 234 235 LOCK(&ecdb->lock); 236 ISC_LIST_UNLINK(ecdb->nodes, node, link); 237 if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes)) 238 need_destroydb = ISC_TRUE; 239 UNLOCK(&ecdb->lock); 240 241 dns_name_free(&node->name, mctx); 242 243 while ((header = ISC_LIST_HEAD(node->rdatasets)) != NULL) { 244 unsigned int headersize; 245 246 ISC_LIST_UNLINK(node->rdatasets, header, link); 247 headersize = 248 dns_rdataslab_size((unsigned char *)header, 249 sizeof(*header)); 250 isc_mem_put(mctx, header, headersize); 251 } 252 253 DESTROYLOCK(&node->lock); 254 255 node->magic = 0; 256 isc_mem_put(mctx, node, sizeof(*node)); 257 258 if (need_destroydb) 259 destroy_ecdb(&ecdb); 260} 261 262static void 263detachnode(dns_db_t *db, dns_dbnode_t **nodep) { 264 dns_ecdb_t *ecdb = (dns_ecdb_t *)db; 265 dns_ecdbnode_t *node; 266 isc_boolean_t need_destroy = ISC_FALSE; 267 268 REQUIRE(VALID_ECDB(ecdb)); 269 REQUIRE(nodep != NULL); 270 node = (dns_ecdbnode_t *)*nodep; 271 REQUIRE(VALID_ECDBNODE(node)); 272 273 UNUSED(ecdb); /* in case REQUIRE() is empty */ 274 275 LOCK(&node->lock); 276 INSIST(node->references > 0); 277 node->references--; 278 if (node->references == 0) 279 need_destroy = ISC_TRUE; 280 UNLOCK(&node->lock); 281 282 if (need_destroy) 283 destroynode(node); 284 285 *nodep = NULL; 286} 287 288static isc_result_t 289find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, 290 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 291 dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, 292 dns_rdataset_t *sigrdataset) 293{ 294 dns_ecdb_t *ecdb = (dns_ecdb_t *)db; 295 296 REQUIRE(VALID_ECDB(ecdb)); 297 298 UNUSED(name); 299 UNUSED(version); 300 UNUSED(type); 301 UNUSED(options); 302 UNUSED(now); 303 UNUSED(nodep); 304 UNUSED(foundname); 305 UNUSED(rdataset); 306 UNUSED(sigrdataset); 307 308 return (ISC_R_NOTFOUND); 309} 310 311static isc_result_t 312findzonecut(dns_db_t *db, dns_name_t *name, 313 unsigned int options, isc_stdtime_t now, 314 dns_dbnode_t **nodep, dns_name_t *foundname, 315 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 316{ 317 dns_ecdb_t *ecdb = (dns_ecdb_t *)db; 318 319 REQUIRE(VALID_ECDB(ecdb)); 320 321 UNUSED(name); 322 UNUSED(options); 323 UNUSED(now); 324 UNUSED(nodep); 325 UNUSED(foundname); 326 UNUSED(rdataset); 327 UNUSED(sigrdataset); 328 329 return (ISC_R_NOTFOUND); 330} 331 332static isc_result_t 333findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, 334 dns_dbnode_t **nodep) 335{ 336 dns_ecdb_t *ecdb = (dns_ecdb_t *)db; 337 isc_mem_t *mctx; 338 dns_ecdbnode_t *node; 339 isc_result_t result; 340 341 REQUIRE(VALID_ECDB(ecdb)); 342 REQUIRE(nodep != NULL && *nodep == NULL); 343 344 UNUSED(name); 345 346 if (create != ISC_TRUE) { 347 /* an 'ephemeral' node is never reused. */ 348 return (ISC_R_NOTFOUND); 349 } 350 351 mctx = ecdb->common.mctx; 352 node = isc_mem_get(mctx, sizeof(*node)); 353 if (node == NULL) 354 return (ISC_R_NOMEMORY); 355 356 result = isc_mutex_init(&node->lock); 357 if (result != ISC_R_SUCCESS) { 358 UNEXPECTED_ERROR(__FILE__, __LINE__, 359 "isc_mutex_init() failed: %s", 360 isc_result_totext(result)); 361 isc_mem_put(mctx, node, sizeof(*node)); 362 return (ISC_R_UNEXPECTED); 363 } 364 365 dns_name_init(&node->name, NULL); 366 result = dns_name_dup(name, mctx, &node->name); 367 if (result != ISC_R_SUCCESS) { 368 DESTROYLOCK(&node->lock); 369 isc_mem_put(mctx, node, sizeof(*node)); 370 return (result); 371 } 372 node->ecdb= ecdb; 373 node->references = 1; 374 ISC_LIST_INIT(node->rdatasets); 375 376 ISC_LINK_INIT(node, link); 377 378 LOCK(&ecdb->lock); 379 ISC_LIST_APPEND(ecdb->nodes, node, link); 380 UNLOCK(&ecdb->lock); 381 382 node->magic = ECDBNODE_MAGIC; 383 384 *nodep = node; 385 386 return (ISC_R_SUCCESS); 387} 388 389static void 390bind_rdataset(dns_ecdb_t *ecdb, dns_ecdbnode_t *node, 391 rdatasetheader_t *header, dns_rdataset_t *rdataset) 392{ 393 unsigned char *raw; 394 395 /* 396 * Caller must be holding the node lock. 397 */ 398 399 REQUIRE(!dns_rdataset_isassociated(rdataset)); 400 401 rdataset->methods = &rdataset_methods; 402 rdataset->rdclass = ecdb->common.rdclass; 403 rdataset->type = header->type; 404 rdataset->covers = header->covers; 405 rdataset->ttl = header->ttl; 406 rdataset->trust = header->trust; 407 if (NXDOMAIN(header)) 408 rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN; 409 410 rdataset->private1 = ecdb; 411 rdataset->private2 = node; 412 raw = (unsigned char *)header + sizeof(*header); 413 rdataset->private3 = raw; 414 rdataset->count = 0; 415 416 /* 417 * Reset iterator state. 418 */ 419 rdataset->privateuint4 = 0; 420 rdataset->private5 = NULL; 421 422 INSIST(node->references > 0); 423 node->references++; 424} 425 426static isc_result_t 427addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 428 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, 429 dns_rdataset_t *addedrdataset) 430{ 431 dns_ecdb_t *ecdb = (dns_ecdb_t *)db; 432 isc_region_t r; 433 isc_result_t result = ISC_R_SUCCESS; 434 isc_mem_t *mctx; 435 dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node; 436 rdatasetheader_t *header; 437 438 REQUIRE(VALID_ECDB(ecdb)); 439 REQUIRE(VALID_ECDBNODE(ecdbnode)); 440 441 UNUSED(version); 442 UNUSED(now); 443 UNUSED(options); 444 445 mctx = ecdb->common.mctx; 446 447 LOCK(&ecdbnode->lock); 448 449 /* 450 * Sanity check: this implementation does not allow overriding an 451 * existing rdataset of the same type. 452 */ 453 for (header = ISC_LIST_HEAD(ecdbnode->rdatasets); header != NULL; 454 header = ISC_LIST_NEXT(header, link)) { 455 INSIST(header->type != rdataset->type || 456 header->covers != rdataset->covers); 457 } 458 459 result = dns_rdataslab_fromrdataset(rdataset, mctx, 460 &r, sizeof(rdatasetheader_t)); 461 if (result != ISC_R_SUCCESS) 462 goto unlock; 463 464 header = (rdatasetheader_t *)r.base; 465 header->type = rdataset->type; 466 header->ttl = rdataset->ttl; 467 header->trust = rdataset->trust; 468 header->covers = rdataset->covers; 469 header->attributes = 0; 470 if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) 471 header->attributes |= RDATASET_ATTR_NXDOMAIN; 472 ISC_LINK_INIT(header, link); 473 ISC_LIST_APPEND(ecdbnode->rdatasets, header, link); 474 475 if (addedrdataset == NULL) 476 goto unlock; 477 478 bind_rdataset(ecdb, ecdbnode, header, addedrdataset); 479 480 unlock: 481 UNLOCK(&ecdbnode->lock); 482 483 return (result); 484} 485 486static isc_result_t 487deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 488 dns_rdatatype_t type, dns_rdatatype_t covers) 489{ 490 UNUSED(db); 491 UNUSED(node); 492 UNUSED(version); 493 UNUSED(type); 494 UNUSED(covers); 495 496 return (ISC_R_NOTIMPLEMENTED); 497} 498 499static isc_result_t 500createiterator(dns_db_t *db, unsigned int options, 501 dns_dbiterator_t **iteratorp) 502{ 503 UNUSED(db); 504 UNUSED(options); 505 UNUSED(iteratorp); 506 507 return (ISC_R_NOTIMPLEMENTED); 508} 509 510static isc_result_t 511allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 512 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) 513{ 514 dns_ecdb_t *ecdb = (dns_ecdb_t *)db; 515 dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node; 516 isc_mem_t *mctx; 517 ecdb_rdatasetiter_t *iterator; 518 519 REQUIRE(VALID_ECDB(ecdb)); 520 REQUIRE(VALID_ECDBNODE(ecdbnode)); 521 522 mctx = ecdb->common.mctx; 523 524 iterator = isc_mem_get(mctx, sizeof(ecdb_rdatasetiter_t)); 525 if (iterator == NULL) 526 return (ISC_R_NOMEMORY); 527 528 iterator->common.magic = DNS_RDATASETITER_MAGIC; 529 iterator->common.methods = &rdatasetiter_methods; 530 iterator->common.db = db; 531 iterator->common.node = NULL; 532 attachnode(db, node, &iterator->common.node); 533 iterator->common.version = version; 534 iterator->common.now = now; 535 536 *iteratorp = (dns_rdatasetiter_t *)iterator; 537 538 return (ISC_R_SUCCESS); 539} 540 541static dns_dbmethods_t ecdb_methods = { 542 attach, 543 detach, 544 NULL, /* beginload */ 545 NULL, /* endload */ 546 NULL, /* dump */ 547 NULL, /* currentversion */ 548 NULL, /* newversion */ 549 NULL, /* attachversion */ 550 NULL, /* closeversion */ 551 findnode, 552 find, 553 findzonecut, 554 attachnode, 555 detachnode, 556 NULL, /* expirenode */ 557 NULL, /* printnode */ 558 createiterator, /* createiterator */ 559 NULL, /* findrdataset */ 560 allrdatasets, 561 addrdataset, 562 NULL, /* subtractrdataset */ 563 deleterdataset, 564 NULL, /* issecure */ 565 NULL, /* nodecount */ 566 NULL, /* ispersistent */ 567 NULL, /* overmem */ 568 NULL, /* settask */ 569 NULL, /* getoriginnode */ 570 NULL, /* transfernode */ 571 NULL, /* getnsec3parameters */ 572 NULL, /* findnsec3node */ 573 NULL, /* setsigningtime */ 574 NULL, /* getsigningtime */ 575 NULL, /* resigned */ 576 NULL, /* isdnssec */ 577 NULL, /* getrrsetstats */ 578 NULL, /* rpz_enabled */ 579 NULL /* rpz_findips */ 580}; 581 582static isc_result_t 583dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type, 584 dns_rdataclass_t rdclass, unsigned int argc, char *argv[], 585 void *driverarg, dns_db_t **dbp) 586{ 587 dns_ecdb_t *ecdb; 588 isc_result_t result; 589 590 REQUIRE(mctx != NULL); 591 REQUIRE(origin == dns_rootname); 592 REQUIRE(type == dns_dbtype_cache); 593 REQUIRE(dbp != NULL && *dbp == NULL); 594 595 UNUSED(argc); 596 UNUSED(argv); 597 UNUSED(driverarg); 598 599 ecdb = isc_mem_get(mctx, sizeof(*ecdb)); 600 if (ecdb == NULL) 601 return (ISC_R_NOMEMORY); 602 603 ecdb->common.attributes = DNS_DBATTR_CACHE; 604 ecdb->common.rdclass = rdclass; 605 ecdb->common.methods = &ecdb_methods; 606 dns_name_init(&ecdb->common.origin, NULL); 607 result = dns_name_dupwithoffsets(origin, mctx, &ecdb->common.origin); 608 if (result != ISC_R_SUCCESS) { 609 isc_mem_put(mctx, ecdb, sizeof(*ecdb)); 610 return (result); 611 } 612 613 result = isc_mutex_init(&ecdb->lock); 614 if (result != ISC_R_SUCCESS) { 615 UNEXPECTED_ERROR(__FILE__, __LINE__, 616 "isc_mutex_init() failed: %s", 617 isc_result_totext(result)); 618 if (dns_name_dynamic(&ecdb->common.origin)) 619 dns_name_free(&ecdb->common.origin, mctx); 620 isc_mem_put(mctx, ecdb, sizeof(*ecdb)); 621 return (ISC_R_UNEXPECTED); 622 } 623 624 ecdb->references = 1; 625 ISC_LIST_INIT(ecdb->nodes); 626 627 ecdb->common.mctx = NULL; 628 isc_mem_attach(mctx, &ecdb->common.mctx); 629 ecdb->common.impmagic = ECDB_MAGIC; 630 ecdb->common.magic = DNS_DB_MAGIC; 631 632 *dbp = (dns_db_t *)ecdb; 633 634 return (ISC_R_SUCCESS); 635} 636 637/*% 638 * Rdataset Methods 639 */ 640 641static void 642rdataset_disassociate(dns_rdataset_t *rdataset) { 643 dns_db_t *db = rdataset->private1; 644 dns_dbnode_t *node = rdataset->private2; 645 646 dns_db_detachnode(db, &node); 647} 648 649static isc_result_t 650rdataset_first(dns_rdataset_t *rdataset) { 651 unsigned char *raw = rdataset->private3; 652 unsigned int count; 653 654 count = raw[0] * 256 + raw[1]; 655 if (count == 0) { 656 rdataset->private5 = NULL; 657 return (ISC_R_NOMORE); 658 } 659#if DNS_RDATASET_FIXED 660 raw += 2 + (4 * count); 661#else 662 raw += 2; 663#endif 664 /* 665 * The privateuint4 field is the number of rdata beyond the cursor 666 * position, so we decrement the total count by one before storing 667 * it. 668 */ 669 count--; 670 rdataset->privateuint4 = count; 671 rdataset->private5 = raw; 672 673 return (ISC_R_SUCCESS); 674} 675 676static isc_result_t 677rdataset_next(dns_rdataset_t *rdataset) { 678 unsigned int count; 679 unsigned int length; 680 unsigned char *raw; 681 682 count = rdataset->privateuint4; 683 if (count == 0) 684 return (ISC_R_NOMORE); 685 count--; 686 rdataset->privateuint4 = count; 687 raw = rdataset->private5; 688 length = raw[0] * 256 + raw[1]; 689#if DNS_RDATASET_FIXED 690 raw += length + 4; 691#else 692 raw += length + 2; 693#endif 694 rdataset->private5 = raw; 695 696 return (ISC_R_SUCCESS); 697} 698 699static void 700rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 701 unsigned char *raw = rdataset->private5; 702 isc_region_t r; 703 unsigned int length; 704 unsigned int flags = 0; 705 706 REQUIRE(raw != NULL); 707 708 length = raw[0] * 256 + raw[1]; 709#if DNS_RDATASET_FIXED 710 raw += 4; 711#else 712 raw += 2; 713#endif 714 if (rdataset->type == dns_rdatatype_rrsig) { 715 if (*raw & DNS_RDATASLAB_OFFLINE) 716 flags |= DNS_RDATA_OFFLINE; 717 length--; 718 raw++; 719 } 720 r.length = length; 721 r.base = raw; 722 dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r); 723 rdata->flags |= flags; 724} 725 726static void 727rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 728 dns_db_t *db = source->private1; 729 dns_dbnode_t *node = source->private2; 730 dns_dbnode_t *cloned_node = NULL; 731 732 attachnode(db, node, &cloned_node); 733 *target = *source; 734 735 /* 736 * Reset iterator state. 737 */ 738 target->privateuint4 = 0; 739 target->private5 = NULL; 740} 741 742static unsigned int 743rdataset_count(dns_rdataset_t *rdataset) { 744 unsigned char *raw = rdataset->private3; 745 unsigned int count; 746 747 count = raw[0] * 256 + raw[1]; 748 749 return (count); 750} 751 752static void 753rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { 754 rdatasetheader_t *header = rdataset->private3; 755 756 header--; 757 header->trust = rdataset->trust = trust; 758} 759 760/* 761 * Rdataset Iterator Methods 762 */ 763 764static void 765rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { 766 ecdb_rdatasetiter_t *ecdbiterator; 767 isc_mem_t *mctx; 768 769 REQUIRE(iteratorp != NULL); 770 ecdbiterator = (ecdb_rdatasetiter_t *)*iteratorp; 771 REQUIRE(DNS_RDATASETITER_VALID(&ecdbiterator->common)); 772 773 mctx = ecdbiterator->common.db->mctx; 774 775 ecdbiterator->common.magic = 0; 776 777 dns_db_detachnode(ecdbiterator->common.db, &ecdbiterator->common.node); 778 isc_mem_put(mctx, ecdbiterator, sizeof(ecdb_rdatasetiter_t)); 779 780 *iteratorp = NULL; 781} 782 783static isc_result_t 784rdatasetiter_first(dns_rdatasetiter_t *iterator) { 785 ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; 786 dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)iterator->node; 787 788 REQUIRE(DNS_RDATASETITER_VALID(iterator)); 789 790 if (ISC_LIST_EMPTY(ecdbnode->rdatasets)) 791 return (ISC_R_NOMORE); 792 ecdbiterator->current = ISC_LIST_HEAD(ecdbnode->rdatasets); 793 return (ISC_R_SUCCESS); 794} 795 796static isc_result_t 797rdatasetiter_next(dns_rdatasetiter_t *iterator) { 798 ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; 799 800 REQUIRE(DNS_RDATASETITER_VALID(iterator)); 801 802 ecdbiterator->current = ISC_LIST_NEXT(ecdbiterator->current, link); 803 if (ecdbiterator->current == NULL) 804 return (ISC_R_NOMORE); 805 else 806 return (ISC_R_SUCCESS); 807} 808 809static void 810rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) { 811 ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; 812 dns_ecdb_t *ecdb; 813 814 ecdb = (dns_ecdb_t *)iterator->db; 815 REQUIRE(VALID_ECDB(ecdb)); 816 817 bind_rdataset(ecdb, iterator->node, ecdbiterator->current, rdataset); 818} 819