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