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