xref: /minix/external/bsd/bind/dist/lib/dns/sdlz.c (revision 00b67f09)
1 /*	$NetBSD: sdlz.c,v 1.9 2015/07/08 17:28:59 christos Exp $	*/
2 
3 /*
4  * Portions Copyright (C) 2005-2014  Internet Systems Consortium, Inc. ("ISC")
5  * Portions Copyright (C) 1999-2001  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
22  *
23  * Permission to use, copy, modify, and distribute this software for any
24  * purpose with or without fee is hereby granted, provided that the
25  * above copyright notice and this permission notice appear in all
26  * copies.
27  *
28  * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
29  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
31  * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
32  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
33  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
34  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
35  * USE OR PERFORMANCE OF THIS SOFTWARE.
36  *
37  * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
38  * conceived and contributed by Rob Butler.
39  *
40  * Permission to use, copy, modify, and distribute this software for any
41  * purpose with or without fee is hereby granted, provided that the
42  * above copyright notice and this permission notice appear in all
43  * copies.
44  *
45  * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
46  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
48  * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
49  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
50  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
51  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
52  * USE OR PERFORMANCE OF THIS SOFTWARE.
53  */
54 
55 /* Id */
56 
57 /*! \file */
58 
59 #include <config.h>
60 #include <string.h>
61 
62 #include <isc/buffer.h>
63 #include <isc/lex.h>
64 #include <isc/log.h>
65 #include <isc/rwlock.h>
66 #include <isc/string.h>
67 #include <isc/util.h>
68 #include <isc/magic.h>
69 #include <isc/mem.h>
70 #include <isc/once.h>
71 #include <isc/print.h>
72 #include <isc/region.h>
73 
74 #include <dns/callbacks.h>
75 #include <dns/db.h>
76 #include <dns/dbiterator.h>
77 #include <dns/dlz.h>
78 #include <dns/fixedname.h>
79 #include <dns/log.h>
80 #include <dns/rdata.h>
81 #include <dns/rdatalist.h>
82 #include <dns/rdataset.h>
83 #include <dns/rdatasetiter.h>
84 #include <dns/rdatatype.h>
85 #include <dns/result.h>
86 #include <dns/master.h>
87 #include <dns/sdlz.h>
88 #include <dns/types.h>
89 
90 #include "rdatalist_p.h"
91 
92 /*
93  * Private Types
94  */
95 
96 struct dns_sdlzimplementation {
97 	const dns_sdlzmethods_t		*methods;
98 	isc_mem_t			*mctx;
99 	void				*driverarg;
100 	unsigned int			flags;
101 	isc_mutex_t			driverlock;
102 	dns_dlzimplementation_t		*dlz_imp;
103 };
104 
105 struct dns_sdlz_db {
106 	/* Unlocked */
107 	dns_db_t			common;
108 	void				*dbdata;
109 	dns_sdlzimplementation_t	*dlzimp;
110 	isc_mutex_t			refcnt_lock;
111 	/* Locked */
112 	unsigned int			references;
113 	dns_dbversion_t			*future_version;
114 	int				dummy_version;
115 };
116 
117 struct dns_sdlzlookup {
118 	/* Unlocked */
119 	unsigned int			magic;
120 	dns_sdlz_db_t			*sdlz;
121 	ISC_LIST(dns_rdatalist_t)	lists;
122 	ISC_LIST(isc_buffer_t)		buffers;
123 	dns_name_t			*name;
124 	ISC_LINK(dns_sdlzlookup_t)	link;
125 	isc_mutex_t			lock;
126 	dns_rdatacallbacks_t		callbacks;
127 	/* Locked */
128 	unsigned int			references;
129 };
130 
131 typedef struct dns_sdlzlookup dns_sdlznode_t;
132 
133 struct dns_sdlzallnodes {
134 	dns_dbiterator_t		common;
135 	ISC_LIST(dns_sdlznode_t)	nodelist;
136 	dns_sdlznode_t			*current;
137 	dns_sdlznode_t			*origin;
138 };
139 
140 typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
141 
142 typedef struct sdlz_rdatasetiter {
143 	dns_rdatasetiter_t		common;
144 	dns_rdatalist_t			*current;
145 } sdlz_rdatasetiter_t;
146 
147 
148 #define SDLZDB_MAGIC		ISC_MAGIC('D', 'L', 'Z', 'S')
149 
150 /*
151  * Note that "impmagic" is not the first four bytes of the struct, so
152  * ISC_MAGIC_VALID cannot be used.
153  */
154 
155 #define VALID_SDLZDB(sdlzdb)	((sdlzdb) != NULL && \
156 				 (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
157 
158 #define SDLZLOOKUP_MAGIC	ISC_MAGIC('D','L','Z','L')
159 #define VALID_SDLZLOOKUP(sdlzl)	ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
160 #define VALID_SDLZNODE(sdlzn)	VALID_SDLZLOOKUP(sdlzn)
161 
162 /* These values are taken from RFC 1537 */
163 #define SDLZ_DEFAULT_REFRESH	(60 * 60 * 8)
164 #define SDLZ_DEFAULT_RETRY	(60 * 60 * 2)
165 #define SDLZ_DEFAULT_EXPIRE	(60 * 60 * 24 * 7)
166 #define SDLZ_DEFAULT_MINIMUM	(60 * 60 * 24)
167 
168 /* This is a reasonable value */
169 #define SDLZ_DEFAULT_TTL	(60 * 60 * 24)
170 
171 #ifdef __COVERITY__
172 #define MAYBE_LOCK(imp) LOCK(&imp->driverlock)
173 #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
174 #else
175 #define MAYBE_LOCK(imp) \
176 	do { \
177 		unsigned int flags = imp->flags; \
178 		if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
179 			LOCK(&imp->driverlock); \
180 	} while (/*CONSTCOND*/0)
181 
182 #define MAYBE_UNLOCK(imp) \
183 	do { \
184 		unsigned int flags = imp->flags; \
185 		if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
186 			UNLOCK(&imp->driverlock); \
187 	} while (/*CONSTCOND*/0)
188 #endif
189 
190 /*
191  * Forward references.  Try to keep these to a minimum.
192  */
193 
194 static void list_tordataset(dns_rdatalist_t *rdatalist,
195 			    dns_db_t *db, dns_dbnode_t *node,
196 			    dns_rdataset_t *rdataset);
197 
198 static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
199 
200 static void		dbiterator_destroy(dns_dbiterator_t **iteratorp);
201 static isc_result_t	dbiterator_first(dns_dbiterator_t *iterator);
202 static isc_result_t	dbiterator_last(dns_dbiterator_t *iterator);
203 static isc_result_t	dbiterator_seek(dns_dbiterator_t *iterator,
204 					dns_name_t *name);
205 static isc_result_t	dbiterator_prev(dns_dbiterator_t *iterator);
206 static isc_result_t	dbiterator_next(dns_dbiterator_t *iterator);
207 static isc_result_t	dbiterator_current(dns_dbiterator_t *iterator,
208 					   dns_dbnode_t **nodep,
209 					   dns_name_t *name);
210 static isc_result_t	dbiterator_pause(dns_dbiterator_t *iterator);
211 static isc_result_t	dbiterator_origin(dns_dbiterator_t *iterator,
212 					  dns_name_t *name);
213 
214 static dns_dbiteratormethods_t dbiterator_methods = {
215 	dbiterator_destroy,
216 	dbiterator_first,
217 	dbiterator_last,
218 	dbiterator_seek,
219 	dbiterator_prev,
220 	dbiterator_next,
221 	dbiterator_current,
222 	dbiterator_pause,
223 	dbiterator_origin
224 };
225 
226 /*
227  * Utility functions
228  */
229 
230 /*
231  * Log a message at the given level
232  */
233 static void
sdlz_log(int level,const char * fmt,...)234 sdlz_log(int level, const char *fmt, ...) {
235 	va_list ap;
236 	va_start(ap, fmt);
237 	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
238 		       DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level),
239 		       fmt, ap);
240 	va_end(ap);
241 }
242 
243 /*% Converts the input string to lowercase, in place. */
244 static void
dns_sdlz_tolower(char * str)245 dns_sdlz_tolower(char *str) {
246 	unsigned int len = strlen(str);
247 	unsigned int i;
248 
249 	for (i = 0; i < len; i++) {
250 		if (str[i] >= 'A' && str[i] <= 'Z')
251 			str[i] += 32;
252 	}
253 }
254 
255 static inline unsigned int
initial_size(const char * data)256 initial_size(const char *data) {
257 	unsigned int len = (strlen(data) / 64) + 1;
258 	return (len * 64 + 64);
259 }
260 
261 /*
262  * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
263  * driver interface.  See the SDB driver interface documentation for more info.
264  */
265 
266 static void
rdatasetiter_destroy(dns_rdatasetiter_t ** iteratorp)267 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
268 	sdlz_rdatasetiter_t *sdlziterator =
269 		(sdlz_rdatasetiter_t *)(*iteratorp);
270 
271 	detachnode(sdlziterator->common.db, &sdlziterator->common.node);
272 	isc_mem_put(sdlziterator->common.db->mctx, sdlziterator,
273 		    sizeof(sdlz_rdatasetiter_t));
274 	*iteratorp = NULL;
275 }
276 
277 static isc_result_t
rdatasetiter_first(dns_rdatasetiter_t * iterator)278 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
279 	sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
280 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node;
281 
282 	if (ISC_LIST_EMPTY(sdlznode->lists))
283 		return (ISC_R_NOMORE);
284 	sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
285 	return (ISC_R_SUCCESS);
286 }
287 
288 static isc_result_t
rdatasetiter_next(dns_rdatasetiter_t * iterator)289 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
290 	sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
291 
292 	sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
293 	if (sdlziterator->current == NULL)
294 		return (ISC_R_NOMORE);
295 	else
296 		return (ISC_R_SUCCESS);
297 }
298 
299 static void
rdatasetiter_current(dns_rdatasetiter_t * iterator,dns_rdataset_t * rdataset)300 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
301 	sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
302 
303 	list_tordataset(sdlziterator->current, iterator->db, iterator->node,
304 			rdataset);
305 }
306 
307 static dns_rdatasetitermethods_t rdatasetiter_methods = {
308 	rdatasetiter_destroy,
309 	rdatasetiter_first,
310 	rdatasetiter_next,
311 	rdatasetiter_current
312 };
313 
314 /*
315  * DB routines. These methods were "borrowed" from the SDB driver interface.
316  * See the SDB driver interface documentation for more info.
317  */
318 
319 static void
attach(dns_db_t * source,dns_db_t ** targetp)320 attach(dns_db_t *source, dns_db_t **targetp) {
321 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) source;
322 
323 	REQUIRE(VALID_SDLZDB(sdlz));
324 
325 	LOCK(&sdlz->refcnt_lock);
326 	REQUIRE(sdlz->references > 0);
327 	sdlz->references++;
328 	UNLOCK(&sdlz->refcnt_lock);
329 
330 	*targetp = source;
331 }
332 
333 static void
destroy(dns_sdlz_db_t * sdlz)334 destroy(dns_sdlz_db_t *sdlz) {
335 	isc_mem_t *mctx;
336 	mctx = sdlz->common.mctx;
337 
338 	sdlz->common.magic = 0;
339 	sdlz->common.impmagic = 0;
340 
341 	(void)isc_mutex_destroy(&sdlz->refcnt_lock);
342 
343 	dns_name_free(&sdlz->common.origin, mctx);
344 
345 	isc_mem_put(mctx, sdlz, sizeof(dns_sdlz_db_t));
346 	isc_mem_detach(&mctx);
347 }
348 
349 static void
detach(dns_db_t ** dbp)350 detach(dns_db_t **dbp) {
351 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
352 	isc_boolean_t need_destroy = ISC_FALSE;
353 
354 	REQUIRE(VALID_SDLZDB(sdlz));
355 	LOCK(&sdlz->refcnt_lock);
356 	REQUIRE(sdlz->references > 0);
357 	sdlz->references--;
358 	if (sdlz->references == 0)
359 		need_destroy = ISC_TRUE;
360 	UNLOCK(&sdlz->refcnt_lock);
361 
362 	if (need_destroy)
363 		destroy(sdlz);
364 
365 	*dbp = NULL;
366 }
367 
368 static isc_result_t
beginload(dns_db_t * db,dns_rdatacallbacks_t * callbacks)369 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
370 	UNUSED(db);
371 	UNUSED(callbacks);
372 	return (ISC_R_NOTIMPLEMENTED);
373 }
374 
375 static isc_result_t
endload(dns_db_t * db,dns_rdatacallbacks_t * callbacks)376 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
377 	UNUSED(db);
378 	UNUSED(callbacks);
379 	return (ISC_R_NOTIMPLEMENTED);
380 }
381 
382 static isc_result_t
dump(dns_db_t * db,dns_dbversion_t * version,const char * filename,dns_masterformat_t masterformat)383 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
384      dns_masterformat_t masterformat)
385 {
386 	UNUSED(db);
387 	UNUSED(version);
388 	UNUSED(filename);
389 	UNUSED(masterformat);
390 	return (ISC_R_NOTIMPLEMENTED);
391 }
392 
393 static void
currentversion(dns_db_t * db,dns_dbversion_t ** versionp)394 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
395 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
396 	REQUIRE(VALID_SDLZDB(sdlz));
397 	REQUIRE(versionp != NULL && *versionp == NULL);
398 
399 	*versionp = (void *) &sdlz->dummy_version;
400 	return;
401 }
402 
403 static isc_result_t
newversion(dns_db_t * db,dns_dbversion_t ** versionp)404 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
405 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
406 	char origin[DNS_NAME_MAXTEXT + 1];
407 	isc_result_t result;
408 
409 	REQUIRE(VALID_SDLZDB(sdlz));
410 
411 	if (sdlz->dlzimp->methods->newversion == NULL)
412 		return (ISC_R_NOTIMPLEMENTED);
413 
414 	dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
415 
416 	result = sdlz->dlzimp->methods->newversion(origin,
417 						   sdlz->dlzimp->driverarg,
418 						   sdlz->dbdata, versionp);
419 	if (result != ISC_R_SUCCESS) {
420 		sdlz_log(ISC_LOG_ERROR,
421 			 "sdlz newversion on origin %s failed : %s",
422 			 origin, isc_result_totext(result));
423 		return (result);
424 	}
425 
426 	sdlz->future_version = *versionp;
427 	return (ISC_R_SUCCESS);
428 }
429 
430 static void
attachversion(dns_db_t * db,dns_dbversion_t * source,dns_dbversion_t ** targetp)431 attachversion(dns_db_t *db, dns_dbversion_t *source,
432 	      dns_dbversion_t **targetp)
433 {
434 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
435 
436 	REQUIRE(VALID_SDLZDB(sdlz));
437 	REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version);
438 
439 	*targetp = source;
440 }
441 
442 static void
closeversion(dns_db_t * db,dns_dbversion_t ** versionp,isc_boolean_t commit)443 closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
444 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
445 	char origin[DNS_NAME_MAXTEXT + 1];
446 
447 	REQUIRE(VALID_SDLZDB(sdlz));
448 	REQUIRE(versionp != NULL);
449 
450 	if (*versionp == (void *)&sdlz->dummy_version) {
451 		*versionp = NULL;
452 		return;
453 	}
454 
455 	REQUIRE(*versionp == sdlz->future_version);
456 	REQUIRE(sdlz->dlzimp->methods->closeversion != NULL);
457 
458 	dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
459 
460 	sdlz->dlzimp->methods->closeversion(origin, commit,
461 					    sdlz->dlzimp->driverarg,
462 					    sdlz->dbdata, versionp);
463 	if (*versionp != NULL)
464 		sdlz_log(ISC_LOG_ERROR,
465 			"sdlz closeversion on origin %s failed", origin);
466 
467 	sdlz->future_version = NULL;
468 }
469 
470 static isc_result_t
createnode(dns_sdlz_db_t * sdlz,dns_sdlznode_t ** nodep)471 createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
472 	dns_sdlznode_t *node;
473 	isc_result_t result;
474 	void *sdlzv, *tdlzv;
475 
476 	node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
477 	if (node == NULL)
478 		return (ISC_R_NOMEMORY);
479 
480 	node->sdlz = NULL;
481 	sdlzv = sdlz;
482 	tdlzv = &node->sdlz;
483 	attach(sdlzv, tdlzv);
484 	ISC_LIST_INIT(node->lists);
485 	ISC_LIST_INIT(node->buffers);
486 	ISC_LINK_INIT(node, link);
487 	node->name = NULL;
488 	result = isc_mutex_init(&node->lock);
489 	if (result != ISC_R_SUCCESS) {
490 		UNEXPECTED_ERROR(__FILE__, __LINE__,
491 				 "isc_mutex_init() failed: %s",
492 				 isc_result_totext(result));
493 		isc_mem_put(sdlz->common.mctx, node, sizeof(dns_sdlznode_t));
494 		return (ISC_R_UNEXPECTED);
495 	}
496 	dns_rdatacallbacks_init(&node->callbacks);
497 	node->references = 1;
498 	node->magic = SDLZLOOKUP_MAGIC;
499 
500 	*nodep = node;
501 	return (ISC_R_SUCCESS);
502 }
503 
504 static void
destroynode(dns_sdlznode_t * node)505 destroynode(dns_sdlznode_t *node) {
506 	dns_rdatalist_t *list;
507 	dns_rdata_t *rdata;
508 	isc_buffer_t *b;
509 	dns_sdlz_db_t *sdlz;
510 	dns_db_t *db;
511 	isc_mem_t *mctx;
512 
513 	sdlz = node->sdlz;
514 	mctx = sdlz->common.mctx;
515 
516 	while (!ISC_LIST_EMPTY(node->lists)) {
517 		list = ISC_LIST_HEAD(node->lists);
518 		while (!ISC_LIST_EMPTY(list->rdata)) {
519 			rdata = ISC_LIST_HEAD(list->rdata);
520 			ISC_LIST_UNLINK(list->rdata, rdata, link);
521 			isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
522 		}
523 		ISC_LIST_UNLINK(node->lists, list, link);
524 		isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
525 	}
526 
527 	while (!ISC_LIST_EMPTY(node->buffers)) {
528 		b = ISC_LIST_HEAD(node->buffers);
529 		ISC_LIST_UNLINK(node->buffers, b, link);
530 		isc_buffer_free(&b);
531 	}
532 
533 	if (node->name != NULL) {
534 		dns_name_free(node->name, mctx);
535 		isc_mem_put(mctx, node->name, sizeof(dns_name_t));
536 	}
537 	DESTROYLOCK(&node->lock);
538 	node->magic = 0;
539 	isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
540 	db = &sdlz->common;
541 	detach(&db);
542 }
543 
544 static isc_result_t
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)545 findnodeext(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
546 	    dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
547 	    dns_dbnode_t **nodep)
548 {
549 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
550 	dns_sdlznode_t *node = NULL;
551 	isc_result_t result;
552 	isc_buffer_t b;
553 	char namestr[DNS_NAME_MAXTEXT + 1];
554 	isc_buffer_t b2;
555 	char zonestr[DNS_NAME_MAXTEXT + 1];
556 	isc_boolean_t isorigin;
557 	dns_sdlzauthorityfunc_t authority;
558 
559 	REQUIRE(VALID_SDLZDB(sdlz));
560 	REQUIRE(nodep != NULL && *nodep == NULL);
561 
562 	if (sdlz->dlzimp->methods->newversion == NULL) {
563 		REQUIRE(create == ISC_FALSE);
564 	}
565 
566 	isc_buffer_init(&b, namestr, sizeof(namestr));
567 	if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
568 		dns_name_t relname;
569 		unsigned int labels;
570 
571 		labels = dns_name_countlabels(name) -
572 			 dns_name_countlabels(&db->origin);
573 		dns_name_init(&relname, NULL);
574 		dns_name_getlabelsequence(name, 0, labels, &relname);
575 		result = dns_name_totext(&relname, ISC_TRUE, &b);
576 		if (result != ISC_R_SUCCESS)
577 			return (result);
578 	} else {
579 		result = dns_name_totext(name, ISC_TRUE, &b);
580 		if (result != ISC_R_SUCCESS)
581 			return (result);
582 	}
583 	isc_buffer_putuint8(&b, 0);
584 
585 	isc_buffer_init(&b2, zonestr, sizeof(zonestr));
586 	result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b2);
587 	if (result != ISC_R_SUCCESS)
588 		return (result);
589 	isc_buffer_putuint8(&b2, 0);
590 
591 	result = createnode(sdlz, &node);
592 	if (result != ISC_R_SUCCESS)
593 		return (result);
594 
595 	isorigin = dns_name_equal(name, &sdlz->common.origin);
596 
597 	/* make sure strings are always lowercase */
598 	dns_sdlz_tolower(zonestr);
599 	dns_sdlz_tolower(namestr);
600 
601 	MAYBE_LOCK(sdlz->dlzimp);
602 
603 	/* try to lookup the host (namestr) */
604 	result = sdlz->dlzimp->methods->lookup(zonestr, namestr,
605 					       sdlz->dlzimp->driverarg,
606 					       sdlz->dbdata, node,
607 					       methods, clientinfo);
608 
609 	/*
610 	 * if the host (namestr) was not found, try to lookup a
611 	 * "wildcard" host.
612 	 */
613 	if (result == ISC_R_NOTFOUND && !create)
614 		result = sdlz->dlzimp->methods->lookup(zonestr, "*",
615 						       sdlz->dlzimp->driverarg,
616 						       sdlz->dbdata, node,
617 						       methods, clientinfo);
618 
619 	MAYBE_UNLOCK(sdlz->dlzimp);
620 
621 	if (result == ISC_R_NOTFOUND && (isorigin || create))
622 		result = ISC_R_SUCCESS;
623 
624 	if (result != ISC_R_SUCCESS) {
625 		destroynode(node);
626 		return (result);
627 	}
628 
629 	if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
630 		MAYBE_LOCK(sdlz->dlzimp);
631 		authority = sdlz->dlzimp->methods->authority;
632 		result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
633 				      sdlz->dbdata, node);
634 		MAYBE_UNLOCK(sdlz->dlzimp);
635 		if (result != ISC_R_SUCCESS &&
636 		    result != ISC_R_NOTIMPLEMENTED)
637 		{
638 			destroynode(node);
639 			return (result);
640 		}
641 	}
642 
643 	if (node->name == NULL) {
644 		node->name = isc_mem_get(sdlz->common.mctx,
645 					 sizeof(dns_name_t));
646 		if (node->name == NULL) {
647 			destroynode(node);
648 			return (ISC_R_NOMEMORY);
649 		}
650 		dns_name_init(node->name, NULL);
651 		result = dns_name_dup(name, sdlz->common.mctx, node->name);
652 		if (result != ISC_R_SUCCESS) {
653 			isc_mem_put(sdlz->common.mctx, node->name,
654 				    sizeof(dns_name_t));
655 			destroynode(node);
656 			return (result);
657 		}
658 	}
659 
660 	*nodep = node;
661 	return (ISC_R_SUCCESS);
662 }
663 
664 static isc_result_t
findnode(dns_db_t * db,dns_name_t * name,isc_boolean_t create,dns_dbnode_t ** nodep)665 findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
666 	 dns_dbnode_t **nodep)
667 {
668 	return (findnodeext(db, name, create, NULL, NULL, nodep));
669 }
670 
671 static isc_result_t
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)672 findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
673 	    isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
674 	    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
675 {
676 	UNUSED(db);
677 	UNUSED(name);
678 	UNUSED(options);
679 	UNUSED(now);
680 	UNUSED(nodep);
681 	UNUSED(foundname);
682 	UNUSED(rdataset);
683 	UNUSED(sigrdataset);
684 
685 	return (ISC_R_NOTIMPLEMENTED);
686 }
687 
688 static void
attachnode(dns_db_t * db,dns_dbnode_t * source,dns_dbnode_t ** targetp)689 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
690 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
691 	dns_sdlznode_t *node = (dns_sdlznode_t *)source;
692 
693 	REQUIRE(VALID_SDLZDB(sdlz));
694 
695 	UNUSED(sdlz);
696 
697 	LOCK(&node->lock);
698 	INSIST(node->references > 0);
699 	node->references++;
700 	INSIST(node->references != 0);		/* Catch overflow. */
701 	UNLOCK(&node->lock);
702 
703 	*targetp = source;
704 }
705 
706 static void
detachnode(dns_db_t * db,dns_dbnode_t ** targetp)707 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
708 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
709 	dns_sdlznode_t *node;
710 	isc_boolean_t need_destroy = ISC_FALSE;
711 
712 	REQUIRE(VALID_SDLZDB(sdlz));
713 	REQUIRE(targetp != NULL && *targetp != NULL);
714 
715 	UNUSED(sdlz);
716 
717 	node = (dns_sdlznode_t *)(*targetp);
718 
719 	LOCK(&node->lock);
720 	INSIST(node->references > 0);
721 	node->references--;
722 	if (node->references == 0)
723 		need_destroy = ISC_TRUE;
724 	UNLOCK(&node->lock);
725 
726 	if (need_destroy)
727 		destroynode(node);
728 
729 	*targetp = NULL;
730 }
731 
732 static isc_result_t
expirenode(dns_db_t * db,dns_dbnode_t * node,isc_stdtime_t now)733 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
734 	UNUSED(db);
735 	UNUSED(node);
736 	UNUSED(now);
737 	INSIST(0);
738 	return (ISC_R_UNEXPECTED);
739 }
740 
741 static void
printnode(dns_db_t * db,dns_dbnode_t * node,FILE * out)742 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
743 	UNUSED(db);
744 	UNUSED(node);
745 	UNUSED(out);
746 	return;
747 }
748 
749 static isc_result_t
createiterator(dns_db_t * db,unsigned int options,dns_dbiterator_t ** iteratorp)750 createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
751 {
752 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
753 	sdlz_dbiterator_t *sdlziter;
754 	isc_result_t result;
755 	isc_buffer_t b;
756 	char zonestr[DNS_NAME_MAXTEXT + 1];
757 
758 	REQUIRE(VALID_SDLZDB(sdlz));
759 
760 	if (sdlz->dlzimp->methods->allnodes == NULL)
761 		return (ISC_R_NOTIMPLEMENTED);
762 
763 	if ((options & DNS_DB_NSEC3ONLY) != 0 ||
764 	    (options & DNS_DB_NONSEC3) != 0)
765 		 return (ISC_R_NOTIMPLEMENTED);
766 
767 	isc_buffer_init(&b, zonestr, sizeof(zonestr));
768 	result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b);
769 	if (result != ISC_R_SUCCESS)
770 		return (result);
771 	isc_buffer_putuint8(&b, 0);
772 
773 	sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
774 	if (sdlziter == NULL)
775 		return (ISC_R_NOMEMORY);
776 
777 	sdlziter->common.methods = &dbiterator_methods;
778 	sdlziter->common.db = NULL;
779 	dns_db_attach(db, &sdlziter->common.db);
780 	sdlziter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
781 	sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
782 	ISC_LIST_INIT(sdlziter->nodelist);
783 	sdlziter->current = NULL;
784 	sdlziter->origin = NULL;
785 
786 	/* make sure strings are always lowercase */
787 	dns_sdlz_tolower(zonestr);
788 
789 	MAYBE_LOCK(sdlz->dlzimp);
790 	result = sdlz->dlzimp->methods->allnodes(zonestr,
791 						 sdlz->dlzimp->driverarg,
792 						 sdlz->dbdata, sdlziter);
793 	MAYBE_UNLOCK(sdlz->dlzimp);
794 	if (result != ISC_R_SUCCESS) {
795 		dns_dbiterator_t *iter = &sdlziter->common;
796 		dbiterator_destroy(&iter);
797 		return (result);
798 	}
799 
800 	if (sdlziter->origin != NULL) {
801 		ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
802 		ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
803 	}
804 
805 	*iteratorp = (dns_dbiterator_t *)sdlziter;
806 
807 	return (ISC_R_SUCCESS);
808 }
809 
810 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)811 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
812 	     dns_rdatatype_t type, dns_rdatatype_t covers,
813 	     isc_stdtime_t now, dns_rdataset_t *rdataset,
814 	     dns_rdataset_t *sigrdataset)
815 {
816 	dns_rdatalist_t *list;
817 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
818 
819 	REQUIRE(VALID_SDLZNODE(node));
820 
821 	UNUSED(db);
822 	UNUSED(version);
823 	UNUSED(covers);
824 	UNUSED(now);
825 	UNUSED(sigrdataset);
826 
827 	if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig)
828 		return (ISC_R_NOTIMPLEMENTED);
829 
830 	list = ISC_LIST_HEAD(sdlznode->lists);
831 	while (list != NULL) {
832 		if (list->type == type)
833 			break;
834 		list = ISC_LIST_NEXT(list, link);
835 	}
836 	if (list == NULL)
837 		return (ISC_R_NOTFOUND);
838 
839 	list_tordataset(list, db, node, rdataset);
840 
841 	return (ISC_R_SUCCESS);
842 }
843 
844 static isc_result_t
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)845 findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
846 	dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
847 	dns_dbnode_t **nodep, dns_name_t *foundname,
848 	dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
849 	dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
850 {
851 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
852 	dns_dbnode_t *node = NULL;
853 	dns_fixedname_t fname;
854 	dns_rdataset_t xrdataset;
855 	dns_name_t *xname;
856 	unsigned int nlabels, olabels;
857 	isc_result_t result;
858 	unsigned int i;
859 
860 	REQUIRE(VALID_SDLZDB(sdlz));
861 	REQUIRE(nodep == NULL || *nodep == NULL);
862 	REQUIRE(version == NULL || version == (void*)&sdlz->dummy_version);
863 
864 	UNUSED(options);
865 	UNUSED(sdlz);
866 
867 	if (!dns_name_issubdomain(name, &db->origin))
868 		return (DNS_R_NXDOMAIN);
869 
870 	olabels = dns_name_countlabels(&db->origin);
871 	nlabels = dns_name_countlabels(name);
872 
873 	dns_fixedname_init(&fname);
874 	xname = dns_fixedname_name(&fname);
875 
876 	if (rdataset == NULL) {
877 		dns_rdataset_init(&xrdataset);
878 		rdataset = &xrdataset;
879 	}
880 
881 	result = DNS_R_NXDOMAIN;
882 
883 	for (i = olabels; i <= nlabels; i++) {
884 		/*
885 		 * Look up the next label.
886 		 */
887 		dns_name_getlabelsequence(name, nlabels - i, i, xname);
888 		result = findnodeext(db, xname, ISC_FALSE,
889 				     methods, clientinfo, &node);
890 		if (result == ISC_R_NOTFOUND) {
891 			result = DNS_R_NXDOMAIN;
892 			continue;
893 		} else if (result != ISC_R_SUCCESS)
894 			break;
895 
896 		/*
897 		 * Look for a DNAME at the current label, unless this is
898 		 * the qname.
899 		 */
900 		if (i < nlabels) {
901 			result = findrdataset(db, node, version,
902 					      dns_rdatatype_dname, 0, now,
903 					      rdataset, sigrdataset);
904 			if (result == ISC_R_SUCCESS) {
905 				result = DNS_R_DNAME;
906 				break;
907 			}
908 		}
909 
910 		/*
911 		 * Look for an NS at the current label, unless this is the
912 		 * origin or glue is ok.
913 		 */
914 		if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
915 			result = findrdataset(db, node, version,
916 					      dns_rdatatype_ns, 0, now,
917 					      rdataset, sigrdataset);
918 			if (result == ISC_R_SUCCESS) {
919 				if (i == nlabels && type == dns_rdatatype_any)
920 				{
921 					result = DNS_R_ZONECUT;
922 					dns_rdataset_disassociate(rdataset);
923 					if (sigrdataset != NULL &&
924 					    dns_rdataset_isassociated
925 							(sigrdataset)) {
926 						dns_rdataset_disassociate
927 							(sigrdataset);
928 					}
929 				} else
930 					result = DNS_R_DELEGATION;
931 				break;
932 			}
933 		}
934 
935 		/*
936 		 * If the current name is not the qname, add another label
937 		 * and try again.
938 		 */
939 		if (i < nlabels) {
940 			destroynode(node);
941 			node = NULL;
942 			continue;
943 		}
944 
945 		/*
946 		 * If we're looking for ANY, we're done.
947 		 */
948 		if (type == dns_rdatatype_any) {
949 			result = ISC_R_SUCCESS;
950 			break;
951 		}
952 
953 		/*
954 		 * Look for the qtype.
955 		 */
956 		result = findrdataset(db, node, version, type, 0, now,
957 				      rdataset, sigrdataset);
958 		if (result == ISC_R_SUCCESS)
959 			break;
960 
961 		/*
962 		 * Look for a CNAME
963 		 */
964 		if (type != dns_rdatatype_cname) {
965 			result = findrdataset(db, node, version,
966 					      dns_rdatatype_cname, 0, now,
967 					      rdataset, sigrdataset);
968 			if (result == ISC_R_SUCCESS) {
969 				result = DNS_R_CNAME;
970 				break;
971 			}
972 		}
973 
974 		result = DNS_R_NXRRSET;
975 		break;
976 	}
977 
978 	if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
979 		dns_rdataset_disassociate(rdataset);
980 
981 	if (foundname != NULL) {
982 		isc_result_t xresult;
983 
984 		xresult = dns_name_copy(xname, foundname, NULL);
985 		if (xresult != ISC_R_SUCCESS) {
986 			if (node != NULL)
987 				destroynode(node);
988 			if (dns_rdataset_isassociated(rdataset))
989 				dns_rdataset_disassociate(rdataset);
990 			return (DNS_R_BADDB);
991 		}
992 	}
993 
994 	if (nodep != NULL)
995 		*nodep = node;
996 	else if (node != NULL)
997 		detachnode(db, &node);
998 
999 	return (result);
1000 }
1001 
1002 static isc_result_t
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)1003 find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
1004      dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
1005      dns_dbnode_t **nodep, dns_name_t *foundname,
1006      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
1007 {
1008 	return (findext(db, name, version, type, options, now, nodep,
1009 			foundname, NULL, NULL, rdataset, sigrdataset));
1010 }
1011 
1012 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)1013 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1014 	     isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
1015 {
1016 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) db;
1017 	sdlz_rdatasetiter_t *iterator;
1018 
1019 	REQUIRE(VALID_SDLZDB(sdlz));
1020 
1021 	REQUIRE(version == NULL ||
1022 		version == (void*)&sdlz->dummy_version ||
1023 		version == sdlz->future_version);
1024 
1025 	UNUSED(version);
1026 	UNUSED(now);
1027 
1028 	iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
1029 	if (iterator == NULL)
1030 		return (ISC_R_NOMEMORY);
1031 
1032 	iterator->common.magic = DNS_RDATASETITER_MAGIC;
1033 	iterator->common.methods = &rdatasetiter_methods;
1034 	iterator->common.db = db;
1035 	iterator->common.node = NULL;
1036 	attachnode(db, node, &iterator->common.node);
1037 	iterator->common.version = version;
1038 	iterator->common.now = now;
1039 
1040 	*iteratorp = (dns_rdatasetiter_t *)iterator;
1041 
1042 	return (ISC_R_SUCCESS);
1043 }
1044 
1045 static isc_result_t
modrdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdataset_t * rdataset,unsigned int options,dns_sdlzmodrdataset_t mod_function)1046 modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1047 	    dns_rdataset_t *rdataset, unsigned int options,
1048 	    dns_sdlzmodrdataset_t mod_function)
1049 {
1050 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1051 	dns_master_style_t *style = NULL;
1052 	isc_result_t result;
1053 	isc_buffer_t *buffer = NULL;
1054 	isc_mem_t *mctx;
1055 	dns_sdlznode_t *sdlznode;
1056 	char *rdatastr = NULL;
1057 	char name[DNS_NAME_MAXTEXT + 1];
1058 
1059 	REQUIRE(VALID_SDLZDB(sdlz));
1060 
1061 	if (mod_function == NULL)
1062 		return (ISC_R_NOTIMPLEMENTED);
1063 
1064 	sdlznode = (dns_sdlznode_t *)node;
1065 
1066 	UNUSED(options);
1067 
1068 	dns_name_format(sdlznode->name, name, sizeof(name));
1069 
1070 	mctx = sdlz->common.mctx;
1071 
1072 	result = isc_buffer_allocate(mctx, &buffer, 1024);
1073 	if (result != ISC_R_SUCCESS)
1074 		return (result);
1075 
1076 	result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, mctx);
1077 	if (result != ISC_R_SUCCESS)
1078 		goto cleanup;
1079 
1080 	result = dns_master_rdatasettotext(sdlznode->name, rdataset,
1081 					   style, buffer);
1082 	if (result != ISC_R_SUCCESS)
1083 		goto cleanup;
1084 
1085 	if (isc_buffer_usedlength(buffer) < 1) {
1086 		result = ISC_R_BADADDRESSFORM;
1087 		goto cleanup;
1088 	}
1089 
1090 	rdatastr = isc_buffer_base(buffer);
1091 	if (rdatastr == NULL) {
1092 		result = ISC_R_NOMEMORY;
1093 		goto cleanup;
1094 	}
1095 	rdatastr[isc_buffer_usedlength(buffer) - 1] = 0;
1096 
1097 	MAYBE_LOCK(sdlz->dlzimp);
1098 	result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg,
1099 			      sdlz->dbdata, version);
1100 	MAYBE_UNLOCK(sdlz->dlzimp);
1101 
1102 cleanup:
1103 	isc_buffer_free(&buffer);
1104 	if (style != NULL)
1105 		dns_master_styledestroy(&style, mctx);
1106 
1107 	return (result);
1108 }
1109 
1110 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)1111 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1112 	    isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
1113 	    dns_rdataset_t *addedrdataset)
1114 {
1115 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1116 	isc_result_t result;
1117 
1118 	UNUSED(now);
1119 	UNUSED(addedrdataset);
1120 	REQUIRE(VALID_SDLZDB(sdlz));
1121 
1122 	if (sdlz->dlzimp->methods->addrdataset == NULL)
1123 		return (ISC_R_NOTIMPLEMENTED);
1124 
1125 	result = modrdataset(db, node, version, rdataset, options,
1126 			     sdlz->dlzimp->methods->addrdataset);
1127 	return (result);
1128 }
1129 
1130 
1131 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)1132 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1133 		 dns_rdataset_t *rdataset, unsigned int options,
1134 		 dns_rdataset_t *newrdataset)
1135 {
1136 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1137 	isc_result_t result;
1138 
1139 	UNUSED(newrdataset);
1140 	REQUIRE(VALID_SDLZDB(sdlz));
1141 
1142 	if (sdlz->dlzimp->methods->subtractrdataset == NULL) {
1143 		return (ISC_R_NOTIMPLEMENTED);
1144 	}
1145 
1146 	result = modrdataset(db, node, version, rdataset, options,
1147 			     sdlz->dlzimp->methods->subtractrdataset);
1148 	return (result);
1149 }
1150 
1151 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)1152 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1153 	       dns_rdatatype_t type, dns_rdatatype_t covers)
1154 {
1155 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1156 	char name[DNS_NAME_MAXTEXT + 1];
1157 	char b_type[DNS_RDATATYPE_FORMATSIZE];
1158 	dns_sdlznode_t *sdlznode;
1159 	isc_result_t result;
1160 
1161 	UNUSED(covers);
1162 
1163 	REQUIRE(VALID_SDLZDB(sdlz));
1164 
1165 	if (sdlz->dlzimp->methods->delrdataset == NULL)
1166 		return (ISC_R_NOTIMPLEMENTED);
1167 
1168 	sdlznode = (dns_sdlznode_t *)node;
1169 	dns_name_format(sdlznode->name, name, sizeof(name));
1170 	dns_rdatatype_format(type, b_type, sizeof(b_type));
1171 
1172 	MAYBE_LOCK(sdlz->dlzimp);
1173 	result = sdlz->dlzimp->methods->delrdataset(name, b_type,
1174 						    sdlz->dlzimp->driverarg,
1175 						    sdlz->dbdata, version);
1176 	MAYBE_UNLOCK(sdlz->dlzimp);
1177 
1178 	return (result);
1179 }
1180 
1181 static isc_boolean_t
issecure(dns_db_t * db)1182 issecure(dns_db_t *db) {
1183 	UNUSED(db);
1184 
1185 	return (ISC_FALSE);
1186 }
1187 
1188 static unsigned int
nodecount(dns_db_t * db)1189 nodecount(dns_db_t *db) {
1190 	UNUSED(db);
1191 
1192 	return (0);
1193 }
1194 
1195 static isc_boolean_t
ispersistent(dns_db_t * db)1196 ispersistent(dns_db_t *db) {
1197 	UNUSED(db);
1198 	return (ISC_TRUE);
1199 }
1200 
1201 static void
overmem(dns_db_t * db,isc_boolean_t overmem)1202 overmem(dns_db_t *db, isc_boolean_t overmem) {
1203 	UNUSED(db);
1204 	UNUSED(overmem);
1205 }
1206 
1207 static void
settask(dns_db_t * db,isc_task_t * task)1208 settask(dns_db_t *db, isc_task_t *task) {
1209 	UNUSED(db);
1210 	UNUSED(task);
1211 }
1212 
1213 /*
1214  * getoriginnode() is used by the update code to find the
1215  * dns_rdatatype_dnskey record for a zone
1216  */
1217 static isc_result_t
getoriginnode(dns_db_t * db,dns_dbnode_t ** nodep)1218 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
1219 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1220 	isc_result_t result;
1221 
1222 	REQUIRE(VALID_SDLZDB(sdlz));
1223 	if (sdlz->dlzimp->methods->newversion == NULL)
1224 		return (ISC_R_NOTIMPLEMENTED);
1225 
1226 	result = findnodeext(db, &sdlz->common.origin, ISC_FALSE,
1227 			     NULL, NULL, nodep);
1228 	if (result != ISC_R_SUCCESS)
1229 		sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s",
1230 			 isc_result_totext(result));
1231 	return (result);
1232 }
1233 
1234 static dns_dbmethods_t sdlzdb_methods = {
1235 	attach,
1236 	detach,
1237 	beginload,
1238 	endload,
1239 	NULL,
1240 	dump,
1241 	currentversion,
1242 	newversion,
1243 	attachversion,
1244 	closeversion,
1245 	findnode,
1246 	find,
1247 	findzonecut,
1248 	attachnode,
1249 	detachnode,
1250 	expirenode,
1251 	printnode,
1252 	createiterator,
1253 	findrdataset,
1254 	allrdatasets,
1255 	addrdataset,
1256 	subtractrdataset,
1257 	deleterdataset,
1258 	issecure,
1259 	nodecount,
1260 	ispersistent,
1261 	overmem,
1262 	settask,
1263 	getoriginnode,
1264 	NULL,			/* transfernode */
1265 	NULL,			/* getnsec3parameters */
1266 	NULL,			/* findnsec3node */
1267 	NULL,			/* setsigningtime */
1268 	NULL,			/* getsigningtime */
1269 	NULL,			/* resigned */
1270 	NULL,			/* isdnssec */
1271 	NULL,			/* getrrsetstats */
1272 	NULL,			/* rpz_attach */
1273 	NULL,			/* rpz_ready */
1274 	findnodeext,
1275 	findext,
1276 	NULL,			/* setcachestats */
1277 	NULL			/* hashsize */
1278 };
1279 
1280 /*
1281  * Database Iterator Methods.  These methods were "borrowed" from the SDB
1282  * driver interface.  See the SDB driver interface documentation for more info.
1283  */
1284 
1285 static void
dbiterator_destroy(dns_dbiterator_t ** iteratorp)1286 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1287 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
1288 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
1289 
1290 	while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
1291 		dns_sdlznode_t *node;
1292 		node = ISC_LIST_HEAD(sdlziter->nodelist);
1293 		ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
1294 		destroynode(node);
1295 	}
1296 
1297 	dns_db_detach(&sdlziter->common.db);
1298 	isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
1299 
1300 	*iteratorp = NULL;
1301 }
1302 
1303 static isc_result_t
dbiterator_first(dns_dbiterator_t * iterator)1304 dbiterator_first(dns_dbiterator_t *iterator) {
1305 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1306 
1307 	sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1308 	if (sdlziter->current == NULL)
1309 		return (ISC_R_NOMORE);
1310 	else
1311 		return (ISC_R_SUCCESS);
1312 }
1313 
1314 static isc_result_t
dbiterator_last(dns_dbiterator_t * iterator)1315 dbiterator_last(dns_dbiterator_t *iterator) {
1316 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1317 
1318 	sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
1319 	if (sdlziter->current == NULL)
1320 		return (ISC_R_NOMORE);
1321 	else
1322 		return (ISC_R_SUCCESS);
1323 }
1324 
1325 static isc_result_t
dbiterator_seek(dns_dbiterator_t * iterator,dns_name_t * name)1326 dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
1327 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1328 
1329 	sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1330 	while (sdlziter->current != NULL) {
1331 		if (dns_name_equal(sdlziter->current->name, name))
1332 			return (ISC_R_SUCCESS);
1333 		sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1334 	}
1335 	return (ISC_R_NOTFOUND);
1336 }
1337 
1338 static isc_result_t
dbiterator_prev(dns_dbiterator_t * iterator)1339 dbiterator_prev(dns_dbiterator_t *iterator) {
1340 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1341 
1342 	sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
1343 	if (sdlziter->current == NULL)
1344 		return (ISC_R_NOMORE);
1345 	else
1346 		return (ISC_R_SUCCESS);
1347 }
1348 
1349 static isc_result_t
dbiterator_next(dns_dbiterator_t * iterator)1350 dbiterator_next(dns_dbiterator_t *iterator) {
1351 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1352 
1353 	sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1354 	if (sdlziter->current == NULL)
1355 		return (ISC_R_NOMORE);
1356 	else
1357 		return (ISC_R_SUCCESS);
1358 }
1359 
1360 static isc_result_t
dbiterator_current(dns_dbiterator_t * iterator,dns_dbnode_t ** nodep,dns_name_t * name)1361 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1362 		   dns_name_t *name)
1363 {
1364 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1365 
1366 	attachnode(iterator->db, sdlziter->current, nodep);
1367 	if (name != NULL)
1368 		return (dns_name_copy(sdlziter->current->name, name, NULL));
1369 	return (ISC_R_SUCCESS);
1370 }
1371 
1372 static isc_result_t
dbiterator_pause(dns_dbiterator_t * iterator)1373 dbiterator_pause(dns_dbiterator_t *iterator) {
1374 	UNUSED(iterator);
1375 	return (ISC_R_SUCCESS);
1376 }
1377 
1378 static isc_result_t
dbiterator_origin(dns_dbiterator_t * iterator,dns_name_t * name)1379 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1380 	UNUSED(iterator);
1381 	return (dns_name_copy(dns_rootname, name, NULL));
1382 }
1383 
1384 /*
1385  * Rdataset Methods. These methods were "borrowed" from the SDB driver
1386  * interface.  See the SDB driver interface documentation for more info.
1387  */
1388 
1389 static void
disassociate(dns_rdataset_t * rdataset)1390 disassociate(dns_rdataset_t *rdataset) {
1391 	dns_dbnode_t *node = rdataset->private5;
1392 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
1393 	dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
1394 
1395 	detachnode(db, &node);
1396 	isc__rdatalist_disassociate(rdataset);
1397 }
1398 
1399 static void
rdataset_clone(dns_rdataset_t * source,dns_rdataset_t * target)1400 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1401 	dns_dbnode_t *node = source->private5;
1402 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
1403 	dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
1404 	dns_dbnode_t *tempdb = NULL;
1405 
1406 	isc__rdatalist_clone(source, target);
1407 	attachnode(db, node, &tempdb);
1408 	source->private5 = tempdb;
1409 }
1410 
1411 static dns_rdatasetmethods_t rdataset_methods = {
1412 	disassociate,
1413 	isc__rdatalist_first,
1414 	isc__rdatalist_next,
1415 	isc__rdatalist_current,
1416 	rdataset_clone,
1417 	isc__rdatalist_count,
1418 	isc__rdatalist_addnoqname,
1419 	isc__rdatalist_getnoqname,
1420 	NULL,
1421 	NULL,
1422 	NULL,
1423 	NULL,
1424 	NULL,
1425 	NULL,
1426 	NULL,
1427 	NULL
1428 };
1429 
1430 static void
list_tordataset(dns_rdatalist_t * rdatalist,dns_db_t * db,dns_dbnode_t * node,dns_rdataset_t * rdataset)1431 list_tordataset(dns_rdatalist_t *rdatalist,
1432 		dns_db_t *db, dns_dbnode_t *node,
1433 		dns_rdataset_t *rdataset)
1434 {
1435 	/*
1436 	 * The sdlz rdataset is an rdatalist with some additions.
1437 	 *	- private1 & private2 are used by the rdatalist.
1438 	 *	- private3 & private 4 are unused.
1439 	 *	- private5 is the node.
1440 	 */
1441 
1442 	/* This should never fail. */
1443 	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1444 		      ISC_R_SUCCESS);
1445 
1446 	rdataset->methods = &rdataset_methods;
1447 	dns_db_attachnode(db, node, &rdataset->private5);
1448 }
1449 
1450 /*
1451  * SDLZ core methods. This is the core of the new DLZ functionality.
1452  */
1453 
1454 /*%
1455  * Build a 'bind' database driver structure to be returned by
1456  * either the find zone or the allow zone transfer method.
1457  * This method is only available in this source file, it is
1458  * not made available anywhere else.
1459  */
1460 
1461 static isc_result_t
dns_sdlzcreateDBP(isc_mem_t * mctx,void * driverarg,void * dbdata,dns_name_t * name,dns_rdataclass_t rdclass,dns_db_t ** dbp)1462 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
1463 		  dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp)
1464 {
1465 	isc_result_t result;
1466 	dns_sdlz_db_t *sdlzdb;
1467 	dns_sdlzimplementation_t *imp;
1468 
1469 	/* check that things are as we expect */
1470 	REQUIRE(dbp != NULL && *dbp == NULL);
1471 	REQUIRE(name != NULL);
1472 
1473 	imp = (dns_sdlzimplementation_t *) driverarg;
1474 
1475 	/* allocate and zero memory for driver structure */
1476 	sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
1477 	if (sdlzdb == NULL)
1478 		return (ISC_R_NOMEMORY);
1479 	memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
1480 
1481 	/* initialize and set origin */
1482 	dns_name_init(&sdlzdb->common.origin, NULL);
1483 	result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
1484 	if (result != ISC_R_SUCCESS)
1485 		goto mem_cleanup;
1486 
1487 	/* initialize the reference count mutex */
1488 	result = isc_mutex_init(&sdlzdb->refcnt_lock);
1489 	if (result != ISC_R_SUCCESS)
1490 		goto name_cleanup;
1491 
1492 	/* set the rest of the database structure attributes */
1493 	sdlzdb->dlzimp = imp;
1494 	sdlzdb->common.methods = &sdlzdb_methods;
1495 	sdlzdb->common.attributes = 0;
1496 	sdlzdb->common.rdclass = rdclass;
1497 	sdlzdb->common.mctx = NULL;
1498 	sdlzdb->dbdata = dbdata;
1499 	sdlzdb->references = 1;
1500 
1501 	/* attach to the memory context */
1502 	isc_mem_attach(mctx, &sdlzdb->common.mctx);
1503 
1504 	/* mark structure as valid */
1505 	sdlzdb->common.magic = DNS_DB_MAGIC;
1506 	sdlzdb->common.impmagic = SDLZDB_MAGIC;
1507 	*dbp = (dns_db_t *) sdlzdb;
1508 
1509 	return (result);
1510 
1511 	/*
1512 	 * reference count mutex could not be initialized, clean up
1513 	 * name memory
1514 	 */
1515  name_cleanup:
1516 	dns_name_free(&sdlzdb->common.origin, mctx);
1517  mem_cleanup:
1518 	isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
1519 	return (result);
1520 }
1521 
1522 static isc_result_t
dns_sdlzallowzonexfr(void * driverarg,void * dbdata,isc_mem_t * mctx,dns_rdataclass_t rdclass,dns_name_t * name,isc_sockaddr_t * clientaddr,dns_db_t ** dbp)1523 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
1524 		     dns_rdataclass_t rdclass, dns_name_t *name,
1525 		     isc_sockaddr_t *clientaddr, dns_db_t **dbp)
1526 {
1527 	isc_buffer_t b;
1528 	isc_buffer_t b2;
1529 	char namestr[DNS_NAME_MAXTEXT + 1];
1530 	char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
1531 		       + 1];
1532 	isc_netaddr_t netaddr;
1533 	isc_result_t result;
1534 	dns_sdlzimplementation_t *imp;
1535 
1536 	/*
1537 	 * Perform checks to make sure data is as we expect it to be.
1538 	 */
1539 	REQUIRE(driverarg != NULL);
1540 	REQUIRE(name != NULL);
1541 	REQUIRE(clientaddr != NULL);
1542 	REQUIRE(dbp != NULL && *dbp == NULL);
1543 
1544 	imp = (dns_sdlzimplementation_t *) driverarg;
1545 
1546 	/* Convert DNS name to ascii text */
1547 	isc_buffer_init(&b, namestr, sizeof(namestr));
1548 	result = dns_name_totext(name, ISC_TRUE, &b);
1549 	if (result != ISC_R_SUCCESS)
1550 		return (result);
1551 	isc_buffer_putuint8(&b, 0);
1552 
1553 	/* convert client address to ascii text */
1554 	isc_buffer_init(&b2, clientstr, sizeof(clientstr));
1555 	isc_netaddr_fromsockaddr(&netaddr, clientaddr);
1556 	result = isc_netaddr_totext(&netaddr, &b2);
1557 	if (result != ISC_R_SUCCESS)
1558 		return (result);
1559 	isc_buffer_putuint8(&b2, 0);
1560 
1561 	/* make sure strings are always lowercase */
1562 	dns_sdlz_tolower(namestr);
1563 	dns_sdlz_tolower(clientstr);
1564 
1565 	/* Call SDLZ driver's find zone method */
1566 	if (imp->methods->allowzonexfr != NULL) {
1567 		MAYBE_LOCK(imp);
1568 		result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
1569 						    namestr, clientstr);
1570 		MAYBE_UNLOCK(imp);
1571 		/*
1572 		 * if zone is supported and transfers allowed build a 'bind'
1573 		 * database driver
1574 		 */
1575 		if (result == ISC_R_SUCCESS)
1576 			result = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
1577 						   name, rdclass, dbp);
1578 		return (result);
1579 	}
1580 
1581 	return (ISC_R_NOTIMPLEMENTED);
1582 }
1583 
1584 static isc_result_t
dns_sdlzcreate(isc_mem_t * mctx,const char * dlzname,unsigned int argc,char * argv[],void * driverarg,void ** dbdata)1585 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
1586 	       char *argv[], void *driverarg, void **dbdata)
1587 {
1588 	dns_sdlzimplementation_t *imp;
1589 	isc_result_t result = ISC_R_NOTFOUND;
1590 
1591 	/* Write debugging message to log */
1592 	sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
1593 
1594 	/*
1595 	 * Performs checks to make sure data is as we expect it to be.
1596 	 */
1597 	REQUIRE(driverarg != NULL);
1598 	REQUIRE(dlzname != NULL);
1599 	REQUIRE(dbdata != NULL);
1600 	UNUSED(mctx);
1601 
1602 	imp = driverarg;
1603 
1604 	/* If the create method exists, call it. */
1605 	if (imp->methods->create != NULL) {
1606 		MAYBE_LOCK(imp);
1607 		result = imp->methods->create(dlzname, argc, argv,
1608 					      imp->driverarg, dbdata);
1609 		MAYBE_UNLOCK(imp);
1610 	}
1611 
1612 	/* Write debugging message to log */
1613 	if (result == ISC_R_SUCCESS) {
1614 		sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
1615 	} else {
1616 		sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
1617 	}
1618 
1619 	return (result);
1620 }
1621 
1622 static void
dns_sdlzdestroy(void * driverdata,void ** dbdata)1623 dns_sdlzdestroy(void *driverdata, void **dbdata) {
1624 	dns_sdlzimplementation_t *imp;
1625 
1626 	/* Write debugging message to log */
1627 	sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
1628 
1629 	imp = driverdata;
1630 
1631 	/* If the destroy method exists, call it. */
1632 	if (imp->methods->destroy != NULL) {
1633 		MAYBE_LOCK(imp);
1634 		imp->methods->destroy(imp->driverarg, dbdata);
1635 		MAYBE_UNLOCK(imp);
1636 	}
1637 }
1638 
1639 static isc_result_t
dns_sdlzfindzone(void * driverarg,void * dbdata,isc_mem_t * mctx,dns_rdataclass_t rdclass,dns_name_t * name,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo,dns_db_t ** dbp)1640 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
1641 		 dns_rdataclass_t rdclass, dns_name_t *name,
1642 		 dns_clientinfomethods_t *methods,
1643 		 dns_clientinfo_t *clientinfo,
1644 		 dns_db_t **dbp)
1645 {
1646 	isc_buffer_t b;
1647 	char namestr[DNS_NAME_MAXTEXT + 1];
1648 	isc_result_t result;
1649 	dns_sdlzimplementation_t *imp;
1650 
1651 	/*
1652 	 * Perform checks to make sure data is as we expect it to be.
1653 	 */
1654 	REQUIRE(driverarg != NULL);
1655 	REQUIRE(name != NULL);
1656 	REQUIRE(dbp != NULL && *dbp == NULL);
1657 
1658 	imp = (dns_sdlzimplementation_t *) driverarg;
1659 
1660 	/* Convert DNS name to ascii text */
1661 	isc_buffer_init(&b, namestr, sizeof(namestr));
1662 	result = dns_name_totext(name, ISC_TRUE, &b);
1663 	if (result != ISC_R_SUCCESS)
1664 		return (result);
1665 	isc_buffer_putuint8(&b, 0);
1666 
1667 	/* make sure strings are always lowercase */
1668 	dns_sdlz_tolower(namestr);
1669 
1670 	/* Call SDLZ driver's find zone method */
1671 	MAYBE_LOCK(imp);
1672 	result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
1673 					methods, clientinfo);
1674 	MAYBE_UNLOCK(imp);
1675 
1676 	/*
1677 	 * if zone is supported build a 'bind' database driver
1678 	 * structure to return
1679 	 */
1680 	if (result == ISC_R_SUCCESS)
1681 		result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
1682 					   rdclass, dbp);
1683 
1684 	return (result);
1685 }
1686 
1687 
1688 static isc_result_t
dns_sdlzconfigure(void * driverarg,void * dbdata,dns_view_t * view,dns_dlzdb_t * dlzdb)1689 dns_sdlzconfigure(void *driverarg, void *dbdata,
1690 		  dns_view_t *view, dns_dlzdb_t *dlzdb)
1691 {
1692 	isc_result_t result;
1693 	dns_sdlzimplementation_t *imp;
1694 
1695 	REQUIRE(driverarg != NULL);
1696 
1697 	imp = (dns_sdlzimplementation_t *) driverarg;
1698 
1699 	/* Call SDLZ driver's configure method */
1700 	if (imp->methods->configure != NULL) {
1701 		MAYBE_LOCK(imp);
1702 		result = imp->methods->configure(view, dlzdb,
1703 						 imp->driverarg, dbdata);
1704 		MAYBE_UNLOCK(imp);
1705 	} else {
1706 		result = ISC_R_SUCCESS;
1707 	}
1708 
1709 	return (result);
1710 }
1711 
1712 static isc_boolean_t
dns_sdlzssumatch(dns_name_t * signer,dns_name_t * name,isc_netaddr_t * tcpaddr,dns_rdatatype_t type,const dst_key_t * key,void * driverarg,void * dbdata)1713 dns_sdlzssumatch(dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr,
1714 		 dns_rdatatype_t type, const dst_key_t *key, void *driverarg,
1715 		 void *dbdata)
1716 {
1717 	dns_sdlzimplementation_t *imp;
1718 	char b_signer[DNS_NAME_FORMATSIZE];
1719 	char b_name[DNS_NAME_FORMATSIZE];
1720 	char b_addr[ISC_NETADDR_FORMATSIZE];
1721 	char b_type[DNS_RDATATYPE_FORMATSIZE];
1722 	char b_key[DST_KEY_FORMATSIZE];
1723 	isc_buffer_t *tkey_token = NULL;
1724 	isc_region_t token_region;
1725 	isc_uint32_t token_len = 0;
1726 	isc_boolean_t ret;
1727 
1728 	REQUIRE(driverarg != NULL);
1729 
1730 	imp = (dns_sdlzimplementation_t *) driverarg;
1731 	if (imp->methods->ssumatch == NULL)
1732 		return (ISC_FALSE);
1733 
1734 	/*
1735 	 * Format the request elements. sdlz operates on strings, not
1736 	 * structures
1737 	 */
1738 	if (signer != NULL)
1739 		dns_name_format(signer, b_signer, sizeof(b_signer));
1740 	else
1741 		b_signer[0] = 0;
1742 
1743 	dns_name_format(name, b_name, sizeof(b_name));
1744 
1745 	if (tcpaddr != NULL)
1746 		isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
1747 	else
1748 		b_addr[0] = 0;
1749 
1750 	dns_rdatatype_format(type, b_type, sizeof(b_type));
1751 
1752 	if (key != NULL) {
1753 		dst_key_format(key, b_key, sizeof(b_key));
1754 		tkey_token = dst_key_tkeytoken(key);
1755 	} else
1756 		b_key[0] = 0;
1757 
1758 	if (tkey_token != NULL) {
1759 		isc_buffer_region(tkey_token, &token_region);
1760 		token_len = token_region.length;
1761 	}
1762 
1763 	MAYBE_LOCK(imp);
1764 	ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
1765 				     token_len,
1766 				     token_len != 0 ? token_region.base : NULL,
1767 				     imp->driverarg, dbdata);
1768 	MAYBE_UNLOCK(imp);
1769 	return (ret);
1770 }
1771 
1772 static dns_dlzmethods_t sdlzmethods = {
1773 	dns_sdlzcreate,
1774 	dns_sdlzdestroy,
1775 	dns_sdlzfindzone,
1776 	dns_sdlzallowzonexfr,
1777 	dns_sdlzconfigure,
1778 	dns_sdlzssumatch
1779 };
1780 
1781 /*
1782  * Public functions.
1783  */
1784 
1785 isc_result_t
dns_sdlz_putrr(dns_sdlzlookup_t * lookup,const char * type,dns_ttl_t ttl,const char * data)1786 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
1787 	       const char *data)
1788 {
1789 	dns_rdatalist_t *rdatalist;
1790 	dns_rdata_t *rdata;
1791 	dns_rdatatype_t typeval;
1792 	isc_consttextregion_t r;
1793 	isc_buffer_t b;
1794 	isc_buffer_t *rdatabuf = NULL;
1795 	isc_lex_t *lex;
1796 	isc_result_t result;
1797 	unsigned int size;
1798 	isc_mem_t *mctx;
1799 	dns_name_t *origin;
1800 
1801 	REQUIRE(VALID_SDLZLOOKUP(lookup));
1802 	REQUIRE(type != NULL);
1803 	REQUIRE(data != NULL);
1804 
1805 	mctx = lookup->sdlz->common.mctx;
1806 
1807 	r.base = type;
1808 	r.length = strlen(type);
1809 	result = dns_rdatatype_fromtext(&typeval, (void *) &r);
1810 	if (result != ISC_R_SUCCESS)
1811 		return (result);
1812 
1813 	rdatalist = ISC_LIST_HEAD(lookup->lists);
1814 	while (rdatalist != NULL) {
1815 		if (rdatalist->type == typeval)
1816 			break;
1817 		rdatalist = ISC_LIST_NEXT(rdatalist, link);
1818 	}
1819 
1820 	if (rdatalist == NULL) {
1821 		rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
1822 		if (rdatalist == NULL)
1823 			return (ISC_R_NOMEMORY);
1824 		rdatalist->rdclass = lookup->sdlz->common.rdclass;
1825 		rdatalist->type = typeval;
1826 		rdatalist->covers = 0;
1827 		rdatalist->ttl = ttl;
1828 		ISC_LIST_INIT(rdatalist->rdata);
1829 		ISC_LINK_INIT(rdatalist, link);
1830 		ISC_LIST_APPEND(lookup->lists, rdatalist, link);
1831 	} else
1832 		if (rdatalist->ttl > ttl) {
1833 			/*
1834 			 * BIND9 doesn't enforce all RRs in an RRset
1835 			 * having the same TTL, as per RFC 2136,
1836 			 * section 7.12. If a DLZ backend has
1837 			 * different TTLs, then the best
1838 			 * we can do is return the lowest.
1839 			*/
1840 			rdatalist->ttl = ttl;
1841 		}
1842 
1843 	rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
1844 	if (rdata == NULL)
1845 		return (ISC_R_NOMEMORY);
1846 	dns_rdata_init(rdata);
1847 
1848 	if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1849 		origin = &lookup->sdlz->common.origin;
1850 	else
1851 		origin = dns_rootname;
1852 
1853 	lex = NULL;
1854 	result = isc_lex_create(mctx, 64, &lex);
1855 	if (result != ISC_R_SUCCESS)
1856 		goto failure;
1857 
1858 	size = initial_size(data);
1859 	do {
1860 		isc_buffer_constinit(&b, data, strlen(data));
1861 		isc_buffer_add(&b, strlen(data));
1862 
1863 		result = isc_lex_openbuffer(lex, &b);
1864 		if (result != ISC_R_SUCCESS)
1865 			goto failure;
1866 
1867 		rdatabuf = NULL;
1868 		result = isc_buffer_allocate(mctx, &rdatabuf, size);
1869 		if (result != ISC_R_SUCCESS)
1870 			goto failure;
1871 
1872 		result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
1873 					    rdatalist->type, lex,
1874 					    origin, ISC_FALSE,
1875 					    mctx, rdatabuf,
1876 					    &lookup->callbacks);
1877 		if (result != ISC_R_SUCCESS)
1878 			isc_buffer_free(&rdatabuf);
1879 		if (size >= 65535)
1880 			break;
1881 		size *= 2;
1882 		if (size >= 65535)
1883 			size = 65535;
1884 	} while (result == ISC_R_NOSPACE);
1885 
1886 	if (result != ISC_R_SUCCESS)
1887 		goto failure;
1888 
1889 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1890 	ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
1891 
1892 	if (lex != NULL)
1893 		isc_lex_destroy(&lex);
1894 
1895 	return (ISC_R_SUCCESS);
1896 
1897  failure:
1898 	if (rdatabuf != NULL)
1899 		isc_buffer_free(&rdatabuf);
1900 	if (lex != NULL)
1901 		isc_lex_destroy(&lex);
1902 	isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
1903 
1904 	return (result);
1905 }
1906 
1907 isc_result_t
dns_sdlz_putnamedrr(dns_sdlzallnodes_t * allnodes,const char * name,const char * type,dns_ttl_t ttl,const char * data)1908 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
1909 		    const char *type, dns_ttl_t ttl, const char *data)
1910 {
1911 	dns_name_t *newname, *origin;
1912 	dns_fixedname_t fnewname;
1913 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
1914 	dns_sdlznode_t *sdlznode;
1915 	isc_mem_t *mctx = sdlz->common.mctx;
1916 	isc_buffer_t b;
1917 	isc_result_t result;
1918 
1919 	dns_fixedname_init(&fnewname);
1920 	newname = dns_fixedname_name(&fnewname);
1921 
1922 	if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1923 		origin = &sdlz->common.origin;
1924 	else
1925 		origin = dns_rootname;
1926 	isc_buffer_constinit(&b, name, strlen(name));
1927 	isc_buffer_add(&b, strlen(name));
1928 
1929 	result = dns_name_fromtext(newname, &b, origin, 0, NULL);
1930 	if (result != ISC_R_SUCCESS)
1931 		return (result);
1932 
1933 	if (allnodes->common.relative_names) {
1934 		/* All names are relative to the root */
1935 		unsigned int nlabels = dns_name_countlabels(newname);
1936 		dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
1937 	}
1938 
1939 	sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
1940 	if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
1941 		sdlznode = NULL;
1942 		result = createnode(sdlz, &sdlznode);
1943 		if (result != ISC_R_SUCCESS)
1944 			return (result);
1945 		sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
1946 		if (sdlznode->name == NULL) {
1947 			destroynode(sdlznode);
1948 			return (ISC_R_NOMEMORY);
1949 		}
1950 		dns_name_init(sdlznode->name, NULL);
1951 		result = dns_name_dup(newname, mctx, sdlznode->name);
1952 		if (result != ISC_R_SUCCESS) {
1953 			isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
1954 			destroynode(sdlznode);
1955 			return (result);
1956 		}
1957 		ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
1958 		if (allnodes->origin == NULL &&
1959 		    dns_name_equal(newname, &sdlz->common.origin))
1960 			allnodes->origin = sdlznode;
1961 	}
1962 	return (dns_sdlz_putrr(sdlznode, type, ttl, data));
1963 
1964 }
1965 
1966 isc_result_t
dns_sdlz_putsoa(dns_sdlzlookup_t * lookup,const char * mname,const char * rname,isc_uint32_t serial)1967 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
1968 		isc_uint32_t serial)
1969 {
1970 	char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
1971 	int n;
1972 
1973 	REQUIRE(mname != NULL);
1974 	REQUIRE(rname != NULL);
1975 
1976 	n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
1977 		     mname, rname, serial,
1978 		     SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
1979 		     SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
1980 	if (n >= (int)sizeof(str) || n < 0)
1981 		return (ISC_R_NOSPACE);
1982 	return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
1983 }
1984 
1985 isc_result_t
dns_sdlzregister(const char * drivername,const dns_sdlzmethods_t * methods,void * driverarg,unsigned int flags,isc_mem_t * mctx,dns_sdlzimplementation_t ** sdlzimp)1986 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
1987 		 void *driverarg, unsigned int flags, isc_mem_t *mctx,
1988 		 dns_sdlzimplementation_t **sdlzimp)
1989 {
1990 
1991 	dns_sdlzimplementation_t *imp;
1992 	isc_result_t result;
1993 
1994 	/*
1995 	 * Performs checks to make sure data is as we expect it to be.
1996 	 */
1997 	REQUIRE(drivername != NULL);
1998 	REQUIRE(methods != NULL);
1999 	REQUIRE(methods->findzone != NULL);
2000 	REQUIRE(methods->lookup != NULL);
2001 	REQUIRE(mctx != NULL);
2002 	REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
2003 	REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER |
2004 			   DNS_SDLZFLAG_RELATIVERDATA |
2005 			   DNS_SDLZFLAG_THREADSAFE)) == 0);
2006 
2007 	/* Write debugging message to log */
2008 	sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
2009 
2010 	/*
2011 	 * Allocate memory for a sdlz_implementation object.  Error if
2012 	 * we cannot.
2013 	 */
2014 	imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
2015 	if (imp == NULL)
2016 		return (ISC_R_NOMEMORY);
2017 
2018 	/* Make sure memory region is set to all 0's */
2019 	memset(imp, 0, sizeof(dns_sdlzimplementation_t));
2020 
2021 	/* Store the data passed into this method */
2022 	imp->methods = methods;
2023 	imp->driverarg = driverarg;
2024 	imp->flags = flags;
2025 	imp->mctx = NULL;
2026 
2027 	/* attach the new sdlz_implementation object to a memory context */
2028 	isc_mem_attach(mctx, &imp->mctx);
2029 
2030 	/*
2031 	 * initialize the driver lock, error if we cannot
2032 	 * (used if a driver does not support multiple threads)
2033 	 */
2034 	result = isc_mutex_init(&imp->driverlock);
2035 	if (result != ISC_R_SUCCESS) {
2036 		UNEXPECTED_ERROR(__FILE__, __LINE__,
2037 				 "isc_mutex_init() failed: %s",
2038 				 isc_result_totext(result));
2039 		goto cleanup_mctx;
2040 	}
2041 
2042 	imp->dlz_imp = NULL;
2043 
2044 	/*
2045 	 * register the DLZ driver.  Pass in our "extra" sdlz information as
2046 	 * a driverarg.  (that's why we stored the passed in driver arg in our
2047 	 * sdlz_implementation structure)  Also, store the dlz_implementation
2048 	 * structure in our sdlz_implementation.
2049 	 */
2050 	result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
2051 				 &imp->dlz_imp);
2052 
2053 	/* if registration fails, cleanup and get outta here. */
2054 	if (result != ISC_R_SUCCESS)
2055 		goto cleanup_mutex;
2056 
2057 	*sdlzimp = imp;
2058 
2059 	return (ISC_R_SUCCESS);
2060 
2061  cleanup_mutex:
2062 	/* destroy the driver lock, we don't need it anymore */
2063 	DESTROYLOCK(&imp->driverlock);
2064 
2065  cleanup_mctx:
2066 	/*
2067 	 * return the memory back to the available memory pool and
2068 	 * remove it from the memory context.
2069 	 */
2070 	isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
2071 	isc_mem_detach(&mctx);
2072 	return (result);
2073 }
2074 
2075 void
dns_sdlzunregister(dns_sdlzimplementation_t ** sdlzimp)2076 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
2077 	dns_sdlzimplementation_t *imp;
2078 	isc_mem_t *mctx;
2079 
2080 	/* Write debugging message to log */
2081 	sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
2082 
2083 	/*
2084 	 * Performs checks to make sure data is as we expect it to be.
2085 	 */
2086 	REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
2087 
2088 	imp = *sdlzimp;
2089 
2090 	/* Unregister the DLZ driver implementation */
2091 	dns_dlzunregister(&imp->dlz_imp);
2092 
2093 	/* destroy the driver lock, we don't need it anymore */
2094 	DESTROYLOCK(&imp->driverlock);
2095 
2096 	mctx = imp->mctx;
2097 
2098 	/*
2099 	 * return the memory back to the available memory pool and
2100 	 * remove it from the memory context.
2101 	 */
2102 	isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
2103 	isc_mem_detach(&mctx);
2104 
2105 	*sdlzimp = NULL;
2106 }
2107 
2108 
2109 isc_result_t
dns_sdlz_setdb(dns_dlzdb_t * dlzdatabase,dns_rdataclass_t rdclass,dns_name_t * name,dns_db_t ** dbp)2110 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
2111 	       dns_name_t *name, dns_db_t **dbp)
2112 {
2113 	isc_result_t result;
2114 
2115 	result = dns_sdlzcreateDBP(dlzdatabase->mctx,
2116 				   dlzdatabase->implementation->driverarg,
2117 				   dlzdatabase->dbdata, name, rdclass, dbp);
2118 	return (result);
2119 }
2120