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