db.c revision 222395
1/* 2 * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-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: db.c,v 1.88.50.2 2009-06-23 00:19:34 tbox Exp $ */ 19 20/*! \file */ 21 22/*** 23 *** Imports 24 ***/ 25 26#include <config.h> 27 28#include <isc/buffer.h> 29#include <isc/mem.h> 30#include <isc/once.h> 31#include <isc/rwlock.h> 32#include <isc/string.h> 33#include <isc/util.h> 34 35#include <dns/callbacks.h> 36#include <dns/db.h> 37#include <dns/log.h> 38#include <dns/master.h> 39#include <dns/rdata.h> 40#include <dns/rdataset.h> 41#include <dns/result.h> 42 43/*** 44 *** Private Types 45 ***/ 46 47struct dns_dbimplementation { 48 const char * name; 49 dns_dbcreatefunc_t create; 50 isc_mem_t * mctx; 51 void * driverarg; 52 ISC_LINK(dns_dbimplementation_t) link; 53}; 54 55/*** 56 *** Supported DB Implementations Registry 57 ***/ 58 59/* 60 * Built in database implementations are registered here. 61 */ 62 63#include "rbtdb.h" 64#include "rbtdb64.h" 65 66static ISC_LIST(dns_dbimplementation_t) implementations; 67static isc_rwlock_t implock; 68static isc_once_t once = ISC_ONCE_INIT; 69 70static dns_dbimplementation_t rbtimp; 71static dns_dbimplementation_t rbt64imp; 72 73static void 74initialize(void) { 75 RUNTIME_CHECK(isc_rwlock_init(&implock, 0, 0) == ISC_R_SUCCESS); 76 77 rbtimp.name = "rbt"; 78 rbtimp.create = dns_rbtdb_create; 79 rbtimp.mctx = NULL; 80 rbtimp.driverarg = NULL; 81 ISC_LINK_INIT(&rbtimp, link); 82 83 rbt64imp.name = "rbt64"; 84 rbt64imp.create = dns_rbtdb64_create; 85 rbt64imp.mctx = NULL; 86 rbt64imp.driverarg = NULL; 87 ISC_LINK_INIT(&rbt64imp, link); 88 89 ISC_LIST_INIT(implementations); 90 ISC_LIST_APPEND(implementations, &rbtimp, link); 91 ISC_LIST_APPEND(implementations, &rbt64imp, link); 92} 93 94static inline dns_dbimplementation_t * 95impfind(const char *name) { 96 dns_dbimplementation_t *imp; 97 98 for (imp = ISC_LIST_HEAD(implementations); 99 imp != NULL; 100 imp = ISC_LIST_NEXT(imp, link)) 101 if (strcasecmp(name, imp->name) == 0) 102 return (imp); 103 return (NULL); 104} 105 106 107/*** 108 *** Basic DB Methods 109 ***/ 110 111isc_result_t 112dns_db_create(isc_mem_t *mctx, const char *db_type, dns_name_t *origin, 113 dns_dbtype_t type, dns_rdataclass_t rdclass, 114 unsigned int argc, char *argv[], dns_db_t **dbp) 115{ 116 dns_dbimplementation_t *impinfo; 117 118 RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); 119 120 /* 121 * Create a new database using implementation 'db_type'. 122 */ 123 124 REQUIRE(dbp != NULL && *dbp == NULL); 125 REQUIRE(dns_name_isabsolute(origin)); 126 127 RWLOCK(&implock, isc_rwlocktype_read); 128 impinfo = impfind(db_type); 129 if (impinfo != NULL) { 130 isc_result_t result; 131 result = ((impinfo->create)(mctx, origin, type, 132 rdclass, argc, argv, 133 impinfo->driverarg, dbp)); 134 RWUNLOCK(&implock, isc_rwlocktype_read); 135 return (result); 136 } 137 138 RWUNLOCK(&implock, isc_rwlocktype_read); 139 140 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 141 DNS_LOGMODULE_DB, ISC_LOG_ERROR, 142 "unsupported database type '%s'", db_type); 143 144 return (ISC_R_NOTFOUND); 145} 146 147void 148dns_db_attach(dns_db_t *source, dns_db_t **targetp) { 149 150 /* 151 * Attach *targetp to source. 152 */ 153 154 REQUIRE(DNS_DB_VALID(source)); 155 REQUIRE(targetp != NULL && *targetp == NULL); 156 157 (source->methods->attach)(source, targetp); 158 159 ENSURE(*targetp == source); 160} 161 162void 163dns_db_detach(dns_db_t **dbp) { 164 165 /* 166 * Detach *dbp from its database. 167 */ 168 169 REQUIRE(dbp != NULL); 170 REQUIRE(DNS_DB_VALID(*dbp)); 171 172 ((*dbp)->methods->detach)(dbp); 173 174 ENSURE(*dbp == NULL); 175} 176 177isc_result_t 178dns_db_ondestroy(dns_db_t *db, isc_task_t *task, isc_event_t **eventp) 179{ 180 REQUIRE(DNS_DB_VALID(db)); 181 182 return (isc_ondestroy_register(&db->ondest, task, eventp)); 183} 184 185 186isc_boolean_t 187dns_db_iscache(dns_db_t *db) { 188 189 /* 190 * Does 'db' have cache semantics? 191 */ 192 193 REQUIRE(DNS_DB_VALID(db)); 194 195 if ((db->attributes & DNS_DBATTR_CACHE) != 0) 196 return (ISC_TRUE); 197 198 return (ISC_FALSE); 199} 200 201isc_boolean_t 202dns_db_iszone(dns_db_t *db) { 203 204 /* 205 * Does 'db' have zone semantics? 206 */ 207 208 REQUIRE(DNS_DB_VALID(db)); 209 210 if ((db->attributes & (DNS_DBATTR_CACHE|DNS_DBATTR_STUB)) == 0) 211 return (ISC_TRUE); 212 213 return (ISC_FALSE); 214} 215 216isc_boolean_t 217dns_db_isstub(dns_db_t *db) { 218 219 /* 220 * Does 'db' have stub semantics? 221 */ 222 223 REQUIRE(DNS_DB_VALID(db)); 224 225 if ((db->attributes & DNS_DBATTR_STUB) != 0) 226 return (ISC_TRUE); 227 228 return (ISC_FALSE); 229} 230 231isc_boolean_t 232dns_db_isdnssec(dns_db_t *db) { 233 234 /* 235 * Is 'db' secure or partially secure? 236 */ 237 238 REQUIRE(DNS_DB_VALID(db)); 239 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0); 240 241 if (db->methods->isdnssec != NULL) 242 return ((db->methods->isdnssec)(db)); 243 return ((db->methods->issecure)(db)); 244} 245 246isc_boolean_t 247dns_db_issecure(dns_db_t *db) { 248 249 /* 250 * Is 'db' secure? 251 */ 252 253 REQUIRE(DNS_DB_VALID(db)); 254 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0); 255 256 return ((db->methods->issecure)(db)); 257} 258 259isc_boolean_t 260dns_db_ispersistent(dns_db_t *db) { 261 262 /* 263 * Is 'db' persistent? 264 */ 265 266 REQUIRE(DNS_DB_VALID(db)); 267 268 return ((db->methods->ispersistent)(db)); 269} 270 271dns_name_t * 272dns_db_origin(dns_db_t *db) { 273 /* 274 * The origin of the database. 275 */ 276 277 REQUIRE(DNS_DB_VALID(db)); 278 279 return (&db->origin); 280} 281 282dns_rdataclass_t 283dns_db_class(dns_db_t *db) { 284 /* 285 * The class of the database. 286 */ 287 288 REQUIRE(DNS_DB_VALID(db)); 289 290 return (db->rdclass); 291} 292 293isc_result_t 294dns_db_beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, 295 dns_dbload_t **dbloadp) { 296 /* 297 * Begin loading 'db'. 298 */ 299 300 REQUIRE(DNS_DB_VALID(db)); 301 REQUIRE(addp != NULL && *addp == NULL); 302 REQUIRE(dbloadp != NULL && *dbloadp == NULL); 303 304 return ((db->methods->beginload)(db, addp, dbloadp)); 305} 306 307isc_result_t 308dns_db_endload(dns_db_t *db, dns_dbload_t **dbloadp) { 309 /* 310 * Finish loading 'db'. 311 */ 312 313 REQUIRE(DNS_DB_VALID(db)); 314 REQUIRE(dbloadp != NULL && *dbloadp != NULL); 315 316 return ((db->methods->endload)(db, dbloadp)); 317} 318 319isc_result_t 320dns_db_load(dns_db_t *db, const char *filename) { 321 return (dns_db_load2(db, filename, dns_masterformat_text)); 322} 323 324isc_result_t 325dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format) { 326 isc_result_t result, eresult; 327 dns_rdatacallbacks_t callbacks; 328 unsigned int options = 0; 329 330 /* 331 * Load master file 'filename' into 'db'. 332 */ 333 334 REQUIRE(DNS_DB_VALID(db)); 335 336 if ((db->attributes & DNS_DBATTR_CACHE) != 0) 337 options |= DNS_MASTER_AGETTL; 338 339 dns_rdatacallbacks_init(&callbacks); 340 341 result = dns_db_beginload(db, &callbacks.add, &callbacks.add_private); 342 if (result != ISC_R_SUCCESS) 343 return (result); 344 result = dns_master_loadfile2(filename, &db->origin, &db->origin, 345 db->rdclass, options, 346 &callbacks, db->mctx, format); 347 eresult = dns_db_endload(db, &callbacks.add_private); 348 /* 349 * We always call dns_db_endload(), but we only want to return its 350 * result if dns_master_loadfile() succeeded. If dns_master_loadfile() 351 * failed, we want to return the result code it gave us. 352 */ 353 if (eresult != ISC_R_SUCCESS && 354 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE)) 355 result = eresult; 356 357 return (result); 358} 359 360isc_result_t 361dns_db_dump(dns_db_t *db, dns_dbversion_t *version, const char *filename) { 362 return ((db->methods->dump)(db, version, filename, 363 dns_masterformat_text)); 364} 365 366isc_result_t 367dns_db_dump2(dns_db_t *db, dns_dbversion_t *version, const char *filename, 368 dns_masterformat_t masterformat) { 369 /* 370 * Dump 'db' into master file 'filename' in the 'masterformat' format. 371 * XXXJT: is it okay to modify the interface to the existing "dump" 372 * method? 373 */ 374 375 REQUIRE(DNS_DB_VALID(db)); 376 377 return ((db->methods->dump)(db, version, filename, masterformat)); 378} 379 380/*** 381 *** Version Methods 382 ***/ 383 384void 385dns_db_currentversion(dns_db_t *db, dns_dbversion_t **versionp) { 386 387 /* 388 * Open the current version for reading. 389 */ 390 391 REQUIRE(DNS_DB_VALID(db)); 392 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0); 393 REQUIRE(versionp != NULL && *versionp == NULL); 394 395 (db->methods->currentversion)(db, versionp); 396} 397 398isc_result_t 399dns_db_newversion(dns_db_t *db, dns_dbversion_t **versionp) { 400 401 /* 402 * Open a new version for reading and writing. 403 */ 404 405 REQUIRE(DNS_DB_VALID(db)); 406 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0); 407 REQUIRE(versionp != NULL && *versionp == NULL); 408 409 return ((db->methods->newversion)(db, versionp)); 410} 411 412void 413dns_db_attachversion(dns_db_t *db, dns_dbversion_t *source, 414 dns_dbversion_t **targetp) 415{ 416 /* 417 * Attach '*targetp' to 'source'. 418 */ 419 420 REQUIRE(DNS_DB_VALID(db)); 421 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0); 422 REQUIRE(source != NULL); 423 REQUIRE(targetp != NULL && *targetp == NULL); 424 425 (db->methods->attachversion)(db, source, targetp); 426 427 ENSURE(*targetp != NULL); 428} 429 430void 431dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp, 432 isc_boolean_t commit) 433{ 434 435 /* 436 * Close version '*versionp'. 437 */ 438 439 REQUIRE(DNS_DB_VALID(db)); 440 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0); 441 REQUIRE(versionp != NULL && *versionp != NULL); 442 443 (db->methods->closeversion)(db, versionp, commit); 444 445 ENSURE(*versionp == NULL); 446} 447 448/*** 449 *** Node Methods 450 ***/ 451 452isc_result_t 453dns_db_findnode(dns_db_t *db, dns_name_t *name, 454 isc_boolean_t create, dns_dbnode_t **nodep) 455{ 456 457 /* 458 * Find the node with name 'name'. 459 */ 460 461 REQUIRE(DNS_DB_VALID(db)); 462 REQUIRE(nodep != NULL && *nodep == NULL); 463 464 return ((db->methods->findnode)(db, name, create, nodep)); 465} 466 467isc_result_t 468dns_db_findnsec3node(dns_db_t *db, dns_name_t *name, 469 isc_boolean_t create, dns_dbnode_t **nodep) 470{ 471 472 /* 473 * Find the node with name 'name'. 474 */ 475 476 REQUIRE(DNS_DB_VALID(db)); 477 REQUIRE(nodep != NULL && *nodep == NULL); 478 479 return ((db->methods->findnsec3node)(db, name, create, nodep)); 480} 481 482isc_result_t 483dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, 484 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 485 dns_dbnode_t **nodep, dns_name_t *foundname, 486 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 487{ 488 489 /* 490 * Find the best match for 'name' and 'type' in version 'version' 491 * of 'db'. 492 */ 493 494 REQUIRE(DNS_DB_VALID(db)); 495 REQUIRE(type != dns_rdatatype_rrsig); 496 REQUIRE(nodep == NULL || (nodep != NULL && *nodep == NULL)); 497 REQUIRE(dns_name_hasbuffer(foundname)); 498 REQUIRE(rdataset == NULL || 499 (DNS_RDATASET_VALID(rdataset) && 500 ! dns_rdataset_isassociated(rdataset))); 501 REQUIRE(sigrdataset == NULL || 502 (DNS_RDATASET_VALID(sigrdataset) && 503 ! dns_rdataset_isassociated(sigrdataset))); 504 505 return ((db->methods->find)(db, name, version, type, options, now, 506 nodep, foundname, rdataset, sigrdataset)); 507} 508 509isc_result_t 510dns_db_findzonecut(dns_db_t *db, dns_name_t *name, 511 unsigned int options, isc_stdtime_t now, 512 dns_dbnode_t **nodep, dns_name_t *foundname, 513 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 514{ 515 /* 516 * Find the deepest known zonecut which encloses 'name' in 'db'. 517 */ 518 519 REQUIRE(DNS_DB_VALID(db)); 520 REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0); 521 REQUIRE(nodep == NULL || (nodep != NULL && *nodep == NULL)); 522 REQUIRE(dns_name_hasbuffer(foundname)); 523 REQUIRE(sigrdataset == NULL || 524 (DNS_RDATASET_VALID(sigrdataset) && 525 ! dns_rdataset_isassociated(sigrdataset))); 526 527 return ((db->methods->findzonecut)(db, name, options, now, nodep, 528 foundname, rdataset, sigrdataset)); 529} 530 531void 532dns_db_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { 533 534 /* 535 * Attach *targetp to source. 536 */ 537 538 REQUIRE(DNS_DB_VALID(db)); 539 REQUIRE(source != NULL); 540 REQUIRE(targetp != NULL && *targetp == NULL); 541 542 (db->methods->attachnode)(db, source, targetp); 543} 544 545void 546dns_db_detachnode(dns_db_t *db, dns_dbnode_t **nodep) { 547 548 /* 549 * Detach *nodep from its node. 550 */ 551 552 REQUIRE(DNS_DB_VALID(db)); 553 REQUIRE(nodep != NULL && *nodep != NULL); 554 555 (db->methods->detachnode)(db, nodep); 556 557 ENSURE(*nodep == NULL); 558} 559 560void 561dns_db_transfernode(dns_db_t *db, dns_dbnode_t **sourcep, 562 dns_dbnode_t **targetp) 563{ 564 REQUIRE(DNS_DB_VALID(db)); 565 REQUIRE(targetp != NULL && *targetp == NULL); 566 /* 567 * This doesn't check the implementation magic. If we find that 568 * we need such checks in future then this will be done in the 569 * method. 570 */ 571 REQUIRE(sourcep != NULL && *sourcep != NULL); 572 573 UNUSED(db); 574 575 if (db->methods->transfernode == NULL) { 576 *targetp = *sourcep; 577 *sourcep = NULL; 578 } else 579 (db->methods->transfernode)(db, sourcep, targetp); 580 581 ENSURE(*sourcep == NULL); 582} 583 584isc_result_t 585dns_db_expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) { 586 587 /* 588 * Mark as stale all records at 'node' which expire at or before 'now'. 589 */ 590 591 REQUIRE(DNS_DB_VALID(db)); 592 REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0); 593 REQUIRE(node != NULL); 594 595 return ((db->methods->expirenode)(db, node, now)); 596} 597 598void 599dns_db_printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) { 600 /* 601 * Print a textual representation of the contents of the node to 602 * 'out'. 603 */ 604 605 REQUIRE(DNS_DB_VALID(db)); 606 REQUIRE(node != NULL); 607 608 (db->methods->printnode)(db, node, out); 609} 610 611/*** 612 *** DB Iterator Creation 613 ***/ 614 615isc_result_t 616dns_db_createiterator(dns_db_t *db, unsigned int flags, 617 dns_dbiterator_t **iteratorp) 618{ 619 /* 620 * Create an iterator for version 'version' of 'db'. 621 */ 622 623 REQUIRE(DNS_DB_VALID(db)); 624 REQUIRE(iteratorp != NULL && *iteratorp == NULL); 625 626 return (db->methods->createiterator(db, flags, iteratorp)); 627} 628 629/*** 630 *** Rdataset Methods 631 ***/ 632 633isc_result_t 634dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 635 dns_rdatatype_t type, dns_rdatatype_t covers, 636 isc_stdtime_t now, dns_rdataset_t *rdataset, 637 dns_rdataset_t *sigrdataset) 638{ 639 /* 640 * Search for an rdataset of type 'type' at 'node' that are in version 641 * 'version' of 'db'. If found, make 'rdataset' refer to it. 642 */ 643 644 REQUIRE(DNS_DB_VALID(db)); 645 REQUIRE(node != NULL); 646 REQUIRE(DNS_RDATASET_VALID(rdataset)); 647 REQUIRE(! dns_rdataset_isassociated(rdataset)); 648 REQUIRE(covers == 0 || type == dns_rdatatype_rrsig); 649 REQUIRE(type != dns_rdatatype_any); 650 REQUIRE(sigrdataset == NULL || 651 (DNS_RDATASET_VALID(sigrdataset) && 652 ! dns_rdataset_isassociated(sigrdataset))); 653 654 return ((db->methods->findrdataset)(db, node, version, type, covers, 655 now, rdataset, sigrdataset)); 656} 657 658isc_result_t 659dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 660 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) 661{ 662 /* 663 * Make '*iteratorp' an rdataset iteratator for all rdatasets at 664 * 'node' in version 'version' of 'db'. 665 */ 666 667 REQUIRE(DNS_DB_VALID(db)); 668 REQUIRE(iteratorp != NULL && *iteratorp == NULL); 669 670 return ((db->methods->allrdatasets)(db, node, version, now, 671 iteratorp)); 672} 673 674isc_result_t 675dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 676 isc_stdtime_t now, dns_rdataset_t *rdataset, 677 unsigned int options, dns_rdataset_t *addedrdataset) 678{ 679 /* 680 * Add 'rdataset' to 'node' in version 'version' of 'db'. 681 */ 682 683 REQUIRE(DNS_DB_VALID(db)); 684 REQUIRE(node != NULL); 685 REQUIRE(((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL)|| 686 ((db->attributes & DNS_DBATTR_CACHE) != 0 && 687 version == NULL && (options & DNS_DBADD_MERGE) == 0)); 688 REQUIRE((options & DNS_DBADD_EXACT) == 0 || 689 (options & DNS_DBADD_MERGE) != 0); 690 REQUIRE(DNS_RDATASET_VALID(rdataset)); 691 REQUIRE(dns_rdataset_isassociated(rdataset)); 692 REQUIRE(rdataset->rdclass == db->rdclass); 693 REQUIRE(addedrdataset == NULL || 694 (DNS_RDATASET_VALID(addedrdataset) && 695 ! dns_rdataset_isassociated(addedrdataset))); 696 697 return ((db->methods->addrdataset)(db, node, version, now, rdataset, 698 options, addedrdataset)); 699} 700 701isc_result_t 702dns_db_subtractrdataset(dns_db_t *db, dns_dbnode_t *node, 703 dns_dbversion_t *version, dns_rdataset_t *rdataset, 704 unsigned int options, dns_rdataset_t *newrdataset) 705{ 706 /* 707 * Remove any rdata in 'rdataset' from 'node' in version 'version' of 708 * 'db'. 709 */ 710 711 REQUIRE(DNS_DB_VALID(db)); 712 REQUIRE(node != NULL); 713 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL); 714 REQUIRE(DNS_RDATASET_VALID(rdataset)); 715 REQUIRE(dns_rdataset_isassociated(rdataset)); 716 REQUIRE(rdataset->rdclass == db->rdclass); 717 REQUIRE(newrdataset == NULL || 718 (DNS_RDATASET_VALID(newrdataset) && 719 ! dns_rdataset_isassociated(newrdataset))); 720 721 return ((db->methods->subtractrdataset)(db, node, version, rdataset, 722 options, newrdataset)); 723} 724 725isc_result_t 726dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node, 727 dns_dbversion_t *version, dns_rdatatype_t type, 728 dns_rdatatype_t covers) 729{ 730 /* 731 * Make it so that no rdataset of type 'type' exists at 'node' in 732 * version version 'version' of 'db'. 733 */ 734 735 REQUIRE(DNS_DB_VALID(db)); 736 REQUIRE(node != NULL); 737 REQUIRE(((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL)|| 738 ((db->attributes & DNS_DBATTR_CACHE) != 0 && version == NULL)); 739 740 return ((db->methods->deleterdataset)(db, node, version, 741 type, covers)); 742} 743 744void 745dns_db_overmem(dns_db_t *db, isc_boolean_t overmem) { 746 747 REQUIRE(DNS_DB_VALID(db)); 748 749 (db->methods->overmem)(db, overmem); 750} 751 752isc_result_t 753dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, isc_uint32_t *serialp) 754{ 755 isc_result_t result; 756 dns_dbnode_t *node = NULL; 757 dns_rdataset_t rdataset; 758 dns_rdata_t rdata = DNS_RDATA_INIT; 759 isc_buffer_t buffer; 760 761 REQUIRE(dns_db_iszone(db) || dns_db_isstub(db)); 762 763 result = dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node); 764 if (result != ISC_R_SUCCESS) 765 return (result); 766 767 dns_rdataset_init(&rdataset); 768 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0, 769 (isc_stdtime_t)0, &rdataset, NULL); 770 if (result != ISC_R_SUCCESS) 771 goto freenode; 772 773 result = dns_rdataset_first(&rdataset); 774 if (result != ISC_R_SUCCESS) 775 goto freerdataset; 776 dns_rdataset_current(&rdataset, &rdata); 777 result = dns_rdataset_next(&rdataset); 778 INSIST(result == ISC_R_NOMORE); 779 780 INSIST(rdata.length > 20); 781 isc_buffer_init(&buffer, rdata.data, rdata.length); 782 isc_buffer_add(&buffer, rdata.length); 783 isc_buffer_forward(&buffer, rdata.length - 20); 784 *serialp = isc_buffer_getuint32(&buffer); 785 786 result = ISC_R_SUCCESS; 787 788 freerdataset: 789 dns_rdataset_disassociate(&rdataset); 790 791 freenode: 792 dns_db_detachnode(db, &node); 793 return (result); 794} 795 796unsigned int 797dns_db_nodecount(dns_db_t *db) { 798 REQUIRE(DNS_DB_VALID(db)); 799 800 return ((db->methods->nodecount)(db)); 801} 802 803void 804dns_db_settask(dns_db_t *db, isc_task_t *task) { 805 REQUIRE(DNS_DB_VALID(db)); 806 807 (db->methods->settask)(db, task); 808} 809 810isc_result_t 811dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg, 812 isc_mem_t *mctx, dns_dbimplementation_t **dbimp) 813{ 814 dns_dbimplementation_t *imp; 815 816 REQUIRE(name != NULL); 817 REQUIRE(dbimp != NULL && *dbimp == NULL); 818 819 RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); 820 821 RWLOCK(&implock, isc_rwlocktype_write); 822 imp = impfind(name); 823 if (imp != NULL) { 824 RWUNLOCK(&implock, isc_rwlocktype_write); 825 return (ISC_R_EXISTS); 826 } 827 828 imp = isc_mem_get(mctx, sizeof(dns_dbimplementation_t)); 829 if (imp == NULL) { 830 RWUNLOCK(&implock, isc_rwlocktype_write); 831 return (ISC_R_NOMEMORY); 832 } 833 imp->name = name; 834 imp->create = create; 835 imp->mctx = NULL; 836 imp->driverarg = driverarg; 837 isc_mem_attach(mctx, &imp->mctx); 838 ISC_LINK_INIT(imp, link); 839 ISC_LIST_APPEND(implementations, imp, link); 840 RWUNLOCK(&implock, isc_rwlocktype_write); 841 842 *dbimp = imp; 843 844 return (ISC_R_SUCCESS); 845} 846 847void 848dns_db_unregister(dns_dbimplementation_t **dbimp) { 849 dns_dbimplementation_t *imp; 850 isc_mem_t *mctx; 851 852 REQUIRE(dbimp != NULL && *dbimp != NULL); 853 854 RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); 855 856 imp = *dbimp; 857 *dbimp = NULL; 858 RWLOCK(&implock, isc_rwlocktype_write); 859 ISC_LIST_UNLINK(implementations, imp, link); 860 mctx = imp->mctx; 861 isc_mem_put(mctx, imp, sizeof(dns_dbimplementation_t)); 862 isc_mem_detach(&mctx); 863 RWUNLOCK(&implock, isc_rwlocktype_write); 864 ENSURE(*dbimp == NULL); 865} 866 867isc_result_t 868dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { 869 REQUIRE(DNS_DB_VALID(db)); 870 REQUIRE(dns_db_iszone(db) == ISC_TRUE); 871 REQUIRE(nodep != NULL && *nodep == NULL); 872 873 if (db->methods->getoriginnode != NULL) 874 return ((db->methods->getoriginnode)(db, nodep)); 875 876 return (ISC_R_NOTFOUND); 877} 878 879dns_stats_t * 880dns_db_getrrsetstats(dns_db_t *db) { 881 REQUIRE(DNS_DB_VALID(db)); 882 883 if (db->methods->getrrsetstats != NULL) 884 return ((db->methods->getrrsetstats)(db)); 885 886 return (NULL); 887} 888 889isc_result_t 890dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, 891 dns_hash_t *hash, isc_uint8_t *flags, 892 isc_uint16_t *iterations, 893 unsigned char *salt, size_t *salt_length) 894{ 895 REQUIRE(DNS_DB_VALID(db)); 896 REQUIRE(dns_db_iszone(db) == ISC_TRUE); 897 898 if (db->methods->getnsec3parameters != NULL) 899 return ((db->methods->getnsec3parameters)(db, version, hash, 900 flags, iterations, 901 salt, salt_length)); 902 903 return (ISC_R_NOTFOUND); 904} 905 906isc_result_t 907dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, 908 isc_stdtime_t resign) 909{ 910 if (db->methods->setsigningtime != NULL) 911 return ((db->methods->setsigningtime)(db, rdataset, resign)); 912 return (ISC_R_NOTIMPLEMENTED); 913} 914 915isc_result_t 916dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name) 917{ 918 if (db->methods->getsigningtime != NULL) 919 return ((db->methods->getsigningtime)(db, rdataset, name)); 920 return (ISC_R_NOTFOUND); 921} 922 923void 924dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) 925{ 926 if (db->methods->resigned != NULL) 927 (db->methods->resigned)(db, rdataset, version); 928} 929