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