1/* $NetBSD: sdb.c,v 1.12 2024/02/21 22:52:08 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/*! \file */ 17 18#include <inttypes.h> 19#include <stdbool.h> 20#include <string.h> 21 22#include <isc/buffer.h> 23#include <isc/lex.h> 24#include <isc/log.h> 25#include <isc/magic.h> 26#include <isc/mem.h> 27#include <isc/once.h> 28#include <isc/print.h> 29#include <isc/refcount.h> 30#include <isc/region.h> 31#include <isc/result.h> 32#include <isc/util.h> 33 34#include <dns/callbacks.h> 35#include <dns/db.h> 36#include <dns/dbiterator.h> 37#include <dns/fixedname.h> 38#include <dns/log.h> 39#include <dns/rdata.h> 40#include <dns/rdatalist.h> 41#include <dns/rdataset.h> 42#include <dns/rdatasetiter.h> 43#include <dns/rdatatype.h> 44#include <dns/sdb.h> 45#include <dns/types.h> 46 47#include "rdatalist_p.h" 48 49struct dns_sdbimplementation { 50 const dns_sdbmethods_t *methods; 51 void *driverdata; 52 unsigned int flags; 53 isc_mem_t *mctx; 54 isc_mutex_t driverlock; 55 dns_dbimplementation_t *dbimp; 56}; 57 58struct dns_sdb { 59 /* Unlocked */ 60 dns_db_t common; 61 char *zone; 62 dns_sdbimplementation_t *implementation; 63 void *dbdata; 64 65 /* Atomic */ 66 isc_refcount_t references; 67}; 68 69struct dns_sdblookup { 70 /* Unlocked */ 71 unsigned int magic; 72 dns_sdb_t *sdb; 73 ISC_LIST(dns_rdatalist_t) lists; 74 ISC_LIST(isc_buffer_t) buffers; 75 dns_name_t *name; 76 ISC_LINK(dns_sdblookup_t) link; 77 dns_rdatacallbacks_t callbacks; 78 79 /* Atomic */ 80 isc_refcount_t references; 81}; 82 83typedef struct dns_sdblookup dns_sdbnode_t; 84 85struct dns_sdballnodes { 86 dns_dbiterator_t common; 87 ISC_LIST(dns_sdbnode_t) nodelist; 88 dns_sdbnode_t *current; 89 dns_sdbnode_t *origin; 90}; 91 92typedef dns_sdballnodes_t sdb_dbiterator_t; 93 94typedef struct sdb_rdatasetiter { 95 dns_rdatasetiter_t common; 96 dns_rdatalist_t *current; 97} sdb_rdatasetiter_t; 98 99#define SDB_MAGIC ISC_MAGIC('S', 'D', 'B', '-') 100 101/*% 102 * Note that "impmagic" is not the first four bytes of the struct, so 103 * ISC_MAGIC_VALID cannot be used. 104 */ 105#define VALID_SDB(sdb) ((sdb) != NULL && (sdb)->common.impmagic == SDB_MAGIC) 106 107#define SDBLOOKUP_MAGIC ISC_MAGIC('S', 'D', 'B', 'L') 108#define VALID_SDBLOOKUP(sdbl) ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC) 109#define VALID_SDBNODE(sdbn) VALID_SDBLOOKUP(sdbn) 110 111/* These values are taken from RFC1537 */ 112#define SDB_DEFAULT_REFRESH 28800U /* 8 hours */ 113#define SDB_DEFAULT_RETRY 7200U /* 2 hours */ 114#define SDB_DEFAULT_EXPIRE 604800U /* 7 days */ 115#define SDB_DEFAULT_MINIMUM 86400U /* 1 day */ 116 117/* This is a reasonable value */ 118#define SDB_DEFAULT_TTL (60 * 60 * 24) 119 120#ifdef __COVERITY__ 121#define MAYBE_LOCK(sdb) LOCK(&sdb->implementation->driverlock) 122#define MAYBE_UNLOCK(sdb) UNLOCK(&sdb->implementation->driverlock) 123#else /* ifdef __COVERITY__ */ 124#define MAYBE_LOCK(sdb) \ 125 do { \ 126 unsigned int flags = sdb->implementation->flags; \ 127 if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \ 128 LOCK(&sdb->implementation->driverlock); \ 129 } while (0) 130 131#define MAYBE_UNLOCK(sdb) \ 132 do { \ 133 unsigned int flags = sdb->implementation->flags; \ 134 if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \ 135 UNLOCK(&sdb->implementation->driverlock); \ 136 } while (0) 137#endif /* ifdef __COVERITY__ */ 138 139static int dummy; 140 141static isc_result_t 142dns_sdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, 143 dns_rdataclass_t rdclass, unsigned int argc, char *argv[], 144 void *driverarg, dns_db_t **dbp); 145 146static isc_result_t 147findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 148 dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, 149 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); 150 151static isc_result_t 152createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep); 153 154static void 155destroynode(dns_sdbnode_t *node); 156 157static void 158detachnode(dns_db_t *db, dns_dbnode_t **targetp); 159 160static void 161list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node, 162 dns_rdataset_t *rdataset); 163 164static void 165dbiterator_destroy(dns_dbiterator_t **iteratorp); 166static isc_result_t 167dbiterator_first(dns_dbiterator_t *iterator); 168static isc_result_t 169dbiterator_last(dns_dbiterator_t *iterator); 170static isc_result_t 171dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name); 172static isc_result_t 173dbiterator_prev(dns_dbiterator_t *iterator); 174static isc_result_t 175dbiterator_next(dns_dbiterator_t *iterator); 176static isc_result_t 177dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, 178 dns_name_t *name); 179static isc_result_t 180dbiterator_pause(dns_dbiterator_t *iterator); 181static isc_result_t 182dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name); 183 184static dns_dbiteratormethods_t dbiterator_methods = { 185 dbiterator_destroy, dbiterator_first, dbiterator_last, 186 dbiterator_seek, dbiterator_prev, dbiterator_next, 187 dbiterator_current, dbiterator_pause, dbiterator_origin 188}; 189 190static void 191rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp); 192static isc_result_t 193rdatasetiter_first(dns_rdatasetiter_t *iterator); 194static isc_result_t 195rdatasetiter_next(dns_rdatasetiter_t *iterator); 196static void 197rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset); 198 199static dns_rdatasetitermethods_t rdatasetiter_methods = { 200 rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next, 201 rdatasetiter_current 202}; 203 204/* 205 * Functions used by implementors of simple databases 206 */ 207isc_result_t 208dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods, 209 void *driverdata, unsigned int flags, isc_mem_t *mctx, 210 dns_sdbimplementation_t **sdbimp) { 211 dns_sdbimplementation_t *imp; 212 isc_result_t result; 213 214 REQUIRE(drivername != NULL); 215 REQUIRE(methods != NULL); 216 REQUIRE(methods->lookup != NULL || methods->lookup2 != NULL); 217 REQUIRE(mctx != NULL); 218 REQUIRE(sdbimp != NULL && *sdbimp == NULL); 219 REQUIRE((flags & 220 ~(DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA | 221 DNS_SDBFLAG_THREADSAFE | DNS_SDBFLAG_DNS64)) == 0); 222 223 imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t)); 224 imp->methods = methods; 225 imp->driverdata = driverdata; 226 imp->flags = flags; 227 imp->mctx = NULL; 228 isc_mem_attach(mctx, &imp->mctx); 229 isc_mutex_init(&imp->driverlock); 230 231 imp->dbimp = NULL; 232 result = dns_db_register(drivername, dns_sdb_create, imp, mctx, 233 &imp->dbimp); 234 if (result != ISC_R_SUCCESS) { 235 goto cleanup_mutex; 236 } 237 *sdbimp = imp; 238 239 return (ISC_R_SUCCESS); 240 241cleanup_mutex: 242 isc_mutex_destroy(&imp->driverlock); 243 isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t)); 244 return (result); 245} 246 247void 248dns_sdb_unregister(dns_sdbimplementation_t **sdbimp) { 249 dns_sdbimplementation_t *imp; 250 251 REQUIRE(sdbimp != NULL && *sdbimp != NULL); 252 253 imp = *sdbimp; 254 *sdbimp = NULL; 255 dns_db_unregister(&imp->dbimp); 256 isc_mutex_destroy(&imp->driverlock); 257 258 isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdbimplementation_t)); 259} 260 261static unsigned int 262initial_size(unsigned int len) { 263 unsigned int size; 264 265 for (size = 1024; size < (64 * 1024); size *= 2) { 266 if (len < size) { 267 return (size); 268 } 269 } 270 return (65535); 271} 272 273isc_result_t 274dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval, 275 dns_ttl_t ttl, const unsigned char *rdatap, 276 unsigned int rdlen) { 277 dns_rdatalist_t *rdatalist; 278 dns_rdata_t *rdata; 279 isc_buffer_t *rdatabuf = NULL; 280 isc_mem_t *mctx; 281 isc_region_t region; 282 283 mctx = lookup->sdb->common.mctx; 284 285 rdatalist = ISC_LIST_HEAD(lookup->lists); 286 while (rdatalist != NULL) { 287 if (rdatalist->type == typeval) { 288 break; 289 } 290 rdatalist = ISC_LIST_NEXT(rdatalist, link); 291 } 292 293 if (rdatalist == NULL) { 294 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t)); 295 dns_rdatalist_init(rdatalist); 296 rdatalist->rdclass = lookup->sdb->common.rdclass; 297 rdatalist->type = typeval; 298 rdatalist->ttl = ttl; 299 ISC_LIST_APPEND(lookup->lists, rdatalist, link); 300 } else if (rdatalist->ttl != ttl) { 301 return (DNS_R_BADTTL); 302 } 303 304 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t)); 305 306 isc_buffer_allocate(mctx, &rdatabuf, rdlen); 307 DE_CONST(rdatap, region.base); 308 region.length = rdlen; 309 isc_buffer_copyregion(rdatabuf, ®ion); 310 isc_buffer_usedregion(rdatabuf, ®ion); 311 dns_rdata_init(rdata); 312 dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type, 313 ®ion); 314 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 315 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link); 316 317 return (ISC_R_SUCCESS); 318} 319 320isc_result_t 321dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl, 322 const char *data) { 323 unsigned int datalen; 324 dns_rdatatype_t typeval; 325 isc_textregion_t r; 326 isc_lex_t *lex = NULL; 327 isc_result_t result; 328 unsigned char *p = NULL; 329 unsigned int size = 0; /* Init to suppress compiler warning */ 330 isc_mem_t *mctx; 331 dns_sdbimplementation_t *imp; 332 const dns_name_t *origin; 333 isc_buffer_t b; 334 isc_buffer_t rb; 335 336 REQUIRE(VALID_SDBLOOKUP(lookup)); 337 REQUIRE(type != NULL); 338 REQUIRE(data != NULL); 339 340 mctx = lookup->sdb->common.mctx; 341 342 DE_CONST(type, r.base); 343 r.length = strlen(type); 344 result = dns_rdatatype_fromtext(&typeval, &r); 345 if (result != ISC_R_SUCCESS) { 346 return (result); 347 } 348 349 imp = lookup->sdb->implementation; 350 if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0) { 351 origin = &lookup->sdb->common.origin; 352 } else { 353 origin = dns_rootname; 354 } 355 356 result = isc_lex_create(mctx, 64, &lex); 357 if (result != ISC_R_SUCCESS) { 358 goto failure; 359 } 360 361 datalen = strlen(data); 362 size = initial_size(datalen); 363 do { 364 isc_buffer_constinit(&b, data, datalen); 365 isc_buffer_add(&b, datalen); 366 result = isc_lex_openbuffer(lex, &b); 367 if (result != ISC_R_SUCCESS) { 368 goto failure; 369 } 370 371 if (size >= 65535) { 372 size = 65535; 373 } 374 p = isc_mem_get(mctx, size); 375 isc_buffer_init(&rb, p, size); 376 result = dns_rdata_fromtext(NULL, lookup->sdb->common.rdclass, 377 typeval, lex, origin, 0, mctx, &rb, 378 &lookup->callbacks); 379 if (result != ISC_R_NOSPACE) { 380 break; 381 } 382 383 /* 384 * Is the RR too big? 385 */ 386 if (size >= 65535) { 387 break; 388 } 389 isc_mem_put(mctx, p, size); 390 p = NULL; 391 size *= 2; 392 } while (result == ISC_R_NOSPACE); 393 394 if (result != ISC_R_SUCCESS) { 395 goto failure; 396 } 397 398 result = dns_sdb_putrdata(lookup, typeval, ttl, isc_buffer_base(&rb), 399 isc_buffer_usedlength(&rb)); 400failure: 401 if (p != NULL) { 402 isc_mem_put(mctx, p, size); 403 } 404 if (lex != NULL) { 405 isc_lex_destroy(&lex); 406 } 407 408 return (result); 409} 410 411static isc_result_t 412getnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) { 413 dns_name_t *newname; 414 const dns_name_t *origin; 415 dns_fixedname_t fnewname; 416 dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db; 417 dns_sdbimplementation_t *imp = sdb->implementation; 418 dns_sdbnode_t *sdbnode; 419 isc_mem_t *mctx = sdb->common.mctx; 420 isc_buffer_t b; 421 isc_result_t result; 422 423 newname = dns_fixedname_initname(&fnewname); 424 425 if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0) { 426 origin = &sdb->common.origin; 427 } else { 428 origin = dns_rootname; 429 } 430 isc_buffer_constinit(&b, name, strlen(name)); 431 isc_buffer_add(&b, strlen(name)); 432 433 result = dns_name_fromtext(newname, &b, origin, 0, NULL); 434 if (result != ISC_R_SUCCESS) { 435 return (result); 436 } 437 438 if (allnodes->common.relative_names) { 439 /* All names are relative to the root */ 440 unsigned int nlabels = dns_name_countlabels(newname); 441 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname); 442 } 443 444 sdbnode = ISC_LIST_HEAD(allnodes->nodelist); 445 if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) { 446 sdbnode = NULL; 447 result = createnode(sdb, &sdbnode); 448 if (result != ISC_R_SUCCESS) { 449 return (result); 450 } 451 sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t)); 452 dns_name_init(sdbnode->name, NULL); 453 dns_name_dup(newname, mctx, sdbnode->name); 454 ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link); 455 if (allnodes->origin == NULL && 456 dns_name_equal(newname, &sdb->common.origin)) 457 { 458 allnodes->origin = sdbnode; 459 } 460 } 461 *nodep = sdbnode; 462 return (ISC_R_SUCCESS); 463} 464 465isc_result_t 466dns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name, 467 const char *type, dns_ttl_t ttl, const char *data) { 468 isc_result_t result; 469 dns_sdbnode_t *sdbnode = NULL; 470 result = getnode(allnodes, name, &sdbnode); 471 if (result != ISC_R_SUCCESS) { 472 return (result); 473 } 474 return (dns_sdb_putrr(sdbnode, type, ttl, data)); 475} 476 477isc_result_t 478dns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name, 479 dns_rdatatype_t type, dns_ttl_t ttl, const void *rdata, 480 unsigned int rdlen) { 481 isc_result_t result; 482 dns_sdbnode_t *sdbnode = NULL; 483 result = getnode(allnodes, name, &sdbnode); 484 if (result != ISC_R_SUCCESS) { 485 return (result); 486 } 487 return (dns_sdb_putrdata(sdbnode, type, ttl, rdata, rdlen)); 488} 489 490isc_result_t 491dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname, 492 uint32_t serial) { 493 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7]; 494 int n; 495 496 REQUIRE(mname != NULL); 497 REQUIRE(rname != NULL); 498 499 n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u", mname, rname, 500 serial, SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY, 501 SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM); 502 if (n >= (int)sizeof(str) || n < 0) { 503 return (ISC_R_NOSPACE); 504 } 505 return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str)); 506} 507 508/* 509 * DB routines 510 */ 511 512static void 513attach(dns_db_t *source, dns_db_t **targetp) { 514 dns_sdb_t *sdb = (dns_sdb_t *)source; 515 516 REQUIRE(VALID_SDB(sdb)); 517 518 isc_refcount_increment(&sdb->references); 519 520 *targetp = source; 521} 522 523static void 524destroy(dns_sdb_t *sdb) { 525 dns_sdbimplementation_t *imp = sdb->implementation; 526 527 isc_refcount_destroy(&sdb->references); 528 529 if (imp->methods->destroy != NULL) { 530 MAYBE_LOCK(sdb); 531 imp->methods->destroy(sdb->zone, imp->driverdata, &sdb->dbdata); 532 MAYBE_UNLOCK(sdb); 533 } 534 535 isc_mem_free(sdb->common.mctx, sdb->zone); 536 537 sdb->common.magic = 0; 538 sdb->common.impmagic = 0; 539 540 dns_name_free(&sdb->common.origin, sdb->common.mctx); 541 542 isc_mem_putanddetach(&sdb->common.mctx, sdb, sizeof(dns_sdb_t)); 543} 544 545static void 546detach(dns_db_t **dbp) { 547 dns_sdb_t *sdb = (dns_sdb_t *)(*dbp); 548 549 REQUIRE(VALID_SDB(sdb)); 550 551 *dbp = NULL; 552 553 if (isc_refcount_decrement(&sdb->references) == 1) { 554 destroy(sdb); 555 } 556} 557 558static isc_result_t 559beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { 560 UNUSED(db); 561 UNUSED(callbacks); 562 return (ISC_R_NOTIMPLEMENTED); 563} 564 565static isc_result_t 566endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { 567 UNUSED(db); 568 UNUSED(callbacks); 569 return (ISC_R_NOTIMPLEMENTED); 570} 571 572static isc_result_t 573dump(dns_db_t *db, dns_dbversion_t *version, const char *filename, 574 dns_masterformat_t masterformat) { 575 UNUSED(db); 576 UNUSED(version); 577 UNUSED(filename); 578 UNUSED(masterformat); 579 return (ISC_R_NOTIMPLEMENTED); 580} 581 582static void 583currentversion(dns_db_t *db, dns_dbversion_t **versionp) { 584 REQUIRE(versionp != NULL && *versionp == NULL); 585 586 UNUSED(db); 587 588 *versionp = (void *)&dummy; 589 return; 590} 591 592static isc_result_t 593newversion(dns_db_t *db, dns_dbversion_t **versionp) { 594 UNUSED(db); 595 UNUSED(versionp); 596 597 return (ISC_R_NOTIMPLEMENTED); 598} 599 600static void 601attachversion(dns_db_t *db, dns_dbversion_t *source, 602 dns_dbversion_t **targetp) { 603 REQUIRE(source != NULL && source == (void *)&dummy); 604 REQUIRE(targetp != NULL && *targetp == NULL); 605 606 UNUSED(db); 607 *targetp = source; 608 return; 609} 610 611static void 612closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) { 613 REQUIRE(versionp != NULL && *versionp == (void *)&dummy); 614 REQUIRE(!commit); 615 616 UNUSED(db); 617 UNUSED(commit); 618 619 *versionp = NULL; 620} 621 622static isc_result_t 623createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) { 624 dns_sdbnode_t *node; 625 626 node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t)); 627 628 node->sdb = NULL; 629 attach((dns_db_t *)sdb, (dns_db_t **)(void *)&node->sdb); 630 ISC_LIST_INIT(node->lists); 631 ISC_LIST_INIT(node->buffers); 632 ISC_LINK_INIT(node, link); 633 node->name = NULL; 634 dns_rdatacallbacks_init(&node->callbacks); 635 636 isc_refcount_init(&node->references, 1); 637 638 node->magic = SDBLOOKUP_MAGIC; 639 640 *nodep = node; 641 return (ISC_R_SUCCESS); 642} 643 644static void 645destroynode(dns_sdbnode_t *node) { 646 dns_rdatalist_t *list; 647 dns_rdata_t *rdata; 648 isc_buffer_t *b; 649 dns_sdb_t *sdb; 650 isc_mem_t *mctx; 651 652 sdb = node->sdb; 653 mctx = sdb->common.mctx; 654 655 while (!ISC_LIST_EMPTY(node->lists)) { 656 list = ISC_LIST_HEAD(node->lists); 657 while (!ISC_LIST_EMPTY(list->rdata)) { 658 rdata = ISC_LIST_HEAD(list->rdata); 659 ISC_LIST_UNLINK(list->rdata, rdata, link); 660 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); 661 } 662 ISC_LIST_UNLINK(node->lists, list, link); 663 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t)); 664 } 665 666 while (!ISC_LIST_EMPTY(node->buffers)) { 667 b = ISC_LIST_HEAD(node->buffers); 668 ISC_LIST_UNLINK(node->buffers, b, link); 669 isc_buffer_free(&b); 670 } 671 672 if (node->name != NULL) { 673 dns_name_free(node->name, mctx); 674 isc_mem_put(mctx, node->name, sizeof(dns_name_t)); 675 } 676 677 node->magic = 0; 678 isc_mem_put(mctx, node, sizeof(dns_sdbnode_t)); 679 detach((dns_db_t **)(void *)&sdb); 680} 681 682static isc_result_t 683getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { 684 dns_sdb_t *sdb = (dns_sdb_t *)db; 685 dns_sdbnode_t *node = NULL; 686 isc_result_t result; 687 isc_buffer_t b; 688 char namestr[DNS_NAME_MAXTEXT + 1]; 689 dns_sdbimplementation_t *imp; 690 dns_name_t relname; 691 dns_name_t *name; 692 693 REQUIRE(VALID_SDB(sdb)); 694 REQUIRE(nodep != NULL && *nodep == NULL); 695 696 imp = sdb->implementation; 697 name = &sdb->common.origin; 698 699 if (imp->methods->lookup2 != NULL) { 700 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) { 701 dns_name_init(&relname, NULL); 702 name = &relname; 703 } 704 } else { 705 isc_buffer_init(&b, namestr, sizeof(namestr)); 706 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) { 707 dns_name_init(&relname, NULL); 708 result = dns_name_totext(&relname, true, &b); 709 if (result != ISC_R_SUCCESS) { 710 return (result); 711 } 712 } else { 713 result = dns_name_totext(name, true, &b); 714 if (result != ISC_R_SUCCESS) { 715 return (result); 716 } 717 } 718 isc_buffer_putuint8(&b, 0); 719 } 720 721 result = createnode(sdb, &node); 722 if (result != ISC_R_SUCCESS) { 723 return (result); 724 } 725 726 MAYBE_LOCK(sdb); 727 if (imp->methods->lookup2 != NULL) { 728 result = imp->methods->lookup2(&sdb->common.origin, name, 729 sdb->dbdata, node, NULL, NULL); 730 } else { 731 result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata, 732 node, NULL, NULL); 733 } 734 MAYBE_UNLOCK(sdb); 735 if (result != ISC_R_SUCCESS && 736 !(result == ISC_R_NOTFOUND && imp->methods->authority != NULL)) 737 { 738 destroynode(node); 739 return (result); 740 } 741 742 if (imp->methods->authority != NULL) { 743 MAYBE_LOCK(sdb); 744 result = imp->methods->authority(sdb->zone, sdb->dbdata, node); 745 MAYBE_UNLOCK(sdb); 746 if (result != ISC_R_SUCCESS) { 747 destroynode(node); 748 return (result); 749 } 750 } 751 752 *nodep = node; 753 return (ISC_R_SUCCESS); 754} 755 756static isc_result_t 757findnodeext(dns_db_t *db, const dns_name_t *name, bool create, 758 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, 759 dns_dbnode_t **nodep) { 760 dns_sdb_t *sdb = (dns_sdb_t *)db; 761 dns_sdbnode_t *node = NULL; 762 isc_result_t result; 763 isc_buffer_t b; 764 char namestr[DNS_NAME_MAXTEXT + 1]; 765 bool isorigin; 766 dns_sdbimplementation_t *imp; 767 dns_name_t relname; 768 unsigned int labels; 769 770 REQUIRE(VALID_SDB(sdb)); 771 REQUIRE(nodep != NULL && *nodep == NULL); 772 773 UNUSED(name); 774 UNUSED(create); 775 776 imp = sdb->implementation; 777 778 isorigin = dns_name_equal(name, &sdb->common.origin); 779 780 if (imp->methods->lookup2 != NULL) { 781 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) { 782 labels = dns_name_countlabels(name) - 783 dns_name_countlabels(&db->origin); 784 dns_name_init(&relname, NULL); 785 dns_name_getlabelsequence(name, 0, labels, &relname); 786 name = &relname; 787 } 788 } else { 789 isc_buffer_init(&b, namestr, sizeof(namestr)); 790 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) { 791 labels = dns_name_countlabels(name) - 792 dns_name_countlabels(&db->origin); 793 dns_name_init(&relname, NULL); 794 dns_name_getlabelsequence(name, 0, labels, &relname); 795 result = dns_name_totext(&relname, true, &b); 796 if (result != ISC_R_SUCCESS) { 797 return (result); 798 } 799 } else { 800 result = dns_name_totext(name, true, &b); 801 if (result != ISC_R_SUCCESS) { 802 return (result); 803 } 804 } 805 isc_buffer_putuint8(&b, 0); 806 } 807 808 result = createnode(sdb, &node); 809 if (result != ISC_R_SUCCESS) { 810 return (result); 811 } 812 813 MAYBE_LOCK(sdb); 814 if (imp->methods->lookup2 != NULL) { 815 result = imp->methods->lookup2(&sdb->common.origin, name, 816 sdb->dbdata, node, methods, 817 clientinfo); 818 } else { 819 result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata, 820 node, methods, clientinfo); 821 } 822 MAYBE_UNLOCK(sdb); 823 if (result != ISC_R_SUCCESS && !(result == ISC_R_NOTFOUND && isorigin && 824 imp->methods->authority != NULL)) 825 { 826 destroynode(node); 827 return (result); 828 } 829 830 if (isorigin && imp->methods->authority != NULL) { 831 MAYBE_LOCK(sdb); 832 result = imp->methods->authority(sdb->zone, sdb->dbdata, node); 833 MAYBE_UNLOCK(sdb); 834 if (result != ISC_R_SUCCESS) { 835 destroynode(node); 836 return (result); 837 } 838 } 839 840 *nodep = node; 841 return (ISC_R_SUCCESS); 842} 843 844static isc_result_t 845findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, 846 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 847 dns_dbnode_t **nodep, dns_name_t *foundname, 848 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, 849 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 850 dns_sdb_t *sdb = (dns_sdb_t *)db; 851 dns_dbnode_t *node = NULL; 852 dns_fixedname_t fname; 853 dns_rdataset_t xrdataset; 854 dns_name_t *xname; 855 unsigned int nlabels, olabels; 856 isc_result_t result; 857 unsigned int i; 858 unsigned int flags; 859 860 REQUIRE(VALID_SDB(sdb)); 861 REQUIRE(nodep == NULL || *nodep == NULL); 862 REQUIRE(version == NULL || version == (void *)&dummy); 863 864 UNUSED(options); 865 866 if (!dns_name_issubdomain(name, &db->origin)) { 867 return (DNS_R_NXDOMAIN); 868 } 869 870 olabels = dns_name_countlabels(&db->origin); 871 nlabels = dns_name_countlabels(name); 872 873 xname = dns_fixedname_initname(&fname); 874 875 if (rdataset == NULL) { 876 dns_rdataset_init(&xrdataset); 877 rdataset = &xrdataset; 878 } 879 880 result = DNS_R_NXDOMAIN; 881 flags = sdb->implementation->flags; 882 i = (flags & DNS_SDBFLAG_DNS64) != 0 ? nlabels : olabels; 883 for (; i <= nlabels; i++) { 884 /* 885 * Look up the next label. 886 */ 887 dns_name_getlabelsequence(name, nlabels - i, i, xname); 888 result = findnodeext(db, xname, false, methods, clientinfo, 889 &node); 890 if (result == ISC_R_NOTFOUND) { 891 /* 892 * No data at zone apex? 893 */ 894 if (i == olabels) { 895 return (DNS_R_BADDB); 896 } 897 result = DNS_R_NXDOMAIN; 898 continue; 899 } 900 if (result != ISC_R_SUCCESS) { 901 return (result); 902 } 903 904 /* 905 * DNS64 zone's don't have DNAME or NS records. 906 */ 907 if ((flags & DNS_SDBFLAG_DNS64) != 0) { 908 goto skip; 909 } 910 911 /* 912 * DNS64 zone's don't have DNAME or NS records. 913 */ 914 if ((flags & DNS_SDBFLAG_DNS64) != 0) { 915 goto skip; 916 } 917 918 /* 919 * Look for a DNAME at the current label, unless this is 920 * the qname. 921 */ 922 if (i < nlabels) { 923 result = findrdataset(db, node, version, 924 dns_rdatatype_dname, 0, now, 925 rdataset, sigrdataset); 926 if (result == ISC_R_SUCCESS) { 927 result = DNS_R_DNAME; 928 break; 929 } 930 } 931 932 /* 933 * Look for an NS at the current label, unless this is the 934 * origin or glue is ok. 935 */ 936 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) { 937 result = findrdataset(db, node, version, 938 dns_rdatatype_ns, 0, now, 939 rdataset, sigrdataset); 940 if (result == ISC_R_SUCCESS) { 941 if (i == nlabels && type == dns_rdatatype_any) { 942 result = DNS_R_ZONECUT; 943 dns_rdataset_disassociate(rdataset); 944 if (sigrdataset != NULL && 945 dns_rdataset_isassociated( 946 sigrdataset)) 947 { 948 dns_rdataset_disassociate( 949 sigrdataset); 950 } 951 } else { 952 result = DNS_R_DELEGATION; 953 } 954 break; 955 } 956 } 957 958 /* 959 * If the current name is not the qname, add another label 960 * and try again. 961 */ 962 if (i < nlabels) { 963 destroynode(node); 964 node = NULL; 965 continue; 966 } 967 968 skip: 969 /* 970 * If we're looking for ANY, we're done. 971 */ 972 if (type == dns_rdatatype_any) { 973 result = ISC_R_SUCCESS; 974 break; 975 } 976 977 /* 978 * Look for the qtype. 979 */ 980 result = findrdataset(db, node, version, type, 0, now, rdataset, 981 sigrdataset); 982 if (result == ISC_R_SUCCESS) { 983 break; 984 } 985 986 /* 987 * Look for a CNAME 988 */ 989 if (type != dns_rdatatype_cname) { 990 result = findrdataset(db, node, version, 991 dns_rdatatype_cname, 0, now, 992 rdataset, sigrdataset); 993 if (result == ISC_R_SUCCESS) { 994 result = DNS_R_CNAME; 995 break; 996 } 997 } 998 999 result = DNS_R_NXRRSET; 1000 break; 1001 } 1002 1003 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) { 1004 dns_rdataset_disassociate(rdataset); 1005 } 1006 1007 if (foundname != NULL) { 1008 dns_name_copy(xname, foundname); 1009 } 1010 1011 if (nodep != NULL) { 1012 *nodep = node; 1013 } else if (node != NULL) { 1014 detachnode(db, &node); 1015 } 1016 1017 return (result); 1018} 1019 1020static isc_result_t 1021findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options, 1022 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname, 1023 dns_name_t *dcname, dns_rdataset_t *rdataset, 1024 dns_rdataset_t *sigrdataset) { 1025 UNUSED(db); 1026 UNUSED(name); 1027 UNUSED(options); 1028 UNUSED(now); 1029 UNUSED(nodep); 1030 UNUSED(foundname); 1031 UNUSED(dcname); 1032 UNUSED(rdataset); 1033 UNUSED(sigrdataset); 1034 1035 return (ISC_R_NOTIMPLEMENTED); 1036} 1037 1038static void 1039attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { 1040 dns_sdb_t *sdb = (dns_sdb_t *)db; 1041 dns_sdbnode_t *node = (dns_sdbnode_t *)source; 1042 1043 REQUIRE(VALID_SDB(sdb)); 1044 1045 UNUSED(sdb); 1046 1047 isc_refcount_increment(&node->references); 1048 1049 *targetp = source; 1050} 1051 1052static void 1053detachnode(dns_db_t *db, dns_dbnode_t **targetp) { 1054 dns_sdb_t *sdb = (dns_sdb_t *)db; 1055 dns_sdbnode_t *node; 1056 1057 REQUIRE(VALID_SDB(sdb)); 1058 REQUIRE(targetp != NULL && *targetp != NULL); 1059 1060 UNUSED(sdb); 1061 1062 node = (dns_sdbnode_t *)(*targetp); 1063 1064 *targetp = NULL; 1065 1066 if (isc_refcount_decrement(&node->references) == 1) { 1067 destroynode(node); 1068 } 1069} 1070 1071static isc_result_t 1072expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) { 1073 UNUSED(db); 1074 UNUSED(node); 1075 UNUSED(now); 1076 UNREACHABLE(); 1077} 1078 1079static void 1080printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) { 1081 UNUSED(db); 1082 UNUSED(node); 1083 UNUSED(out); 1084 return; 1085} 1086 1087static isc_result_t 1088createiterator(dns_db_t *db, unsigned int options, 1089 dns_dbiterator_t **iteratorp) { 1090 dns_sdb_t *sdb = (dns_sdb_t *)db; 1091 REQUIRE(VALID_SDB(sdb)); 1092 1093 sdb_dbiterator_t *sdbiter; 1094 isc_result_t result; 1095 dns_sdbimplementation_t *imp = sdb->implementation; 1096 1097 if (imp->methods->allnodes == NULL) { 1098 return (ISC_R_NOTIMPLEMENTED); 1099 } 1100 1101 if ((options & DNS_DB_NSEC3ONLY) != 0 || 1102 (options & DNS_DB_NONSEC3) != 0) 1103 { 1104 return (ISC_R_NOTIMPLEMENTED); 1105 } 1106 1107 sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t)); 1108 1109 sdbiter->common.methods = &dbiterator_methods; 1110 sdbiter->common.db = NULL; 1111 dns_db_attach(db, &sdbiter->common.db); 1112 sdbiter->common.relative_names = ((options & DNS_DB_RELATIVENAMES) != 1113 0); 1114 sdbiter->common.magic = DNS_DBITERATOR_MAGIC; 1115 ISC_LIST_INIT(sdbiter->nodelist); 1116 sdbiter->current = NULL; 1117 sdbiter->origin = NULL; 1118 1119 MAYBE_LOCK(sdb); 1120 result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter); 1121 MAYBE_UNLOCK(sdb); 1122 if (result != ISC_R_SUCCESS) { 1123 dbiterator_destroy((dns_dbiterator_t **)(void *)&sdbiter); 1124 return (result); 1125 } 1126 1127 if (sdbiter->origin != NULL) { 1128 ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link); 1129 ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link); 1130 } 1131 1132 *iteratorp = (dns_dbiterator_t *)sdbiter; 1133 1134 return (ISC_R_SUCCESS); 1135} 1136 1137static isc_result_t 1138findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1139 dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, 1140 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 1141 REQUIRE(VALID_SDBNODE(node)); 1142 1143 dns_rdatalist_t *list; 1144 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node; 1145 1146 UNUSED(db); 1147 UNUSED(version); 1148 UNUSED(covers); 1149 UNUSED(now); 1150 UNUSED(sigrdataset); 1151 1152 if (type == dns_rdatatype_rrsig) { 1153 return (ISC_R_NOTIMPLEMENTED); 1154 } 1155 1156 list = ISC_LIST_HEAD(sdbnode->lists); 1157 while (list != NULL) { 1158 if (list->type == type) { 1159 break; 1160 } 1161 list = ISC_LIST_NEXT(list, link); 1162 } 1163 if (list == NULL) { 1164 return (ISC_R_NOTFOUND); 1165 } 1166 1167 list_tordataset(list, db, node, rdataset); 1168 1169 return (ISC_R_SUCCESS); 1170} 1171 1172static isc_result_t 1173allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1174 unsigned int options, isc_stdtime_t now, 1175 dns_rdatasetiter_t **iteratorp) { 1176 sdb_rdatasetiter_t *iterator; 1177 1178 REQUIRE(version == NULL || version == &dummy); 1179 1180 UNUSED(version); 1181 UNUSED(now); 1182 1183 iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t)); 1184 1185 iterator->common.magic = DNS_RDATASETITER_MAGIC; 1186 iterator->common.methods = &rdatasetiter_methods; 1187 iterator->common.db = db; 1188 iterator->common.node = NULL; 1189 attachnode(db, node, &iterator->common.node); 1190 iterator->common.version = version; 1191 iterator->common.options = options; 1192 iterator->common.now = now; 1193 1194 *iteratorp = (dns_rdatasetiter_t *)iterator; 1195 1196 return (ISC_R_SUCCESS); 1197} 1198 1199static isc_result_t 1200addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1201 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, 1202 dns_rdataset_t *addedrdataset) { 1203 UNUSED(db); 1204 UNUSED(node); 1205 UNUSED(version); 1206 UNUSED(now); 1207 UNUSED(rdataset); 1208 UNUSED(options); 1209 UNUSED(addedrdataset); 1210 1211 return (ISC_R_NOTIMPLEMENTED); 1212} 1213 1214static isc_result_t 1215subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1216 dns_rdataset_t *rdataset, unsigned int options, 1217 dns_rdataset_t *newrdataset) { 1218 UNUSED(db); 1219 UNUSED(node); 1220 UNUSED(version); 1221 UNUSED(rdataset); 1222 UNUSED(options); 1223 UNUSED(newrdataset); 1224 1225 return (ISC_R_NOTIMPLEMENTED); 1226} 1227 1228static isc_result_t 1229deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1230 dns_rdatatype_t type, dns_rdatatype_t covers) { 1231 UNUSED(db); 1232 UNUSED(node); 1233 UNUSED(version); 1234 UNUSED(type); 1235 UNUSED(covers); 1236 1237 return (ISC_R_NOTIMPLEMENTED); 1238} 1239 1240static bool 1241issecure(dns_db_t *db) { 1242 UNUSED(db); 1243 1244 return (false); 1245} 1246 1247static unsigned int 1248nodecount(dns_db_t *db, dns_dbtree_t tree) { 1249 UNUSED(db); 1250 UNUSED(tree); 1251 1252 return (0); 1253} 1254 1255static bool 1256ispersistent(dns_db_t *db) { 1257 UNUSED(db); 1258 return (true); 1259} 1260 1261static void 1262overmem(dns_db_t *db, bool over) { 1263 UNUSED(db); 1264 UNUSED(over); 1265} 1266 1267static void 1268settask(dns_db_t *db, isc_task_t *task) { 1269 UNUSED(db); 1270 UNUSED(task); 1271} 1272 1273static dns_dbmethods_t sdb_methods = { 1274 attach, detach, 1275 beginload, endload, 1276 dump, currentversion, 1277 newversion, attachversion, 1278 closeversion, NULL, /* findnode */ 1279 NULL, /* find */ 1280 findzonecut, attachnode, 1281 detachnode, expirenode, 1282 printnode, createiterator, 1283 findrdataset, allrdatasets, 1284 addrdataset, subtractrdataset, 1285 deleterdataset, issecure, 1286 nodecount, ispersistent, 1287 overmem, settask, 1288 getoriginnode, /* getoriginnode */ 1289 NULL, /* transfernode */ 1290 NULL, /* getnsec3parameters */ 1291 NULL, /* findnsec3node */ 1292 NULL, /* setsigningtime */ 1293 NULL, /* getsigningtime */ 1294 NULL, /* resigned */ 1295 NULL, /* isdnssec */ 1296 NULL, /* getrrsetstats */ 1297 NULL, /* rpz_attach */ 1298 NULL, /* rpz_ready */ 1299 findnodeext, findext, 1300 NULL, /* setcachestats */ 1301 NULL, /* hashsize */ 1302 NULL, /* nodefullname */ 1303 NULL, /* getsize */ 1304 NULL, /* setservestalettl */ 1305 NULL, /* getservestalettl */ 1306 NULL, /* setservestalerefresh */ 1307 NULL, /* getservestalerefresh */ 1308 NULL, /* setgluecachestats */ 1309}; 1310 1311static isc_result_t 1312dns_sdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, 1313 dns_rdataclass_t rdclass, unsigned int argc, char *argv[], 1314 void *driverarg, dns_db_t **dbp) { 1315 dns_sdb_t *sdb; 1316 isc_result_t result; 1317 char zonestr[DNS_NAME_MAXTEXT + 1]; 1318 isc_buffer_t b; 1319 dns_sdbimplementation_t *imp; 1320 1321 REQUIRE(driverarg != NULL); 1322 1323 imp = driverarg; 1324 1325 if (type != dns_dbtype_zone) { 1326 return (ISC_R_NOTIMPLEMENTED); 1327 } 1328 1329 sdb = isc_mem_get(mctx, sizeof(dns_sdb_t)); 1330 memset(sdb, 0, sizeof(dns_sdb_t)); 1331 1332 dns_name_init(&sdb->common.origin, NULL); 1333 sdb->common.attributes = 0; 1334 sdb->common.methods = &sdb_methods; 1335 sdb->common.rdclass = rdclass; 1336 sdb->common.mctx = NULL; 1337 sdb->implementation = imp; 1338 1339 isc_mem_attach(mctx, &sdb->common.mctx); 1340 1341 result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin); 1342 if (result != ISC_R_SUCCESS) { 1343 goto cleanup_lock; 1344 } 1345 1346 isc_buffer_init(&b, zonestr, sizeof(zonestr)); 1347 result = dns_name_totext(origin, true, &b); 1348 if (result != ISC_R_SUCCESS) { 1349 goto cleanup_origin; 1350 } 1351 isc_buffer_putuint8(&b, 0); 1352 1353 sdb->zone = isc_mem_strdup(mctx, zonestr); 1354 1355 sdb->dbdata = NULL; 1356 if (imp->methods->create != NULL) { 1357 MAYBE_LOCK(sdb); 1358 result = imp->methods->create(sdb->zone, argc, argv, 1359 imp->driverdata, &sdb->dbdata); 1360 MAYBE_UNLOCK(sdb); 1361 if (result != ISC_R_SUCCESS) { 1362 goto cleanup_zonestr; 1363 } 1364 } 1365 1366 isc_refcount_init(&sdb->references, 1); 1367 1368 sdb->common.magic = DNS_DB_MAGIC; 1369 sdb->common.impmagic = SDB_MAGIC; 1370 1371 *dbp = (dns_db_t *)sdb; 1372 1373 return (ISC_R_SUCCESS); 1374 1375cleanup_zonestr: 1376 isc_mem_free(mctx, sdb->zone); 1377cleanup_origin: 1378 dns_name_free(&sdb->common.origin, mctx); 1379cleanup_lock: 1380 isc_mem_putanddetach(&mctx, sdb, sizeof(dns_sdb_t)); 1381 1382 return (result); 1383} 1384 1385/* 1386 * Rdataset Methods 1387 */ 1388 1389static void 1390disassociate(dns_rdataset_t *rdataset) { 1391 dns_dbnode_t *node = rdataset->private5; 1392 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node; 1393 dns_db_t *db = (dns_db_t *)sdbnode->sdb; 1394 1395 detachnode(db, &node); 1396 isc__rdatalist_disassociate(rdataset); 1397} 1398 1399static void 1400rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 1401 dns_dbnode_t *node = source->private5; 1402 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node; 1403 dns_db_t *db = (dns_db_t *)sdbnode->sdb; 1404 dns_dbnode_t *tempdb = NULL; 1405 1406 isc__rdatalist_clone(source, target); 1407 attachnode(db, node, &tempdb); 1408 source->private5 = tempdb; 1409} 1410 1411static dns_rdatasetmethods_t sdb_rdataset_methods = { 1412 disassociate, 1413 isc__rdatalist_first, 1414 isc__rdatalist_next, 1415 isc__rdatalist_current, 1416 rdataset_clone, 1417 isc__rdatalist_count, 1418 isc__rdatalist_addnoqname, 1419 isc__rdatalist_getnoqname, 1420 NULL, /* addclosest */ 1421 NULL, /* getclosest */ 1422 NULL, /* settrust */ 1423 NULL, /* expire */ 1424 NULL, /* clearprefetch */ 1425 NULL, /* setownercase */ 1426 NULL, /* getownercase */ 1427 NULL /* addglue */ 1428}; 1429 1430static void 1431list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node, 1432 dns_rdataset_t *rdataset) { 1433 /* 1434 * The sdb rdataset is an rdatalist with some additions. 1435 * - private1 & private2 are used by the rdatalist. 1436 * - private3 & private 4 are unused. 1437 * - private5 is the node. 1438 */ 1439 1440 /* This should never fail. */ 1441 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == 1442 ISC_R_SUCCESS); 1443 1444 rdataset->methods = &sdb_rdataset_methods; 1445 dns_db_attachnode(db, node, &rdataset->private5); 1446} 1447 1448/* 1449 * Database Iterator Methods 1450 */ 1451static void 1452dbiterator_destroy(dns_dbiterator_t **iteratorp) { 1453 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp); 1454 dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db; 1455 1456 while (!ISC_LIST_EMPTY(sdbiter->nodelist)) { 1457 dns_sdbnode_t *node; 1458 node = ISC_LIST_HEAD(sdbiter->nodelist); 1459 ISC_LIST_UNLINK(sdbiter->nodelist, node, link); 1460 destroynode(node); 1461 } 1462 1463 dns_db_detach(&sdbiter->common.db); 1464 isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t)); 1465 1466 *iteratorp = NULL; 1467} 1468 1469static isc_result_t 1470dbiterator_first(dns_dbiterator_t *iterator) { 1471 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1472 1473 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist); 1474 if (sdbiter->current == NULL) { 1475 return (ISC_R_NOMORE); 1476 } else { 1477 return (ISC_R_SUCCESS); 1478 } 1479} 1480 1481static isc_result_t 1482dbiterator_last(dns_dbiterator_t *iterator) { 1483 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1484 1485 sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist); 1486 if (sdbiter->current == NULL) { 1487 return (ISC_R_NOMORE); 1488 } else { 1489 return (ISC_R_SUCCESS); 1490 } 1491} 1492 1493static isc_result_t 1494dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) { 1495 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1496 1497 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist); 1498 while (sdbiter->current != NULL) { 1499 if (dns_name_equal(sdbiter->current->name, name)) { 1500 return (ISC_R_SUCCESS); 1501 } 1502 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link); 1503 } 1504 return (ISC_R_NOTFOUND); 1505} 1506 1507static isc_result_t 1508dbiterator_prev(dns_dbiterator_t *iterator) { 1509 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1510 1511 sdbiter->current = ISC_LIST_PREV(sdbiter->current, link); 1512 if (sdbiter->current == NULL) { 1513 return (ISC_R_NOMORE); 1514 } else { 1515 return (ISC_R_SUCCESS); 1516 } 1517} 1518 1519static isc_result_t 1520dbiterator_next(dns_dbiterator_t *iterator) { 1521 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1522 1523 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link); 1524 if (sdbiter->current == NULL) { 1525 return (ISC_R_NOMORE); 1526 } else { 1527 return (ISC_R_SUCCESS); 1528 } 1529} 1530 1531static isc_result_t 1532dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, 1533 dns_name_t *name) { 1534 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1535 1536 attachnode(iterator->db, sdbiter->current, nodep); 1537 if (name != NULL) { 1538 dns_name_copy(sdbiter->current->name, name); 1539 return (ISC_R_SUCCESS); 1540 } 1541 return (ISC_R_SUCCESS); 1542} 1543 1544static isc_result_t 1545dbiterator_pause(dns_dbiterator_t *iterator) { 1546 UNUSED(iterator); 1547 return (ISC_R_SUCCESS); 1548} 1549 1550static isc_result_t 1551dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) { 1552 UNUSED(iterator); 1553 dns_name_copy(dns_rootname, name); 1554 return (ISC_R_SUCCESS); 1555} 1556 1557/* 1558 * Rdataset Iterator Methods 1559 */ 1560 1561static void 1562rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { 1563 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp); 1564 detachnode(sdbiterator->common.db, &sdbiterator->common.node); 1565 isc_mem_put(sdbiterator->common.db->mctx, sdbiterator, 1566 sizeof(sdb_rdatasetiter_t)); 1567 *iteratorp = NULL; 1568} 1569 1570static isc_result_t 1571rdatasetiter_first(dns_rdatasetiter_t *iterator) { 1572 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator; 1573 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node; 1574 1575 if (ISC_LIST_EMPTY(sdbnode->lists)) { 1576 return (ISC_R_NOMORE); 1577 } 1578 sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists); 1579 return (ISC_R_SUCCESS); 1580} 1581 1582static isc_result_t 1583rdatasetiter_next(dns_rdatasetiter_t *iterator) { 1584 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator; 1585 1586 sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link); 1587 if (sdbiterator->current == NULL) { 1588 return (ISC_R_NOMORE); 1589 } else { 1590 return (ISC_R_SUCCESS); 1591 } 1592} 1593 1594static void 1595rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) { 1596 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator; 1597 1598 list_tordataset(sdbiterator->current, iterator->db, iterator->node, 1599 rdataset); 1600} 1601