1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * See the COPYRIGHT file distributed with this work for additional
9  * information regarding copyright ownership.
10  */
11 
12 /*! \file */
13 
14 #include <inttypes.h>
15 #include <stdbool.h>
16 #include <string.h>
17 
18 #include <isc/buffer.h>
19 #include <isc/lex.h>
20 #include <isc/log.h>
21 #include <isc/magic.h>
22 #include <isc/mem.h>
23 #include <isc/once.h>
24 #include <isc/print.h>
25 #include <isc/refcount.h>
26 #include <isc/region.h>
27 #include <isc/util.h>
28 
29 #include <dns/callbacks.h>
30 #include <dns/db.h>
31 #include <dns/dbiterator.h>
32 #include <dns/fixedname.h>
33 #include <dns/log.h>
34 #include <dns/rdata.h>
35 #include <dns/rdatalist.h>
36 #include <dns/rdataset.h>
37 #include <dns/rdatasetiter.h>
38 #include <dns/rdatatype.h>
39 #include <dns/result.h>
40 #include <dns/sdb.h>
41 #include <dns/types.h>
42 
43 #include "rdatalist_p.h"
44 
45 struct dns_sdbimplementation {
46 	const dns_sdbmethods_t *methods;
47 	void *driverdata;
48 	unsigned int flags;
49 	isc_mem_t *mctx;
50 	isc_mutex_t driverlock;
51 	dns_dbimplementation_t *dbimp;
52 };
53 
54 struct dns_sdb {
55 	/* Unlocked */
56 	dns_db_t common;
57 	char *zone;
58 	dns_sdbimplementation_t *implementation;
59 	void *dbdata;
60 
61 	/* Atomic */
62 	isc_refcount_t references;
63 };
64 
65 struct dns_sdblookup {
66 	/* Unlocked */
67 	unsigned int magic;
68 	dns_sdb_t *sdb;
69 	ISC_LIST(dns_rdatalist_t) lists;
70 	ISC_LIST(isc_buffer_t) buffers;
71 	dns_name_t *name;
72 	ISC_LINK(dns_sdblookup_t) link;
73 	dns_rdatacallbacks_t callbacks;
74 
75 	/* Atomic */
76 	isc_refcount_t references;
77 };
78 
79 typedef struct dns_sdblookup dns_sdbnode_t;
80 
81 struct dns_sdballnodes {
82 	dns_dbiterator_t common;
83 	ISC_LIST(dns_sdbnode_t) nodelist;
84 	dns_sdbnode_t *current;
85 	dns_sdbnode_t *origin;
86 };
87 
88 typedef dns_sdballnodes_t sdb_dbiterator_t;
89 
90 typedef struct sdb_rdatasetiter {
91 	dns_rdatasetiter_t common;
92 	dns_rdatalist_t *current;
93 } sdb_rdatasetiter_t;
94 
95 #define SDB_MAGIC ISC_MAGIC('S', 'D', 'B', '-')
96 
97 /*%
98  * Note that "impmagic" is not the first four bytes of the struct, so
99  * ISC_MAGIC_VALID cannot be used.
100  */
101 #define VALID_SDB(sdb) ((sdb) != NULL && (sdb)->common.impmagic == SDB_MAGIC)
102 
103 #define SDBLOOKUP_MAGIC	      ISC_MAGIC('S', 'D', 'B', 'L')
104 #define VALID_SDBLOOKUP(sdbl) ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)
105 #define VALID_SDBNODE(sdbn)   VALID_SDBLOOKUP(sdbn)
106 
107 /* These values are taken from RFC1537 */
108 #define SDB_DEFAULT_REFRESH 28800U  /* 8 hours */
109 #define SDB_DEFAULT_RETRY   7200U   /* 2 hours */
110 #define SDB_DEFAULT_EXPIRE  604800U /* 7 days */
111 #define SDB_DEFAULT_MINIMUM 86400U  /* 1 day */
112 
113 /* This is a reasonable value */
114 #define SDB_DEFAULT_TTL (60 * 60 * 24)
115 
116 #ifdef __COVERITY__
117 #define MAYBE_LOCK(sdb)	  LOCK(&sdb->implementation->driverlock)
118 #define MAYBE_UNLOCK(sdb) UNLOCK(&sdb->implementation->driverlock)
119 #else /* ifdef __COVERITY__ */
120 #define MAYBE_LOCK(sdb)                                          \
121 	do {                                                     \
122 		unsigned int flags = sdb->implementation->flags; \
123 		if ((flags & DNS_SDBFLAG_THREADSAFE) == 0)       \
124 			LOCK(&sdb->implementation->driverlock);  \
125 	} while (0)
126 
127 #define MAYBE_UNLOCK(sdb)                                         \
128 	do {                                                      \
129 		unsigned int flags = sdb->implementation->flags;  \
130 		if ((flags & DNS_SDBFLAG_THREADSAFE) == 0)        \
131 			UNLOCK(&sdb->implementation->driverlock); \
132 	} while (0)
133 #endif /* ifdef __COVERITY__ */
134 
135 static int dummy;
136 
137 static isc_result_t
138 dns_sdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
139 	       dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
140 	       void *driverarg, dns_db_t **dbp);
141 
142 static isc_result_t
143 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
144 	     dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
145 	     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
146 
147 static isc_result_t
148 createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep);
149 
150 static void
151 destroynode(dns_sdbnode_t *node);
152 
153 static void
154 detachnode(dns_db_t *db, dns_dbnode_t **targetp);
155 
156 static void
157 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
158 		dns_rdataset_t *rdataset);
159 
160 static void
161 dbiterator_destroy(dns_dbiterator_t **iteratorp);
162 static isc_result_t
163 dbiterator_first(dns_dbiterator_t *iterator);
164 static isc_result_t
165 dbiterator_last(dns_dbiterator_t *iterator);
166 static isc_result_t
167 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name);
168 static isc_result_t
169 dbiterator_prev(dns_dbiterator_t *iterator);
170 static isc_result_t
171 dbiterator_next(dns_dbiterator_t *iterator);
172 static isc_result_t
173 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
174 		   dns_name_t *name);
175 static isc_result_t
176 dbiterator_pause(dns_dbiterator_t *iterator);
177 static isc_result_t
178 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
179 
180 static dns_dbiteratormethods_t dbiterator_methods = {
181 	dbiterator_destroy, dbiterator_first, dbiterator_last,
182 	dbiterator_seek,    dbiterator_prev,  dbiterator_next,
183 	dbiterator_current, dbiterator_pause, dbiterator_origin
184 };
185 
186 static void
187 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
188 static isc_result_t
189 rdatasetiter_first(dns_rdatasetiter_t *iterator);
190 static isc_result_t
191 rdatasetiter_next(dns_rdatasetiter_t *iterator);
192 static void
193 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset);
194 
195 static dns_rdatasetitermethods_t rdatasetiter_methods = {
196 	rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next,
197 	rdatasetiter_current
198 };
199 
200 /*
201  * Functions used by implementors of simple databases
202  */
203 isc_result_t
dns_sdb_register(const char * drivername,const dns_sdbmethods_t * methods,void * driverdata,unsigned int flags,isc_mem_t * mctx,dns_sdbimplementation_t ** sdbimp)204 dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
205 		 void *driverdata, unsigned int flags, isc_mem_t *mctx,
206 		 dns_sdbimplementation_t **sdbimp) {
207 	dns_sdbimplementation_t *imp;
208 	isc_result_t result;
209 
210 	REQUIRE(drivername != NULL);
211 	REQUIRE(methods != NULL);
212 	REQUIRE(methods->lookup != NULL || methods->lookup2 != NULL);
213 	REQUIRE(mctx != NULL);
214 	REQUIRE(sdbimp != NULL && *sdbimp == NULL);
215 	REQUIRE((flags &
216 		 ~(DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA |
217 		   DNS_SDBFLAG_THREADSAFE | DNS_SDBFLAG_DNS64)) == 0);
218 
219 	imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t));
220 	imp->methods = methods;
221 	imp->driverdata = driverdata;
222 	imp->flags = flags;
223 	imp->mctx = NULL;
224 	isc_mem_attach(mctx, &imp->mctx);
225 	isc_mutex_init(&imp->driverlock);
226 
227 	imp->dbimp = NULL;
228 	result = dns_db_register(drivername, dns_sdb_create, imp, mctx,
229 				 &imp->dbimp);
230 	if (result != ISC_R_SUCCESS) {
231 		goto cleanup_mutex;
232 	}
233 	*sdbimp = imp;
234 
235 	return (ISC_R_SUCCESS);
236 
237 cleanup_mutex:
238 	isc_mutex_destroy(&imp->driverlock);
239 	isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
240 	return (result);
241 }
242 
243 void
dns_sdb_unregister(dns_sdbimplementation_t ** sdbimp)244 dns_sdb_unregister(dns_sdbimplementation_t **sdbimp) {
245 	dns_sdbimplementation_t *imp;
246 
247 	REQUIRE(sdbimp != NULL && *sdbimp != NULL);
248 
249 	imp = *sdbimp;
250 	*sdbimp = NULL;
251 	dns_db_unregister(&imp->dbimp);
252 	isc_mutex_destroy(&imp->driverlock);
253 
254 	isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdbimplementation_t));
255 }
256 
257 static inline unsigned int
initial_size(unsigned int len)258 initial_size(unsigned int len) {
259 	unsigned int size;
260 
261 	for (size = 1024; size < (64 * 1024); size *= 2) {
262 		if (len < size) {
263 			return (size);
264 		}
265 	}
266 	return (65535);
267 }
268 
269 isc_result_t
dns_sdb_putrdata(dns_sdblookup_t * lookup,dns_rdatatype_t typeval,dns_ttl_t ttl,const unsigned char * rdatap,unsigned int rdlen)270 dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval,
271 		 dns_ttl_t ttl, const unsigned char *rdatap,
272 		 unsigned int rdlen) {
273 	dns_rdatalist_t *rdatalist;
274 	dns_rdata_t *rdata;
275 	isc_buffer_t *rdatabuf = NULL;
276 	isc_mem_t *mctx;
277 	isc_region_t region;
278 
279 	mctx = lookup->sdb->common.mctx;
280 
281 	rdatalist = ISC_LIST_HEAD(lookup->lists);
282 	while (rdatalist != NULL) {
283 		if (rdatalist->type == typeval) {
284 			break;
285 		}
286 		rdatalist = ISC_LIST_NEXT(rdatalist, link);
287 	}
288 
289 	if (rdatalist == NULL) {
290 		rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
291 		dns_rdatalist_init(rdatalist);
292 		rdatalist->rdclass = lookup->sdb->common.rdclass;
293 		rdatalist->type = typeval;
294 		rdatalist->ttl = ttl;
295 		ISC_LIST_APPEND(lookup->lists, rdatalist, link);
296 	} else if (rdatalist->ttl != ttl) {
297 		return (DNS_R_BADTTL);
298 	}
299 
300 	rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
301 
302 	isc_buffer_allocate(mctx, &rdatabuf, rdlen);
303 	DE_CONST(rdatap, region.base);
304 	region.length = rdlen;
305 	isc_buffer_copyregion(rdatabuf, &region);
306 	isc_buffer_usedregion(rdatabuf, &region);
307 	dns_rdata_init(rdata);
308 	dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type,
309 			     &region);
310 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
311 	ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
312 
313 	return (ISC_R_SUCCESS);
314 }
315 
316 isc_result_t
dns_sdb_putrr(dns_sdblookup_t * lookup,const char * type,dns_ttl_t ttl,const char * data)317 dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
318 	      const char *data) {
319 	unsigned int datalen;
320 	dns_rdatatype_t typeval;
321 	isc_textregion_t r;
322 	isc_lex_t *lex = NULL;
323 	isc_result_t result;
324 	unsigned char *p = NULL;
325 	unsigned int size = 0; /* Init to suppress compiler warning */
326 	isc_mem_t *mctx;
327 	dns_sdbimplementation_t *imp;
328 	const dns_name_t *origin;
329 	isc_buffer_t b;
330 	isc_buffer_t rb;
331 
332 	REQUIRE(VALID_SDBLOOKUP(lookup));
333 	REQUIRE(type != NULL);
334 	REQUIRE(data != NULL);
335 
336 	mctx = lookup->sdb->common.mctx;
337 
338 	DE_CONST(type, r.base);
339 	r.length = strlen(type);
340 	result = dns_rdatatype_fromtext(&typeval, &r);
341 	if (result != ISC_R_SUCCESS) {
342 		return (result);
343 	}
344 
345 	imp = lookup->sdb->implementation;
346 	if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0) {
347 		origin = &lookup->sdb->common.origin;
348 	} else {
349 		origin = dns_rootname;
350 	}
351 
352 	result = isc_lex_create(mctx, 64, &lex);
353 	if (result != ISC_R_SUCCESS) {
354 		goto failure;
355 	}
356 
357 	datalen = strlen(data);
358 	size = initial_size(datalen);
359 	do {
360 		isc_buffer_constinit(&b, data, datalen);
361 		isc_buffer_add(&b, datalen);
362 		result = isc_lex_openbuffer(lex, &b);
363 		if (result != ISC_R_SUCCESS) {
364 			goto failure;
365 		}
366 
367 		if (size >= 65535) {
368 			size = 65535;
369 		}
370 		p = isc_mem_get(mctx, size);
371 		isc_buffer_init(&rb, p, size);
372 		result = dns_rdata_fromtext(NULL, lookup->sdb->common.rdclass,
373 					    typeval, lex, origin, 0, mctx, &rb,
374 					    &lookup->callbacks);
375 		if (result != ISC_R_NOSPACE) {
376 			break;
377 		}
378 
379 		/*
380 		 * Is the RR too big?
381 		 */
382 		if (size >= 65535) {
383 			break;
384 		}
385 		isc_mem_put(mctx, p, size);
386 		p = NULL;
387 		size *= 2;
388 	} while (result == ISC_R_NOSPACE);
389 
390 	if (result != ISC_R_SUCCESS) {
391 		goto failure;
392 	}
393 
394 	result = dns_sdb_putrdata(lookup, typeval, ttl, isc_buffer_base(&rb),
395 				  isc_buffer_usedlength(&rb));
396 failure:
397 	if (p != NULL) {
398 		isc_mem_put(mctx, p, size);
399 	}
400 	if (lex != NULL) {
401 		isc_lex_destroy(&lex);
402 	}
403 
404 	return (result);
405 }
406 
407 static isc_result_t
getnode(dns_sdballnodes_t * allnodes,const char * name,dns_sdbnode_t ** nodep)408 getnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) {
409 	dns_name_t *newname;
410 	const dns_name_t *origin;
411 	dns_fixedname_t fnewname;
412 	dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db;
413 	dns_sdbimplementation_t *imp = sdb->implementation;
414 	dns_sdbnode_t *sdbnode;
415 	isc_mem_t *mctx = sdb->common.mctx;
416 	isc_buffer_t b;
417 	isc_result_t result;
418 
419 	newname = dns_fixedname_initname(&fnewname);
420 
421 	if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0) {
422 		origin = &sdb->common.origin;
423 	} else {
424 		origin = dns_rootname;
425 	}
426 	isc_buffer_constinit(&b, name, strlen(name));
427 	isc_buffer_add(&b, strlen(name));
428 
429 	result = dns_name_fromtext(newname, &b, origin, 0, NULL);
430 	if (result != ISC_R_SUCCESS) {
431 		return (result);
432 	}
433 
434 	if (allnodes->common.relative_names) {
435 		/* All names are relative to the root */
436 		unsigned int nlabels = dns_name_countlabels(newname);
437 		dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
438 	}
439 
440 	sdbnode = ISC_LIST_HEAD(allnodes->nodelist);
441 	if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) {
442 		sdbnode = NULL;
443 		result = createnode(sdb, &sdbnode);
444 		if (result != ISC_R_SUCCESS) {
445 			return (result);
446 		}
447 		sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t));
448 		dns_name_init(sdbnode->name, NULL);
449 		dns_name_dup(newname, mctx, sdbnode->name);
450 		ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link);
451 		if (allnodes->origin == NULL &&
452 		    dns_name_equal(newname, &sdb->common.origin)) {
453 			allnodes->origin = sdbnode;
454 		}
455 	}
456 	*nodep = sdbnode;
457 	return (ISC_R_SUCCESS);
458 }
459 
460 isc_result_t
dns_sdb_putnamedrr(dns_sdballnodes_t * allnodes,const char * name,const char * type,dns_ttl_t ttl,const char * data)461 dns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name,
462 		   const char *type, dns_ttl_t ttl, const char *data) {
463 	isc_result_t result;
464 	dns_sdbnode_t *sdbnode = NULL;
465 	result = getnode(allnodes, name, &sdbnode);
466 	if (result != ISC_R_SUCCESS) {
467 		return (result);
468 	}
469 	return (dns_sdb_putrr(sdbnode, type, ttl, data));
470 }
471 
472 isc_result_t
dns_sdb_putnamedrdata(dns_sdballnodes_t * allnodes,const char * name,dns_rdatatype_t type,dns_ttl_t ttl,const void * rdata,unsigned int rdlen)473 dns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name,
474 		      dns_rdatatype_t type, dns_ttl_t ttl, const void *rdata,
475 		      unsigned int rdlen) {
476 	isc_result_t result;
477 	dns_sdbnode_t *sdbnode = NULL;
478 	result = getnode(allnodes, name, &sdbnode);
479 	if (result != ISC_R_SUCCESS) {
480 		return (result);
481 	}
482 	return (dns_sdb_putrdata(sdbnode, type, ttl, rdata, rdlen));
483 }
484 
485 isc_result_t
dns_sdb_putsoa(dns_sdblookup_t * lookup,const char * mname,const char * rname,uint32_t serial)486 dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
487 	       uint32_t serial) {
488 	char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
489 	int n;
490 
491 	REQUIRE(mname != NULL);
492 	REQUIRE(rname != NULL);
493 
494 	n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u", mname, rname,
495 		     serial, SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY,
496 		     SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM);
497 	if (n >= (int)sizeof(str) || n < 0) {
498 		return (ISC_R_NOSPACE);
499 	}
500 	return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));
501 }
502 
503 /*
504  * DB routines
505  */
506 
507 static void
attach(dns_db_t * source,dns_db_t ** targetp)508 attach(dns_db_t *source, dns_db_t **targetp) {
509 	dns_sdb_t *sdb = (dns_sdb_t *)source;
510 
511 	REQUIRE(VALID_SDB(sdb));
512 
513 	isc_refcount_increment(&sdb->references);
514 
515 	*targetp = source;
516 }
517 
518 static void
destroy(dns_sdb_t * sdb)519 destroy(dns_sdb_t *sdb) {
520 	dns_sdbimplementation_t *imp = sdb->implementation;
521 
522 	isc_refcount_destroy(&sdb->references);
523 
524 	if (imp->methods->destroy != NULL) {
525 		MAYBE_LOCK(sdb);
526 		imp->methods->destroy(sdb->zone, imp->driverdata, &sdb->dbdata);
527 		MAYBE_UNLOCK(sdb);
528 	}
529 
530 	isc_mem_free(sdb->common.mctx, sdb->zone);
531 
532 	sdb->common.magic = 0;
533 	sdb->common.impmagic = 0;
534 
535 	dns_name_free(&sdb->common.origin, sdb->common.mctx);
536 
537 	isc_mem_putanddetach(&sdb->common.mctx, sdb, sizeof(dns_sdb_t));
538 }
539 
540 static void
detach(dns_db_t ** dbp)541 detach(dns_db_t **dbp) {
542 	dns_sdb_t *sdb = (dns_sdb_t *)(*dbp);
543 
544 	REQUIRE(VALID_SDB(sdb));
545 
546 	*dbp = NULL;
547 
548 	if (isc_refcount_decrement(&sdb->references) == 1) {
549 		destroy(sdb);
550 	}
551 }
552 
553 static isc_result_t
beginload(dns_db_t * db,dns_rdatacallbacks_t * callbacks)554 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
555 	UNUSED(db);
556 	UNUSED(callbacks);
557 	return (ISC_R_NOTIMPLEMENTED);
558 }
559 
560 static isc_result_t
endload(dns_db_t * db,dns_rdatacallbacks_t * callbacks)561 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
562 	UNUSED(db);
563 	UNUSED(callbacks);
564 	return (ISC_R_NOTIMPLEMENTED);
565 }
566 
567 static isc_result_t
dump(dns_db_t * db,dns_dbversion_t * version,const char * filename,dns_masterformat_t masterformat)568 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
569      dns_masterformat_t masterformat) {
570 	UNUSED(db);
571 	UNUSED(version);
572 	UNUSED(filename);
573 	UNUSED(masterformat);
574 	return (ISC_R_NOTIMPLEMENTED);
575 }
576 
577 static void
currentversion(dns_db_t * db,dns_dbversion_t ** versionp)578 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
579 	REQUIRE(versionp != NULL && *versionp == NULL);
580 
581 	UNUSED(db);
582 
583 	*versionp = (void *)&dummy;
584 	return;
585 }
586 
587 static isc_result_t
newversion(dns_db_t * db,dns_dbversion_t ** versionp)588 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
589 	UNUSED(db);
590 	UNUSED(versionp);
591 
592 	return (ISC_R_NOTIMPLEMENTED);
593 }
594 
595 static void
attachversion(dns_db_t * db,dns_dbversion_t * source,dns_dbversion_t ** targetp)596 attachversion(dns_db_t *db, dns_dbversion_t *source,
597 	      dns_dbversion_t **targetp) {
598 	REQUIRE(source != NULL && source == (void *)&dummy);
599 	REQUIRE(targetp != NULL && *targetp == NULL);
600 
601 	UNUSED(db);
602 	*targetp = source;
603 	return;
604 }
605 
606 static void
closeversion(dns_db_t * db,dns_dbversion_t ** versionp,bool commit)607 closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
608 	REQUIRE(versionp != NULL && *versionp == (void *)&dummy);
609 	REQUIRE(!commit);
610 
611 	UNUSED(db);
612 	UNUSED(commit);
613 
614 	*versionp = NULL;
615 }
616 
617 static isc_result_t
createnode(dns_sdb_t * sdb,dns_sdbnode_t ** nodep)618 createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) {
619 	dns_sdbnode_t *node;
620 
621 	node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t));
622 
623 	node->sdb = NULL;
624 	attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb);
625 	ISC_LIST_INIT(node->lists);
626 	ISC_LIST_INIT(node->buffers);
627 	ISC_LINK_INIT(node, link);
628 	node->name = NULL;
629 	dns_rdatacallbacks_init(&node->callbacks);
630 
631 	isc_refcount_init(&node->references, 1);
632 
633 	node->magic = SDBLOOKUP_MAGIC;
634 
635 	*nodep = node;
636 	return (ISC_R_SUCCESS);
637 }
638 
639 static void
destroynode(dns_sdbnode_t * node)640 destroynode(dns_sdbnode_t *node) {
641 	dns_rdatalist_t *list;
642 	dns_rdata_t *rdata;
643 	isc_buffer_t *b;
644 	dns_sdb_t *sdb;
645 	isc_mem_t *mctx;
646 
647 	sdb = node->sdb;
648 	mctx = sdb->common.mctx;
649 
650 	while (!ISC_LIST_EMPTY(node->lists)) {
651 		list = ISC_LIST_HEAD(node->lists);
652 		while (!ISC_LIST_EMPTY(list->rdata)) {
653 			rdata = ISC_LIST_HEAD(list->rdata);
654 			ISC_LIST_UNLINK(list->rdata, rdata, link);
655 			isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
656 		}
657 		ISC_LIST_UNLINK(node->lists, list, link);
658 		isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
659 	}
660 
661 	while (!ISC_LIST_EMPTY(node->buffers)) {
662 		b = ISC_LIST_HEAD(node->buffers);
663 		ISC_LIST_UNLINK(node->buffers, b, link);
664 		isc_buffer_free(&b);
665 	}
666 
667 	if (node->name != NULL) {
668 		dns_name_free(node->name, mctx);
669 		isc_mem_put(mctx, node->name, sizeof(dns_name_t));
670 	}
671 
672 	node->magic = 0;
673 	isc_mem_put(mctx, node, sizeof(dns_sdbnode_t));
674 	detach((dns_db_t **)(void *)&sdb);
675 }
676 
677 static isc_result_t
getoriginnode(dns_db_t * db,dns_dbnode_t ** nodep)678 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
679 	dns_sdb_t *sdb = (dns_sdb_t *)db;
680 	dns_sdbnode_t *node = NULL;
681 	isc_result_t result;
682 	isc_buffer_t b;
683 	char namestr[DNS_NAME_MAXTEXT + 1];
684 	dns_sdbimplementation_t *imp;
685 	dns_name_t relname;
686 	dns_name_t *name;
687 
688 	REQUIRE(VALID_SDB(sdb));
689 	REQUIRE(nodep != NULL && *nodep == NULL);
690 
691 	imp = sdb->implementation;
692 	name = &sdb->common.origin;
693 
694 	if (imp->methods->lookup2 != NULL) {
695 		if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
696 			dns_name_init(&relname, NULL);
697 			name = &relname;
698 		}
699 	} else {
700 		isc_buffer_init(&b, namestr, sizeof(namestr));
701 		if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
702 			dns_name_init(&relname, NULL);
703 			result = dns_name_totext(&relname, true, &b);
704 			if (result != ISC_R_SUCCESS) {
705 				return (result);
706 			}
707 		} else {
708 			result = dns_name_totext(name, true, &b);
709 			if (result != ISC_R_SUCCESS) {
710 				return (result);
711 			}
712 		}
713 		isc_buffer_putuint8(&b, 0);
714 	}
715 
716 	result = createnode(sdb, &node);
717 	if (result != ISC_R_SUCCESS) {
718 		return (result);
719 	}
720 
721 	MAYBE_LOCK(sdb);
722 	if (imp->methods->lookup2 != NULL) {
723 		result = imp->methods->lookup2(&sdb->common.origin, name,
724 					       sdb->dbdata, node, NULL, NULL);
725 	} else {
726 		result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata,
727 					      node, NULL, NULL);
728 	}
729 	MAYBE_UNLOCK(sdb);
730 	if (result != ISC_R_SUCCESS &&
731 	    !(result == ISC_R_NOTFOUND && imp->methods->authority != NULL))
732 	{
733 		destroynode(node);
734 		return (result);
735 	}
736 
737 	if (imp->methods->authority != NULL) {
738 		MAYBE_LOCK(sdb);
739 		result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
740 		MAYBE_UNLOCK(sdb);
741 		if (result != ISC_R_SUCCESS) {
742 			destroynode(node);
743 			return (result);
744 		}
745 	}
746 
747 	*nodep = node;
748 	return (ISC_R_SUCCESS);
749 }
750 
751 static isc_result_t
findnodeext(dns_db_t * db,const dns_name_t * name,bool create,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo,dns_dbnode_t ** nodep)752 findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
753 	    dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
754 	    dns_dbnode_t **nodep) {
755 	dns_sdb_t *sdb = (dns_sdb_t *)db;
756 	dns_sdbnode_t *node = NULL;
757 	isc_result_t result;
758 	isc_buffer_t b;
759 	char namestr[DNS_NAME_MAXTEXT + 1];
760 	bool isorigin;
761 	dns_sdbimplementation_t *imp;
762 	dns_name_t relname;
763 	unsigned int labels;
764 
765 	REQUIRE(VALID_SDB(sdb));
766 	REQUIRE(nodep != NULL && *nodep == NULL);
767 
768 	UNUSED(name);
769 	UNUSED(create);
770 
771 	imp = sdb->implementation;
772 
773 	isorigin = dns_name_equal(name, &sdb->common.origin);
774 
775 	if (imp->methods->lookup2 != NULL) {
776 		if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
777 			labels = dns_name_countlabels(name) -
778 				 dns_name_countlabels(&db->origin);
779 			dns_name_init(&relname, NULL);
780 			dns_name_getlabelsequence(name, 0, labels, &relname);
781 			name = &relname;
782 		}
783 	} else {
784 		isc_buffer_init(&b, namestr, sizeof(namestr));
785 		if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
786 			labels = dns_name_countlabels(name) -
787 				 dns_name_countlabels(&db->origin);
788 			dns_name_init(&relname, NULL);
789 			dns_name_getlabelsequence(name, 0, labels, &relname);
790 			result = dns_name_totext(&relname, true, &b);
791 			if (result != ISC_R_SUCCESS) {
792 				return (result);
793 			}
794 		} else {
795 			result = dns_name_totext(name, true, &b);
796 			if (result != ISC_R_SUCCESS) {
797 				return (result);
798 			}
799 		}
800 		isc_buffer_putuint8(&b, 0);
801 	}
802 
803 	result = createnode(sdb, &node);
804 	if (result != ISC_R_SUCCESS) {
805 		return (result);
806 	}
807 
808 	MAYBE_LOCK(sdb);
809 	if (imp->methods->lookup2 != NULL) {
810 		result = imp->methods->lookup2(&sdb->common.origin, name,
811 					       sdb->dbdata, node, methods,
812 					       clientinfo);
813 	} else {
814 		result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata,
815 					      node, methods, clientinfo);
816 	}
817 	MAYBE_UNLOCK(sdb);
818 	if (result != ISC_R_SUCCESS && !(result == ISC_R_NOTFOUND && isorigin &&
819 					 imp->methods->authority != NULL))
820 	{
821 		destroynode(node);
822 		return (result);
823 	}
824 
825 	if (isorigin && imp->methods->authority != NULL) {
826 		MAYBE_LOCK(sdb);
827 		result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
828 		MAYBE_UNLOCK(sdb);
829 		if (result != ISC_R_SUCCESS) {
830 			destroynode(node);
831 			return (result);
832 		}
833 	}
834 
835 	*nodep = node;
836 	return (ISC_R_SUCCESS);
837 }
838 
839 static isc_result_t
findext(dns_db_t * db,const 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)840 findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
841 	dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
842 	dns_dbnode_t **nodep, dns_name_t *foundname,
843 	dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
844 	dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
845 	dns_sdb_t *sdb = (dns_sdb_t *)db;
846 	dns_dbnode_t *node = NULL;
847 	dns_fixedname_t fname;
848 	dns_rdataset_t xrdataset;
849 	dns_name_t *xname;
850 	unsigned int nlabels, olabels;
851 	isc_result_t result;
852 	unsigned int i;
853 	unsigned int flags;
854 
855 	REQUIRE(VALID_SDB(sdb));
856 	REQUIRE(nodep == NULL || *nodep == NULL);
857 	REQUIRE(version == NULL || version == (void *)&dummy);
858 
859 	UNUSED(options);
860 
861 	if (!dns_name_issubdomain(name, &db->origin)) {
862 		return (DNS_R_NXDOMAIN);
863 	}
864 
865 	olabels = dns_name_countlabels(&db->origin);
866 	nlabels = dns_name_countlabels(name);
867 
868 	xname = dns_fixedname_initname(&fname);
869 
870 	if (rdataset == NULL) {
871 		dns_rdataset_init(&xrdataset);
872 		rdataset = &xrdataset;
873 	}
874 
875 	result = DNS_R_NXDOMAIN;
876 	flags = sdb->implementation->flags;
877 	i = (flags & DNS_SDBFLAG_DNS64) != 0 ? nlabels : olabels;
878 	for (; i <= nlabels; i++) {
879 		/*
880 		 * Look up the next label.
881 		 */
882 		dns_name_getlabelsequence(name, nlabels - i, i, xname);
883 		result = findnodeext(db, xname, false, methods, clientinfo,
884 				     &node);
885 		if (result == ISC_R_NOTFOUND) {
886 			/*
887 			 * No data at zone apex?
888 			 */
889 			if (i == olabels) {
890 				return (DNS_R_BADDB);
891 			}
892 			result = DNS_R_NXDOMAIN;
893 			continue;
894 		}
895 		if (result != ISC_R_SUCCESS) {
896 			return (result);
897 		}
898 
899 		/*
900 		 * DNS64 zone's don't have DNAME or NS records.
901 		 */
902 		if ((flags & DNS_SDBFLAG_DNS64) != 0) {
903 			goto skip;
904 		}
905 
906 		/*
907 		 * DNS64 zone's don't have DNAME or NS records.
908 		 */
909 		if ((flags & DNS_SDBFLAG_DNS64) != 0) {
910 			goto skip;
911 		}
912 
913 		/*
914 		 * Look for a DNAME at the current label, unless this is
915 		 * the qname.
916 		 */
917 		if (i < nlabels) {
918 			result = findrdataset(db, node, version,
919 					      dns_rdatatype_dname, 0, now,
920 					      rdataset, sigrdataset);
921 			if (result == ISC_R_SUCCESS) {
922 				result = DNS_R_DNAME;
923 				break;
924 			}
925 		}
926 
927 		/*
928 		 * Look for an NS at the current label, unless this is the
929 		 * origin or glue is ok.
930 		 */
931 		if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
932 			result = findrdataset(db, node, version,
933 					      dns_rdatatype_ns, 0, now,
934 					      rdataset, sigrdataset);
935 			if (result == ISC_R_SUCCESS) {
936 				if (i == nlabels && type == dns_rdatatype_any) {
937 					result = DNS_R_ZONECUT;
938 					dns_rdataset_disassociate(rdataset);
939 					if (sigrdataset != NULL &&
940 					    dns_rdataset_isassociated(
941 						    sigrdataset)) {
942 						dns_rdataset_disassociate(
943 							sigrdataset);
944 					}
945 				} else {
946 					result = DNS_R_DELEGATION;
947 				}
948 				break;
949 			}
950 		}
951 
952 		/*
953 		 * If the current name is not the qname, add another label
954 		 * and try again.
955 		 */
956 		if (i < nlabels) {
957 			destroynode(node);
958 			node = NULL;
959 			continue;
960 		}
961 
962 	skip:
963 		/*
964 		 * If we're looking for ANY, we're done.
965 		 */
966 		if (type == dns_rdatatype_any) {
967 			result = ISC_R_SUCCESS;
968 			break;
969 		}
970 
971 		/*
972 		 * Look for the qtype.
973 		 */
974 		result = findrdataset(db, node, version, type, 0, now, rdataset,
975 				      sigrdataset);
976 		if (result == ISC_R_SUCCESS) {
977 			break;
978 		}
979 
980 		/*
981 		 * Look for a CNAME
982 		 */
983 		if (type != dns_rdatatype_cname) {
984 			result = findrdataset(db, node, version,
985 					      dns_rdatatype_cname, 0, now,
986 					      rdataset, sigrdataset);
987 			if (result == ISC_R_SUCCESS) {
988 				result = DNS_R_CNAME;
989 				break;
990 			}
991 		}
992 
993 		result = DNS_R_NXRRSET;
994 		break;
995 	}
996 
997 	if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) {
998 		dns_rdataset_disassociate(rdataset);
999 	}
1000 
1001 	if (foundname != NULL) {
1002 		dns_name_copynf(xname, foundname);
1003 	}
1004 
1005 	if (nodep != NULL) {
1006 		*nodep = node;
1007 	} else if (node != NULL) {
1008 		detachnode(db, &node);
1009 	}
1010 
1011 	return (result);
1012 }
1013 
1014 static isc_result_t
findzonecut(dns_db_t * db,const dns_name_t * name,unsigned int options,isc_stdtime_t now,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_name_t * dcname,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)1015 findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
1016 	    isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
1017 	    dns_name_t *dcname, dns_rdataset_t *rdataset,
1018 	    dns_rdataset_t *sigrdataset) {
1019 	UNUSED(db);
1020 	UNUSED(name);
1021 	UNUSED(options);
1022 	UNUSED(now);
1023 	UNUSED(nodep);
1024 	UNUSED(foundname);
1025 	UNUSED(dcname);
1026 	UNUSED(rdataset);
1027 	UNUSED(sigrdataset);
1028 
1029 	return (ISC_R_NOTIMPLEMENTED);
1030 }
1031 
1032 static void
attachnode(dns_db_t * db,dns_dbnode_t * source,dns_dbnode_t ** targetp)1033 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
1034 	dns_sdb_t *sdb = (dns_sdb_t *)db;
1035 	dns_sdbnode_t *node = (dns_sdbnode_t *)source;
1036 
1037 	REQUIRE(VALID_SDB(sdb));
1038 
1039 	UNUSED(sdb);
1040 
1041 	isc_refcount_increment(&node->references);
1042 
1043 	*targetp = source;
1044 }
1045 
1046 static void
detachnode(dns_db_t * db,dns_dbnode_t ** targetp)1047 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
1048 	dns_sdb_t *sdb = (dns_sdb_t *)db;
1049 	dns_sdbnode_t *node;
1050 
1051 	REQUIRE(VALID_SDB(sdb));
1052 	REQUIRE(targetp != NULL && *targetp != NULL);
1053 
1054 	UNUSED(sdb);
1055 
1056 	node = (dns_sdbnode_t *)(*targetp);
1057 
1058 	*targetp = NULL;
1059 
1060 	if (isc_refcount_decrement(&node->references) == 1) {
1061 		destroynode(node);
1062 	}
1063 }
1064 
1065 static isc_result_t
expirenode(dns_db_t * db,dns_dbnode_t * node,isc_stdtime_t now)1066 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
1067 	UNUSED(db);
1068 	UNUSED(node);
1069 	UNUSED(now);
1070 	INSIST(0);
1071 	ISC_UNREACHABLE();
1072 }
1073 
1074 static void
printnode(dns_db_t * db,dns_dbnode_t * node,FILE * out)1075 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
1076 	UNUSED(db);
1077 	UNUSED(node);
1078 	UNUSED(out);
1079 	return;
1080 }
1081 
1082 static isc_result_t
createiterator(dns_db_t * db,unsigned int options,dns_dbiterator_t ** iteratorp)1083 createiterator(dns_db_t *db, unsigned int options,
1084 	       dns_dbiterator_t **iteratorp) {
1085 	dns_sdb_t *sdb = (dns_sdb_t *)db;
1086 	REQUIRE(VALID_SDB(sdb));
1087 
1088 	sdb_dbiterator_t *sdbiter;
1089 	isc_result_t result;
1090 	dns_sdbimplementation_t *imp = sdb->implementation;
1091 
1092 	if (imp->methods->allnodes == NULL) {
1093 		return (ISC_R_NOTIMPLEMENTED);
1094 	}
1095 
1096 	if ((options & DNS_DB_NSEC3ONLY) != 0 ||
1097 	    (options & DNS_DB_NONSEC3) != 0) {
1098 		return (ISC_R_NOTIMPLEMENTED);
1099 	}
1100 
1101 	sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t));
1102 
1103 	sdbiter->common.methods = &dbiterator_methods;
1104 	sdbiter->common.db = NULL;
1105 	dns_db_attach(db, &sdbiter->common.db);
1106 	sdbiter->common.relative_names = ((options & DNS_DB_RELATIVENAMES) !=
1107 					  0);
1108 	sdbiter->common.magic = DNS_DBITERATOR_MAGIC;
1109 	ISC_LIST_INIT(sdbiter->nodelist);
1110 	sdbiter->current = NULL;
1111 	sdbiter->origin = NULL;
1112 
1113 	MAYBE_LOCK(sdb);
1114 	result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter);
1115 	MAYBE_UNLOCK(sdb);
1116 	if (result != ISC_R_SUCCESS) {
1117 		dbiterator_destroy((dns_dbiterator_t **)(void *)&sdbiter);
1118 		return (result);
1119 	}
1120 
1121 	if (sdbiter->origin != NULL) {
1122 		ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link);
1123 		ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link);
1124 	}
1125 
1126 	*iteratorp = (dns_dbiterator_t *)sdbiter;
1127 
1128 	return (ISC_R_SUCCESS);
1129 }
1130 
1131 static isc_result_t
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)1132 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1133 	     dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
1134 	     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
1135 	REQUIRE(VALID_SDBNODE(node));
1136 
1137 	dns_rdatalist_t *list;
1138 	dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
1139 
1140 	UNUSED(db);
1141 	UNUSED(version);
1142 	UNUSED(covers);
1143 	UNUSED(now);
1144 	UNUSED(sigrdataset);
1145 
1146 	if (type == dns_rdatatype_rrsig) {
1147 		return (ISC_R_NOTIMPLEMENTED);
1148 	}
1149 
1150 	list = ISC_LIST_HEAD(sdbnode->lists);
1151 	while (list != NULL) {
1152 		if (list->type == type) {
1153 			break;
1154 		}
1155 		list = ISC_LIST_NEXT(list, link);
1156 	}
1157 	if (list == NULL) {
1158 		return (ISC_R_NOTFOUND);
1159 	}
1160 
1161 	list_tordataset(list, db, node, rdataset);
1162 
1163 	return (ISC_R_SUCCESS);
1164 }
1165 
1166 static isc_result_t
allrdatasets(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,isc_stdtime_t now,dns_rdatasetiter_t ** iteratorp)1167 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1168 	     isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) {
1169 	sdb_rdatasetiter_t *iterator;
1170 
1171 	REQUIRE(version == NULL || version == &dummy);
1172 
1173 	UNUSED(version);
1174 	UNUSED(now);
1175 
1176 	iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t));
1177 
1178 	iterator->common.magic = DNS_RDATASETITER_MAGIC;
1179 	iterator->common.methods = &rdatasetiter_methods;
1180 	iterator->common.db = db;
1181 	iterator->common.node = NULL;
1182 	attachnode(db, node, &iterator->common.node);
1183 	iterator->common.version = version;
1184 	iterator->common.now = now;
1185 
1186 	*iteratorp = (dns_rdatasetiter_t *)iterator;
1187 
1188 	return (ISC_R_SUCCESS);
1189 }
1190 
1191 static isc_result_t
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)1192 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1193 	    isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
1194 	    dns_rdataset_t *addedrdataset) {
1195 	UNUSED(db);
1196 	UNUSED(node);
1197 	UNUSED(version);
1198 	UNUSED(now);
1199 	UNUSED(rdataset);
1200 	UNUSED(options);
1201 	UNUSED(addedrdataset);
1202 
1203 	return (ISC_R_NOTIMPLEMENTED);
1204 }
1205 
1206 static isc_result_t
subtractrdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdataset_t * rdataset,unsigned int options,dns_rdataset_t * newrdataset)1207 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1208 		 dns_rdataset_t *rdataset, unsigned int options,
1209 		 dns_rdataset_t *newrdataset) {
1210 	UNUSED(db);
1211 	UNUSED(node);
1212 	UNUSED(version);
1213 	UNUSED(rdataset);
1214 	UNUSED(options);
1215 	UNUSED(newrdataset);
1216 
1217 	return (ISC_R_NOTIMPLEMENTED);
1218 }
1219 
1220 static isc_result_t
deleterdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdatatype_t type,dns_rdatatype_t covers)1221 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1222 	       dns_rdatatype_t type, dns_rdatatype_t covers) {
1223 	UNUSED(db);
1224 	UNUSED(node);
1225 	UNUSED(version);
1226 	UNUSED(type);
1227 	UNUSED(covers);
1228 
1229 	return (ISC_R_NOTIMPLEMENTED);
1230 }
1231 
1232 static bool
issecure(dns_db_t * db)1233 issecure(dns_db_t *db) {
1234 	UNUSED(db);
1235 
1236 	return (false);
1237 }
1238 
1239 static unsigned int
nodecount(dns_db_t * db)1240 nodecount(dns_db_t *db) {
1241 	UNUSED(db);
1242 
1243 	return (0);
1244 }
1245 
1246 static bool
ispersistent(dns_db_t * db)1247 ispersistent(dns_db_t *db) {
1248 	UNUSED(db);
1249 	return (true);
1250 }
1251 
1252 static void
overmem(dns_db_t * db,bool over)1253 overmem(dns_db_t *db, bool over) {
1254 	UNUSED(db);
1255 	UNUSED(over);
1256 }
1257 
1258 static void
settask(dns_db_t * db,isc_task_t * task)1259 settask(dns_db_t *db, isc_task_t *task) {
1260 	UNUSED(db);
1261 	UNUSED(task);
1262 }
1263 
1264 static dns_dbmethods_t sdb_methods = {
1265 	attach,
1266 	detach,
1267 	beginload,
1268 	endload,
1269 	NULL, /* serialize */
1270 	dump,
1271 	currentversion,
1272 	newversion,
1273 	attachversion,
1274 	closeversion,
1275 	NULL, /* findnode */
1276 	NULL, /* find */
1277 	findzonecut,
1278 	attachnode,
1279 	detachnode,
1280 	expirenode,
1281 	printnode,
1282 	createiterator,
1283 	findrdataset,
1284 	allrdatasets,
1285 	addrdataset,
1286 	subtractrdataset,
1287 	deleterdataset,
1288 	issecure,
1289 	nodecount,
1290 	ispersistent,
1291 	overmem,
1292 	settask,
1293 	getoriginnode, /* getoriginnode */
1294 	NULL,	       /* transfernode */
1295 	NULL,	       /* getnsec3parameters */
1296 	NULL,	       /* findnsec3node */
1297 	NULL,	       /* setsigningtime */
1298 	NULL,	       /* getsigningtime */
1299 	NULL,	       /* resigned */
1300 	NULL,	       /* isdnssec */
1301 	NULL,	       /* getrrsetstats */
1302 	NULL,	       /* rpz_attach */
1303 	NULL,	       /* rpz_ready */
1304 	findnodeext,
1305 	findext,
1306 	NULL, /* setcachestats */
1307 	NULL, /* hashsize */
1308 	NULL, /* nodefullname */
1309 	NULL, /* getsize */
1310 	NULL, /* setservestalettl */
1311 	NULL, /* getservestalettl */
1312 	NULL  /* setgluecachestats */
1313 };
1314 
1315 static isc_result_t
dns_sdb_create(isc_mem_t * mctx,const dns_name_t * origin,dns_dbtype_t type,dns_rdataclass_t rdclass,unsigned int argc,char * argv[],void * driverarg,dns_db_t ** dbp)1316 dns_sdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
1317 	       dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
1318 	       void *driverarg, dns_db_t **dbp) {
1319 	dns_sdb_t *sdb;
1320 	isc_result_t result;
1321 	char zonestr[DNS_NAME_MAXTEXT + 1];
1322 	isc_buffer_t b;
1323 	dns_sdbimplementation_t *imp;
1324 
1325 	REQUIRE(driverarg != NULL);
1326 
1327 	imp = driverarg;
1328 
1329 	if (type != dns_dbtype_zone) {
1330 		return (ISC_R_NOTIMPLEMENTED);
1331 	}
1332 
1333 	sdb = isc_mem_get(mctx, sizeof(dns_sdb_t));
1334 	memset(sdb, 0, sizeof(dns_sdb_t));
1335 
1336 	dns_name_init(&sdb->common.origin, NULL);
1337 	sdb->common.attributes = 0;
1338 	sdb->common.methods = &sdb_methods;
1339 	sdb->common.rdclass = rdclass;
1340 	sdb->common.mctx = NULL;
1341 	sdb->implementation = imp;
1342 
1343 	isc_mem_attach(mctx, &sdb->common.mctx);
1344 
1345 	result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
1346 	if (result != ISC_R_SUCCESS) {
1347 		goto cleanup_lock;
1348 	}
1349 
1350 	isc_buffer_init(&b, zonestr, sizeof(zonestr));
1351 	result = dns_name_totext(origin, true, &b);
1352 	if (result != ISC_R_SUCCESS) {
1353 		goto cleanup_origin;
1354 	}
1355 	isc_buffer_putuint8(&b, 0);
1356 
1357 	sdb->zone = isc_mem_strdup(mctx, zonestr);
1358 
1359 	sdb->dbdata = NULL;
1360 	if (imp->methods->create != NULL) {
1361 		MAYBE_LOCK(sdb);
1362 		result = imp->methods->create(sdb->zone, argc, argv,
1363 					      imp->driverdata, &sdb->dbdata);
1364 		MAYBE_UNLOCK(sdb);
1365 		if (result != ISC_R_SUCCESS) {
1366 			goto cleanup_zonestr;
1367 		}
1368 	}
1369 
1370 	isc_refcount_init(&sdb->references, 1);
1371 
1372 	sdb->common.magic = DNS_DB_MAGIC;
1373 	sdb->common.impmagic = SDB_MAGIC;
1374 
1375 	*dbp = (dns_db_t *)sdb;
1376 
1377 	return (ISC_R_SUCCESS);
1378 
1379 cleanup_zonestr:
1380 	isc_mem_free(mctx, sdb->zone);
1381 cleanup_origin:
1382 	dns_name_free(&sdb->common.origin, mctx);
1383 cleanup_lock:
1384 	isc_mem_putanddetach(&mctx, sdb, sizeof(dns_sdb_t));
1385 
1386 	return (result);
1387 }
1388 
1389 /*
1390  * Rdataset Methods
1391  */
1392 
1393 static void
disassociate(dns_rdataset_t * rdataset)1394 disassociate(dns_rdataset_t *rdataset) {
1395 	dns_dbnode_t *node = rdataset->private5;
1396 	dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
1397 	dns_db_t *db = (dns_db_t *)sdbnode->sdb;
1398 
1399 	detachnode(db, &node);
1400 	isc__rdatalist_disassociate(rdataset);
1401 }
1402 
1403 static void
rdataset_clone(dns_rdataset_t * source,dns_rdataset_t * target)1404 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1405 	dns_dbnode_t *node = source->private5;
1406 	dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
1407 	dns_db_t *db = (dns_db_t *)sdbnode->sdb;
1408 	dns_dbnode_t *tempdb = NULL;
1409 
1410 	isc__rdatalist_clone(source, target);
1411 	attachnode(db, node, &tempdb);
1412 	source->private5 = tempdb;
1413 }
1414 
1415 static dns_rdatasetmethods_t sdb_rdataset_methods = {
1416 	disassociate,
1417 	isc__rdatalist_first,
1418 	isc__rdatalist_next,
1419 	isc__rdatalist_current,
1420 	rdataset_clone,
1421 	isc__rdatalist_count,
1422 	isc__rdatalist_addnoqname,
1423 	isc__rdatalist_getnoqname,
1424 	NULL, /* addclosest */
1425 	NULL, /* getclosest */
1426 	NULL, /* settrust */
1427 	NULL, /* expire */
1428 	NULL, /* clearprefetch */
1429 	NULL, /* setownercase */
1430 	NULL, /* getownercase */
1431 	NULL  /* addglue */
1432 };
1433 
1434 static void
list_tordataset(dns_rdatalist_t * rdatalist,dns_db_t * db,dns_dbnode_t * node,dns_rdataset_t * rdataset)1435 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
1436 		dns_rdataset_t *rdataset) {
1437 	/*
1438 	 * The sdb rdataset is an rdatalist with some additions.
1439 	 *	- private1 & private2 are used by the rdatalist.
1440 	 *	- private3 & private 4 are unused.
1441 	 *	- private5 is the node.
1442 	 */
1443 
1444 	/* This should never fail. */
1445 	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1446 		      ISC_R_SUCCESS);
1447 
1448 	rdataset->methods = &sdb_rdataset_methods;
1449 	dns_db_attachnode(db, node, &rdataset->private5);
1450 }
1451 
1452 /*
1453  * Database Iterator Methods
1454  */
1455 static void
dbiterator_destroy(dns_dbiterator_t ** iteratorp)1456 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1457 	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp);
1458 	dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db;
1459 
1460 	while (!ISC_LIST_EMPTY(sdbiter->nodelist)) {
1461 		dns_sdbnode_t *node;
1462 		node = ISC_LIST_HEAD(sdbiter->nodelist);
1463 		ISC_LIST_UNLINK(sdbiter->nodelist, node, link);
1464 		destroynode(node);
1465 	}
1466 
1467 	dns_db_detach(&sdbiter->common.db);
1468 	isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t));
1469 
1470 	*iteratorp = NULL;
1471 }
1472 
1473 static isc_result_t
dbiterator_first(dns_dbiterator_t * iterator)1474 dbiterator_first(dns_dbiterator_t *iterator) {
1475 	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1476 
1477 	sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1478 	if (sdbiter->current == NULL) {
1479 		return (ISC_R_NOMORE);
1480 	} else {
1481 		return (ISC_R_SUCCESS);
1482 	}
1483 }
1484 
1485 static isc_result_t
dbiterator_last(dns_dbiterator_t * iterator)1486 dbiterator_last(dns_dbiterator_t *iterator) {
1487 	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1488 
1489 	sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist);
1490 	if (sdbiter->current == NULL) {
1491 		return (ISC_R_NOMORE);
1492 	} else {
1493 		return (ISC_R_SUCCESS);
1494 	}
1495 }
1496 
1497 static isc_result_t
dbiterator_seek(dns_dbiterator_t * iterator,const dns_name_t * name)1498 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) {
1499 	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1500 
1501 	sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1502 	while (sdbiter->current != NULL) {
1503 		if (dns_name_equal(sdbiter->current->name, name)) {
1504 			return (ISC_R_SUCCESS);
1505 		}
1506 		sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
1507 	}
1508 	return (ISC_R_NOTFOUND);
1509 }
1510 
1511 static isc_result_t
dbiterator_prev(dns_dbiterator_t * iterator)1512 dbiterator_prev(dns_dbiterator_t *iterator) {
1513 	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1514 
1515 	sdbiter->current = ISC_LIST_PREV(sdbiter->current, link);
1516 	if (sdbiter->current == NULL) {
1517 		return (ISC_R_NOMORE);
1518 	} else {
1519 		return (ISC_R_SUCCESS);
1520 	}
1521 }
1522 
1523 static isc_result_t
dbiterator_next(dns_dbiterator_t * iterator)1524 dbiterator_next(dns_dbiterator_t *iterator) {
1525 	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1526 
1527 	sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
1528 	if (sdbiter->current == NULL) {
1529 		return (ISC_R_NOMORE);
1530 	} else {
1531 		return (ISC_R_SUCCESS);
1532 	}
1533 }
1534 
1535 static isc_result_t
dbiterator_current(dns_dbiterator_t * iterator,dns_dbnode_t ** nodep,dns_name_t * name)1536 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1537 		   dns_name_t *name) {
1538 	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1539 
1540 	attachnode(iterator->db, sdbiter->current, nodep);
1541 	if (name != NULL) {
1542 		dns_name_copynf(sdbiter->current->name, name);
1543 		return (ISC_R_SUCCESS);
1544 	}
1545 	return (ISC_R_SUCCESS);
1546 }
1547 
1548 static isc_result_t
dbiterator_pause(dns_dbiterator_t * iterator)1549 dbiterator_pause(dns_dbiterator_t *iterator) {
1550 	UNUSED(iterator);
1551 	return (ISC_R_SUCCESS);
1552 }
1553 
1554 static isc_result_t
dbiterator_origin(dns_dbiterator_t * iterator,dns_name_t * name)1555 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1556 	UNUSED(iterator);
1557 	dns_name_copynf(dns_rootname, name);
1558 	return (ISC_R_SUCCESS);
1559 }
1560 
1561 /*
1562  * Rdataset Iterator Methods
1563  */
1564 
1565 static void
rdatasetiter_destroy(dns_rdatasetiter_t ** iteratorp)1566 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
1567 	sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp);
1568 	detachnode(sdbiterator->common.db, &sdbiterator->common.node);
1569 	isc_mem_put(sdbiterator->common.db->mctx, sdbiterator,
1570 		    sizeof(sdb_rdatasetiter_t));
1571 	*iteratorp = NULL;
1572 }
1573 
1574 static isc_result_t
rdatasetiter_first(dns_rdatasetiter_t * iterator)1575 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
1576 	sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1577 	dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node;
1578 
1579 	if (ISC_LIST_EMPTY(sdbnode->lists)) {
1580 		return (ISC_R_NOMORE);
1581 	}
1582 	sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists);
1583 	return (ISC_R_SUCCESS);
1584 }
1585 
1586 static isc_result_t
rdatasetiter_next(dns_rdatasetiter_t * iterator)1587 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
1588 	sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1589 
1590 	sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link);
1591 	if (sdbiterator->current == NULL) {
1592 		return (ISC_R_NOMORE);
1593 	} else {
1594 		return (ISC_R_SUCCESS);
1595 	}
1596 }
1597 
1598 static void
rdatasetiter_current(dns_rdatasetiter_t * iterator,dns_rdataset_t * rdataset)1599 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
1600 	sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1601 
1602 	list_tordataset(sdbiterator->current, iterator->db, iterator->node,
1603 			rdataset);
1604 }
1605