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