1 /* $NetBSD: sdb.c,v 1.1 2024/02/18 20:57:33 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/util.h> 32 33 #include <dns/callbacks.h> 34 #include <dns/db.h> 35 #include <dns/dbiterator.h> 36 #include <dns/fixedname.h> 37 #include <dns/log.h> 38 #include <dns/rdata.h> 39 #include <dns/rdatalist.h> 40 #include <dns/rdataset.h> 41 #include <dns/rdatasetiter.h> 42 #include <dns/rdatatype.h> 43 #include <dns/result.h> 44 #include <dns/sdb.h> 45 #include <dns/types.h> 46 47 #include "rdatalist_p.h" 48 49 struct 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 58 struct 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 69 struct 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 83 typedef struct dns_sdblookup dns_sdbnode_t; 84 85 struct 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 92 typedef dns_sdballnodes_t sdb_dbiterator_t; 93 94 typedef 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 139 static int dummy; 140 141 static isc_result_t 142 dns_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 146 static isc_result_t 147 findrdataset(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 151 static isc_result_t 152 createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep); 153 154 static void 155 destroynode(dns_sdbnode_t *node); 156 157 static void 158 detachnode(dns_db_t *db, dns_dbnode_t **targetp); 159 160 static void 161 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node, 162 dns_rdataset_t *rdataset); 163 164 static void 165 dbiterator_destroy(dns_dbiterator_t **iteratorp); 166 static isc_result_t 167 dbiterator_first(dns_dbiterator_t *iterator); 168 static isc_result_t 169 dbiterator_last(dns_dbiterator_t *iterator); 170 static isc_result_t 171 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name); 172 static isc_result_t 173 dbiterator_prev(dns_dbiterator_t *iterator); 174 static isc_result_t 175 dbiterator_next(dns_dbiterator_t *iterator); 176 static isc_result_t 177 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, 178 dns_name_t *name); 179 static isc_result_t 180 dbiterator_pause(dns_dbiterator_t *iterator); 181 static isc_result_t 182 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name); 183 184 static 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 190 static void 191 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp); 192 static isc_result_t 193 rdatasetiter_first(dns_rdatasetiter_t *iterator); 194 static isc_result_t 195 rdatasetiter_next(dns_rdatasetiter_t *iterator); 196 static void 197 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset); 198 199 static 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 */ 207 isc_result_t 208 dns_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 241 cleanup_mutex: 242 isc_mutex_destroy(&imp->driverlock); 243 isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t)); 244 return (result); 245 } 246 247 void 248 dns_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 261 static unsigned int 262 initial_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 273 isc_result_t 274 dns_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 320 isc_result_t 321 dns_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)); 400 failure: 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 411 static isc_result_t 412 getnode(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 465 isc_result_t 466 dns_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 477 isc_result_t 478 dns_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 490 isc_result_t 491 dns_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 512 static void 513 attach(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 523 static void 524 destroy(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 545 static void 546 detach(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 558 static isc_result_t 559 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { 560 UNUSED(db); 561 UNUSED(callbacks); 562 return (ISC_R_NOTIMPLEMENTED); 563 } 564 565 static isc_result_t 566 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { 567 UNUSED(db); 568 UNUSED(callbacks); 569 return (ISC_R_NOTIMPLEMENTED); 570 } 571 572 static isc_result_t 573 dump(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 582 static void 583 currentversion(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 592 static isc_result_t 593 newversion(dns_db_t *db, dns_dbversion_t **versionp) { 594 UNUSED(db); 595 UNUSED(versionp); 596 597 return (ISC_R_NOTIMPLEMENTED); 598 } 599 600 static void 601 attachversion(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 611 static void 612 closeversion(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 622 static isc_result_t 623 createnode(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 644 static void 645 destroynode(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 682 static isc_result_t 683 getoriginnode(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 756 static isc_result_t 757 findnodeext(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 844 static isc_result_t 845 findext(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_copynf(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 1020 static isc_result_t 1021 findzonecut(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 1038 static void 1039 attachnode(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 1052 static void 1053 detachnode(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 1071 static isc_result_t 1072 expirenode(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 1079 static void 1080 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) { 1081 UNUSED(db); 1082 UNUSED(node); 1083 UNUSED(out); 1084 return; 1085 } 1086 1087 static isc_result_t 1088 createiterator(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 1137 static isc_result_t 1138 findrdataset(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 1172 static isc_result_t 1173 allrdatasets(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 1199 static isc_result_t 1200 addrdataset(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 1214 static isc_result_t 1215 subtractrdataset(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 1228 static isc_result_t 1229 deleterdataset(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 1240 static bool 1241 issecure(dns_db_t *db) { 1242 UNUSED(db); 1243 1244 return (false); 1245 } 1246 1247 static unsigned int 1248 nodecount(dns_db_t *db) { 1249 UNUSED(db); 1250 1251 return (0); 1252 } 1253 1254 static bool 1255 ispersistent(dns_db_t *db) { 1256 UNUSED(db); 1257 return (true); 1258 } 1259 1260 static void 1261 overmem(dns_db_t *db, bool over) { 1262 UNUSED(db); 1263 UNUSED(over); 1264 } 1265 1266 static void 1267 settask(dns_db_t *db, isc_task_t *task) { 1268 UNUSED(db); 1269 UNUSED(task); 1270 } 1271 1272 static dns_dbmethods_t sdb_methods = { 1273 attach, 1274 detach, 1275 beginload, 1276 endload, 1277 NULL, /* serialize */ 1278 dump, 1279 currentversion, 1280 newversion, 1281 attachversion, 1282 closeversion, 1283 NULL, /* findnode */ 1284 NULL, /* find */ 1285 findzonecut, 1286 attachnode, 1287 detachnode, 1288 expirenode, 1289 printnode, 1290 createiterator, 1291 findrdataset, 1292 allrdatasets, 1293 addrdataset, 1294 subtractrdataset, 1295 deleterdataset, 1296 issecure, 1297 nodecount, 1298 ispersistent, 1299 overmem, 1300 settask, 1301 getoriginnode, /* getoriginnode */ 1302 NULL, /* transfernode */ 1303 NULL, /* getnsec3parameters */ 1304 NULL, /* findnsec3node */ 1305 NULL, /* setsigningtime */ 1306 NULL, /* getsigningtime */ 1307 NULL, /* resigned */ 1308 NULL, /* isdnssec */ 1309 NULL, /* getrrsetstats */ 1310 NULL, /* rpz_attach */ 1311 NULL, /* rpz_ready */ 1312 findnodeext, 1313 findext, 1314 NULL, /* setcachestats */ 1315 NULL, /* hashsize */ 1316 NULL, /* nodefullname */ 1317 NULL, /* getsize */ 1318 NULL, /* setservestalettl */ 1319 NULL, /* getservestalettl */ 1320 NULL, /* setservestalerefresh */ 1321 NULL, /* getservestalerefresh */ 1322 NULL, /* setgluecachestats */ 1323 NULL /* adjusthashsize */ 1324 }; 1325 1326 static isc_result_t 1327 dns_sdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, 1328 dns_rdataclass_t rdclass, unsigned int argc, char *argv[], 1329 void *driverarg, dns_db_t **dbp) { 1330 dns_sdb_t *sdb; 1331 isc_result_t result; 1332 char zonestr[DNS_NAME_MAXTEXT + 1]; 1333 isc_buffer_t b; 1334 dns_sdbimplementation_t *imp; 1335 1336 REQUIRE(driverarg != NULL); 1337 1338 imp = driverarg; 1339 1340 if (type != dns_dbtype_zone) { 1341 return (ISC_R_NOTIMPLEMENTED); 1342 } 1343 1344 sdb = isc_mem_get(mctx, sizeof(dns_sdb_t)); 1345 memset(sdb, 0, sizeof(dns_sdb_t)); 1346 1347 dns_name_init(&sdb->common.origin, NULL); 1348 sdb->common.attributes = 0; 1349 sdb->common.methods = &sdb_methods; 1350 sdb->common.rdclass = rdclass; 1351 sdb->common.mctx = NULL; 1352 sdb->implementation = imp; 1353 1354 isc_mem_attach(mctx, &sdb->common.mctx); 1355 1356 result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin); 1357 if (result != ISC_R_SUCCESS) { 1358 goto cleanup_lock; 1359 } 1360 1361 isc_buffer_init(&b, zonestr, sizeof(zonestr)); 1362 result = dns_name_totext(origin, true, &b); 1363 if (result != ISC_R_SUCCESS) { 1364 goto cleanup_origin; 1365 } 1366 isc_buffer_putuint8(&b, 0); 1367 1368 sdb->zone = isc_mem_strdup(mctx, zonestr); 1369 1370 sdb->dbdata = NULL; 1371 if (imp->methods->create != NULL) { 1372 MAYBE_LOCK(sdb); 1373 result = imp->methods->create(sdb->zone, argc, argv, 1374 imp->driverdata, &sdb->dbdata); 1375 MAYBE_UNLOCK(sdb); 1376 if (result != ISC_R_SUCCESS) { 1377 goto cleanup_zonestr; 1378 } 1379 } 1380 1381 isc_refcount_init(&sdb->references, 1); 1382 1383 sdb->common.magic = DNS_DB_MAGIC; 1384 sdb->common.impmagic = SDB_MAGIC; 1385 1386 *dbp = (dns_db_t *)sdb; 1387 1388 return (ISC_R_SUCCESS); 1389 1390 cleanup_zonestr: 1391 isc_mem_free(mctx, sdb->zone); 1392 cleanup_origin: 1393 dns_name_free(&sdb->common.origin, mctx); 1394 cleanup_lock: 1395 isc_mem_putanddetach(&mctx, sdb, sizeof(dns_sdb_t)); 1396 1397 return (result); 1398 } 1399 1400 /* 1401 * Rdataset Methods 1402 */ 1403 1404 static void 1405 disassociate(dns_rdataset_t *rdataset) { 1406 dns_dbnode_t *node = rdataset->private5; 1407 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node; 1408 dns_db_t *db = (dns_db_t *)sdbnode->sdb; 1409 1410 detachnode(db, &node); 1411 isc__rdatalist_disassociate(rdataset); 1412 } 1413 1414 static void 1415 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 1416 dns_dbnode_t *node = source->private5; 1417 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node; 1418 dns_db_t *db = (dns_db_t *)sdbnode->sdb; 1419 dns_dbnode_t *tempdb = NULL; 1420 1421 isc__rdatalist_clone(source, target); 1422 attachnode(db, node, &tempdb); 1423 source->private5 = tempdb; 1424 } 1425 1426 static dns_rdatasetmethods_t sdb_rdataset_methods = { 1427 disassociate, 1428 isc__rdatalist_first, 1429 isc__rdatalist_next, 1430 isc__rdatalist_current, 1431 rdataset_clone, 1432 isc__rdatalist_count, 1433 isc__rdatalist_addnoqname, 1434 isc__rdatalist_getnoqname, 1435 NULL, /* addclosest */ 1436 NULL, /* getclosest */ 1437 NULL, /* settrust */ 1438 NULL, /* expire */ 1439 NULL, /* clearprefetch */ 1440 NULL, /* setownercase */ 1441 NULL, /* getownercase */ 1442 NULL /* addglue */ 1443 }; 1444 1445 static void 1446 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node, 1447 dns_rdataset_t *rdataset) { 1448 /* 1449 * The sdb rdataset is an rdatalist with some additions. 1450 * - private1 & private2 are used by the rdatalist. 1451 * - private3 & private 4 are unused. 1452 * - private5 is the node. 1453 */ 1454 1455 /* This should never fail. */ 1456 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == 1457 ISC_R_SUCCESS); 1458 1459 rdataset->methods = &sdb_rdataset_methods; 1460 dns_db_attachnode(db, node, &rdataset->private5); 1461 } 1462 1463 /* 1464 * Database Iterator Methods 1465 */ 1466 static void 1467 dbiterator_destroy(dns_dbiterator_t **iteratorp) { 1468 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp); 1469 dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db; 1470 1471 while (!ISC_LIST_EMPTY(sdbiter->nodelist)) { 1472 dns_sdbnode_t *node; 1473 node = ISC_LIST_HEAD(sdbiter->nodelist); 1474 ISC_LIST_UNLINK(sdbiter->nodelist, node, link); 1475 destroynode(node); 1476 } 1477 1478 dns_db_detach(&sdbiter->common.db); 1479 isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t)); 1480 1481 *iteratorp = NULL; 1482 } 1483 1484 static isc_result_t 1485 dbiterator_first(dns_dbiterator_t *iterator) { 1486 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1487 1488 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist); 1489 if (sdbiter->current == NULL) { 1490 return (ISC_R_NOMORE); 1491 } else { 1492 return (ISC_R_SUCCESS); 1493 } 1494 } 1495 1496 static isc_result_t 1497 dbiterator_last(dns_dbiterator_t *iterator) { 1498 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1499 1500 sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist); 1501 if (sdbiter->current == NULL) { 1502 return (ISC_R_NOMORE); 1503 } else { 1504 return (ISC_R_SUCCESS); 1505 } 1506 } 1507 1508 static isc_result_t 1509 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) { 1510 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1511 1512 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist); 1513 while (sdbiter->current != NULL) { 1514 if (dns_name_equal(sdbiter->current->name, name)) { 1515 return (ISC_R_SUCCESS); 1516 } 1517 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link); 1518 } 1519 return (ISC_R_NOTFOUND); 1520 } 1521 1522 static isc_result_t 1523 dbiterator_prev(dns_dbiterator_t *iterator) { 1524 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1525 1526 sdbiter->current = ISC_LIST_PREV(sdbiter->current, link); 1527 if (sdbiter->current == NULL) { 1528 return (ISC_R_NOMORE); 1529 } else { 1530 return (ISC_R_SUCCESS); 1531 } 1532 } 1533 1534 static isc_result_t 1535 dbiterator_next(dns_dbiterator_t *iterator) { 1536 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1537 1538 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link); 1539 if (sdbiter->current == NULL) { 1540 return (ISC_R_NOMORE); 1541 } else { 1542 return (ISC_R_SUCCESS); 1543 } 1544 } 1545 1546 static isc_result_t 1547 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, 1548 dns_name_t *name) { 1549 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1550 1551 attachnode(iterator->db, sdbiter->current, nodep); 1552 if (name != NULL) { 1553 dns_name_copynf(sdbiter->current->name, name); 1554 return (ISC_R_SUCCESS); 1555 } 1556 return (ISC_R_SUCCESS); 1557 } 1558 1559 static isc_result_t 1560 dbiterator_pause(dns_dbiterator_t *iterator) { 1561 UNUSED(iterator); 1562 return (ISC_R_SUCCESS); 1563 } 1564 1565 static isc_result_t 1566 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) { 1567 UNUSED(iterator); 1568 dns_name_copynf(dns_rootname, name); 1569 return (ISC_R_SUCCESS); 1570 } 1571 1572 /* 1573 * Rdataset Iterator Methods 1574 */ 1575 1576 static void 1577 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { 1578 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp); 1579 detachnode(sdbiterator->common.db, &sdbiterator->common.node); 1580 isc_mem_put(sdbiterator->common.db->mctx, sdbiterator, 1581 sizeof(sdb_rdatasetiter_t)); 1582 *iteratorp = NULL; 1583 } 1584 1585 static isc_result_t 1586 rdatasetiter_first(dns_rdatasetiter_t *iterator) { 1587 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator; 1588 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node; 1589 1590 if (ISC_LIST_EMPTY(sdbnode->lists)) { 1591 return (ISC_R_NOMORE); 1592 } 1593 sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists); 1594 return (ISC_R_SUCCESS); 1595 } 1596 1597 static isc_result_t 1598 rdatasetiter_next(dns_rdatasetiter_t *iterator) { 1599 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator; 1600 1601 sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link); 1602 if (sdbiterator->current == NULL) { 1603 return (ISC_R_NOMORE); 1604 } else { 1605 return (ISC_R_SUCCESS); 1606 } 1607 } 1608 1609 static void 1610 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) { 1611 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator; 1612 1613 list_tordataset(sdbiterator->current, iterator->db, iterator->node, 1614 rdataset); 1615 } 1616