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