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