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