sdb.c revision 267654
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 731findnodeext(dns_db_t *db, dns_name_t *name, isc_boolean_t create, 732 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, 733 dns_dbnode_t **nodep) 734{ 735 dns_sdb_t *sdb = (dns_sdb_t *)db; 736 dns_sdbnode_t *node = NULL; 737 isc_result_t result; 738 isc_buffer_t b; 739 char namestr[DNS_NAME_MAXTEXT + 1]; 740 isc_boolean_t isorigin; 741 dns_sdbimplementation_t *imp; 742 dns_name_t relname; 743 unsigned int labels; 744 745 REQUIRE(VALID_SDB(sdb)); 746 REQUIRE(create == ISC_FALSE); 747 REQUIRE(nodep != NULL && *nodep == NULL); 748 749 UNUSED(name); 750 UNUSED(create); 751 752 imp = sdb->implementation; 753 754 isorigin = dns_name_equal(name, &sdb->common.origin); 755 756 if (imp->methods->lookup2 != NULL) { 757 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) { 758 labels = dns_name_countlabels(name) - 759 dns_name_countlabels(&db->origin); 760 dns_name_init(&relname, NULL); 761 dns_name_getlabelsequence(name, 0, labels, &relname); 762 name = &relname; 763 } 764 } else { 765 isc_buffer_init(&b, namestr, sizeof(namestr)); 766 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) { 767 768 labels = dns_name_countlabels(name) - 769 dns_name_countlabels(&db->origin); 770 dns_name_init(&relname, NULL); 771 dns_name_getlabelsequence(name, 0, labels, &relname); 772 result = dns_name_totext(&relname, ISC_TRUE, &b); 773 if (result != ISC_R_SUCCESS) 774 return (result); 775 } else { 776 result = dns_name_totext(name, ISC_TRUE, &b); 777 if (result != ISC_R_SUCCESS) 778 return (result); 779 } 780 isc_buffer_putuint8(&b, 0); 781 } 782 783 result = createnode(sdb, &node); 784 if (result != ISC_R_SUCCESS) 785 return (result); 786 787 MAYBE_LOCK(sdb); 788 if (imp->methods->lookup2 != NULL) 789 result = imp->methods->lookup2(&sdb->common.origin, name, 790 sdb->dbdata, node, methods, 791 clientinfo); 792 else 793 result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata, 794 node, methods, clientinfo); 795 MAYBE_UNLOCK(sdb); 796 if (result != ISC_R_SUCCESS && 797 !(result == ISC_R_NOTFOUND && 798 isorigin && imp->methods->authority != NULL)) 799 { 800 destroynode(node); 801 return (result); 802 } 803 804 if (isorigin && imp->methods->authority != NULL) { 805 MAYBE_LOCK(sdb); 806 result = imp->methods->authority(sdb->zone, sdb->dbdata, node); 807 MAYBE_UNLOCK(sdb); 808 if (result != ISC_R_SUCCESS) { 809 destroynode(node); 810 return (result); 811 } 812 } 813 814 *nodep = node; 815 return (ISC_R_SUCCESS); 816} 817 818static isc_result_t 819findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, 820 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 821 dns_dbnode_t **nodep, dns_name_t *foundname, 822 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, 823 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 824{ 825 dns_sdb_t *sdb = (dns_sdb_t *)db; 826 dns_dbnode_t *node = NULL; 827 dns_fixedname_t fname; 828 dns_rdataset_t xrdataset; 829 dns_name_t *xname; 830 unsigned int nlabels, olabels; 831 isc_result_t result; 832 unsigned int i; 833 unsigned int flags; 834 835 REQUIRE(VALID_SDB(sdb)); 836 REQUIRE(nodep == NULL || *nodep == NULL); 837 REQUIRE(version == NULL || version == (void *) &dummy); 838 839 UNUSED(options); 840 841 if (!dns_name_issubdomain(name, &db->origin)) 842 return (DNS_R_NXDOMAIN); 843 844 olabels = dns_name_countlabels(&db->origin); 845 nlabels = dns_name_countlabels(name); 846 847 dns_fixedname_init(&fname); 848 xname = dns_fixedname_name(&fname); 849 850 if (rdataset == NULL) { 851 dns_rdataset_init(&xrdataset); 852 rdataset = &xrdataset; 853 } 854 855 result = DNS_R_NXDOMAIN; 856 flags = sdb->implementation->flags; 857 i = (flags & DNS_SDBFLAG_DNS64) != 0 ? nlabels : olabels; 858 for (; i <= nlabels; i++) { 859 /* 860 * Look up the next label. 861 */ 862 dns_name_getlabelsequence(name, nlabels - i, i, xname); 863 result = findnodeext(db, xname, ISC_FALSE, methods, 864 clientinfo, &node); 865 if (result == ISC_R_NOTFOUND) { 866 /* 867 * No data at zone apex? 868 */ 869 if (i == olabels) 870 return (DNS_R_BADDB); 871 result = DNS_R_NXDOMAIN; 872 continue; 873 } 874 if (result != ISC_R_SUCCESS) 875 return (result); 876 877 /* 878 * DNS64 zone's don't have DNAME or NS records. 879 */ 880 if ((flags & DNS_SDBFLAG_DNS64) != 0) 881 goto skip; 882 883 /* 884 * DNS64 zone's don't have DNAME or NS records. 885 */ 886 if ((flags & DNS_SDBFLAG_DNS64) != 0) 887 goto skip; 888 889 /* 890 * Look for a DNAME at the current label, unless this is 891 * the qname. 892 */ 893 if (i < nlabels) { 894 result = findrdataset(db, node, version, 895 dns_rdatatype_dname, 896 0, now, rdataset, sigrdataset); 897 if (result == ISC_R_SUCCESS) { 898 result = DNS_R_DNAME; 899 break; 900 } 901 } 902 903 /* 904 * Look for an NS at the current label, unless this is the 905 * origin or glue is ok. 906 */ 907 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) { 908 result = findrdataset(db, node, version, 909 dns_rdatatype_ns, 910 0, now, rdataset, sigrdataset); 911 if (result == ISC_R_SUCCESS) { 912 if (i == nlabels && type == dns_rdatatype_any) 913 { 914 result = DNS_R_ZONECUT; 915 dns_rdataset_disassociate(rdataset); 916 if (sigrdataset != NULL && 917 dns_rdataset_isassociated 918 (sigrdataset)) { 919 dns_rdataset_disassociate 920 (sigrdataset); 921 } 922 } else 923 result = DNS_R_DELEGATION; 924 break; 925 } 926 } 927 928 /* 929 * If the current name is not the qname, add another label 930 * and try again. 931 */ 932 if (i < nlabels) { 933 destroynode(node); 934 node = NULL; 935 continue; 936 } 937 938 skip: 939 /* 940 * If we're looking for ANY, we're done. 941 */ 942 if (type == dns_rdatatype_any) { 943 result = ISC_R_SUCCESS; 944 break; 945 } 946 947 /* 948 * Look for the qtype. 949 */ 950 result = findrdataset(db, node, version, type, 951 0, now, rdataset, sigrdataset); 952 if (result == ISC_R_SUCCESS) 953 break; 954 955 /* 956 * Look for a CNAME 957 */ 958 if (type != dns_rdatatype_cname) { 959 result = findrdataset(db, node, version, 960 dns_rdatatype_cname, 961 0, now, rdataset, sigrdataset); 962 if (result == ISC_R_SUCCESS) { 963 result = DNS_R_CNAME; 964 break; 965 } 966 } 967 968 result = DNS_R_NXRRSET; 969 break; 970 } 971 972 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) 973 dns_rdataset_disassociate(rdataset); 974 975 if (foundname != NULL) { 976 isc_result_t xresult; 977 978 xresult = dns_name_copy(xname, foundname, NULL); 979 if (xresult != ISC_R_SUCCESS) { 980 if (node != NULL) 981 destroynode(node); 982 if (dns_rdataset_isassociated(rdataset)) 983 dns_rdataset_disassociate(rdataset); 984 return (DNS_R_BADDB); 985 } 986 } 987 988 if (nodep != NULL) 989 *nodep = node; 990 else if (node != NULL) 991 detachnode(db, &node); 992 993 return (result); 994} 995 996static isc_result_t 997findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options, 998 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname, 999 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 1000{ 1001 UNUSED(db); 1002 UNUSED(name); 1003 UNUSED(options); 1004 UNUSED(now); 1005 UNUSED(nodep); 1006 UNUSED(foundname); 1007 UNUSED(rdataset); 1008 UNUSED(sigrdataset); 1009 1010 return (ISC_R_NOTIMPLEMENTED); 1011} 1012 1013static void 1014attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { 1015 dns_sdb_t *sdb = (dns_sdb_t *)db; 1016 dns_sdbnode_t *node = (dns_sdbnode_t *)source; 1017 1018 REQUIRE(VALID_SDB(sdb)); 1019 1020 UNUSED(sdb); 1021 1022 LOCK(&node->lock); 1023 INSIST(node->references > 0); 1024 node->references++; 1025 INSIST(node->references != 0); /* Catch overflow. */ 1026 UNLOCK(&node->lock); 1027 1028 *targetp = source; 1029} 1030 1031static void 1032detachnode(dns_db_t *db, dns_dbnode_t **targetp) { 1033 dns_sdb_t *sdb = (dns_sdb_t *)db; 1034 dns_sdbnode_t *node; 1035 isc_boolean_t need_destroy = ISC_FALSE; 1036 1037 REQUIRE(VALID_SDB(sdb)); 1038 REQUIRE(targetp != NULL && *targetp != NULL); 1039 1040 UNUSED(sdb); 1041 1042 node = (dns_sdbnode_t *)(*targetp); 1043 1044 LOCK(&node->lock); 1045 INSIST(node->references > 0); 1046 node->references--; 1047 if (node->references == 0) 1048 need_destroy = ISC_TRUE; 1049 UNLOCK(&node->lock); 1050 1051 if (need_destroy) 1052 destroynode(node); 1053 1054 *targetp = NULL; 1055} 1056 1057static isc_result_t 1058expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) { 1059 UNUSED(db); 1060 UNUSED(node); 1061 UNUSED(now); 1062 INSIST(0); 1063 return (ISC_R_UNEXPECTED); 1064} 1065 1066static void 1067printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) { 1068 UNUSED(db); 1069 UNUSED(node); 1070 UNUSED(out); 1071 return; 1072} 1073 1074static isc_result_t 1075createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp) 1076{ 1077 dns_sdb_t *sdb = (dns_sdb_t *)db; 1078 sdb_dbiterator_t *sdbiter; 1079 dns_sdbimplementation_t *imp = sdb->implementation; 1080 isc_result_t result; 1081 1082 REQUIRE(VALID_SDB(sdb)); 1083 1084 if (imp->methods->allnodes == NULL) 1085 return (ISC_R_NOTIMPLEMENTED); 1086 1087 if ((options & DNS_DB_NSEC3ONLY) != 0 || 1088 (options & DNS_DB_NONSEC3) != 0) 1089 return (ISC_R_NOTIMPLEMENTED); 1090 1091 sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t)); 1092 if (sdbiter == NULL) 1093 return (ISC_R_NOMEMORY); 1094 1095 sdbiter->common.methods = &dbiterator_methods; 1096 sdbiter->common.db = NULL; 1097 dns_db_attach(db, &sdbiter->common.db); 1098 sdbiter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES); 1099 sdbiter->common.magic = DNS_DBITERATOR_MAGIC; 1100 ISC_LIST_INIT(sdbiter->nodelist); 1101 sdbiter->current = NULL; 1102 sdbiter->origin = NULL; 1103 1104 MAYBE_LOCK(sdb); 1105 result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter); 1106 MAYBE_UNLOCK(sdb); 1107 if (result != ISC_R_SUCCESS) { 1108 dbiterator_destroy((dns_dbiterator_t **) (void *)&sdbiter); 1109 return (result); 1110 } 1111 1112 if (sdbiter->origin != NULL) { 1113 ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link); 1114 ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link); 1115 } 1116 1117 *iteratorp = (dns_dbiterator_t *)sdbiter; 1118 1119 return (ISC_R_SUCCESS); 1120} 1121 1122static isc_result_t 1123findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1124 dns_rdatatype_t type, dns_rdatatype_t covers, 1125 isc_stdtime_t now, dns_rdataset_t *rdataset, 1126 dns_rdataset_t *sigrdataset) 1127{ 1128 dns_rdatalist_t *list; 1129 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node; 1130 1131 REQUIRE(VALID_SDBNODE(node)); 1132 1133 UNUSED(db); 1134 UNUSED(version); 1135 UNUSED(covers); 1136 UNUSED(now); 1137 UNUSED(sigrdataset); 1138 1139 if (type == dns_rdatatype_rrsig) 1140 return (ISC_R_NOTIMPLEMENTED); 1141 1142 list = ISC_LIST_HEAD(sdbnode->lists); 1143 while (list != NULL) { 1144 if (list->type == type) 1145 break; 1146 list = ISC_LIST_NEXT(list, link); 1147 } 1148 if (list == NULL) 1149 return (ISC_R_NOTFOUND); 1150 1151 list_tordataset(list, db, node, rdataset); 1152 1153 return (ISC_R_SUCCESS); 1154} 1155 1156static isc_result_t 1157allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1158 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) 1159{ 1160 sdb_rdatasetiter_t *iterator; 1161 1162 REQUIRE(version == NULL || version == &dummy); 1163 1164 UNUSED(version); 1165 UNUSED(now); 1166 1167 iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t)); 1168 if (iterator == NULL) 1169 return (ISC_R_NOMEMORY); 1170 1171 iterator->common.magic = DNS_RDATASETITER_MAGIC; 1172 iterator->common.methods = &rdatasetiter_methods; 1173 iterator->common.db = db; 1174 iterator->common.node = NULL; 1175 attachnode(db, node, &iterator->common.node); 1176 iterator->common.version = version; 1177 iterator->common.now = now; 1178 1179 *iteratorp = (dns_rdatasetiter_t *)iterator; 1180 1181 return (ISC_R_SUCCESS); 1182} 1183 1184static isc_result_t 1185addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1186 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, 1187 dns_rdataset_t *addedrdataset) 1188{ 1189 UNUSED(db); 1190 UNUSED(node); 1191 UNUSED(version); 1192 UNUSED(now); 1193 UNUSED(rdataset); 1194 UNUSED(options); 1195 UNUSED(addedrdataset); 1196 1197 return (ISC_R_NOTIMPLEMENTED); 1198} 1199 1200static isc_result_t 1201subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1202 dns_rdataset_t *rdataset, unsigned int options, 1203 dns_rdataset_t *newrdataset) 1204{ 1205 UNUSED(db); 1206 UNUSED(node); 1207 UNUSED(version); 1208 UNUSED(rdataset); 1209 UNUSED(options); 1210 UNUSED(newrdataset); 1211 1212 return (ISC_R_NOTIMPLEMENTED); 1213} 1214 1215static isc_result_t 1216deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1217 dns_rdatatype_t type, dns_rdatatype_t covers) 1218{ 1219 UNUSED(db); 1220 UNUSED(node); 1221 UNUSED(version); 1222 UNUSED(type); 1223 UNUSED(covers); 1224 1225 return (ISC_R_NOTIMPLEMENTED); 1226} 1227 1228static isc_boolean_t 1229issecure(dns_db_t *db) { 1230 UNUSED(db); 1231 1232 return (ISC_FALSE); 1233} 1234 1235static unsigned int 1236nodecount(dns_db_t *db) { 1237 UNUSED(db); 1238 1239 return (0); 1240} 1241 1242static isc_boolean_t 1243ispersistent(dns_db_t *db) { 1244 UNUSED(db); 1245 return (ISC_TRUE); 1246} 1247 1248static void 1249overmem(dns_db_t *db, isc_boolean_t overmem) { 1250 UNUSED(db); 1251 UNUSED(overmem); 1252} 1253 1254static void 1255settask(dns_db_t *db, isc_task_t *task) { 1256 UNUSED(db); 1257 UNUSED(task); 1258} 1259 1260 1261static dns_dbmethods_t sdb_methods = { 1262 attach, 1263 detach, 1264 beginload, 1265 endload, 1266 dump, 1267 currentversion, 1268 newversion, 1269 attachversion, 1270 closeversion, 1271 NULL, 1272 NULL, 1273 findzonecut, 1274 attachnode, 1275 detachnode, 1276 expirenode, 1277 printnode, 1278 createiterator, 1279 findrdataset, 1280 allrdatasets, 1281 addrdataset, 1282 subtractrdataset, 1283 deleterdataset, 1284 issecure, 1285 nodecount, 1286 ispersistent, 1287 overmem, 1288 settask, 1289 NULL, /* getoriginnode */ 1290 NULL, /* transfernode */ 1291 NULL, /* getnsec3parameters */ 1292 NULL, /* findnsec3node */ 1293 NULL, /* setsigningtime */ 1294 NULL, /* getsigningtime */ 1295 NULL, /* resigned */ 1296 NULL, /* isdnssec */ 1297 NULL, /* getrrsetstats */ 1298 NULL, /* rpz_enabled */ 1299 NULL, /* rpz_findips */ 1300 findnodeext, 1301 findext 1302}; 1303 1304static isc_result_t 1305dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type, 1306 dns_rdataclass_t rdclass, unsigned int argc, char *argv[], 1307 void *driverarg, dns_db_t **dbp) 1308{ 1309 dns_sdb_t *sdb; 1310 isc_result_t result; 1311 char zonestr[DNS_NAME_MAXTEXT + 1]; 1312 isc_buffer_t b; 1313 dns_sdbimplementation_t *imp; 1314 1315 REQUIRE(driverarg != NULL); 1316 1317 imp = driverarg; 1318 1319 if (type != dns_dbtype_zone) 1320 return (ISC_R_NOTIMPLEMENTED); 1321 1322 sdb = isc_mem_get(mctx, sizeof(dns_sdb_t)); 1323 if (sdb == NULL) 1324 return (ISC_R_NOMEMORY); 1325 memset(sdb, 0, sizeof(dns_sdb_t)); 1326 1327 dns_name_init(&sdb->common.origin, NULL); 1328 sdb->common.attributes = 0; 1329 sdb->common.methods = &sdb_methods; 1330 sdb->common.rdclass = rdclass; 1331 sdb->common.mctx = NULL; 1332 sdb->implementation = imp; 1333 1334 isc_mem_attach(mctx, &sdb->common.mctx); 1335 1336 result = isc_mutex_init(&sdb->lock); 1337 if (result != ISC_R_SUCCESS) 1338 goto cleanup_mctx; 1339 1340 result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin); 1341 if (result != ISC_R_SUCCESS) 1342 goto cleanup_lock; 1343 1344 isc_buffer_init(&b, zonestr, sizeof(zonestr)); 1345 result = dns_name_totext(origin, ISC_TRUE, &b); 1346 if (result != ISC_R_SUCCESS) 1347 goto cleanup_origin; 1348 isc_buffer_putuint8(&b, 0); 1349 1350 sdb->zone = isc_mem_strdup(mctx, zonestr); 1351 if (sdb->zone == NULL) { 1352 result = ISC_R_NOMEMORY; 1353 goto cleanup_origin; 1354 } 1355 1356 sdb->dbdata = NULL; 1357 if (imp->methods->create != NULL) { 1358 MAYBE_LOCK(sdb); 1359 result = imp->methods->create(sdb->zone, argc, argv, 1360 imp->driverdata, &sdb->dbdata); 1361 MAYBE_UNLOCK(sdb); 1362 if (result != ISC_R_SUCCESS) 1363 goto cleanup_zonestr; 1364 } 1365 1366 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 1375 cleanup_zonestr: 1376 isc_mem_free(mctx, sdb->zone); 1377 cleanup_origin: 1378 dns_name_free(&sdb->common.origin, mctx); 1379 cleanup_lock: 1380 (void)isc_mutex_destroy(&sdb->lock); 1381 cleanup_mctx: 1382 isc_mem_put(mctx, sdb, sizeof(dns_sdb_t)); 1383 isc_mem_detach(&mctx); 1384 1385 return (result); 1386} 1387 1388 1389/* 1390 * Rdataset Methods 1391 */ 1392 1393static void 1394disassociate(dns_rdataset_t *rdataset) { 1395 dns_dbnode_t *node = rdataset->private5; 1396 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node; 1397 dns_db_t *db = (dns_db_t *) sdbnode->sdb; 1398 1399 detachnode(db, &node); 1400 isc__rdatalist_disassociate(rdataset); 1401} 1402 1403static void 1404rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 1405 dns_dbnode_t *node = source->private5; 1406 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node; 1407 dns_db_t *db = (dns_db_t *) sdbnode->sdb; 1408 dns_dbnode_t *tempdb = NULL; 1409 1410 isc__rdatalist_clone(source, target); 1411 attachnode(db, node, &tempdb); 1412 source->private5 = tempdb; 1413} 1414 1415static dns_rdatasetmethods_t methods = { 1416 disassociate, 1417 isc__rdatalist_first, 1418 isc__rdatalist_next, 1419 isc__rdatalist_current, 1420 rdataset_clone, 1421 isc__rdatalist_count, 1422 isc__rdatalist_addnoqname, 1423 isc__rdatalist_getnoqname, 1424 NULL, 1425 NULL, 1426 NULL, 1427 NULL, 1428 NULL, 1429 NULL, 1430 NULL 1431}; 1432 1433static void 1434list_tordataset(dns_rdatalist_t *rdatalist, 1435 dns_db_t *db, dns_dbnode_t *node, 1436 dns_rdataset_t *rdataset) 1437{ 1438 /* 1439 * The sdb rdataset is an rdatalist with some additions. 1440 * - private1 & private2 are used by the rdatalist. 1441 * - private3 & private 4 are unused. 1442 * - private5 is the node. 1443 */ 1444 1445 /* This should never fail. */ 1446 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == 1447 ISC_R_SUCCESS); 1448 1449 rdataset->methods = &methods; 1450 dns_db_attachnode(db, node, &rdataset->private5); 1451} 1452 1453/* 1454 * Database Iterator Methods 1455 */ 1456static void 1457dbiterator_destroy(dns_dbiterator_t **iteratorp) { 1458 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp); 1459 dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db; 1460 1461 while (!ISC_LIST_EMPTY(sdbiter->nodelist)) { 1462 dns_sdbnode_t *node; 1463 node = ISC_LIST_HEAD(sdbiter->nodelist); 1464 ISC_LIST_UNLINK(sdbiter->nodelist, node, link); 1465 destroynode(node); 1466 } 1467 1468 dns_db_detach(&sdbiter->common.db); 1469 isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t)); 1470 1471 *iteratorp = NULL; 1472} 1473 1474static isc_result_t 1475dbiterator_first(dns_dbiterator_t *iterator) { 1476 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1477 1478 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist); 1479 if (sdbiter->current == NULL) 1480 return (ISC_R_NOMORE); 1481 else 1482 return (ISC_R_SUCCESS); 1483} 1484 1485static isc_result_t 1486dbiterator_last(dns_dbiterator_t *iterator) { 1487 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1488 1489 sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist); 1490 if (sdbiter->current == NULL) 1491 return (ISC_R_NOMORE); 1492 else 1493 return (ISC_R_SUCCESS); 1494} 1495 1496static isc_result_t 1497dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) { 1498 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1499 1500 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist); 1501 while (sdbiter->current != NULL) { 1502 if (dns_name_equal(sdbiter->current->name, name)) 1503 return (ISC_R_SUCCESS); 1504 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link); 1505 } 1506 return (ISC_R_NOTFOUND); 1507} 1508 1509static isc_result_t 1510dbiterator_prev(dns_dbiterator_t *iterator) { 1511 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1512 1513 sdbiter->current = ISC_LIST_PREV(sdbiter->current, link); 1514 if (sdbiter->current == NULL) 1515 return (ISC_R_NOMORE); 1516 else 1517 return (ISC_R_SUCCESS); 1518} 1519 1520static isc_result_t 1521dbiterator_next(dns_dbiterator_t *iterator) { 1522 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1523 1524 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link); 1525 if (sdbiter->current == NULL) 1526 return (ISC_R_NOMORE); 1527 else 1528 return (ISC_R_SUCCESS); 1529} 1530 1531static isc_result_t 1532dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, 1533 dns_name_t *name) 1534{ 1535 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1536 1537 attachnode(iterator->db, sdbiter->current, nodep); 1538 if (name != NULL) 1539 return (dns_name_copy(sdbiter->current->name, name, NULL)); 1540 return (ISC_R_SUCCESS); 1541} 1542 1543static isc_result_t 1544dbiterator_pause(dns_dbiterator_t *iterator) { 1545 UNUSED(iterator); 1546 return (ISC_R_SUCCESS); 1547} 1548 1549static isc_result_t 1550dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) { 1551 UNUSED(iterator); 1552 return (dns_name_copy(dns_rootname, name, NULL)); 1553} 1554 1555/* 1556 * Rdataset Iterator Methods 1557 */ 1558 1559static void 1560rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { 1561 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp); 1562 detachnode(sdbiterator->common.db, &sdbiterator->common.node); 1563 isc_mem_put(sdbiterator->common.db->mctx, sdbiterator, 1564 sizeof(sdb_rdatasetiter_t)); 1565 *iteratorp = NULL; 1566} 1567 1568static isc_result_t 1569rdatasetiter_first(dns_rdatasetiter_t *iterator) { 1570 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator; 1571 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node; 1572 1573 if (ISC_LIST_EMPTY(sdbnode->lists)) 1574 return (ISC_R_NOMORE); 1575 sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists); 1576 return (ISC_R_SUCCESS); 1577} 1578 1579static isc_result_t 1580rdatasetiter_next(dns_rdatasetiter_t *iterator) { 1581 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator; 1582 1583 sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link); 1584 if (sdbiterator->current == NULL) 1585 return (ISC_R_NOMORE); 1586 else 1587 return (ISC_R_SUCCESS); 1588} 1589 1590static void 1591rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) { 1592 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator; 1593 1594 list_tordataset(sdbiterator->current, iterator->db, iterator->node, 1595 rdataset); 1596} 1597