sdb.c revision 236374
1135446Strhodes/*
2234010Sdougb * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
3135446Strhodes * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
4135446Strhodes *
5174187Sdougb * Permission to use, copy, modify, and/or distribute this software for any
6135446Strhodes * purpose with or without fee is hereby granted, provided that the above
7135446Strhodes * copyright notice and this permission notice appear in all copies.
8135446Strhodes *
9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11135446Strhodes * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15135446Strhodes * PERFORMANCE OF THIS SOFTWARE.
16135446Strhodes */
17135446Strhodes
18234010Sdougb/* $Id$ */
19135446Strhodes
20170222Sdougb/*! \file */
21170222Sdougb
22135446Strhodes#include <config.h>
23135446Strhodes
24135446Strhodes#include <string.h>
25135446Strhodes
26135446Strhodes#include <isc/buffer.h>
27135446Strhodes#include <isc/lex.h>
28135446Strhodes#include <isc/log.h>
29135446Strhodes#include <isc/magic.h>
30135446Strhodes#include <isc/mem.h>
31135446Strhodes#include <isc/once.h>
32135446Strhodes#include <isc/print.h>
33135446Strhodes#include <isc/region.h>
34135446Strhodes#include <isc/util.h>
35135446Strhodes
36135446Strhodes#include <dns/callbacks.h>
37135446Strhodes#include <dns/db.h>
38135446Strhodes#include <dns/dbiterator.h>
39135446Strhodes#include <dns/fixedname.h>
40135446Strhodes#include <dns/log.h>
41135446Strhodes#include <dns/rdata.h>
42135446Strhodes#include <dns/rdatalist.h>
43135446Strhodes#include <dns/rdataset.h>
44135446Strhodes#include <dns/rdatasetiter.h>
45135446Strhodes#include <dns/rdatatype.h>
46135446Strhodes#include <dns/result.h>
47135446Strhodes#include <dns/sdb.h>
48135446Strhodes#include <dns/types.h>
49135446Strhodes
50135446Strhodes#include "rdatalist_p.h"
51135446Strhodes
52135446Strhodesstruct dns_sdbimplementation {
53135446Strhodes	const dns_sdbmethods_t		*methods;
54135446Strhodes	void				*driverdata;
55135446Strhodes	unsigned int			flags;
56135446Strhodes	isc_mem_t			*mctx;
57135446Strhodes	isc_mutex_t			driverlock;
58135446Strhodes	dns_dbimplementation_t		*dbimp;
59135446Strhodes};
60135446Strhodes
61135446Strhodesstruct dns_sdb {
62135446Strhodes	/* Unlocked */
63135446Strhodes	dns_db_t			common;
64135446Strhodes	char				*zone;
65135446Strhodes	dns_sdbimplementation_t		*implementation;
66135446Strhodes	void				*dbdata;
67135446Strhodes	isc_mutex_t			lock;
68135446Strhodes	/* Locked */
69135446Strhodes	unsigned int			references;
70135446Strhodes};
71135446Strhodes
72135446Strhodesstruct dns_sdblookup {
73135446Strhodes	/* Unlocked */
74135446Strhodes	unsigned int			magic;
75135446Strhodes	dns_sdb_t			*sdb;
76135446Strhodes	ISC_LIST(dns_rdatalist_t)	lists;
77135446Strhodes	ISC_LIST(isc_buffer_t)		buffers;
78135446Strhodes	dns_name_t			*name;
79135446Strhodes	ISC_LINK(dns_sdblookup_t)	link;
80135446Strhodes	isc_mutex_t			lock;
81135446Strhodes	dns_rdatacallbacks_t		callbacks;
82135446Strhodes	/* Locked */
83135446Strhodes	unsigned int			references;
84135446Strhodes};
85135446Strhodes
86135446Strhodestypedef struct dns_sdblookup dns_sdbnode_t;
87135446Strhodes
88135446Strhodesstruct dns_sdballnodes {
89135446Strhodes	dns_dbiterator_t		common;
90135446Strhodes	ISC_LIST(dns_sdbnode_t)		nodelist;
91135446Strhodes	dns_sdbnode_t			*current;
92135446Strhodes	dns_sdbnode_t			*origin;
93135446Strhodes};
94135446Strhodes
95135446Strhodestypedef dns_sdballnodes_t sdb_dbiterator_t;
96135446Strhodes
97135446Strhodestypedef struct sdb_rdatasetiter {
98135446Strhodes	dns_rdatasetiter_t		common;
99135446Strhodes	dns_rdatalist_t			*current;
100135446Strhodes} sdb_rdatasetiter_t;
101135446Strhodes
102135446Strhodes#define SDB_MAGIC		ISC_MAGIC('S', 'D', 'B', '-')
103135446Strhodes
104170222Sdougb/*%
105135446Strhodes * Note that "impmagic" is not the first four bytes of the struct, so
106135446Strhodes * ISC_MAGIC_VALID cannot be used.
107135446Strhodes */
108135446Strhodes#define VALID_SDB(sdb)		((sdb) != NULL && \
109135446Strhodes				 (sdb)->common.impmagic == SDB_MAGIC)
110135446Strhodes
111135446Strhodes#define SDBLOOKUP_MAGIC		ISC_MAGIC('S','D','B','L')
112135446Strhodes#define VALID_SDBLOOKUP(sdbl)	ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)
113135446Strhodes#define VALID_SDBNODE(sdbn)	VALID_SDBLOOKUP(sdbn)
114135446Strhodes
115170222Sdougb/* These values are taken from RFC1537 */
116135446Strhodes#define SDB_DEFAULT_REFRESH	(60 * 60 * 8)
117135446Strhodes#define SDB_DEFAULT_RETRY	(60 * 60 * 2)
118135446Strhodes#define SDB_DEFAULT_EXPIRE	(60 * 60 * 24 * 7)
119135446Strhodes#define SDB_DEFAULT_MINIMUM	(60 * 60 * 24)
120135446Strhodes
121135446Strhodes/* This is a reasonable value */
122135446Strhodes#define SDB_DEFAULT_TTL		(60 * 60 * 24)
123135446Strhodes
124174187Sdougb#ifdef __COVERITY__
125174187Sdougb#define MAYBE_LOCK(sdb) LOCK(&sdb->implementation->driverlock)
126174187Sdougb#define MAYBE_UNLOCK(sdb) UNLOCK(&sdb->implementation->driverlock)
127174187Sdougb#else
128135446Strhodes#define MAYBE_LOCK(sdb)							\
129135446Strhodes	do {								\
130135446Strhodes		unsigned int flags = sdb->implementation->flags;	\
131135446Strhodes		if ((flags & DNS_SDBFLAG_THREADSAFE) == 0)		\
132135446Strhodes			LOCK(&sdb->implementation->driverlock);		\
133135446Strhodes	} while (0)
134135446Strhodes
135135446Strhodes#define MAYBE_UNLOCK(sdb)						\
136135446Strhodes	do {								\
137135446Strhodes		unsigned int flags = sdb->implementation->flags;	\
138135446Strhodes		if ((flags & DNS_SDBFLAG_THREADSAFE) == 0)		\
139135446Strhodes			UNLOCK(&sdb->implementation->driverlock);	\
140135446Strhodes	} while (0)
141174187Sdougb#endif
142135446Strhodes
143135446Strhodesstatic int dummy;
144135446Strhodes
145135446Strhodesstatic isc_result_t dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin,
146135446Strhodes				   dns_dbtype_t type, dns_rdataclass_t rdclass,
147135446Strhodes				   unsigned int argc, char *argv[],
148135446Strhodes				   void *driverarg, dns_db_t **dbp);
149135446Strhodes
150135446Strhodesstatic isc_result_t findrdataset(dns_db_t *db, dns_dbnode_t *node,
151135446Strhodes				 dns_dbversion_t *version,
152135446Strhodes				 dns_rdatatype_t type, dns_rdatatype_t covers,
153135446Strhodes				 isc_stdtime_t now, dns_rdataset_t *rdataset,
154135446Strhodes				 dns_rdataset_t *sigrdataset);
155135446Strhodes
156135446Strhodesstatic isc_result_t createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep);
157135446Strhodes
158135446Strhodesstatic void destroynode(dns_sdbnode_t *node);
159135446Strhodes
160135446Strhodesstatic void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
161135446Strhodes
162135446Strhodes
163135446Strhodesstatic void list_tordataset(dns_rdatalist_t *rdatalist,
164135446Strhodes			    dns_db_t *db, dns_dbnode_t *node,
165135446Strhodes			    dns_rdataset_t *rdataset);
166135446Strhodes
167135446Strhodesstatic void		dbiterator_destroy(dns_dbiterator_t **iteratorp);
168135446Strhodesstatic isc_result_t	dbiterator_first(dns_dbiterator_t *iterator);
169135446Strhodesstatic isc_result_t	dbiterator_last(dns_dbiterator_t *iterator);
170135446Strhodesstatic isc_result_t	dbiterator_seek(dns_dbiterator_t *iterator,
171135446Strhodes					dns_name_t *name);
172135446Strhodesstatic isc_result_t	dbiterator_prev(dns_dbiterator_t *iterator);
173135446Strhodesstatic isc_result_t	dbiterator_next(dns_dbiterator_t *iterator);
174135446Strhodesstatic isc_result_t	dbiterator_current(dns_dbiterator_t *iterator,
175135446Strhodes					   dns_dbnode_t **nodep,
176135446Strhodes					   dns_name_t *name);
177135446Strhodesstatic isc_result_t	dbiterator_pause(dns_dbiterator_t *iterator);
178135446Strhodesstatic isc_result_t	dbiterator_origin(dns_dbiterator_t *iterator,
179135446Strhodes					  dns_name_t *name);
180135446Strhodes
181135446Strhodesstatic dns_dbiteratormethods_t dbiterator_methods = {
182135446Strhodes	dbiterator_destroy,
183135446Strhodes	dbiterator_first,
184135446Strhodes	dbiterator_last,
185135446Strhodes	dbiterator_seek,
186135446Strhodes	dbiterator_prev,
187135446Strhodes	dbiterator_next,
188135446Strhodes	dbiterator_current,
189135446Strhodes	dbiterator_pause,
190135446Strhodes	dbiterator_origin
191135446Strhodes};
192135446Strhodes
193135446Strhodesstatic void		rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
194135446Strhodesstatic isc_result_t	rdatasetiter_first(dns_rdatasetiter_t *iterator);
195135446Strhodesstatic isc_result_t	rdatasetiter_next(dns_rdatasetiter_t *iterator);
196135446Strhodesstatic void		rdatasetiter_current(dns_rdatasetiter_t *iterator,
197135446Strhodes					     dns_rdataset_t *rdataset);
198135446Strhodes
199135446Strhodesstatic dns_rdatasetitermethods_t rdatasetiter_methods = {
200135446Strhodes	rdatasetiter_destroy,
201135446Strhodes	rdatasetiter_first,
202135446Strhodes	rdatasetiter_next,
203135446Strhodes	rdatasetiter_current
204135446Strhodes};
205135446Strhodes
206135446Strhodes/*
207135446Strhodes * Functions used by implementors of simple databases
208135446Strhodes */
209135446Strhodesisc_result_t
210135446Strhodesdns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
211135446Strhodes		 void *driverdata, unsigned int flags, isc_mem_t *mctx,
212135446Strhodes		 dns_sdbimplementation_t **sdbimp)
213135446Strhodes{
214135446Strhodes	dns_sdbimplementation_t *imp;
215135446Strhodes	isc_result_t result;
216135446Strhodes
217135446Strhodes	REQUIRE(drivername != NULL);
218135446Strhodes	REQUIRE(methods != NULL);
219236374Sdougb	REQUIRE(methods->lookup != NULL || methods->lookup2 != NULL);
220135446Strhodes	REQUIRE(mctx != NULL);
221135446Strhodes	REQUIRE(sdbimp != NULL && *sdbimp == NULL);
222135446Strhodes	REQUIRE((flags & ~(DNS_SDBFLAG_RELATIVEOWNER |
223135446Strhodes			   DNS_SDBFLAG_RELATIVERDATA |
224236374Sdougb			   DNS_SDBFLAG_THREADSAFE|
225236374Sdougb			   DNS_SDBFLAG_DNS64)) == 0);
226135446Strhodes
227135446Strhodes	imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t));
228135446Strhodes	if (imp == NULL)
229135446Strhodes		return (ISC_R_NOMEMORY);
230135446Strhodes	imp->methods = methods;
231135446Strhodes	imp->driverdata = driverdata;
232135446Strhodes	imp->flags = flags;
233135446Strhodes	imp->mctx = NULL;
234135446Strhodes	isc_mem_attach(mctx, &imp->mctx);
235135446Strhodes	result = isc_mutex_init(&imp->driverlock);
236170222Sdougb	if (result != ISC_R_SUCCESS)
237135446Strhodes		goto cleanup_mctx;
238135446Strhodes
239135446Strhodes	imp->dbimp = NULL;
240135446Strhodes	result = dns_db_register(drivername, dns_sdb_create, imp, mctx,
241135446Strhodes				 &imp->dbimp);
242135446Strhodes	if (result != ISC_R_SUCCESS)
243135446Strhodes		goto cleanup_mutex;
244135446Strhodes	*sdbimp = imp;
245135446Strhodes
246135446Strhodes	return (ISC_R_SUCCESS);
247135446Strhodes
248135446Strhodes cleanup_mutex:
249135446Strhodes	DESTROYLOCK(&imp->driverlock);
250135446Strhodes cleanup_mctx:
251135446Strhodes	isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
252135446Strhodes	return (result);
253135446Strhodes}
254135446Strhodes
255135446Strhodesvoid
256135446Strhodesdns_sdb_unregister(dns_sdbimplementation_t **sdbimp) {
257135446Strhodes	dns_sdbimplementation_t *imp;
258135446Strhodes	isc_mem_t *mctx;
259135446Strhodes
260135446Strhodes	REQUIRE(sdbimp != NULL && *sdbimp != NULL);
261135446Strhodes
262135446Strhodes	imp = *sdbimp;
263135446Strhodes	dns_db_unregister(&imp->dbimp);
264135446Strhodes	DESTROYLOCK(&imp->driverlock);
265135446Strhodes
266135446Strhodes	mctx = imp->mctx;
267135446Strhodes	isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
268135446Strhodes	isc_mem_detach(&mctx);
269135446Strhodes
270135446Strhodes	*sdbimp = NULL;
271135446Strhodes}
272135446Strhodes
273135446Strhodesstatic inline unsigned int
274135446Strhodesinitial_size(unsigned int len) {
275135446Strhodes	unsigned int size;
276170222Sdougb
277170222Sdougb	for (size = 1024; size < (64 * 1024); size *= 2)
278135446Strhodes		if (len < size)
279135446Strhodes			return (size);
280170222Sdougb	return (65535);
281135446Strhodes}
282135446Strhodes
283135446Strhodesisc_result_t
284236374Sdougbdns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval,
285236374Sdougb		 dns_ttl_t ttl, const unsigned char *rdatap,
286236374Sdougb		 unsigned int rdlen)
287135446Strhodes{
288135446Strhodes	dns_rdatalist_t *rdatalist;
289135446Strhodes	dns_rdata_t *rdata;
290135446Strhodes	isc_buffer_t *rdatabuf = NULL;
291135446Strhodes	isc_result_t result;
292135446Strhodes	isc_mem_t *mctx;
293135446Strhodes	isc_region_t region;
294135446Strhodes
295135446Strhodes	mctx = lookup->sdb->common.mctx;
296135446Strhodes
297135446Strhodes	rdatalist = ISC_LIST_HEAD(lookup->lists);
298135446Strhodes	while (rdatalist != NULL) {
299135446Strhodes		if (rdatalist->type == typeval)
300135446Strhodes			break;
301135446Strhodes		rdatalist = ISC_LIST_NEXT(rdatalist, link);
302135446Strhodes	}
303135446Strhodes
304135446Strhodes	if (rdatalist == NULL) {
305135446Strhodes		rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
306135446Strhodes		if (rdatalist == NULL)
307135446Strhodes			return (ISC_R_NOMEMORY);
308135446Strhodes		rdatalist->rdclass = lookup->sdb->common.rdclass;
309135446Strhodes		rdatalist->type = typeval;
310135446Strhodes		rdatalist->covers = 0;
311135446Strhodes		rdatalist->ttl = ttl;
312135446Strhodes		ISC_LIST_INIT(rdatalist->rdata);
313135446Strhodes		ISC_LINK_INIT(rdatalist, link);
314135446Strhodes		ISC_LIST_APPEND(lookup->lists, rdatalist, link);
315186462Sdougb	} else
316135446Strhodes		if (rdatalist->ttl != ttl)
317135446Strhodes			return (DNS_R_BADTTL);
318135446Strhodes
319135446Strhodes	rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
320135446Strhodes	if (rdata == NULL)
321135446Strhodes		return (ISC_R_NOMEMORY);
322135446Strhodes
323135446Strhodes	result = isc_buffer_allocate(mctx, &rdatabuf, rdlen);
324135446Strhodes	if (result != ISC_R_SUCCESS)
325135446Strhodes		goto failure;
326135446Strhodes	DE_CONST(rdatap, region.base);
327135446Strhodes	region.length = rdlen;
328135446Strhodes	isc_buffer_copyregion(rdatabuf, &region);
329135446Strhodes	isc_buffer_usedregion(rdatabuf, &region);
330135446Strhodes	dns_rdata_init(rdata);
331135446Strhodes	dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type,
332135446Strhodes			     &region);
333135446Strhodes	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
334135446Strhodes	ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
335135446Strhodes	rdata = NULL;
336135446Strhodes
337135446Strhodes failure:
338135446Strhodes	if (rdata != NULL)
339135446Strhodes		isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
340135446Strhodes	return (result);
341135446Strhodes}
342135446Strhodes
343135446Strhodesisc_result_t
344135446Strhodesdns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
345135446Strhodes	      const char *data)
346135446Strhodes{
347135446Strhodes	unsigned int datalen;
348135446Strhodes	dns_rdatatype_t typeval;
349135446Strhodes	isc_textregion_t r;
350135446Strhodes	isc_lex_t *lex = NULL;
351135446Strhodes	isc_result_t result;
352135446Strhodes	unsigned char *p = NULL;
353135446Strhodes	unsigned int size = 0; /* Init to suppress compiler warning */
354135446Strhodes	isc_mem_t *mctx;
355135446Strhodes	dns_sdbimplementation_t *imp;
356135446Strhodes	dns_name_t *origin;
357135446Strhodes	isc_buffer_t b;
358135446Strhodes	isc_buffer_t rb;
359135446Strhodes
360135446Strhodes	REQUIRE(VALID_SDBLOOKUP(lookup));
361135446Strhodes	REQUIRE(type != NULL);
362135446Strhodes	REQUIRE(data != NULL);
363135446Strhodes
364135446Strhodes	mctx = lookup->sdb->common.mctx;
365135446Strhodes
366135446Strhodes	DE_CONST(type, r.base);
367135446Strhodes	r.length = strlen(type);
368135446Strhodes	result = dns_rdatatype_fromtext(&typeval, &r);
369135446Strhodes	if (result != ISC_R_SUCCESS)
370135446Strhodes		return (result);
371135446Strhodes
372135446Strhodes	imp = lookup->sdb->implementation;
373135446Strhodes	if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
374135446Strhodes		origin = &lookup->sdb->common.origin;
375135446Strhodes	else
376135446Strhodes		origin = dns_rootname;
377135446Strhodes
378135446Strhodes	result = isc_lex_create(mctx, 64, &lex);
379135446Strhodes	if (result != ISC_R_SUCCESS)
380135446Strhodes		goto failure;
381135446Strhodes
382135446Strhodes	datalen = strlen(data);
383135446Strhodes	size = initial_size(datalen);
384186462Sdougb	do {
385135446Strhodes		isc_buffer_init(&b, data, datalen);
386135446Strhodes		isc_buffer_add(&b, datalen);
387135446Strhodes		result = isc_lex_openbuffer(lex, &b);
388135446Strhodes		if (result != ISC_R_SUCCESS)
389135446Strhodes			goto failure;
390135446Strhodes
391170222Sdougb		if (size >= 65535)
392170222Sdougb			size = 65535;
393135446Strhodes		p = isc_mem_get(mctx, size);
394135446Strhodes		if (p == NULL) {
395135446Strhodes			result = ISC_R_NOMEMORY;
396135446Strhodes			goto failure;
397135446Strhodes		}
398135446Strhodes		isc_buffer_init(&rb, p, size);
399135446Strhodes		result = dns_rdata_fromtext(NULL,
400135446Strhodes					    lookup->sdb->common.rdclass,
401135446Strhodes					    typeval, lex,
402135446Strhodes					    origin, 0,
403135446Strhodes					    mctx, &rb,
404135446Strhodes					    &lookup->callbacks);
405135446Strhodes		if (result != ISC_R_NOSPACE)
406135446Strhodes			break;
407135446Strhodes
408170222Sdougb		/*
409170222Sdougb		 * Is the RR too big?
410170222Sdougb		 */
411170222Sdougb		if (size >= 65535)
412170222Sdougb			break;
413135446Strhodes		isc_mem_put(mctx, p, size);
414135446Strhodes		p = NULL;
415135446Strhodes		size *= 2;
416135446Strhodes	} while (result == ISC_R_NOSPACE);
417135446Strhodes
418135446Strhodes	if (result != ISC_R_SUCCESS)
419135446Strhodes		goto failure;
420135446Strhodes
421135446Strhodes	result = dns_sdb_putrdata(lookup, typeval, ttl,
422135446Strhodes				  isc_buffer_base(&rb),
423135446Strhodes				  isc_buffer_usedlength(&rb));
424135446Strhodes failure:
425135446Strhodes	if (p != NULL)
426135446Strhodes		isc_mem_put(mctx, p, size);
427135446Strhodes	if (lex != NULL)
428135446Strhodes		isc_lex_destroy(&lex);
429135446Strhodes
430135446Strhodes	return (result);
431135446Strhodes}
432135446Strhodes
433135446Strhodesstatic isc_result_t
434135446Strhodesgetnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) {
435135446Strhodes	dns_name_t *newname, *origin;
436135446Strhodes	dns_fixedname_t fnewname;
437135446Strhodes	dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db;
438135446Strhodes	dns_sdbimplementation_t *imp = sdb->implementation;
439135446Strhodes	dns_sdbnode_t *sdbnode;
440135446Strhodes	isc_mem_t *mctx = sdb->common.mctx;
441135446Strhodes	isc_buffer_t b;
442135446Strhodes	isc_result_t result;
443135446Strhodes
444135446Strhodes	dns_fixedname_init(&fnewname);
445135446Strhodes	newname = dns_fixedname_name(&fnewname);
446135446Strhodes
447135446Strhodes	if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
448135446Strhodes		origin = &sdb->common.origin;
449135446Strhodes	else
450135446Strhodes		origin = dns_rootname;
451135446Strhodes	isc_buffer_init(&b, name, strlen(name));
452135446Strhodes	isc_buffer_add(&b, strlen(name));
453135446Strhodes
454224092Sdougb	result = dns_name_fromtext(newname, &b, origin, 0, NULL);
455135446Strhodes	if (result != ISC_R_SUCCESS)
456135446Strhodes		return (result);
457135446Strhodes
458135446Strhodes	if (allnodes->common.relative_names) {
459135446Strhodes		/* All names are relative to the root */
460135446Strhodes		unsigned int nlabels = dns_name_countlabels(newname);
461135446Strhodes		dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
462135446Strhodes	}
463135446Strhodes
464135446Strhodes	sdbnode = ISC_LIST_HEAD(allnodes->nodelist);
465135446Strhodes	if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) {
466135446Strhodes		sdbnode = NULL;
467135446Strhodes		result = createnode(sdb, &sdbnode);
468135446Strhodes		if (result != ISC_R_SUCCESS)
469135446Strhodes			return (result);
470135446Strhodes		sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t));
471135446Strhodes		if (sdbnode->name == NULL) {
472135446Strhodes			destroynode(sdbnode);
473135446Strhodes			return (ISC_R_NOMEMORY);
474135446Strhodes		}
475135446Strhodes		dns_name_init(sdbnode->name, NULL);
476135446Strhodes		result = dns_name_dup(newname, mctx, sdbnode->name);
477135446Strhodes		if (result != ISC_R_SUCCESS) {
478135446Strhodes			isc_mem_put(mctx, sdbnode->name, sizeof(dns_name_t));
479135446Strhodes			destroynode(sdbnode);
480135446Strhodes			return (result);
481135446Strhodes		}
482135446Strhodes		ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link);
483135446Strhodes		if (allnodes->origin == NULL &&
484135446Strhodes		    dns_name_equal(newname, &sdb->common.origin))
485135446Strhodes			allnodes->origin = sdbnode;
486135446Strhodes	}
487135446Strhodes	*nodep = sdbnode;
488135446Strhodes	return (ISC_R_SUCCESS);
489135446Strhodes}
490135446Strhodes
491135446Strhodesisc_result_t
492135446Strhodesdns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name,
493135446Strhodes		   const char *type, dns_ttl_t ttl, const char *data)
494135446Strhodes{
495135446Strhodes	isc_result_t result;
496135446Strhodes	dns_sdbnode_t *sdbnode = NULL;
497135446Strhodes	result = getnode(allnodes, name, &sdbnode);
498135446Strhodes	if (result != ISC_R_SUCCESS)
499135446Strhodes		return (result);
500135446Strhodes	return (dns_sdb_putrr(sdbnode, type, ttl, data));
501135446Strhodes}
502135446Strhodes
503135446Strhodesisc_result_t
504135446Strhodesdns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name,
505135446Strhodes		      dns_rdatatype_t type, dns_ttl_t ttl,
506135446Strhodes		      const void *rdata, unsigned int rdlen)
507135446Strhodes{
508135446Strhodes	isc_result_t result;
509135446Strhodes	dns_sdbnode_t *sdbnode = NULL;
510135446Strhodes	result = getnode(allnodes, name, &sdbnode);
511135446Strhodes	if (result != ISC_R_SUCCESS)
512135446Strhodes		return (result);
513135446Strhodes	return (dns_sdb_putrdata(sdbnode, type, ttl, rdata, rdlen));
514135446Strhodes}
515135446Strhodes
516135446Strhodesisc_result_t
517135446Strhodesdns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
518135446Strhodes	       isc_uint32_t serial)
519135446Strhodes{
520135446Strhodes	char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
521135446Strhodes	int n;
522135446Strhodes
523135446Strhodes	REQUIRE(mname != NULL);
524135446Strhodes	REQUIRE(rname != NULL);
525135446Strhodes
526135446Strhodes	n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u",
527135446Strhodes		     mname, rname, serial,
528135446Strhodes		     SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY,
529135446Strhodes		     SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM);
530135446Strhodes	if (n >= (int)sizeof(str) || n < 0)
531135446Strhodes		return (ISC_R_NOSPACE);
532135446Strhodes	return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));
533135446Strhodes}
534135446Strhodes
535135446Strhodes/*
536135446Strhodes * DB routines
537135446Strhodes */
538135446Strhodes
539135446Strhodesstatic void
540135446Strhodesattach(dns_db_t *source, dns_db_t **targetp) {
541135446Strhodes	dns_sdb_t *sdb = (dns_sdb_t *) source;
542135446Strhodes
543135446Strhodes	REQUIRE(VALID_SDB(sdb));
544135446Strhodes
545135446Strhodes	LOCK(&sdb->lock);
546135446Strhodes	REQUIRE(sdb->references > 0);
547135446Strhodes	sdb->references++;
548135446Strhodes	UNLOCK(&sdb->lock);
549135446Strhodes
550135446Strhodes	*targetp = source;
551135446Strhodes}
552135446Strhodes
553135446Strhodesstatic void
554135446Strhodesdestroy(dns_sdb_t *sdb) {
555135446Strhodes	isc_mem_t *mctx;
556135446Strhodes	dns_sdbimplementation_t *imp = sdb->implementation;
557135446Strhodes
558135446Strhodes	mctx = sdb->common.mctx;
559135446Strhodes
560135446Strhodes	if (imp->methods->destroy != NULL) {
561135446Strhodes		MAYBE_LOCK(sdb);
562135446Strhodes		imp->methods->destroy(sdb->zone, imp->driverdata,
563135446Strhodes				      &sdb->dbdata);
564135446Strhodes		MAYBE_UNLOCK(sdb);
565135446Strhodes	}
566135446Strhodes
567135446Strhodes	isc_mem_free(mctx, sdb->zone);
568135446Strhodes	DESTROYLOCK(&sdb->lock);
569135446Strhodes
570135446Strhodes	sdb->common.magic = 0;
571135446Strhodes	sdb->common.impmagic = 0;
572135446Strhodes
573135446Strhodes	dns_name_free(&sdb->common.origin, mctx);
574135446Strhodes
575135446Strhodes	isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
576135446Strhodes	isc_mem_detach(&mctx);
577135446Strhodes}
578135446Strhodes
579135446Strhodesstatic void
580135446Strhodesdetach(dns_db_t **dbp) {
581135446Strhodes	dns_sdb_t *sdb = (dns_sdb_t *)(*dbp);
582135446Strhodes	isc_boolean_t need_destroy = ISC_FALSE;
583135446Strhodes
584135446Strhodes	REQUIRE(VALID_SDB(sdb));
585135446Strhodes	LOCK(&sdb->lock);
586135446Strhodes	REQUIRE(sdb->references > 0);
587135446Strhodes	sdb->references--;
588135446Strhodes	if (sdb->references == 0)
589135446Strhodes		need_destroy = ISC_TRUE;
590135446Strhodes	UNLOCK(&sdb->lock);
591135446Strhodes
592135446Strhodes	if (need_destroy)
593135446Strhodes		destroy(sdb);
594135446Strhodes
595135446Strhodes	*dbp = NULL;
596135446Strhodes}
597135446Strhodes
598135446Strhodesstatic isc_result_t
599135446Strhodesbeginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
600135446Strhodes	UNUSED(db);
601135446Strhodes	UNUSED(addp);
602135446Strhodes	UNUSED(dbloadp);
603135446Strhodes	return (ISC_R_NOTIMPLEMENTED);
604135446Strhodes}
605135446Strhodes
606135446Strhodesstatic isc_result_t
607135446Strhodesendload(dns_db_t *db, dns_dbload_t **dbloadp) {
608135446Strhodes	UNUSED(db);
609135446Strhodes	UNUSED(dbloadp);
610135446Strhodes	return (ISC_R_NOTIMPLEMENTED);
611135446Strhodes}
612135446Strhodes
613135446Strhodesstatic isc_result_t
614170222Sdougbdump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
615170222Sdougb     dns_masterformat_t masterformat) {
616135446Strhodes	UNUSED(db);
617135446Strhodes	UNUSED(version);
618135446Strhodes	UNUSED(filename);
619170222Sdougb	UNUSED(masterformat);
620135446Strhodes	return (ISC_R_NOTIMPLEMENTED);
621135446Strhodes}
622135446Strhodes
623135446Strhodesstatic void
624135446Strhodescurrentversion(dns_db_t *db, dns_dbversion_t **versionp) {
625135446Strhodes	REQUIRE(versionp != NULL && *versionp == NULL);
626135446Strhodes
627135446Strhodes	UNUSED(db);
628135446Strhodes
629135446Strhodes	*versionp = (void *) &dummy;
630135446Strhodes	return;
631135446Strhodes}
632135446Strhodes
633135446Strhodesstatic isc_result_t
634135446Strhodesnewversion(dns_db_t *db, dns_dbversion_t **versionp) {
635135446Strhodes	UNUSED(db);
636135446Strhodes	UNUSED(versionp);
637135446Strhodes
638135446Strhodes	return (ISC_R_NOTIMPLEMENTED);
639135446Strhodes}
640135446Strhodes
641135446Strhodesstatic void
642186462Sdougbattachversion(dns_db_t *db, dns_dbversion_t *source,
643135446Strhodes	      dns_dbversion_t **targetp)
644135446Strhodes{
645135446Strhodes	REQUIRE(source != NULL && source == (void *) &dummy);
646135446Strhodes	REQUIRE(targetp != NULL && *targetp == NULL);
647135446Strhodes
648135446Strhodes	UNUSED(db);
649135446Strhodes	*targetp = source;
650135446Strhodes	return;
651135446Strhodes}
652135446Strhodes
653135446Strhodesstatic void
654135446Strhodescloseversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
655135446Strhodes	REQUIRE(versionp != NULL && *versionp == (void *) &dummy);
656135446Strhodes	REQUIRE(commit == ISC_FALSE);
657135446Strhodes
658135446Strhodes	UNUSED(db);
659135446Strhodes	UNUSED(commit);
660135446Strhodes
661135446Strhodes	*versionp = NULL;
662135446Strhodes}
663135446Strhodes
664135446Strhodesstatic isc_result_t
665135446Strhodescreatenode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) {
666135446Strhodes	dns_sdbnode_t *node;
667135446Strhodes	isc_result_t result;
668135446Strhodes
669135446Strhodes	node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t));
670135446Strhodes	if (node == NULL)
671135446Strhodes		return (ISC_R_NOMEMORY);
672135446Strhodes
673135446Strhodes	node->sdb = NULL;
674135446Strhodes	attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb);
675135446Strhodes	ISC_LIST_INIT(node->lists);
676135446Strhodes	ISC_LIST_INIT(node->buffers);
677135446Strhodes	ISC_LINK_INIT(node, link);
678135446Strhodes	node->name = NULL;
679135446Strhodes	result = isc_mutex_init(&node->lock);
680135446Strhodes	if (result != ISC_R_SUCCESS) {
681135446Strhodes		isc_mem_put(sdb->common.mctx, node, sizeof(dns_sdbnode_t));
682170222Sdougb		return (result);
683135446Strhodes	}
684135446Strhodes	dns_rdatacallbacks_init(&node->callbacks);
685135446Strhodes	node->references = 1;
686135446Strhodes	node->magic = SDBLOOKUP_MAGIC;
687135446Strhodes
688135446Strhodes	*nodep = node;
689135446Strhodes	return (ISC_R_SUCCESS);
690135446Strhodes}
691135446Strhodes
692135446Strhodesstatic void
693135446Strhodesdestroynode(dns_sdbnode_t *node) {
694135446Strhodes	dns_rdatalist_t *list;
695135446Strhodes	dns_rdata_t *rdata;
696135446Strhodes	isc_buffer_t *b;
697135446Strhodes	dns_sdb_t *sdb;
698135446Strhodes	isc_mem_t *mctx;
699135446Strhodes
700135446Strhodes	sdb = node->sdb;
701135446Strhodes	mctx = sdb->common.mctx;
702135446Strhodes
703135446Strhodes	while (!ISC_LIST_EMPTY(node->lists)) {
704135446Strhodes		list = ISC_LIST_HEAD(node->lists);
705135446Strhodes		while (!ISC_LIST_EMPTY(list->rdata)) {
706135446Strhodes			rdata = ISC_LIST_HEAD(list->rdata);
707135446Strhodes			ISC_LIST_UNLINK(list->rdata, rdata, link);
708135446Strhodes			isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
709135446Strhodes		}
710135446Strhodes		ISC_LIST_UNLINK(node->lists, list, link);
711135446Strhodes		isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
712135446Strhodes	}
713135446Strhodes
714135446Strhodes	while (!ISC_LIST_EMPTY(node->buffers)) {
715135446Strhodes		b = ISC_LIST_HEAD(node->buffers);
716135446Strhodes		ISC_LIST_UNLINK(node->buffers, b, link);
717135446Strhodes		isc_buffer_free(&b);
718135446Strhodes	}
719135446Strhodes
720135446Strhodes	if (node->name != NULL) {
721135446Strhodes		dns_name_free(node->name, mctx);
722135446Strhodes		isc_mem_put(mctx, node->name, sizeof(dns_name_t));
723135446Strhodes	}
724135446Strhodes	DESTROYLOCK(&node->lock);
725135446Strhodes	node->magic = 0;
726135446Strhodes	isc_mem_put(mctx, node, sizeof(dns_sdbnode_t));
727135446Strhodes	detach((dns_db_t **) (void *)&sdb);
728135446Strhodes}
729135446Strhodes
730135446Strhodesstatic isc_result_t
731135446Strhodesfindnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
732135446Strhodes	 dns_dbnode_t **nodep)
733135446Strhodes{
734135446Strhodes	dns_sdb_t *sdb = (dns_sdb_t *)db;
735135446Strhodes	dns_sdbnode_t *node = NULL;
736135446Strhodes	isc_result_t result;
737135446Strhodes	isc_buffer_t b;
738135446Strhodes	char namestr[DNS_NAME_MAXTEXT + 1];
739135446Strhodes	isc_boolean_t isorigin;
740135446Strhodes	dns_sdbimplementation_t *imp;
741236374Sdougb	dns_name_t relname;
742236374Sdougb	unsigned int labels;
743135446Strhodes
744135446Strhodes	REQUIRE(VALID_SDB(sdb));
745135446Strhodes	REQUIRE(create == ISC_FALSE);
746135446Strhodes	REQUIRE(nodep != NULL && *nodep == NULL);
747135446Strhodes
748135446Strhodes	UNUSED(name);
749135446Strhodes	UNUSED(create);
750135446Strhodes
751135446Strhodes	imp = sdb->implementation;
752135446Strhodes
753236374Sdougb	isorigin = dns_name_equal(name, &sdb->common.origin);
754135446Strhodes
755236374Sdougb	if (imp->methods->lookup2 != NULL) {
756236374Sdougb		if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
757236374Sdougb			labels = dns_name_countlabels(name) -
758236374Sdougb				 dns_name_countlabels(&db->origin);
759236374Sdougb			dns_name_init(&relname, NULL);
760236374Sdougb			dns_name_getlabelsequence(name, 0, labels, &relname);
761236374Sdougb			name = &relname;
762236374Sdougb		}
763135446Strhodes	} else {
764236374Sdougb		isc_buffer_init(&b, namestr, sizeof(namestr));
765236374Sdougb		if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
766236374Sdougb
767236374Sdougb			labels = dns_name_countlabels(name) -
768236374Sdougb				 dns_name_countlabels(&db->origin);
769236374Sdougb			dns_name_init(&relname, NULL);
770236374Sdougb			dns_name_getlabelsequence(name, 0, labels, &relname);
771236374Sdougb			result = dns_name_totext(&relname, ISC_TRUE, &b);
772236374Sdougb			if (result != ISC_R_SUCCESS)
773236374Sdougb				return (result);
774236374Sdougb		} else {
775236374Sdougb			result = dns_name_totext(name, ISC_TRUE, &b);
776236374Sdougb			if (result != ISC_R_SUCCESS)
777236374Sdougb				return (result);
778236374Sdougb		}
779236374Sdougb		isc_buffer_putuint8(&b, 0);
780135446Strhodes	}
781135446Strhodes
782135446Strhodes	result = createnode(sdb, &node);
783135446Strhodes	if (result != ISC_R_SUCCESS)
784135446Strhodes		return (result);
785135446Strhodes
786135446Strhodes	MAYBE_LOCK(sdb);
787236374Sdougb	if (imp->methods->lookup2 != NULL)
788236374Sdougb		result = imp->methods->lookup2(&sdb->common.origin, name,
789236374Sdougb					       sdb->dbdata, node);
790236374Sdougb	else
791236374Sdougb		result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata,
792236374Sdougb					      node);
793135446Strhodes	MAYBE_UNLOCK(sdb);
794135446Strhodes	if (result != ISC_R_SUCCESS &&
795135446Strhodes	    !(result == ISC_R_NOTFOUND &&
796135446Strhodes	      isorigin && imp->methods->authority != NULL))
797135446Strhodes	{
798135446Strhodes		destroynode(node);
799135446Strhodes		return (result);
800135446Strhodes	}
801135446Strhodes
802135446Strhodes	if (isorigin && imp->methods->authority != NULL) {
803135446Strhodes		MAYBE_LOCK(sdb);
804135446Strhodes		result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
805135446Strhodes		MAYBE_UNLOCK(sdb);
806135446Strhodes		if (result != ISC_R_SUCCESS) {
807135446Strhodes			destroynode(node);
808135446Strhodes			return (result);
809135446Strhodes		}
810135446Strhodes	}
811186462Sdougb
812135446Strhodes	*nodep = node;
813135446Strhodes	return (ISC_R_SUCCESS);
814135446Strhodes}
815135446Strhodes
816135446Strhodesstatic isc_result_t
817135446Strhodesfind(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
818135446Strhodes     dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
819135446Strhodes     dns_dbnode_t **nodep, dns_name_t *foundname,
820135446Strhodes     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
821135446Strhodes{
822135446Strhodes	dns_sdb_t *sdb = (dns_sdb_t *)db;
823135446Strhodes	dns_dbnode_t *node = NULL;
824135446Strhodes	dns_fixedname_t fname;
825135446Strhodes	dns_rdataset_t xrdataset;
826135446Strhodes	dns_name_t *xname;
827135446Strhodes	unsigned int nlabels, olabels;
828135446Strhodes	isc_result_t result;
829135446Strhodes	unsigned int i;
830236374Sdougb	unsigned int flags;
831135446Strhodes
832135446Strhodes	REQUIRE(VALID_SDB(sdb));
833135446Strhodes	REQUIRE(nodep == NULL || *nodep == NULL);
834135446Strhodes	REQUIRE(version == NULL || version == (void *) &dummy);
835135446Strhodes
836135446Strhodes	UNUSED(options);
837135446Strhodes
838135446Strhodes	if (!dns_name_issubdomain(name, &db->origin))
839135446Strhodes		return (DNS_R_NXDOMAIN);
840135446Strhodes
841135446Strhodes	olabels = dns_name_countlabels(&db->origin);
842135446Strhodes	nlabels = dns_name_countlabels(name);
843135446Strhodes
844135446Strhodes	dns_fixedname_init(&fname);
845135446Strhodes	xname = dns_fixedname_name(&fname);
846135446Strhodes
847135446Strhodes	if (rdataset == NULL) {
848135446Strhodes		dns_rdataset_init(&xrdataset);
849135446Strhodes		rdataset = &xrdataset;
850135446Strhodes	}
851135446Strhodes
852135446Strhodes	result = DNS_R_NXDOMAIN;
853236374Sdougb	flags = sdb->implementation->flags;
854236374Sdougb	i = (flags & DNS_SDBFLAG_DNS64) != 0 ? nlabels : olabels;
855236374Sdougb	for (; i <= nlabels; i++) {
856135446Strhodes		/*
857135446Strhodes		 * Look up the next label.
858135446Strhodes		 */
859135446Strhodes		dns_name_getlabelsequence(name, nlabels - i, i, xname);
860135446Strhodes		result = findnode(db, xname, ISC_FALSE, &node);
861236374Sdougb		if (result == ISC_R_NOTFOUND) {
862236374Sdougb			/*
863236374Sdougb			 * No data at zone apex?
864236374Sdougb			 */
865236374Sdougb			if (i == olabels)
866236374Sdougb				return (DNS_R_BADDB);
867135446Strhodes			result = DNS_R_NXDOMAIN;
868135446Strhodes			continue;
869135446Strhodes		}
870236374Sdougb		if (result != ISC_R_SUCCESS)
871236374Sdougb			return (result);
872135446Strhodes
873135446Strhodes		/*
874236374Sdougb		 * DNS64 zone's don't have DNAME or NS records.
875236374Sdougb		 */
876236374Sdougb		if ((flags & DNS_SDBFLAG_DNS64) != 0)
877236374Sdougb			goto skip;
878236374Sdougb
879236374Sdougb		/*
880236374Sdougb		 * DNS64 zone's don't have DNAME or NS records.
881236374Sdougb		 */
882236374Sdougb		if ((flags & DNS_SDBFLAG_DNS64) != 0)
883236374Sdougb			goto skip;
884236374Sdougb
885236374Sdougb		/*
886135446Strhodes		 * Look for a DNAME at the current label, unless this is
887135446Strhodes		 * the qname.
888135446Strhodes		 */
889135446Strhodes		if (i < nlabels) {
890135446Strhodes			result = findrdataset(db, node, version,
891135446Strhodes					      dns_rdatatype_dname,
892135446Strhodes					      0, now, rdataset, sigrdataset);
893135446Strhodes			if (result == ISC_R_SUCCESS) {
894135446Strhodes				result = DNS_R_DNAME;
895135446Strhodes				break;
896135446Strhodes			}
897135446Strhodes		}
898135446Strhodes
899135446Strhodes		/*
900135446Strhodes		 * Look for an NS at the current label, unless this is the
901135446Strhodes		 * origin or glue is ok.
902135446Strhodes		 */
903135446Strhodes		if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
904135446Strhodes			result = findrdataset(db, node, version,
905135446Strhodes					      dns_rdatatype_ns,
906135446Strhodes					      0, now, rdataset, sigrdataset);
907135446Strhodes			if (result == ISC_R_SUCCESS) {
908135446Strhodes				if (i == nlabels && type == dns_rdatatype_any)
909135446Strhodes				{
910135446Strhodes					result = DNS_R_ZONECUT;
911135446Strhodes					dns_rdataset_disassociate(rdataset);
912193149Sdougb					if (sigrdataset != NULL &&
913193149Sdougb					    dns_rdataset_isassociated
914193149Sdougb							(sigrdataset)) {
915135446Strhodes						dns_rdataset_disassociate
916135446Strhodes								(sigrdataset);
917193149Sdougb					}
918135446Strhodes				} else
919135446Strhodes					result = DNS_R_DELEGATION;
920135446Strhodes				break;
921135446Strhodes			}
922135446Strhodes		}
923135446Strhodes
924135446Strhodes		/*
925135446Strhodes		 * If the current name is not the qname, add another label
926135446Strhodes		 * and try again.
927135446Strhodes		 */
928135446Strhodes		if (i < nlabels) {
929135446Strhodes			destroynode(node);
930135446Strhodes			node = NULL;
931135446Strhodes			continue;
932135446Strhodes		}
933135446Strhodes
934236374Sdougb skip:
935135446Strhodes		/*
936135446Strhodes		 * If we're looking for ANY, we're done.
937135446Strhodes		 */
938135446Strhodes		if (type == dns_rdatatype_any) {
939135446Strhodes			result = ISC_R_SUCCESS;
940135446Strhodes			break;
941135446Strhodes		}
942135446Strhodes
943135446Strhodes		/*
944135446Strhodes		 * Look for the qtype.
945135446Strhodes		 */
946135446Strhodes		result = findrdataset(db, node, version, type,
947135446Strhodes				      0, now, rdataset, sigrdataset);
948135446Strhodes		if (result == ISC_R_SUCCESS)
949135446Strhodes			break;
950135446Strhodes
951135446Strhodes		/*
952135446Strhodes		 * Look for a CNAME
953135446Strhodes		 */
954135446Strhodes		if (type != dns_rdatatype_cname) {
955135446Strhodes			result = findrdataset(db, node, version,
956135446Strhodes					      dns_rdatatype_cname,
957135446Strhodes					      0, now, rdataset, sigrdataset);
958135446Strhodes			if (result == ISC_R_SUCCESS) {
959135446Strhodes				result = DNS_R_CNAME;
960135446Strhodes				break;
961135446Strhodes			}
962135446Strhodes		}
963135446Strhodes
964135446Strhodes		result = DNS_R_NXRRSET;
965135446Strhodes		break;
966135446Strhodes	}
967135446Strhodes
968135446Strhodes	if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
969135446Strhodes		dns_rdataset_disassociate(rdataset);
970135446Strhodes
971135446Strhodes	if (foundname != NULL) {
972135446Strhodes		isc_result_t xresult;
973135446Strhodes
974135446Strhodes		xresult = dns_name_copy(xname, foundname, NULL);
975135446Strhodes		if (xresult != ISC_R_SUCCESS) {
976170222Sdougb			if (node != NULL)
977170222Sdougb				destroynode(node);
978135446Strhodes			if (dns_rdataset_isassociated(rdataset))
979135446Strhodes				dns_rdataset_disassociate(rdataset);
980135446Strhodes			return (DNS_R_BADDB);
981135446Strhodes		}
982135446Strhodes	}
983135446Strhodes
984135446Strhodes	if (nodep != NULL)
985135446Strhodes		*nodep = node;
986135446Strhodes	else if (node != NULL)
987135446Strhodes		detachnode(db, &node);
988135446Strhodes
989135446Strhodes	return (result);
990135446Strhodes}
991135446Strhodes
992135446Strhodesstatic isc_result_t
993135446Strhodesfindzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
994135446Strhodes	    isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
995135446Strhodes	    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
996135446Strhodes{
997135446Strhodes	UNUSED(db);
998135446Strhodes	UNUSED(name);
999135446Strhodes	UNUSED(options);
1000135446Strhodes	UNUSED(now);
1001135446Strhodes	UNUSED(nodep);
1002135446Strhodes	UNUSED(foundname);
1003135446Strhodes	UNUSED(rdataset);
1004135446Strhodes	UNUSED(sigrdataset);
1005135446Strhodes
1006135446Strhodes	return (ISC_R_NOTIMPLEMENTED);
1007135446Strhodes}
1008135446Strhodes
1009135446Strhodesstatic void
1010135446Strhodesattachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
1011135446Strhodes	dns_sdb_t *sdb = (dns_sdb_t *)db;
1012135446Strhodes	dns_sdbnode_t *node = (dns_sdbnode_t *)source;
1013135446Strhodes
1014135446Strhodes	REQUIRE(VALID_SDB(sdb));
1015135446Strhodes
1016135446Strhodes	UNUSED(sdb);
1017135446Strhodes
1018135446Strhodes	LOCK(&node->lock);
1019135446Strhodes	INSIST(node->references > 0);
1020135446Strhodes	node->references++;
1021135446Strhodes	INSIST(node->references != 0);		/* Catch overflow. */
1022135446Strhodes	UNLOCK(&node->lock);
1023135446Strhodes
1024135446Strhodes	*targetp = source;
1025135446Strhodes}
1026135446Strhodes
1027135446Strhodesstatic void
1028135446Strhodesdetachnode(dns_db_t *db, dns_dbnode_t **targetp) {
1029135446Strhodes	dns_sdb_t *sdb = (dns_sdb_t *)db;
1030135446Strhodes	dns_sdbnode_t *node;
1031135446Strhodes	isc_boolean_t need_destroy = ISC_FALSE;
1032135446Strhodes
1033135446Strhodes	REQUIRE(VALID_SDB(sdb));
1034135446Strhodes	REQUIRE(targetp != NULL && *targetp != NULL);
1035135446Strhodes
1036135446Strhodes	UNUSED(sdb);
1037135446Strhodes
1038135446Strhodes	node = (dns_sdbnode_t *)(*targetp);
1039135446Strhodes
1040135446Strhodes	LOCK(&node->lock);
1041135446Strhodes	INSIST(node->references > 0);
1042135446Strhodes	node->references--;
1043135446Strhodes	if (node->references == 0)
1044135446Strhodes		need_destroy = ISC_TRUE;
1045135446Strhodes	UNLOCK(&node->lock);
1046135446Strhodes
1047135446Strhodes	if (need_destroy)
1048135446Strhodes		destroynode(node);
1049135446Strhodes
1050135446Strhodes	*targetp = NULL;
1051135446Strhodes}
1052135446Strhodes
1053135446Strhodesstatic isc_result_t
1054135446Strhodesexpirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
1055135446Strhodes	UNUSED(db);
1056135446Strhodes	UNUSED(node);
1057135446Strhodes	UNUSED(now);
1058135446Strhodes	INSIST(0);
1059135446Strhodes	return (ISC_R_UNEXPECTED);
1060135446Strhodes}
1061135446Strhodes
1062135446Strhodesstatic void
1063135446Strhodesprintnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
1064135446Strhodes	UNUSED(db);
1065135446Strhodes	UNUSED(node);
1066135446Strhodes	UNUSED(out);
1067135446Strhodes	return;
1068135446Strhodes}
1069135446Strhodes
1070135446Strhodesstatic isc_result_t
1071193149Sdougbcreateiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
1072135446Strhodes{
1073135446Strhodes	dns_sdb_t *sdb = (dns_sdb_t *)db;
1074135446Strhodes	sdb_dbiterator_t *sdbiter;
1075135446Strhodes	dns_sdbimplementation_t *imp = sdb->implementation;
1076135446Strhodes	isc_result_t result;
1077135446Strhodes
1078135446Strhodes	REQUIRE(VALID_SDB(sdb));
1079135446Strhodes
1080135446Strhodes	if (imp->methods->allnodes == NULL)
1081135446Strhodes		return (ISC_R_NOTIMPLEMENTED);
1082135446Strhodes
1083193149Sdougb	if ((options & DNS_DB_NSEC3ONLY) != 0 ||
1084193149Sdougb	    (options & DNS_DB_NONSEC3) != 0)
1085193149Sdougb		return (ISC_R_NOTIMPLEMENTED);
1086193149Sdougb
1087135446Strhodes	sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t));
1088135446Strhodes	if (sdbiter == NULL)
1089135446Strhodes		return (ISC_R_NOMEMORY);
1090135446Strhodes
1091135446Strhodes	sdbiter->common.methods = &dbiterator_methods;
1092135446Strhodes	sdbiter->common.db = NULL;
1093135446Strhodes	dns_db_attach(db, &sdbiter->common.db);
1094193149Sdougb	sdbiter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
1095135446Strhodes	sdbiter->common.magic = DNS_DBITERATOR_MAGIC;
1096135446Strhodes	ISC_LIST_INIT(sdbiter->nodelist);
1097135446Strhodes	sdbiter->current = NULL;
1098135446Strhodes	sdbiter->origin = NULL;
1099135446Strhodes
1100135446Strhodes	MAYBE_LOCK(sdb);
1101135446Strhodes	result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter);
1102135446Strhodes	MAYBE_UNLOCK(sdb);
1103135446Strhodes	if (result != ISC_R_SUCCESS) {
1104135446Strhodes		dbiterator_destroy((dns_dbiterator_t **) (void *)&sdbiter);
1105135446Strhodes		return (result);
1106135446Strhodes	}
1107135446Strhodes
1108135446Strhodes	if (sdbiter->origin != NULL) {
1109135446Strhodes		ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link);
1110135446Strhodes		ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link);
1111135446Strhodes	}
1112135446Strhodes
1113135446Strhodes	*iteratorp = (dns_dbiterator_t *)sdbiter;
1114135446Strhodes
1115135446Strhodes	return (ISC_R_SUCCESS);
1116135446Strhodes}
1117135446Strhodes
1118135446Strhodesstatic isc_result_t
1119135446Strhodesfindrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1120135446Strhodes	     dns_rdatatype_t type, dns_rdatatype_t covers,
1121135446Strhodes	     isc_stdtime_t now, dns_rdataset_t *rdataset,
1122135446Strhodes	     dns_rdataset_t *sigrdataset)
1123135446Strhodes{
1124135446Strhodes	dns_rdatalist_t *list;
1125135446Strhodes	dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
1126135446Strhodes
1127135446Strhodes	REQUIRE(VALID_SDBNODE(node));
1128135446Strhodes
1129135446Strhodes	UNUSED(db);
1130135446Strhodes	UNUSED(version);
1131135446Strhodes	UNUSED(covers);
1132135446Strhodes	UNUSED(now);
1133135446Strhodes	UNUSED(sigrdataset);
1134135446Strhodes
1135135446Strhodes	if (type == dns_rdatatype_rrsig)
1136135446Strhodes		return (ISC_R_NOTIMPLEMENTED);
1137135446Strhodes
1138135446Strhodes	list = ISC_LIST_HEAD(sdbnode->lists);
1139135446Strhodes	while (list != NULL) {
1140135446Strhodes		if (list->type == type)
1141135446Strhodes			break;
1142135446Strhodes		list = ISC_LIST_NEXT(list, link);
1143135446Strhodes	}
1144135446Strhodes	if (list == NULL)
1145135446Strhodes		return (ISC_R_NOTFOUND);
1146135446Strhodes
1147135446Strhodes	list_tordataset(list, db, node, rdataset);
1148135446Strhodes
1149135446Strhodes	return (ISC_R_SUCCESS);
1150135446Strhodes}
1151135446Strhodes
1152135446Strhodesstatic isc_result_t
1153135446Strhodesallrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1154135446Strhodes	     isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
1155135446Strhodes{
1156135446Strhodes	sdb_rdatasetiter_t *iterator;
1157135446Strhodes
1158135446Strhodes	REQUIRE(version == NULL || version == &dummy);
1159186462Sdougb
1160135446Strhodes	UNUSED(version);
1161135446Strhodes	UNUSED(now);
1162135446Strhodes
1163135446Strhodes	iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t));
1164135446Strhodes	if (iterator == NULL)
1165135446Strhodes		return (ISC_R_NOMEMORY);
1166135446Strhodes
1167135446Strhodes	iterator->common.magic = DNS_RDATASETITER_MAGIC;
1168135446Strhodes	iterator->common.methods = &rdatasetiter_methods;
1169135446Strhodes	iterator->common.db = db;
1170135446Strhodes	iterator->common.node = NULL;
1171135446Strhodes	attachnode(db, node, &iterator->common.node);
1172135446Strhodes	iterator->common.version = version;
1173135446Strhodes	iterator->common.now = now;
1174135446Strhodes
1175135446Strhodes	*iteratorp = (dns_rdatasetiter_t *)iterator;
1176135446Strhodes
1177135446Strhodes	return (ISC_R_SUCCESS);
1178135446Strhodes}
1179135446Strhodes
1180135446Strhodesstatic isc_result_t
1181135446Strhodesaddrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1182135446Strhodes	    isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
1183135446Strhodes	    dns_rdataset_t *addedrdataset)
1184135446Strhodes{
1185135446Strhodes	UNUSED(db);
1186135446Strhodes	UNUSED(node);
1187135446Strhodes	UNUSED(version);
1188135446Strhodes	UNUSED(now);
1189135446Strhodes	UNUSED(rdataset);
1190135446Strhodes	UNUSED(options);
1191135446Strhodes	UNUSED(addedrdataset);
1192135446Strhodes
1193135446Strhodes	return (ISC_R_NOTIMPLEMENTED);
1194135446Strhodes}
1195135446Strhodes
1196135446Strhodesstatic isc_result_t
1197135446Strhodessubtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1198135446Strhodes		 dns_rdataset_t *rdataset, unsigned int options,
1199135446Strhodes		 dns_rdataset_t *newrdataset)
1200135446Strhodes{
1201135446Strhodes	UNUSED(db);
1202135446Strhodes	UNUSED(node);
1203135446Strhodes	UNUSED(version);
1204135446Strhodes	UNUSED(rdataset);
1205135446Strhodes	UNUSED(options);
1206135446Strhodes	UNUSED(newrdataset);
1207135446Strhodes
1208135446Strhodes	return (ISC_R_NOTIMPLEMENTED);
1209135446Strhodes}
1210135446Strhodes
1211135446Strhodesstatic isc_result_t
1212135446Strhodesdeleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1213135446Strhodes	       dns_rdatatype_t type, dns_rdatatype_t covers)
1214135446Strhodes{
1215135446Strhodes	UNUSED(db);
1216135446Strhodes	UNUSED(node);
1217135446Strhodes	UNUSED(version);
1218135446Strhodes	UNUSED(type);
1219135446Strhodes	UNUSED(covers);
1220135446Strhodes
1221135446Strhodes	return (ISC_R_NOTIMPLEMENTED);
1222135446Strhodes}
1223135446Strhodes
1224135446Strhodesstatic isc_boolean_t
1225135446Strhodesissecure(dns_db_t *db) {
1226135446Strhodes	UNUSED(db);
1227135446Strhodes
1228135446Strhodes	return (ISC_FALSE);
1229135446Strhodes}
1230135446Strhodes
1231135446Strhodesstatic unsigned int
1232135446Strhodesnodecount(dns_db_t *db) {
1233135446Strhodes	UNUSED(db);
1234135446Strhodes
1235135446Strhodes	return (0);
1236135446Strhodes}
1237135446Strhodes
1238135446Strhodesstatic isc_boolean_t
1239135446Strhodesispersistent(dns_db_t *db) {
1240135446Strhodes	UNUSED(db);
1241135446Strhodes	return (ISC_TRUE);
1242135446Strhodes}
1243135446Strhodes
1244135446Strhodesstatic void
1245135446Strhodesovermem(dns_db_t *db, isc_boolean_t overmem) {
1246135446Strhodes	UNUSED(db);
1247135446Strhodes	UNUSED(overmem);
1248135446Strhodes}
1249135446Strhodes
1250135446Strhodesstatic void
1251135446Strhodessettask(dns_db_t *db, isc_task_t *task) {
1252135446Strhodes	UNUSED(db);
1253135446Strhodes	UNUSED(task);
1254135446Strhodes}
1255135446Strhodes
1256135446Strhodes
1257135446Strhodesstatic dns_dbmethods_t sdb_methods = {
1258135446Strhodes	attach,
1259135446Strhodes	detach,
1260135446Strhodes	beginload,
1261135446Strhodes	endload,
1262135446Strhodes	dump,
1263135446Strhodes	currentversion,
1264135446Strhodes	newversion,
1265135446Strhodes	attachversion,
1266135446Strhodes	closeversion,
1267135446Strhodes	findnode,
1268135446Strhodes	find,
1269135446Strhodes	findzonecut,
1270135446Strhodes	attachnode,
1271135446Strhodes	detachnode,
1272135446Strhodes	expirenode,
1273135446Strhodes	printnode,
1274135446Strhodes	createiterator,
1275135446Strhodes	findrdataset,
1276135446Strhodes	allrdatasets,
1277135446Strhodes	addrdataset,
1278135446Strhodes	subtractrdataset,
1279135446Strhodes	deleterdataset,
1280135446Strhodes	issecure,
1281135446Strhodes	nodecount,
1282135446Strhodes	ispersistent,
1283135446Strhodes	overmem,
1284170222Sdougb	settask,
1285193149Sdougb	NULL,
1286193149Sdougb	NULL,
1287193149Sdougb	NULL,
1288193149Sdougb	NULL,
1289193149Sdougb	NULL,
1290193149Sdougb	NULL,
1291193149Sdougb	NULL,
1292193149Sdougb	NULL,
1293224092Sdougb	NULL,
1294224092Sdougb	NULL,
1295170222Sdougb	NULL
1296135446Strhodes};
1297135446Strhodes
1298135446Strhodesstatic isc_result_t
1299135446Strhodesdns_sdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
1300135446Strhodes	       dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
1301135446Strhodes	       void *driverarg, dns_db_t **dbp)
1302135446Strhodes{
1303135446Strhodes	dns_sdb_t *sdb;
1304135446Strhodes	isc_result_t result;
1305135446Strhodes	char zonestr[DNS_NAME_MAXTEXT + 1];
1306135446Strhodes	isc_buffer_t b;
1307135446Strhodes	dns_sdbimplementation_t *imp;
1308135446Strhodes
1309135446Strhodes	REQUIRE(driverarg != NULL);
1310135446Strhodes
1311135446Strhodes	imp = driverarg;
1312135446Strhodes
1313135446Strhodes	if (type != dns_dbtype_zone)
1314135446Strhodes		return (ISC_R_NOTIMPLEMENTED);
1315135446Strhodes
1316135446Strhodes	sdb = isc_mem_get(mctx, sizeof(dns_sdb_t));
1317135446Strhodes	if (sdb == NULL)
1318135446Strhodes		return (ISC_R_NOMEMORY);
1319135446Strhodes	memset(sdb, 0, sizeof(dns_sdb_t));
1320135446Strhodes
1321135446Strhodes	dns_name_init(&sdb->common.origin, NULL);
1322135446Strhodes	sdb->common.attributes = 0;
1323135446Strhodes	sdb->common.methods = &sdb_methods;
1324135446Strhodes	sdb->common.rdclass = rdclass;
1325135446Strhodes	sdb->common.mctx = NULL;
1326135446Strhodes	sdb->implementation = imp;
1327135446Strhodes
1328135446Strhodes	isc_mem_attach(mctx, &sdb->common.mctx);
1329135446Strhodes
1330135446Strhodes	result = isc_mutex_init(&sdb->lock);
1331170222Sdougb	if (result != ISC_R_SUCCESS)
1332135446Strhodes		goto cleanup_mctx;
1333135446Strhodes
1334135446Strhodes	result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
1335135446Strhodes	if (result != ISC_R_SUCCESS)
1336135446Strhodes		goto cleanup_lock;
1337135446Strhodes
1338135446Strhodes	isc_buffer_init(&b, zonestr, sizeof(zonestr));
1339135446Strhodes	result = dns_name_totext(origin, ISC_TRUE, &b);
1340135446Strhodes	if (result != ISC_R_SUCCESS)
1341135446Strhodes		goto cleanup_origin;
1342135446Strhodes	isc_buffer_putuint8(&b, 0);
1343135446Strhodes
1344135446Strhodes	sdb->zone = isc_mem_strdup(mctx, zonestr);
1345135446Strhodes	if (sdb->zone == NULL) {
1346135446Strhodes		result = ISC_R_NOMEMORY;
1347135446Strhodes		goto cleanup_origin;
1348135446Strhodes	}
1349135446Strhodes
1350135446Strhodes	sdb->dbdata = NULL;
1351135446Strhodes	if (imp->methods->create != NULL) {
1352135446Strhodes		MAYBE_LOCK(sdb);
1353135446Strhodes		result = imp->methods->create(sdb->zone, argc, argv,
1354135446Strhodes					      imp->driverdata, &sdb->dbdata);
1355135446Strhodes		MAYBE_UNLOCK(sdb);
1356135446Strhodes		if (result != ISC_R_SUCCESS)
1357135446Strhodes			goto cleanup_zonestr;
1358135446Strhodes	}
1359135446Strhodes
1360135446Strhodes	sdb->references = 1;
1361135446Strhodes
1362135446Strhodes	sdb->common.magic = DNS_DB_MAGIC;
1363135446Strhodes	sdb->common.impmagic = SDB_MAGIC;
1364135446Strhodes
1365135446Strhodes	*dbp = (dns_db_t *)sdb;
1366135446Strhodes
1367135446Strhodes	return (ISC_R_SUCCESS);
1368135446Strhodes
1369135446Strhodes cleanup_zonestr:
1370135446Strhodes	isc_mem_free(mctx, sdb->zone);
1371135446Strhodes cleanup_origin:
1372135446Strhodes	dns_name_free(&sdb->common.origin, mctx);
1373135446Strhodes cleanup_lock:
1374225361Sdougb	(void)isc_mutex_destroy(&sdb->lock);
1375135446Strhodes cleanup_mctx:
1376135446Strhodes	isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
1377135446Strhodes	isc_mem_detach(&mctx);
1378135446Strhodes
1379135446Strhodes	return (result);
1380135446Strhodes}
1381135446Strhodes
1382135446Strhodes
1383135446Strhodes/*
1384135446Strhodes * Rdataset Methods
1385135446Strhodes */
1386135446Strhodes
1387135446Strhodesstatic void
1388135446Strhodesdisassociate(dns_rdataset_t *rdataset) {
1389135446Strhodes	dns_dbnode_t *node = rdataset->private5;
1390135446Strhodes	dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
1391135446Strhodes	dns_db_t *db = (dns_db_t *) sdbnode->sdb;
1392135446Strhodes
1393135446Strhodes	detachnode(db, &node);
1394135446Strhodes	isc__rdatalist_disassociate(rdataset);
1395135446Strhodes}
1396135446Strhodes
1397135446Strhodesstatic void
1398135446Strhodesrdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1399135446Strhodes	dns_dbnode_t *node = source->private5;
1400135446Strhodes	dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
1401135446Strhodes	dns_db_t *db = (dns_db_t *) sdbnode->sdb;
1402135446Strhodes	dns_dbnode_t *tempdb = NULL;
1403135446Strhodes
1404135446Strhodes	isc__rdatalist_clone(source, target);
1405135446Strhodes	attachnode(db, node, &tempdb);
1406135446Strhodes	source->private5 = tempdb;
1407135446Strhodes}
1408135446Strhodes
1409135446Strhodesstatic dns_rdatasetmethods_t methods = {
1410135446Strhodes	disassociate,
1411135446Strhodes	isc__rdatalist_first,
1412135446Strhodes	isc__rdatalist_next,
1413135446Strhodes	isc__rdatalist_current,
1414135446Strhodes	rdataset_clone,
1415135446Strhodes	isc__rdatalist_count,
1416135446Strhodes	isc__rdatalist_addnoqname,
1417170222Sdougb	isc__rdatalist_getnoqname,
1418170222Sdougb	NULL,
1419170222Sdougb	NULL,
1420193149Sdougb	NULL,
1421193149Sdougb	NULL,
1422205292Sdougb	NULL,
1423205292Sdougb	NULL,
1424170222Sdougb	NULL
1425135446Strhodes};
1426135446Strhodes
1427135446Strhodesstatic void
1428135446Strhodeslist_tordataset(dns_rdatalist_t *rdatalist,
1429135446Strhodes		dns_db_t *db, dns_dbnode_t *node,
1430135446Strhodes		dns_rdataset_t *rdataset)
1431135446Strhodes{
1432135446Strhodes	/*
1433135446Strhodes	 * The sdb rdataset is an rdatalist with some additions.
1434135446Strhodes	 *	- private1 & private2 are used by the rdatalist.
1435135446Strhodes	 *	- private3 & private 4 are unused.
1436135446Strhodes	 *	- private5 is the node.
1437135446Strhodes	 */
1438135446Strhodes
1439135446Strhodes	/* This should never fail. */
1440135446Strhodes	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1441135446Strhodes		      ISC_R_SUCCESS);
1442135446Strhodes
1443135446Strhodes	rdataset->methods = &methods;
1444135446Strhodes	dns_db_attachnode(db, node, &rdataset->private5);
1445135446Strhodes}
1446135446Strhodes
1447135446Strhodes/*
1448135446Strhodes * Database Iterator Methods
1449135446Strhodes */
1450135446Strhodesstatic void
1451135446Strhodesdbiterator_destroy(dns_dbiterator_t **iteratorp) {
1452135446Strhodes	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp);
1453135446Strhodes	dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db;
1454135446Strhodes
1455135446Strhodes	while (!ISC_LIST_EMPTY(sdbiter->nodelist)) {
1456135446Strhodes		dns_sdbnode_t *node;
1457135446Strhodes		node = ISC_LIST_HEAD(sdbiter->nodelist);
1458135446Strhodes		ISC_LIST_UNLINK(sdbiter->nodelist, node, link);
1459135446Strhodes		destroynode(node);
1460135446Strhodes	}
1461135446Strhodes
1462135446Strhodes	dns_db_detach(&sdbiter->common.db);
1463135446Strhodes	isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t));
1464135446Strhodes
1465135446Strhodes	*iteratorp = NULL;
1466135446Strhodes}
1467135446Strhodes
1468135446Strhodesstatic isc_result_t
1469135446Strhodesdbiterator_first(dns_dbiterator_t *iterator) {
1470135446Strhodes	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1471135446Strhodes
1472135446Strhodes	sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1473135446Strhodes	if (sdbiter->current == NULL)
1474135446Strhodes		return (ISC_R_NOMORE);
1475135446Strhodes	else
1476135446Strhodes		return (ISC_R_SUCCESS);
1477135446Strhodes}
1478135446Strhodes
1479135446Strhodesstatic isc_result_t
1480135446Strhodesdbiterator_last(dns_dbiterator_t *iterator) {
1481135446Strhodes	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1482135446Strhodes
1483135446Strhodes	sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist);
1484135446Strhodes	if (sdbiter->current == NULL)
1485135446Strhodes		return (ISC_R_NOMORE);
1486135446Strhodes	else
1487135446Strhodes		return (ISC_R_SUCCESS);
1488135446Strhodes}
1489135446Strhodes
1490135446Strhodesstatic isc_result_t
1491135446Strhodesdbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
1492135446Strhodes	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1493135446Strhodes
1494135446Strhodes	sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1495204619Sdougb	while (sdbiter->current != NULL) {
1496135446Strhodes		if (dns_name_equal(sdbiter->current->name, name))
1497135446Strhodes			return (ISC_R_SUCCESS);
1498204619Sdougb		sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
1499204619Sdougb	}
1500135446Strhodes	return (ISC_R_NOTFOUND);
1501135446Strhodes}
1502135446Strhodes
1503135446Strhodesstatic isc_result_t
1504135446Strhodesdbiterator_prev(dns_dbiterator_t *iterator) {
1505135446Strhodes	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1506135446Strhodes
1507135446Strhodes	sdbiter->current = ISC_LIST_PREV(sdbiter->current, link);
1508135446Strhodes	if (sdbiter->current == NULL)
1509135446Strhodes		return (ISC_R_NOMORE);
1510135446Strhodes	else
1511135446Strhodes		return (ISC_R_SUCCESS);
1512135446Strhodes}
1513135446Strhodes
1514135446Strhodesstatic isc_result_t
1515135446Strhodesdbiterator_next(dns_dbiterator_t *iterator) {
1516135446Strhodes	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1517135446Strhodes
1518135446Strhodes	sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
1519135446Strhodes	if (sdbiter->current == NULL)
1520135446Strhodes		return (ISC_R_NOMORE);
1521135446Strhodes	else
1522135446Strhodes		return (ISC_R_SUCCESS);
1523135446Strhodes}
1524135446Strhodes
1525135446Strhodesstatic isc_result_t
1526135446Strhodesdbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1527135446Strhodes		   dns_name_t *name)
1528135446Strhodes{
1529135446Strhodes	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1530135446Strhodes
1531135446Strhodes	attachnode(iterator->db, sdbiter->current, nodep);
1532135446Strhodes	if (name != NULL)
1533135446Strhodes		return (dns_name_copy(sdbiter->current->name, name, NULL));
1534135446Strhodes	return (ISC_R_SUCCESS);
1535135446Strhodes}
1536135446Strhodes
1537135446Strhodesstatic isc_result_t
1538135446Strhodesdbiterator_pause(dns_dbiterator_t *iterator) {
1539135446Strhodes	UNUSED(iterator);
1540135446Strhodes	return (ISC_R_SUCCESS);
1541135446Strhodes}
1542135446Strhodes
1543135446Strhodesstatic isc_result_t
1544135446Strhodesdbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1545135446Strhodes	UNUSED(iterator);
1546135446Strhodes	return (dns_name_copy(dns_rootname, name, NULL));
1547135446Strhodes}
1548135446Strhodes
1549135446Strhodes/*
1550135446Strhodes * Rdataset Iterator Methods
1551135446Strhodes */
1552135446Strhodes
1553135446Strhodesstatic void
1554135446Strhodesrdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
1555135446Strhodes	sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp);
1556135446Strhodes	detachnode(sdbiterator->common.db, &sdbiterator->common.node);
1557135446Strhodes	isc_mem_put(sdbiterator->common.db->mctx, sdbiterator,
1558135446Strhodes		    sizeof(sdb_rdatasetiter_t));
1559135446Strhodes	*iteratorp = NULL;
1560135446Strhodes}
1561135446Strhodes
1562135446Strhodesstatic isc_result_t
1563135446Strhodesrdatasetiter_first(dns_rdatasetiter_t *iterator) {
1564135446Strhodes	sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1565135446Strhodes	dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node;
1566135446Strhodes
1567135446Strhodes	if (ISC_LIST_EMPTY(sdbnode->lists))
1568135446Strhodes		return (ISC_R_NOMORE);
1569135446Strhodes	sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists);
1570135446Strhodes	return (ISC_R_SUCCESS);
1571135446Strhodes}
1572135446Strhodes
1573135446Strhodesstatic isc_result_t
1574135446Strhodesrdatasetiter_next(dns_rdatasetiter_t *iterator) {
1575135446Strhodes	sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1576135446Strhodes
1577135446Strhodes	sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link);
1578135446Strhodes	if (sdbiterator->current == NULL)
1579135446Strhodes		return (ISC_R_NOMORE);
1580135446Strhodes	else
1581135446Strhodes		return (ISC_R_SUCCESS);
1582135446Strhodes}
1583135446Strhodes
1584135446Strhodesstatic void
1585135446Strhodesrdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
1586135446Strhodes	sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1587135446Strhodes
1588135446Strhodes	list_tordataset(sdbiterator->current, iterator->db, iterator->node,
1589135446Strhodes			rdataset);
1590135446Strhodes}
1591