1 /* $NetBSD: db.c,v 1.7 2014/12/10 04:37:58 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2001, 2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
30 #include <isc/buffer.h>
33 #include <isc/rwlock.h>
34 #include <isc/string.h>
37 #include <dns/callbacks.h>
38 #include <dns/clientinfo.h>
40 #include <dns/dbiterator.h>
42 #include <dns/master.h>
43 #include <dns/rdata.h>
44 #include <dns/rdataset.h>
45 #include <dns/rdatasetiter.h>
46 #include <dns/result.h>
52 struct dns_dbimplementation
{
54 dns_dbcreatefunc_t create
;
57 ISC_LINK(dns_dbimplementation_t
) link
;
61 *** Supported DB Implementations Registry
65 * 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
;
76 static dns_dbimplementation_t rbt64imp
;
80 RUNTIME_CHECK(isc_rwlock_init(&implock
, 0, 0) == ISC_R_SUCCESS
);
83 rbtimp
.create
= dns_rbtdb_create
;
85 rbtimp
.driverarg
= NULL
;
86 ISC_LINK_INIT(&rbtimp
, link
);
88 rbt64imp
.name
= "rbt64";
89 rbt64imp
.create
= dns_rbtdb64_create
;
91 rbt64imp
.driverarg
= NULL
;
92 ISC_LINK_INIT(&rbt64imp
, link
);
94 ISC_LIST_INIT(implementations
);
95 ISC_LIST_APPEND(implementations
, &rbtimp
, link
);
96 ISC_LIST_APPEND(implementations
, &rbt64imp
, link
);
99 static inline dns_dbimplementation_t
*
100 impfind(const char *name
) {
101 dns_dbimplementation_t
*imp
;
103 for (imp
= ISC_LIST_HEAD(implementations
);
105 imp
= ISC_LIST_NEXT(imp
, link
))
106 if (strcasecmp(name
, imp
->name
) == 0)
117 dns_db_create(isc_mem_t
*mctx
, const char *db_type
, dns_name_t
*origin
,
118 dns_dbtype_t type
, dns_rdataclass_t rdclass
,
119 unsigned int argc
, char *argv
[], dns_db_t
**dbp
)
121 dns_dbimplementation_t
*impinfo
;
123 RUNTIME_CHECK(isc_once_do(&once
, initialize
) == ISC_R_SUCCESS
);
126 * Create a new database using implementation 'db_type'.
129 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
130 REQUIRE(dns_name_isabsolute(origin
));
132 RWLOCK(&implock
, isc_rwlocktype_read
);
133 impinfo
= impfind(db_type
);
134 if (impinfo
!= NULL
) {
136 result
= ((impinfo
->create
)(mctx
, origin
, type
,
138 impinfo
->driverarg
, dbp
));
139 RWUNLOCK(&implock
, isc_rwlocktype_read
);
143 RWUNLOCK(&implock
, isc_rwlocktype_read
);
145 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
146 DNS_LOGMODULE_DB
, ISC_LOG_ERROR
,
147 "unsupported database type '%s'", db_type
);
149 return (ISC_R_NOTFOUND
);
153 dns_db_attach(dns_db_t
*source
, dns_db_t
**targetp
) {
156 * Attach *targetp to source.
159 REQUIRE(DNS_DB_VALID(source
));
160 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
162 (source
->methods
->attach
)(source
, targetp
);
164 ENSURE(*targetp
== source
);
168 dns_db_detach(dns_db_t
**dbp
) {
171 * Detach *dbp from its database.
174 REQUIRE(dbp
!= NULL
);
175 REQUIRE(DNS_DB_VALID(*dbp
));
177 ((*dbp
)->methods
->detach
)(dbp
);
179 ENSURE(*dbp
== NULL
);
183 dns_db_ondestroy(dns_db_t
*db
, isc_task_t
*task
, isc_event_t
**eventp
)
185 REQUIRE(DNS_DB_VALID(db
));
187 return (isc_ondestroy_register(&db
->ondest
, task
, eventp
));
192 dns_db_iscache(dns_db_t
*db
) {
195 * Does 'db' have cache semantics?
198 REQUIRE(DNS_DB_VALID(db
));
200 if ((db
->attributes
& DNS_DBATTR_CACHE
) != 0)
207 dns_db_iszone(dns_db_t
*db
) {
210 * Does 'db' have zone semantics?
213 REQUIRE(DNS_DB_VALID(db
));
215 if ((db
->attributes
& (DNS_DBATTR_CACHE
|DNS_DBATTR_STUB
)) == 0)
222 dns_db_isstub(dns_db_t
*db
) {
225 * Does 'db' have stub semantics?
228 REQUIRE(DNS_DB_VALID(db
));
230 if ((db
->attributes
& DNS_DBATTR_STUB
) != 0)
237 dns_db_isdnssec(dns_db_t
*db
) {
240 * Is 'db' secure or partially secure?
243 REQUIRE(DNS_DB_VALID(db
));
244 REQUIRE((db
->attributes
& DNS_DBATTR_CACHE
) == 0);
246 if (db
->methods
->isdnssec
!= NULL
)
247 return ((db
->methods
->isdnssec
)(db
));
248 return ((db
->methods
->issecure
)(db
));
252 dns_db_issecure(dns_db_t
*db
) {
258 REQUIRE(DNS_DB_VALID(db
));
259 REQUIRE((db
->attributes
& DNS_DBATTR_CACHE
) == 0);
261 return ((db
->methods
->issecure
)(db
));
265 dns_db_ispersistent(dns_db_t
*db
) {
268 * Is 'db' persistent?
271 REQUIRE(DNS_DB_VALID(db
));
273 return ((db
->methods
->ispersistent
)(db
));
277 dns_db_origin(dns_db_t
*db
) {
279 * The origin of the database.
282 REQUIRE(DNS_DB_VALID(db
));
284 return (&db
->origin
);
288 dns_db_class(dns_db_t
*db
) {
290 * The class of the database.
293 REQUIRE(DNS_DB_VALID(db
));
295 return (db
->rdclass
);
299 dns_db_beginload(dns_db_t
*db
, dns_rdatacallbacks_t
*callbacks
) {
301 * Begin loading 'db'.
304 REQUIRE(DNS_DB_VALID(db
));
305 REQUIRE(DNS_CALLBACK_VALID(callbacks
));
307 return ((db
->methods
->beginload
)(db
, callbacks
));
311 dns_db_endload(dns_db_t
*db
, dns_rdatacallbacks_t
*callbacks
) {
313 * Finish loading 'db'.
316 REQUIRE(DNS_DB_VALID(db
));
317 REQUIRE(DNS_CALLBACK_VALID(callbacks
));
318 REQUIRE(callbacks
->add_private
!= NULL
);
320 return ((db
->methods
->endload
)(db
, callbacks
));
324 dns_db_load(dns_db_t
*db
, const char *filename
) {
325 return (dns_db_load3(db
, filename
, dns_masterformat_text
, 0));
329 dns_db_load2(dns_db_t
*db
, const char *filename
, dns_masterformat_t format
) {
330 return (dns_db_load3(db
, filename
, format
, 0));
334 dns_db_load3(dns_db_t
*db
, const char *filename
, dns_masterformat_t format
,
335 unsigned int options
) {
336 isc_result_t result
, eresult
;
337 dns_rdatacallbacks_t callbacks
;
340 * Load master file 'filename' into 'db'.
343 REQUIRE(DNS_DB_VALID(db
));
345 if ((db
->attributes
& DNS_DBATTR_CACHE
) != 0)
346 options
|= DNS_MASTER_AGETTL
;
348 dns_rdatacallbacks_init(&callbacks
);
349 result
= dns_db_beginload(db
, &callbacks
);
350 if (result
!= ISC_R_SUCCESS
)
352 result
= dns_master_loadfile2(filename
, &db
->origin
, &db
->origin
,
353 db
->rdclass
, options
,
354 &callbacks
, db
->mctx
, format
);
355 eresult
= dns_db_endload(db
, &callbacks
);
357 * We always call dns_db_endload(), but we only want to return its
358 * result if dns_master_loadfile() succeeded. If dns_master_loadfile()
359 * failed, we want to return the result code it gave us.
361 if (eresult
!= ISC_R_SUCCESS
&&
362 (result
== ISC_R_SUCCESS
|| result
== DNS_R_SEENINCLUDE
))
369 dns_db_serialize(dns_db_t
*db
, dns_dbversion_t
*version
, FILE *file
) {
370 REQUIRE(DNS_DB_VALID(db
));
371 if (db
->methods
->serialize
== NULL
)
372 return (ISC_R_NOTIMPLEMENTED
);
373 return ((db
->methods
->serialize
)(db
, version
, file
));
377 dns_db_dump(dns_db_t
*db
, dns_dbversion_t
*version
, const char *filename
) {
378 return ((db
->methods
->dump
)(db
, version
, filename
,
379 dns_masterformat_text
));
383 dns_db_dump2(dns_db_t
*db
, dns_dbversion_t
*version
, const char *filename
,
384 dns_masterformat_t masterformat
) {
386 * Dump 'db' into master file 'filename' in the 'masterformat' format.
387 * XXXJT: is it okay to modify the interface to the existing "dump"
391 REQUIRE(DNS_DB_VALID(db
));
393 return ((db
->methods
->dump
)(db
, version
, filename
, masterformat
));
401 dns_db_currentversion(dns_db_t
*db
, dns_dbversion_t
**versionp
) {
404 * Open the current version for reading.
407 REQUIRE(DNS_DB_VALID(db
));
408 REQUIRE((db
->attributes
& DNS_DBATTR_CACHE
) == 0);
409 REQUIRE(versionp
!= NULL
&& *versionp
== NULL
);
411 (db
->methods
->currentversion
)(db
, versionp
);
415 dns_db_newversion(dns_db_t
*db
, dns_dbversion_t
**versionp
) {
418 * Open a new version for reading and writing.
421 REQUIRE(DNS_DB_VALID(db
));
422 REQUIRE((db
->attributes
& DNS_DBATTR_CACHE
) == 0);
423 REQUIRE(versionp
!= NULL
&& *versionp
== NULL
);
425 return ((db
->methods
->newversion
)(db
, versionp
));
429 dns_db_attachversion(dns_db_t
*db
, dns_dbversion_t
*source
,
430 dns_dbversion_t
**targetp
)
433 * Attach '*targetp' to 'source'.
436 REQUIRE(DNS_DB_VALID(db
));
437 REQUIRE((db
->attributes
& DNS_DBATTR_CACHE
) == 0);
438 REQUIRE(source
!= NULL
);
439 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
441 (db
->methods
->attachversion
)(db
, source
, targetp
);
443 ENSURE(*targetp
!= NULL
);
447 dns_db_closeversion(dns_db_t
*db
, dns_dbversion_t
**versionp
,
448 isc_boolean_t commit
)
452 * Close version '*versionp'.
455 REQUIRE(DNS_DB_VALID(db
));
456 REQUIRE((db
->attributes
& DNS_DBATTR_CACHE
) == 0);
457 REQUIRE(versionp
!= NULL
&& *versionp
!= NULL
);
459 (db
->methods
->closeversion
)(db
, versionp
, commit
);
461 ENSURE(*versionp
== NULL
);
469 dns_db_findnode(dns_db_t
*db
, dns_name_t
*name
,
470 isc_boolean_t create
, dns_dbnode_t
**nodep
)
474 * Find the node with name 'name'.
477 REQUIRE(DNS_DB_VALID(db
));
478 REQUIRE(nodep
!= NULL
&& *nodep
== NULL
);
480 if (db
->methods
->findnode
!= NULL
)
481 return ((db
->methods
->findnode
)(db
, name
, create
, nodep
));
483 return ((db
->methods
->findnodeext
)(db
, name
, create
,
488 dns_db_findnodeext(dns_db_t
*db
, dns_name_t
*name
,
489 isc_boolean_t create
, dns_clientinfomethods_t
*methods
,
490 dns_clientinfo_t
*clientinfo
, dns_dbnode_t
**nodep
)
493 * Find the node with name 'name', passing 'arg' to the database
497 REQUIRE(DNS_DB_VALID(db
));
498 REQUIRE(nodep
!= NULL
&& *nodep
== NULL
);
500 if (db
->methods
->findnodeext
!= NULL
)
501 return ((db
->methods
->findnodeext
)(db
, name
, create
,
502 methods
, clientinfo
, nodep
));
504 return ((db
->methods
->findnode
)(db
, name
, create
, nodep
));
508 dns_db_findnsec3node(dns_db_t
*db
, dns_name_t
*name
,
509 isc_boolean_t create
, dns_dbnode_t
**nodep
)
513 * Find the node with name 'name'.
516 REQUIRE(DNS_DB_VALID(db
));
517 REQUIRE(nodep
!= NULL
&& *nodep
== NULL
);
519 return ((db
->methods
->findnsec3node
)(db
, name
, create
, nodep
));
523 dns_db_find(dns_db_t
*db
, dns_name_t
*name
, dns_dbversion_t
*version
,
524 dns_rdatatype_t type
, unsigned int options
, isc_stdtime_t now
,
525 dns_dbnode_t
**nodep
, dns_name_t
*foundname
,
526 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
529 * Find the best match for 'name' and 'type' in version 'version'
533 REQUIRE(DNS_DB_VALID(db
));
534 REQUIRE(type
!= dns_rdatatype_rrsig
);
535 REQUIRE(nodep
== NULL
|| (nodep
!= NULL
&& *nodep
== NULL
));
536 REQUIRE(dns_name_hasbuffer(foundname
));
537 REQUIRE(rdataset
== NULL
||
538 (DNS_RDATASET_VALID(rdataset
) &&
539 ! dns_rdataset_isassociated(rdataset
)));
540 REQUIRE(sigrdataset
== NULL
||
541 (DNS_RDATASET_VALID(sigrdataset
) &&
542 ! dns_rdataset_isassociated(sigrdataset
)));
544 if (db
->methods
->find
!= NULL
)
545 return ((db
->methods
->find
)(db
, name
, version
, type
,
546 options
, now
, nodep
, foundname
,
547 rdataset
, sigrdataset
));
549 return ((db
->methods
->findext
)(db
, name
, version
, type
,
550 options
, now
, nodep
, foundname
,
552 rdataset
, sigrdataset
));
556 dns_db_findext(dns_db_t
*db
, dns_name_t
*name
, dns_dbversion_t
*version
,
557 dns_rdatatype_t type
, unsigned int options
, isc_stdtime_t now
,
558 dns_dbnode_t
**nodep
, dns_name_t
*foundname
,
559 dns_clientinfomethods_t
*methods
, dns_clientinfo_t
*clientinfo
,
560 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
564 * Find the best match for 'name' and 'type' in version 'version'
565 * of 'db', passing in 'arg'.
568 REQUIRE(DNS_DB_VALID(db
));
569 REQUIRE(type
!= dns_rdatatype_rrsig
);
570 REQUIRE(nodep
== NULL
|| (nodep
!= NULL
&& *nodep
== NULL
));
571 REQUIRE(dns_name_hasbuffer(foundname
));
572 REQUIRE(rdataset
== NULL
||
573 (DNS_RDATASET_VALID(rdataset
) &&
574 ! dns_rdataset_isassociated(rdataset
)));
575 REQUIRE(sigrdataset
== NULL
||
576 (DNS_RDATASET_VALID(sigrdataset
) &&
577 ! dns_rdataset_isassociated(sigrdataset
)));
579 if (db
->methods
->findext
!= NULL
)
580 return ((db
->methods
->findext
)(db
, name
, version
, type
,
581 options
, now
, nodep
, foundname
,
583 rdataset
, sigrdataset
));
585 return ((db
->methods
->find
)(db
, name
, version
, type
,
586 options
, now
, nodep
, foundname
,
587 rdataset
, sigrdataset
));
591 dns_db_findzonecut(dns_db_t
*db
, dns_name_t
*name
,
592 unsigned int options
, isc_stdtime_t now
,
593 dns_dbnode_t
**nodep
, dns_name_t
*foundname
,
594 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
597 * Find the deepest known zonecut which encloses 'name' in 'db'.
600 REQUIRE(DNS_DB_VALID(db
));
601 REQUIRE((db
->attributes
& DNS_DBATTR_CACHE
) != 0);
602 REQUIRE(nodep
== NULL
|| (nodep
!= NULL
&& *nodep
== NULL
));
603 REQUIRE(dns_name_hasbuffer(foundname
));
604 REQUIRE(sigrdataset
== NULL
||
605 (DNS_RDATASET_VALID(sigrdataset
) &&
606 ! dns_rdataset_isassociated(sigrdataset
)));
608 return ((db
->methods
->findzonecut
)(db
, name
, options
, now
, nodep
,
609 foundname
, rdataset
, sigrdataset
));
613 dns_db_attachnode(dns_db_t
*db
, dns_dbnode_t
*source
, dns_dbnode_t
**targetp
) {
616 * Attach *targetp to source.
619 REQUIRE(DNS_DB_VALID(db
));
620 REQUIRE(source
!= NULL
);
621 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
623 (db
->methods
->attachnode
)(db
, source
, targetp
);
627 dns_db_detachnode(dns_db_t
*db
, dns_dbnode_t
**nodep
) {
630 * Detach *nodep from its node.
633 REQUIRE(DNS_DB_VALID(db
));
634 REQUIRE(nodep
!= NULL
&& *nodep
!= NULL
);
636 (db
->methods
->detachnode
)(db
, nodep
);
638 ENSURE(*nodep
== NULL
);
642 dns_db_transfernode(dns_db_t
*db
, dns_dbnode_t
**sourcep
,
643 dns_dbnode_t
**targetp
)
645 REQUIRE(DNS_DB_VALID(db
));
646 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
648 * This doesn't check the implementation magic. If we find that
649 * we need such checks in future then this will be done in the
652 REQUIRE(sourcep
!= NULL
&& *sourcep
!= NULL
);
656 if (db
->methods
->transfernode
== NULL
) {
660 (db
->methods
->transfernode
)(db
, sourcep
, targetp
);
662 ENSURE(*sourcep
== NULL
);
666 dns_db_expirenode(dns_db_t
*db
, dns_dbnode_t
*node
, isc_stdtime_t now
) {
669 * Mark as stale all records at 'node' which expire at or before 'now'.
672 REQUIRE(DNS_DB_VALID(db
));
673 REQUIRE((db
->attributes
& DNS_DBATTR_CACHE
) != 0);
674 REQUIRE(node
!= NULL
);
676 return ((db
->methods
->expirenode
)(db
, node
, now
));
680 dns_db_printnode(dns_db_t
*db
, dns_dbnode_t
*node
, FILE *out
) {
682 * Print a textual representation of the contents of the node to
686 REQUIRE(DNS_DB_VALID(db
));
687 REQUIRE(node
!= NULL
);
689 (db
->methods
->printnode
)(db
, node
, out
);
693 *** DB Iterator Creation
697 dns_db_createiterator(dns_db_t
*db
, unsigned int flags
,
698 dns_dbiterator_t
**iteratorp
)
701 * Create an iterator for version 'version' of 'db'.
704 REQUIRE(DNS_DB_VALID(db
));
705 REQUIRE(iteratorp
!= NULL
&& *iteratorp
== NULL
);
707 return (db
->methods
->createiterator(db
, flags
, iteratorp
));
715 dns_db_findrdataset(dns_db_t
*db
, dns_dbnode_t
*node
, dns_dbversion_t
*version
,
716 dns_rdatatype_t type
, dns_rdatatype_t covers
,
717 isc_stdtime_t now
, dns_rdataset_t
*rdataset
,
718 dns_rdataset_t
*sigrdataset
)
720 REQUIRE(DNS_DB_VALID(db
));
721 REQUIRE(node
!= NULL
);
722 REQUIRE(DNS_RDATASET_VALID(rdataset
));
723 REQUIRE(! dns_rdataset_isassociated(rdataset
));
724 REQUIRE(covers
== 0 || type
== dns_rdatatype_rrsig
);
725 REQUIRE(type
!= dns_rdatatype_any
);
726 REQUIRE(sigrdataset
== NULL
||
727 (DNS_RDATASET_VALID(sigrdataset
) &&
728 ! dns_rdataset_isassociated(sigrdataset
)));
730 return ((db
->methods
->findrdataset
)(db
, node
, version
, type
,
731 covers
, now
, rdataset
,
736 dns_db_allrdatasets(dns_db_t
*db
, dns_dbnode_t
*node
, dns_dbversion_t
*version
,
737 isc_stdtime_t now
, dns_rdatasetiter_t
**iteratorp
)
740 * Make '*iteratorp' an rdataset iteratator for all rdatasets at
741 * 'node' in version 'version' of 'db'.
744 REQUIRE(DNS_DB_VALID(db
));
745 REQUIRE(iteratorp
!= NULL
&& *iteratorp
== NULL
);
747 return ((db
->methods
->allrdatasets
)(db
, node
, version
, now
,
752 dns_db_addrdataset(dns_db_t
*db
, dns_dbnode_t
*node
, dns_dbversion_t
*version
,
753 isc_stdtime_t now
, dns_rdataset_t
*rdataset
,
754 unsigned int options
, dns_rdataset_t
*addedrdataset
)
757 * Add 'rdataset' to 'node' in version 'version' of 'db'.
760 REQUIRE(DNS_DB_VALID(db
));
761 REQUIRE(node
!= NULL
);
762 REQUIRE(((db
->attributes
& DNS_DBATTR_CACHE
) == 0 && version
!= NULL
)||
763 ((db
->attributes
& DNS_DBATTR_CACHE
) != 0 &&
764 version
== NULL
&& (options
& DNS_DBADD_MERGE
) == 0));
765 REQUIRE((options
& DNS_DBADD_EXACT
) == 0 ||
766 (options
& DNS_DBADD_MERGE
) != 0);
767 REQUIRE(DNS_RDATASET_VALID(rdataset
));
768 REQUIRE(dns_rdataset_isassociated(rdataset
));
769 REQUIRE(rdataset
->rdclass
== db
->rdclass
);
770 REQUIRE(addedrdataset
== NULL
||
771 (DNS_RDATASET_VALID(addedrdataset
) &&
772 ! dns_rdataset_isassociated(addedrdataset
)));
774 return ((db
->methods
->addrdataset
)(db
, node
, version
, now
, rdataset
,
775 options
, addedrdataset
));
779 dns_db_subtractrdataset(dns_db_t
*db
, dns_dbnode_t
*node
,
780 dns_dbversion_t
*version
, dns_rdataset_t
*rdataset
,
781 unsigned int options
, dns_rdataset_t
*newrdataset
)
784 * Remove any rdata in 'rdataset' from 'node' in version 'version' of
788 REQUIRE(DNS_DB_VALID(db
));
789 REQUIRE(node
!= NULL
);
790 REQUIRE((db
->attributes
& DNS_DBATTR_CACHE
) == 0 && version
!= NULL
);
791 REQUIRE(DNS_RDATASET_VALID(rdataset
));
792 REQUIRE(dns_rdataset_isassociated(rdataset
));
793 REQUIRE(rdataset
->rdclass
== db
->rdclass
);
794 REQUIRE(newrdataset
== NULL
||
795 (DNS_RDATASET_VALID(newrdataset
) &&
796 ! dns_rdataset_isassociated(newrdataset
)));
798 return ((db
->methods
->subtractrdataset
)(db
, node
, version
, rdataset
,
799 options
, newrdataset
));
803 dns_db_deleterdataset(dns_db_t
*db
, dns_dbnode_t
*node
,
804 dns_dbversion_t
*version
, dns_rdatatype_t type
,
805 dns_rdatatype_t covers
)
808 * Make it so that no rdataset of type 'type' exists at 'node' in
809 * version version 'version' of 'db'.
812 REQUIRE(DNS_DB_VALID(db
));
813 REQUIRE(node
!= NULL
);
814 REQUIRE(((db
->attributes
& DNS_DBATTR_CACHE
) == 0 && version
!= NULL
)||
815 ((db
->attributes
& DNS_DBATTR_CACHE
) != 0 && version
== NULL
));
817 return ((db
->methods
->deleterdataset
)(db
, node
, version
,
822 dns_db_overmem(dns_db_t
*db
, isc_boolean_t overmem
) {
824 REQUIRE(DNS_DB_VALID(db
));
826 (db
->methods
->overmem
)(db
, overmem
);
830 dns_db_getsoaserial(dns_db_t
*db
, dns_dbversion_t
*ver
, isc_uint32_t
*serialp
)
833 dns_dbnode_t
*node
= NULL
;
834 dns_rdataset_t rdataset
;
835 dns_rdata_t rdata
= DNS_RDATA_INIT
;
838 REQUIRE(dns_db_iszone(db
) || dns_db_isstub(db
));
840 result
= dns_db_findnode(db
, dns_db_origin(db
), ISC_FALSE
, &node
);
841 if (result
!= ISC_R_SUCCESS
)
844 dns_rdataset_init(&rdataset
);
845 result
= dns_db_findrdataset(db
, node
, ver
, dns_rdatatype_soa
, 0,
846 (isc_stdtime_t
)0, &rdataset
, NULL
);
847 if (result
!= ISC_R_SUCCESS
)
850 result
= dns_rdataset_first(&rdataset
);
851 if (result
!= ISC_R_SUCCESS
)
853 dns_rdataset_current(&rdataset
, &rdata
);
854 result
= dns_rdataset_next(&rdataset
);
855 INSIST(result
== ISC_R_NOMORE
);
857 INSIST(rdata
.length
> 20);
858 isc_buffer_init(&buffer
, rdata
.data
, rdata
.length
);
859 isc_buffer_add(&buffer
, rdata
.length
);
860 isc_buffer_forward(&buffer
, rdata
.length
- 20);
861 *serialp
= isc_buffer_getuint32(&buffer
);
863 result
= ISC_R_SUCCESS
;
866 dns_rdataset_disassociate(&rdataset
);
869 dns_db_detachnode(db
, &node
);
874 dns_db_nodecount(dns_db_t
*db
) {
875 REQUIRE(DNS_DB_VALID(db
));
877 return ((db
->methods
->nodecount
)(db
));
881 dns_db_hashsize(dns_db_t
*db
) {
882 REQUIRE(DNS_DB_VALID(db
));
884 if (db
->methods
->hashsize
== NULL
)
885 return (ISC_R_NOTIMPLEMENTED
);
887 return ((db
->methods
->hashsize
)(db
));
891 dns_db_settask(dns_db_t
*db
, isc_task_t
*task
) {
892 REQUIRE(DNS_DB_VALID(db
));
894 (db
->methods
->settask
)(db
, task
);
898 dns_db_register(const char *name
, dns_dbcreatefunc_t create
, void *driverarg
,
899 isc_mem_t
*mctx
, dns_dbimplementation_t
**dbimp
)
901 dns_dbimplementation_t
*imp
;
903 REQUIRE(name
!= NULL
);
904 REQUIRE(dbimp
!= NULL
&& *dbimp
== NULL
);
906 RUNTIME_CHECK(isc_once_do(&once
, initialize
) == ISC_R_SUCCESS
);
908 RWLOCK(&implock
, isc_rwlocktype_write
);
911 RWUNLOCK(&implock
, isc_rwlocktype_write
);
912 return (ISC_R_EXISTS
);
915 imp
= isc_mem_get(mctx
, sizeof(dns_dbimplementation_t
));
917 RWUNLOCK(&implock
, isc_rwlocktype_write
);
918 return (ISC_R_NOMEMORY
);
921 imp
->create
= create
;
923 imp
->driverarg
= driverarg
;
924 isc_mem_attach(mctx
, &imp
->mctx
);
925 ISC_LINK_INIT(imp
, link
);
926 ISC_LIST_APPEND(implementations
, imp
, link
);
927 RWUNLOCK(&implock
, isc_rwlocktype_write
);
931 return (ISC_R_SUCCESS
);
935 dns_db_unregister(dns_dbimplementation_t
**dbimp
) {
936 dns_dbimplementation_t
*imp
;
939 REQUIRE(dbimp
!= NULL
&& *dbimp
!= NULL
);
941 RUNTIME_CHECK(isc_once_do(&once
, initialize
) == ISC_R_SUCCESS
);
945 RWLOCK(&implock
, isc_rwlocktype_write
);
946 ISC_LIST_UNLINK(implementations
, imp
, link
);
948 isc_mem_put(mctx
, imp
, sizeof(dns_dbimplementation_t
));
949 isc_mem_detach(&mctx
);
950 RWUNLOCK(&implock
, isc_rwlocktype_write
);
951 ENSURE(*dbimp
== NULL
);
955 dns_db_getoriginnode(dns_db_t
*db
, dns_dbnode_t
**nodep
) {
956 REQUIRE(DNS_DB_VALID(db
));
957 REQUIRE(dns_db_iszone(db
) == ISC_TRUE
);
958 REQUIRE(nodep
!= NULL
&& *nodep
== NULL
);
960 if (db
->methods
->getoriginnode
!= NULL
)
961 return ((db
->methods
->getoriginnode
)(db
, nodep
));
963 return (ISC_R_NOTFOUND
);
967 dns_db_getrrsetstats(dns_db_t
*db
) {
968 REQUIRE(DNS_DB_VALID(db
));
970 if (db
->methods
->getrrsetstats
!= NULL
)
971 return ((db
->methods
->getrrsetstats
)(db
));
977 dns_db_setcachestats(dns_db_t
*db
, isc_stats_t
*stats
) {
978 REQUIRE(DNS_DB_VALID(db
));
980 if (db
->methods
->setcachestats
!= NULL
)
981 return ((db
->methods
->setcachestats
)(db
, stats
));
983 return (ISC_R_NOTIMPLEMENTED
);
987 dns_db_getnsec3parameters(dns_db_t
*db
, dns_dbversion_t
*version
,
988 dns_hash_t
*hash
, isc_uint8_t
*flags
,
989 isc_uint16_t
*iterations
,
990 unsigned char *salt
, size_t *salt_length
)
992 REQUIRE(DNS_DB_VALID(db
));
993 REQUIRE(dns_db_iszone(db
) == ISC_TRUE
);
995 if (db
->methods
->getnsec3parameters
!= NULL
)
996 return ((db
->methods
->getnsec3parameters
)(db
, version
, hash
,
1000 return (ISC_R_NOTFOUND
);
1004 dns_db_setsigningtime(dns_db_t
*db
, dns_rdataset_t
*rdataset
,
1005 isc_stdtime_t resign
)
1007 if (db
->methods
->setsigningtime
!= NULL
)
1008 return ((db
->methods
->setsigningtime
)(db
, rdataset
, resign
));
1009 return (ISC_R_NOTIMPLEMENTED
);
1013 dns_db_getsigningtime(dns_db_t
*db
, dns_rdataset_t
*rdataset
, dns_name_t
*name
)
1015 if (db
->methods
->getsigningtime
!= NULL
)
1016 return ((db
->methods
->getsigningtime
)(db
, rdataset
, name
));
1017 return (ISC_R_NOTFOUND
);
1021 dns_db_resigned(dns_db_t
*db
, dns_rdataset_t
*rdataset
,
1022 dns_dbversion_t
*version
)
1024 if (db
->methods
->resigned
!= NULL
)
1025 (db
->methods
->resigned
)(db
, rdataset
, version
);
1029 * Attach a database to policy zone databases.
1030 * This should only happen when the caller has already ensured that
1031 * it is dealing with a database that understands response policy zones.
1034 dns_db_rpz_attach(dns_db_t
*db
, dns_rpz_zones_t
*rpzs
, dns_rpz_num_t rpz_num
) {
1035 REQUIRE(db
->methods
->rpz_attach
!= NULL
);
1036 (db
->methods
->rpz_attach
)(db
, rpzs
, rpz_num
);
1040 * Finish loading a response policy zone.
1043 dns_db_rpz_ready(dns_db_t
*db
) {
1044 if (db
->methods
->rpz_ready
== NULL
)
1045 return (ISC_R_SUCCESS
);
1046 return ((db
->methods
->rpz_ready
)(db
));