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