1 /* $NetBSD: ecdb.c,v 1.9 2015/07/08 17:28:58 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2009-2014 Internet Systems Consortium, Inc. ("ISC") 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 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 48 typedef 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 58 typedef 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 71 typedef 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 89 static 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 95 static void rdataset_disassociate(dns_rdataset_t *rdataset); 96 static isc_result_t rdataset_first(dns_rdataset_t *rdataset); 97 static isc_result_t rdataset_next(dns_rdataset_t *rdataset); 98 static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata); 99 static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target); 100 static unsigned int rdataset_count(dns_rdataset_t *rdataset); 101 static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust); 102 103 static 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 NULL /* clearprefetch */ 120 }; 121 122 typedef struct ecdb_rdatasetiter { 123 dns_rdatasetiter_t common; 124 rdatasetheader_t *current; 125 } ecdb_rdatasetiter_t; 126 127 static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp); 128 static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator); 129 static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator); 130 static void rdatasetiter_current(dns_rdatasetiter_t *iterator, 131 dns_rdataset_t *rdataset); 132 133 static dns_rdatasetitermethods_t rdatasetiter_methods = { 134 rdatasetiter_destroy, 135 rdatasetiter_first, 136 rdatasetiter_next, 137 rdatasetiter_current 138 }; 139 140 isc_result_t 141 dns_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 148 void 149 dns_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 159 static void 160 attach(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 173 static void 174 destroy_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 191 static void 192 detach(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 212 static void 213 attachnode(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 230 static void 231 destroynode(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 266 static void 267 detachnode(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 292 static isc_result_t 293 find(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 315 static isc_result_t 316 findzonecut(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 336 static isc_result_t 337 findnode(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 393 static void 394 bind_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 if (NEGATIVE(header)) 414 rdataset->attributes |= DNS_RDATASETATTR_NEGATIVE; 415 416 rdataset->private1 = ecdb; 417 rdataset->private2 = node; 418 raw = (unsigned char *)header + sizeof(*header); 419 rdataset->private3 = raw; 420 rdataset->count = 0; 421 422 /* 423 * Reset iterator state. 424 */ 425 rdataset->privateuint4 = 0; 426 rdataset->private5 = NULL; 427 428 INSIST(node->references > 0); 429 node->references++; 430 } 431 432 static isc_result_t 433 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 434 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, 435 dns_rdataset_t *addedrdataset) 436 { 437 dns_ecdb_t *ecdb = (dns_ecdb_t *)db; 438 isc_region_t r; 439 isc_result_t result = ISC_R_SUCCESS; 440 isc_mem_t *mctx; 441 dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node; 442 rdatasetheader_t *header; 443 444 REQUIRE(VALID_ECDB(ecdb)); 445 REQUIRE(VALID_ECDBNODE(ecdbnode)); 446 447 UNUSED(version); 448 UNUSED(now); 449 UNUSED(options); 450 451 mctx = ecdb->common.mctx; 452 453 LOCK(&ecdbnode->lock); 454 455 /* 456 * Sanity check: this implementation does not allow overriding an 457 * existing rdataset of the same type. 458 */ 459 for (header = ISC_LIST_HEAD(ecdbnode->rdatasets); header != NULL; 460 header = ISC_LIST_NEXT(header, link)) { 461 INSIST(header->type != rdataset->type || 462 header->covers != rdataset->covers); 463 } 464 465 result = dns_rdataslab_fromrdataset(rdataset, mctx, 466 &r, sizeof(rdatasetheader_t)); 467 if (result != ISC_R_SUCCESS) 468 goto unlock; 469 470 header = (rdatasetheader_t *)r.base; 471 header->type = rdataset->type; 472 header->ttl = rdataset->ttl; 473 header->trust = rdataset->trust; 474 header->covers = rdataset->covers; 475 header->attributes = 0; 476 if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) 477 header->attributes |= RDATASET_ATTR_NXDOMAIN; 478 if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) 479 header->attributes |= RDATASET_ATTR_NEGATIVE; 480 ISC_LINK_INIT(header, link); 481 ISC_LIST_APPEND(ecdbnode->rdatasets, header, link); 482 483 if (addedrdataset == NULL) 484 goto unlock; 485 486 bind_rdataset(ecdb, ecdbnode, header, addedrdataset); 487 488 unlock: 489 UNLOCK(&ecdbnode->lock); 490 491 return (result); 492 } 493 494 static isc_result_t 495 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 496 dns_rdatatype_t type, dns_rdatatype_t covers) 497 { 498 UNUSED(db); 499 UNUSED(node); 500 UNUSED(version); 501 UNUSED(type); 502 UNUSED(covers); 503 504 return (ISC_R_NOTIMPLEMENTED); 505 } 506 507 static isc_result_t 508 createiterator(dns_db_t *db, unsigned int options, 509 dns_dbiterator_t **iteratorp) 510 { 511 UNUSED(db); 512 UNUSED(options); 513 UNUSED(iteratorp); 514 515 return (ISC_R_NOTIMPLEMENTED); 516 } 517 518 static isc_result_t 519 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 520 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) 521 { 522 dns_ecdb_t *ecdb = (dns_ecdb_t *)db; 523 dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node; 524 isc_mem_t *mctx; 525 ecdb_rdatasetiter_t *iterator; 526 527 REQUIRE(VALID_ECDB(ecdb)); 528 REQUIRE(VALID_ECDBNODE(ecdbnode)); 529 530 mctx = ecdb->common.mctx; 531 532 iterator = isc_mem_get(mctx, sizeof(ecdb_rdatasetiter_t)); 533 if (iterator == NULL) 534 return (ISC_R_NOMEMORY); 535 536 iterator->common.magic = DNS_RDATASETITER_MAGIC; 537 iterator->common.methods = &rdatasetiter_methods; 538 iterator->common.db = db; 539 iterator->common.node = NULL; 540 attachnode(db, node, &iterator->common.node); 541 iterator->common.version = version; 542 iterator->common.now = now; 543 544 *iteratorp = (dns_rdatasetiter_t *)iterator; 545 546 return (ISC_R_SUCCESS); 547 } 548 549 static dns_dbmethods_t ecdb_methods = { 550 attach, 551 detach, 552 NULL, /* beginload */ 553 NULL, /* endload */ 554 NULL, /* serialize */ 555 NULL, /* dump */ 556 NULL, /* currentversion */ 557 NULL, /* newversion */ 558 NULL, /* attachversion */ 559 NULL, /* closeversion */ 560 findnode, 561 find, 562 findzonecut, 563 attachnode, 564 detachnode, 565 NULL, /* expirenode */ 566 NULL, /* printnode */ 567 createiterator, /* createiterator */ 568 NULL, /* findrdataset */ 569 allrdatasets, 570 addrdataset, 571 NULL, /* subtractrdataset */ 572 deleterdataset, 573 NULL, /* issecure */ 574 NULL, /* nodecount */ 575 NULL, /* ispersistent */ 576 NULL, /* overmem */ 577 NULL, /* settask */ 578 NULL, /* getoriginnode */ 579 NULL, /* transfernode */ 580 NULL, /* getnsec3parameters */ 581 NULL, /* findnsec3node */ 582 NULL, /* setsigningtime */ 583 NULL, /* getsigningtime */ 584 NULL, /* resigned */ 585 NULL, /* isdnssec */ 586 NULL, /* getrrsetstats */ 587 NULL, /* rpz_attach */ 588 NULL, /* rpz_ready */ 589 NULL, /* findnodeext */ 590 NULL, /* findext */ 591 NULL, /* setcachestats */ 592 NULL /* hashsize */ 593 }; 594 595 static isc_result_t 596 dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type, 597 dns_rdataclass_t rdclass, unsigned int argc, char *argv[], 598 void *driverarg, dns_db_t **dbp) 599 { 600 dns_ecdb_t *ecdb; 601 isc_result_t result; 602 603 REQUIRE(mctx != NULL); 604 REQUIRE(origin == dns_rootname); 605 REQUIRE(type == dns_dbtype_cache); 606 REQUIRE(dbp != NULL && *dbp == NULL); 607 608 UNUSED(argc); 609 UNUSED(argv); 610 UNUSED(driverarg); 611 612 ecdb = isc_mem_get(mctx, sizeof(*ecdb)); 613 if (ecdb == NULL) 614 return (ISC_R_NOMEMORY); 615 616 ecdb->common.attributes = DNS_DBATTR_CACHE; 617 ecdb->common.rdclass = rdclass; 618 ecdb->common.methods = &ecdb_methods; 619 dns_name_init(&ecdb->common.origin, NULL); 620 result = dns_name_dupwithoffsets(origin, mctx, &ecdb->common.origin); 621 if (result != ISC_R_SUCCESS) { 622 isc_mem_put(mctx, ecdb, sizeof(*ecdb)); 623 return (result); 624 } 625 626 result = isc_mutex_init(&ecdb->lock); 627 if (result != ISC_R_SUCCESS) { 628 UNEXPECTED_ERROR(__FILE__, __LINE__, 629 "isc_mutex_init() failed: %s", 630 isc_result_totext(result)); 631 if (dns_name_dynamic(&ecdb->common.origin)) 632 dns_name_free(&ecdb->common.origin, mctx); 633 isc_mem_put(mctx, ecdb, sizeof(*ecdb)); 634 return (ISC_R_UNEXPECTED); 635 } 636 637 ecdb->references = 1; 638 ISC_LIST_INIT(ecdb->nodes); 639 640 ecdb->common.mctx = NULL; 641 isc_mem_attach(mctx, &ecdb->common.mctx); 642 ecdb->common.impmagic = ECDB_MAGIC; 643 ecdb->common.magic = DNS_DB_MAGIC; 644 645 *dbp = (dns_db_t *)ecdb; 646 647 return (ISC_R_SUCCESS); 648 } 649 650 /*% 651 * Rdataset Methods 652 */ 653 654 static void 655 rdataset_disassociate(dns_rdataset_t *rdataset) { 656 dns_db_t *db = rdataset->private1; 657 dns_dbnode_t *node = rdataset->private2; 658 659 dns_db_detachnode(db, &node); 660 } 661 662 static isc_result_t 663 rdataset_first(dns_rdataset_t *rdataset) { 664 unsigned char *raw = rdataset->private3; 665 unsigned int count; 666 667 count = raw[0] * 256 + raw[1]; 668 if (count == 0) { 669 rdataset->private5 = NULL; 670 return (ISC_R_NOMORE); 671 } 672 #if DNS_RDATASET_FIXED 673 raw += 2 + (4 * count); 674 #else 675 raw += 2; 676 #endif 677 /* 678 * The privateuint4 field is the number of rdata beyond the cursor 679 * position, so we decrement the total count by one before storing 680 * it. 681 */ 682 count--; 683 rdataset->privateuint4 = count; 684 rdataset->private5 = raw; 685 686 return (ISC_R_SUCCESS); 687 } 688 689 static isc_result_t 690 rdataset_next(dns_rdataset_t *rdataset) { 691 unsigned int count; 692 unsigned int length; 693 unsigned char *raw; 694 695 count = rdataset->privateuint4; 696 if (count == 0) 697 return (ISC_R_NOMORE); 698 count--; 699 rdataset->privateuint4 = count; 700 raw = rdataset->private5; 701 length = raw[0] * 256 + raw[1]; 702 #if DNS_RDATASET_FIXED 703 raw += length + 4; 704 #else 705 raw += length + 2; 706 #endif 707 rdataset->private5 = raw; 708 709 return (ISC_R_SUCCESS); 710 } 711 712 static void 713 rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { 714 unsigned char *raw = rdataset->private5; 715 isc_region_t r; 716 unsigned int length; 717 unsigned int flags = 0; 718 719 REQUIRE(raw != NULL); 720 721 length = raw[0] * 256 + raw[1]; 722 #if DNS_RDATASET_FIXED 723 raw += 4; 724 #else 725 raw += 2; 726 #endif 727 if (rdataset->type == dns_rdatatype_rrsig) { 728 if (*raw & DNS_RDATASLAB_OFFLINE) 729 flags |= DNS_RDATA_OFFLINE; 730 length--; 731 raw++; 732 } 733 r.length = length; 734 r.base = raw; 735 dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r); 736 rdata->flags |= flags; 737 } 738 739 static void 740 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 741 dns_db_t *db = source->private1; 742 dns_dbnode_t *node = source->private2; 743 dns_dbnode_t *cloned_node = NULL; 744 745 attachnode(db, node, &cloned_node); 746 *target = *source; 747 748 /* 749 * Reset iterator state. 750 */ 751 target->privateuint4 = 0; 752 target->private5 = NULL; 753 } 754 755 static unsigned int 756 rdataset_count(dns_rdataset_t *rdataset) { 757 unsigned char *raw = rdataset->private3; 758 unsigned int count; 759 760 count = raw[0] * 256 + raw[1]; 761 762 return (count); 763 } 764 765 static void 766 rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { 767 rdatasetheader_t *header = rdataset->private3; 768 769 header--; 770 header->trust = rdataset->trust = trust; 771 } 772 773 /* 774 * Rdataset Iterator Methods 775 */ 776 777 static void 778 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { 779 isc_mem_t *mctx; 780 union { 781 dns_rdatasetiter_t *rdatasetiterator; 782 ecdb_rdatasetiter_t *ecdbiterator; 783 } u; 784 785 REQUIRE(iteratorp != NULL); 786 REQUIRE(DNS_RDATASETITER_VALID(*iteratorp)); 787 788 u.rdatasetiterator = *iteratorp; 789 790 mctx = u.ecdbiterator->common.db->mctx; 791 u.ecdbiterator->common.magic = 0; 792 793 dns_db_detachnode(u.ecdbiterator->common.db, 794 &u.ecdbiterator->common.node); 795 isc_mem_put(mctx, u.ecdbiterator, 796 sizeof(ecdb_rdatasetiter_t)); 797 798 *iteratorp = NULL; 799 } 800 801 static isc_result_t 802 rdatasetiter_first(dns_rdatasetiter_t *iterator) { 803 ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; 804 dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)iterator->node; 805 806 REQUIRE(DNS_RDATASETITER_VALID(iterator)); 807 808 if (ISC_LIST_EMPTY(ecdbnode->rdatasets)) 809 return (ISC_R_NOMORE); 810 ecdbiterator->current = ISC_LIST_HEAD(ecdbnode->rdatasets); 811 return (ISC_R_SUCCESS); 812 } 813 814 static isc_result_t 815 rdatasetiter_next(dns_rdatasetiter_t *iterator) { 816 ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; 817 818 REQUIRE(DNS_RDATASETITER_VALID(iterator)); 819 820 ecdbiterator->current = ISC_LIST_NEXT(ecdbiterator->current, link); 821 if (ecdbiterator->current == NULL) 822 return (ISC_R_NOMORE); 823 else 824 return (ISC_R_SUCCESS); 825 } 826 827 static void 828 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) { 829 ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; 830 dns_ecdb_t *ecdb; 831 832 ecdb = (dns_ecdb_t *)iterator->db; 833 REQUIRE(VALID_ECDB(ecdb)); 834 835 bind_rdataset(ecdb, iterator->node, ecdbiterator->current, rdataset); 836 } 837