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