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