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