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