xref: /netbsd/external/mpl/bind/dist/lib/dns/sdlz.c (revision 4ac1c27e)
1*4ac1c27eSchristos /*	$NetBSD: sdlz.c,v 1.11 2023/01/25 21:43:30 christos Exp $	*/
2e2b1b9c0Schristos 
3e2b1b9c0Schristos /*
4c0b5d9fbSchristos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5c0b5d9fbSchristos  *
6c0b5d9fbSchristos  * SPDX-License-Identifier: MPL-2.0 AND ISC
7e2b1b9c0Schristos  *
8e2b1b9c0Schristos  * This Source Code Form is subject to the terms of the Mozilla Public
9e2b1b9c0Schristos  * License, v. 2.0. If a copy of the MPL was not distributed with this
1073584a28Schristos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11e2b1b9c0Schristos  *
12e2b1b9c0Schristos  * See the COPYRIGHT file distributed with this work for additional
13e2b1b9c0Schristos  * information regarding copyright ownership.
14e2b1b9c0Schristos  */
15e2b1b9c0Schristos 
16e2b1b9c0Schristos /*
17e2b1b9c0Schristos  * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
18e2b1b9c0Schristos  *
19e2b1b9c0Schristos  * Permission to use, copy, modify, and distribute this software for any
20e2b1b9c0Schristos  * purpose with or without fee is hereby granted, provided that the
21e2b1b9c0Schristos  * above copyright notice and this permission notice appear in all
22e2b1b9c0Schristos  * copies.
23e2b1b9c0Schristos  *
24e2b1b9c0Schristos  * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
25e2b1b9c0Schristos  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
26e2b1b9c0Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
27e2b1b9c0Schristos  * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
28e2b1b9c0Schristos  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
29e2b1b9c0Schristos  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
30e2b1b9c0Schristos  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
31e2b1b9c0Schristos  * USE OR PERFORMANCE OF THIS SOFTWARE.
32e2b1b9c0Schristos  *
33e2b1b9c0Schristos  * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
34e2b1b9c0Schristos  * conceived and contributed by Rob Butler.
35e2b1b9c0Schristos  *
36e2b1b9c0Schristos  * Permission to use, copy, modify, and distribute this software for any
37e2b1b9c0Schristos  * purpose with or without fee is hereby granted, provided that the
38e2b1b9c0Schristos  * above copyright notice and this permission notice appear in all
39e2b1b9c0Schristos  * copies.
40e2b1b9c0Schristos  *
41e2b1b9c0Schristos  * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
42e2b1b9c0Schristos  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
43e2b1b9c0Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
44e2b1b9c0Schristos  * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
45e2b1b9c0Schristos  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
46e2b1b9c0Schristos  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
47e2b1b9c0Schristos  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
48e2b1b9c0Schristos  * USE OR PERFORMANCE OF THIS SOFTWARE.
49e2b1b9c0Schristos  */
50e2b1b9c0Schristos 
51e2b1b9c0Schristos /*! \file */
52e2b1b9c0Schristos 
53f2e20987Schristos #include <inttypes.h>
54f2e20987Schristos #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/magic.h>
61e2b1b9c0Schristos #include <isc/mem.h>
62e2b1b9c0Schristos #include <isc/once.h>
63e2b1b9c0Schristos #include <isc/print.h>
64e2b1b9c0Schristos #include <isc/region.h>
659742fdb4Schristos #include <isc/rwlock.h>
669742fdb4Schristos #include <isc/string.h>
679742fdb4Schristos #include <isc/util.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>
759742fdb4Schristos #include <dns/master.h>
76e2b1b9c0Schristos #include <dns/rdata.h>
77e2b1b9c0Schristos #include <dns/rdatalist.h>
78e2b1b9c0Schristos #include <dns/rdataset.h>
79e2b1b9c0Schristos #include <dns/rdatasetiter.h>
80e2b1b9c0Schristos #include <dns/rdatatype.h>
81e2b1b9c0Schristos #include <dns/result.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;
1059742fdb4Schristos 
1069742fdb4Schristos 	/* Atomic */
1079742fdb4Schristos 	isc_refcount_t references;
1089742fdb4Schristos 
109e2b1b9c0Schristos 	/* Locked */
110e2b1b9c0Schristos 	dns_dbversion_t *future_version;
111e2b1b9c0Schristos 	int dummy_version;
112e2b1b9c0Schristos };
113e2b1b9c0Schristos 
114e2b1b9c0Schristos struct dns_sdlzlookup {
115e2b1b9c0Schristos 	/* Unlocked */
116e2b1b9c0Schristos 	unsigned int magic;
117e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz;
118e2b1b9c0Schristos 	ISC_LIST(dns_rdatalist_t) lists;
119e2b1b9c0Schristos 	ISC_LIST(isc_buffer_t) buffers;
120e2b1b9c0Schristos 	dns_name_t *name;
121e2b1b9c0Schristos 	ISC_LINK(dns_sdlzlookup_t) link;
122e2b1b9c0Schristos 	dns_rdatacallbacks_t callbacks;
1239742fdb4Schristos 
1249742fdb4Schristos 	/* Atomic */
1259742fdb4Schristos 	isc_refcount_t references;
126e2b1b9c0Schristos };
127e2b1b9c0Schristos 
128e2b1b9c0Schristos typedef struct dns_sdlzlookup dns_sdlznode_t;
129e2b1b9c0Schristos 
130e2b1b9c0Schristos struct dns_sdlzallnodes {
131e2b1b9c0Schristos 	dns_dbiterator_t common;
132e2b1b9c0Schristos 	ISC_LIST(dns_sdlznode_t) nodelist;
133e2b1b9c0Schristos 	dns_sdlznode_t *current;
134e2b1b9c0Schristos 	dns_sdlznode_t *origin;
135e2b1b9c0Schristos };
136e2b1b9c0Schristos 
137e2b1b9c0Schristos typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
138e2b1b9c0Schristos 
139e2b1b9c0Schristos typedef struct sdlz_rdatasetiter {
140e2b1b9c0Schristos 	dns_rdatasetiter_t common;
141e2b1b9c0Schristos 	dns_rdatalist_t *current;
142e2b1b9c0Schristos } sdlz_rdatasetiter_t;
143e2b1b9c0Schristos 
144e2b1b9c0Schristos #define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S')
145e2b1b9c0Schristos 
146e2b1b9c0Schristos /*
147e2b1b9c0Schristos  * Note that "impmagic" is not the first four bytes of the struct, so
148e2b1b9c0Schristos  * ISC_MAGIC_VALID cannot be used.
149e2b1b9c0Schristos  */
150e2b1b9c0Schristos 
1519742fdb4Schristos #define VALID_SDLZDB(sdlzdb) \
1529742fdb4Schristos 	((sdlzdb) != NULL && (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
153e2b1b9c0Schristos 
154e2b1b9c0Schristos #define SDLZLOOKUP_MAGIC	ISC_MAGIC('D', 'L', 'Z', 'L')
155e2b1b9c0Schristos #define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
156e2b1b9c0Schristos #define VALID_SDLZNODE(sdlzn)	VALID_SDLZLOOKUP(sdlzn)
157e2b1b9c0Schristos 
158e2b1b9c0Schristos /* These values are taken from RFC 1537 */
159e2b1b9c0Schristos #define SDLZ_DEFAULT_REFRESH 28800U  /* 8 hours */
160e2b1b9c0Schristos #define SDLZ_DEFAULT_RETRY   7200U   /* 2 hours */
161e2b1b9c0Schristos #define SDLZ_DEFAULT_EXPIRE  604800U /* 7 days */
162e2b1b9c0Schristos #define SDLZ_DEFAULT_MINIMUM 86400U  /* 1 day */
163e2b1b9c0Schristos 
164e2b1b9c0Schristos /* This is a reasonable value */
165e2b1b9c0Schristos #define SDLZ_DEFAULT_TTL (60 * 60 * 24)
166e2b1b9c0Schristos 
167e2b1b9c0Schristos #ifdef __COVERITY__
168e2b1b9c0Schristos #define MAYBE_LOCK(imp)	  LOCK(&imp->driverlock)
169e2b1b9c0Schristos #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
1709742fdb4Schristos #else /* ifdef __COVERITY__ */
171e2b1b9c0Schristos #define MAYBE_LOCK(imp)                                     \
172e2b1b9c0Schristos 	do {                                                \
173e2b1b9c0Schristos 		unsigned int flags = imp->flags;            \
174e2b1b9c0Schristos 		if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
175e2b1b9c0Schristos 			LOCK(&imp->driverlock);             \
176245a9365Srillig 	} while (0)
177e2b1b9c0Schristos 
178e2b1b9c0Schristos #define MAYBE_UNLOCK(imp)                                   \
179e2b1b9c0Schristos 	do {                                                \
180e2b1b9c0Schristos 		unsigned int flags = imp->flags;            \
181e2b1b9c0Schristos 		if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
182e2b1b9c0Schristos 			UNLOCK(&imp->driverlock);           \
183245a9365Srillig 	} while (0)
1849742fdb4Schristos #endif /* ifdef __COVERITY__ */
185e2b1b9c0Schristos 
186e2b1b9c0Schristos /*
187e2b1b9c0Schristos  * Forward references.
188e2b1b9c0Schristos  */
1899742fdb4Schristos static isc_result_t
1909742fdb4Schristos getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
1919742fdb4Schristos 	    unsigned int options, dns_clientinfomethods_t *methods,
1929742fdb4Schristos 	    dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep);
193e2b1b9c0Schristos 
1949742fdb4Schristos static void
1959742fdb4Schristos list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
196e2b1b9c0Schristos 		dns_rdataset_t *rdataset);
197e2b1b9c0Schristos 
1989742fdb4Schristos static void
1999742fdb4Schristos detachnode(dns_db_t *db, dns_dbnode_t **targetp);
200e2b1b9c0Schristos 
2019742fdb4Schristos static void
2029742fdb4Schristos dbiterator_destroy(dns_dbiterator_t **iteratorp);
2039742fdb4Schristos static isc_result_t
2049742fdb4Schristos dbiterator_first(dns_dbiterator_t *iterator);
2059742fdb4Schristos static isc_result_t
2069742fdb4Schristos dbiterator_last(dns_dbiterator_t *iterator);
2079742fdb4Schristos static isc_result_t
2089742fdb4Schristos dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name);
2099742fdb4Schristos static isc_result_t
2109742fdb4Schristos dbiterator_prev(dns_dbiterator_t *iterator);
2119742fdb4Schristos static isc_result_t
2129742fdb4Schristos dbiterator_next(dns_dbiterator_t *iterator);
2139742fdb4Schristos static isc_result_t
2149742fdb4Schristos dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
215e2b1b9c0Schristos 		   dns_name_t *name);
2169742fdb4Schristos static isc_result_t
2179742fdb4Schristos dbiterator_pause(dns_dbiterator_t *iterator);
2189742fdb4Schristos static isc_result_t
2199742fdb4Schristos dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
220e2b1b9c0Schristos 
221e2b1b9c0Schristos static dns_dbiteratormethods_t dbiterator_methods = {
2229742fdb4Schristos 	dbiterator_destroy, dbiterator_first, dbiterator_last,
2239742fdb4Schristos 	dbiterator_seek,    dbiterator_prev,  dbiterator_next,
2249742fdb4Schristos 	dbiterator_current, dbiterator_pause, dbiterator_origin
225e2b1b9c0Schristos };
226e2b1b9c0Schristos 
227e2b1b9c0Schristos /*
228e2b1b9c0Schristos  * Utility functions
229e2b1b9c0Schristos  */
230e2b1b9c0Schristos 
231e2b1b9c0Schristos /*
232e2b1b9c0Schristos  * Log a message at the given level
233e2b1b9c0Schristos  */
234e2b1b9c0Schristos static void
sdlz_log(int level,const char * fmt,...)235e2b1b9c0Schristos sdlz_log(int level, const char *fmt, ...) {
236e2b1b9c0Schristos 	va_list ap;
237e2b1b9c0Schristos 	va_start(ap, fmt);
2389742fdb4Schristos 	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ,
2399742fdb4Schristos 		       ISC_LOG_DEBUG(level), fmt, ap);
240e2b1b9c0Schristos 	va_end(ap);
241e2b1b9c0Schristos }
242e2b1b9c0Schristos 
243e2b1b9c0Schristos /*% Converts the input string to lowercase, in place. */
244e2b1b9c0Schristos static void
dns_sdlz_tolower(char * str)245e2b1b9c0Schristos dns_sdlz_tolower(char *str) {
246e2b1b9c0Schristos 	unsigned int len = strlen(str);
247e2b1b9c0Schristos 	unsigned int i;
248e2b1b9c0Schristos 
249e2b1b9c0Schristos 	for (i = 0; i < len; i++) {
2509742fdb4Schristos 		if (str[i] >= 'A' && str[i] <= 'Z') {
251e2b1b9c0Schristos 			str[i] += 32;
252e2b1b9c0Schristos 		}
253e2b1b9c0Schristos 	}
2549742fdb4Schristos }
255e2b1b9c0Schristos 
256c0b5d9fbSchristos static unsigned int
initial_size(const char * data)257e2b1b9c0Schristos initial_size(const char *data) {
258e2b1b9c0Schristos 	unsigned int len = (strlen(data) / 64) + 1;
259e2b1b9c0Schristos 	return (len * 64 + 64);
260e2b1b9c0Schristos }
261e2b1b9c0Schristos 
262e2b1b9c0Schristos /*
263e2b1b9c0Schristos  * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
264e2b1b9c0Schristos  * driver interface.  See the SDB driver interface documentation for more info.
265e2b1b9c0Schristos  */
266e2b1b9c0Schristos 
267e2b1b9c0Schristos static void
rdatasetiter_destroy(dns_rdatasetiter_t ** iteratorp)268e2b1b9c0Schristos rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
2699742fdb4Schristos 	sdlz_rdatasetiter_t *sdlziterator = (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
rdatasetiter_first(dns_rdatasetiter_t * iterator)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 
2829742fdb4Schristos 	if (ISC_LIST_EMPTY(sdlznode->lists)) {
283e2b1b9c0Schristos 		return (ISC_R_NOMORE);
2849742fdb4Schristos 	}
285e2b1b9c0Schristos 	sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
286e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
287e2b1b9c0Schristos }
288e2b1b9c0Schristos 
289e2b1b9c0Schristos static isc_result_t
rdatasetiter_next(dns_rdatasetiter_t * iterator)290e2b1b9c0Schristos rdatasetiter_next(dns_rdatasetiter_t *iterator) {
291e2b1b9c0Schristos 	sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
292e2b1b9c0Schristos 
293e2b1b9c0Schristos 	sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
2949742fdb4Schristos 	if (sdlziterator->current == NULL) {
295e2b1b9c0Schristos 		return (ISC_R_NOMORE);
2969742fdb4Schristos 	} else {
297e2b1b9c0Schristos 		return (ISC_R_SUCCESS);
298e2b1b9c0Schristos 	}
2999742fdb4Schristos }
300e2b1b9c0Schristos 
301e2b1b9c0Schristos static void
rdatasetiter_current(dns_rdatasetiter_t * iterator,dns_rdataset_t * rdataset)302e2b1b9c0Schristos rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
303e2b1b9c0Schristos 	sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
304e2b1b9c0Schristos 
305e2b1b9c0Schristos 	list_tordataset(sdlziterator->current, iterator->db, iterator->node,
306e2b1b9c0Schristos 			rdataset);
307e2b1b9c0Schristos }
308e2b1b9c0Schristos 
309e2b1b9c0Schristos static dns_rdatasetitermethods_t rdatasetiter_methods = {
3109742fdb4Schristos 	rdatasetiter_destroy, rdatasetiter_first, 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
attach(dns_db_t * source,dns_db_t ** targetp)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 
3259742fdb4Schristos 	isc_refcount_increment(&sdlz->references);
326e2b1b9c0Schristos 
327e2b1b9c0Schristos 	*targetp = source;
328e2b1b9c0Schristos }
329e2b1b9c0Schristos 
330e2b1b9c0Schristos static void
destroy(dns_sdlz_db_t * sdlz)331e2b1b9c0Schristos destroy(dns_sdlz_db_t *sdlz) {
332e2b1b9c0Schristos 	sdlz->common.magic = 0;
333e2b1b9c0Schristos 	sdlz->common.impmagic = 0;
334e2b1b9c0Schristos 
3359742fdb4Schristos 	dns_name_free(&sdlz->common.origin, sdlz->common.mctx);
336e2b1b9c0Schristos 
3379742fdb4Schristos 	isc_refcount_destroy(&sdlz->references);
3389742fdb4Schristos 	isc_mem_putanddetach(&sdlz->common.mctx, sdlz, sizeof(dns_sdlz_db_t));
339e2b1b9c0Schristos }
340e2b1b9c0Schristos 
341e2b1b9c0Schristos static void
detach(dns_db_t ** dbp)342e2b1b9c0Schristos detach(dns_db_t **dbp) {
343e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
344e2b1b9c0Schristos 
345e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
346e2b1b9c0Schristos 
347e2b1b9c0Schristos 	*dbp = NULL;
3489742fdb4Schristos 
3499742fdb4Schristos 	if (isc_refcount_decrement(&sdlz->references) == 1) {
3509742fdb4Schristos 		destroy(sdlz);
3519742fdb4Schristos 	}
352e2b1b9c0Schristos }
353e2b1b9c0Schristos 
354e2b1b9c0Schristos static isc_result_t
beginload(dns_db_t * db,dns_rdatacallbacks_t * callbacks)355e2b1b9c0Schristos beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
356e2b1b9c0Schristos 	UNUSED(db);
357e2b1b9c0Schristos 	UNUSED(callbacks);
358e2b1b9c0Schristos 	return (ISC_R_NOTIMPLEMENTED);
359e2b1b9c0Schristos }
360e2b1b9c0Schristos 
361e2b1b9c0Schristos static isc_result_t
endload(dns_db_t * db,dns_rdatacallbacks_t * callbacks)362e2b1b9c0Schristos endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
363e2b1b9c0Schristos 	UNUSED(db);
364e2b1b9c0Schristos 	UNUSED(callbacks);
365e2b1b9c0Schristos 	return (ISC_R_NOTIMPLEMENTED);
366e2b1b9c0Schristos }
367e2b1b9c0Schristos 
368e2b1b9c0Schristos static isc_result_t
dump(dns_db_t * db,dns_dbversion_t * version,const char * filename,dns_masterformat_t masterformat)369e2b1b9c0Schristos dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
3709742fdb4Schristos      dns_masterformat_t masterformat) {
371e2b1b9c0Schristos 	UNUSED(db);
372e2b1b9c0Schristos 	UNUSED(version);
373e2b1b9c0Schristos 	UNUSED(filename);
374e2b1b9c0Schristos 	UNUSED(masterformat);
375e2b1b9c0Schristos 	return (ISC_R_NOTIMPLEMENTED);
376e2b1b9c0Schristos }
377e2b1b9c0Schristos 
378e2b1b9c0Schristos static void
currentversion(dns_db_t * db,dns_dbversion_t ** versionp)379e2b1b9c0Schristos currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
380e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
381e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
382e2b1b9c0Schristos 	REQUIRE(versionp != NULL && *versionp == NULL);
383e2b1b9c0Schristos 
384e2b1b9c0Schristos 	*versionp = (void *)&sdlz->dummy_version;
385e2b1b9c0Schristos 	return;
386e2b1b9c0Schristos }
387e2b1b9c0Schristos 
388e2b1b9c0Schristos static isc_result_t
newversion(dns_db_t * db,dns_dbversion_t ** versionp)389e2b1b9c0Schristos newversion(dns_db_t *db, dns_dbversion_t **versionp) {
390e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
391e2b1b9c0Schristos 	char origin[DNS_NAME_MAXTEXT + 1];
392e2b1b9c0Schristos 	isc_result_t result;
393e2b1b9c0Schristos 
394e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
395e2b1b9c0Schristos 
3969742fdb4Schristos 	if (sdlz->dlzimp->methods->newversion == NULL) {
397e2b1b9c0Schristos 		return (ISC_R_NOTIMPLEMENTED);
3989742fdb4Schristos 	}
399e2b1b9c0Schristos 
400e2b1b9c0Schristos 	dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
401e2b1b9c0Schristos 
4029742fdb4Schristos 	result = sdlz->dlzimp->methods->newversion(
4039742fdb4Schristos 		origin, sdlz->dlzimp->driverarg, sdlz->dbdata, versionp);
404e2b1b9c0Schristos 	if (result != ISC_R_SUCCESS) {
405e2b1b9c0Schristos 		sdlz_log(ISC_LOG_ERROR,
4069742fdb4Schristos 			 "sdlz newversion on origin %s failed : %s", origin,
4079742fdb4Schristos 			 isc_result_totext(result));
408e2b1b9c0Schristos 		return (result);
409e2b1b9c0Schristos 	}
410e2b1b9c0Schristos 
411e2b1b9c0Schristos 	sdlz->future_version = *versionp;
412e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
413e2b1b9c0Schristos }
414e2b1b9c0Schristos 
415e2b1b9c0Schristos static void
attachversion(dns_db_t * db,dns_dbversion_t * source,dns_dbversion_t ** targetp)4169742fdb4Schristos attachversion(dns_db_t *db, dns_dbversion_t *source,
4179742fdb4Schristos 	      dns_dbversion_t **targetp) {
418e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
419e2b1b9c0Schristos 
420e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
421e2b1b9c0Schristos 	REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version);
422e2b1b9c0Schristos 
423e2b1b9c0Schristos 	*targetp = source;
424e2b1b9c0Schristos }
425e2b1b9c0Schristos 
426e2b1b9c0Schristos static void
closeversion(dns_db_t * db,dns_dbversion_t ** versionp,bool commit)427f2e20987Schristos closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
428e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
429e2b1b9c0Schristos 	char origin[DNS_NAME_MAXTEXT + 1];
430e2b1b9c0Schristos 
431e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
432e2b1b9c0Schristos 	REQUIRE(versionp != NULL);
433e2b1b9c0Schristos 
434e2b1b9c0Schristos 	if (*versionp == (void *)&sdlz->dummy_version) {
435e2b1b9c0Schristos 		*versionp = NULL;
436e2b1b9c0Schristos 		return;
437e2b1b9c0Schristos 	}
438e2b1b9c0Schristos 
439e2b1b9c0Schristos 	REQUIRE(*versionp == sdlz->future_version);
440e2b1b9c0Schristos 	REQUIRE(sdlz->dlzimp->methods->closeversion != NULL);
441e2b1b9c0Schristos 
442e2b1b9c0Schristos 	dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
443e2b1b9c0Schristos 
444e2b1b9c0Schristos 	sdlz->dlzimp->methods->closeversion(origin, commit,
445e2b1b9c0Schristos 					    sdlz->dlzimp->driverarg,
446e2b1b9c0Schristos 					    sdlz->dbdata, versionp);
4479742fdb4Schristos 	if (*versionp != NULL) {
4489742fdb4Schristos 		sdlz_log(ISC_LOG_ERROR, "sdlz closeversion on origin %s failed",
4499742fdb4Schristos 			 origin);
4509742fdb4Schristos 	}
451e2b1b9c0Schristos 
452e2b1b9c0Schristos 	sdlz->future_version = NULL;
453e2b1b9c0Schristos }
454e2b1b9c0Schristos 
455e2b1b9c0Schristos static isc_result_t
createnode(dns_sdlz_db_t * sdlz,dns_sdlznode_t ** nodep)456e2b1b9c0Schristos createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
457e2b1b9c0Schristos 	dns_sdlznode_t *node;
4580377c12bSchristos 	void *sdlzv, *tdlzv;
459e2b1b9c0Schristos 
460e2b1b9c0Schristos 	node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
461e2b1b9c0Schristos 
462e2b1b9c0Schristos 	node->sdlz = NULL;
4630377c12bSchristos 	sdlzv = sdlz;
4640377c12bSchristos 	tdlzv = &node->sdlz;
4650377c12bSchristos 	attach(sdlzv, tdlzv);
466e2b1b9c0Schristos 	ISC_LIST_INIT(node->lists);
467e2b1b9c0Schristos 	ISC_LIST_INIT(node->buffers);
468e2b1b9c0Schristos 	ISC_LINK_INIT(node, link);
469e2b1b9c0Schristos 	node->name = NULL;
470e2b1b9c0Schristos 	dns_rdatacallbacks_init(&node->callbacks);
4719742fdb4Schristos 
4729742fdb4Schristos 	isc_refcount_init(&node->references, 1);
473e2b1b9c0Schristos 	node->magic = SDLZLOOKUP_MAGIC;
474e2b1b9c0Schristos 
475e2b1b9c0Schristos 	*nodep = node;
476e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
477e2b1b9c0Schristos }
478e2b1b9c0Schristos 
479e2b1b9c0Schristos static void
destroynode(dns_sdlznode_t * node)480e2b1b9c0Schristos destroynode(dns_sdlznode_t *node) {
481e2b1b9c0Schristos 	dns_rdatalist_t *list;
482e2b1b9c0Schristos 	dns_rdata_t *rdata;
483e2b1b9c0Schristos 	isc_buffer_t *b;
484e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz;
485e2b1b9c0Schristos 	dns_db_t *db;
486e2b1b9c0Schristos 	isc_mem_t *mctx;
487e2b1b9c0Schristos 
4889742fdb4Schristos 	isc_refcount_destroy(&node->references);
4899742fdb4Schristos 
490e2b1b9c0Schristos 	sdlz = node->sdlz;
491e2b1b9c0Schristos 	mctx = sdlz->common.mctx;
492e2b1b9c0Schristos 
493e2b1b9c0Schristos 	while (!ISC_LIST_EMPTY(node->lists)) {
494e2b1b9c0Schristos 		list = ISC_LIST_HEAD(node->lists);
495e2b1b9c0Schristos 		while (!ISC_LIST_EMPTY(list->rdata)) {
496e2b1b9c0Schristos 			rdata = ISC_LIST_HEAD(list->rdata);
497e2b1b9c0Schristos 			ISC_LIST_UNLINK(list->rdata, rdata, link);
498e2b1b9c0Schristos 			isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
499e2b1b9c0Schristos 		}
500e2b1b9c0Schristos 		ISC_LIST_UNLINK(node->lists, list, link);
501e2b1b9c0Schristos 		isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
502e2b1b9c0Schristos 	}
503e2b1b9c0Schristos 
504e2b1b9c0Schristos 	while (!ISC_LIST_EMPTY(node->buffers)) {
505e2b1b9c0Schristos 		b = ISC_LIST_HEAD(node->buffers);
506e2b1b9c0Schristos 		ISC_LIST_UNLINK(node->buffers, b, link);
507e2b1b9c0Schristos 		isc_buffer_free(&b);
508e2b1b9c0Schristos 	}
509e2b1b9c0Schristos 
510e2b1b9c0Schristos 	if (node->name != NULL) {
511e2b1b9c0Schristos 		dns_name_free(node->name, mctx);
512e2b1b9c0Schristos 		isc_mem_put(mctx, node->name, sizeof(dns_name_t));
513e2b1b9c0Schristos 	}
5149742fdb4Schristos 
515e2b1b9c0Schristos 	node->magic = 0;
516e2b1b9c0Schristos 	isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
517e2b1b9c0Schristos 	db = &sdlz->common;
518e2b1b9c0Schristos 	detach(&db);
519e2b1b9c0Schristos }
520e2b1b9c0Schristos 
521e2b1b9c0Schristos static isc_result_t
getnodedata(dns_db_t * db,const dns_name_t * name,bool create,unsigned int options,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo,dns_dbnode_t ** nodep)522f2e20987Schristos getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
523e2b1b9c0Schristos 	    unsigned int options, dns_clientinfomethods_t *methods,
5249742fdb4Schristos 	    dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) {
525e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
526e2b1b9c0Schristos 	dns_sdlznode_t *node = NULL;
527e2b1b9c0Schristos 	isc_result_t result;
528e2b1b9c0Schristos 	isc_buffer_t b;
529e2b1b9c0Schristos 	char namestr[DNS_NAME_MAXTEXT + 1];
530e2b1b9c0Schristos 	isc_buffer_t b2;
531e2b1b9c0Schristos 	char zonestr[DNS_NAME_MAXTEXT + 1];
532f2e20987Schristos 	bool isorigin;
533e2b1b9c0Schristos 	dns_sdlzauthorityfunc_t authority;
534e2b1b9c0Schristos 
535e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
536e2b1b9c0Schristos 	REQUIRE(nodep != NULL && *nodep == NULL);
537e2b1b9c0Schristos 
538e2b1b9c0Schristos 	if (sdlz->dlzimp->methods->newversion == NULL) {
539803e9293Schristos 		REQUIRE(!create);
540e2b1b9c0Schristos 	}
541e2b1b9c0Schristos 
542e2b1b9c0Schristos 	isc_buffer_init(&b, namestr, sizeof(namestr));
543e2b1b9c0Schristos 	if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
544e2b1b9c0Schristos 		dns_name_t relname;
545e2b1b9c0Schristos 		unsigned int labels;
546e2b1b9c0Schristos 
547e2b1b9c0Schristos 		labels = dns_name_countlabels(name) -
548e2b1b9c0Schristos 			 dns_name_countlabels(&sdlz->common.origin);
549e2b1b9c0Schristos 		dns_name_init(&relname, NULL);
550e2b1b9c0Schristos 		dns_name_getlabelsequence(name, 0, labels, &relname);
551f2e20987Schristos 		result = dns_name_totext(&relname, true, &b);
5529742fdb4Schristos 		if (result != ISC_R_SUCCESS) {
553e2b1b9c0Schristos 			return (result);
5549742fdb4Schristos 		}
555e2b1b9c0Schristos 	} else {
556f2e20987Schristos 		result = dns_name_totext(name, true, &b);
5579742fdb4Schristos 		if (result != ISC_R_SUCCESS) {
558e2b1b9c0Schristos 			return (result);
559e2b1b9c0Schristos 		}
5609742fdb4Schristos 	}
561e2b1b9c0Schristos 	isc_buffer_putuint8(&b, 0);
562e2b1b9c0Schristos 
563e2b1b9c0Schristos 	isc_buffer_init(&b2, zonestr, sizeof(zonestr));
564f2e20987Schristos 	result = dns_name_totext(&sdlz->common.origin, true, &b2);
5659742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
566e2b1b9c0Schristos 		return (result);
5679742fdb4Schristos 	}
568e2b1b9c0Schristos 	isc_buffer_putuint8(&b2, 0);
569e2b1b9c0Schristos 
570e2b1b9c0Schristos 	result = createnode(sdlz, &node);
5719742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
572e2b1b9c0Schristos 		return (result);
5739742fdb4Schristos 	}
574e2b1b9c0Schristos 
575e2b1b9c0Schristos 	isorigin = dns_name_equal(name, &sdlz->common.origin);
576e2b1b9c0Schristos 
577e2b1b9c0Schristos 	/* make sure strings are always lowercase */
578e2b1b9c0Schristos 	dns_sdlz_tolower(zonestr);
579e2b1b9c0Schristos 	dns_sdlz_tolower(namestr);
580e2b1b9c0Schristos 
581e2b1b9c0Schristos 	MAYBE_LOCK(sdlz->dlzimp);
582e2b1b9c0Schristos 
583e2b1b9c0Schristos 	/* try to lookup the host (namestr) */
5849742fdb4Schristos 	result = sdlz->dlzimp->methods->lookup(
5859742fdb4Schristos 		zonestr, namestr, sdlz->dlzimp->driverarg, sdlz->dbdata, node,
586e2b1b9c0Schristos 		methods, clientinfo);
587e2b1b9c0Schristos 
588e2b1b9c0Schristos 	/*
589e2b1b9c0Schristos 	 * If the name was not found and DNS_DBFIND_NOWILD is not
590e2b1b9c0Schristos 	 * set, then we try to find a wildcard entry.
591e2b1b9c0Schristos 	 *
592e2b1b9c0Schristos 	 * If DNS_DBFIND_NOZONECUT is set and there are multiple
593e2b1b9c0Schristos 	 * levels between the host and the zone origin, we also look
594e2b1b9c0Schristos 	 * for wildcards at each level.
595e2b1b9c0Schristos 	 */
596e2b1b9c0Schristos 	if (result == ISC_R_NOTFOUND && !create &&
597*4ac1c27eSchristos 	    (options & DNS_DBFIND_NOWILD) == 0)
598*4ac1c27eSchristos 	{
599e2b1b9c0Schristos 		unsigned int i, dlabels, nlabels;
600e2b1b9c0Schristos 
601e2b1b9c0Schristos 		nlabels = dns_name_countlabels(name);
602e2b1b9c0Schristos 		dlabels = nlabels - dns_name_countlabels(&sdlz->common.origin);
603e2b1b9c0Schristos 		for (i = 0; i < dlabels; i++) {
604e2b1b9c0Schristos 			char wildstr[DNS_NAME_MAXTEXT + 1];
605e2b1b9c0Schristos 			dns_fixedname_t fixed;
606e2b1b9c0Schristos 			const dns_name_t *wild;
607e2b1b9c0Schristos 
608e2b1b9c0Schristos 			dns_fixedname_init(&fixed);
60977279b93Schristos 			if (i == dlabels - 1) {
610e2b1b9c0Schristos 				wild = dns_wildcardname;
61177279b93Schristos 			} else {
612e2b1b9c0Schristos 				dns_name_t *fname;
613e2b1b9c0Schristos 				fname = dns_fixedname_name(&fixed);
6149742fdb4Schristos 				dns_name_getlabelsequence(
6159742fdb4Schristos 					name, i + 1, dlabels - i - 1, fname);
6169742fdb4Schristos 				result = dns_name_concatenate(
6179742fdb4Schristos 					dns_wildcardname, fname, fname, NULL);
61877279b93Schristos 				if (result != ISC_R_SUCCESS) {
61977279b93Schristos 					MAYBE_UNLOCK(sdlz->dlzimp);
620e2b1b9c0Schristos 					return (result);
62177279b93Schristos 				}
622e2b1b9c0Schristos 				wild = fname;
623e2b1b9c0Schristos 			}
624e2b1b9c0Schristos 
625e2b1b9c0Schristos 			isc_buffer_init(&b, wildstr, sizeof(wildstr));
626f2e20987Schristos 			result = dns_name_totext(wild, true, &b);
62777279b93Schristos 			if (result != ISC_R_SUCCESS) {
62877279b93Schristos 				MAYBE_UNLOCK(sdlz->dlzimp);
629e2b1b9c0Schristos 				return (result);
63077279b93Schristos 			}
631e2b1b9c0Schristos 			isc_buffer_putuint8(&b, 0);
632e2b1b9c0Schristos 
6339742fdb4Schristos 			result = sdlz->dlzimp->methods->lookup(
6349742fdb4Schristos 				zonestr, wildstr, sdlz->dlzimp->driverarg,
6359742fdb4Schristos 				sdlz->dbdata, node, methods, clientinfo);
6369742fdb4Schristos 			if (result == ISC_R_SUCCESS) {
637e2b1b9c0Schristos 				break;
638e2b1b9c0Schristos 			}
639e2b1b9c0Schristos 		}
6409742fdb4Schristos 	}
641e2b1b9c0Schristos 
642e2b1b9c0Schristos 	MAYBE_UNLOCK(sdlz->dlzimp);
643e2b1b9c0Schristos 
6449742fdb4Schristos 	if (result == ISC_R_NOTFOUND && (isorigin || create)) {
645e2b1b9c0Schristos 		result = ISC_R_SUCCESS;
6469742fdb4Schristos 	}
647e2b1b9c0Schristos 
648e2b1b9c0Schristos 	if (result != ISC_R_SUCCESS) {
64973584a28Schristos 		isc_refcount_decrementz(&node->references);
650e2b1b9c0Schristos 		destroynode(node);
651e2b1b9c0Schristos 		return (result);
652e2b1b9c0Schristos 	}
653e2b1b9c0Schristos 
654e2b1b9c0Schristos 	if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
655e2b1b9c0Schristos 		MAYBE_LOCK(sdlz->dlzimp);
656e2b1b9c0Schristos 		authority = sdlz->dlzimp->methods->authority;
657e2b1b9c0Schristos 		result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
658e2b1b9c0Schristos 				      sdlz->dbdata, node);
659e2b1b9c0Schristos 		MAYBE_UNLOCK(sdlz->dlzimp);
6609742fdb4Schristos 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
66173584a28Schristos 			isc_refcount_decrementz(&node->references);
662e2b1b9c0Schristos 			destroynode(node);
663e2b1b9c0Schristos 			return (result);
664e2b1b9c0Schristos 		}
665e2b1b9c0Schristos 	}
666e2b1b9c0Schristos 
667e2b1b9c0Schristos 	if (node->name == NULL) {
6689742fdb4Schristos 		node->name = isc_mem_get(sdlz->common.mctx, sizeof(dns_name_t));
669e2b1b9c0Schristos 		dns_name_init(node->name, NULL);
6709742fdb4Schristos 		dns_name_dup(name, sdlz->common.mctx, node->name);
671e2b1b9c0Schristos 	}
672e2b1b9c0Schristos 
673e2b1b9c0Schristos 	*nodep = node;
674e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
675e2b1b9c0Schristos }
676e2b1b9c0Schristos 
677e2b1b9c0Schristos static isc_result_t
findnodeext(dns_db_t * db,const dns_name_t * name,bool create,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo,dns_dbnode_t ** nodep)678f2e20987Schristos findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
679e2b1b9c0Schristos 	    dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
6809742fdb4Schristos 	    dns_dbnode_t **nodep) {
681e2b1b9c0Schristos 	return (getnodedata(db, name, create, 0, methods, clientinfo, nodep));
682e2b1b9c0Schristos }
683e2b1b9c0Schristos 
684e2b1b9c0Schristos static isc_result_t
findnode(dns_db_t * db,const dns_name_t * name,bool create,dns_dbnode_t ** nodep)685f2e20987Schristos findnode(dns_db_t *db, const dns_name_t *name, bool create,
6869742fdb4Schristos 	 dns_dbnode_t **nodep) {
687e2b1b9c0Schristos 	return (getnodedata(db, name, create, 0, NULL, NULL, nodep));
688e2b1b9c0Schristos }
689e2b1b9c0Schristos 
690e2b1b9c0Schristos static isc_result_t
findzonecut(dns_db_t * db,const dns_name_t * name,unsigned int options,isc_stdtime_t now,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_name_t * dcname,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)691e2b1b9c0Schristos findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
692e2b1b9c0Schristos 	    isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
693f2e20987Schristos 	    dns_name_t *dcname, dns_rdataset_t *rdataset,
6949742fdb4Schristos 	    dns_rdataset_t *sigrdataset) {
695e2b1b9c0Schristos 	UNUSED(db);
696e2b1b9c0Schristos 	UNUSED(name);
697e2b1b9c0Schristos 	UNUSED(options);
698e2b1b9c0Schristos 	UNUSED(now);
699e2b1b9c0Schristos 	UNUSED(nodep);
700e2b1b9c0Schristos 	UNUSED(foundname);
701f2e20987Schristos 	UNUSED(dcname);
702e2b1b9c0Schristos 	UNUSED(rdataset);
703e2b1b9c0Schristos 	UNUSED(sigrdataset);
704e2b1b9c0Schristos 
705e2b1b9c0Schristos 	return (ISC_R_NOTIMPLEMENTED);
706e2b1b9c0Schristos }
707e2b1b9c0Schristos 
708e2b1b9c0Schristos static void
attachnode(dns_db_t * db,dns_dbnode_t * source,dns_dbnode_t ** targetp)709e2b1b9c0Schristos attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
710e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
711e2b1b9c0Schristos 	dns_sdlznode_t *node = (dns_sdlznode_t *)source;
712e2b1b9c0Schristos 
713e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
714e2b1b9c0Schristos 
715e2b1b9c0Schristos 	UNUSED(sdlz);
716e2b1b9c0Schristos 
7179742fdb4Schristos 	isc_refcount_increment(&node->references);
718e2b1b9c0Schristos 
719e2b1b9c0Schristos 	*targetp = source;
720e2b1b9c0Schristos }
721e2b1b9c0Schristos 
722e2b1b9c0Schristos static void
detachnode(dns_db_t * db,dns_dbnode_t ** targetp)723e2b1b9c0Schristos detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
724e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
725e2b1b9c0Schristos 	dns_sdlznode_t *node;
726e2b1b9c0Schristos 
727e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
728e2b1b9c0Schristos 	REQUIRE(targetp != NULL && *targetp != NULL);
729e2b1b9c0Schristos 
730e2b1b9c0Schristos 	UNUSED(sdlz);
731e2b1b9c0Schristos 
732e2b1b9c0Schristos 	node = (dns_sdlznode_t *)(*targetp);
733e2b1b9c0Schristos 	*targetp = NULL;
7349742fdb4Schristos 
7359742fdb4Schristos 	if (isc_refcount_decrement(&node->references) == 1) {
7369742fdb4Schristos 		destroynode(node);
7379742fdb4Schristos 	}
738e2b1b9c0Schristos }
739e2b1b9c0Schristos 
740e2b1b9c0Schristos static isc_result_t
expirenode(dns_db_t * db,dns_dbnode_t * node,isc_stdtime_t now)741e2b1b9c0Schristos expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
742e2b1b9c0Schristos 	UNUSED(db);
743e2b1b9c0Schristos 	UNUSED(node);
744e2b1b9c0Schristos 	UNUSED(now);
745c0b5d9fbSchristos 	UNREACHABLE();
746e2b1b9c0Schristos }
747e2b1b9c0Schristos 
748e2b1b9c0Schristos static void
printnode(dns_db_t * db,dns_dbnode_t * node,FILE * out)749e2b1b9c0Schristos printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
750e2b1b9c0Schristos 	UNUSED(db);
751e2b1b9c0Schristos 	UNUSED(node);
752e2b1b9c0Schristos 	UNUSED(out);
753e2b1b9c0Schristos 	return;
754e2b1b9c0Schristos }
755e2b1b9c0Schristos 
756e2b1b9c0Schristos static isc_result_t
createiterator(dns_db_t * db,unsigned int options,dns_dbiterator_t ** iteratorp)7579742fdb4Schristos createiterator(dns_db_t *db, unsigned int options,
7589742fdb4Schristos 	       dns_dbiterator_t **iteratorp) {
759e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
760e2b1b9c0Schristos 	sdlz_dbiterator_t *sdlziter;
761e2b1b9c0Schristos 	isc_result_t result;
762e2b1b9c0Schristos 	isc_buffer_t b;
763e2b1b9c0Schristos 	char zonestr[DNS_NAME_MAXTEXT + 1];
764e2b1b9c0Schristos 
765e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
766e2b1b9c0Schristos 
7679742fdb4Schristos 	if (sdlz->dlzimp->methods->allnodes == NULL) {
768e2b1b9c0Schristos 		return (ISC_R_NOTIMPLEMENTED);
7699742fdb4Schristos 	}
770e2b1b9c0Schristos 
771e2b1b9c0Schristos 	if ((options & DNS_DB_NSEC3ONLY) != 0 ||
772*4ac1c27eSchristos 	    (options & DNS_DB_NONSEC3) != 0)
773*4ac1c27eSchristos 	{
774e2b1b9c0Schristos 		return (ISC_R_NOTIMPLEMENTED);
7759742fdb4Schristos 	}
776e2b1b9c0Schristos 
777e2b1b9c0Schristos 	isc_buffer_init(&b, zonestr, sizeof(zonestr));
778f2e20987Schristos 	result = dns_name_totext(&sdlz->common.origin, true, &b);
7799742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
780e2b1b9c0Schristos 		return (result);
7819742fdb4Schristos 	}
782e2b1b9c0Schristos 	isc_buffer_putuint8(&b, 0);
783e2b1b9c0Schristos 
784e2b1b9c0Schristos 	sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
785e2b1b9c0Schristos 
786e2b1b9c0Schristos 	sdlziter->common.methods = &dbiterator_methods;
787e2b1b9c0Schristos 	sdlziter->common.db = NULL;
788e2b1b9c0Schristos 	dns_db_attach(db, &sdlziter->common.db);
7899742fdb4Schristos 	sdlziter->common.relative_names = ((options & DNS_DB_RELATIVENAMES) !=
7909742fdb4Schristos 					   0);
791e2b1b9c0Schristos 	sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
792e2b1b9c0Schristos 	ISC_LIST_INIT(sdlziter->nodelist);
793e2b1b9c0Schristos 	sdlziter->current = NULL;
794e2b1b9c0Schristos 	sdlziter->origin = NULL;
795e2b1b9c0Schristos 
796e2b1b9c0Schristos 	/* make sure strings are always lowercase */
797e2b1b9c0Schristos 	dns_sdlz_tolower(zonestr);
798e2b1b9c0Schristos 
799e2b1b9c0Schristos 	MAYBE_LOCK(sdlz->dlzimp);
8009742fdb4Schristos 	result = sdlz->dlzimp->methods->allnodes(
8019742fdb4Schristos 		zonestr, sdlz->dlzimp->driverarg, sdlz->dbdata, sdlziter);
802e2b1b9c0Schristos 	MAYBE_UNLOCK(sdlz->dlzimp);
803e2b1b9c0Schristos 	if (result != ISC_R_SUCCESS) {
804e2b1b9c0Schristos 		dns_dbiterator_t *iter = &sdlziter->common;
805e2b1b9c0Schristos 		dbiterator_destroy(&iter);
806e2b1b9c0Schristos 		return (result);
807e2b1b9c0Schristos 	}
808e2b1b9c0Schristos 
809e2b1b9c0Schristos 	if (sdlziter->origin != NULL) {
810e2b1b9c0Schristos 		ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
811e2b1b9c0Schristos 		ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
812e2b1b9c0Schristos 	}
813e2b1b9c0Schristos 
814e2b1b9c0Schristos 	*iteratorp = (dns_dbiterator_t *)sdlziter;
815e2b1b9c0Schristos 
816e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
817e2b1b9c0Schristos }
818e2b1b9c0Schristos 
819e2b1b9c0Schristos static isc_result_t
findrdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdatatype_t type,dns_rdatatype_t covers,isc_stdtime_t now,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)820e2b1b9c0Schristos findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
8219742fdb4Schristos 	     dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
8229742fdb4Schristos 	     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
8239742fdb4Schristos 	REQUIRE(VALID_SDLZNODE(node));
824e2b1b9c0Schristos 	dns_rdatalist_t *list;
825e2b1b9c0Schristos 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
826e2b1b9c0Schristos 
827e2b1b9c0Schristos 	UNUSED(db);
828e2b1b9c0Schristos 	UNUSED(version);
829e2b1b9c0Schristos 	UNUSED(covers);
830e2b1b9c0Schristos 	UNUSED(now);
831e2b1b9c0Schristos 	UNUSED(sigrdataset);
832e2b1b9c0Schristos 
8339742fdb4Schristos 	if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig) {
834e2b1b9c0Schristos 		return (ISC_R_NOTIMPLEMENTED);
8359742fdb4Schristos 	}
836e2b1b9c0Schristos 
837e2b1b9c0Schristos 	list = ISC_LIST_HEAD(sdlznode->lists);
838e2b1b9c0Schristos 	while (list != NULL) {
8399742fdb4Schristos 		if (list->type == type) {
840e2b1b9c0Schristos 			break;
8419742fdb4Schristos 		}
842e2b1b9c0Schristos 		list = ISC_LIST_NEXT(list, link);
843e2b1b9c0Schristos 	}
8449742fdb4Schristos 	if (list == NULL) {
845e2b1b9c0Schristos 		return (ISC_R_NOTFOUND);
8469742fdb4Schristos 	}
847e2b1b9c0Schristos 
848e2b1b9c0Schristos 	list_tordataset(list, db, node, rdataset);
849e2b1b9c0Schristos 
850e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
851e2b1b9c0Schristos }
852e2b1b9c0Schristos 
853e2b1b9c0Schristos static isc_result_t
findext(dns_db_t * db,const dns_name_t * name,dns_dbversion_t * version,dns_rdatatype_t type,unsigned int options,isc_stdtime_t now,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)854e2b1b9c0Schristos findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
855e2b1b9c0Schristos 	dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
856e2b1b9c0Schristos 	dns_dbnode_t **nodep, dns_name_t *foundname,
857e2b1b9c0Schristos 	dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
8589742fdb4Schristos 	dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
859e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
860e2b1b9c0Schristos 	dns_dbnode_t *node = NULL;
861e2b1b9c0Schristos 	dns_fixedname_t fname;
862e2b1b9c0Schristos 	dns_rdataset_t xrdataset;
863e2b1b9c0Schristos 	dns_name_t *xname;
864e2b1b9c0Schristos 	unsigned int nlabels, olabels;
865e2b1b9c0Schristos 	isc_result_t result;
866e2b1b9c0Schristos 	unsigned int i;
867e2b1b9c0Schristos 
868e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
869e2b1b9c0Schristos 	REQUIRE(nodep == NULL || *nodep == NULL);
8709742fdb4Schristos 	REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version ||
871e2b1b9c0Schristos 		version == sdlz->future_version);
872e2b1b9c0Schristos 
873e2b1b9c0Schristos 	UNUSED(sdlz);
874e2b1b9c0Schristos 
8759742fdb4Schristos 	if (!dns_name_issubdomain(name, &db->origin)) {
876e2b1b9c0Schristos 		return (DNS_R_NXDOMAIN);
8779742fdb4Schristos 	}
878e2b1b9c0Schristos 
879e2b1b9c0Schristos 	olabels = dns_name_countlabels(&db->origin);
880e2b1b9c0Schristos 	nlabels = dns_name_countlabels(name);
881e2b1b9c0Schristos 
882e2b1b9c0Schristos 	xname = dns_fixedname_initname(&fname);
883e2b1b9c0Schristos 
884e2b1b9c0Schristos 	if (rdataset == NULL) {
885e2b1b9c0Schristos 		dns_rdataset_init(&xrdataset);
886e2b1b9c0Schristos 		rdataset = &xrdataset;
887e2b1b9c0Schristos 	}
888e2b1b9c0Schristos 
889e2b1b9c0Schristos 	result = DNS_R_NXDOMAIN;
890e2b1b9c0Schristos 
891e2b1b9c0Schristos 	/*
892e2b1b9c0Schristos 	 * If we're not walking down searching for zone
893e2b1b9c0Schristos 	 * cuts, we can cut straight to the chase
894e2b1b9c0Schristos 	 */
895e2b1b9c0Schristos 	if ((options & DNS_DBFIND_NOZONECUT) != 0) {
896e2b1b9c0Schristos 		i = nlabels;
897e2b1b9c0Schristos 		goto search;
898e2b1b9c0Schristos 	}
899e2b1b9c0Schristos 
900e2b1b9c0Schristos 	for (i = olabels; i <= nlabels; i++) {
901e2b1b9c0Schristos 	search:
902e2b1b9c0Schristos 		/*
903e2b1b9c0Schristos 		 * Look up the next label.
904e2b1b9c0Schristos 		 */
905e2b1b9c0Schristos 		dns_name_getlabelsequence(name, nlabels - i, i, xname);
9069742fdb4Schristos 		result = getnodedata(db, xname, false, options, methods,
9079742fdb4Schristos 				     clientinfo, &node);
908e2b1b9c0Schristos 		if (result == ISC_R_NOTFOUND) {
909e2b1b9c0Schristos 			result = DNS_R_NXDOMAIN;
910e2b1b9c0Schristos 			continue;
9119742fdb4Schristos 		} else if (result != ISC_R_SUCCESS) {
912e2b1b9c0Schristos 			break;
9139742fdb4Schristos 		}
914e2b1b9c0Schristos 
915e2b1b9c0Schristos 		/*
916e2b1b9c0Schristos 		 * Look for a DNAME at the current label, unless this is
917e2b1b9c0Schristos 		 * the qname.
918e2b1b9c0Schristos 		 */
919e2b1b9c0Schristos 		if (i < nlabels) {
920e2b1b9c0Schristos 			result = findrdataset(db, node, version,
921e2b1b9c0Schristos 					      dns_rdatatype_dname, 0, now,
922e2b1b9c0Schristos 					      rdataset, sigrdataset);
923e2b1b9c0Schristos 			if (result == ISC_R_SUCCESS) {
924e2b1b9c0Schristos 				result = DNS_R_DNAME;
925e2b1b9c0Schristos 				break;
926e2b1b9c0Schristos 			}
927e2b1b9c0Schristos 		}
928e2b1b9c0Schristos 
929e2b1b9c0Schristos 		/*
930e2b1b9c0Schristos 		 * Look for an NS at the current label, unless this is the
931e2b1b9c0Schristos 		 * origin, glue is ok, or there are known to be no zone cuts.
932e2b1b9c0Schristos 		 */
933e2b1b9c0Schristos 		if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0 &&
934e2b1b9c0Schristos 		    (options & DNS_DBFIND_NOZONECUT) == 0)
935e2b1b9c0Schristos 		{
936e2b1b9c0Schristos 			result = findrdataset(db, node, version,
937e2b1b9c0Schristos 					      dns_rdatatype_ns, 0, now,
938e2b1b9c0Schristos 					      rdataset, sigrdataset);
939e2b1b9c0Schristos 
9409742fdb4Schristos 			if (result == ISC_R_SUCCESS && i == nlabels &&
941*4ac1c27eSchristos 			    type == dns_rdatatype_any)
942*4ac1c27eSchristos 			{
943e2b1b9c0Schristos 				result = DNS_R_ZONECUT;
944e2b1b9c0Schristos 				dns_rdataset_disassociate(rdataset);
945e2b1b9c0Schristos 				if (sigrdataset != NULL &&
946*4ac1c27eSchristos 				    dns_rdataset_isassociated(sigrdataset))
947*4ac1c27eSchristos 				{
948e2b1b9c0Schristos 					dns_rdataset_disassociate(sigrdataset);
9499742fdb4Schristos 				}
950e2b1b9c0Schristos 				break;
951e2b1b9c0Schristos 			} else if (result == ISC_R_SUCCESS) {
952e2b1b9c0Schristos 				result = DNS_R_DELEGATION;
953e2b1b9c0Schristos 				break;
954e2b1b9c0Schristos 			}
955e2b1b9c0Schristos 		}
956e2b1b9c0Schristos 
957e2b1b9c0Schristos 		/*
958e2b1b9c0Schristos 		 * If the current name is not the qname, add another label
959e2b1b9c0Schristos 		 * and try again.
960e2b1b9c0Schristos 		 */
961e2b1b9c0Schristos 		if (i < nlabels) {
9629742fdb4Schristos 			detachnode(db, &node);
963e2b1b9c0Schristos 			node = NULL;
964e2b1b9c0Schristos 			continue;
965e2b1b9c0Schristos 		}
966e2b1b9c0Schristos 
967e2b1b9c0Schristos 		/*
968e2b1b9c0Schristos 		 * If we're looking for ANY, we're done.
969e2b1b9c0Schristos 		 */
970e2b1b9c0Schristos 		if (type == dns_rdatatype_any) {
971e2b1b9c0Schristos 			result = ISC_R_SUCCESS;
972e2b1b9c0Schristos 			break;
973e2b1b9c0Schristos 		}
974e2b1b9c0Schristos 
975e2b1b9c0Schristos 		/*
976e2b1b9c0Schristos 		 * Look for the qtype.
977e2b1b9c0Schristos 		 */
9789742fdb4Schristos 		result = findrdataset(db, node, version, type, 0, now, rdataset,
9799742fdb4Schristos 				      sigrdataset);
9809742fdb4Schristos 		if (result == ISC_R_SUCCESS) {
981e2b1b9c0Schristos 			break;
9829742fdb4Schristos 		}
983e2b1b9c0Schristos 
984e2b1b9c0Schristos 		/*
985e2b1b9c0Schristos 		 * Look for a CNAME
986e2b1b9c0Schristos 		 */
987e2b1b9c0Schristos 		if (type != dns_rdatatype_cname) {
988e2b1b9c0Schristos 			result = findrdataset(db, node, version,
989e2b1b9c0Schristos 					      dns_rdatatype_cname, 0, now,
990e2b1b9c0Schristos 					      rdataset, sigrdataset);
991e2b1b9c0Schristos 			if (result == ISC_R_SUCCESS) {
992e2b1b9c0Schristos 				result = DNS_R_CNAME;
993e2b1b9c0Schristos 				break;
994e2b1b9c0Schristos 			}
995e2b1b9c0Schristos 		}
996e2b1b9c0Schristos 
997e2b1b9c0Schristos 		result = DNS_R_NXRRSET;
998e2b1b9c0Schristos 		break;
999e2b1b9c0Schristos 	}
1000e2b1b9c0Schristos 
10019742fdb4Schristos 	if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) {
1002e2b1b9c0Schristos 		dns_rdataset_disassociate(rdataset);
10039742fdb4Schristos 	}
1004e2b1b9c0Schristos 
1005e2b1b9c0Schristos 	if (foundname != NULL) {
10068b4c8a26Schristos 		dns_name_copynf(xname, foundname);
1007e2b1b9c0Schristos 	}
1008e2b1b9c0Schristos 
10099742fdb4Schristos 	if (nodep != NULL) {
1010e2b1b9c0Schristos 		*nodep = node;
10119742fdb4Schristos 	} else if (node != NULL) {
1012e2b1b9c0Schristos 		detachnode(db, &node);
10139742fdb4Schristos 	}
1014e2b1b9c0Schristos 
1015e2b1b9c0Schristos 	return (result);
1016e2b1b9c0Schristos }
1017e2b1b9c0Schristos 
1018e2b1b9c0Schristos static isc_result_t
find(dns_db_t * db,const dns_name_t * name,dns_dbversion_t * version,dns_rdatatype_t type,unsigned int options,isc_stdtime_t now,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)1019e2b1b9c0Schristos find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
1020e2b1b9c0Schristos      dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
10219742fdb4Schristos      dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset,
10229742fdb4Schristos      dns_rdataset_t *sigrdataset) {
10239742fdb4Schristos 	return (findext(db, name, version, type, options, now, nodep, foundname,
10249742fdb4Schristos 			NULL, NULL, rdataset, sigrdataset));
1025e2b1b9c0Schristos }
1026e2b1b9c0Schristos 
1027e2b1b9c0Schristos static isc_result_t
allrdatasets(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,unsigned int options,isc_stdtime_t now,dns_rdatasetiter_t ** iteratorp)1028e2b1b9c0Schristos allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1029*4ac1c27eSchristos 	     unsigned int options, isc_stdtime_t now,
1030*4ac1c27eSchristos 	     dns_rdatasetiter_t **iteratorp) {
1031e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1032e2b1b9c0Schristos 	sdlz_rdatasetiter_t *iterator;
1033e2b1b9c0Schristos 
1034e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
1035e2b1b9c0Schristos 
10369742fdb4Schristos 	REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version ||
1037e2b1b9c0Schristos 		version == sdlz->future_version);
1038e2b1b9c0Schristos 
1039e2b1b9c0Schristos 	UNUSED(version);
1040e2b1b9c0Schristos 	UNUSED(now);
1041e2b1b9c0Schristos 
1042e2b1b9c0Schristos 	iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
1043e2b1b9c0Schristos 
1044e2b1b9c0Schristos 	iterator->common.magic = DNS_RDATASETITER_MAGIC;
1045e2b1b9c0Schristos 	iterator->common.methods = &rdatasetiter_methods;
1046e2b1b9c0Schristos 	iterator->common.db = db;
1047e2b1b9c0Schristos 	iterator->common.node = NULL;
1048e2b1b9c0Schristos 	attachnode(db, node, &iterator->common.node);
1049e2b1b9c0Schristos 	iterator->common.version = version;
1050*4ac1c27eSchristos 	iterator->common.options = options;
1051e2b1b9c0Schristos 	iterator->common.now = now;
1052e2b1b9c0Schristos 
1053e2b1b9c0Schristos 	*iteratorp = (dns_rdatasetiter_t *)iterator;
1054e2b1b9c0Schristos 
1055e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
1056e2b1b9c0Schristos }
1057e2b1b9c0Schristos 
1058e2b1b9c0Schristos static isc_result_t
modrdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdataset_t * rdataset,unsigned int options,dns_sdlzmodrdataset_t mod_function)1059e2b1b9c0Schristos modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1060e2b1b9c0Schristos 	    dns_rdataset_t *rdataset, unsigned int options,
10619742fdb4Schristos 	    dns_sdlzmodrdataset_t mod_function) {
1062e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1063e2b1b9c0Schristos 	dns_master_style_t *style = NULL;
1064e2b1b9c0Schristos 	isc_result_t result;
1065e2b1b9c0Schristos 	isc_buffer_t *buffer = NULL;
1066e2b1b9c0Schristos 	isc_mem_t *mctx;
1067e2b1b9c0Schristos 	dns_sdlznode_t *sdlznode;
1068e2b1b9c0Schristos 	char *rdatastr = NULL;
1069e2b1b9c0Schristos 	char name[DNS_NAME_MAXTEXT + 1];
1070e2b1b9c0Schristos 
1071e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
1072e2b1b9c0Schristos 
10739742fdb4Schristos 	if (mod_function == NULL) {
1074e2b1b9c0Schristos 		return (ISC_R_NOTIMPLEMENTED);
10759742fdb4Schristos 	}
1076e2b1b9c0Schristos 
1077e2b1b9c0Schristos 	sdlznode = (dns_sdlznode_t *)node;
1078e2b1b9c0Schristos 
1079e2b1b9c0Schristos 	UNUSED(options);
1080e2b1b9c0Schristos 
1081e2b1b9c0Schristos 	dns_name_format(sdlznode->name, name, sizeof(name));
1082e2b1b9c0Schristos 
1083e2b1b9c0Schristos 	mctx = sdlz->common.mctx;
1084e2b1b9c0Schristos 
10859742fdb4Schristos 	isc_buffer_allocate(mctx, &buffer, 1024);
1086e2b1b9c0Schristos 
10879742fdb4Schristos 	result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, 0xffffffff,
10889742fdb4Schristos 					mctx);
10899742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
1090e2b1b9c0Schristos 		goto cleanup;
10919742fdb4Schristos 	}
1092e2b1b9c0Schristos 
10939742fdb4Schristos 	result = dns_master_rdatasettotext(sdlznode->name, rdataset, style,
10949742fdb4Schristos 					   NULL, buffer);
10959742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
1096e2b1b9c0Schristos 		goto cleanup;
10979742fdb4Schristos 	}
1098e2b1b9c0Schristos 
1099e2b1b9c0Schristos 	if (isc_buffer_usedlength(buffer) < 1) {
1100e2b1b9c0Schristos 		result = ISC_R_BADADDRESSFORM;
1101e2b1b9c0Schristos 		goto cleanup;
1102e2b1b9c0Schristos 	}
1103e2b1b9c0Schristos 
1104e2b1b9c0Schristos 	rdatastr = isc_buffer_base(buffer);
1105e2b1b9c0Schristos 	if (rdatastr == NULL) {
1106e2b1b9c0Schristos 		result = ISC_R_NOMEMORY;
1107e2b1b9c0Schristos 		goto cleanup;
1108e2b1b9c0Schristos 	}
1109e2b1b9c0Schristos 	rdatastr[isc_buffer_usedlength(buffer) - 1] = 0;
1110e2b1b9c0Schristos 
1111e2b1b9c0Schristos 	MAYBE_LOCK(sdlz->dlzimp);
1112e2b1b9c0Schristos 	result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg,
1113e2b1b9c0Schristos 			      sdlz->dbdata, version);
1114e2b1b9c0Schristos 	MAYBE_UNLOCK(sdlz->dlzimp);
1115e2b1b9c0Schristos 
1116e2b1b9c0Schristos cleanup:
1117e2b1b9c0Schristos 	isc_buffer_free(&buffer);
11189742fdb4Schristos 	if (style != NULL) {
1119e2b1b9c0Schristos 		dns_master_styledestroy(&style, mctx);
11209742fdb4Schristos 	}
1121e2b1b9c0Schristos 
1122e2b1b9c0Schristos 	return (result);
1123e2b1b9c0Schristos }
1124e2b1b9c0Schristos 
1125e2b1b9c0Schristos static isc_result_t
addrdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,isc_stdtime_t now,dns_rdataset_t * rdataset,unsigned int options,dns_rdataset_t * addedrdataset)1126e2b1b9c0Schristos addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1127e2b1b9c0Schristos 	    isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
11289742fdb4Schristos 	    dns_rdataset_t *addedrdataset) {
1129e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1130e2b1b9c0Schristos 	isc_result_t result;
1131e2b1b9c0Schristos 
1132e2b1b9c0Schristos 	UNUSED(now);
1133e2b1b9c0Schristos 	UNUSED(addedrdataset);
1134e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
1135e2b1b9c0Schristos 
11369742fdb4Schristos 	if (sdlz->dlzimp->methods->addrdataset == NULL) {
1137e2b1b9c0Schristos 		return (ISC_R_NOTIMPLEMENTED);
11389742fdb4Schristos 	}
1139e2b1b9c0Schristos 
1140e2b1b9c0Schristos 	result = modrdataset(db, node, version, rdataset, options,
1141e2b1b9c0Schristos 			     sdlz->dlzimp->methods->addrdataset);
1142e2b1b9c0Schristos 	return (result);
1143e2b1b9c0Schristos }
1144e2b1b9c0Schristos 
1145e2b1b9c0Schristos static isc_result_t
subtractrdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdataset_t * rdataset,unsigned int options,dns_rdataset_t * newrdataset)1146e2b1b9c0Schristos subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1147e2b1b9c0Schristos 		 dns_rdataset_t *rdataset, unsigned int options,
11489742fdb4Schristos 		 dns_rdataset_t *newrdataset) {
1149e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1150e2b1b9c0Schristos 	isc_result_t result;
1151e2b1b9c0Schristos 
1152e2b1b9c0Schristos 	UNUSED(newrdataset);
1153e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
1154e2b1b9c0Schristos 
1155e2b1b9c0Schristos 	if (sdlz->dlzimp->methods->subtractrdataset == NULL) {
1156e2b1b9c0Schristos 		return (ISC_R_NOTIMPLEMENTED);
1157e2b1b9c0Schristos 	}
1158e2b1b9c0Schristos 
1159e2b1b9c0Schristos 	result = modrdataset(db, node, version, rdataset, options,
1160e2b1b9c0Schristos 			     sdlz->dlzimp->methods->subtractrdataset);
1161e2b1b9c0Schristos 	return (result);
1162e2b1b9c0Schristos }
1163e2b1b9c0Schristos 
1164e2b1b9c0Schristos static isc_result_t
deleterdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdatatype_t type,dns_rdatatype_t covers)1165e2b1b9c0Schristos deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
11669742fdb4Schristos 	       dns_rdatatype_t type, dns_rdatatype_t covers) {
1167e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1168e2b1b9c0Schristos 	char name[DNS_NAME_MAXTEXT + 1];
1169e2b1b9c0Schristos 	char b_type[DNS_RDATATYPE_FORMATSIZE];
1170e2b1b9c0Schristos 	dns_sdlznode_t *sdlznode;
1171e2b1b9c0Schristos 	isc_result_t result;
1172e2b1b9c0Schristos 
1173e2b1b9c0Schristos 	UNUSED(covers);
1174e2b1b9c0Schristos 
1175e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
1176e2b1b9c0Schristos 
11779742fdb4Schristos 	if (sdlz->dlzimp->methods->delrdataset == NULL) {
1178e2b1b9c0Schristos 		return (ISC_R_NOTIMPLEMENTED);
11799742fdb4Schristos 	}
1180e2b1b9c0Schristos 
1181e2b1b9c0Schristos 	sdlznode = (dns_sdlznode_t *)node;
1182e2b1b9c0Schristos 	dns_name_format(sdlznode->name, name, sizeof(name));
1183e2b1b9c0Schristos 	dns_rdatatype_format(type, b_type, sizeof(b_type));
1184e2b1b9c0Schristos 
1185e2b1b9c0Schristos 	MAYBE_LOCK(sdlz->dlzimp);
11869742fdb4Schristos 	result = sdlz->dlzimp->methods->delrdataset(
11879742fdb4Schristos 		name, b_type, sdlz->dlzimp->driverarg, sdlz->dbdata, version);
1188e2b1b9c0Schristos 	MAYBE_UNLOCK(sdlz->dlzimp);
1189e2b1b9c0Schristos 
1190e2b1b9c0Schristos 	return (result);
1191e2b1b9c0Schristos }
1192e2b1b9c0Schristos 
1193f2e20987Schristos static bool
issecure(dns_db_t * db)1194e2b1b9c0Schristos issecure(dns_db_t *db) {
1195e2b1b9c0Schristos 	UNUSED(db);
1196e2b1b9c0Schristos 
1197f2e20987Schristos 	return (false);
1198e2b1b9c0Schristos }
1199e2b1b9c0Schristos 
1200e2b1b9c0Schristos static unsigned int
nodecount(dns_db_t * db)1201e2b1b9c0Schristos nodecount(dns_db_t *db) {
1202e2b1b9c0Schristos 	UNUSED(db);
1203e2b1b9c0Schristos 
1204e2b1b9c0Schristos 	return (0);
1205e2b1b9c0Schristos }
1206e2b1b9c0Schristos 
1207f2e20987Schristos static bool
ispersistent(dns_db_t * db)1208e2b1b9c0Schristos ispersistent(dns_db_t *db) {
1209e2b1b9c0Schristos 	UNUSED(db);
1210f2e20987Schristos 	return (true);
1211e2b1b9c0Schristos }
1212e2b1b9c0Schristos 
1213e2b1b9c0Schristos static void
overmem(dns_db_t * db,bool over)1214f2e20987Schristos overmem(dns_db_t *db, bool over) {
1215e2b1b9c0Schristos 	UNUSED(db);
1216e2b1b9c0Schristos 	UNUSED(over);
1217e2b1b9c0Schristos }
1218e2b1b9c0Schristos 
1219e2b1b9c0Schristos static void
settask(dns_db_t * db,isc_task_t * task)1220e2b1b9c0Schristos settask(dns_db_t *db, isc_task_t *task) {
1221e2b1b9c0Schristos 	UNUSED(db);
1222e2b1b9c0Schristos 	UNUSED(task);
1223e2b1b9c0Schristos }
1224e2b1b9c0Schristos 
1225e2b1b9c0Schristos /*
1226e2b1b9c0Schristos  * getoriginnode() is used by the update code to find the
1227e2b1b9c0Schristos  * dns_rdatatype_dnskey record for a zone
1228e2b1b9c0Schristos  */
1229e2b1b9c0Schristos static isc_result_t
getoriginnode(dns_db_t * db,dns_dbnode_t ** nodep)1230e2b1b9c0Schristos getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
1231e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1232e2b1b9c0Schristos 	isc_result_t result;
1233e2b1b9c0Schristos 
1234e2b1b9c0Schristos 	REQUIRE(VALID_SDLZDB(sdlz));
12359742fdb4Schristos 	if (sdlz->dlzimp->methods->newversion == NULL) {
1236e2b1b9c0Schristos 		return (ISC_R_NOTIMPLEMENTED);
12379742fdb4Schristos 	}
1238e2b1b9c0Schristos 
12399742fdb4Schristos 	result = getnodedata(db, &sdlz->common.origin, false, 0, NULL, NULL,
12409742fdb4Schristos 			     nodep);
12419742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
1242e2b1b9c0Schristos 		sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s",
1243e2b1b9c0Schristos 			 isc_result_totext(result));
12449742fdb4Schristos 	}
1245e2b1b9c0Schristos 	return (result);
1246e2b1b9c0Schristos }
1247e2b1b9c0Schristos 
1248e2b1b9c0Schristos static dns_dbmethods_t sdlzdb_methods = {
1249e2b1b9c0Schristos 	attach,
1250e2b1b9c0Schristos 	detach,
1251e2b1b9c0Schristos 	beginload,
1252e2b1b9c0Schristos 	endload,
1253e2b1b9c0Schristos 	NULL, /* serialize */
1254e2b1b9c0Schristos 	dump,
1255e2b1b9c0Schristos 	currentversion,
1256e2b1b9c0Schristos 	newversion,
1257e2b1b9c0Schristos 	attachversion,
1258e2b1b9c0Schristos 	closeversion,
1259e2b1b9c0Schristos 	findnode,
1260e2b1b9c0Schristos 	find,
1261e2b1b9c0Schristos 	findzonecut,
1262e2b1b9c0Schristos 	attachnode,
1263e2b1b9c0Schristos 	detachnode,
1264e2b1b9c0Schristos 	expirenode,
1265e2b1b9c0Schristos 	printnode,
1266e2b1b9c0Schristos 	createiterator,
1267e2b1b9c0Schristos 	findrdataset,
1268e2b1b9c0Schristos 	allrdatasets,
1269e2b1b9c0Schristos 	addrdataset,
1270e2b1b9c0Schristos 	subtractrdataset,
1271e2b1b9c0Schristos 	deleterdataset,
1272e2b1b9c0Schristos 	issecure,
1273e2b1b9c0Schristos 	nodecount,
1274e2b1b9c0Schristos 	ispersistent,
1275e2b1b9c0Schristos 	overmem,
1276e2b1b9c0Schristos 	settask,
1277e2b1b9c0Schristos 	getoriginnode,
1278e2b1b9c0Schristos 	NULL, /* transfernode */
1279e2b1b9c0Schristos 	NULL, /* getnsec3parameters */
1280e2b1b9c0Schristos 	NULL, /* findnsec3node */
1281e2b1b9c0Schristos 	NULL, /* setsigningtime */
1282e2b1b9c0Schristos 	NULL, /* getsigningtime */
1283e2b1b9c0Schristos 	NULL, /* resigned */
1284e2b1b9c0Schristos 	NULL, /* isdnssec */
1285e2b1b9c0Schristos 	NULL, /* getrrsetstats */
1286e2b1b9c0Schristos 	NULL, /* rpz_attach */
1287e2b1b9c0Schristos 	NULL, /* rpz_ready */
1288e2b1b9c0Schristos 	findnodeext,
1289e2b1b9c0Schristos 	findext,
1290e2b1b9c0Schristos 	NULL, /* setcachestats */
1291e2b1b9c0Schristos 	NULL, /* hashsize */
1292e2b1b9c0Schristos 	NULL, /* nodefullname */
1293e2b1b9c0Schristos 	NULL, /* getsize */
1294e2b1b9c0Schristos 	NULL, /* setservestalettl */
1295e2b1b9c0Schristos 	NULL, /* getservestalettl */
129673584a28Schristos 	NULL, /* setservestalerefresh */
129773584a28Schristos 	NULL, /* getservestalerefresh */
129873584a28Schristos 	NULL, /* setgluecachestats */
129973584a28Schristos 	NULL  /* adjusthashsize */
1300e2b1b9c0Schristos };
1301e2b1b9c0Schristos 
1302e2b1b9c0Schristos /*
1303e2b1b9c0Schristos  * Database Iterator Methods.  These methods were "borrowed" from the SDB
1304e2b1b9c0Schristos  * driver interface.  See the SDB driver interface documentation for more info.
1305e2b1b9c0Schristos  */
1306e2b1b9c0Schristos 
1307e2b1b9c0Schristos static void
dbiterator_destroy(dns_dbiterator_t ** iteratorp)1308e2b1b9c0Schristos dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1309e2b1b9c0Schristos 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
1310e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
1311e2b1b9c0Schristos 
1312e2b1b9c0Schristos 	while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
1313e2b1b9c0Schristos 		dns_sdlznode_t *node;
1314e2b1b9c0Schristos 		node = ISC_LIST_HEAD(sdlziter->nodelist);
1315e2b1b9c0Schristos 		ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
131673584a28Schristos 		isc_refcount_decrementz(&node->references);
1317e2b1b9c0Schristos 		destroynode(node);
1318e2b1b9c0Schristos 	}
1319e2b1b9c0Schristos 
1320e2b1b9c0Schristos 	dns_db_detach(&sdlziter->common.db);
1321e2b1b9c0Schristos 	isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
1322e2b1b9c0Schristos 
1323e2b1b9c0Schristos 	*iteratorp = NULL;
1324e2b1b9c0Schristos }
1325e2b1b9c0Schristos 
1326e2b1b9c0Schristos static isc_result_t
dbiterator_first(dns_dbiterator_t * iterator)1327e2b1b9c0Schristos dbiterator_first(dns_dbiterator_t *iterator) {
1328e2b1b9c0Schristos 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1329e2b1b9c0Schristos 
1330e2b1b9c0Schristos 	sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
13319742fdb4Schristos 	if (sdlziter->current == NULL) {
1332e2b1b9c0Schristos 		return (ISC_R_NOMORE);
13339742fdb4Schristos 	} else {
1334e2b1b9c0Schristos 		return (ISC_R_SUCCESS);
1335e2b1b9c0Schristos 	}
13369742fdb4Schristos }
1337e2b1b9c0Schristos 
1338e2b1b9c0Schristos static isc_result_t
dbiterator_last(dns_dbiterator_t * iterator)1339e2b1b9c0Schristos dbiterator_last(dns_dbiterator_t *iterator) {
1340e2b1b9c0Schristos 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1341e2b1b9c0Schristos 
1342e2b1b9c0Schristos 	sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
13439742fdb4Schristos 	if (sdlziter->current == NULL) {
1344e2b1b9c0Schristos 		return (ISC_R_NOMORE);
13459742fdb4Schristos 	} else {
1346e2b1b9c0Schristos 		return (ISC_R_SUCCESS);
1347e2b1b9c0Schristos 	}
13489742fdb4Schristos }
1349e2b1b9c0Schristos 
1350e2b1b9c0Schristos static isc_result_t
dbiterator_seek(dns_dbiterator_t * iterator,const dns_name_t * name)1351e2b1b9c0Schristos dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) {
1352e2b1b9c0Schristos 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1353e2b1b9c0Schristos 
1354e2b1b9c0Schristos 	sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1355e2b1b9c0Schristos 	while (sdlziter->current != NULL) {
13569742fdb4Schristos 		if (dns_name_equal(sdlziter->current->name, name)) {
1357e2b1b9c0Schristos 			return (ISC_R_SUCCESS);
13589742fdb4Schristos 		}
1359e2b1b9c0Schristos 		sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1360e2b1b9c0Schristos 	}
1361e2b1b9c0Schristos 	return (ISC_R_NOTFOUND);
1362e2b1b9c0Schristos }
1363e2b1b9c0Schristos 
1364e2b1b9c0Schristos static isc_result_t
dbiterator_prev(dns_dbiterator_t * iterator)1365e2b1b9c0Schristos dbiterator_prev(dns_dbiterator_t *iterator) {
1366e2b1b9c0Schristos 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1367e2b1b9c0Schristos 
1368e2b1b9c0Schristos 	sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
13699742fdb4Schristos 	if (sdlziter->current == NULL) {
1370e2b1b9c0Schristos 		return (ISC_R_NOMORE);
13719742fdb4Schristos 	} else {
1372e2b1b9c0Schristos 		return (ISC_R_SUCCESS);
1373e2b1b9c0Schristos 	}
13749742fdb4Schristos }
1375e2b1b9c0Schristos 
1376e2b1b9c0Schristos static isc_result_t
dbiterator_next(dns_dbiterator_t * iterator)1377e2b1b9c0Schristos dbiterator_next(dns_dbiterator_t *iterator) {
1378e2b1b9c0Schristos 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1379e2b1b9c0Schristos 
1380e2b1b9c0Schristos 	sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
13819742fdb4Schristos 	if (sdlziter->current == NULL) {
1382e2b1b9c0Schristos 		return (ISC_R_NOMORE);
13839742fdb4Schristos 	} else {
1384e2b1b9c0Schristos 		return (ISC_R_SUCCESS);
1385e2b1b9c0Schristos 	}
13869742fdb4Schristos }
1387e2b1b9c0Schristos 
1388e2b1b9c0Schristos static isc_result_t
dbiterator_current(dns_dbiterator_t * iterator,dns_dbnode_t ** nodep,dns_name_t * name)1389e2b1b9c0Schristos dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
13909742fdb4Schristos 		   dns_name_t *name) {
1391e2b1b9c0Schristos 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1392e2b1b9c0Schristos 
1393e2b1b9c0Schristos 	attachnode(iterator->db, sdlziter->current, nodep);
13948b4c8a26Schristos 	if (name != NULL) {
13958b4c8a26Schristos 		dns_name_copynf(sdlziter->current->name, name);
13968b4c8a26Schristos 		return (ISC_R_SUCCESS);
13978b4c8a26Schristos 	}
1398e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
1399e2b1b9c0Schristos }
1400e2b1b9c0Schristos 
1401e2b1b9c0Schristos static isc_result_t
dbiterator_pause(dns_dbiterator_t * iterator)1402e2b1b9c0Schristos dbiterator_pause(dns_dbiterator_t *iterator) {
1403e2b1b9c0Schristos 	UNUSED(iterator);
1404e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
1405e2b1b9c0Schristos }
1406e2b1b9c0Schristos 
1407e2b1b9c0Schristos static isc_result_t
dbiterator_origin(dns_dbiterator_t * iterator,dns_name_t * name)1408e2b1b9c0Schristos dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1409e2b1b9c0Schristos 	UNUSED(iterator);
14108b4c8a26Schristos 	dns_name_copynf(dns_rootname, name);
14118b4c8a26Schristos 	return (ISC_R_SUCCESS);
1412e2b1b9c0Schristos }
1413e2b1b9c0Schristos 
1414e2b1b9c0Schristos /*
1415e2b1b9c0Schristos  * Rdataset Methods. These methods were "borrowed" from the SDB driver
1416e2b1b9c0Schristos  * interface.  See the SDB driver interface documentation for more info.
1417e2b1b9c0Schristos  */
1418e2b1b9c0Schristos 
1419e2b1b9c0Schristos static void
disassociate(dns_rdataset_t * rdataset)1420e2b1b9c0Schristos disassociate(dns_rdataset_t *rdataset) {
1421e2b1b9c0Schristos 	dns_dbnode_t *node = rdataset->private5;
1422e2b1b9c0Schristos 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
1423e2b1b9c0Schristos 	dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
1424e2b1b9c0Schristos 
1425e2b1b9c0Schristos 	detachnode(db, &node);
1426e2b1b9c0Schristos 	isc__rdatalist_disassociate(rdataset);
1427e2b1b9c0Schristos }
1428e2b1b9c0Schristos 
1429e2b1b9c0Schristos static void
rdataset_clone(dns_rdataset_t * source,dns_rdataset_t * target)1430e2b1b9c0Schristos rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1431e2b1b9c0Schristos 	dns_dbnode_t *node = source->private5;
1432e2b1b9c0Schristos 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
1433e2b1b9c0Schristos 	dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
1434e2b1b9c0Schristos 	dns_dbnode_t *tempdb = NULL;
1435e2b1b9c0Schristos 
1436e2b1b9c0Schristos 	isc__rdatalist_clone(source, target);
1437e2b1b9c0Schristos 	attachnode(db, node, &tempdb);
1438e2b1b9c0Schristos 	source->private5 = tempdb;
1439e2b1b9c0Schristos }
1440e2b1b9c0Schristos 
1441e2b1b9c0Schristos static dns_rdatasetmethods_t rdataset_methods = {
1442e2b1b9c0Schristos 	disassociate,
1443e2b1b9c0Schristos 	isc__rdatalist_first,
1444e2b1b9c0Schristos 	isc__rdatalist_next,
1445e2b1b9c0Schristos 	isc__rdatalist_current,
1446e2b1b9c0Schristos 	rdataset_clone,
1447e2b1b9c0Schristos 	isc__rdatalist_count,
1448e2b1b9c0Schristos 	isc__rdatalist_addnoqname,
1449e2b1b9c0Schristos 	isc__rdatalist_getnoqname,
1450e2b1b9c0Schristos 	NULL, /* addclosest */
1451e2b1b9c0Schristos 	NULL, /* getclosest */
1452e2b1b9c0Schristos 	NULL, /* settrust */
1453e2b1b9c0Schristos 	NULL, /* expire */
1454e2b1b9c0Schristos 	NULL, /* clearprefetch */
1455e2b1b9c0Schristos 	NULL, /* setownercase */
1456e2b1b9c0Schristos 	NULL, /* getownercase */
1457e2b1b9c0Schristos 	NULL  /* addglue */
1458e2b1b9c0Schristos };
1459e2b1b9c0Schristos 
1460e2b1b9c0Schristos static void
list_tordataset(dns_rdatalist_t * rdatalist,dns_db_t * db,dns_dbnode_t * node,dns_rdataset_t * rdataset)14619742fdb4Schristos list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
14629742fdb4Schristos 		dns_rdataset_t *rdataset) {
1463e2b1b9c0Schristos 	/*
1464e2b1b9c0Schristos 	 * The sdlz rdataset is an rdatalist with some additions.
1465e2b1b9c0Schristos 	 *	- private1 & private2 are used by the rdatalist.
1466e2b1b9c0Schristos 	 *	- private3 & private 4 are unused.
1467e2b1b9c0Schristos 	 *	- private5 is the node.
1468e2b1b9c0Schristos 	 */
1469e2b1b9c0Schristos 
1470e2b1b9c0Schristos 	/* This should never fail. */
1471e2b1b9c0Schristos 	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1472e2b1b9c0Schristos 		      ISC_R_SUCCESS);
1473e2b1b9c0Schristos 
1474e2b1b9c0Schristos 	rdataset->methods = &rdataset_methods;
1475e2b1b9c0Schristos 	dns_db_attachnode(db, node, &rdataset->private5);
1476e2b1b9c0Schristos }
1477e2b1b9c0Schristos 
1478e2b1b9c0Schristos /*
1479e2b1b9c0Schristos  * SDLZ core methods. This is the core of the new DLZ functionality.
1480e2b1b9c0Schristos  */
1481e2b1b9c0Schristos 
1482e2b1b9c0Schristos /*%
1483e2b1b9c0Schristos  * Build a 'bind' database driver structure to be returned by
1484e2b1b9c0Schristos  * either the find zone or the allow zone transfer method.
1485e2b1b9c0Schristos  * This method is only available in this source file, it is
1486e2b1b9c0Schristos  * not made available anywhere else.
1487e2b1b9c0Schristos  */
1488e2b1b9c0Schristos 
1489e2b1b9c0Schristos static isc_result_t
dns_sdlzcreateDBP(isc_mem_t * mctx,void * driverarg,void * dbdata,const dns_name_t * name,dns_rdataclass_t rdclass,dns_db_t ** dbp)1490e2b1b9c0Schristos dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
1491e2b1b9c0Schristos 		  const dns_name_t *name, dns_rdataclass_t rdclass,
14929742fdb4Schristos 		  dns_db_t **dbp) {
1493e2b1b9c0Schristos 	isc_result_t result;
1494e2b1b9c0Schristos 	dns_sdlz_db_t *sdlzdb;
1495e2b1b9c0Schristos 	dns_sdlzimplementation_t *imp;
1496e2b1b9c0Schristos 
1497e2b1b9c0Schristos 	/* check that things are as we expect */
1498e2b1b9c0Schristos 	REQUIRE(dbp != NULL && *dbp == NULL);
1499e2b1b9c0Schristos 	REQUIRE(name != NULL);
1500e2b1b9c0Schristos 
1501e2b1b9c0Schristos 	imp = (dns_sdlzimplementation_t *)driverarg;
1502e2b1b9c0Schristos 
1503e2b1b9c0Schristos 	/* allocate and zero memory for driver structure */
1504e2b1b9c0Schristos 	sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
1505e2b1b9c0Schristos 	memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
1506e2b1b9c0Schristos 
1507e2b1b9c0Schristos 	/* initialize and set origin */
1508e2b1b9c0Schristos 	dns_name_init(&sdlzdb->common.origin, NULL);
1509e2b1b9c0Schristos 	result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
15109742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
1511e2b1b9c0Schristos 		goto mem_cleanup;
15129742fdb4Schristos 	}
1513e2b1b9c0Schristos 
1514e2b1b9c0Schristos 	/* set the rest of the database structure attributes */
1515e2b1b9c0Schristos 	sdlzdb->dlzimp = imp;
1516e2b1b9c0Schristos 	sdlzdb->common.methods = &sdlzdb_methods;
1517e2b1b9c0Schristos 	sdlzdb->common.attributes = 0;
1518e2b1b9c0Schristos 	sdlzdb->common.rdclass = rdclass;
1519e2b1b9c0Schristos 	sdlzdb->common.mctx = NULL;
1520e2b1b9c0Schristos 	sdlzdb->dbdata = dbdata;
15219742fdb4Schristos 	isc_refcount_init(&sdlzdb->references, 1);
1522e2b1b9c0Schristos 
1523e2b1b9c0Schristos 	/* attach to the memory context */
1524e2b1b9c0Schristos 	isc_mem_attach(mctx, &sdlzdb->common.mctx);
1525e2b1b9c0Schristos 
1526e2b1b9c0Schristos 	/* mark structure as valid */
1527e2b1b9c0Schristos 	sdlzdb->common.magic = DNS_DB_MAGIC;
1528e2b1b9c0Schristos 	sdlzdb->common.impmagic = SDLZDB_MAGIC;
1529e2b1b9c0Schristos 	*dbp = (dns_db_t *)sdlzdb;
1530e2b1b9c0Schristos 
1531e2b1b9c0Schristos 	return (result);
1532e2b1b9c0Schristos mem_cleanup:
1533e2b1b9c0Schristos 	isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
1534e2b1b9c0Schristos 	return (result);
1535e2b1b9c0Schristos }
1536e2b1b9c0Schristos 
1537e2b1b9c0Schristos static isc_result_t
dns_sdlzallowzonexfr(void * driverarg,void * dbdata,isc_mem_t * mctx,dns_rdataclass_t rdclass,const dns_name_t * name,const isc_sockaddr_t * clientaddr,dns_db_t ** dbp)1538e2b1b9c0Schristos dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
1539e2b1b9c0Schristos 		     dns_rdataclass_t rdclass, const dns_name_t *name,
15409742fdb4Schristos 		     const isc_sockaddr_t *clientaddr, dns_db_t **dbp) {
1541e2b1b9c0Schristos 	isc_buffer_t b;
1542e2b1b9c0Schristos 	isc_buffer_t b2;
1543e2b1b9c0Schristos 	char namestr[DNS_NAME_MAXTEXT + 1];
15449742fdb4Schristos 	char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255."
15459742fdb4Schristos 			       "255") +
15469742fdb4Schristos 		       1];
1547e2b1b9c0Schristos 	isc_netaddr_t netaddr;
1548e2b1b9c0Schristos 	isc_result_t result;
1549e2b1b9c0Schristos 	dns_sdlzimplementation_t *imp;
1550e2b1b9c0Schristos 
1551e2b1b9c0Schristos 	/*
1552e2b1b9c0Schristos 	 * Perform checks to make sure data is as we expect it to be.
1553e2b1b9c0Schristos 	 */
1554e2b1b9c0Schristos 	REQUIRE(driverarg != NULL);
1555e2b1b9c0Schristos 	REQUIRE(name != NULL);
1556e2b1b9c0Schristos 	REQUIRE(clientaddr != NULL);
1557e2b1b9c0Schristos 	REQUIRE(dbp != NULL && *dbp == NULL);
1558e2b1b9c0Schristos 
1559e2b1b9c0Schristos 	imp = (dns_sdlzimplementation_t *)driverarg;
1560e2b1b9c0Schristos 
1561e2b1b9c0Schristos 	/* Convert DNS name to ascii text */
1562e2b1b9c0Schristos 	isc_buffer_init(&b, namestr, sizeof(namestr));
1563f2e20987Schristos 	result = dns_name_totext(name, true, &b);
15649742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
1565e2b1b9c0Schristos 		return (result);
15669742fdb4Schristos 	}
1567e2b1b9c0Schristos 	isc_buffer_putuint8(&b, 0);
1568e2b1b9c0Schristos 
1569e2b1b9c0Schristos 	/* convert client address to ascii text */
1570e2b1b9c0Schristos 	isc_buffer_init(&b2, clientstr, sizeof(clientstr));
1571e2b1b9c0Schristos 	isc_netaddr_fromsockaddr(&netaddr, clientaddr);
1572e2b1b9c0Schristos 	result = isc_netaddr_totext(&netaddr, &b2);
15739742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
1574e2b1b9c0Schristos 		return (result);
15759742fdb4Schristos 	}
1576e2b1b9c0Schristos 	isc_buffer_putuint8(&b2, 0);
1577e2b1b9c0Schristos 
1578e2b1b9c0Schristos 	/* make sure strings are always lowercase */
1579e2b1b9c0Schristos 	dns_sdlz_tolower(namestr);
1580e2b1b9c0Schristos 	dns_sdlz_tolower(clientstr);
1581e2b1b9c0Schristos 
1582e2b1b9c0Schristos 	/* Call SDLZ driver's find zone method */
1583e2b1b9c0Schristos 	if (imp->methods->allowzonexfr != NULL) {
15849742fdb4Schristos 		isc_result_t rresult = ISC_R_SUCCESS;
15859742fdb4Schristos 
1586e2b1b9c0Schristos 		MAYBE_LOCK(imp);
1587e2b1b9c0Schristos 		result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
1588e2b1b9c0Schristos 						    namestr, clientstr);
1589e2b1b9c0Schristos 		MAYBE_UNLOCK(imp);
1590e2b1b9c0Schristos 		/*
15919742fdb4Schristos 		 * if zone is supported and transfers are (or might be)
15929742fdb4Schristos 		 * allowed, build a 'bind' database driver
1593e2b1b9c0Schristos 		 */
15949742fdb4Schristos 		if (result == ISC_R_SUCCESS || result == ISC_R_DEFAULT) {
15959742fdb4Schristos 			rresult = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
1596e2b1b9c0Schristos 						    name, rdclass, dbp);
15979742fdb4Schristos 		}
15989742fdb4Schristos 		if (rresult != ISC_R_SUCCESS) {
15999742fdb4Schristos 			result = rresult;
16009742fdb4Schristos 		}
1601e2b1b9c0Schristos 		return (result);
1602e2b1b9c0Schristos 	}
1603e2b1b9c0Schristos 
1604e2b1b9c0Schristos 	return (ISC_R_NOTIMPLEMENTED);
1605e2b1b9c0Schristos }
1606e2b1b9c0Schristos 
1607e2b1b9c0Schristos static isc_result_t
dns_sdlzcreate(isc_mem_t * mctx,const char * dlzname,unsigned int argc,char * argv[],void * driverarg,void ** dbdata)1608e2b1b9c0Schristos dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
16099742fdb4Schristos 	       char *argv[], void *driverarg, void **dbdata) {
1610e2b1b9c0Schristos 	dns_sdlzimplementation_t *imp;
1611e2b1b9c0Schristos 	isc_result_t result = ISC_R_NOTFOUND;
1612e2b1b9c0Schristos 
1613e2b1b9c0Schristos 	/* Write debugging message to log */
1614e2b1b9c0Schristos 	sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
1615e2b1b9c0Schristos 
1616e2b1b9c0Schristos 	/*
1617e2b1b9c0Schristos 	 * Performs checks to make sure data is as we expect it to be.
1618e2b1b9c0Schristos 	 */
1619e2b1b9c0Schristos 	REQUIRE(driverarg != NULL);
1620e2b1b9c0Schristos 	REQUIRE(dlzname != NULL);
1621e2b1b9c0Schristos 	REQUIRE(dbdata != NULL);
1622e2b1b9c0Schristos 	UNUSED(mctx);
1623e2b1b9c0Schristos 
1624e2b1b9c0Schristos 	imp = driverarg;
1625e2b1b9c0Schristos 
1626e2b1b9c0Schristos 	/* If the create method exists, call it. */
1627e2b1b9c0Schristos 	if (imp->methods->create != NULL) {
1628e2b1b9c0Schristos 		MAYBE_LOCK(imp);
1629e2b1b9c0Schristos 		result = imp->methods->create(dlzname, argc, argv,
1630e2b1b9c0Schristos 					      imp->driverarg, dbdata);
1631e2b1b9c0Schristos 		MAYBE_UNLOCK(imp);
1632e2b1b9c0Schristos 	}
1633e2b1b9c0Schristos 
1634e2b1b9c0Schristos 	/* Write debugging message to log */
1635e2b1b9c0Schristos 	if (result == ISC_R_SUCCESS) {
1636e2b1b9c0Schristos 		sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
1637e2b1b9c0Schristos 	} else {
1638e2b1b9c0Schristos 		sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
1639e2b1b9c0Schristos 	}
1640e2b1b9c0Schristos 
1641e2b1b9c0Schristos 	return (result);
1642e2b1b9c0Schristos }
1643e2b1b9c0Schristos 
1644e2b1b9c0Schristos static void
dns_sdlzdestroy(void * driverdata,void ** dbdata)1645e2b1b9c0Schristos dns_sdlzdestroy(void *driverdata, void **dbdata) {
1646e2b1b9c0Schristos 	dns_sdlzimplementation_t *imp;
1647e2b1b9c0Schristos 
1648e2b1b9c0Schristos 	/* Write debugging message to log */
1649e2b1b9c0Schristos 	sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
1650e2b1b9c0Schristos 
1651e2b1b9c0Schristos 	imp = driverdata;
1652e2b1b9c0Schristos 
1653e2b1b9c0Schristos 	/* If the destroy method exists, call it. */
1654e2b1b9c0Schristos 	if (imp->methods->destroy != NULL) {
1655e2b1b9c0Schristos 		MAYBE_LOCK(imp);
1656e2b1b9c0Schristos 		imp->methods->destroy(imp->driverarg, dbdata);
1657e2b1b9c0Schristos 		MAYBE_UNLOCK(imp);
1658e2b1b9c0Schristos 	}
1659e2b1b9c0Schristos }
1660e2b1b9c0Schristos 
1661e2b1b9c0Schristos static isc_result_t
dns_sdlzfindzone(void * driverarg,void * dbdata,isc_mem_t * mctx,dns_rdataclass_t rdclass,const dns_name_t * name,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo,dns_db_t ** dbp)1662e2b1b9c0Schristos dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
1663e2b1b9c0Schristos 		 dns_rdataclass_t rdclass, const dns_name_t *name,
16649742fdb4Schristos 		 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
16659742fdb4Schristos 		 dns_db_t **dbp) {
1666e2b1b9c0Schristos 	isc_buffer_t b;
1667e2b1b9c0Schristos 	char namestr[DNS_NAME_MAXTEXT + 1];
1668e2b1b9c0Schristos 	isc_result_t result;
1669e2b1b9c0Schristos 	dns_sdlzimplementation_t *imp;
1670e2b1b9c0Schristos 
1671e2b1b9c0Schristos 	/*
1672e2b1b9c0Schristos 	 * Perform checks to make sure data is as we expect it to be.
1673e2b1b9c0Schristos 	 */
1674e2b1b9c0Schristos 	REQUIRE(driverarg != NULL);
1675e2b1b9c0Schristos 	REQUIRE(name != NULL);
1676e2b1b9c0Schristos 	REQUIRE(dbp != NULL && *dbp == NULL);
1677e2b1b9c0Schristos 
1678e2b1b9c0Schristos 	imp = (dns_sdlzimplementation_t *)driverarg;
1679e2b1b9c0Schristos 
1680e2b1b9c0Schristos 	/* Convert DNS name to ascii text */
1681e2b1b9c0Schristos 	isc_buffer_init(&b, namestr, sizeof(namestr));
1682f2e20987Schristos 	result = dns_name_totext(name, true, &b);
16839742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
1684e2b1b9c0Schristos 		return (result);
16859742fdb4Schristos 	}
1686e2b1b9c0Schristos 	isc_buffer_putuint8(&b, 0);
1687e2b1b9c0Schristos 
1688e2b1b9c0Schristos 	/* make sure strings are always lowercase */
1689e2b1b9c0Schristos 	dns_sdlz_tolower(namestr);
1690e2b1b9c0Schristos 
1691e2b1b9c0Schristos 	/* Call SDLZ driver's find zone method */
1692e2b1b9c0Schristos 	MAYBE_LOCK(imp);
1693e2b1b9c0Schristos 	result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
1694e2b1b9c0Schristos 					methods, clientinfo);
1695e2b1b9c0Schristos 	MAYBE_UNLOCK(imp);
1696e2b1b9c0Schristos 
1697e2b1b9c0Schristos 	/*
1698e2b1b9c0Schristos 	 * if zone is supported build a 'bind' database driver
1699e2b1b9c0Schristos 	 * structure to return
1700e2b1b9c0Schristos 	 */
17019742fdb4Schristos 	if (result == ISC_R_SUCCESS) {
1702e2b1b9c0Schristos 		result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
1703e2b1b9c0Schristos 					   rdclass, dbp);
17049742fdb4Schristos 	}
1705e2b1b9c0Schristos 
1706e2b1b9c0Schristos 	return (result);
1707e2b1b9c0Schristos }
1708e2b1b9c0Schristos 
1709e2b1b9c0Schristos static isc_result_t
dns_sdlzconfigure(void * driverarg,void * dbdata,dns_view_t * view,dns_dlzdb_t * dlzdb)17109742fdb4Schristos dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view,
17119742fdb4Schristos 		  dns_dlzdb_t *dlzdb) {
1712e2b1b9c0Schristos 	isc_result_t result;
1713e2b1b9c0Schristos 	dns_sdlzimplementation_t *imp;
1714e2b1b9c0Schristos 
1715e2b1b9c0Schristos 	REQUIRE(driverarg != NULL);
1716e2b1b9c0Schristos 
1717e2b1b9c0Schristos 	imp = (dns_sdlzimplementation_t *)driverarg;
1718e2b1b9c0Schristos 
1719e2b1b9c0Schristos 	/* Call SDLZ driver's configure method */
1720e2b1b9c0Schristos 	if (imp->methods->configure != NULL) {
1721e2b1b9c0Schristos 		MAYBE_LOCK(imp);
17229742fdb4Schristos 		result = imp->methods->configure(view, dlzdb, imp->driverarg,
17239742fdb4Schristos 						 dbdata);
1724e2b1b9c0Schristos 		MAYBE_UNLOCK(imp);
1725e2b1b9c0Schristos 	} else {
1726e2b1b9c0Schristos 		result = ISC_R_SUCCESS;
1727e2b1b9c0Schristos 	}
1728e2b1b9c0Schristos 
1729e2b1b9c0Schristos 	return (result);
1730e2b1b9c0Schristos }
1731e2b1b9c0Schristos 
1732f2e20987Schristos static bool
dns_sdlzssumatch(const dns_name_t * signer,const dns_name_t * name,const isc_netaddr_t * tcpaddr,dns_rdatatype_t type,const dst_key_t * key,void * driverarg,void * dbdata)1733e2b1b9c0Schristos dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name,
1734e2b1b9c0Schristos 		 const isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
17359742fdb4Schristos 		 const dst_key_t *key, void *driverarg, void *dbdata) {
1736e2b1b9c0Schristos 	dns_sdlzimplementation_t *imp;
1737e2b1b9c0Schristos 	char b_signer[DNS_NAME_FORMATSIZE];
1738e2b1b9c0Schristos 	char b_name[DNS_NAME_FORMATSIZE];
1739e2b1b9c0Schristos 	char b_addr[ISC_NETADDR_FORMATSIZE];
1740e2b1b9c0Schristos 	char b_type[DNS_RDATATYPE_FORMATSIZE];
1741e2b1b9c0Schristos 	char b_key[DST_KEY_FORMATSIZE];
1742e2b1b9c0Schristos 	isc_buffer_t *tkey_token = NULL;
1743e2b1b9c0Schristos 	isc_region_t token_region = { NULL, 0 };
1744f2e20987Schristos 	uint32_t token_len = 0;
1745f2e20987Schristos 	bool ret;
1746e2b1b9c0Schristos 
1747e2b1b9c0Schristos 	REQUIRE(driverarg != NULL);
1748e2b1b9c0Schristos 
1749e2b1b9c0Schristos 	imp = (dns_sdlzimplementation_t *)driverarg;
17509742fdb4Schristos 	if (imp->methods->ssumatch == NULL) {
1751f2e20987Schristos 		return (false);
17529742fdb4Schristos 	}
1753e2b1b9c0Schristos 
1754e2b1b9c0Schristos 	/*
1755e2b1b9c0Schristos 	 * Format the request elements. sdlz operates on strings, not
1756e2b1b9c0Schristos 	 * structures
1757e2b1b9c0Schristos 	 */
17589742fdb4Schristos 	if (signer != NULL) {
1759e2b1b9c0Schristos 		dns_name_format(signer, b_signer, sizeof(b_signer));
17609742fdb4Schristos 	} else {
1761e2b1b9c0Schristos 		b_signer[0] = 0;
17629742fdb4Schristos 	}
1763e2b1b9c0Schristos 
1764e2b1b9c0Schristos 	dns_name_format(name, b_name, sizeof(b_name));
1765e2b1b9c0Schristos 
17669742fdb4Schristos 	if (tcpaddr != NULL) {
1767e2b1b9c0Schristos 		isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
17689742fdb4Schristos 	} else {
1769e2b1b9c0Schristos 		b_addr[0] = 0;
17709742fdb4Schristos 	}
1771e2b1b9c0Schristos 
1772e2b1b9c0Schristos 	dns_rdatatype_format(type, b_type, sizeof(b_type));
1773e2b1b9c0Schristos 
1774e2b1b9c0Schristos 	if (key != NULL) {
1775e2b1b9c0Schristos 		dst_key_format(key, b_key, sizeof(b_key));
1776e2b1b9c0Schristos 		tkey_token = dst_key_tkeytoken(key);
17779742fdb4Schristos 	} else {
1778e2b1b9c0Schristos 		b_key[0] = 0;
17799742fdb4Schristos 	}
1780e2b1b9c0Schristos 
1781e2b1b9c0Schristos 	if (tkey_token != NULL) {
1782e2b1b9c0Schristos 		isc_buffer_region(tkey_token, &token_region);
1783e2b1b9c0Schristos 		token_len = token_region.length;
1784e2b1b9c0Schristos 	}
1785e2b1b9c0Schristos 
1786e2b1b9c0Schristos 	MAYBE_LOCK(imp);
1787e2b1b9c0Schristos 	ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
1788e2b1b9c0Schristos 				     token_len,
1789e2b1b9c0Schristos 				     token_len != 0 ? token_region.base : NULL,
1790e2b1b9c0Schristos 				     imp->driverarg, dbdata);
1791e2b1b9c0Schristos 	MAYBE_UNLOCK(imp);
1792e2b1b9c0Schristos 	return (ret);
1793e2b1b9c0Schristos }
1794e2b1b9c0Schristos 
17959742fdb4Schristos static dns_dlzmethods_t sdlzmethods = { dns_sdlzcreate,	   dns_sdlzdestroy,
17969742fdb4Schristos 					dns_sdlzfindzone,  dns_sdlzallowzonexfr,
17979742fdb4Schristos 					dns_sdlzconfigure, dns_sdlzssumatch };
1798e2b1b9c0Schristos 
1799e2b1b9c0Schristos /*
1800e2b1b9c0Schristos  * Public functions.
1801e2b1b9c0Schristos  */
1802e2b1b9c0Schristos 
1803e2b1b9c0Schristos isc_result_t
dns_sdlz_putrr(dns_sdlzlookup_t * lookup,const char * type,dns_ttl_t ttl,const char * data)1804e2b1b9c0Schristos dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
18059742fdb4Schristos 	       const char *data) {
1806e2b1b9c0Schristos 	dns_rdatalist_t *rdatalist;
1807e2b1b9c0Schristos 	dns_rdata_t *rdata;
1808e2b1b9c0Schristos 	dns_rdatatype_t typeval;
1809e2b1b9c0Schristos 	isc_consttextregion_t r;
1810e2b1b9c0Schristos 	isc_buffer_t b;
1811e2b1b9c0Schristos 	isc_buffer_t *rdatabuf = NULL;
1812e2b1b9c0Schristos 	isc_lex_t *lex;
1813e2b1b9c0Schristos 	isc_result_t result;
1814e2b1b9c0Schristos 	unsigned int size;
1815e2b1b9c0Schristos 	isc_mem_t *mctx;
1816e2b1b9c0Schristos 	const dns_name_t *origin;
1817e2b1b9c0Schristos 
1818e2b1b9c0Schristos 	REQUIRE(VALID_SDLZLOOKUP(lookup));
1819e2b1b9c0Schristos 	REQUIRE(type != NULL);
1820e2b1b9c0Schristos 	REQUIRE(data != NULL);
1821e2b1b9c0Schristos 
1822e2b1b9c0Schristos 	mctx = lookup->sdlz->common.mctx;
1823e2b1b9c0Schristos 
1824e2b1b9c0Schristos 	r.base = type;
1825e2b1b9c0Schristos 	r.length = strlen(type);
1826e2b1b9c0Schristos 	result = dns_rdatatype_fromtext(&typeval, (void *)&r);
18279742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
1828e2b1b9c0Schristos 		return (result);
18299742fdb4Schristos 	}
1830e2b1b9c0Schristos 
1831e2b1b9c0Schristos 	rdatalist = ISC_LIST_HEAD(lookup->lists);
1832e2b1b9c0Schristos 	while (rdatalist != NULL) {
18339742fdb4Schristos 		if (rdatalist->type == typeval) {
1834e2b1b9c0Schristos 			break;
18359742fdb4Schristos 		}
1836e2b1b9c0Schristos 		rdatalist = ISC_LIST_NEXT(rdatalist, link);
1837e2b1b9c0Schristos 	}
1838e2b1b9c0Schristos 
1839e2b1b9c0Schristos 	if (rdatalist == NULL) {
1840e2b1b9c0Schristos 		rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
1841e2b1b9c0Schristos 		dns_rdatalist_init(rdatalist);
1842e2b1b9c0Schristos 		rdatalist->rdclass = lookup->sdlz->common.rdclass;
1843e2b1b9c0Schristos 		rdatalist->type = typeval;
1844e2b1b9c0Schristos 		rdatalist->ttl = ttl;
1845e2b1b9c0Schristos 		ISC_LIST_APPEND(lookup->lists, rdatalist, link);
18469742fdb4Schristos 	} else if (rdatalist->ttl > ttl) {
1847e2b1b9c0Schristos 		/*
1848e2b1b9c0Schristos 		 * BIND9 doesn't enforce all RRs in an RRset
1849e2b1b9c0Schristos 		 * having the same TTL, as per RFC 2136,
1850e2b1b9c0Schristos 		 * section 7.12. If a DLZ backend has
1851e2b1b9c0Schristos 		 * different TTLs, then the best
1852e2b1b9c0Schristos 		 * we can do is return the lowest.
1853e2b1b9c0Schristos 		 */
1854e2b1b9c0Schristos 		rdatalist->ttl = ttl;
1855e2b1b9c0Schristos 	}
1856e2b1b9c0Schristos 
1857e2b1b9c0Schristos 	rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
1858e2b1b9c0Schristos 	dns_rdata_init(rdata);
1859e2b1b9c0Schristos 
18609742fdb4Schristos 	if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
1861e2b1b9c0Schristos 		origin = &lookup->sdlz->common.origin;
18629742fdb4Schristos 	} else {
1863e2b1b9c0Schristos 		origin = dns_rootname;
18649742fdb4Schristos 	}
1865e2b1b9c0Schristos 
1866e2b1b9c0Schristos 	lex = NULL;
1867e2b1b9c0Schristos 	result = isc_lex_create(mctx, 64, &lex);
18689742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
1869e2b1b9c0Schristos 		goto failure;
18709742fdb4Schristos 	}
1871e2b1b9c0Schristos 
1872e2b1b9c0Schristos 	size = initial_size(data);
1873e2b1b9c0Schristos 	do {
1874e2b1b9c0Schristos 		isc_buffer_constinit(&b, data, strlen(data));
1875e2b1b9c0Schristos 		isc_buffer_add(&b, strlen(data));
1876e2b1b9c0Schristos 
1877e2b1b9c0Schristos 		result = isc_lex_openbuffer(lex, &b);
18789742fdb4Schristos 		if (result != ISC_R_SUCCESS) {
1879e2b1b9c0Schristos 			goto failure;
18809742fdb4Schristos 		}
1881e2b1b9c0Schristos 
1882e2b1b9c0Schristos 		rdatabuf = NULL;
18839742fdb4Schristos 		isc_buffer_allocate(mctx, &rdatabuf, size);
1884e2b1b9c0Schristos 
1885e2b1b9c0Schristos 		result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
18869742fdb4Schristos 					    rdatalist->type, lex, origin, false,
18879742fdb4Schristos 					    mctx, rdatabuf, &lookup->callbacks);
1888f2e20987Schristos 		if (result != ISC_R_SUCCESS) {
1889e2b1b9c0Schristos 			isc_buffer_free(&rdatabuf);
1890f2e20987Schristos 		}
18919742fdb4Schristos 		if (size >= 65535) {
1892e2b1b9c0Schristos 			break;
18939742fdb4Schristos 		}
1894e2b1b9c0Schristos 		size *= 2;
18959742fdb4Schristos 		if (size >= 65535) {
1896e2b1b9c0Schristos 			size = 65535;
18979742fdb4Schristos 		}
1898e2b1b9c0Schristos 	} while (result == ISC_R_NOSPACE);
1899e2b1b9c0Schristos 
19009742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
1901c0b5d9fbSchristos 		result = DNS_R_SERVFAIL;
1902e2b1b9c0Schristos 		goto failure;
19039742fdb4Schristos 	}
1904e2b1b9c0Schristos 
1905e2b1b9c0Schristos 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1906e2b1b9c0Schristos 	ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
1907e2b1b9c0Schristos 
19089742fdb4Schristos 	if (lex != NULL) {
1909e2b1b9c0Schristos 		isc_lex_destroy(&lex);
19109742fdb4Schristos 	}
1911e2b1b9c0Schristos 
1912e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
1913e2b1b9c0Schristos 
1914e2b1b9c0Schristos failure:
19159742fdb4Schristos 	if (rdatabuf != NULL) {
1916e2b1b9c0Schristos 		isc_buffer_free(&rdatabuf);
19179742fdb4Schristos 	}
19189742fdb4Schristos 	if (lex != NULL) {
1919e2b1b9c0Schristos 		isc_lex_destroy(&lex);
19209742fdb4Schristos 	}
1921e2b1b9c0Schristos 	isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
1922e2b1b9c0Schristos 
1923e2b1b9c0Schristos 	return (result);
1924e2b1b9c0Schristos }
1925e2b1b9c0Schristos 
1926e2b1b9c0Schristos isc_result_t
dns_sdlz_putnamedrr(dns_sdlzallnodes_t * allnodes,const char * name,const char * type,dns_ttl_t ttl,const char * data)1927e2b1b9c0Schristos dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
19289742fdb4Schristos 		    const char *type, dns_ttl_t ttl, const char *data) {
1929e2b1b9c0Schristos 	dns_name_t *newname;
1930e2b1b9c0Schristos 	const dns_name_t *origin;
1931e2b1b9c0Schristos 	dns_fixedname_t fnewname;
1932e2b1b9c0Schristos 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
1933e2b1b9c0Schristos 	dns_sdlznode_t *sdlznode;
1934e2b1b9c0Schristos 	isc_mem_t *mctx = sdlz->common.mctx;
1935e2b1b9c0Schristos 	isc_buffer_t b;
1936e2b1b9c0Schristos 	isc_result_t result;
1937e2b1b9c0Schristos 
1938e2b1b9c0Schristos 	newname = dns_fixedname_initname(&fnewname);
1939e2b1b9c0Schristos 
19409742fdb4Schristos 	if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
1941e2b1b9c0Schristos 		origin = &sdlz->common.origin;
19429742fdb4Schristos 	} else {
1943e2b1b9c0Schristos 		origin = dns_rootname;
19449742fdb4Schristos 	}
1945e2b1b9c0Schristos 	isc_buffer_constinit(&b, name, strlen(name));
1946e2b1b9c0Schristos 	isc_buffer_add(&b, strlen(name));
1947e2b1b9c0Schristos 
1948e2b1b9c0Schristos 	result = dns_name_fromtext(newname, &b, origin, 0, NULL);
19499742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
1950e2b1b9c0Schristos 		return (result);
19519742fdb4Schristos 	}
1952e2b1b9c0Schristos 
1953e2b1b9c0Schristos 	if (allnodes->common.relative_names) {
1954e2b1b9c0Schristos 		/* All names are relative to the root */
1955e2b1b9c0Schristos 		unsigned int nlabels = dns_name_countlabels(newname);
1956e2b1b9c0Schristos 		dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
1957e2b1b9c0Schristos 	}
1958e2b1b9c0Schristos 
1959e2b1b9c0Schristos 	sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
1960e2b1b9c0Schristos 	if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
1961e2b1b9c0Schristos 		sdlznode = NULL;
1962e2b1b9c0Schristos 		result = createnode(sdlz, &sdlznode);
1963e2b1b9c0Schristos 		if (result != ISC_R_SUCCESS) {
1964e2b1b9c0Schristos 			return (result);
1965e2b1b9c0Schristos 		}
19669742fdb4Schristos 		sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
19679742fdb4Schristos 		dns_name_init(sdlznode->name, NULL);
19689742fdb4Schristos 		dns_name_dup(newname, mctx, sdlznode->name);
1969e2b1b9c0Schristos 		ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
1970e2b1b9c0Schristos 		if (allnodes->origin == NULL &&
1971*4ac1c27eSchristos 		    dns_name_equal(newname, &sdlz->common.origin))
1972*4ac1c27eSchristos 		{
1973e2b1b9c0Schristos 			allnodes->origin = sdlznode;
1974e2b1b9c0Schristos 		}
19759742fdb4Schristos 	}
1976e2b1b9c0Schristos 	return (dns_sdlz_putrr(sdlznode, type, ttl, data));
1977e2b1b9c0Schristos }
1978e2b1b9c0Schristos 
1979e2b1b9c0Schristos isc_result_t
dns_sdlz_putsoa(dns_sdlzlookup_t * lookup,const char * mname,const char * rname,uint32_t serial)1980e2b1b9c0Schristos dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
19819742fdb4Schristos 		uint32_t serial) {
1982e2b1b9c0Schristos 	char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
1983e2b1b9c0Schristos 	int n;
1984e2b1b9c0Schristos 
1985e2b1b9c0Schristos 	REQUIRE(mname != NULL);
1986e2b1b9c0Schristos 	REQUIRE(rname != NULL);
1987e2b1b9c0Schristos 
19889742fdb4Schristos 	n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", mname, rname,
19899742fdb4Schristos 		     serial, SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
1990e2b1b9c0Schristos 		     SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
19919742fdb4Schristos 	if (n >= (int)sizeof(str) || n < 0) {
1992e2b1b9c0Schristos 		return (ISC_R_NOSPACE);
19939742fdb4Schristos 	}
1994e2b1b9c0Schristos 	return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
1995e2b1b9c0Schristos }
1996e2b1b9c0Schristos 
1997e2b1b9c0Schristos isc_result_t
dns_sdlzregister(const char * drivername,const dns_sdlzmethods_t * methods,void * driverarg,unsigned int flags,isc_mem_t * mctx,dns_sdlzimplementation_t ** sdlzimp)1998e2b1b9c0Schristos dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
1999e2b1b9c0Schristos 		 void *driverarg, unsigned int flags, isc_mem_t *mctx,
20009742fdb4Schristos 		 dns_sdlzimplementation_t **sdlzimp) {
2001e2b1b9c0Schristos 	dns_sdlzimplementation_t *imp;
2002e2b1b9c0Schristos 	isc_result_t result;
2003e2b1b9c0Schristos 
2004e2b1b9c0Schristos 	/*
2005e2b1b9c0Schristos 	 * Performs checks to make sure data is as we expect it to be.
2006e2b1b9c0Schristos 	 */
2007e2b1b9c0Schristos 	REQUIRE(drivername != NULL);
2008e2b1b9c0Schristos 	REQUIRE(methods != NULL);
2009e2b1b9c0Schristos 	REQUIRE(methods->findzone != NULL);
2010e2b1b9c0Schristos 	REQUIRE(methods->lookup != NULL);
2011e2b1b9c0Schristos 	REQUIRE(mctx != NULL);
2012e2b1b9c0Schristos 	REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
20139742fdb4Schristos 	REQUIRE((flags &
20149742fdb4Schristos 		 ~(DNS_SDLZFLAG_RELATIVEOWNER | DNS_SDLZFLAG_RELATIVERDATA |
2015e2b1b9c0Schristos 		   DNS_SDLZFLAG_THREADSAFE)) == 0);
2016e2b1b9c0Schristos 
2017e2b1b9c0Schristos 	/* Write debugging message to log */
2018e2b1b9c0Schristos 	sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
2019e2b1b9c0Schristos 
2020e2b1b9c0Schristos 	/*
2021e2b1b9c0Schristos 	 * Allocate memory for a sdlz_implementation object.  Error if
2022e2b1b9c0Schristos 	 * we cannot.
2023e2b1b9c0Schristos 	 */
2024e2b1b9c0Schristos 	imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
2025e2b1b9c0Schristos 
2026e2b1b9c0Schristos 	/* Make sure memory region is set to all 0's */
2027e2b1b9c0Schristos 	memset(imp, 0, sizeof(dns_sdlzimplementation_t));
2028e2b1b9c0Schristos 
2029e2b1b9c0Schristos 	/* Store the data passed into this method */
2030e2b1b9c0Schristos 	imp->methods = methods;
2031e2b1b9c0Schristos 	imp->driverarg = driverarg;
2032e2b1b9c0Schristos 	imp->flags = flags;
2033e2b1b9c0Schristos 	imp->mctx = NULL;
2034e2b1b9c0Schristos 
2035e2b1b9c0Schristos 	/* attach the new sdlz_implementation object to a memory context */
2036e2b1b9c0Schristos 	isc_mem_attach(mctx, &imp->mctx);
2037e2b1b9c0Schristos 
2038e2b1b9c0Schristos 	/*
2039e2b1b9c0Schristos 	 * initialize the driver lock, error if we cannot
2040e2b1b9c0Schristos 	 * (used if a driver does not support multiple threads)
2041e2b1b9c0Schristos 	 */
2042f2e20987Schristos 	isc_mutex_init(&imp->driverlock);
2043e2b1b9c0Schristos 
2044e2b1b9c0Schristos 	imp->dlz_imp = NULL;
2045e2b1b9c0Schristos 
2046e2b1b9c0Schristos 	/*
2047e2b1b9c0Schristos 	 * register the DLZ driver.  Pass in our "extra" sdlz information as
2048e2b1b9c0Schristos 	 * a driverarg.  (that's why we stored the passed in driver arg in our
2049e2b1b9c0Schristos 	 * sdlz_implementation structure)  Also, store the dlz_implementation
2050e2b1b9c0Schristos 	 * structure in our sdlz_implementation.
2051e2b1b9c0Schristos 	 */
2052e2b1b9c0Schristos 	result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
2053e2b1b9c0Schristos 				 &imp->dlz_imp);
2054e2b1b9c0Schristos 
2055e2b1b9c0Schristos 	/* if registration fails, cleanup and get outta here. */
20569742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
2057e2b1b9c0Schristos 		goto cleanup_mutex;
20589742fdb4Schristos 	}
2059e2b1b9c0Schristos 
2060e2b1b9c0Schristos 	*sdlzimp = imp;
2061e2b1b9c0Schristos 
2062e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
2063e2b1b9c0Schristos 
2064e2b1b9c0Schristos cleanup_mutex:
2065e2b1b9c0Schristos 	/* destroy the driver lock, we don't need it anymore */
2066f2e20987Schristos 	isc_mutex_destroy(&imp->driverlock);
2067e2b1b9c0Schristos 
2068e2b1b9c0Schristos 	/*
2069e2b1b9c0Schristos 	 * return the memory back to the available memory pool and
2070e2b1b9c0Schristos 	 * remove it from the memory context.
2071e2b1b9c0Schristos 	 */
20729742fdb4Schristos 	isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
2073e2b1b9c0Schristos 	return (result);
2074e2b1b9c0Schristos }
2075e2b1b9c0Schristos 
2076e2b1b9c0Schristos void
dns_sdlzunregister(dns_sdlzimplementation_t ** sdlzimp)2077e2b1b9c0Schristos dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
2078e2b1b9c0Schristos 	dns_sdlzimplementation_t *imp;
2079e2b1b9c0Schristos 
2080e2b1b9c0Schristos 	/* Write debugging message to log */
2081e2b1b9c0Schristos 	sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
2082e2b1b9c0Schristos 
2083e2b1b9c0Schristos 	/*
2084e2b1b9c0Schristos 	 * Performs checks to make sure data is as we expect it to be.
2085e2b1b9c0Schristos 	 */
2086e2b1b9c0Schristos 	REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
2087e2b1b9c0Schristos 
2088e2b1b9c0Schristos 	imp = *sdlzimp;
20899742fdb4Schristos 	*sdlzimp = NULL;
2090e2b1b9c0Schristos 
2091e2b1b9c0Schristos 	/* Unregister the DLZ driver implementation */
2092e2b1b9c0Schristos 	dns_dlzunregister(&imp->dlz_imp);
2093e2b1b9c0Schristos 
2094e2b1b9c0Schristos 	/* destroy the driver lock, we don't need it anymore */
2095f2e20987Schristos 	isc_mutex_destroy(&imp->driverlock);
2096e2b1b9c0Schristos 
2097e2b1b9c0Schristos 	/*
2098e2b1b9c0Schristos 	 * return the memory back to the available memory pool and
2099e2b1b9c0Schristos 	 * remove it from the memory context.
2100e2b1b9c0Schristos 	 */
21019742fdb4Schristos 	isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
2102e2b1b9c0Schristos }
2103e2b1b9c0Schristos 
2104e2b1b9c0Schristos isc_result_t
dns_sdlz_setdb(dns_dlzdb_t * dlzdatabase,dns_rdataclass_t rdclass,const dns_name_t * name,dns_db_t ** dbp)2105e2b1b9c0Schristos dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
21069742fdb4Schristos 	       const dns_name_t *name, dns_db_t **dbp) {
2107e2b1b9c0Schristos 	isc_result_t result;
2108e2b1b9c0Schristos 
2109e2b1b9c0Schristos 	result = dns_sdlzcreateDBP(dlzdatabase->mctx,
2110e2b1b9c0Schristos 				   dlzdatabase->implementation->driverarg,
2111e2b1b9c0Schristos 				   dlzdatabase->dbdata, name, rdclass, dbp);
2112e2b1b9c0Schristos 	return (result);
2113e2b1b9c0Schristos }
2114