Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / dns / db.c
blobfa200d93377adb87576810e66099ce8810597bbc
1 /* $NetBSD: db.c,v 1.7 2014/12/10 04:37:58 christos Exp $ */
3 /*
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.
20 /* Id */
22 /*! \file */
24 /***
25 *** Imports
26 ***/
28 #include <config.h>
30 #include <isc/buffer.h>
31 #include <isc/mem.h>
32 #include <isc/once.h>
33 #include <isc/rwlock.h>
34 #include <isc/string.h>
35 #include <isc/util.h>
37 #include <dns/callbacks.h>
38 #include <dns/clientinfo.h>
39 #include <dns/db.h>
40 #include <dns/dbiterator.h>
41 #include <dns/log.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>
48 /***
49 *** Private Types
50 ***/
52 struct dns_dbimplementation {
53 const char * name;
54 dns_dbcreatefunc_t create;
55 isc_mem_t * mctx;
56 void * driverarg;
57 ISC_LINK(dns_dbimplementation_t) link;
60 /***
61 *** Supported DB Implementations Registry
62 ***/
65 * Built in database implementations are registered here.
68 #include "rbtdb.h"
69 #include "rbtdb64.h"
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;
78 static void
79 initialize(void) {
80 RUNTIME_CHECK(isc_rwlock_init(&implock, 0, 0) == ISC_R_SUCCESS);
82 rbtimp.name = "rbt";
83 rbtimp.create = dns_rbtdb_create;
84 rbtimp.mctx = NULL;
85 rbtimp.driverarg = NULL;
86 ISC_LINK_INIT(&rbtimp, link);
88 rbt64imp.name = "rbt64";
89 rbt64imp.create = dns_rbtdb64_create;
90 rbt64imp.mctx = NULL;
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);
104 imp != NULL;
105 imp = ISC_LIST_NEXT(imp, link))
106 if (strcasecmp(name, imp->name) == 0)
107 return (imp);
108 return (NULL);
112 /***
113 *** Basic DB Methods
114 ***/
116 isc_result_t
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) {
135 isc_result_t result;
136 result = ((impinfo->create)(mctx, origin, type,
137 rdclass, argc, argv,
138 impinfo->driverarg, dbp));
139 RWUNLOCK(&implock, isc_rwlocktype_read);
140 return (result);
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);
152 void
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);
167 void
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);
182 isc_result_t
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));
191 isc_boolean_t
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)
201 return (ISC_TRUE);
203 return (ISC_FALSE);
206 isc_boolean_t
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)
216 return (ISC_TRUE);
218 return (ISC_FALSE);
221 isc_boolean_t
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)
231 return (ISC_TRUE);
233 return (ISC_FALSE);
236 isc_boolean_t
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));
251 isc_boolean_t
252 dns_db_issecure(dns_db_t *db) {
255 * Is 'db' secure?
258 REQUIRE(DNS_DB_VALID(db));
259 REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
261 return ((db->methods->issecure)(db));
264 isc_boolean_t
265 dns_db_ispersistent(dns_db_t *db) {
268 * Is 'db' persistent?
271 REQUIRE(DNS_DB_VALID(db));
273 return ((db->methods->ispersistent)(db));
276 dns_name_t *
277 dns_db_origin(dns_db_t *db) {
279 * The origin of the database.
282 REQUIRE(DNS_DB_VALID(db));
284 return (&db->origin);
287 dns_rdataclass_t
288 dns_db_class(dns_db_t *db) {
290 * The class of the database.
293 REQUIRE(DNS_DB_VALID(db));
295 return (db->rdclass);
298 isc_result_t
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));
310 isc_result_t
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));
323 isc_result_t
324 dns_db_load(dns_db_t *db, const char *filename) {
325 return (dns_db_load3(db, filename, dns_masterformat_text, 0));
328 isc_result_t
329 dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format) {
330 return (dns_db_load3(db, filename, format, 0));
333 isc_result_t
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)
351 return (result);
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))
363 result = eresult;
365 return (result);
368 isc_result_t
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));
376 isc_result_t
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));
382 isc_result_t
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"
388 * method?
391 REQUIRE(DNS_DB_VALID(db));
393 return ((db->methods->dump)(db, version, filename, masterformat));
396 /***
397 *** Version Methods
398 ***/
400 void
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);
414 isc_result_t
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));
428 void
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);
446 void
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);
464 /***
465 *** Node Methods
466 ***/
468 isc_result_t
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));
482 else
483 return ((db->methods->findnodeext)(db, name, create,
484 NULL, NULL, nodep));
487 isc_result_t
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
494 * implementation.
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));
503 else
504 return ((db->methods->findnode)(db, name, create, nodep));
507 isc_result_t
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));
522 isc_result_t
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'
530 * of 'db'.
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));
548 else
549 return ((db->methods->findext)(db, name, version, type,
550 options, now, nodep, foundname,
551 NULL, NULL,
552 rdataset, sigrdataset));
555 isc_result_t
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,
582 methods, clientinfo,
583 rdataset, sigrdataset));
584 else
585 return ((db->methods->find)(db, name, version, type,
586 options, now, nodep, foundname,
587 rdataset, sigrdataset));
590 isc_result_t
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));
612 void
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);
626 void
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);
641 void
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
650 * method.
652 REQUIRE(sourcep != NULL && *sourcep != NULL);
654 UNUSED(db);
656 if (db->methods->transfernode == NULL) {
657 *targetp = *sourcep;
658 *sourcep = NULL;
659 } else
660 (db->methods->transfernode)(db, sourcep, targetp);
662 ENSURE(*sourcep == NULL);
665 isc_result_t
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));
679 void
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
683 * 'out'.
686 REQUIRE(DNS_DB_VALID(db));
687 REQUIRE(node != NULL);
689 (db->methods->printnode)(db, node, out);
692 /***
693 *** DB Iterator Creation
694 ***/
696 isc_result_t
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));
710 /***
711 *** Rdataset Methods
712 ***/
714 isc_result_t
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,
732 sigrdataset));
735 isc_result_t
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,
748 iteratorp));
751 isc_result_t
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));
778 isc_result_t
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
785 * 'db'.
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));
802 isc_result_t
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,
818 type, covers));
821 void
822 dns_db_overmem(dns_db_t *db, isc_boolean_t overmem) {
824 REQUIRE(DNS_DB_VALID(db));
826 (db->methods->overmem)(db, overmem);
829 isc_result_t
830 dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, isc_uint32_t *serialp)
832 isc_result_t result;
833 dns_dbnode_t *node = NULL;
834 dns_rdataset_t rdataset;
835 dns_rdata_t rdata = DNS_RDATA_INIT;
836 isc_buffer_t buffer;
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)
842 return (result);
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)
848 goto freenode;
850 result = dns_rdataset_first(&rdataset);
851 if (result != ISC_R_SUCCESS)
852 goto freerdataset;
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;
865 freerdataset:
866 dns_rdataset_disassociate(&rdataset);
868 freenode:
869 dns_db_detachnode(db, &node);
870 return (result);
873 unsigned int
874 dns_db_nodecount(dns_db_t *db) {
875 REQUIRE(DNS_DB_VALID(db));
877 return ((db->methods->nodecount)(db));
880 unsigned int
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));
890 void
891 dns_db_settask(dns_db_t *db, isc_task_t *task) {
892 REQUIRE(DNS_DB_VALID(db));
894 (db->methods->settask)(db, task);
897 isc_result_t
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);
909 imp = impfind(name);
910 if (imp != NULL) {
911 RWUNLOCK(&implock, isc_rwlocktype_write);
912 return (ISC_R_EXISTS);
915 imp = isc_mem_get(mctx, sizeof(dns_dbimplementation_t));
916 if (imp == NULL) {
917 RWUNLOCK(&implock, isc_rwlocktype_write);
918 return (ISC_R_NOMEMORY);
920 imp->name = name;
921 imp->create = create;
922 imp->mctx = NULL;
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);
929 *dbimp = imp;
931 return (ISC_R_SUCCESS);
934 void
935 dns_db_unregister(dns_dbimplementation_t **dbimp) {
936 dns_dbimplementation_t *imp;
937 isc_mem_t *mctx;
939 REQUIRE(dbimp != NULL && *dbimp != NULL);
941 RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
943 imp = *dbimp;
944 *dbimp = NULL;
945 RWLOCK(&implock, isc_rwlocktype_write);
946 ISC_LIST_UNLINK(implementations, imp, link);
947 mctx = imp->mctx;
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);
954 isc_result_t
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);
966 dns_stats_t *
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));
973 return (NULL);
976 isc_result_t
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);
986 isc_result_t
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,
997 flags, iterations,
998 salt, salt_length));
1000 return (ISC_R_NOTFOUND);
1003 isc_result_t
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);
1012 isc_result_t
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);
1020 void
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.
1033 void
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.
1042 isc_result_t
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));