]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/bind9/lib/dns/db.c
Fix BIND remote denial of service vulnerability. [SA-15:27]
[FreeBSD/releng/9.3.git] / contrib / bind9 / lib / dns / db.c
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
50 struct 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
71 static ISC_LIST(dns_dbimplementation_t) implementations;
72 static isc_rwlock_t implock;
73 static isc_once_t once = ISC_ONCE_INIT;
74
75 static dns_dbimplementation_t rbtimp;
76 #ifdef BIND9
77 static dns_dbimplementation_t rbt64imp;
78 #endif
79
80 static void
81 initialize(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
105 static inline dns_dbimplementation_t *
106 impfind(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
122 isc_result_t
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)
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
158 void
159 dns_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
173 void
174 dns_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
188 isc_result_t
189 dns_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
197 isc_boolean_t
198 dns_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
212 isc_boolean_t
213 dns_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
227 isc_boolean_t
228 dns_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
242 isc_boolean_t
243 dns_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
257 isc_boolean_t
258 dns_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
270 isc_boolean_t
271 dns_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
282 dns_name_t *
283 dns_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
293 dns_rdataclass_t
294 dns_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
305 isc_result_t
306 dns_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
319 isc_result_t
320 dns_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
331 isc_result_t
332 dns_db_load(dns_db_t *db, const char *filename) {
333         return (dns_db_load3(db, filename, dns_masterformat_text, 0));
334 }
335
336 isc_result_t
337 dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format) {
338         return (dns_db_load3(db, filename, format, 0));
339 }
340
341 isc_result_t
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;
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
377 isc_result_t
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));
381 }
382
383 isc_result_t
384 dns_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
402 void
403 dns_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
416 isc_result_t
417 dns_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
430 void
431 dns_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
448 void
449 dns_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
470 isc_result_t
471 dns_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
489 isc_result_t
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)
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
509 isc_result_t
510 dns_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
524 isc_result_t
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)
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
557 isc_result_t
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)
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
592 isc_result_t
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)
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
614 void
615 dns_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
628 void
629 dns_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
643 void
644 dns_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
667 isc_result_t
668 dns_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
681 void
682 dns_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
698 isc_result_t
699 dns_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
716 isc_result_t
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)
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
737 isc_result_t
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)
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
753 isc_result_t
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)
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
780 isc_result_t
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)
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
804 isc_result_t
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)
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
823 void
824 dns_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
831 isc_result_t
832 dns_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
875 unsigned int
876 dns_db_nodecount(dns_db_t *db) {
877         REQUIRE(DNS_DB_VALID(db));
878
879         return ((db->methods->nodecount)(db));
880 }
881
882 void
883 dns_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
889 isc_result_t
890 dns_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
926 void
927 dns_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
946 isc_result_t
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);
951
952         if (db->methods->getoriginnode != NULL)
953                 return ((db->methods->getoriginnode)(db, nodep));
954
955         return (ISC_R_NOTFOUND);
956 }
957
958 dns_stats_t *
959 dns_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
968 isc_result_t
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)
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
985 isc_result_t
986 dns_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
994 isc_result_t
995 dns_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
1002 void
1003 dns_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
1010 isc_result_t
1011 dns_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
1018 void
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)
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 }