sdb.c revision 193149
1163953Srrs/*
2169382Srrs * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
3218319Srrs * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
4218319Srrs *
5163953Srrs * Permission to use, copy, modify, and/or distribute this software for any
6163953Srrs * purpose with or without fee is hereby granted, provided that the above
7163953Srrs * copyright notice and this permission notice appear in all copies.
8163953Srrs *
9163953Srrs * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10231038Stuexen * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11163953Srrs * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12163953Srrs * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13163953Srrs * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14231038Stuexen * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15163953Srrs * PERFORMANCE OF THIS SOFTWARE.
16163953Srrs */
17163953Srrs
18163953Srrs/* $Id: sdb.c,v 1.66.48.2 2009/04/21 23:47:18 tbox Exp $ */
19163953Srrs
20163953Srrs/*! \file */
21163953Srrs
22163953Srrs#include <config.h>
23163953Srrs
24163953Srrs#include <string.h>
25163953Srrs
26163953Srrs#include <isc/buffer.h>
27163953Srrs#include <isc/lex.h>
28163953Srrs#include <isc/log.h>
29163953Srrs#include <isc/magic.h>
30163953Srrs#include <isc/mem.h>
31163953Srrs#include <isc/once.h>
32163953Srrs#include <isc/print.h>
33163953Srrs#include <isc/region.h>
34163953Srrs#include <isc/util.h>
35163953Srrs
36163953Srrs#include <dns/callbacks.h>
37163953Srrs#include <dns/db.h>
38163953Srrs#include <dns/dbiterator.h>
39166086Srrs#include <dns/fixedname.h>
40163953Srrs#include <dns/log.h>
41163953Srrs#include <dns/rdata.h>
42163953Srrs#include <dns/rdatalist.h>
43163953Srrs#include <dns/rdataset.h>
44167598Srrs#include <dns/rdatasetiter.h>
45163953Srrs#include <dns/rdatatype.h>
46163953Srrs#include <dns/result.h>
47163953Srrs#include <dns/sdb.h>
48163953Srrs#include <dns/types.h>
49163953Srrs
50163953Srrs#include "rdatalist_p.h"
51163953Srrs
52163953Srrsstruct dns_sdbimplementation {
53163953Srrs	const dns_sdbmethods_t		*methods;
54185694Srrs	void				*driverdata;
55163953Srrs	unsigned int			flags;
56163953Srrs	isc_mem_t			*mctx;
57163953Srrs	isc_mutex_t			driverlock;
58163953Srrs	dns_dbimplementation_t		*dbimp;
59163953Srrs};
60163953Srrs
61163953Srrsstruct dns_sdb {
62169420Srrs	/* Unlocked */
63169420Srrs	dns_db_t			common;
64169420Srrs	char				*zone;
65163953Srrs	dns_sdbimplementation_t		*implementation;
66163953Srrs	void				*dbdata;
67163953Srrs	isc_mutex_t			lock;
68163953Srrs	/* Locked */
69163953Srrs	unsigned int			references;
70163953Srrs};
71163953Srrs
72163953Srrsstruct dns_sdblookup {
73163953Srrs	/* Unlocked */
74163953Srrs	unsigned int			magic;
75163953Srrs	dns_sdb_t			*sdb;
76163953Srrs	ISC_LIST(dns_rdatalist_t)	lists;
77163953Srrs	ISC_LIST(isc_buffer_t)		buffers;
78179157Srrs	dns_name_t			*name;
79179157Srrs	ISC_LINK(dns_sdblookup_t)	link;
80179157Srrs	isc_mutex_t			lock;
81179157Srrs	dns_rdatacallbacks_t		callbacks;
82179157Srrs	/* Locked */
83169420Srrs	unsigned int			references;
84169420Srrs};
85169420Srrs
86163953Srrstypedef struct dns_sdblookup dns_sdbnode_t;
87163953Srrs
88163953Srrsstruct dns_sdballnodes {
89163953Srrs	dns_dbiterator_t		common;
90163953Srrs	ISC_LIST(dns_sdbnode_t)		nodelist;
91163953Srrs	dns_sdbnode_t			*current;
92163953Srrs	dns_sdbnode_t			*origin;
93163953Srrs};
94169420Srrs
95169420Srrstypedef dns_sdballnodes_t sdb_dbiterator_t;
96169420Srrs
97163953Srrstypedef struct sdb_rdatasetiter {
98163953Srrs	dns_rdatasetiter_t		common;
99163953Srrs	dns_rdatalist_t			*current;
100163953Srrs} sdb_rdatasetiter_t;
101167598Srrs
102224641Stuexen#define SDB_MAGIC		ISC_MAGIC('S', 'D', 'B', '-')
103163953Srrs
104163953Srrs/*%
105163953Srrs * Note that "impmagic" is not the first four bytes of the struct, so
106172090Srrs * ISC_MAGIC_VALID cannot be used.
107163953Srrs */
108224641Stuexen#define VALID_SDB(sdb)		((sdb) != NULL && \
109224641Stuexen				 (sdb)->common.impmagic == SDB_MAGIC)
110224641Stuexen
111224641Stuexen#define SDBLOOKUP_MAGIC		ISC_MAGIC('S','D','B','L')
112224641Stuexen#define VALID_SDBLOOKUP(sdbl)	ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)
113224641Stuexen#define VALID_SDBNODE(sdbn)	VALID_SDBLOOKUP(sdbn)
114224641Stuexen
115224641Stuexen/* These values are taken from RFC1537 */
116224641Stuexen#define SDB_DEFAULT_REFRESH	(60 * 60 * 8)
117163953Srrs#define SDB_DEFAULT_RETRY	(60 * 60 * 2)
118163953Srrs#define SDB_DEFAULT_EXPIRE	(60 * 60 * 24 * 7)
119163953Srrs#define SDB_DEFAULT_MINIMUM	(60 * 60 * 24)
120163953Srrs
121163953Srrs/* This is a reasonable value */
122163953Srrs#define SDB_DEFAULT_TTL		(60 * 60 * 24)
123163953Srrs
124179783Srrs#ifdef __COVERITY__
125171943Srrs#define MAYBE_LOCK(sdb) LOCK(&sdb->implementation->driverlock)
126171943Srrs#define MAYBE_UNLOCK(sdb) UNLOCK(&sdb->implementation->driverlock)
127171943Srrs#else
128171943Srrs#define MAYBE_LOCK(sdb)							\
129171943Srrs	do {								\
130171943Srrs		unsigned int flags = sdb->implementation->flags;	\
131163953Srrs		if ((flags & DNS_SDBFLAG_THREADSAFE) == 0)		\
132163953Srrs			LOCK(&sdb->implementation->driverlock);		\
133163953Srrs	} while (0)
134179783Srrs
135171943Srrs#define MAYBE_UNLOCK(sdb)						\
136171943Srrs	do {								\
137171943Srrs		unsigned int flags = sdb->implementation->flags;	\
138171943Srrs		if ((flags & DNS_SDBFLAG_THREADSAFE) == 0)		\
139171943Srrs			UNLOCK(&sdb->implementation->driverlock);	\
140171943Srrs	} while (0)
141163953Srrs#endif
142163953Srrs
143169420Srrsstatic int dummy;
144169420Srrs
145169420Srrsstatic isc_result_t dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin,
146169420Srrs				   dns_dbtype_t type, dns_rdataclass_t rdclass,
147163953Srrs				   unsigned int argc, char *argv[],
148163953Srrs				   void *driverarg, dns_db_t **dbp);
149163953Srrs
150163953Srrsstatic isc_result_t findrdataset(dns_db_t *db, dns_dbnode_t *node,
151163953Srrs				 dns_dbversion_t *version,
152163953Srrs				 dns_rdatatype_t type, dns_rdatatype_t covers,
153163953Srrs				 isc_stdtime_t now, dns_rdataset_t *rdataset,
154163953Srrs				 dns_rdataset_t *sigrdataset);
155163953Srrs
156163953Srrsstatic isc_result_t createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep);
157163953Srrs
158163953Srrsstatic void destroynode(dns_sdbnode_t *node);
159163953Srrs
160163953Srrsstatic void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
161165647Srrs
162163953Srrs
163163953Srrsstatic void list_tordataset(dns_rdatalist_t *rdatalist,
164163953Srrs			    dns_db_t *db, dns_dbnode_t *node,
165165647Srrs			    dns_rdataset_t *rdataset);
166163953Srrs
167165220Srrsstatic void		dbiterator_destroy(dns_dbiterator_t **iteratorp);
168163953Srrsstatic isc_result_t	dbiterator_first(dns_dbiterator_t *iterator);
169165220Srrsstatic isc_result_t	dbiterator_last(dns_dbiterator_t *iterator);
170172090Srrsstatic isc_result_t	dbiterator_seek(dns_dbiterator_t *iterator,
171163953Srrs					dns_name_t *name);
172163953Srrsstatic isc_result_t	dbiterator_prev(dns_dbiterator_t *iterator);
173163953Srrsstatic isc_result_t	dbiterator_next(dns_dbiterator_t *iterator);
174163953Srrsstatic isc_result_t	dbiterator_current(dns_dbiterator_t *iterator,
175163953Srrs					   dns_dbnode_t **nodep,
176214928Stuexen					   dns_name_t *name);
177214928Stuexenstatic isc_result_t	dbiterator_pause(dns_dbiterator_t *iterator);
178214928Stuexenstatic isc_result_t	dbiterator_origin(dns_dbiterator_t *iterator,
179214928Stuexen					  dns_name_t *name);
180163953Srrs
181163953Srrsstatic dns_dbiteratormethods_t dbiterator_methods = {
182163953Srrs	dbiterator_destroy,
183171440Srrs	dbiterator_first,
184163953Srrs	dbiterator_last,
185163953Srrs	dbiterator_seek,
186171440Srrs	dbiterator_prev,
187163953Srrs	dbiterator_next,
188163953Srrs	dbiterator_current,
189171440Srrs	dbiterator_pause,
190171440Srrs	dbiterator_origin
191171440Srrs};
192171440Srrs
193163953Srrsstatic void		rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
194163953Srrsstatic isc_result_t	rdatasetiter_first(dns_rdatasetiter_t *iterator);
195163953Srrsstatic isc_result_t	rdatasetiter_next(dns_rdatasetiter_t *iterator);
196163953Srrsstatic void		rdatasetiter_current(dns_rdatasetiter_t *iterator,
197171440Srrs					     dns_rdataset_t *rdataset);
198171440Srrs
199171440Srrsstatic dns_rdatasetitermethods_t rdatasetiter_methods = {
200171440Srrs	rdatasetiter_destroy,
201171440Srrs	rdatasetiter_first,
202171440Srrs	rdatasetiter_next,
203171440Srrs	rdatasetiter_current
204171440Srrs};
205171440Srrs
206163953Srrs/*
207171440Srrs * Functions used by implementors of simple databases
208171440Srrs */
209171440Srrsisc_result_t
210171440Srrsdns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
211163953Srrs		 void *driverdata, unsigned int flags, isc_mem_t *mctx,
212171440Srrs		 dns_sdbimplementation_t **sdbimp)
213171440Srrs{
214171440Srrs	dns_sdbimplementation_t *imp;
215171440Srrs	isc_result_t result;
216171440Srrs
217171440Srrs	REQUIRE(drivername != NULL);
218171440Srrs	REQUIRE(methods != NULL);
219171440Srrs	REQUIRE(methods->lookup != NULL);
220171440Srrs	REQUIRE(mctx != NULL);
221171440Srrs	REQUIRE(sdbimp != NULL && *sdbimp == NULL);
222171440Srrs	REQUIRE((flags & ~(DNS_SDBFLAG_RELATIVEOWNER |
223171440Srrs			   DNS_SDBFLAG_RELATIVERDATA |
224171440Srrs			   DNS_SDBFLAG_THREADSAFE)) == 0);
225171440Srrs
226171440Srrs	imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t));
227171440Srrs	if (imp == NULL)
228171440Srrs		return (ISC_R_NOMEMORY);
229171440Srrs	imp->methods = methods;
230171440Srrs	imp->driverdata = driverdata;
231171440Srrs	imp->flags = flags;
232171440Srrs	imp->mctx = NULL;
233171440Srrs	isc_mem_attach(mctx, &imp->mctx);
234171440Srrs	result = isc_mutex_init(&imp->driverlock);
235171440Srrs	if (result != ISC_R_SUCCESS)
236171440Srrs		goto cleanup_mctx;
237171440Srrs
238171440Srrs	imp->dbimp = NULL;
239171440Srrs	result = dns_db_register(drivername, dns_sdb_create, imp, mctx,
240171440Srrs				 &imp->dbimp);
241171440Srrs	if (result != ISC_R_SUCCESS)
242171440Srrs		goto cleanup_mutex;
243171440Srrs	*sdbimp = imp;
244171440Srrs
245171440Srrs	return (ISC_R_SUCCESS);
246171440Srrs
247171440Srrs cleanup_mutex:
248171440Srrs	DESTROYLOCK(&imp->driverlock);
249171440Srrs cleanup_mctx:
250171440Srrs	isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
251171440Srrs	return (result);
252171440Srrs}
253171440Srrs
254171440Srrsvoid
255171440Srrsdns_sdb_unregister(dns_sdbimplementation_t **sdbimp) {
256171440Srrs	dns_sdbimplementation_t *imp;
257171440Srrs	isc_mem_t *mctx;
258171440Srrs
259171440Srrs	REQUIRE(sdbimp != NULL && *sdbimp != NULL);
260171440Srrs
261171440Srrs	imp = *sdbimp;
262171440Srrs	dns_db_unregister(&imp->dbimp);
263171440Srrs	DESTROYLOCK(&imp->driverlock);
264171440Srrs
265171440Srrs	mctx = imp->mctx;
266171440Srrs	isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
267171440Srrs	isc_mem_detach(&mctx);
268171440Srrs
269171440Srrs	*sdbimp = NULL;
270171440Srrs}
271171440Srrs
272171440Srrsstatic inline unsigned int
273171440Srrsinitial_size(unsigned int len) {
274171440Srrs	unsigned int size;
275171440Srrs
276171440Srrs	for (size = 1024; size < (64 * 1024); size *= 2)
277171440Srrs		if (len < size)
278171440Srrs			return (size);
279171440Srrs	return (65535);
280171440Srrs}
281171440Srrs
282171440Srrsisc_result_t
283171440Srrsdns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval, dns_ttl_t ttl,
284171440Srrs		 const unsigned char *rdatap, unsigned int rdlen)
285171440Srrs{
286171440Srrs	dns_rdatalist_t *rdatalist;
287171440Srrs	dns_rdata_t *rdata;
288180387Srrs	isc_buffer_t *rdatabuf = NULL;
289171440Srrs	isc_result_t result;
290171440Srrs	isc_mem_t *mctx;
291171440Srrs	isc_region_t region;
292171440Srrs
293171440Srrs	mctx = lookup->sdb->common.mctx;
294171440Srrs
295171440Srrs	rdatalist = ISC_LIST_HEAD(lookup->lists);
296171440Srrs	while (rdatalist != NULL) {
297171440Srrs		if (rdatalist->type == typeval)
298171440Srrs			break;
299171440Srrs		rdatalist = ISC_LIST_NEXT(rdatalist, link);
300171440Srrs	}
301171440Srrs
302171440Srrs	if (rdatalist == NULL) {
303171440Srrs		rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
304171440Srrs		if (rdatalist == NULL)
305171440Srrs			return (ISC_R_NOMEMORY);
306171440Srrs		rdatalist->rdclass = lookup->sdb->common.rdclass;
307171440Srrs		rdatalist->type = typeval;
308214928Stuexen		rdatalist->covers = 0;
309163953Srrs		rdatalist->ttl = ttl;
310163953Srrs		ISC_LIST_INIT(rdatalist->rdata);
311163953Srrs		ISC_LINK_INIT(rdatalist, link);
312163953Srrs		ISC_LIST_APPEND(lookup->lists, rdatalist, link);
313163953Srrs	} else
314163953Srrs		if (rdatalist->ttl != ttl)
315171440Srrs			return (DNS_R_BADTTL);
316171440Srrs
317171440Srrs	rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
318171440Srrs	if (rdata == NULL)
319163953Srrs		return (ISC_R_NOMEMORY);
320163953Srrs
321163953Srrs	result = isc_buffer_allocate(mctx, &rdatabuf, rdlen);
322163953Srrs	if (result != ISC_R_SUCCESS)
323163953Srrs		goto failure;
324163953Srrs	DE_CONST(rdatap, region.base);
325163953Srrs	region.length = rdlen;
326163953Srrs	isc_buffer_copyregion(rdatabuf, &region);
327163953Srrs	isc_buffer_usedregion(rdatabuf, &region);
328163953Srrs	dns_rdata_init(rdata);
329163953Srrs	dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type,
330163953Srrs			     &region);
331163953Srrs	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
332163953Srrs	ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
333163953Srrs	rdata = NULL;
334163953Srrs
335171440Srrs failure:
336171440Srrs	if (rdata != NULL)
337163953Srrs		isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
338163953Srrs	return (result);
339163953Srrs}
340171440Srrs
341171440Srrs
342163953Srrsisc_result_t
343163953Srrsdns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
344163953Srrs	      const char *data)
345163953Srrs{
346163953Srrs	unsigned int datalen;
347163953Srrs	dns_rdatatype_t typeval;
348163953Srrs	isc_textregion_t r;
349212225Srrs	isc_lex_t *lex = NULL;
350212225Srrs	isc_result_t result;
351212225Srrs	unsigned char *p = NULL;
352163953Srrs	unsigned int size = 0; /* Init to suppress compiler warning */
353163953Srrs	isc_mem_t *mctx;
354163953Srrs	dns_sdbimplementation_t *imp;
355163953Srrs	dns_name_t *origin;
356163953Srrs	isc_buffer_t b;
357163953Srrs	isc_buffer_t rb;
358163953Srrs
359163953Srrs	REQUIRE(VALID_SDBLOOKUP(lookup));
360163953Srrs	REQUIRE(type != NULL);
361212225Srrs	REQUIRE(data != NULL);
362212225Srrs
363212225Srrs	mctx = lookup->sdb->common.mctx;
364163953Srrs
365163953Srrs	DE_CONST(type, r.base);
366167598Srrs	r.length = strlen(type);
367167598Srrs	result = dns_rdatatype_fromtext(&typeval, &r);
368167598Srrs	if (result != ISC_R_SUCCESS)
369167598Srrs		return (result);
370163953Srrs
371163953Srrs	imp = lookup->sdb->implementation;
372214928Stuexen	if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
373214928Stuexen		origin = &lookup->sdb->common.origin;
374163953Srrs	else
375214928Stuexen		origin = dns_rootname;
376163953Srrs
377163953Srrs	result = isc_lex_create(mctx, 64, &lex);
378163953Srrs	if (result != ISC_R_SUCCESS)
379163953Srrs		goto failure;
380163953Srrs
381163953Srrs	datalen = strlen(data);
382163953Srrs	size = initial_size(datalen);
383163953Srrs	do {
384163953Srrs		isc_buffer_init(&b, data, datalen);
385163953Srrs		isc_buffer_add(&b, datalen);
386163953Srrs		result = isc_lex_openbuffer(lex, &b);
387163953Srrs		if (result != ISC_R_SUCCESS)
388212225Srrs			goto failure;
389212225Srrs
390212225Srrs		if (size >= 65535)
391163953Srrs			size = 65535;
392163953Srrs		p = isc_mem_get(mctx, size);
393163953Srrs		if (p == NULL) {
394163953Srrs			result = ISC_R_NOMEMORY;
395163953Srrs			goto failure;
396163953Srrs		}
397163953Srrs		isc_buffer_init(&rb, p, size);
398163953Srrs		result = dns_rdata_fromtext(NULL,
399169655Srrs					    lookup->sdb->common.rdclass,
400163953Srrs					    typeval, lex,
401163953Srrs					    origin, 0,
402163953Srrs					    mctx, &rb,
403163953Srrs					    &lookup->callbacks);
404163953Srrs		if (result != ISC_R_NOSPACE)
405163953Srrs			break;
406163953Srrs
407163953Srrs		/*
408163953Srrs		 * Is the RR too big?
409163953Srrs		 */
410163953Srrs		if (size >= 65535)
411163953Srrs			break;
412163953Srrs		isc_mem_put(mctx, p, size);
413163953Srrs		p = NULL;
414163953Srrs		size *= 2;
415163953Srrs	} while (result == ISC_R_NOSPACE);
416163953Srrs
417163953Srrs	if (result != ISC_R_SUCCESS)
418210599Srrs		goto failure;
419163953Srrs
420170642Srrs	result = dns_sdb_putrdata(lookup, typeval, ttl,
421170642Srrs				  isc_buffer_base(&rb),
422170642Srrs				  isc_buffer_usedlength(&rb));
423163953Srrs failure:
424163953Srrs	if (p != NULL)
425163953Srrs		isc_mem_put(mctx, p, size);
426163953Srrs	if (lex != NULL)
427210599Srrs		isc_lex_destroy(&lex);
428163953Srrs
429171440Srrs	return (result);
430171440Srrs}
431163953Srrs
432163953Srrsstatic isc_result_t
433163953Srrsgetnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) {
434184333Srrs	dns_name_t *newname, *origin;
435184333Srrs	dns_fixedname_t fnewname;
436182367Srrs	dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db;
437182367Srrs	dns_sdbimplementation_t *imp = sdb->implementation;
438216822Stuexen	dns_sdbnode_t *sdbnode;
439182367Srrs	isc_mem_t *mctx = sdb->common.mctx;
440182367Srrs	isc_buffer_t b;
441182367Srrs	isc_result_t result;
442216822Stuexen
443216825Stuexen	dns_fixedname_init(&fnewname);
444182367Srrs	newname = dns_fixedname_name(&fnewname);
445216822Stuexen
446182367Srrs	if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
447182367Srrs		origin = &sdb->common.origin;
448182367Srrs	else
449182367Srrs		origin = dns_rootname;
450182367Srrs	isc_buffer_init(&b, name, strlen(name));
451182367Srrs	isc_buffer_add(&b, strlen(name));
452182367Srrs
453182367Srrs	result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL);
454182367Srrs	if (result != ISC_R_SUCCESS)
455216822Stuexen		return (result);
456196260Stuexen
457182367Srrs	if (allnodes->common.relative_names) {
458182367Srrs		/* All names are relative to the root */
459182367Srrs		unsigned int nlabels = dns_name_countlabels(newname);
460182367Srrs		dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
461221627Stuexen	}
462182367Srrs
463182367Srrs	sdbnode = ISC_LIST_HEAD(allnodes->nodelist);
464182367Srrs	if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) {
465216822Stuexen		sdbnode = NULL;
466182367Srrs		result = createnode(sdb, &sdbnode);
467182367Srrs		if (result != ISC_R_SUCCESS)
468182367Srrs			return (result);
469182367Srrs		sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t));
470184333Srrs		if (sdbnode->name == NULL) {
471184333Srrs			destroynode(sdbnode);
472163953Srrs			return (ISC_R_NOMEMORY);
473163953Srrs		}
474163953Srrs		dns_name_init(sdbnode->name, NULL);
475163953Srrs		result = dns_name_dup(newname, mctx, sdbnode->name);
476163953Srrs		if (result != ISC_R_SUCCESS) {
477210599Srrs			isc_mem_put(mctx, sdbnode->name, sizeof(dns_name_t));
478210599Srrs			destroynode(sdbnode);
479163953Srrs			return (result);
480163953Srrs		}
481163953Srrs		ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link);
482163953Srrs		if (allnodes->origin == NULL &&
483163953Srrs		    dns_name_equal(newname, &sdb->common.origin))
484163953Srrs			allnodes->origin = sdbnode;
485163953Srrs	}
486163953Srrs	*nodep = sdbnode;
487216822Stuexen	return (ISC_R_SUCCESS);
488163953Srrs}
489163953Srrs
490219014Stuexenisc_result_t
491210599Srrsdns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name,
492168709Srrs		   const char *type, dns_ttl_t ttl, const char *data)
493163953Srrs{
494168709Srrs	isc_result_t result;
495163953Srrs	dns_sdbnode_t *sdbnode = NULL;
496182367Srrs	result = getnode(allnodes, name, &sdbnode);
497163953Srrs	if (result != ISC_R_SUCCESS)
498171440Srrs		return (result);
499163953Srrs	return (dns_sdb_putrr(sdbnode, type, ttl, data));
500163953Srrs}
501163953Srrs
502163953Srrsisc_result_t
503163953Srrsdns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name,
504163953Srrs		      dns_rdatatype_t type, dns_ttl_t ttl,
505163953Srrs		      const void *rdata, unsigned int rdlen)
506169378Srrs{
507163953Srrs	isc_result_t result;
508219014Stuexen	dns_sdbnode_t *sdbnode = NULL;
509219014Stuexen	result = getnode(allnodes, name, &sdbnode);
510224641Stuexen	if (result != ISC_R_SUCCESS)
511219014Stuexen		return (result);
512170744Srrs	return (dns_sdb_putrdata(sdbnode, type, ttl, rdata, rdlen));
513170744Srrs}
514170744Srrs
515224641Stuexenisc_result_t
516170744Srrsdns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
517170744Srrs	       isc_uint32_t serial)
518219014Stuexen{
519219014Stuexen	char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
520163953Srrs	int n;
521163953Srrs
522163953Srrs	REQUIRE(mname != NULL);
523163953Srrs	REQUIRE(rname != NULL);
524163953Srrs
525163953Srrs	n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u",
526163953Srrs		     mname, rname, serial,
527163953Srrs		     SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY,
528163953Srrs		     SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM);
529163953Srrs	if (n >= (int)sizeof(str) || n < 0)
530163953Srrs		return (ISC_R_NOSPACE);
531224641Stuexen	return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));
532219014Stuexen}
533170744Srrs
534170744Srrs/*
535163953Srrs * DB routines
536163953Srrs */
537163953Srrs
538163953Srrsstatic void
539163953Srrsattach(dns_db_t *source, dns_db_t **targetp) {
540168709Srrs	dns_sdb_t *sdb = (dns_sdb_t *) source;
541168709Srrs
542163953Srrs	REQUIRE(VALID_SDB(sdb));
543163953Srrs
544210599Srrs	LOCK(&sdb->lock);
545163953Srrs	REQUIRE(sdb->references > 0);
546163953Srrs	sdb->references++;
547184333Srrs	UNLOCK(&sdb->lock);
548182367Srrs
549184333Srrs	*targetp = source;
550216822Stuexen}
551216825Stuexen
552163953Srrsstatic void
553182367Srrsdestroy(dns_sdb_t *sdb) {
554182367Srrs	isc_mem_t *mctx;
555182367Srrs	dns_sdbimplementation_t *imp = sdb->implementation;
556182367Srrs
557182367Srrs	mctx = sdb->common.mctx;
558182367Srrs
559182367Srrs	if (imp->methods->destroy != NULL) {
560182367Srrs		MAYBE_LOCK(sdb);
561182367Srrs		imp->methods->destroy(sdb->zone, imp->driverdata,
562182367Srrs				      &sdb->dbdata);
563182367Srrs		MAYBE_UNLOCK(sdb);
564182367Srrs	}
565182367Srrs
566182367Srrs	isc_mem_free(mctx, sdb->zone);
567163953Srrs	DESTROYLOCK(&sdb->lock);
568163953Srrs
569163953Srrs	sdb->common.magic = 0;
570163953Srrs	sdb->common.impmagic = 0;
571163953Srrs
572163953Srrs	dns_name_free(&sdb->common.origin, mctx);
573163953Srrs
574163953Srrs	isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
575163953Srrs	isc_mem_detach(&mctx);
576163953Srrs}
577163953Srrs
578224641Stuexenstatic void
579170744Srrsdetach(dns_db_t **dbp) {
580170744Srrs	dns_sdb_t *sdb = (dns_sdb_t *)(*dbp);
581170744Srrs	isc_boolean_t need_destroy = ISC_FALSE;
582170744Srrs
583170744Srrs	REQUIRE(VALID_SDB(sdb));
584163953Srrs	LOCK(&sdb->lock);
585163953Srrs	REQUIRE(sdb->references > 0);
586163953Srrs	sdb->references--;
587163953Srrs	if (sdb->references == 0)
588163953Srrs		need_destroy = ISC_TRUE;
589163953Srrs	UNLOCK(&sdb->lock);
590224641Stuexen
591170744Srrs	if (need_destroy)
592170744Srrs		destroy(sdb);
593170744Srrs
594170744Srrs	*dbp = NULL;
595170744Srrs}
596163953Srrs
597163953Srrsstatic isc_result_t
598163953Srrsbeginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
599163953Srrs	UNUSED(db);
600163953Srrs	UNUSED(addp);
601163953Srrs	UNUSED(dbloadp);
602163953Srrs	return (ISC_R_NOTIMPLEMENTED);
603163953Srrs}
604163953Srrs
605163953Srrsstatic isc_result_t
606163953Srrsendload(dns_db_t *db, dns_dbload_t **dbloadp) {
607163953Srrs	UNUSED(db);
608163953Srrs	UNUSED(dbloadp);
609163953Srrs	return (ISC_R_NOTIMPLEMENTED);
610163953Srrs}
611196260Stuexen
612163953Srrsstatic isc_result_t
613212801Stuexendump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
614163953Srrs     dns_masterformat_t masterformat) {
615163953Srrs	UNUSED(db);
616169420Srrs	UNUSED(version);
617163953Srrs	UNUSED(filename);
618163953Srrs	UNUSED(masterformat);
619189790Srrs	return (ISC_R_NOTIMPLEMENTED);
620210599Srrs}
621163953Srrs
622185694Srrsstatic void
623163953Srrscurrentversion(dns_db_t *db, dns_dbversion_t **versionp) {
624163953Srrs	REQUIRE(versionp != NULL && *versionp == NULL);
625196260Stuexen
626163953Srrs	UNUSED(db);
627163953Srrs
628163953Srrs	*versionp = (void *) &dummy;
629169420Srrs	return;
630163953Srrs}
631163953Srrs
632189790Srrsstatic isc_result_t
633210599Srrsnewversion(dns_db_t *db, dns_dbversion_t **versionp) {
634163953Srrs	UNUSED(db);
635185694Srrs	UNUSED(versionp);
636163953Srrs
637163953Srrs	return (ISC_R_NOTIMPLEMENTED);
638168709Srrs}
639163953Srrs
640163953Srrsstatic void
641163953Srrsattachversion(dns_db_t *db, dns_dbversion_t *source,
642163953Srrs	      dns_dbversion_t **targetp)
643163953Srrs{
644163953Srrs	REQUIRE(source != NULL && source == (void *) &dummy);
645163953Srrs	REQUIRE(targetp != NULL && *targetp == NULL);
646224641Stuexen
647170744Srrs	UNUSED(db);
648170744Srrs	*targetp = source;
649170744Srrs	return;
650168709Srrs}
651168709Srrs
652168709Srrsstatic void
653168709Srrscloseversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
654168709Srrs	REQUIRE(versionp != NULL && *versionp == (void *) &dummy);
655168709Srrs	REQUIRE(commit == ISC_FALSE);
656168709Srrs
657179783Srrs	UNUSED(db);
658170744Srrs	UNUSED(commit);
659170744Srrs
660170744Srrs	*versionp = NULL;
661170744Srrs}
662170744Srrs
663170744Srrsstatic isc_result_t
664168709Srrscreatenode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) {
665168709Srrs	dns_sdbnode_t *node;
666168709Srrs	isc_result_t result;
667179783Srrs
668163953Srrs	node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t));
669163953Srrs	if (node == NULL)
670163953Srrs		return (ISC_R_NOMEMORY);
671165220Srrs
672163953Srrs	node->sdb = NULL;
673163953Srrs	attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb);
674163953Srrs	ISC_LIST_INIT(node->lists);
675219397Srrs	ISC_LIST_INIT(node->buffers);
676219397Srrs	ISC_LINK_INIT(node, link);
677219397Srrs	node->name = NULL;
678219397Srrs	result = isc_mutex_init(&node->lock);
679219397Srrs	if (result != ISC_R_SUCCESS) {
680219397Srrs		isc_mem_put(sdb->common.mctx, node, sizeof(dns_sdbnode_t));
681163953Srrs		return (result);
682163953Srrs	}
683163953Srrs	dns_rdatacallbacks_init(&node->callbacks);
684163953Srrs	node->references = 1;
685163953Srrs	node->magic = SDBLOOKUP_MAGIC;
686163953Srrs
687163953Srrs	*nodep = node;
688163953Srrs	return (ISC_R_SUCCESS);
689163953Srrs}
690163953Srrs
691163953Srrsstatic void
692163953Srrsdestroynode(dns_sdbnode_t *node) {
693163953Srrs	dns_rdatalist_t *list;
694163953Srrs	dns_rdata_t *rdata;
695170181Srrs	isc_buffer_t *b;
696170181Srrs	dns_sdb_t *sdb;
697170181Srrs	isc_mem_t *mctx;
698216669Stuexen
699163953Srrs	sdb = node->sdb;
700163953Srrs	mctx = sdb->common.mctx;
701210599Srrs
702163953Srrs	while (!ISC_LIST_EMPTY(node->lists)) {
703163953Srrs		list = ISC_LIST_HEAD(node->lists);
704163953Srrs		while (!ISC_LIST_EMPTY(list->rdata)) {
705210599Srrs			rdata = ISC_LIST_HEAD(list->rdata);
706163953Srrs			ISC_LIST_UNLINK(list->rdata, rdata, link);
707163953Srrs			isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
708163953Srrs		}
709163953Srrs		ISC_LIST_UNLINK(node->lists, list, link);
710163953Srrs		isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
711168709Srrs	}
712168709Srrs
713168709Srrs	while (!ISC_LIST_EMPTY(node->buffers)) {
714168709Srrs		b = ISC_LIST_HEAD(node->buffers);
715224641Stuexen		ISC_LIST_UNLINK(node->buffers, b, link);
716170744Srrs		isc_buffer_free(&b);
717170744Srrs	}
718163953Srrs
719169420Srrs	if (node->name != NULL) {
720169420Srrs		dns_name_free(node->name, mctx);
721169420Srrs		isc_mem_put(mctx, node->name, sizeof(dns_name_t));
722169420Srrs	}
723169420Srrs	DESTROYLOCK(&node->lock);
724169420Srrs	node->magic = 0;
725169420Srrs	isc_mem_put(mctx, node, sizeof(dns_sdbnode_t));
726169420Srrs	detach((dns_db_t **) (void *)&sdb);
727169420Srrs}
728169420Srrs
729163953Srrsstatic isc_result_t
730163953Srrsfindnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
731163953Srrs	 dns_dbnode_t **nodep)
732210599Srrs{
733210493Srrs	dns_sdb_t *sdb = (dns_sdb_t *)db;
734210493Srrs	dns_sdbnode_t *node = NULL;
735210493Srrs	isc_result_t result;
736210493Srrs	isc_buffer_t b;
737210493Srrs	char namestr[DNS_NAME_MAXTEXT + 1];
738210493Srrs	isc_boolean_t isorigin;
739210493Srrs	dns_sdbimplementation_t *imp;
740210493Srrs
741210493Srrs	REQUIRE(VALID_SDB(sdb));
742210493Srrs	REQUIRE(create == ISC_FALSE);
743210493Srrs	REQUIRE(nodep != NULL && *nodep == NULL);
744210493Srrs
745210493Srrs	UNUSED(name);
746210493Srrs	UNUSED(create);
747210493Srrs
748210493Srrs	imp = sdb->implementation;
749210493Srrs
750210493Srrs	isc_buffer_init(&b, namestr, sizeof(namestr));
751210493Srrs	if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
752210493Srrs		dns_name_t relname;
753210599Srrs		unsigned int labels;
754163953Srrs
755163953Srrs		labels = dns_name_countlabels(name) -
756163953Srrs			 dns_name_countlabels(&db->origin);
757163953Srrs		dns_name_init(&relname, NULL);
758163953Srrs		dns_name_getlabelsequence(name, 0, labels, &relname);
759163953Srrs		result = dns_name_totext(&relname, ISC_TRUE, &b);
760210599Srrs		if (result != ISC_R_SUCCESS)
761163953Srrs			return (result);
762165220Srrs	} else {
763171477Srrs		result = dns_name_totext(name, ISC_TRUE, &b);
764171477Srrs		if (result != ISC_R_SUCCESS)
765163953Srrs			return (result);
766163953Srrs	}
767163953Srrs	isc_buffer_putuint8(&b, 0);
768163953Srrs
769163953Srrs	result = createnode(sdb, &node);
770163953Srrs	if (result != ISC_R_SUCCESS)
771169420Srrs		return (result);
772169420Srrs
773169420Srrs	isorigin = dns_name_equal(name, &sdb->common.origin);
774163953Srrs
775163953Srrs	MAYBE_LOCK(sdb);
776163953Srrs	result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata, node);
777163953Srrs	MAYBE_UNLOCK(sdb);
778163953Srrs	if (result != ISC_R_SUCCESS &&
779169420Srrs	    !(result == ISC_R_NOTFOUND &&
780169420Srrs	      isorigin && imp->methods->authority != NULL))
781169420Srrs	{
782163953Srrs		destroynode(node);
783163953Srrs		return (result);
784163953Srrs	}
785179783Srrs
786170744Srrs	if (isorigin && imp->methods->authority != NULL) {
787170744Srrs		MAYBE_LOCK(sdb);
788170744Srrs		result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
789170744Srrs		MAYBE_UNLOCK(sdb);
790170744Srrs		if (result != ISC_R_SUCCESS) {
791170744Srrs			destroynode(node);
792168709Srrs			return (result);
793168709Srrs		}
794163953Srrs	}
795163953Srrs
796163953Srrs	*nodep = node;
797163953Srrs	return (ISC_R_SUCCESS);
798163953Srrs}
799163953Srrs
800163953Srrsstatic isc_result_t
801163953Srrsfind(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
802163953Srrs     dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
803163953Srrs     dns_dbnode_t **nodep, dns_name_t *foundname,
804163953Srrs     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
805163953Srrs{
806163953Srrs	dns_sdb_t *sdb = (dns_sdb_t *)db;
807163953Srrs	dns_dbnode_t *node = NULL;
808210599Srrs	dns_fixedname_t fname;
809163953Srrs	dns_rdataset_t xrdataset;
810179783Srrs	dns_name_t *xname;
811170744Srrs	unsigned int nlabels, olabels;
812170744Srrs	isc_result_t result;
813179783Srrs	unsigned int i;
814163953Srrs
815163953Srrs	REQUIRE(VALID_SDB(sdb));
816163953Srrs	REQUIRE(nodep == NULL || *nodep == NULL);
817163953Srrs	REQUIRE(version == NULL || version == (void *) &dummy);
818163953Srrs
819163953Srrs	UNUSED(options);
820163953Srrs	UNUSED(sdb);
821163953Srrs
822163953Srrs	if (!dns_name_issubdomain(name, &db->origin))
823163953Srrs		return (DNS_R_NXDOMAIN);
824163953Srrs
825163953Srrs	olabels = dns_name_countlabels(&db->origin);
826163953Srrs	nlabels = dns_name_countlabels(name);
827163953Srrs
828163953Srrs	dns_fixedname_init(&fname);
829163953Srrs	xname = dns_fixedname_name(&fname);
830163953Srrs
831163953Srrs	if (rdataset == NULL) {
832168709Srrs		dns_rdataset_init(&xrdataset);
833163953Srrs		rdataset = &xrdataset;
834163953Srrs	}
835163953Srrs
836163953Srrs	result = DNS_R_NXDOMAIN;
837163953Srrs
838163953Srrs	for (i = olabels; i <= nlabels; i++) {
839163953Srrs		/*
840163953Srrs		 * Unless this is an explicit lookup at the origin, don't
841163953Srrs		 * look at the origin.
842163953Srrs		 */
843163953Srrs		if (i == olabels && i != nlabels)
844163953Srrs			continue;
845169378Srrs
846163953Srrs		/*
847163953Srrs		 * Look up the next label.
848163953Srrs		 */
849163953Srrs		dns_name_getlabelsequence(name, nlabels - i, i, xname);
850163953Srrs		result = findnode(db, xname, ISC_FALSE, &node);
851224641Stuexen		if (result != ISC_R_SUCCESS) {
852224641Stuexen			result = DNS_R_NXDOMAIN;
853185694Srrs			continue;
854224641Stuexen		}
855224641Stuexen
856224641Stuexen		/*
857185694Srrs		 * Look for a DNAME at the current label, unless this is
858224641Stuexen		 * the qname.
859224641Stuexen		 */
860163953Srrs		if (i < nlabels) {
861163953Srrs			result = findrdataset(db, node, version,
862163953Srrs					      dns_rdatatype_dname,
863163953Srrs					      0, now, rdataset, sigrdataset);
864163953Srrs			if (result == ISC_R_SUCCESS) {
865163953Srrs				result = DNS_R_DNAME;
866163953Srrs				break;
867163953Srrs			}
868163953Srrs		}
869163953Srrs
870163953Srrs		/*
871163953Srrs		 * Look for an NS at the current label, unless this is the
872163953Srrs		 * origin or glue is ok.
873163953Srrs		 */
874163953Srrs		if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
875163953Srrs			result = findrdataset(db, node, version,
876224641Stuexen					      dns_rdatatype_ns,
877224641Stuexen					      0, now, rdataset, sigrdataset);
878224641Stuexen			if (result == ISC_R_SUCCESS) {
879224641Stuexen				if (i == nlabels && type == dns_rdatatype_any)
880224641Stuexen				{
881224641Stuexen					result = DNS_R_ZONECUT;
882224641Stuexen					dns_rdataset_disassociate(rdataset);
883224641Stuexen					if (sigrdataset != NULL &&
884224641Stuexen					    dns_rdataset_isassociated
885224641Stuexen							(sigrdataset)) {
886224641Stuexen						dns_rdataset_disassociate
887224641Stuexen								(sigrdataset);
888224641Stuexen					}
889224641Stuexen				} else
890224641Stuexen					result = DNS_R_DELEGATION;
891224641Stuexen				break;
892224641Stuexen			}
893224641Stuexen		}
894224641Stuexen
895224641Stuexen		/*
896224641Stuexen		 * If the current name is not the qname, add another label
897224641Stuexen		 * and try again.
898224641Stuexen		 */
899224641Stuexen		if (i < nlabels) {
900224641Stuexen			destroynode(node);
901224641Stuexen			node = NULL;
902224641Stuexen			continue;
903224641Stuexen		}
904224641Stuexen
905224641Stuexen		/*
906224641Stuexen		 * If we're looking for ANY, we're done.
907224641Stuexen		 */
908224641Stuexen		if (type == dns_rdatatype_any) {
909224641Stuexen			result = ISC_R_SUCCESS;
910224641Stuexen			break;
911224641Stuexen		}
912224641Stuexen
913224641Stuexen		/*
914224641Stuexen		 * Look for the qtype.
915224641Stuexen		 */
916224641Stuexen		result = findrdataset(db, node, version, type,
917224641Stuexen				      0, now, rdataset, sigrdataset);
918224641Stuexen		if (result == ISC_R_SUCCESS)
919224641Stuexen			break;
920224641Stuexen
921224641Stuexen		/*
922163953Srrs		 * Look for a CNAME
923212712Stuexen		 */
924169352Srrs		if (type != dns_rdatatype_cname) {
925169352Srrs			result = findrdataset(db, node, version,
926169352Srrs					      dns_rdatatype_cname,
927169352Srrs					      0, now, rdataset, sigrdataset);
928169352Srrs			if (result == ISC_R_SUCCESS) {
929169352Srrs				result = DNS_R_CNAME;
930169352Srrs				break;
931169352Srrs			}
932169352Srrs		}
933169352Srrs
934169352Srrs		result = DNS_R_NXRRSET;
935169352Srrs		break;
936169352Srrs	}
937169352Srrs
938169352Srrs	if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
939169352Srrs		dns_rdataset_disassociate(rdataset);
940163953Srrs
941163953Srrs	if (foundname != NULL) {
942163953Srrs		isc_result_t xresult;
943163953Srrs
944163953Srrs		xresult = dns_name_copy(xname, foundname, NULL);
945163953Srrs		if (xresult != ISC_R_SUCCESS) {
946163953Srrs			if (node != NULL)
947163953Srrs				destroynode(node);
948163953Srrs			if (dns_rdataset_isassociated(rdataset))
949224641Stuexen				dns_rdataset_disassociate(rdataset);
950224641Stuexen			return (DNS_R_BADDB);
951163953Srrs		}
952224641Stuexen	}
953224641Stuexen
954163953Srrs	if (nodep != NULL)
955163953Srrs		*nodep = node;
956163953Srrs	else if (node != NULL)
957163953Srrs		detachnode(db, &node);
958163953Srrs
959163953Srrs	return (result);
960163953Srrs}
961163953Srrs
962163953Srrsstatic isc_result_t
963163953Srrsfindzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
964163953Srrs	    isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
965163953Srrs	    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
966163953Srrs{
967163953Srrs	UNUSED(db);
968163953Srrs	UNUSED(name);
969163953Srrs	UNUSED(options);
970163953Srrs	UNUSED(now);
971163953Srrs	UNUSED(nodep);
972163953Srrs	UNUSED(foundname);
973216825Stuexen	UNUSED(rdataset);
974163953Srrs	UNUSED(sigrdataset);
975163953Srrs
976163953Srrs	return (ISC_R_NOTIMPLEMENTED);
977163953Srrs}
978163953Srrs
979163953Srrsstatic void
980163953Srrsattachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
981179783Srrs	dns_sdb_t *sdb = (dns_sdb_t *)db;
982170744Srrs	dns_sdbnode_t *node = (dns_sdbnode_t *)source;
983170744Srrs
984163953Srrs	REQUIRE(VALID_SDB(sdb));
985163953Srrs
986163953Srrs	UNUSED(sdb);
987163953Srrs
988163953Srrs	LOCK(&node->lock);
989163953Srrs	INSIST(node->references > 0);
990163953Srrs	node->references++;
991163953Srrs	INSIST(node->references != 0);		/* Catch overflow. */
992163953Srrs	UNLOCK(&node->lock);
993163953Srrs
994163953Srrs	*targetp = source;
995163953Srrs}
996163953Srrs
997163953Srrsstatic void
998163953Srrsdetachnode(dns_db_t *db, dns_dbnode_t **targetp) {
999172090Srrs	dns_sdb_t *sdb = (dns_sdb_t *)db;
1000163953Srrs	dns_sdbnode_t *node;
1001163953Srrs	isc_boolean_t need_destroy = ISC_FALSE;
1002163953Srrs
1003163953Srrs	REQUIRE(VALID_SDB(sdb));
1004163953Srrs	REQUIRE(targetp != NULL && *targetp != NULL);
1005163953Srrs
1006163953Srrs	UNUSED(sdb);
1007163953Srrs
1008163953Srrs	node = (dns_sdbnode_t *)(*targetp);
1009163953Srrs
1010163953Srrs	LOCK(&node->lock);
1011210599Srrs	INSIST(node->references > 0);
1012163953Srrs	node->references--;
1013163953Srrs	if (node->references == 0)
1014163953Srrs		need_destroy = ISC_TRUE;
1015163953Srrs	UNLOCK(&node->lock);
1016163953Srrs
1017163953Srrs	if (need_destroy)
1018163953Srrs		destroynode(node);
1019163953Srrs
1020214928Stuexen	*targetp = NULL;
1021212712Stuexen}
1022163953Srrs
1023163953Srrsstatic isc_result_t
1024163953Srrsexpirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
1025163953Srrs	UNUSED(db);
1026172090Srrs	UNUSED(node);
1027163953Srrs	UNUSED(now);
1028163953Srrs	INSIST(0);
1029163953Srrs	return (ISC_R_UNEXPECTED);
1030163953Srrs}
1031163953Srrs
1032163953Srrsstatic void
1033163953Srrsprintnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
1034163953Srrs	UNUSED(db);
1035163953Srrs	UNUSED(node);
1036163953Srrs	UNUSED(out);
1037163953Srrs	return;
1038231038Stuexen}
1039163953Srrs
1040163953Srrsstatic isc_result_t
1041163953Srrscreateiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
1042163953Srrs{
1043163953Srrs	dns_sdb_t *sdb = (dns_sdb_t *)db;
1044163953Srrs	sdb_dbiterator_t *sdbiter;
1045163953Srrs	dns_sdbimplementation_t *imp = sdb->implementation;
1046163953Srrs	isc_result_t result;
1047163953Srrs
1048163953Srrs	REQUIRE(VALID_SDB(sdb));
1049163953Srrs
1050163953Srrs	if (imp->methods->allnodes == NULL)
1051163953Srrs		return (ISC_R_NOTIMPLEMENTED);
1052163953Srrs
1053163953Srrs	if ((options & DNS_DB_NSEC3ONLY) != 0 ||
1054163953Srrs	    (options & DNS_DB_NONSEC3) != 0)
1055163953Srrs		return (ISC_R_NOTIMPLEMENTED);
1056163953Srrs
1057163953Srrs	sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t));
1058163953Srrs	if (sdbiter == NULL)
1059163953Srrs		return (ISC_R_NOMEMORY);
1060165647Srrs
1061163953Srrs	sdbiter->common.methods = &dbiterator_methods;
1062163953Srrs	sdbiter->common.db = NULL;
1063163953Srrs	dns_db_attach(db, &sdbiter->common.db);
1064165647Srrs	sdbiter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
1065163953Srrs	sdbiter->common.magic = DNS_DBITERATOR_MAGIC;
1066171440Srrs	ISC_LIST_INIT(sdbiter->nodelist);
1067163953Srrs	sdbiter->current = NULL;
1068171440Srrs	sdbiter->origin = NULL;
1069163953Srrs
1070172090Srrs	MAYBE_LOCK(sdb);
1071163953Srrs	result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter);
1072165220Srrs	MAYBE_UNLOCK(sdb);
1073163953Srrs	if (result != ISC_R_SUCCESS) {
1074163953Srrs		dbiterator_destroy((dns_dbiterator_t **) (void *)&sdbiter);
1075169420Srrs		return (result);
1076163953Srrs	}
1077163953Srrs
1078163953Srrs	if (sdbiter->origin != NULL) {
1079163953Srrs		ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link);
1080163953Srrs		ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link);
1081163953Srrs	}
1082163953Srrs
1083163953Srrs	*iteratorp = (dns_dbiterator_t *)sdbiter;
1084163953Srrs
1085163953Srrs	return (ISC_R_SUCCESS);
1086163953Srrs}
1087163953Srrs
1088163953Srrsstatic isc_result_t
1089163953Srrsfindrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1090163953Srrs	     dns_rdatatype_t type, dns_rdatatype_t covers,
1091163953Srrs	     isc_stdtime_t now, dns_rdataset_t *rdataset,
1092210599Srrs	     dns_rdataset_t *sigrdataset)
1093163953Srrs{
1094163953Srrs	dns_rdatalist_t *list;
1095163953Srrs	dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
1096163953Srrs
1097163953Srrs	REQUIRE(VALID_SDBNODE(node));
1098163953Srrs
1099163953Srrs	UNUSED(db);
1100163953Srrs	UNUSED(version);
1101163953Srrs	UNUSED(covers);
1102163953Srrs	UNUSED(now);
1103163953Srrs	UNUSED(sigrdataset);
1104163953Srrs
1105163953Srrs	if (type == dns_rdatatype_rrsig)
1106163953Srrs		return (ISC_R_NOTIMPLEMENTED);
1107163953Srrs
1108163953Srrs	list = ISC_LIST_HEAD(sdbnode->lists);
1109163953Srrs	while (list != NULL) {
1110163953Srrs		if (list->type == type)
1111163953Srrs			break;
1112163953Srrs		list = ISC_LIST_NEXT(list, link);
1113163953Srrs	}
1114163953Srrs	if (list == NULL)
1115163953Srrs		return (ISC_R_NOTFOUND);
1116163953Srrs
1117163953Srrs	list_tordataset(list, db, node, rdataset);
1118163953Srrs
1119163953Srrs	return (ISC_R_SUCCESS);
1120163953Srrs}
1121163953Srrs
1122163953Srrsstatic isc_result_t
1123169420Srrsallrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1124163953Srrs	     isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
1125163953Srrs{
1126163953Srrs	sdb_rdatasetiter_t *iterator;
1127163953Srrs
1128163953Srrs	REQUIRE(version == NULL || version == &dummy);
1129163953Srrs
1130163953Srrs	UNUSED(version);
1131163953Srrs	UNUSED(now);
1132163953Srrs
1133163953Srrs	iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t));
1134163953Srrs	if (iterator == NULL)
1135163953Srrs		return (ISC_R_NOMEMORY);
1136163953Srrs
1137210599Srrs	iterator->common.magic = DNS_RDATASETITER_MAGIC;
1138163953Srrs	iterator->common.methods = &rdatasetiter_methods;
1139163953Srrs	iterator->common.db = db;
1140163953Srrs	iterator->common.node = NULL;
1141163953Srrs	attachnode(db, node, &iterator->common.node);
1142163953Srrs	iterator->common.version = version;
1143163953Srrs	iterator->common.now = now;
1144163953Srrs
1145163953Srrs	*iteratorp = (dns_rdatasetiter_t *)iterator;
1146163953Srrs
1147163953Srrs	return (ISC_R_SUCCESS);
1148163953Srrs}
1149163953Srrs
1150163953Srrsstatic isc_result_t
1151163953Srrsaddrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1152163953Srrs	    isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
1153163953Srrs	    dns_rdataset_t *addedrdataset)
1154163953Srrs{
1155163953Srrs	UNUSED(db);
1156224641Stuexen	UNUSED(node);
1157163953Srrs	UNUSED(version);
1158163953Srrs	UNUSED(now);
1159163953Srrs	UNUSED(rdataset);
1160163953Srrs	UNUSED(options);
1161212712Stuexen	UNUSED(addedrdataset);
1162163953Srrs
1163163953Srrs	return (ISC_R_NOTIMPLEMENTED);
1164163953Srrs}
1165163953Srrs
1166163953Srrsstatic isc_result_t
1167163953Srrssubtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1168163953Srrs		 dns_rdataset_t *rdataset, unsigned int options,
1169163953Srrs		 dns_rdataset_t *newrdataset)
1170163953Srrs{
1171163953Srrs	UNUSED(db);
1172163953Srrs	UNUSED(node);
1173163953Srrs	UNUSED(version);
1174163953Srrs	UNUSED(rdataset);
1175163953Srrs	UNUSED(options);
1176163953Srrs	UNUSED(newrdataset);
1177163953Srrs
1178216822Stuexen	return (ISC_R_NOTIMPLEMENTED);
1179163953Srrs}
1180171572Srrs
1181179157Srrsstatic isc_result_t
1182163953Srrsdeleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1183172190Srrs	       dns_rdatatype_t type, dns_rdatatype_t covers)
1184163953Srrs{
1185171572Srrs	UNUSED(db);
1186171572Srrs	UNUSED(node);
1187171572Srrs	UNUSED(version);
1188163953Srrs	UNUSED(type);
1189163953Srrs	UNUSED(covers);
1190179157Srrs
1191163953Srrs	return (ISC_R_NOTIMPLEMENTED);
1192163953Srrs}
1193163953Srrs
1194163953Srrsstatic isc_boolean_t
1195163953Srrsissecure(dns_db_t *db) {
1196163953Srrs	UNUSED(db);
1197163953Srrs
1198163953Srrs	return (ISC_FALSE);
1199163953Srrs}
1200163953Srrs
1201163953Srrsstatic unsigned int
1202171572Srrsnodecount(dns_db_t *db) {
1203171572Srrs	UNUSED(db);
1204171572Srrs
1205171572Srrs	return (0);
1206171572Srrs}
1207163953Srrs
1208169420Srrsstatic isc_boolean_t
1209163953Srrsispersistent(dns_db_t *db) {
1210163953Srrs	UNUSED(db);
1211163953Srrs	return (ISC_TRUE);
1212163953Srrs}
1213171572Srrs
1214171572Srrsstatic void
1215163953Srrsovermem(dns_db_t *db, isc_boolean_t overmem) {
1216210599Srrs	UNUSED(db);
1217163953Srrs	UNUSED(overmem);
1218179157Srrs}
1219179157Srrs
1220179157Srrsstatic void
1221179157Srrssettask(dns_db_t *db, isc_task_t *task) {
1222179157Srrs	UNUSED(db);
1223171572Srrs	UNUSED(task);
1224163953Srrs}
1225163953Srrs
1226163953Srrs
1227163953Srrsstatic dns_dbmethods_t sdb_methods = {
1228163953Srrs	attach,
1229163953Srrs	detach,
1230163953Srrs	beginload,
1231163953Srrs	endload,
1232163953Srrs	dump,
1233163953Srrs	currentversion,
1234163953Srrs	newversion,
1235163953Srrs	attachversion,
1236216822Stuexen	closeversion,
1237179157Srrs	findnode,
1238179157Srrs	find,
1239179157Srrs	findzonecut,
1240179157Srrs	attachnode,
1241179157Srrs	detachnode,
1242179157Srrs	expirenode,
1243179157Srrs	printnode,
1244179157Srrs	createiterator,
1245179157Srrs	findrdataset,
1246224641Stuexen	allrdatasets,
1247163953Srrs	addrdataset,
1248163953Srrs	subtractrdataset,
1249171572Srrs	deleterdataset,
1250163953Srrs	issecure,
1251212712Stuexen	nodecount,
1252163953Srrs	ispersistent,
1253163953Srrs	overmem,
1254163953Srrs	settask,
1255163953Srrs	NULL,
1256163953Srrs	NULL,
1257179157Srrs	NULL,
1258179157Srrs	NULL,
1259179157Srrs	NULL,
1260163953Srrs	NULL,
1261163953Srrs	NULL,
1262163953Srrs	NULL,
1263163953Srrs	NULL
1264172091Srrs};
1265172156Srrs
1266172091Srrsstatic isc_result_t
1267231038Stuexendns_sdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
1268172091Srrs	       dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
1269172091Srrs	       void *driverarg, dns_db_t **dbp)
1270172091Srrs{
1271172091Srrs	dns_sdb_t *sdb;
1272172156Srrs	isc_result_t result;
1273172091Srrs	char zonestr[DNS_NAME_MAXTEXT + 1];
1274172091Srrs	isc_buffer_t b;
1275172091Srrs	dns_sdbimplementation_t *imp;
1276172091Srrs
1277172091Srrs	REQUIRE(driverarg != NULL);
1278172091Srrs
1279172156Srrs	imp = driverarg;
1280172091Srrs
1281172091Srrs	if (type != dns_dbtype_zone)
1282163953Srrs		return (ISC_R_NOTIMPLEMENTED);
1283163953Srrs
1284163953Srrs	sdb = isc_mem_get(mctx, sizeof(dns_sdb_t));
1285163953Srrs	if (sdb == NULL)
1286214928Stuexen		return (ISC_R_NOMEMORY);
1287163953Srrs	memset(sdb, 0, sizeof(dns_sdb_t));
1288163953Srrs
1289163953Srrs	dns_name_init(&sdb->common.origin, NULL);
1290163953Srrs	sdb->common.attributes = 0;
1291163953Srrs	sdb->common.methods = &sdb_methods;
1292163953Srrs	sdb->common.rdclass = rdclass;
1293163953Srrs	sdb->common.mctx = NULL;
1294163953Srrs	sdb->implementation = imp;
1295163953Srrs
1296163953Srrs	isc_mem_attach(mctx, &sdb->common.mctx);
1297163953Srrs
1298163953Srrs	result = isc_mutex_init(&sdb->lock);
1299214928Stuexen	if (result != ISC_R_SUCCESS)
1300163953Srrs		goto cleanup_mctx;
1301163953Srrs
1302163953Srrs	result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
1303163953Srrs	if (result != ISC_R_SUCCESS)
1304214928Stuexen		goto cleanup_lock;
1305214928Stuexen
1306163953Srrs	isc_buffer_init(&b, zonestr, sizeof(zonestr));
1307163953Srrs	result = dns_name_totext(origin, ISC_TRUE, &b);
1308163953Srrs	if (result != ISC_R_SUCCESS)
1309163953Srrs		goto cleanup_origin;
1310163953Srrs	isc_buffer_putuint8(&b, 0);
1311163953Srrs
1312163953Srrs	sdb->zone = isc_mem_strdup(mctx, zonestr);
1313163953Srrs	if (sdb->zone == NULL) {
1314163953Srrs		result = ISC_R_NOMEMORY;
1315163953Srrs		goto cleanup_origin;
1316163953Srrs	}
1317163953Srrs
1318163953Srrs	sdb->dbdata = NULL;
1319163953Srrs	if (imp->methods->create != NULL) {
1320163953Srrs		MAYBE_LOCK(sdb);
1321163953Srrs		result = imp->methods->create(sdb->zone, argc, argv,
1322214928Stuexen					      imp->driverdata, &sdb->dbdata);
1323163953Srrs		MAYBE_UNLOCK(sdb);
1324163953Srrs		if (result != ISC_R_SUCCESS)
1325163953Srrs			goto cleanup_zonestr;
1326163953Srrs	}
1327163953Srrs
1328163953Srrs	sdb->references = 1;
1329163953Srrs
1330163953Srrs	sdb->common.magic = DNS_DB_MAGIC;
1331163953Srrs	sdb->common.impmagic = SDB_MAGIC;
1332163953Srrs
1333163953Srrs	*dbp = (dns_db_t *)sdb;
1334163953Srrs
1335163953Srrs	return (ISC_R_SUCCESS);
1336163953Srrs
1337163953Srrs cleanup_zonestr:
1338163953Srrs	isc_mem_free(mctx, sdb->zone);
1339217760Stuexen cleanup_origin:
1340163953Srrs	dns_name_free(&sdb->common.origin, mctx);
1341163953Srrs cleanup_lock:
1342163953Srrs	isc_mutex_destroy(&sdb->lock);
1343163953Srrs cleanup_mctx:
1344163953Srrs	isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
1345163953Srrs	isc_mem_detach(&mctx);
1346163953Srrs
1347163953Srrs	return (result);
1348163953Srrs}
1349169420Srrs
1350163953Srrs
1351163953Srrs/*
1352163953Srrs * Rdataset Methods
1353217760Stuexen */
1354218241Stuexen
1355218241Stuexenstatic void
1356218241Stuexendisassociate(dns_rdataset_t *rdataset) {
1357218241Stuexen	dns_dbnode_t *node = rdataset->private5;
1358218241Stuexen	dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
1359163953Srrs	dns_db_t *db = (dns_db_t *) sdbnode->sdb;
1360218241Stuexen
1361163953Srrs	detachnode(db, &node);
1362163953Srrs	isc__rdatalist_disassociate(rdataset);
1363163953Srrs}
1364163953Srrs
1365217760Stuexenstatic void
1366217760Stuexenrdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1367217760Stuexen	dns_dbnode_t *node = source->private5;
1368163953Srrs	dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
1369163953Srrs	dns_db_t *db = (dns_db_t *) sdbnode->sdb;
1370163953Srrs	dns_dbnode_t *tempdb = NULL;
1371163953Srrs
1372163953Srrs	isc__rdatalist_clone(source, target);
1373163953Srrs	attachnode(db, node, &tempdb);
1374163953Srrs	source->private5 = tempdb;
1375169420Srrs}
1376163953Srrs
1377163953Srrsstatic dns_rdatasetmethods_t methods = {
1378163953Srrs	disassociate,
1379163953Srrs	isc__rdatalist_first,
1380172090Srrs	isc__rdatalist_next,
1381163953Srrs	isc__rdatalist_current,
1382163953Srrs	rdataset_clone,
1383163953Srrs	isc__rdatalist_count,
1384163953Srrs	isc__rdatalist_addnoqname,
1385163953Srrs	isc__rdatalist_getnoqname,
1386163953Srrs	NULL,
1387163953Srrs	NULL,
1388169420Srrs	NULL,
1389163953Srrs	NULL,
1390163953Srrs	NULL
1391163953Srrs};
1392163953Srrs
1393169420Srrsstatic void
1394163953Srrslist_tordataset(dns_rdatalist_t *rdatalist,
1395163953Srrs		dns_db_t *db, dns_dbnode_t *node,
1396163953Srrs		dns_rdataset_t *rdataset)
1397163953Srrs{
1398163953Srrs	/*
1399163953Srrs	 * The sdb rdataset is an rdatalist with some additions.
1400163953Srrs	 *	- private1 & private2 are used by the rdatalist.
1401224641Stuexen	 *	- private3 & private 4 are unused.
1402163953Srrs	 *	- private5 is the node.
1403224641Stuexen	 */
1404171440Srrs
1405224641Stuexen	/* This should never fail. */
1406163953Srrs	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1407224641Stuexen		      ISC_R_SUCCESS);
1408224641Stuexen
1409224641Stuexen	rdataset->methods = &methods;
1410163953Srrs	dns_db_attachnode(db, node, &rdataset->private5);
1411167598Srrs}
1412167598Srrs
1413167598Srrs/*
1414167598Srrs * Database Iterator Methods
1415167598Srrs */
1416167598Srrsstatic void
1417167598Srrsdbiterator_destroy(dns_dbiterator_t **iteratorp) {
1418167598Srrs	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp);
1419167598Srrs	dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db;
1420210599Srrs
1421224641Stuexen	while (!ISC_LIST_EMPTY(sdbiter->nodelist)) {
1422224641Stuexen		dns_sdbnode_t *node;
1423224641Stuexen		node = ISC_LIST_HEAD(sdbiter->nodelist);
1424224641Stuexen		ISC_LIST_UNLINK(sdbiter->nodelist, node, link);
1425163953Srrs		destroynode(node);
1426163953Srrs	}
1427163953Srrs
1428163953Srrs	dns_db_detach(&sdbiter->common.db);
1429163953Srrs	isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t));
1430163953Srrs
1431163953Srrs	*iteratorp = NULL;
1432163953Srrs}
1433163953Srrs
1434163953Srrsstatic isc_result_t
1435163953Srrsdbiterator_first(dns_dbiterator_t *iterator) {
1436224641Stuexen	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1437224641Stuexen
1438163953Srrs	sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1439224641Stuexen	if (sdbiter->current == NULL)
1440224641Stuexen		return (ISC_R_NOMORE);
1441163953Srrs	else
1442224641Stuexen		return (ISC_R_SUCCESS);
1443163953Srrs}
1444163953Srrs
1445163953Srrsstatic isc_result_t
1446163953Srrsdbiterator_last(dns_dbiterator_t *iterator) {
1447163953Srrs	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1448163953Srrs
1449163953Srrs	sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist);
1450163953Srrs	if (sdbiter->current == NULL)
1451163953Srrs		return (ISC_R_NOMORE);
1452179157Srrs	else
1453163953Srrs		return (ISC_R_SUCCESS);
1454231038Stuexen}
1455169352Srrs
1456179157Srrsstatic isc_result_t
1457169352Srrsdbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
1458169352Srrs	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1459169352Srrs
1460169420Srrs	sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1461169352Srrs	while (sdbiter->current != NULL)
1462169352Srrs		if (dns_name_equal(sdbiter->current->name, name))
1463169352Srrs			return (ISC_R_SUCCESS);
1464169420Srrs	return (ISC_R_NOTFOUND);
1465179157Srrs}
1466179157Srrs
1467179157Srrsstatic isc_result_t
1468179157Srrsdbiterator_prev(dns_dbiterator_t *iterator) {
1469179157Srrs	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1470197288Srrs
1471179157Srrs	sdbiter->current = ISC_LIST_PREV(sdbiter->current, link);
1472179157Srrs	if (sdbiter->current == NULL)
1473179157Srrs		return (ISC_R_NOMORE);
1474169420Srrs	else
1475169420Srrs		return (ISC_R_SUCCESS);
1476169420Srrs}
1477169420Srrs
1478179157Srrsstatic isc_result_t
1479179157Srrsdbiterator_next(dns_dbiterator_t *iterator) {
1480179157Srrs	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1481179157Srrs
1482179157Srrs	sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
1483179157Srrs	if (sdbiter->current == NULL)
1484179157Srrs		return (ISC_R_NOMORE);
1485169352Srrs	else
1486169352Srrs		return (ISC_R_SUCCESS);
1487169352Srrs}
1488169352Srrs
1489169352Srrsstatic isc_result_t
1490169352Srrsdbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1491185694Srrs		   dns_name_t *name)
1492185694Srrs{
1493185694Srrs	sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1494169352Srrs
1495163953Srrs	attachnode(iterator->db, sdbiter->current, nodep);
1496163953Srrs	if (name != NULL)
1497163953Srrs		return (dns_name_copy(sdbiter->current->name, name, NULL));
1498163953Srrs	return (ISC_R_SUCCESS);
1499163953Srrs}
1500163953Srrs
1501163953Srrsstatic isc_result_t
1502163953Srrsdbiterator_pause(dns_dbiterator_t *iterator) {
1503163953Srrs	UNUSED(iterator);
1504163953Srrs	return (ISC_R_SUCCESS);
1505163953Srrs}
1506163953Srrs
1507163953Srrsstatic isc_result_t
1508163953Srrsdbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1509163953Srrs	UNUSED(iterator);
1510163953Srrs	return (dns_name_copy(dns_rootname, name, NULL));
1511163953Srrs}
1512169378Srrs
1513163953Srrs/*
1514163953Srrs * Rdataset Iterator Methods
1515163953Srrs */
1516163953Srrs
1517163953Srrsstatic void
1518163953Srrsrdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
1519163953Srrs	sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp);
1520163953Srrs	detachnode(sdbiterator->common.db, &sdbiterator->common.node);
1521163953Srrs	isc_mem_put(sdbiterator->common.db->mctx, sdbiterator,
1522163953Srrs		    sizeof(sdb_rdatasetiter_t));
1523163953Srrs	*iteratorp = NULL;
1524163953Srrs}
1525163953Srrs
1526163953Srrsstatic isc_result_t
1527163953Srrsrdatasetiter_first(dns_rdatasetiter_t *iterator) {
1528163953Srrs	sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1529163953Srrs	dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node;
1530163953Srrs
1531163953Srrs	if (ISC_LIST_EMPTY(sdbnode->lists))
1532163953Srrs		return (ISC_R_NOMORE);
1533163953Srrs	sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists);
1534163953Srrs	return (ISC_R_SUCCESS);
1535172090Srrs}
1536163953Srrs
1537163953Srrsstatic isc_result_t
1538163953Srrsrdatasetiter_next(dns_rdatasetiter_t *iterator) {
1539163953Srrs	sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1540163953Srrs
1541163953Srrs	sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link);
1542163953Srrs	if (sdbiterator->current == NULL)
1543166675Srrs		return (ISC_R_NOMORE);
1544163953Srrs	else
1545224641Stuexen		return (ISC_R_SUCCESS);
1546224641Stuexen}
1547224641Stuexen
1548224641Stuexenstatic void
1549224641Stuexenrdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
1550224641Stuexen	sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1551224641Stuexen
1552224641Stuexen	list_tordataset(sdbiterator->current, iterator->db, iterator->node,
1553166675Srrs			rdataset);
1554166675Srrs}
1555166675Srrs