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