xref: /minix3/external/bsd/bind/dist/lib/dns/ecdb.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: ecdb.c,v 1.9 2015/07/08 17:28:58 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2009-2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  *
6*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
7*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9*00b67f09SDavid van Moolenbroek  *
10*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
17*00b67f09SDavid van Moolenbroek  */
18*00b67f09SDavid van Moolenbroek 
19*00b67f09SDavid van Moolenbroek #include "config.h"
20*00b67f09SDavid van Moolenbroek 
21*00b67f09SDavid van Moolenbroek #include <isc/result.h>
22*00b67f09SDavid van Moolenbroek #include <isc/util.h>
23*00b67f09SDavid van Moolenbroek #include <isc/mutex.h>
24*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #include <dns/db.h>
27*00b67f09SDavid van Moolenbroek #include <dns/ecdb.h>
28*00b67f09SDavid van Moolenbroek #include <dns/rdata.h>
29*00b67f09SDavid van Moolenbroek #include <dns/rdataset.h>
30*00b67f09SDavid van Moolenbroek #include <dns/rdatasetiter.h>
31*00b67f09SDavid van Moolenbroek #include <dns/rdataslab.h>
32*00b67f09SDavid van Moolenbroek 
33*00b67f09SDavid van Moolenbroek #define ECDB_MAGIC		ISC_MAGIC('E', 'C', 'D', 'B')
34*00b67f09SDavid van Moolenbroek #define VALID_ECDB(db)		((db) != NULL && \
35*00b67f09SDavid van Moolenbroek 				 (db)->common.impmagic == ECDB_MAGIC)
36*00b67f09SDavid van Moolenbroek 
37*00b67f09SDavid van Moolenbroek #define ECDBNODE_MAGIC		ISC_MAGIC('E', 'C', 'D', 'N')
38*00b67f09SDavid van Moolenbroek #define VALID_ECDBNODE(ecdbn)	ISC_MAGIC_VALID(ecdbn, ECDBNODE_MAGIC)
39*00b67f09SDavid van Moolenbroek 
40*00b67f09SDavid van Moolenbroek /*%
41*00b67f09SDavid van Moolenbroek  * The 'ephemeral' cache DB (ecdb) implementation.  An ecdb just provides
42*00b67f09SDavid van Moolenbroek  * temporary storage for ongoing name resolution with the common DB interfaces.
43*00b67f09SDavid van Moolenbroek  * It actually doesn't cache anything.  The implementation expects any stored
44*00b67f09SDavid van Moolenbroek  * data is released within a short period, and does not care about the
45*00b67f09SDavid van Moolenbroek  * scalability in terms of the number of nodes.
46*00b67f09SDavid van Moolenbroek  */
47*00b67f09SDavid van Moolenbroek 
48*00b67f09SDavid van Moolenbroek typedef struct dns_ecdb {
49*00b67f09SDavid van Moolenbroek 	/* Unlocked */
50*00b67f09SDavid van Moolenbroek 	dns_db_t			common;
51*00b67f09SDavid van Moolenbroek 	isc_mutex_t			lock;
52*00b67f09SDavid van Moolenbroek 
53*00b67f09SDavid van Moolenbroek 	/* Locked */
54*00b67f09SDavid van Moolenbroek 	unsigned int			references;
55*00b67f09SDavid van Moolenbroek 	ISC_LIST(struct dns_ecdbnode)	nodes;
56*00b67f09SDavid van Moolenbroek } dns_ecdb_t;
57*00b67f09SDavid van Moolenbroek 
58*00b67f09SDavid van Moolenbroek typedef struct dns_ecdbnode {
59*00b67f09SDavid van Moolenbroek 	/* Unlocked */
60*00b67f09SDavid van Moolenbroek 	unsigned int			magic;
61*00b67f09SDavid van Moolenbroek 	isc_mutex_t			lock;
62*00b67f09SDavid van Moolenbroek 	dns_ecdb_t			*ecdb;
63*00b67f09SDavid van Moolenbroek 	dns_name_t			name;
64*00b67f09SDavid van Moolenbroek 	ISC_LINK(struct dns_ecdbnode)	link;
65*00b67f09SDavid van Moolenbroek 
66*00b67f09SDavid van Moolenbroek 	/* Locked */
67*00b67f09SDavid van Moolenbroek 	ISC_LIST(struct rdatasetheader)	rdatasets;
68*00b67f09SDavid van Moolenbroek 	unsigned int			references;
69*00b67f09SDavid van Moolenbroek } dns_ecdbnode_t;
70*00b67f09SDavid van Moolenbroek 
71*00b67f09SDavid van Moolenbroek typedef struct rdatasetheader {
72*00b67f09SDavid van Moolenbroek 	dns_rdatatype_t			type;
73*00b67f09SDavid van Moolenbroek 	dns_ttl_t			ttl;
74*00b67f09SDavid van Moolenbroek 	dns_trust_t			trust;
75*00b67f09SDavid van Moolenbroek 	dns_rdatatype_t			covers;
76*00b67f09SDavid van Moolenbroek 	unsigned int			attributes;
77*00b67f09SDavid van Moolenbroek 
78*00b67f09SDavid van Moolenbroek 	ISC_LINK(struct rdatasetheader)	link;
79*00b67f09SDavid van Moolenbroek } rdatasetheader_t;
80*00b67f09SDavid van Moolenbroek 
81*00b67f09SDavid van Moolenbroek /* Copied from rbtdb.c */
82*00b67f09SDavid van Moolenbroek #define RDATASET_ATTR_NXDOMAIN		0x0010
83*00b67f09SDavid van Moolenbroek #define RDATASET_ATTR_NEGATIVE		0x0100
84*00b67f09SDavid van Moolenbroek #define NXDOMAIN(header) \
85*00b67f09SDavid van Moolenbroek 	(((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
86*00b67f09SDavid van Moolenbroek #define NEGATIVE(header) \
87*00b67f09SDavid van Moolenbroek 	(((header)->attributes & RDATASET_ATTR_NEGATIVE) != 0)
88*00b67f09SDavid van Moolenbroek 
89*00b67f09SDavid van Moolenbroek static isc_result_t dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin,
90*00b67f09SDavid van Moolenbroek 				    dns_dbtype_t type,
91*00b67f09SDavid van Moolenbroek 				    dns_rdataclass_t rdclass,
92*00b67f09SDavid van Moolenbroek 				    unsigned int argc, char *argv[],
93*00b67f09SDavid van Moolenbroek 				    void *driverarg, dns_db_t **dbp);
94*00b67f09SDavid van Moolenbroek 
95*00b67f09SDavid van Moolenbroek static void rdataset_disassociate(dns_rdataset_t *rdataset);
96*00b67f09SDavid van Moolenbroek static isc_result_t rdataset_first(dns_rdataset_t *rdataset);
97*00b67f09SDavid van Moolenbroek static isc_result_t rdataset_next(dns_rdataset_t *rdataset);
98*00b67f09SDavid van Moolenbroek static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
99*00b67f09SDavid van Moolenbroek static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);
100*00b67f09SDavid van Moolenbroek static unsigned int rdataset_count(dns_rdataset_t *rdataset);
101*00b67f09SDavid van Moolenbroek static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
102*00b67f09SDavid van Moolenbroek 
103*00b67f09SDavid van Moolenbroek static dns_rdatasetmethods_t rdataset_methods = {
104*00b67f09SDavid van Moolenbroek 	rdataset_disassociate,
105*00b67f09SDavid van Moolenbroek 	rdataset_first,
106*00b67f09SDavid van Moolenbroek 	rdataset_next,
107*00b67f09SDavid van Moolenbroek 	rdataset_current,
108*00b67f09SDavid van Moolenbroek 	rdataset_clone,
109*00b67f09SDavid van Moolenbroek 	rdataset_count,
110*00b67f09SDavid van Moolenbroek 	NULL,			/* addnoqname */
111*00b67f09SDavid van Moolenbroek 	NULL,			/* getnoqname */
112*00b67f09SDavid van Moolenbroek 	NULL,			/* addclosest */
113*00b67f09SDavid van Moolenbroek 	NULL,			/* getclosest */
114*00b67f09SDavid van Moolenbroek 	NULL,			/* getadditional */
115*00b67f09SDavid van Moolenbroek 	NULL,			/* setadditional */
116*00b67f09SDavid van Moolenbroek 	NULL,			/* putadditional */
117*00b67f09SDavid van Moolenbroek 	rdataset_settrust,	/* settrust */
118*00b67f09SDavid van Moolenbroek 	NULL,			/* expire */
119*00b67f09SDavid van Moolenbroek 	NULL			/* clearprefetch */
120*00b67f09SDavid van Moolenbroek };
121*00b67f09SDavid van Moolenbroek 
122*00b67f09SDavid van Moolenbroek typedef struct ecdb_rdatasetiter {
123*00b67f09SDavid van Moolenbroek 	dns_rdatasetiter_t		common;
124*00b67f09SDavid van Moolenbroek 	rdatasetheader_t	       *current;
125*00b67f09SDavid van Moolenbroek } ecdb_rdatasetiter_t;
126*00b67f09SDavid van Moolenbroek 
127*00b67f09SDavid van Moolenbroek static void		rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
128*00b67f09SDavid van Moolenbroek static isc_result_t	rdatasetiter_first(dns_rdatasetiter_t *iterator);
129*00b67f09SDavid van Moolenbroek static isc_result_t	rdatasetiter_next(dns_rdatasetiter_t *iterator);
130*00b67f09SDavid van Moolenbroek static void		rdatasetiter_current(dns_rdatasetiter_t *iterator,
131*00b67f09SDavid van Moolenbroek 					     dns_rdataset_t *rdataset);
132*00b67f09SDavid van Moolenbroek 
133*00b67f09SDavid van Moolenbroek static dns_rdatasetitermethods_t rdatasetiter_methods = {
134*00b67f09SDavid van Moolenbroek 	rdatasetiter_destroy,
135*00b67f09SDavid van Moolenbroek 	rdatasetiter_first,
136*00b67f09SDavid van Moolenbroek 	rdatasetiter_next,
137*00b67f09SDavid van Moolenbroek 	rdatasetiter_current
138*00b67f09SDavid van Moolenbroek };
139*00b67f09SDavid van Moolenbroek 
140*00b67f09SDavid van Moolenbroek isc_result_t
dns_ecdb_register(isc_mem_t * mctx,dns_dbimplementation_t ** dbimp)141*00b67f09SDavid van Moolenbroek dns_ecdb_register(isc_mem_t *mctx, dns_dbimplementation_t **dbimp) {
142*00b67f09SDavid van Moolenbroek 	REQUIRE(mctx != NULL);
143*00b67f09SDavid van Moolenbroek 	REQUIRE(dbimp != NULL && *dbimp == NULL);
144*00b67f09SDavid van Moolenbroek 
145*00b67f09SDavid van Moolenbroek 	return (dns_db_register("ecdb", dns_ecdb_create, NULL, mctx, dbimp));
146*00b67f09SDavid van Moolenbroek }
147*00b67f09SDavid van Moolenbroek 
148*00b67f09SDavid van Moolenbroek void
dns_ecdb_unregister(dns_dbimplementation_t ** dbimp)149*00b67f09SDavid van Moolenbroek dns_ecdb_unregister(dns_dbimplementation_t **dbimp) {
150*00b67f09SDavid van Moolenbroek 	REQUIRE(dbimp != NULL && *dbimp != NULL);
151*00b67f09SDavid van Moolenbroek 
152*00b67f09SDavid van Moolenbroek 	dns_db_unregister(dbimp);
153*00b67f09SDavid van Moolenbroek }
154*00b67f09SDavid van Moolenbroek 
155*00b67f09SDavid van Moolenbroek /*%
156*00b67f09SDavid van Moolenbroek  * DB routines
157*00b67f09SDavid van Moolenbroek  */
158*00b67f09SDavid van Moolenbroek 
159*00b67f09SDavid van Moolenbroek static void
attach(dns_db_t * source,dns_db_t ** targetp)160*00b67f09SDavid van Moolenbroek attach(dns_db_t *source, dns_db_t **targetp) {
161*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb = (dns_ecdb_t *)source;
162*00b67f09SDavid van Moolenbroek 
163*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDB(ecdb));
164*00b67f09SDavid van Moolenbroek 	REQUIRE(targetp != NULL && *targetp == NULL);
165*00b67f09SDavid van Moolenbroek 
166*00b67f09SDavid van Moolenbroek 	LOCK(&ecdb->lock);
167*00b67f09SDavid van Moolenbroek 	ecdb->references++;
168*00b67f09SDavid van Moolenbroek 	UNLOCK(&ecdb->lock);
169*00b67f09SDavid van Moolenbroek 
170*00b67f09SDavid van Moolenbroek 	*targetp = source;
171*00b67f09SDavid van Moolenbroek }
172*00b67f09SDavid van Moolenbroek 
173*00b67f09SDavid van Moolenbroek static void
destroy_ecdb(dns_ecdb_t ** ecdbp)174*00b67f09SDavid van Moolenbroek destroy_ecdb(dns_ecdb_t **ecdbp) {
175*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb = *ecdbp;
176*00b67f09SDavid van Moolenbroek 	isc_mem_t *mctx = ecdb->common.mctx;
177*00b67f09SDavid van Moolenbroek 
178*00b67f09SDavid van Moolenbroek 	if (dns_name_dynamic(&ecdb->common.origin))
179*00b67f09SDavid van Moolenbroek 		dns_name_free(&ecdb->common.origin, mctx);
180*00b67f09SDavid van Moolenbroek 
181*00b67f09SDavid van Moolenbroek 	DESTROYLOCK(&ecdb->lock);
182*00b67f09SDavid van Moolenbroek 
183*00b67f09SDavid van Moolenbroek 	ecdb->common.impmagic = 0;
184*00b67f09SDavid van Moolenbroek 	ecdb->common.magic = 0;
185*00b67f09SDavid van Moolenbroek 
186*00b67f09SDavid van Moolenbroek 	isc_mem_putanddetach(&mctx, ecdb, sizeof(*ecdb));
187*00b67f09SDavid van Moolenbroek 
188*00b67f09SDavid van Moolenbroek 	*ecdbp = NULL;
189*00b67f09SDavid van Moolenbroek }
190*00b67f09SDavid van Moolenbroek 
191*00b67f09SDavid van Moolenbroek static void
detach(dns_db_t ** dbp)192*00b67f09SDavid van Moolenbroek detach(dns_db_t **dbp) {
193*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb;
194*00b67f09SDavid van Moolenbroek 	isc_boolean_t need_destroy = ISC_FALSE;
195*00b67f09SDavid van Moolenbroek 
196*00b67f09SDavid van Moolenbroek 	REQUIRE(dbp != NULL);
197*00b67f09SDavid van Moolenbroek 	ecdb = (dns_ecdb_t *)*dbp;
198*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDB(ecdb));
199*00b67f09SDavid van Moolenbroek 
200*00b67f09SDavid van Moolenbroek 	LOCK(&ecdb->lock);
201*00b67f09SDavid van Moolenbroek 	ecdb->references--;
202*00b67f09SDavid van Moolenbroek 	if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
203*00b67f09SDavid van Moolenbroek 		need_destroy = ISC_TRUE;
204*00b67f09SDavid van Moolenbroek 	UNLOCK(&ecdb->lock);
205*00b67f09SDavid van Moolenbroek 
206*00b67f09SDavid van Moolenbroek 	if (need_destroy)
207*00b67f09SDavid van Moolenbroek 		destroy_ecdb(&ecdb);
208*00b67f09SDavid van Moolenbroek 
209*00b67f09SDavid van Moolenbroek 	*dbp = NULL;
210*00b67f09SDavid van Moolenbroek }
211*00b67f09SDavid van Moolenbroek 
212*00b67f09SDavid van Moolenbroek static void
attachnode(dns_db_t * db,dns_dbnode_t * source,dns_dbnode_t ** targetp)213*00b67f09SDavid van Moolenbroek attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
214*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
215*00b67f09SDavid van Moolenbroek 	dns_ecdbnode_t *node = (dns_ecdbnode_t *)source;
216*00b67f09SDavid van Moolenbroek 
217*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDB(ecdb));
218*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDBNODE(node));
219*00b67f09SDavid van Moolenbroek 	REQUIRE(targetp != NULL && *targetp == NULL);
220*00b67f09SDavid van Moolenbroek 
221*00b67f09SDavid van Moolenbroek 	LOCK(&node->lock);
222*00b67f09SDavid van Moolenbroek 	INSIST(node->references > 0);
223*00b67f09SDavid van Moolenbroek 	node->references++;
224*00b67f09SDavid van Moolenbroek 	INSIST(node->references != 0);		/* Catch overflow. */
225*00b67f09SDavid van Moolenbroek 	UNLOCK(&node->lock);
226*00b67f09SDavid van Moolenbroek 
227*00b67f09SDavid van Moolenbroek 	*targetp = node;
228*00b67f09SDavid van Moolenbroek }
229*00b67f09SDavid van Moolenbroek 
230*00b67f09SDavid van Moolenbroek static void
destroynode(dns_ecdbnode_t * node)231*00b67f09SDavid van Moolenbroek destroynode(dns_ecdbnode_t *node) {
232*00b67f09SDavid van Moolenbroek 	isc_mem_t *mctx;
233*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb = node->ecdb;
234*00b67f09SDavid van Moolenbroek 	isc_boolean_t need_destroydb = ISC_FALSE;
235*00b67f09SDavid van Moolenbroek 	rdatasetheader_t *header;
236*00b67f09SDavid van Moolenbroek 
237*00b67f09SDavid van Moolenbroek 	mctx = ecdb->common.mctx;
238*00b67f09SDavid van Moolenbroek 
239*00b67f09SDavid van Moolenbroek 	LOCK(&ecdb->lock);
240*00b67f09SDavid van Moolenbroek 	ISC_LIST_UNLINK(ecdb->nodes, node, link);
241*00b67f09SDavid van Moolenbroek 	if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
242*00b67f09SDavid van Moolenbroek 		need_destroydb = ISC_TRUE;
243*00b67f09SDavid van Moolenbroek 	UNLOCK(&ecdb->lock);
244*00b67f09SDavid van Moolenbroek 
245*00b67f09SDavid van Moolenbroek 	dns_name_free(&node->name, mctx);
246*00b67f09SDavid van Moolenbroek 
247*00b67f09SDavid van Moolenbroek 	while ((header = ISC_LIST_HEAD(node->rdatasets)) != NULL) {
248*00b67f09SDavid van Moolenbroek 		unsigned int headersize;
249*00b67f09SDavid van Moolenbroek 
250*00b67f09SDavid van Moolenbroek 		ISC_LIST_UNLINK(node->rdatasets, header, link);
251*00b67f09SDavid van Moolenbroek 		headersize =
252*00b67f09SDavid van Moolenbroek 			dns_rdataslab_size((unsigned char *)header,
253*00b67f09SDavid van Moolenbroek 					   sizeof(*header));
254*00b67f09SDavid van Moolenbroek 		isc_mem_put(mctx, header, headersize);
255*00b67f09SDavid van Moolenbroek 	}
256*00b67f09SDavid van Moolenbroek 
257*00b67f09SDavid van Moolenbroek 	DESTROYLOCK(&node->lock);
258*00b67f09SDavid van Moolenbroek 
259*00b67f09SDavid van Moolenbroek 	node->magic = 0;
260*00b67f09SDavid van Moolenbroek 	isc_mem_put(mctx, node, sizeof(*node));
261*00b67f09SDavid van Moolenbroek 
262*00b67f09SDavid van Moolenbroek 	if (need_destroydb)
263*00b67f09SDavid van Moolenbroek 		destroy_ecdb(&ecdb);
264*00b67f09SDavid van Moolenbroek }
265*00b67f09SDavid van Moolenbroek 
266*00b67f09SDavid van Moolenbroek static void
detachnode(dns_db_t * db,dns_dbnode_t ** nodep)267*00b67f09SDavid van Moolenbroek detachnode(dns_db_t *db, dns_dbnode_t **nodep) {
268*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
269*00b67f09SDavid van Moolenbroek 	dns_ecdbnode_t *node;
270*00b67f09SDavid van Moolenbroek 	isc_boolean_t need_destroy = ISC_FALSE;
271*00b67f09SDavid van Moolenbroek 
272*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDB(ecdb));
273*00b67f09SDavid van Moolenbroek 	REQUIRE(nodep != NULL);
274*00b67f09SDavid van Moolenbroek 	node = (dns_ecdbnode_t *)*nodep;
275*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDBNODE(node));
276*00b67f09SDavid van Moolenbroek 
277*00b67f09SDavid van Moolenbroek 	UNUSED(ecdb);		/* in case REQUIRE() is empty */
278*00b67f09SDavid van Moolenbroek 
279*00b67f09SDavid van Moolenbroek 	LOCK(&node->lock);
280*00b67f09SDavid van Moolenbroek 	INSIST(node->references > 0);
281*00b67f09SDavid van Moolenbroek 	node->references--;
282*00b67f09SDavid van Moolenbroek 	if (node->references == 0)
283*00b67f09SDavid van Moolenbroek 		need_destroy = ISC_TRUE;
284*00b67f09SDavid van Moolenbroek 	UNLOCK(&node->lock);
285*00b67f09SDavid van Moolenbroek 
286*00b67f09SDavid van Moolenbroek 	if (need_destroy)
287*00b67f09SDavid van Moolenbroek 		destroynode(node);
288*00b67f09SDavid van Moolenbroek 
289*00b67f09SDavid van Moolenbroek 	*nodep = NULL;
290*00b67f09SDavid van Moolenbroek }
291*00b67f09SDavid van Moolenbroek 
292*00b67f09SDavid van Moolenbroek static isc_result_t
find(dns_db_t * db,dns_name_t * name,dns_dbversion_t * version,dns_rdatatype_t type,unsigned int options,isc_stdtime_t now,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)293*00b67f09SDavid van Moolenbroek find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
294*00b67f09SDavid van Moolenbroek     dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
295*00b67f09SDavid van Moolenbroek     dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset,
296*00b67f09SDavid van Moolenbroek     dns_rdataset_t *sigrdataset)
297*00b67f09SDavid van Moolenbroek {
298*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
299*00b67f09SDavid van Moolenbroek 
300*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDB(ecdb));
301*00b67f09SDavid van Moolenbroek 
302*00b67f09SDavid van Moolenbroek 	UNUSED(name);
303*00b67f09SDavid van Moolenbroek 	UNUSED(version);
304*00b67f09SDavid van Moolenbroek 	UNUSED(type);
305*00b67f09SDavid van Moolenbroek 	UNUSED(options);
306*00b67f09SDavid van Moolenbroek 	UNUSED(now);
307*00b67f09SDavid van Moolenbroek 	UNUSED(nodep);
308*00b67f09SDavid van Moolenbroek 	UNUSED(foundname);
309*00b67f09SDavid van Moolenbroek 	UNUSED(rdataset);
310*00b67f09SDavid van Moolenbroek 	UNUSED(sigrdataset);
311*00b67f09SDavid van Moolenbroek 
312*00b67f09SDavid van Moolenbroek 	return (ISC_R_NOTFOUND);
313*00b67f09SDavid van Moolenbroek }
314*00b67f09SDavid van Moolenbroek 
315*00b67f09SDavid van Moolenbroek static isc_result_t
findzonecut(dns_db_t * db,dns_name_t * name,unsigned int options,isc_stdtime_t now,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)316*00b67f09SDavid van Moolenbroek findzonecut(dns_db_t *db, dns_name_t *name,
317*00b67f09SDavid van Moolenbroek 	    unsigned int options, isc_stdtime_t now,
318*00b67f09SDavid van Moolenbroek 	    dns_dbnode_t **nodep, dns_name_t *foundname,
319*00b67f09SDavid van Moolenbroek 	    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
320*00b67f09SDavid van Moolenbroek {
321*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
322*00b67f09SDavid van Moolenbroek 
323*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDB(ecdb));
324*00b67f09SDavid van Moolenbroek 
325*00b67f09SDavid van Moolenbroek 	UNUSED(name);
326*00b67f09SDavid van Moolenbroek 	UNUSED(options);
327*00b67f09SDavid van Moolenbroek 	UNUSED(now);
328*00b67f09SDavid van Moolenbroek 	UNUSED(nodep);
329*00b67f09SDavid van Moolenbroek 	UNUSED(foundname);
330*00b67f09SDavid van Moolenbroek 	UNUSED(rdataset);
331*00b67f09SDavid van Moolenbroek 	UNUSED(sigrdataset);
332*00b67f09SDavid van Moolenbroek 
333*00b67f09SDavid van Moolenbroek 	return (ISC_R_NOTFOUND);
334*00b67f09SDavid van Moolenbroek }
335*00b67f09SDavid van Moolenbroek 
336*00b67f09SDavid van Moolenbroek static isc_result_t
findnode(dns_db_t * db,dns_name_t * name,isc_boolean_t create,dns_dbnode_t ** nodep)337*00b67f09SDavid van Moolenbroek findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
338*00b67f09SDavid van Moolenbroek 	 dns_dbnode_t **nodep)
339*00b67f09SDavid van Moolenbroek {
340*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
341*00b67f09SDavid van Moolenbroek 	isc_mem_t *mctx;
342*00b67f09SDavid van Moolenbroek 	dns_ecdbnode_t *node;
343*00b67f09SDavid van Moolenbroek 	isc_result_t result;
344*00b67f09SDavid van Moolenbroek 
345*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDB(ecdb));
346*00b67f09SDavid van Moolenbroek 	REQUIRE(nodep != NULL && *nodep == NULL);
347*00b67f09SDavid van Moolenbroek 
348*00b67f09SDavid van Moolenbroek 	UNUSED(name);
349*00b67f09SDavid van Moolenbroek 
350*00b67f09SDavid van Moolenbroek 	if (create != ISC_TRUE)	{
351*00b67f09SDavid van Moolenbroek 		/* an 'ephemeral' node is never reused. */
352*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTFOUND);
353*00b67f09SDavid van Moolenbroek 	}
354*00b67f09SDavid van Moolenbroek 
355*00b67f09SDavid van Moolenbroek 	mctx = ecdb->common.mctx;
356*00b67f09SDavid van Moolenbroek 	node = isc_mem_get(mctx, sizeof(*node));
357*00b67f09SDavid van Moolenbroek 	if (node == NULL)
358*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
359*00b67f09SDavid van Moolenbroek 
360*00b67f09SDavid van Moolenbroek 	result = isc_mutex_init(&node->lock);
361*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
362*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
363*00b67f09SDavid van Moolenbroek 				 "isc_mutex_init() failed: %s",
364*00b67f09SDavid van Moolenbroek 				 isc_result_totext(result));
365*00b67f09SDavid van Moolenbroek 		isc_mem_put(mctx, node, sizeof(*node));
366*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
367*00b67f09SDavid van Moolenbroek 	}
368*00b67f09SDavid van Moolenbroek 
369*00b67f09SDavid van Moolenbroek 	dns_name_init(&node->name, NULL);
370*00b67f09SDavid van Moolenbroek 	result = dns_name_dup(name, mctx, &node->name);
371*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
372*00b67f09SDavid van Moolenbroek 		DESTROYLOCK(&node->lock);
373*00b67f09SDavid van Moolenbroek 		isc_mem_put(mctx, node, sizeof(*node));
374*00b67f09SDavid van Moolenbroek 		return (result);
375*00b67f09SDavid van Moolenbroek 	}
376*00b67f09SDavid van Moolenbroek 	node->ecdb= ecdb;
377*00b67f09SDavid van Moolenbroek 	node->references = 1;
378*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(node->rdatasets);
379*00b67f09SDavid van Moolenbroek 
380*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(node, link);
381*00b67f09SDavid van Moolenbroek 
382*00b67f09SDavid van Moolenbroek 	LOCK(&ecdb->lock);
383*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(ecdb->nodes, node, link);
384*00b67f09SDavid van Moolenbroek 	UNLOCK(&ecdb->lock);
385*00b67f09SDavid van Moolenbroek 
386*00b67f09SDavid van Moolenbroek 	node->magic = ECDBNODE_MAGIC;
387*00b67f09SDavid van Moolenbroek 
388*00b67f09SDavid van Moolenbroek 	*nodep = node;
389*00b67f09SDavid van Moolenbroek 
390*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
391*00b67f09SDavid van Moolenbroek }
392*00b67f09SDavid van Moolenbroek 
393*00b67f09SDavid van Moolenbroek static void
bind_rdataset(dns_ecdb_t * ecdb,dns_ecdbnode_t * node,rdatasetheader_t * header,dns_rdataset_t * rdataset)394*00b67f09SDavid van Moolenbroek bind_rdataset(dns_ecdb_t *ecdb, dns_ecdbnode_t *node,
395*00b67f09SDavid van Moolenbroek 	      rdatasetheader_t *header, dns_rdataset_t *rdataset)
396*00b67f09SDavid van Moolenbroek {
397*00b67f09SDavid van Moolenbroek 	unsigned char *raw;
398*00b67f09SDavid van Moolenbroek 
399*00b67f09SDavid van Moolenbroek 	/*
400*00b67f09SDavid van Moolenbroek 	 * Caller must be holding the node lock.
401*00b67f09SDavid van Moolenbroek 	 */
402*00b67f09SDavid van Moolenbroek 
403*00b67f09SDavid van Moolenbroek 	REQUIRE(!dns_rdataset_isassociated(rdataset));
404*00b67f09SDavid van Moolenbroek 
405*00b67f09SDavid van Moolenbroek 	rdataset->methods = &rdataset_methods;
406*00b67f09SDavid van Moolenbroek 	rdataset->rdclass = ecdb->common.rdclass;
407*00b67f09SDavid van Moolenbroek 	rdataset->type = header->type;
408*00b67f09SDavid van Moolenbroek 	rdataset->covers = header->covers;
409*00b67f09SDavid van Moolenbroek 	rdataset->ttl = header->ttl;
410*00b67f09SDavid van Moolenbroek 	rdataset->trust = header->trust;
411*00b67f09SDavid van Moolenbroek 	if (NXDOMAIN(header))
412*00b67f09SDavid van Moolenbroek 		rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN;
413*00b67f09SDavid van Moolenbroek 	if (NEGATIVE(header))
414*00b67f09SDavid van Moolenbroek 		rdataset->attributes |= DNS_RDATASETATTR_NEGATIVE;
415*00b67f09SDavid van Moolenbroek 
416*00b67f09SDavid van Moolenbroek 	rdataset->private1 = ecdb;
417*00b67f09SDavid van Moolenbroek 	rdataset->private2 = node;
418*00b67f09SDavid van Moolenbroek 	raw = (unsigned char *)header + sizeof(*header);
419*00b67f09SDavid van Moolenbroek 	rdataset->private3 = raw;
420*00b67f09SDavid van Moolenbroek 	rdataset->count = 0;
421*00b67f09SDavid van Moolenbroek 
422*00b67f09SDavid van Moolenbroek 	/*
423*00b67f09SDavid van Moolenbroek 	 * Reset iterator state.
424*00b67f09SDavid van Moolenbroek 	 */
425*00b67f09SDavid van Moolenbroek 	rdataset->privateuint4 = 0;
426*00b67f09SDavid van Moolenbroek 	rdataset->private5 = NULL;
427*00b67f09SDavid van Moolenbroek 
428*00b67f09SDavid van Moolenbroek 	INSIST(node->references > 0);
429*00b67f09SDavid van Moolenbroek 	node->references++;
430*00b67f09SDavid van Moolenbroek }
431*00b67f09SDavid van Moolenbroek 
432*00b67f09SDavid van Moolenbroek static isc_result_t
addrdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,isc_stdtime_t now,dns_rdataset_t * rdataset,unsigned int options,dns_rdataset_t * addedrdataset)433*00b67f09SDavid van Moolenbroek addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
434*00b67f09SDavid van Moolenbroek 	    isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
435*00b67f09SDavid van Moolenbroek 	    dns_rdataset_t *addedrdataset)
436*00b67f09SDavid van Moolenbroek {
437*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
438*00b67f09SDavid van Moolenbroek 	isc_region_t r;
439*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
440*00b67f09SDavid van Moolenbroek 	isc_mem_t *mctx;
441*00b67f09SDavid van Moolenbroek 	dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node;
442*00b67f09SDavid van Moolenbroek 	rdatasetheader_t *header;
443*00b67f09SDavid van Moolenbroek 
444*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDB(ecdb));
445*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDBNODE(ecdbnode));
446*00b67f09SDavid van Moolenbroek 
447*00b67f09SDavid van Moolenbroek 	UNUSED(version);
448*00b67f09SDavid van Moolenbroek 	UNUSED(now);
449*00b67f09SDavid van Moolenbroek 	UNUSED(options);
450*00b67f09SDavid van Moolenbroek 
451*00b67f09SDavid van Moolenbroek 	mctx = ecdb->common.mctx;
452*00b67f09SDavid van Moolenbroek 
453*00b67f09SDavid van Moolenbroek 	LOCK(&ecdbnode->lock);
454*00b67f09SDavid van Moolenbroek 
455*00b67f09SDavid van Moolenbroek 	/*
456*00b67f09SDavid van Moolenbroek 	 * Sanity check: this implementation does not allow overriding an
457*00b67f09SDavid van Moolenbroek 	 * existing rdataset of the same type.
458*00b67f09SDavid van Moolenbroek 	 */
459*00b67f09SDavid van Moolenbroek 	for (header = ISC_LIST_HEAD(ecdbnode->rdatasets); header != NULL;
460*00b67f09SDavid van Moolenbroek 	     header = ISC_LIST_NEXT(header, link)) {
461*00b67f09SDavid van Moolenbroek 		INSIST(header->type != rdataset->type ||
462*00b67f09SDavid van Moolenbroek 		       header->covers != rdataset->covers);
463*00b67f09SDavid van Moolenbroek 	}
464*00b67f09SDavid van Moolenbroek 
465*00b67f09SDavid van Moolenbroek 	result = dns_rdataslab_fromrdataset(rdataset, mctx,
466*00b67f09SDavid van Moolenbroek 					    &r, sizeof(rdatasetheader_t));
467*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
468*00b67f09SDavid van Moolenbroek 		goto unlock;
469*00b67f09SDavid van Moolenbroek 
470*00b67f09SDavid van Moolenbroek 	header = (rdatasetheader_t *)r.base;
471*00b67f09SDavid van Moolenbroek 	header->type = rdataset->type;
472*00b67f09SDavid van Moolenbroek 	header->ttl = rdataset->ttl;
473*00b67f09SDavid van Moolenbroek 	header->trust = rdataset->trust;
474*00b67f09SDavid van Moolenbroek 	header->covers = rdataset->covers;
475*00b67f09SDavid van Moolenbroek 	header->attributes = 0;
476*00b67f09SDavid van Moolenbroek 	if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
477*00b67f09SDavid van Moolenbroek 		header->attributes |= RDATASET_ATTR_NXDOMAIN;
478*00b67f09SDavid van Moolenbroek 	if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
479*00b67f09SDavid van Moolenbroek 		header->attributes |= RDATASET_ATTR_NEGATIVE;
480*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(header, link);
481*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(ecdbnode->rdatasets, header, link);
482*00b67f09SDavid van Moolenbroek 
483*00b67f09SDavid van Moolenbroek 	if (addedrdataset == NULL)
484*00b67f09SDavid van Moolenbroek 		goto unlock;
485*00b67f09SDavid van Moolenbroek 
486*00b67f09SDavid van Moolenbroek 	bind_rdataset(ecdb, ecdbnode, header, addedrdataset);
487*00b67f09SDavid van Moolenbroek 
488*00b67f09SDavid van Moolenbroek  unlock:
489*00b67f09SDavid van Moolenbroek 	UNLOCK(&ecdbnode->lock);
490*00b67f09SDavid van Moolenbroek 
491*00b67f09SDavid van Moolenbroek 	return (result);
492*00b67f09SDavid van Moolenbroek }
493*00b67f09SDavid van Moolenbroek 
494*00b67f09SDavid van Moolenbroek static isc_result_t
deleterdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdatatype_t type,dns_rdatatype_t covers)495*00b67f09SDavid van Moolenbroek deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
496*00b67f09SDavid van Moolenbroek 	       dns_rdatatype_t type, dns_rdatatype_t covers)
497*00b67f09SDavid van Moolenbroek {
498*00b67f09SDavid van Moolenbroek 	UNUSED(db);
499*00b67f09SDavid van Moolenbroek 	UNUSED(node);
500*00b67f09SDavid van Moolenbroek 	UNUSED(version);
501*00b67f09SDavid van Moolenbroek 	UNUSED(type);
502*00b67f09SDavid van Moolenbroek 	UNUSED(covers);
503*00b67f09SDavid van Moolenbroek 
504*00b67f09SDavid van Moolenbroek 	return (ISC_R_NOTIMPLEMENTED);
505*00b67f09SDavid van Moolenbroek }
506*00b67f09SDavid van Moolenbroek 
507*00b67f09SDavid van Moolenbroek static isc_result_t
createiterator(dns_db_t * db,unsigned int options,dns_dbiterator_t ** iteratorp)508*00b67f09SDavid van Moolenbroek createiterator(dns_db_t *db, unsigned int options,
509*00b67f09SDavid van Moolenbroek 	       dns_dbiterator_t **iteratorp)
510*00b67f09SDavid van Moolenbroek {
511*00b67f09SDavid van Moolenbroek 	UNUSED(db);
512*00b67f09SDavid van Moolenbroek 	UNUSED(options);
513*00b67f09SDavid van Moolenbroek 	UNUSED(iteratorp);
514*00b67f09SDavid van Moolenbroek 
515*00b67f09SDavid van Moolenbroek 	return (ISC_R_NOTIMPLEMENTED);
516*00b67f09SDavid van Moolenbroek }
517*00b67f09SDavid van Moolenbroek 
518*00b67f09SDavid van Moolenbroek static isc_result_t
allrdatasets(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,isc_stdtime_t now,dns_rdatasetiter_t ** iteratorp)519*00b67f09SDavid van Moolenbroek allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
520*00b67f09SDavid van Moolenbroek 	     isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
521*00b67f09SDavid van Moolenbroek {
522*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
523*00b67f09SDavid van Moolenbroek 	dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node;
524*00b67f09SDavid van Moolenbroek 	isc_mem_t *mctx;
525*00b67f09SDavid van Moolenbroek 	ecdb_rdatasetiter_t *iterator;
526*00b67f09SDavid van Moolenbroek 
527*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDB(ecdb));
528*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDBNODE(ecdbnode));
529*00b67f09SDavid van Moolenbroek 
530*00b67f09SDavid van Moolenbroek 	mctx = ecdb->common.mctx;
531*00b67f09SDavid van Moolenbroek 
532*00b67f09SDavid van Moolenbroek 	iterator = isc_mem_get(mctx, sizeof(ecdb_rdatasetiter_t));
533*00b67f09SDavid van Moolenbroek 	if (iterator == NULL)
534*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
535*00b67f09SDavid van Moolenbroek 
536*00b67f09SDavid van Moolenbroek 	iterator->common.magic = DNS_RDATASETITER_MAGIC;
537*00b67f09SDavid van Moolenbroek 	iterator->common.methods = &rdatasetiter_methods;
538*00b67f09SDavid van Moolenbroek 	iterator->common.db = db;
539*00b67f09SDavid van Moolenbroek 	iterator->common.node = NULL;
540*00b67f09SDavid van Moolenbroek 	attachnode(db, node, &iterator->common.node);
541*00b67f09SDavid van Moolenbroek 	iterator->common.version = version;
542*00b67f09SDavid van Moolenbroek 	iterator->common.now = now;
543*00b67f09SDavid van Moolenbroek 
544*00b67f09SDavid van Moolenbroek 	*iteratorp = (dns_rdatasetiter_t *)iterator;
545*00b67f09SDavid van Moolenbroek 
546*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
547*00b67f09SDavid van Moolenbroek }
548*00b67f09SDavid van Moolenbroek 
549*00b67f09SDavid van Moolenbroek static dns_dbmethods_t ecdb_methods = {
550*00b67f09SDavid van Moolenbroek 	attach,
551*00b67f09SDavid van Moolenbroek 	detach,
552*00b67f09SDavid van Moolenbroek 	NULL,			/* beginload */
553*00b67f09SDavid van Moolenbroek 	NULL,			/* endload */
554*00b67f09SDavid van Moolenbroek 	NULL,			/* serialize */
555*00b67f09SDavid van Moolenbroek 	NULL,			/* dump */
556*00b67f09SDavid van Moolenbroek 	NULL,			/* currentversion */
557*00b67f09SDavid van Moolenbroek 	NULL,			/* newversion */
558*00b67f09SDavid van Moolenbroek 	NULL,			/* attachversion */
559*00b67f09SDavid van Moolenbroek 	NULL,			/* closeversion */
560*00b67f09SDavid van Moolenbroek 	findnode,
561*00b67f09SDavid van Moolenbroek 	find,
562*00b67f09SDavid van Moolenbroek 	findzonecut,
563*00b67f09SDavid van Moolenbroek 	attachnode,
564*00b67f09SDavid van Moolenbroek 	detachnode,
565*00b67f09SDavid van Moolenbroek 	NULL,			/* expirenode */
566*00b67f09SDavid van Moolenbroek 	NULL,			/* printnode */
567*00b67f09SDavid van Moolenbroek 	createiterator,		/* createiterator */
568*00b67f09SDavid van Moolenbroek 	NULL,			/* findrdataset */
569*00b67f09SDavid van Moolenbroek 	allrdatasets,
570*00b67f09SDavid van Moolenbroek 	addrdataset,
571*00b67f09SDavid van Moolenbroek 	NULL,			/* subtractrdataset */
572*00b67f09SDavid van Moolenbroek 	deleterdataset,
573*00b67f09SDavid van Moolenbroek 	NULL,			/* issecure */
574*00b67f09SDavid van Moolenbroek 	NULL,			/* nodecount */
575*00b67f09SDavid van Moolenbroek 	NULL,			/* ispersistent */
576*00b67f09SDavid van Moolenbroek 	NULL,			/* overmem */
577*00b67f09SDavid van Moolenbroek 	NULL,			/* settask */
578*00b67f09SDavid van Moolenbroek 	NULL,			/* getoriginnode */
579*00b67f09SDavid van Moolenbroek 	NULL,			/* transfernode */
580*00b67f09SDavid van Moolenbroek 	NULL,			/* getnsec3parameters */
581*00b67f09SDavid van Moolenbroek 	NULL,			/* findnsec3node */
582*00b67f09SDavid van Moolenbroek 	NULL,			/* setsigningtime */
583*00b67f09SDavid van Moolenbroek 	NULL,			/* getsigningtime */
584*00b67f09SDavid van Moolenbroek 	NULL,			/* resigned */
585*00b67f09SDavid van Moolenbroek 	NULL,			/* isdnssec */
586*00b67f09SDavid van Moolenbroek 	NULL,			/* getrrsetstats */
587*00b67f09SDavid van Moolenbroek 	NULL,			/* rpz_attach */
588*00b67f09SDavid van Moolenbroek 	NULL,			/* rpz_ready */
589*00b67f09SDavid van Moolenbroek 	NULL,			/* findnodeext */
590*00b67f09SDavid van Moolenbroek 	NULL,			/* findext */
591*00b67f09SDavid van Moolenbroek 	NULL,			/* setcachestats */
592*00b67f09SDavid van Moolenbroek 	NULL			/* hashsize */
593*00b67f09SDavid van Moolenbroek };
594*00b67f09SDavid van Moolenbroek 
595*00b67f09SDavid van Moolenbroek static isc_result_t
dns_ecdb_create(isc_mem_t * mctx,dns_name_t * origin,dns_dbtype_t type,dns_rdataclass_t rdclass,unsigned int argc,char * argv[],void * driverarg,dns_db_t ** dbp)596*00b67f09SDavid van Moolenbroek dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
597*00b67f09SDavid van Moolenbroek 		dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
598*00b67f09SDavid van Moolenbroek 		void *driverarg, dns_db_t **dbp)
599*00b67f09SDavid van Moolenbroek {
600*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb;
601*00b67f09SDavid van Moolenbroek 	isc_result_t result;
602*00b67f09SDavid van Moolenbroek 
603*00b67f09SDavid van Moolenbroek 	REQUIRE(mctx != NULL);
604*00b67f09SDavid van Moolenbroek 	REQUIRE(origin == dns_rootname);
605*00b67f09SDavid van Moolenbroek 	REQUIRE(type == dns_dbtype_cache);
606*00b67f09SDavid van Moolenbroek 	REQUIRE(dbp != NULL && *dbp == NULL);
607*00b67f09SDavid van Moolenbroek 
608*00b67f09SDavid van Moolenbroek 	UNUSED(argc);
609*00b67f09SDavid van Moolenbroek 	UNUSED(argv);
610*00b67f09SDavid van Moolenbroek 	UNUSED(driverarg);
611*00b67f09SDavid van Moolenbroek 
612*00b67f09SDavid van Moolenbroek 	ecdb = isc_mem_get(mctx, sizeof(*ecdb));
613*00b67f09SDavid van Moolenbroek 	if (ecdb == NULL)
614*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
615*00b67f09SDavid van Moolenbroek 
616*00b67f09SDavid van Moolenbroek 	ecdb->common.attributes = DNS_DBATTR_CACHE;
617*00b67f09SDavid van Moolenbroek 	ecdb->common.rdclass = rdclass;
618*00b67f09SDavid van Moolenbroek 	ecdb->common.methods = &ecdb_methods;
619*00b67f09SDavid van Moolenbroek 	dns_name_init(&ecdb->common.origin, NULL);
620*00b67f09SDavid van Moolenbroek 	result = dns_name_dupwithoffsets(origin, mctx, &ecdb->common.origin);
621*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
622*00b67f09SDavid van Moolenbroek 		isc_mem_put(mctx, ecdb, sizeof(*ecdb));
623*00b67f09SDavid van Moolenbroek 		return (result);
624*00b67f09SDavid van Moolenbroek 	}
625*00b67f09SDavid van Moolenbroek 
626*00b67f09SDavid van Moolenbroek 	result = isc_mutex_init(&ecdb->lock);
627*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
628*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
629*00b67f09SDavid van Moolenbroek 				 "isc_mutex_init() failed: %s",
630*00b67f09SDavid van Moolenbroek 				 isc_result_totext(result));
631*00b67f09SDavid van Moolenbroek 		if (dns_name_dynamic(&ecdb->common.origin))
632*00b67f09SDavid van Moolenbroek 			dns_name_free(&ecdb->common.origin, mctx);
633*00b67f09SDavid van Moolenbroek 		isc_mem_put(mctx, ecdb, sizeof(*ecdb));
634*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
635*00b67f09SDavid van Moolenbroek 	}
636*00b67f09SDavid van Moolenbroek 
637*00b67f09SDavid van Moolenbroek 	ecdb->references = 1;
638*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(ecdb->nodes);
639*00b67f09SDavid van Moolenbroek 
640*00b67f09SDavid van Moolenbroek 	ecdb->common.mctx = NULL;
641*00b67f09SDavid van Moolenbroek 	isc_mem_attach(mctx, &ecdb->common.mctx);
642*00b67f09SDavid van Moolenbroek 	ecdb->common.impmagic = ECDB_MAGIC;
643*00b67f09SDavid van Moolenbroek 	ecdb->common.magic = DNS_DB_MAGIC;
644*00b67f09SDavid van Moolenbroek 
645*00b67f09SDavid van Moolenbroek 	*dbp = (dns_db_t *)ecdb;
646*00b67f09SDavid van Moolenbroek 
647*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
648*00b67f09SDavid van Moolenbroek }
649*00b67f09SDavid van Moolenbroek 
650*00b67f09SDavid van Moolenbroek /*%
651*00b67f09SDavid van Moolenbroek  * Rdataset Methods
652*00b67f09SDavid van Moolenbroek  */
653*00b67f09SDavid van Moolenbroek 
654*00b67f09SDavid van Moolenbroek static void
rdataset_disassociate(dns_rdataset_t * rdataset)655*00b67f09SDavid van Moolenbroek rdataset_disassociate(dns_rdataset_t *rdataset) {
656*00b67f09SDavid van Moolenbroek 	dns_db_t *db = rdataset->private1;
657*00b67f09SDavid van Moolenbroek 	dns_dbnode_t *node = rdataset->private2;
658*00b67f09SDavid van Moolenbroek 
659*00b67f09SDavid van Moolenbroek 	dns_db_detachnode(db, &node);
660*00b67f09SDavid van Moolenbroek }
661*00b67f09SDavid van Moolenbroek 
662*00b67f09SDavid van Moolenbroek static isc_result_t
rdataset_first(dns_rdataset_t * rdataset)663*00b67f09SDavid van Moolenbroek rdataset_first(dns_rdataset_t *rdataset) {
664*00b67f09SDavid van Moolenbroek 	unsigned char *raw = rdataset->private3;
665*00b67f09SDavid van Moolenbroek 	unsigned int count;
666*00b67f09SDavid van Moolenbroek 
667*00b67f09SDavid van Moolenbroek 	count = raw[0] * 256 + raw[1];
668*00b67f09SDavid van Moolenbroek 	if (count == 0) {
669*00b67f09SDavid van Moolenbroek 		rdataset->private5 = NULL;
670*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMORE);
671*00b67f09SDavid van Moolenbroek 	}
672*00b67f09SDavid van Moolenbroek #if DNS_RDATASET_FIXED
673*00b67f09SDavid van Moolenbroek 	raw += 2 + (4 * count);
674*00b67f09SDavid van Moolenbroek #else
675*00b67f09SDavid van Moolenbroek 	raw += 2;
676*00b67f09SDavid van Moolenbroek #endif
677*00b67f09SDavid van Moolenbroek 	/*
678*00b67f09SDavid van Moolenbroek 	 * The privateuint4 field is the number of rdata beyond the cursor
679*00b67f09SDavid van Moolenbroek 	 * position, so we decrement the total count by one before storing
680*00b67f09SDavid van Moolenbroek 	 * it.
681*00b67f09SDavid van Moolenbroek 	 */
682*00b67f09SDavid van Moolenbroek 	count--;
683*00b67f09SDavid van Moolenbroek 	rdataset->privateuint4 = count;
684*00b67f09SDavid van Moolenbroek 	rdataset->private5 = raw;
685*00b67f09SDavid van Moolenbroek 
686*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
687*00b67f09SDavid van Moolenbroek }
688*00b67f09SDavid van Moolenbroek 
689*00b67f09SDavid van Moolenbroek static isc_result_t
rdataset_next(dns_rdataset_t * rdataset)690*00b67f09SDavid van Moolenbroek rdataset_next(dns_rdataset_t *rdataset) {
691*00b67f09SDavid van Moolenbroek 	unsigned int count;
692*00b67f09SDavid van Moolenbroek 	unsigned int length;
693*00b67f09SDavid van Moolenbroek 	unsigned char *raw;
694*00b67f09SDavid van Moolenbroek 
695*00b67f09SDavid van Moolenbroek 	count = rdataset->privateuint4;
696*00b67f09SDavid van Moolenbroek 	if (count == 0)
697*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMORE);
698*00b67f09SDavid van Moolenbroek 	count--;
699*00b67f09SDavid van Moolenbroek 	rdataset->privateuint4 = count;
700*00b67f09SDavid van Moolenbroek 	raw = rdataset->private5;
701*00b67f09SDavid van Moolenbroek 	length = raw[0] * 256 + raw[1];
702*00b67f09SDavid van Moolenbroek #if DNS_RDATASET_FIXED
703*00b67f09SDavid van Moolenbroek 	raw += length + 4;
704*00b67f09SDavid van Moolenbroek #else
705*00b67f09SDavid van Moolenbroek 	raw += length + 2;
706*00b67f09SDavid van Moolenbroek #endif
707*00b67f09SDavid van Moolenbroek 	rdataset->private5 = raw;
708*00b67f09SDavid van Moolenbroek 
709*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
710*00b67f09SDavid van Moolenbroek }
711*00b67f09SDavid van Moolenbroek 
712*00b67f09SDavid van Moolenbroek static void
rdataset_current(dns_rdataset_t * rdataset,dns_rdata_t * rdata)713*00b67f09SDavid van Moolenbroek rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
714*00b67f09SDavid van Moolenbroek 	unsigned char *raw = rdataset->private5;
715*00b67f09SDavid van Moolenbroek 	isc_region_t r;
716*00b67f09SDavid van Moolenbroek 	unsigned int length;
717*00b67f09SDavid van Moolenbroek 	unsigned int flags = 0;
718*00b67f09SDavid van Moolenbroek 
719*00b67f09SDavid van Moolenbroek 	REQUIRE(raw != NULL);
720*00b67f09SDavid van Moolenbroek 
721*00b67f09SDavid van Moolenbroek 	length = raw[0] * 256 + raw[1];
722*00b67f09SDavid van Moolenbroek #if DNS_RDATASET_FIXED
723*00b67f09SDavid van Moolenbroek 	raw += 4;
724*00b67f09SDavid van Moolenbroek #else
725*00b67f09SDavid van Moolenbroek 	raw += 2;
726*00b67f09SDavid van Moolenbroek #endif
727*00b67f09SDavid van Moolenbroek 	if (rdataset->type == dns_rdatatype_rrsig) {
728*00b67f09SDavid van Moolenbroek 		if (*raw & DNS_RDATASLAB_OFFLINE)
729*00b67f09SDavid van Moolenbroek 			flags |= DNS_RDATA_OFFLINE;
730*00b67f09SDavid van Moolenbroek 		length--;
731*00b67f09SDavid van Moolenbroek 		raw++;
732*00b67f09SDavid van Moolenbroek 	}
733*00b67f09SDavid van Moolenbroek 	r.length = length;
734*00b67f09SDavid van Moolenbroek 	r.base = raw;
735*00b67f09SDavid van Moolenbroek 	dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
736*00b67f09SDavid van Moolenbroek 	rdata->flags |= flags;
737*00b67f09SDavid van Moolenbroek }
738*00b67f09SDavid van Moolenbroek 
739*00b67f09SDavid van Moolenbroek static void
rdataset_clone(dns_rdataset_t * source,dns_rdataset_t * target)740*00b67f09SDavid van Moolenbroek rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
741*00b67f09SDavid van Moolenbroek 	dns_db_t *db = source->private1;
742*00b67f09SDavid van Moolenbroek 	dns_dbnode_t *node = source->private2;
743*00b67f09SDavid van Moolenbroek 	dns_dbnode_t *cloned_node = NULL;
744*00b67f09SDavid van Moolenbroek 
745*00b67f09SDavid van Moolenbroek 	attachnode(db, node, &cloned_node);
746*00b67f09SDavid van Moolenbroek 	*target = *source;
747*00b67f09SDavid van Moolenbroek 
748*00b67f09SDavid van Moolenbroek 	/*
749*00b67f09SDavid van Moolenbroek 	 * Reset iterator state.
750*00b67f09SDavid van Moolenbroek 	 */
751*00b67f09SDavid van Moolenbroek 	target->privateuint4 = 0;
752*00b67f09SDavid van Moolenbroek 	target->private5 = NULL;
753*00b67f09SDavid van Moolenbroek }
754*00b67f09SDavid van Moolenbroek 
755*00b67f09SDavid van Moolenbroek static unsigned int
rdataset_count(dns_rdataset_t * rdataset)756*00b67f09SDavid van Moolenbroek rdataset_count(dns_rdataset_t *rdataset) {
757*00b67f09SDavid van Moolenbroek 	unsigned char *raw = rdataset->private3;
758*00b67f09SDavid van Moolenbroek 	unsigned int count;
759*00b67f09SDavid van Moolenbroek 
760*00b67f09SDavid van Moolenbroek 	count = raw[0] * 256 + raw[1];
761*00b67f09SDavid van Moolenbroek 
762*00b67f09SDavid van Moolenbroek 	return (count);
763*00b67f09SDavid van Moolenbroek }
764*00b67f09SDavid van Moolenbroek 
765*00b67f09SDavid van Moolenbroek static void
rdataset_settrust(dns_rdataset_t * rdataset,dns_trust_t trust)766*00b67f09SDavid van Moolenbroek rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
767*00b67f09SDavid van Moolenbroek 	rdatasetheader_t *header = rdataset->private3;
768*00b67f09SDavid van Moolenbroek 
769*00b67f09SDavid van Moolenbroek 	header--;
770*00b67f09SDavid van Moolenbroek 	header->trust = rdataset->trust = trust;
771*00b67f09SDavid van Moolenbroek }
772*00b67f09SDavid van Moolenbroek 
773*00b67f09SDavid van Moolenbroek /*
774*00b67f09SDavid van Moolenbroek  * Rdataset Iterator Methods
775*00b67f09SDavid van Moolenbroek  */
776*00b67f09SDavid van Moolenbroek 
777*00b67f09SDavid van Moolenbroek static void
rdatasetiter_destroy(dns_rdatasetiter_t ** iteratorp)778*00b67f09SDavid van Moolenbroek rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
779*00b67f09SDavid van Moolenbroek 	isc_mem_t *mctx;
780*00b67f09SDavid van Moolenbroek 	union {
781*00b67f09SDavid van Moolenbroek 		dns_rdatasetiter_t *rdatasetiterator;
782*00b67f09SDavid van Moolenbroek 		ecdb_rdatasetiter_t *ecdbiterator;
783*00b67f09SDavid van Moolenbroek 	} u;
784*00b67f09SDavid van Moolenbroek 
785*00b67f09SDavid van Moolenbroek 	REQUIRE(iteratorp != NULL);
786*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_RDATASETITER_VALID(*iteratorp));
787*00b67f09SDavid van Moolenbroek 
788*00b67f09SDavid van Moolenbroek 	u.rdatasetiterator = *iteratorp;
789*00b67f09SDavid van Moolenbroek 
790*00b67f09SDavid van Moolenbroek 	mctx = u.ecdbiterator->common.db->mctx;
791*00b67f09SDavid van Moolenbroek 	u.ecdbiterator->common.magic = 0;
792*00b67f09SDavid van Moolenbroek 
793*00b67f09SDavid van Moolenbroek 	dns_db_detachnode(u.ecdbiterator->common.db,
794*00b67f09SDavid van Moolenbroek 			  &u.ecdbiterator->common.node);
795*00b67f09SDavid van Moolenbroek 	isc_mem_put(mctx, u.ecdbiterator,
796*00b67f09SDavid van Moolenbroek 		    sizeof(ecdb_rdatasetiter_t));
797*00b67f09SDavid van Moolenbroek 
798*00b67f09SDavid van Moolenbroek 	*iteratorp = NULL;
799*00b67f09SDavid van Moolenbroek }
800*00b67f09SDavid van Moolenbroek 
801*00b67f09SDavid van Moolenbroek static isc_result_t
rdatasetiter_first(dns_rdatasetiter_t * iterator)802*00b67f09SDavid van Moolenbroek rdatasetiter_first(dns_rdatasetiter_t *iterator) {
803*00b67f09SDavid van Moolenbroek 	ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
804*00b67f09SDavid van Moolenbroek 	dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)iterator->node;
805*00b67f09SDavid van Moolenbroek 
806*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_RDATASETITER_VALID(iterator));
807*00b67f09SDavid van Moolenbroek 
808*00b67f09SDavid van Moolenbroek 	if (ISC_LIST_EMPTY(ecdbnode->rdatasets))
809*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMORE);
810*00b67f09SDavid van Moolenbroek 	ecdbiterator->current = ISC_LIST_HEAD(ecdbnode->rdatasets);
811*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
812*00b67f09SDavid van Moolenbroek }
813*00b67f09SDavid van Moolenbroek 
814*00b67f09SDavid van Moolenbroek static isc_result_t
rdatasetiter_next(dns_rdatasetiter_t * iterator)815*00b67f09SDavid van Moolenbroek rdatasetiter_next(dns_rdatasetiter_t *iterator) {
816*00b67f09SDavid van Moolenbroek 	ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
817*00b67f09SDavid van Moolenbroek 
818*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_RDATASETITER_VALID(iterator));
819*00b67f09SDavid van Moolenbroek 
820*00b67f09SDavid van Moolenbroek 	ecdbiterator->current = ISC_LIST_NEXT(ecdbiterator->current, link);
821*00b67f09SDavid van Moolenbroek 	if (ecdbiterator->current == NULL)
822*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMORE);
823*00b67f09SDavid van Moolenbroek 	else
824*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
825*00b67f09SDavid van Moolenbroek }
826*00b67f09SDavid van Moolenbroek 
827*00b67f09SDavid van Moolenbroek static void
rdatasetiter_current(dns_rdatasetiter_t * iterator,dns_rdataset_t * rdataset)828*00b67f09SDavid van Moolenbroek rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
829*00b67f09SDavid van Moolenbroek 	ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
830*00b67f09SDavid van Moolenbroek 	dns_ecdb_t *ecdb;
831*00b67f09SDavid van Moolenbroek 
832*00b67f09SDavid van Moolenbroek 	ecdb = (dns_ecdb_t *)iterator->db;
833*00b67f09SDavid van Moolenbroek 	REQUIRE(VALID_ECDB(ecdb));
834*00b67f09SDavid van Moolenbroek 
835*00b67f09SDavid van Moolenbroek 	bind_rdataset(ecdb, iterator->node, ecdbiterator->current, rdataset);
836*00b67f09SDavid van Moolenbroek }
837