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
initialize(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 *
impfind(const char * name)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
dns_db_create(isc_mem_t * mctx,const char * db_type,dns_name_t * origin,dns_dbtype_t type,dns_rdataclass_t rdclass,unsigned int argc,char * argv[],dns_db_t ** dbp)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
dns_db_attach(dns_db_t * source,dns_db_t ** targetp)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
dns_db_detach(dns_db_t ** dbp)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
dns_db_ondestroy(dns_db_t * db,isc_task_t * task,isc_event_t ** eventp)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
dns_db_iscache(dns_db_t * db)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
dns_db_iszone(dns_db_t * db)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
dns_db_isstub(dns_db_t * db)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
dns_db_isdnssec(dns_db_t * db)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
dns_db_issecure(dns_db_t * db)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
dns_db_ispersistent(dns_db_t * db)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 *
dns_db_origin(dns_db_t * db)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
dns_db_class(dns_db_t * db)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
dns_db_beginload(dns_db_t * db,dns_addrdatasetfunc_t * addp,dns_dbload_t ** dbloadp)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
dns_db_endload(dns_db_t * db,dns_dbload_t ** dbloadp)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
dns_db_load(dns_db_t * db,const char * filename)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
dns_db_load2(dns_db_t * db,const char * filename,dns_masterformat_t format)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
dns_db_load3(dns_db_t * db,const char * filename,dns_masterformat_t format,unsigned int options)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
dns_db_dump(dns_db_t * db,dns_dbversion_t * version,const char * filename)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
dns_db_dump2(dns_db_t * db,dns_dbversion_t * version,const char * filename,dns_masterformat_t masterformat)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
dns_db_currentversion(dns_db_t * db,dns_dbversion_t ** versionp)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
dns_db_newversion(dns_db_t * db,dns_dbversion_t ** versionp)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
dns_db_attachversion(dns_db_t * db,dns_dbversion_t * source,dns_dbversion_t ** targetp)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
dns_db_closeversion(dns_db_t * db,dns_dbversion_t ** versionp,isc_boolean_t commit)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
dns_db_findnode(dns_db_t * db,dns_name_t * name,isc_boolean_t create,dns_dbnode_t ** nodep)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
dns_db_findnodeext(dns_db_t * db,dns_name_t * name,isc_boolean_t create,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo,dns_dbnode_t ** nodep)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
dns_db_findnsec3node(dns_db_t * db,dns_name_t * name,isc_boolean_t create,dns_dbnode_t ** nodep)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
dns_db_find(dns_db_t * db,dns_name_t * name,dns_dbversion_t * version,dns_rdatatype_t type,unsigned int options,isc_stdtime_t now,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)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
dns_db_findext(dns_db_t * db,dns_name_t * name,dns_dbversion_t * version,dns_rdatatype_t type,unsigned int options,isc_stdtime_t now,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo,dns_rdataset_t * rdataset,dns_rdataset_t * 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)
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
dns_db_findzonecut(dns_db_t * db,dns_name_t * name,unsigned int options,isc_stdtime_t now,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_rdataset_t * rdataset,dns_rdataset_t * 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)
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
dns_db_attachnode(dns_db_t * db,dns_dbnode_t * source,dns_dbnode_t ** targetp)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
dns_db_detachnode(dns_db_t * db,dns_dbnode_t ** nodep)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
dns_db_transfernode(dns_db_t * db,dns_dbnode_t ** sourcep,dns_dbnode_t ** targetp)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
dns_db_expirenode(dns_db_t * db,dns_dbnode_t * node,isc_stdtime_t now)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
dns_db_printnode(dns_db_t * db,dns_dbnode_t * node,FILE * out)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
dns_db_createiterator(dns_db_t * db,unsigned int flags,dns_dbiterator_t ** iteratorp)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
dns_db_findrdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdatatype_t type,dns_rdatatype_t covers,isc_stdtime_t now,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)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
dns_db_allrdatasets(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,isc_stdtime_t now,dns_rdatasetiter_t ** iteratorp)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
dns_db_addrdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,isc_stdtime_t now,dns_rdataset_t * rdataset,unsigned int options,dns_rdataset_t * addedrdataset)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
dns_db_subtractrdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdataset_t * rdataset,unsigned int options,dns_rdataset_t * newrdataset)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
dns_db_deleterdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdatatype_t type,dns_rdatatype_t covers)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
dns_db_overmem(dns_db_t * db,isc_boolean_t overmem)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
dns_db_getsoaserial(dns_db_t * db,dns_dbversion_t * ver,isc_uint32_t * serialp)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
dns_db_nodecount(dns_db_t * db)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
dns_db_settask(dns_db_t * db,isc_task_t * task)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
dns_db_register(const char * name,dns_dbcreatefunc_t create,void * driverarg,isc_mem_t * mctx,dns_dbimplementation_t ** dbimp)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
dns_db_unregister(dns_dbimplementation_t ** dbimp)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
dns_db_getoriginnode(dns_db_t * db,dns_dbnode_t ** nodep)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 *
dns_db_getrrsetstats(dns_db_t * db)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
dns_db_getnsec3parameters(dns_db_t * db,dns_dbversion_t * version,dns_hash_t * hash,isc_uint8_t * flags,isc_uint16_t * iterations,unsigned char * salt,size_t * salt_length)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
dns_db_setsigningtime(dns_db_t * db,dns_rdataset_t * rdataset,isc_stdtime_t resign)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
dns_db_getsigningtime(dns_db_t * db,dns_rdataset_t * rdataset,dns_name_t * name)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
dns_db_resigned(dns_db_t * db,dns_rdataset_t * rdataset,dns_dbversion_t * version)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
dns_db_rpz_enabled(dns_db_t * db,dns_rpz_st_t * st)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
dns_db_rpz_findips(dns_rpz_zone_t * rpz,dns_rpz_type_t rpz_type,dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * version,dns_rdataset_t * ardataset,dns_rpz_st_t * st,dns_name_t * query_qname)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 }
1028