2 * Copyright (C) 2004, 2005, 2007-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2001, 2003 Internet Software Consortium.
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.
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.
18 /* $Id: db.c,v 1.99.4.1 2011/10/23 20:12:07 vjs Exp $ */
28 #include <isc/buffer.h>
31 #include <isc/rwlock.h>
32 #include <isc/string.h>
35 #include <dns/callbacks.h>
36 #include <dns/clientinfo.h>
38 #include <dns/dbiterator.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>
50 struct dns_dbimplementation {
52 dns_dbcreatefunc_t create;
55 ISC_LINK(dns_dbimplementation_t) link;
59 *** Supported DB Implementations Registry
63 * Built in database implementations are registered here.
71 static ISC_LIST(dns_dbimplementation_t) implementations;
72 static isc_rwlock_t implock;
73 static isc_once_t once = ISC_ONCE_INIT;
75 static dns_dbimplementation_t rbtimp;
77 static dns_dbimplementation_t rbt64imp;
82 RUNTIME_CHECK(isc_rwlock_init(&implock, 0, 0) == ISC_R_SUCCESS);
85 rbtimp.create = dns_rbtdb_create;
87 rbtimp.driverarg = NULL;
88 ISC_LINK_INIT(&rbtimp, link);
91 rbt64imp.name = "rbt64";
92 rbt64imp.create = dns_rbtdb64_create;
94 rbt64imp.driverarg = NULL;
95 ISC_LINK_INIT(&rbt64imp, link);
98 ISC_LIST_INIT(implementations);
99 ISC_LIST_APPEND(implementations, &rbtimp, link);
101 ISC_LIST_APPEND(implementations, &rbt64imp, link);
105 static inline dns_dbimplementation_t *
106 impfind(const char *name) {
107 dns_dbimplementation_t *imp;
109 for (imp = ISC_LIST_HEAD(implementations);
111 imp = ISC_LIST_NEXT(imp, link))
112 if (strcasecmp(name, imp->name) == 0)
123 dns_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)
127 dns_dbimplementation_t *impinfo;
129 RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
132 * Create a new database using implementation 'db_type'.
135 REQUIRE(dbp != NULL && *dbp == NULL);
136 REQUIRE(dns_name_isabsolute(origin));
138 RWLOCK(&implock, isc_rwlocktype_read);
139 impinfo = impfind(db_type);
140 if (impinfo != NULL) {
142 result = ((impinfo->create)(mctx, origin, type,
144 impinfo->driverarg, dbp));
145 RWUNLOCK(&implock, isc_rwlocktype_read);
149 RWUNLOCK(&implock, isc_rwlocktype_read);
151 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
152 DNS_LOGMODULE_DB, ISC_LOG_ERROR,
153 "unsupported database type '%s'", db_type);
155 return (ISC_R_NOTFOUND);
159 dns_db_attach(dns_db_t *source, dns_db_t **targetp) {
162 * Attach *targetp to source.
165 REQUIRE(DNS_DB_VALID(source));
166 REQUIRE(targetp != NULL && *targetp == NULL);
168 (source->methods->attach)(source, targetp);
170 ENSURE(*targetp == source);
174 dns_db_detach(dns_db_t **dbp) {
177 * Detach *dbp from its database.
180 REQUIRE(dbp != NULL);
181 REQUIRE(DNS_DB_VALID(*dbp));
183 ((*dbp)->methods->detach)(dbp);
185 ENSURE(*dbp == NULL);
189 dns_db_ondestroy(dns_db_t *db, isc_task_t *task, isc_event_t **eventp)
191 REQUIRE(DNS_DB_VALID(db));
193 return (isc_ondestroy_register(&db->ondest, task, eventp));
198 dns_db_iscache(dns_db_t *db) {
201 * Does 'db' have cache semantics?
204 REQUIRE(DNS_DB_VALID(db));
206 if ((db->attributes & DNS_DBATTR_CACHE) != 0)
213 dns_db_iszone(dns_db_t *db) {
216 * Does 'db' have zone semantics?
219 REQUIRE(DNS_DB_VALID(db));
221 if ((db->attributes & (DNS_DBATTR_CACHE|DNS_DBATTR_STUB)) == 0)
228 dns_db_isstub(dns_db_t *db) {
231 * Does 'db' have stub semantics?
234 REQUIRE(DNS_DB_VALID(db));
236 if ((db->attributes & DNS_DBATTR_STUB) != 0)
243 dns_db_isdnssec(dns_db_t *db) {
246 * Is 'db' secure or partially secure?
249 REQUIRE(DNS_DB_VALID(db));
250 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
252 if (db->methods->isdnssec != NULL)
253 return ((db->methods->isdnssec)(db));
254 return ((db->methods->issecure)(db));
258 dns_db_issecure(dns_db_t *db) {
264 REQUIRE(DNS_DB_VALID(db));
265 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
267 return ((db->methods->issecure)(db));
271 dns_db_ispersistent(dns_db_t *db) {
274 * Is 'db' persistent?
277 REQUIRE(DNS_DB_VALID(db));
279 return ((db->methods->ispersistent)(db));
283 dns_db_origin(dns_db_t *db) {
285 * The origin of the database.
288 REQUIRE(DNS_DB_VALID(db));
290 return (&db->origin);
294 dns_db_class(dns_db_t *db) {
296 * The class of the database.
299 REQUIRE(DNS_DB_VALID(db));
301 return (db->rdclass);
306 dns_db_beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp,
307 dns_dbload_t **dbloadp) {
309 * Begin loading 'db'.
312 REQUIRE(DNS_DB_VALID(db));
313 REQUIRE(addp != NULL && *addp == NULL);
314 REQUIRE(dbloadp != NULL && *dbloadp == NULL);
316 return ((db->methods->beginload)(db, addp, dbloadp));
320 dns_db_endload(dns_db_t *db, dns_dbload_t **dbloadp) {
322 * Finish loading 'db'.
325 REQUIRE(DNS_DB_VALID(db));
326 REQUIRE(dbloadp != NULL && *dbloadp != NULL);
328 return ((db->methods->endload)(db, dbloadp));
332 dns_db_load(dns_db_t *db, const char *filename) {
333 return (dns_db_load3(db, filename, dns_masterformat_text, 0));
337 dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format) {
338 return (dns_db_load3(db, filename, format, 0));
342 dns_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;
348 * Load master file 'filename' into 'db'.
351 REQUIRE(DNS_DB_VALID(db));
353 if ((db->attributes & DNS_DBATTR_CACHE) != 0)
354 options |= DNS_MASTER_AGETTL;
356 dns_rdatacallbacks_init(&callbacks);
358 result = dns_db_beginload(db, &callbacks.add, &callbacks.add_private);
359 if (result != ISC_R_SUCCESS)
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);
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.
370 if (eresult != ISC_R_SUCCESS &&
371 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
378 dns_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));
384 dns_db_dump2(dns_db_t *db, dns_dbversion_t *version, const char *filename,
385 dns_masterformat_t masterformat) {
387 * Dump 'db' into master file 'filename' in the 'masterformat' format.
388 * XXXJT: is it okay to modify the interface to the existing "dump"
392 REQUIRE(DNS_DB_VALID(db));
394 return ((db->methods->dump)(db, version, filename, masterformat));
403 dns_db_currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
406 * Open the current version for reading.
409 REQUIRE(DNS_DB_VALID(db));
410 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
411 REQUIRE(versionp != NULL && *versionp == NULL);
413 (db->methods->currentversion)(db, versionp);
417 dns_db_newversion(dns_db_t *db, dns_dbversion_t **versionp) {
420 * Open a new version for reading and writing.
423 REQUIRE(DNS_DB_VALID(db));
424 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
425 REQUIRE(versionp != NULL && *versionp == NULL);
427 return ((db->methods->newversion)(db, versionp));
431 dns_db_attachversion(dns_db_t *db, dns_dbversion_t *source,
432 dns_dbversion_t **targetp)
435 * Attach '*targetp' to 'source'.
438 REQUIRE(DNS_DB_VALID(db));
439 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
440 REQUIRE(source != NULL);
441 REQUIRE(targetp != NULL && *targetp == NULL);
443 (db->methods->attachversion)(db, source, targetp);
445 ENSURE(*targetp != NULL);
449 dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
450 isc_boolean_t commit)
454 * Close version '*versionp'.
457 REQUIRE(DNS_DB_VALID(db));
458 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
459 REQUIRE(versionp != NULL && *versionp != NULL);
461 (db->methods->closeversion)(db, versionp, commit);
463 ENSURE(*versionp == NULL);
471 dns_db_findnode(dns_db_t *db, dns_name_t *name,
472 isc_boolean_t create, dns_dbnode_t **nodep)
476 * Find the node with name 'name'.
479 REQUIRE(DNS_DB_VALID(db));
480 REQUIRE(nodep != NULL && *nodep == NULL);
482 if (db->methods->findnode != NULL)
483 return ((db->methods->findnode)(db, name, create, nodep));
485 return ((db->methods->findnodeext)(db, name, create,
490 dns_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)
495 * Find the node with name 'name', passing 'arg' to the database
499 REQUIRE(DNS_DB_VALID(db));
500 REQUIRE(nodep != NULL && *nodep == NULL);
502 if (db->methods->findnodeext != NULL)
503 return ((db->methods->findnodeext)(db, name, create,
504 methods, clientinfo, nodep));
506 return ((db->methods->findnode)(db, name, create, nodep));
510 dns_db_findnsec3node(dns_db_t *db, dns_name_t *name,
511 isc_boolean_t create, dns_dbnode_t **nodep)
515 * Find the node with name 'name'.
518 REQUIRE(DNS_DB_VALID(db));
519 REQUIRE(nodep != NULL && *nodep == NULL);
521 return ((db->methods->findnsec3node)(db, name, create, nodep));
525 dns_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)
531 * Find the best match for 'name' and 'type' in version 'version'
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)));
546 if (db->methods->find != NULL)
547 return ((db->methods->find)(db, name, version, type,
548 options, now, nodep, foundname,
549 rdataset, sigrdataset));
551 return ((db->methods->findext)(db, name, version, type,
552 options, now, nodep, foundname,
554 rdataset, sigrdataset));
558 dns_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)
566 * Find the best match for 'name' and 'type' in version 'version'
567 * of 'db', passing in 'arg'.
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)));
581 if (db->methods->findext != NULL)
582 return ((db->methods->findext)(db, name, version, type,
583 options, now, nodep, foundname,
585 rdataset, sigrdataset));
587 return ((db->methods->find)(db, name, version, type,
588 options, now, nodep, foundname,
589 rdataset, sigrdataset));
593 dns_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)
599 * Find the deepest known zonecut which encloses 'name' in 'db'.
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)));
610 return ((db->methods->findzonecut)(db, name, options, now, nodep,
611 foundname, rdataset, sigrdataset));
615 dns_db_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
618 * Attach *targetp to source.
621 REQUIRE(DNS_DB_VALID(db));
622 REQUIRE(source != NULL);
623 REQUIRE(targetp != NULL && *targetp == NULL);
625 (db->methods->attachnode)(db, source, targetp);
629 dns_db_detachnode(dns_db_t *db, dns_dbnode_t **nodep) {
632 * Detach *nodep from its node.
635 REQUIRE(DNS_DB_VALID(db));
636 REQUIRE(nodep != NULL && *nodep != NULL);
638 (db->methods->detachnode)(db, nodep);
640 ENSURE(*nodep == NULL);
644 dns_db_transfernode(dns_db_t *db, dns_dbnode_t **sourcep,
645 dns_dbnode_t **targetp)
647 REQUIRE(DNS_DB_VALID(db));
648 REQUIRE(targetp != NULL && *targetp == NULL);
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
654 REQUIRE(sourcep != NULL && *sourcep != NULL);
658 if (db->methods->transfernode == NULL) {
662 (db->methods->transfernode)(db, sourcep, targetp);
664 ENSURE(*sourcep == NULL);
668 dns_db_expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
671 * Mark as stale all records at 'node' which expire at or before 'now'.
674 REQUIRE(DNS_DB_VALID(db));
675 REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0);
676 REQUIRE(node != NULL);
678 return ((db->methods->expirenode)(db, node, now));
682 dns_db_printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
684 * Print a textual representation of the contents of the node to
688 REQUIRE(DNS_DB_VALID(db));
689 REQUIRE(node != NULL);
691 (db->methods->printnode)(db, node, out);
695 *** DB Iterator Creation
699 dns_db_createiterator(dns_db_t *db, unsigned int flags,
700 dns_dbiterator_t **iteratorp)
703 * Create an iterator for version 'version' of 'db'.
706 REQUIRE(DNS_DB_VALID(db));
707 REQUIRE(iteratorp != NULL && *iteratorp == NULL);
709 return (db->methods->createiterator(db, flags, iteratorp));
717 dns_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)
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)));
732 return ((db->methods->findrdataset)(db, node, version, type,
733 covers, now, rdataset,
738 dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
739 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
742 * Make '*iteratorp' an rdataset iteratator for all rdatasets at
743 * 'node' in version 'version' of 'db'.
746 REQUIRE(DNS_DB_VALID(db));
747 REQUIRE(iteratorp != NULL && *iteratorp == NULL);
749 return ((db->methods->allrdatasets)(db, node, version, now,
754 dns_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)
759 * Add 'rdataset' to 'node' in version 'version' of 'db'.
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)));
776 return ((db->methods->addrdataset)(db, node, version, now, rdataset,
777 options, addedrdataset));
781 dns_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)
786 * Remove any rdata in 'rdataset' from 'node' in version 'version' of
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)));
800 return ((db->methods->subtractrdataset)(db, node, version, rdataset,
801 options, newrdataset));
805 dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
806 dns_dbversion_t *version, dns_rdatatype_t type,
807 dns_rdatatype_t covers)
810 * Make it so that no rdataset of type 'type' exists at 'node' in
811 * version version 'version' of 'db'.
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));
819 return ((db->methods->deleterdataset)(db, node, version,
824 dns_db_overmem(dns_db_t *db, isc_boolean_t overmem) {
826 REQUIRE(DNS_DB_VALID(db));
828 (db->methods->overmem)(db, overmem);
832 dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, isc_uint32_t *serialp)
835 dns_dbnode_t *node = NULL;
836 dns_rdataset_t rdataset;
837 dns_rdata_t rdata = DNS_RDATA_INIT;
840 REQUIRE(dns_db_iszone(db) || dns_db_isstub(db));
842 result = dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node);
843 if (result != ISC_R_SUCCESS)
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)
852 result = dns_rdataset_first(&rdataset);
853 if (result != ISC_R_SUCCESS)
855 dns_rdataset_current(&rdataset, &rdata);
856 result = dns_rdataset_next(&rdataset);
857 INSIST(result == ISC_R_NOMORE);
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);
865 result = ISC_R_SUCCESS;
868 dns_rdataset_disassociate(&rdataset);
871 dns_db_detachnode(db, &node);
876 dns_db_nodecount(dns_db_t *db) {
877 REQUIRE(DNS_DB_VALID(db));
879 return ((db->methods->nodecount)(db));
883 dns_db_settask(dns_db_t *db, isc_task_t *task) {
884 REQUIRE(DNS_DB_VALID(db));
886 (db->methods->settask)(db, task);
890 dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg,
891 isc_mem_t *mctx, dns_dbimplementation_t **dbimp)
893 dns_dbimplementation_t *imp;
895 REQUIRE(name != NULL);
896 REQUIRE(dbimp != NULL && *dbimp == NULL);
898 RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
900 RWLOCK(&implock, isc_rwlocktype_write);
903 RWUNLOCK(&implock, isc_rwlocktype_write);
904 return (ISC_R_EXISTS);
907 imp = isc_mem_get(mctx, sizeof(dns_dbimplementation_t));
909 RWUNLOCK(&implock, isc_rwlocktype_write);
910 return (ISC_R_NOMEMORY);
913 imp->create = create;
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);
923 return (ISC_R_SUCCESS);
927 dns_db_unregister(dns_dbimplementation_t **dbimp) {
928 dns_dbimplementation_t *imp;
931 REQUIRE(dbimp != NULL && *dbimp != NULL);
933 RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
937 RWLOCK(&implock, isc_rwlocktype_write);
938 ISC_LIST_UNLINK(implementations, imp, link);
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);
947 dns_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);
952 if (db->methods->getoriginnode != NULL)
953 return ((db->methods->getoriginnode)(db, nodep));
955 return (ISC_R_NOTFOUND);
959 dns_db_getrrsetstats(dns_db_t *db) {
960 REQUIRE(DNS_DB_VALID(db));
962 if (db->methods->getrrsetstats != NULL)
963 return ((db->methods->getrrsetstats)(db));
969 dns_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)
974 REQUIRE(DNS_DB_VALID(db));
975 REQUIRE(dns_db_iszone(db) == ISC_TRUE);
977 if (db->methods->getnsec3parameters != NULL)
978 return ((db->methods->getnsec3parameters)(db, version, hash,
982 return (ISC_R_NOTFOUND);
986 dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
987 isc_stdtime_t resign)
989 if (db->methods->setsigningtime != NULL)
990 return ((db->methods->setsigningtime)(db, rdataset, resign));
991 return (ISC_R_NOTIMPLEMENTED);
995 dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name)
997 if (db->methods->getsigningtime != NULL)
998 return ((db->methods->getsigningtime)(db, rdataset, name));
999 return (ISC_R_NOTFOUND);
1003 dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset,
1004 dns_dbversion_t *version)
1006 if (db->methods->resigned != NULL)
1007 (db->methods->resigned)(db, rdataset, version);
1011 dns_db_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st)
1013 if (db->methods->rpz_enabled != NULL)
1014 return ((db->methods->rpz_enabled)(db, st));
1015 return (ISC_R_SUCCESS);
1019 dns_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)
1024 if (db->methods->rpz_findips != NULL)
1025 (db->methods->rpz_findips)(rpz, rpz_type, zone, db, version,
1026 ardataset, st, query_qname);