xref: /minix3/external/bsd/bind/dist/lib/dns/view.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: view.c,v 1.10 2014/12/10 04:37:58 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2003  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek /*! \file */
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <config.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #include <isc/file.h>
27*00b67f09SDavid van Moolenbroek #include <isc/hash.h>
28*00b67f09SDavid van Moolenbroek #include <isc/print.h>
29*00b67f09SDavid van Moolenbroek #include <isc/sha2.h>
30*00b67f09SDavid van Moolenbroek #include <isc/stats.h>
31*00b67f09SDavid van Moolenbroek #include <isc/string.h>		/* Required for HP/UX (and others?) */
32*00b67f09SDavid van Moolenbroek #include <isc/task.h>
33*00b67f09SDavid van Moolenbroek #include <isc/util.h>
34*00b67f09SDavid van Moolenbroek 
35*00b67f09SDavid van Moolenbroek #include <dns/acache.h>
36*00b67f09SDavid van Moolenbroek #include <dns/acl.h>
37*00b67f09SDavid van Moolenbroek #include <dns/adb.h>
38*00b67f09SDavid van Moolenbroek #include <dns/cache.h>
39*00b67f09SDavid van Moolenbroek #include <dns/db.h>
40*00b67f09SDavid van Moolenbroek #include <dns/dispatch.h>
41*00b67f09SDavid van Moolenbroek #include <dns/dlz.h>
42*00b67f09SDavid van Moolenbroek #include <dns/dns64.h>
43*00b67f09SDavid van Moolenbroek #include <dns/dnssec.h>
44*00b67f09SDavid van Moolenbroek #include <dns/events.h>
45*00b67f09SDavid van Moolenbroek #include <dns/forward.h>
46*00b67f09SDavid van Moolenbroek #include <dns/keytable.h>
47*00b67f09SDavid van Moolenbroek #include <dns/keyvalues.h>
48*00b67f09SDavid van Moolenbroek #include <dns/master.h>
49*00b67f09SDavid van Moolenbroek #include <dns/masterdump.h>
50*00b67f09SDavid van Moolenbroek #include <dns/order.h>
51*00b67f09SDavid van Moolenbroek #include <dns/peer.h>
52*00b67f09SDavid van Moolenbroek #include <dns/rrl.h>
53*00b67f09SDavid van Moolenbroek #include <dns/rbt.h>
54*00b67f09SDavid van Moolenbroek #include <dns/rdataset.h>
55*00b67f09SDavid van Moolenbroek #include <dns/request.h>
56*00b67f09SDavid van Moolenbroek #include <dns/resolver.h>
57*00b67f09SDavid van Moolenbroek #include <dns/result.h>
58*00b67f09SDavid van Moolenbroek #include <dns/rpz.h>
59*00b67f09SDavid van Moolenbroek #include <dns/stats.h>
60*00b67f09SDavid van Moolenbroek #include <dns/tsig.h>
61*00b67f09SDavid van Moolenbroek #include <dns/zone.h>
62*00b67f09SDavid van Moolenbroek #include <dns/zt.h>
63*00b67f09SDavid van Moolenbroek 
64*00b67f09SDavid van Moolenbroek #define RESSHUTDOWN(v)	(((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0)
65*00b67f09SDavid van Moolenbroek #define ADBSHUTDOWN(v)	(((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
66*00b67f09SDavid van Moolenbroek #define REQSHUTDOWN(v)	(((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0)
67*00b67f09SDavid van Moolenbroek 
68*00b67f09SDavid van Moolenbroek #define DNS_VIEW_DELONLYHASH 111
69*00b67f09SDavid van Moolenbroek 
70*00b67f09SDavid van Moolenbroek static void resolver_shutdown(isc_task_t *task, isc_event_t *event);
71*00b67f09SDavid van Moolenbroek static void adb_shutdown(isc_task_t *task, isc_event_t *event);
72*00b67f09SDavid van Moolenbroek static void req_shutdown(isc_task_t *task, isc_event_t *event);
73*00b67f09SDavid van Moolenbroek 
74*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_create(isc_mem_t * mctx,dns_rdataclass_t rdclass,const char * name,dns_view_t ** viewp)75*00b67f09SDavid van Moolenbroek dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
76*00b67f09SDavid van Moolenbroek 		const char *name, dns_view_t **viewp)
77*00b67f09SDavid van Moolenbroek {
78*00b67f09SDavid van Moolenbroek 	dns_view_t *view;
79*00b67f09SDavid van Moolenbroek 	isc_result_t result;
80*00b67f09SDavid van Moolenbroek 
81*00b67f09SDavid van Moolenbroek 	/*
82*00b67f09SDavid van Moolenbroek 	 * Create a view.
83*00b67f09SDavid van Moolenbroek 	 */
84*00b67f09SDavid van Moolenbroek 
85*00b67f09SDavid van Moolenbroek 	REQUIRE(name != NULL);
86*00b67f09SDavid van Moolenbroek 	REQUIRE(viewp != NULL && *viewp == NULL);
87*00b67f09SDavid van Moolenbroek 
88*00b67f09SDavid van Moolenbroek 	view = isc_mem_get(mctx, sizeof(*view));
89*00b67f09SDavid van Moolenbroek 	if (view == NULL)
90*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
91*00b67f09SDavid van Moolenbroek 
92*00b67f09SDavid van Moolenbroek 	view->mctx = NULL;
93*00b67f09SDavid van Moolenbroek 	isc_mem_attach(mctx, &view->mctx);
94*00b67f09SDavid van Moolenbroek 	view->name = isc_mem_strdup(mctx, name);
95*00b67f09SDavid van Moolenbroek 	if (view->name == NULL) {
96*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
97*00b67f09SDavid van Moolenbroek 		goto cleanup_view;
98*00b67f09SDavid van Moolenbroek 	}
99*00b67f09SDavid van Moolenbroek 	result = isc_mutex_init(&view->lock);
100*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
101*00b67f09SDavid van Moolenbroek 		goto cleanup_name;
102*00b67f09SDavid van Moolenbroek 
103*00b67f09SDavid van Moolenbroek 	view->zonetable = NULL;
104*00b67f09SDavid van Moolenbroek 	if (isc_bind9) {
105*00b67f09SDavid van Moolenbroek 		result = dns_zt_create(mctx, rdclass, &view->zonetable);
106*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
107*00b67f09SDavid van Moolenbroek 			UNEXPECTED_ERROR(__FILE__, __LINE__,
108*00b67f09SDavid van Moolenbroek 					 "dns_zt_create() failed: %s",
109*00b67f09SDavid van Moolenbroek 					 isc_result_totext(result));
110*00b67f09SDavid van Moolenbroek 			result = ISC_R_UNEXPECTED;
111*00b67f09SDavid van Moolenbroek 			goto cleanup_mutex;
112*00b67f09SDavid van Moolenbroek 		}
113*00b67f09SDavid van Moolenbroek 	}
114*00b67f09SDavid van Moolenbroek 	view->secroots_priv = NULL;
115*00b67f09SDavid van Moolenbroek 	view->fwdtable = NULL;
116*00b67f09SDavid van Moolenbroek 	result = dns_fwdtable_create(mctx, &view->fwdtable);
117*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
118*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
119*00b67f09SDavid van Moolenbroek 				 "dns_fwdtable_create() failed: %s",
120*00b67f09SDavid van Moolenbroek 				 isc_result_totext(result));
121*00b67f09SDavid van Moolenbroek 		result = ISC_R_UNEXPECTED;
122*00b67f09SDavid van Moolenbroek 		goto cleanup_zt;
123*00b67f09SDavid van Moolenbroek 	}
124*00b67f09SDavid van Moolenbroek 
125*00b67f09SDavid van Moolenbroek 	view->acache = NULL;
126*00b67f09SDavid van Moolenbroek 	view->cache = NULL;
127*00b67f09SDavid van Moolenbroek 	view->cachedb = NULL;
128*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(view->dlz_searched);
129*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(view->dlz_unsearched);
130*00b67f09SDavid van Moolenbroek 	view->hints = NULL;
131*00b67f09SDavid van Moolenbroek 	view->resolver = NULL;
132*00b67f09SDavid van Moolenbroek 	view->adb = NULL;
133*00b67f09SDavid van Moolenbroek 	view->requestmgr = NULL;
134*00b67f09SDavid van Moolenbroek 	view->rdclass = rdclass;
135*00b67f09SDavid van Moolenbroek 	view->frozen = ISC_FALSE;
136*00b67f09SDavid van Moolenbroek 	view->task = NULL;
137*00b67f09SDavid van Moolenbroek 	result = isc_refcount_init(&view->references, 1);
138*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
139*00b67f09SDavid van Moolenbroek 		goto cleanup_fwdtable;
140*00b67f09SDavid van Moolenbroek 	view->weakrefs = 0;
141*00b67f09SDavid van Moolenbroek 	view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
142*00b67f09SDavid van Moolenbroek 			    DNS_VIEWATTR_REQSHUTDOWN);
143*00b67f09SDavid van Moolenbroek 	view->statickeys = NULL;
144*00b67f09SDavid van Moolenbroek 	view->dynamickeys = NULL;
145*00b67f09SDavid van Moolenbroek 	view->matchclients = NULL;
146*00b67f09SDavid van Moolenbroek 	view->matchdestinations = NULL;
147*00b67f09SDavid van Moolenbroek 	view->matchrecursiveonly = ISC_FALSE;
148*00b67f09SDavid van Moolenbroek 	result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
149*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
150*00b67f09SDavid van Moolenbroek 		goto cleanup_references;
151*00b67f09SDavid van Moolenbroek 	view->peers = NULL;
152*00b67f09SDavid van Moolenbroek 	view->order = NULL;
153*00b67f09SDavid van Moolenbroek 	view->delonly = NULL;
154*00b67f09SDavid van Moolenbroek 	view->rootdelonly = ISC_FALSE;
155*00b67f09SDavid van Moolenbroek 	view->rootexclude = NULL;
156*00b67f09SDavid van Moolenbroek 	view->adbstats = NULL;
157*00b67f09SDavid van Moolenbroek 	view->resstats = NULL;
158*00b67f09SDavid van Moolenbroek 	view->resquerystats = NULL;
159*00b67f09SDavid van Moolenbroek 	view->cacheshared = ISC_FALSE;
160*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(view->dns64);
161*00b67f09SDavid van Moolenbroek 	view->dns64cnt = 0;
162*00b67f09SDavid van Moolenbroek 
163*00b67f09SDavid van Moolenbroek 	/*
164*00b67f09SDavid van Moolenbroek 	 * Initialize configuration data with default values.
165*00b67f09SDavid van Moolenbroek 	 */
166*00b67f09SDavid van Moolenbroek 	view->recursion = ISC_TRUE;
167*00b67f09SDavid van Moolenbroek 	view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */
168*00b67f09SDavid van Moolenbroek 	view->additionalfromcache = ISC_TRUE;
169*00b67f09SDavid van Moolenbroek 	view->additionalfromauth = ISC_TRUE;
170*00b67f09SDavid van Moolenbroek 	view->enablednssec = ISC_TRUE;
171*00b67f09SDavid van Moolenbroek 	view->enablevalidation = ISC_TRUE;
172*00b67f09SDavid van Moolenbroek 	view->acceptexpired = ISC_FALSE;
173*00b67f09SDavid van Moolenbroek 	view->minimalresponses = ISC_FALSE;
174*00b67f09SDavid van Moolenbroek 	view->transfer_format = dns_one_answer;
175*00b67f09SDavid van Moolenbroek 	view->cacheacl = NULL;
176*00b67f09SDavid van Moolenbroek 	view->cacheonacl = NULL;
177*00b67f09SDavid van Moolenbroek 	view->queryacl = NULL;
178*00b67f09SDavid van Moolenbroek 	view->queryonacl = NULL;
179*00b67f09SDavid van Moolenbroek 	view->recursionacl = NULL;
180*00b67f09SDavid van Moolenbroek 	view->recursiononacl = NULL;
181*00b67f09SDavid van Moolenbroek 	view->sortlist = NULL;
182*00b67f09SDavid van Moolenbroek 	view->transferacl = NULL;
183*00b67f09SDavid van Moolenbroek 	view->notifyacl = NULL;
184*00b67f09SDavid van Moolenbroek 	view->updateacl = NULL;
185*00b67f09SDavid van Moolenbroek 	view->upfwdacl = NULL;
186*00b67f09SDavid van Moolenbroek 	view->denyansweracl = NULL;
187*00b67f09SDavid van Moolenbroek 	view->nocasecompress = NULL;
188*00b67f09SDavid van Moolenbroek 	view->answeracl_exclude = NULL;
189*00b67f09SDavid van Moolenbroek 	view->denyanswernames = NULL;
190*00b67f09SDavid van Moolenbroek 	view->answernames_exclude = NULL;
191*00b67f09SDavid van Moolenbroek 	view->rrl = NULL;
192*00b67f09SDavid van Moolenbroek 	view->provideixfr = ISC_TRUE;
193*00b67f09SDavid van Moolenbroek 	view->maxcachettl = 7 * 24 * 3600;
194*00b67f09SDavid van Moolenbroek 	view->maxncachettl = 3 * 3600;
195*00b67f09SDavid van Moolenbroek 	view->prefetch_eligible = 0;
196*00b67f09SDavid van Moolenbroek 	view->prefetch_trigger = 0;
197*00b67f09SDavid van Moolenbroek 	view->dstport = 53;
198*00b67f09SDavid van Moolenbroek 	view->preferred_glue = 0;
199*00b67f09SDavid van Moolenbroek 	view->flush = ISC_FALSE;
200*00b67f09SDavid van Moolenbroek 	view->dlv = NULL;
201*00b67f09SDavid van Moolenbroek 	view->maxudp = 0;
202*00b67f09SDavid van Moolenbroek 	view->situdp = 0;
203*00b67f09SDavid van Moolenbroek 	view->maxbits = 0;
204*00b67f09SDavid van Moolenbroek 	view->v4_aaaa = dns_aaaa_ok;
205*00b67f09SDavid van Moolenbroek 	view->v6_aaaa = dns_aaaa_ok;
206*00b67f09SDavid van Moolenbroek 	view->aaaa_acl = NULL;
207*00b67f09SDavid van Moolenbroek 	view->rpzs = NULL;
208*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&view->dlv_fixed);
209*00b67f09SDavid van Moolenbroek 	view->managed_keys = NULL;
210*00b67f09SDavid van Moolenbroek 	view->redirect = NULL;
211*00b67f09SDavid van Moolenbroek 	view->requestnsid = ISC_FALSE;
212*00b67f09SDavid van Moolenbroek 	view->requestsit = ISC_TRUE;
213*00b67f09SDavid van Moolenbroek 	view->new_zone_file = NULL;
214*00b67f09SDavid van Moolenbroek 	view->new_zone_config = NULL;
215*00b67f09SDavid van Moolenbroek 	view->cfg_destroy = NULL;
216*00b67f09SDavid van Moolenbroek 
217*00b67f09SDavid van Moolenbroek 	if (isc_bind9) {
218*00b67f09SDavid van Moolenbroek 		result = dns_order_create(view->mctx, &view->order);
219*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
220*00b67f09SDavid van Moolenbroek 			goto cleanup_dynkeys;
221*00b67f09SDavid van Moolenbroek 	}
222*00b67f09SDavid van Moolenbroek 
223*00b67f09SDavid van Moolenbroek 	result = dns_peerlist_new(view->mctx, &view->peers);
224*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
225*00b67f09SDavid van Moolenbroek 		goto cleanup_order;
226*00b67f09SDavid van Moolenbroek 
227*00b67f09SDavid van Moolenbroek 	result = dns_aclenv_init(view->mctx, &view->aclenv);
228*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
229*00b67f09SDavid van Moolenbroek 		goto cleanup_peerlist;
230*00b67f09SDavid van Moolenbroek 
231*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(view, link);
232*00b67f09SDavid van Moolenbroek 	ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL,
233*00b67f09SDavid van Moolenbroek 		       DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown,
234*00b67f09SDavid van Moolenbroek 		       view, NULL, NULL, NULL);
235*00b67f09SDavid van Moolenbroek 	ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL,
236*00b67f09SDavid van Moolenbroek 		       DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown,
237*00b67f09SDavid van Moolenbroek 		       view, NULL, NULL, NULL);
238*00b67f09SDavid van Moolenbroek 	ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL,
239*00b67f09SDavid van Moolenbroek 		       DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown,
240*00b67f09SDavid van Moolenbroek 		       view, NULL, NULL, NULL);
241*00b67f09SDavid van Moolenbroek 	view->viewlist = NULL;
242*00b67f09SDavid van Moolenbroek 	view->magic = DNS_VIEW_MAGIC;
243*00b67f09SDavid van Moolenbroek 
244*00b67f09SDavid van Moolenbroek 	*viewp = view;
245*00b67f09SDavid van Moolenbroek 
246*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
247*00b67f09SDavid van Moolenbroek 
248*00b67f09SDavid van Moolenbroek  cleanup_peerlist:
249*00b67f09SDavid van Moolenbroek 	if (view->peers != NULL)
250*00b67f09SDavid van Moolenbroek 		dns_peerlist_detach(&view->peers);
251*00b67f09SDavid van Moolenbroek 
252*00b67f09SDavid van Moolenbroek  cleanup_order:
253*00b67f09SDavid van Moolenbroek 	if (view->order != NULL)
254*00b67f09SDavid van Moolenbroek 		dns_order_detach(&view->order);
255*00b67f09SDavid van Moolenbroek 
256*00b67f09SDavid van Moolenbroek  cleanup_dynkeys:
257*00b67f09SDavid van Moolenbroek 	if (view->dynamickeys != NULL)
258*00b67f09SDavid van Moolenbroek 		dns_tsigkeyring_detach(&view->dynamickeys);
259*00b67f09SDavid van Moolenbroek 
260*00b67f09SDavid van Moolenbroek  cleanup_references:
261*00b67f09SDavid van Moolenbroek 	isc_refcount_destroy(&view->references);
262*00b67f09SDavid van Moolenbroek 
263*00b67f09SDavid van Moolenbroek  cleanup_fwdtable:
264*00b67f09SDavid van Moolenbroek 	if (view->fwdtable != NULL)
265*00b67f09SDavid van Moolenbroek 		dns_fwdtable_destroy(&view->fwdtable);
266*00b67f09SDavid van Moolenbroek 
267*00b67f09SDavid van Moolenbroek  cleanup_zt:
268*00b67f09SDavid van Moolenbroek 	if (view->zonetable != NULL)
269*00b67f09SDavid van Moolenbroek 		dns_zt_detach(&view->zonetable);
270*00b67f09SDavid van Moolenbroek 
271*00b67f09SDavid van Moolenbroek  cleanup_mutex:
272*00b67f09SDavid van Moolenbroek 	DESTROYLOCK(&view->lock);
273*00b67f09SDavid van Moolenbroek 
274*00b67f09SDavid van Moolenbroek  cleanup_name:
275*00b67f09SDavid van Moolenbroek 	isc_mem_free(mctx, view->name);
276*00b67f09SDavid van Moolenbroek 
277*00b67f09SDavid van Moolenbroek  cleanup_view:
278*00b67f09SDavid van Moolenbroek 	isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
279*00b67f09SDavid van Moolenbroek 
280*00b67f09SDavid van Moolenbroek 	return (result);
281*00b67f09SDavid van Moolenbroek }
282*00b67f09SDavid van Moolenbroek 
283*00b67f09SDavid van Moolenbroek static inline void
destroy(dns_view_t * view)284*00b67f09SDavid van Moolenbroek destroy(dns_view_t *view) {
285*00b67f09SDavid van Moolenbroek 	dns_dns64_t *dns64;
286*00b67f09SDavid van Moolenbroek 	dns_dlzdb_t *dlzdb;
287*00b67f09SDavid van Moolenbroek 
288*00b67f09SDavid van Moolenbroek 	REQUIRE(!ISC_LINK_LINKED(view, link));
289*00b67f09SDavid van Moolenbroek 	REQUIRE(isc_refcount_current(&view->references) == 0);
290*00b67f09SDavid van Moolenbroek 	REQUIRE(view->weakrefs == 0);
291*00b67f09SDavid van Moolenbroek 	REQUIRE(RESSHUTDOWN(view));
292*00b67f09SDavid van Moolenbroek 	REQUIRE(ADBSHUTDOWN(view));
293*00b67f09SDavid van Moolenbroek 	REQUIRE(REQSHUTDOWN(view));
294*00b67f09SDavid van Moolenbroek 
295*00b67f09SDavid van Moolenbroek 	if (view->order != NULL)
296*00b67f09SDavid van Moolenbroek 		dns_order_detach(&view->order);
297*00b67f09SDavid van Moolenbroek 	if (view->peers != NULL)
298*00b67f09SDavid van Moolenbroek 		dns_peerlist_detach(&view->peers);
299*00b67f09SDavid van Moolenbroek 
300*00b67f09SDavid van Moolenbroek 	if (view->dynamickeys != NULL) {
301*00b67f09SDavid van Moolenbroek 		isc_result_t result;
302*00b67f09SDavid van Moolenbroek 		char template[20];
303*00b67f09SDavid van Moolenbroek 		char keyfile[20];
304*00b67f09SDavid van Moolenbroek 		FILE *fp = NULL;
305*00b67f09SDavid van Moolenbroek 		int n;
306*00b67f09SDavid van Moolenbroek 
307*00b67f09SDavid van Moolenbroek 		n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys",
308*00b67f09SDavid van Moolenbroek 			     view->name);
309*00b67f09SDavid van Moolenbroek 		if (n > 0 && (size_t)n < sizeof(keyfile)) {
310*00b67f09SDavid van Moolenbroek 			result = isc_file_mktemplate(keyfile, template,
311*00b67f09SDavid van Moolenbroek 						     sizeof(template));
312*00b67f09SDavid van Moolenbroek 			if (result == ISC_R_SUCCESS)
313*00b67f09SDavid van Moolenbroek 				(void)isc_file_openuniqueprivate(template, &fp);
314*00b67f09SDavid van Moolenbroek 		}
315*00b67f09SDavid van Moolenbroek 		if (fp == NULL)
316*00b67f09SDavid van Moolenbroek 			dns_tsigkeyring_detach(&view->dynamickeys);
317*00b67f09SDavid van Moolenbroek 		else {
318*00b67f09SDavid van Moolenbroek 			result = dns_tsigkeyring_dumpanddetach(
319*00b67f09SDavid van Moolenbroek 							&view->dynamickeys, fp);
320*00b67f09SDavid van Moolenbroek 			if (result == ISC_R_SUCCESS) {
321*00b67f09SDavid van Moolenbroek 				if (fclose(fp) == 0)
322*00b67f09SDavid van Moolenbroek 					result = isc_file_rename(template,
323*00b67f09SDavid van Moolenbroek 								 keyfile);
324*00b67f09SDavid van Moolenbroek 				if (result != ISC_R_SUCCESS)
325*00b67f09SDavid van Moolenbroek 					(void)remove(template);
326*00b67f09SDavid van Moolenbroek 			} else {
327*00b67f09SDavid van Moolenbroek 				(void)fclose(fp);
328*00b67f09SDavid van Moolenbroek 				(void)remove(template);
329*00b67f09SDavid van Moolenbroek 			}
330*00b67f09SDavid van Moolenbroek 		}
331*00b67f09SDavid van Moolenbroek 	}
332*00b67f09SDavid van Moolenbroek 	if (view->statickeys != NULL)
333*00b67f09SDavid van Moolenbroek 		dns_tsigkeyring_detach(&view->statickeys);
334*00b67f09SDavid van Moolenbroek 	if (view->adb != NULL)
335*00b67f09SDavid van Moolenbroek 		dns_adb_detach(&view->adb);
336*00b67f09SDavid van Moolenbroek 	if (view->resolver != NULL)
337*00b67f09SDavid van Moolenbroek 		dns_resolver_detach(&view->resolver);
338*00b67f09SDavid van Moolenbroek 	if (view->acache != NULL) {
339*00b67f09SDavid van Moolenbroek 		if (view->cachedb != NULL)
340*00b67f09SDavid van Moolenbroek 			dns_acache_putdb(view->acache, view->cachedb);
341*00b67f09SDavid van Moolenbroek 		dns_acache_detach(&view->acache);
342*00b67f09SDavid van Moolenbroek 	}
343*00b67f09SDavid van Moolenbroek 	dns_rrl_view_destroy(view);
344*00b67f09SDavid van Moolenbroek 	if (view->rpzs != NULL)
345*00b67f09SDavid van Moolenbroek 		dns_rpz_detach_rpzs(&view->rpzs);
346*00b67f09SDavid van Moolenbroek 	for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
347*00b67f09SDavid van Moolenbroek 	     dlzdb != NULL;
348*00b67f09SDavid van Moolenbroek 	     dlzdb = ISC_LIST_HEAD(view->dlz_searched)) {
349*00b67f09SDavid van Moolenbroek 		ISC_LIST_UNLINK(view->dlz_searched, dlzdb, link);
350*00b67f09SDavid van Moolenbroek 		dns_dlzdestroy(&dlzdb);
351*00b67f09SDavid van Moolenbroek 	}
352*00b67f09SDavid van Moolenbroek 	for (dlzdb = ISC_LIST_HEAD(view->dlz_unsearched);
353*00b67f09SDavid van Moolenbroek 	     dlzdb != NULL;
354*00b67f09SDavid van Moolenbroek 	     dlzdb = ISC_LIST_HEAD(view->dlz_unsearched)) {
355*00b67f09SDavid van Moolenbroek 		ISC_LIST_UNLINK(view->dlz_unsearched, dlzdb, link);
356*00b67f09SDavid van Moolenbroek 		dns_dlzdestroy(&dlzdb);
357*00b67f09SDavid van Moolenbroek 	}
358*00b67f09SDavid van Moolenbroek 	if (view->requestmgr != NULL)
359*00b67f09SDavid van Moolenbroek 		dns_requestmgr_detach(&view->requestmgr);
360*00b67f09SDavid van Moolenbroek 	if (view->task != NULL)
361*00b67f09SDavid van Moolenbroek 		isc_task_detach(&view->task);
362*00b67f09SDavid van Moolenbroek 	if (view->hints != NULL)
363*00b67f09SDavid van Moolenbroek 		dns_db_detach(&view->hints);
364*00b67f09SDavid van Moolenbroek 	if (view->cachedb != NULL)
365*00b67f09SDavid van Moolenbroek 		dns_db_detach(&view->cachedb);
366*00b67f09SDavid van Moolenbroek 	if (view->cache != NULL)
367*00b67f09SDavid van Moolenbroek 		dns_cache_detach(&view->cache);
368*00b67f09SDavid van Moolenbroek 	if (view->nocasecompress != NULL)
369*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->nocasecompress);
370*00b67f09SDavid van Moolenbroek 	if (view->matchclients != NULL)
371*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->matchclients);
372*00b67f09SDavid van Moolenbroek 	if (view->matchdestinations != NULL)
373*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->matchdestinations);
374*00b67f09SDavid van Moolenbroek 	if (view->cacheacl != NULL)
375*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->cacheacl);
376*00b67f09SDavid van Moolenbroek 	if (view->cacheonacl != NULL)
377*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->cacheonacl);
378*00b67f09SDavid van Moolenbroek 	if (view->queryacl != NULL)
379*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->queryacl);
380*00b67f09SDavid van Moolenbroek 	if (view->queryonacl != NULL)
381*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->queryonacl);
382*00b67f09SDavid van Moolenbroek 	if (view->recursionacl != NULL)
383*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->recursionacl);
384*00b67f09SDavid van Moolenbroek 	if (view->recursiononacl != NULL)
385*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->recursiononacl);
386*00b67f09SDavid van Moolenbroek 	if (view->sortlist != NULL)
387*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->sortlist);
388*00b67f09SDavid van Moolenbroek 	if (view->transferacl != NULL)
389*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->transferacl);
390*00b67f09SDavid van Moolenbroek 	if (view->notifyacl != NULL)
391*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->notifyacl);
392*00b67f09SDavid van Moolenbroek 	if (view->updateacl != NULL)
393*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->updateacl);
394*00b67f09SDavid van Moolenbroek 	if (view->upfwdacl != NULL)
395*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->upfwdacl);
396*00b67f09SDavid van Moolenbroek 	if (view->denyansweracl != NULL)
397*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->denyansweracl);
398*00b67f09SDavid van Moolenbroek 	if (view->aaaa_acl != NULL)
399*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&view->aaaa_acl);
400*00b67f09SDavid van Moolenbroek 	if (view->answeracl_exclude != NULL)
401*00b67f09SDavid van Moolenbroek 		dns_rbt_destroy(&view->answeracl_exclude);
402*00b67f09SDavid van Moolenbroek 	if (view->denyanswernames != NULL)
403*00b67f09SDavid van Moolenbroek 		dns_rbt_destroy(&view->denyanswernames);
404*00b67f09SDavid van Moolenbroek 	if (view->answernames_exclude != NULL)
405*00b67f09SDavid van Moolenbroek 		dns_rbt_destroy(&view->answernames_exclude);
406*00b67f09SDavid van Moolenbroek 	if (view->delonly != NULL) {
407*00b67f09SDavid van Moolenbroek 		dns_name_t *name;
408*00b67f09SDavid van Moolenbroek 		int i;
409*00b67f09SDavid van Moolenbroek 
410*00b67f09SDavid van Moolenbroek 		for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
411*00b67f09SDavid van Moolenbroek 			name = ISC_LIST_HEAD(view->delonly[i]);
412*00b67f09SDavid van Moolenbroek 			while (name != NULL) {
413*00b67f09SDavid van Moolenbroek 				ISC_LIST_UNLINK(view->delonly[i], name, link);
414*00b67f09SDavid van Moolenbroek 				dns_name_free(name, view->mctx);
415*00b67f09SDavid van Moolenbroek 				isc_mem_put(view->mctx, name, sizeof(*name));
416*00b67f09SDavid van Moolenbroek 				name = ISC_LIST_HEAD(view->delonly[i]);
417*00b67f09SDavid van Moolenbroek 			}
418*00b67f09SDavid van Moolenbroek 		}
419*00b67f09SDavid van Moolenbroek 		isc_mem_put(view->mctx, view->delonly, sizeof(dns_namelist_t) *
420*00b67f09SDavid van Moolenbroek 			    DNS_VIEW_DELONLYHASH);
421*00b67f09SDavid van Moolenbroek 		view->delonly = NULL;
422*00b67f09SDavid van Moolenbroek 	}
423*00b67f09SDavid van Moolenbroek 	if (view->rootexclude != NULL) {
424*00b67f09SDavid van Moolenbroek 		dns_name_t *name;
425*00b67f09SDavid van Moolenbroek 		int i;
426*00b67f09SDavid van Moolenbroek 
427*00b67f09SDavid van Moolenbroek 		for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
428*00b67f09SDavid van Moolenbroek 			name = ISC_LIST_HEAD(view->rootexclude[i]);
429*00b67f09SDavid van Moolenbroek 			while (name != NULL) {
430*00b67f09SDavid van Moolenbroek 				ISC_LIST_UNLINK(view->rootexclude[i],
431*00b67f09SDavid van Moolenbroek 						name, link);
432*00b67f09SDavid van Moolenbroek 				dns_name_free(name, view->mctx);
433*00b67f09SDavid van Moolenbroek 				isc_mem_put(view->mctx, name, sizeof(*name));
434*00b67f09SDavid van Moolenbroek 				name = ISC_LIST_HEAD(view->rootexclude[i]);
435*00b67f09SDavid van Moolenbroek 			}
436*00b67f09SDavid van Moolenbroek 		}
437*00b67f09SDavid van Moolenbroek 		isc_mem_put(view->mctx, view->rootexclude,
438*00b67f09SDavid van Moolenbroek 			    sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH);
439*00b67f09SDavid van Moolenbroek 		view->rootexclude = NULL;
440*00b67f09SDavid van Moolenbroek 	}
441*00b67f09SDavid van Moolenbroek 	if (view->adbstats != NULL)
442*00b67f09SDavid van Moolenbroek 		isc_stats_detach(&view->adbstats);
443*00b67f09SDavid van Moolenbroek 	if (view->resstats != NULL)
444*00b67f09SDavid van Moolenbroek 		isc_stats_detach(&view->resstats);
445*00b67f09SDavid van Moolenbroek 	if (view->resquerystats != NULL)
446*00b67f09SDavid van Moolenbroek 		dns_stats_detach(&view->resquerystats);
447*00b67f09SDavid van Moolenbroek 	if (view->secroots_priv != NULL)
448*00b67f09SDavid van Moolenbroek 		dns_keytable_detach(&view->secroots_priv);
449*00b67f09SDavid van Moolenbroek 	for (dns64 = ISC_LIST_HEAD(view->dns64);
450*00b67f09SDavid van Moolenbroek 	     dns64 != NULL;
451*00b67f09SDavid van Moolenbroek 	     dns64 = ISC_LIST_HEAD(view->dns64)) {
452*00b67f09SDavid van Moolenbroek 		dns_dns64_unlink(&view->dns64, dns64);
453*00b67f09SDavid van Moolenbroek 		dns_dns64_destroy(&dns64);
454*00b67f09SDavid van Moolenbroek 	}
455*00b67f09SDavid van Moolenbroek 	if (view->managed_keys != NULL)
456*00b67f09SDavid van Moolenbroek 		dns_zone_detach(&view->managed_keys);
457*00b67f09SDavid van Moolenbroek 	if (view->redirect != NULL)
458*00b67f09SDavid van Moolenbroek 		dns_zone_detach(&view->redirect);
459*00b67f09SDavid van Moolenbroek 	dns_view_setnewzones(view, ISC_FALSE, NULL, NULL);
460*00b67f09SDavid van Moolenbroek 	dns_fwdtable_destroy(&view->fwdtable);
461*00b67f09SDavid van Moolenbroek 	dns_aclenv_destroy(&view->aclenv);
462*00b67f09SDavid van Moolenbroek 	DESTROYLOCK(&view->lock);
463*00b67f09SDavid van Moolenbroek 	isc_refcount_destroy(&view->references);
464*00b67f09SDavid van Moolenbroek 	isc_mem_free(view->mctx, view->name);
465*00b67f09SDavid van Moolenbroek 	isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
466*00b67f09SDavid van Moolenbroek }
467*00b67f09SDavid van Moolenbroek 
468*00b67f09SDavid van Moolenbroek /*
469*00b67f09SDavid van Moolenbroek  * Return true iff 'view' may be freed.
470*00b67f09SDavid van Moolenbroek  * The caller must be holding the view lock.
471*00b67f09SDavid van Moolenbroek  */
472*00b67f09SDavid van Moolenbroek static isc_boolean_t
all_done(dns_view_t * view)473*00b67f09SDavid van Moolenbroek all_done(dns_view_t *view) {
474*00b67f09SDavid van Moolenbroek 
475*00b67f09SDavid van Moolenbroek 	if (isc_refcount_current(&view->references) == 0 &&
476*00b67f09SDavid van Moolenbroek 	    view->weakrefs == 0 &&
477*00b67f09SDavid van Moolenbroek 	    RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view))
478*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
479*00b67f09SDavid van Moolenbroek 
480*00b67f09SDavid van Moolenbroek 	return (ISC_FALSE);
481*00b67f09SDavid van Moolenbroek }
482*00b67f09SDavid van Moolenbroek 
483*00b67f09SDavid van Moolenbroek void
dns_view_attach(dns_view_t * source,dns_view_t ** targetp)484*00b67f09SDavid van Moolenbroek dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
485*00b67f09SDavid van Moolenbroek 
486*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(source));
487*00b67f09SDavid van Moolenbroek 	REQUIRE(targetp != NULL && *targetp == NULL);
488*00b67f09SDavid van Moolenbroek 
489*00b67f09SDavid van Moolenbroek 	isc_refcount_increment(&source->references, NULL);
490*00b67f09SDavid van Moolenbroek 
491*00b67f09SDavid van Moolenbroek 	*targetp = source;
492*00b67f09SDavid van Moolenbroek }
493*00b67f09SDavid van Moolenbroek 
494*00b67f09SDavid van Moolenbroek static void
view_flushanddetach(dns_view_t ** viewp,isc_boolean_t flush)495*00b67f09SDavid van Moolenbroek view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) {
496*00b67f09SDavid van Moolenbroek 	dns_view_t *view;
497*00b67f09SDavid van Moolenbroek 	unsigned int refs;
498*00b67f09SDavid van Moolenbroek 	isc_boolean_t done = ISC_FALSE;
499*00b67f09SDavid van Moolenbroek 
500*00b67f09SDavid van Moolenbroek 	REQUIRE(viewp != NULL);
501*00b67f09SDavid van Moolenbroek 	view = *viewp;
502*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
503*00b67f09SDavid van Moolenbroek 
504*00b67f09SDavid van Moolenbroek 	if (flush)
505*00b67f09SDavid van Moolenbroek 		view->flush = ISC_TRUE;
506*00b67f09SDavid van Moolenbroek 	isc_refcount_decrement(&view->references, &refs);
507*00b67f09SDavid van Moolenbroek 	if (refs == 0) {
508*00b67f09SDavid van Moolenbroek 		dns_zone_t *mkzone = NULL, *rdzone = NULL;
509*00b67f09SDavid van Moolenbroek 
510*00b67f09SDavid van Moolenbroek 		LOCK(&view->lock);
511*00b67f09SDavid van Moolenbroek 		if (!RESSHUTDOWN(view))
512*00b67f09SDavid van Moolenbroek 			dns_resolver_shutdown(view->resolver);
513*00b67f09SDavid van Moolenbroek 		if (!ADBSHUTDOWN(view))
514*00b67f09SDavid van Moolenbroek 			dns_adb_shutdown(view->adb);
515*00b67f09SDavid van Moolenbroek 		if (!REQSHUTDOWN(view))
516*00b67f09SDavid van Moolenbroek 			dns_requestmgr_shutdown(view->requestmgr);
517*00b67f09SDavid van Moolenbroek 		if (view->acache != NULL)
518*00b67f09SDavid van Moolenbroek 			dns_acache_shutdown(view->acache);
519*00b67f09SDavid van Moolenbroek 		if (view->zonetable != NULL) {
520*00b67f09SDavid van Moolenbroek 			if (view->flush)
521*00b67f09SDavid van Moolenbroek 				dns_zt_flushanddetach(&view->zonetable);
522*00b67f09SDavid van Moolenbroek 			else
523*00b67f09SDavid van Moolenbroek 				dns_zt_detach(&view->zonetable);
524*00b67f09SDavid van Moolenbroek 		}
525*00b67f09SDavid van Moolenbroek 		if (view->managed_keys != NULL) {
526*00b67f09SDavid van Moolenbroek 			mkzone = view->managed_keys;
527*00b67f09SDavid van Moolenbroek 			view->managed_keys = NULL;
528*00b67f09SDavid van Moolenbroek 			if (view->flush)
529*00b67f09SDavid van Moolenbroek 				dns_zone_flush(mkzone);
530*00b67f09SDavid van Moolenbroek 		}
531*00b67f09SDavid van Moolenbroek 		if (view->redirect != NULL) {
532*00b67f09SDavid van Moolenbroek 			rdzone = view->redirect;
533*00b67f09SDavid van Moolenbroek 			view->redirect = NULL;
534*00b67f09SDavid van Moolenbroek 			if (view->flush)
535*00b67f09SDavid van Moolenbroek 				dns_zone_flush(rdzone);
536*00b67f09SDavid van Moolenbroek 		}
537*00b67f09SDavid van Moolenbroek 		done = all_done(view);
538*00b67f09SDavid van Moolenbroek 		UNLOCK(&view->lock);
539*00b67f09SDavid van Moolenbroek 
540*00b67f09SDavid van Moolenbroek 		/* Need to detach zones outside view lock */
541*00b67f09SDavid van Moolenbroek 		if (mkzone != NULL)
542*00b67f09SDavid van Moolenbroek 			dns_zone_detach(&mkzone);
543*00b67f09SDavid van Moolenbroek 
544*00b67f09SDavid van Moolenbroek 		if (rdzone != NULL)
545*00b67f09SDavid van Moolenbroek 			dns_zone_detach(&rdzone);
546*00b67f09SDavid van Moolenbroek 	}
547*00b67f09SDavid van Moolenbroek 
548*00b67f09SDavid van Moolenbroek 	*viewp = NULL;
549*00b67f09SDavid van Moolenbroek 
550*00b67f09SDavid van Moolenbroek 	if (done)
551*00b67f09SDavid van Moolenbroek 		destroy(view);
552*00b67f09SDavid van Moolenbroek }
553*00b67f09SDavid van Moolenbroek 
554*00b67f09SDavid van Moolenbroek void
dns_view_flushanddetach(dns_view_t ** viewp)555*00b67f09SDavid van Moolenbroek dns_view_flushanddetach(dns_view_t **viewp) {
556*00b67f09SDavid van Moolenbroek 	view_flushanddetach(viewp, ISC_TRUE);
557*00b67f09SDavid van Moolenbroek }
558*00b67f09SDavid van Moolenbroek 
559*00b67f09SDavid van Moolenbroek void
dns_view_detach(dns_view_t ** viewp)560*00b67f09SDavid van Moolenbroek dns_view_detach(dns_view_t **viewp) {
561*00b67f09SDavid van Moolenbroek 	view_flushanddetach(viewp, ISC_FALSE);
562*00b67f09SDavid van Moolenbroek }
563*00b67f09SDavid van Moolenbroek 
564*00b67f09SDavid van Moolenbroek static isc_result_t
dialup(dns_zone_t * zone,void * dummy)565*00b67f09SDavid van Moolenbroek dialup(dns_zone_t *zone, void *dummy) {
566*00b67f09SDavid van Moolenbroek 	UNUSED(dummy);
567*00b67f09SDavid van Moolenbroek 	dns_zone_dialup(zone);
568*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
569*00b67f09SDavid van Moolenbroek }
570*00b67f09SDavid van Moolenbroek 
571*00b67f09SDavid van Moolenbroek void
dns_view_dialup(dns_view_t * view)572*00b67f09SDavid van Moolenbroek dns_view_dialup(dns_view_t *view) {
573*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
574*00b67f09SDavid van Moolenbroek 	REQUIRE(view->zonetable != NULL);
575*00b67f09SDavid van Moolenbroek 
576*00b67f09SDavid van Moolenbroek 	(void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL);
577*00b67f09SDavid van Moolenbroek }
578*00b67f09SDavid van Moolenbroek 
579*00b67f09SDavid van Moolenbroek void
dns_view_weakattach(dns_view_t * source,dns_view_t ** targetp)580*00b67f09SDavid van Moolenbroek dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) {
581*00b67f09SDavid van Moolenbroek 
582*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(source));
583*00b67f09SDavid van Moolenbroek 	REQUIRE(targetp != NULL && *targetp == NULL);
584*00b67f09SDavid van Moolenbroek 
585*00b67f09SDavid van Moolenbroek 	LOCK(&source->lock);
586*00b67f09SDavid van Moolenbroek 	source->weakrefs++;
587*00b67f09SDavid van Moolenbroek 	UNLOCK(&source->lock);
588*00b67f09SDavid van Moolenbroek 
589*00b67f09SDavid van Moolenbroek 	*targetp = source;
590*00b67f09SDavid van Moolenbroek }
591*00b67f09SDavid van Moolenbroek 
592*00b67f09SDavid van Moolenbroek void
dns_view_weakdetach(dns_view_t ** viewp)593*00b67f09SDavid van Moolenbroek dns_view_weakdetach(dns_view_t **viewp) {
594*00b67f09SDavid van Moolenbroek 	dns_view_t *view;
595*00b67f09SDavid van Moolenbroek 	isc_boolean_t done = ISC_FALSE;
596*00b67f09SDavid van Moolenbroek 
597*00b67f09SDavid van Moolenbroek 	REQUIRE(viewp != NULL);
598*00b67f09SDavid van Moolenbroek 	view = *viewp;
599*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
600*00b67f09SDavid van Moolenbroek 
601*00b67f09SDavid van Moolenbroek 	LOCK(&view->lock);
602*00b67f09SDavid van Moolenbroek 
603*00b67f09SDavid van Moolenbroek 	INSIST(view->weakrefs > 0);
604*00b67f09SDavid van Moolenbroek 	view->weakrefs--;
605*00b67f09SDavid van Moolenbroek 	done = all_done(view);
606*00b67f09SDavid van Moolenbroek 
607*00b67f09SDavid van Moolenbroek 	UNLOCK(&view->lock);
608*00b67f09SDavid van Moolenbroek 
609*00b67f09SDavid van Moolenbroek 	*viewp = NULL;
610*00b67f09SDavid van Moolenbroek 
611*00b67f09SDavid van Moolenbroek 	if (done)
612*00b67f09SDavid van Moolenbroek 		destroy(view);
613*00b67f09SDavid van Moolenbroek }
614*00b67f09SDavid van Moolenbroek 
615*00b67f09SDavid van Moolenbroek static void
resolver_shutdown(isc_task_t * task,isc_event_t * event)616*00b67f09SDavid van Moolenbroek resolver_shutdown(isc_task_t *task, isc_event_t *event) {
617*00b67f09SDavid van Moolenbroek 	dns_view_t *view = event->ev_arg;
618*00b67f09SDavid van Moolenbroek 	isc_boolean_t done;
619*00b67f09SDavid van Moolenbroek 
620*00b67f09SDavid van Moolenbroek 	REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN);
621*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
622*00b67f09SDavid van Moolenbroek 	REQUIRE(view->task == task);
623*00b67f09SDavid van Moolenbroek 
624*00b67f09SDavid van Moolenbroek 	UNUSED(task);
625*00b67f09SDavid van Moolenbroek 
626*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
627*00b67f09SDavid van Moolenbroek 
628*00b67f09SDavid van Moolenbroek 	LOCK(&view->lock);
629*00b67f09SDavid van Moolenbroek 
630*00b67f09SDavid van Moolenbroek 	view->attributes |= DNS_VIEWATTR_RESSHUTDOWN;
631*00b67f09SDavid van Moolenbroek 	done = all_done(view);
632*00b67f09SDavid van Moolenbroek 
633*00b67f09SDavid van Moolenbroek 	UNLOCK(&view->lock);
634*00b67f09SDavid van Moolenbroek 
635*00b67f09SDavid van Moolenbroek 	if (done)
636*00b67f09SDavid van Moolenbroek 		destroy(view);
637*00b67f09SDavid van Moolenbroek }
638*00b67f09SDavid van Moolenbroek 
639*00b67f09SDavid van Moolenbroek static void
adb_shutdown(isc_task_t * task,isc_event_t * event)640*00b67f09SDavid van Moolenbroek adb_shutdown(isc_task_t *task, isc_event_t *event) {
641*00b67f09SDavid van Moolenbroek 	dns_view_t *view = event->ev_arg;
642*00b67f09SDavid van Moolenbroek 	isc_boolean_t done;
643*00b67f09SDavid van Moolenbroek 
644*00b67f09SDavid van Moolenbroek 	REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN);
645*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
646*00b67f09SDavid van Moolenbroek 	REQUIRE(view->task == task);
647*00b67f09SDavid van Moolenbroek 
648*00b67f09SDavid van Moolenbroek 	UNUSED(task);
649*00b67f09SDavid van Moolenbroek 
650*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
651*00b67f09SDavid van Moolenbroek 
652*00b67f09SDavid van Moolenbroek 	LOCK(&view->lock);
653*00b67f09SDavid van Moolenbroek 
654*00b67f09SDavid van Moolenbroek 	view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN;
655*00b67f09SDavid van Moolenbroek 	done = all_done(view);
656*00b67f09SDavid van Moolenbroek 
657*00b67f09SDavid van Moolenbroek 	UNLOCK(&view->lock);
658*00b67f09SDavid van Moolenbroek 
659*00b67f09SDavid van Moolenbroek 	if (done)
660*00b67f09SDavid van Moolenbroek 		destroy(view);
661*00b67f09SDavid van Moolenbroek }
662*00b67f09SDavid van Moolenbroek 
663*00b67f09SDavid van Moolenbroek static void
req_shutdown(isc_task_t * task,isc_event_t * event)664*00b67f09SDavid van Moolenbroek req_shutdown(isc_task_t *task, isc_event_t *event) {
665*00b67f09SDavid van Moolenbroek 	dns_view_t *view = event->ev_arg;
666*00b67f09SDavid van Moolenbroek 	isc_boolean_t done;
667*00b67f09SDavid van Moolenbroek 
668*00b67f09SDavid van Moolenbroek 	REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN);
669*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
670*00b67f09SDavid van Moolenbroek 	REQUIRE(view->task == task);
671*00b67f09SDavid van Moolenbroek 
672*00b67f09SDavid van Moolenbroek 	UNUSED(task);
673*00b67f09SDavid van Moolenbroek 
674*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
675*00b67f09SDavid van Moolenbroek 
676*00b67f09SDavid van Moolenbroek 	LOCK(&view->lock);
677*00b67f09SDavid van Moolenbroek 
678*00b67f09SDavid van Moolenbroek 	view->attributes |= DNS_VIEWATTR_REQSHUTDOWN;
679*00b67f09SDavid van Moolenbroek 	done = all_done(view);
680*00b67f09SDavid van Moolenbroek 
681*00b67f09SDavid van Moolenbroek 	UNLOCK(&view->lock);
682*00b67f09SDavid van Moolenbroek 
683*00b67f09SDavid van Moolenbroek 	if (done)
684*00b67f09SDavid van Moolenbroek 		destroy(view);
685*00b67f09SDavid van Moolenbroek }
686*00b67f09SDavid van Moolenbroek 
687*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_createzonetable(dns_view_t * view)688*00b67f09SDavid van Moolenbroek dns_view_createzonetable(dns_view_t *view) {
689*00b67f09SDavid van Moolenbroek 
690*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
691*00b67f09SDavid van Moolenbroek 	REQUIRE(!view->frozen);
692*00b67f09SDavid van Moolenbroek 	REQUIRE(view->zonetable == NULL);
693*00b67f09SDavid van Moolenbroek 
694*00b67f09SDavid van Moolenbroek 	return (dns_zt_create(view->mctx, view->rdclass, &view->zonetable));
695*00b67f09SDavid van Moolenbroek }
696*00b67f09SDavid van Moolenbroek 
697*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_createresolver(dns_view_t * view,isc_taskmgr_t * taskmgr,unsigned int ntasks,unsigned int ndisp,isc_socketmgr_t * socketmgr,isc_timermgr_t * timermgr,unsigned int options,dns_dispatchmgr_t * dispatchmgr,dns_dispatch_t * dispatchv4,dns_dispatch_t * dispatchv6)698*00b67f09SDavid van Moolenbroek dns_view_createresolver(dns_view_t *view,
699*00b67f09SDavid van Moolenbroek 			isc_taskmgr_t *taskmgr,
700*00b67f09SDavid van Moolenbroek 			unsigned int ntasks, unsigned int ndisp,
701*00b67f09SDavid van Moolenbroek 			isc_socketmgr_t *socketmgr,
702*00b67f09SDavid van Moolenbroek 			isc_timermgr_t *timermgr,
703*00b67f09SDavid van Moolenbroek 			unsigned int options,
704*00b67f09SDavid van Moolenbroek 			dns_dispatchmgr_t *dispatchmgr,
705*00b67f09SDavid van Moolenbroek 			dns_dispatch_t *dispatchv4,
706*00b67f09SDavid van Moolenbroek 			dns_dispatch_t *dispatchv6)
707*00b67f09SDavid van Moolenbroek {
708*00b67f09SDavid van Moolenbroek 	isc_result_t result;
709*00b67f09SDavid van Moolenbroek 	isc_event_t *event;
710*00b67f09SDavid van Moolenbroek 	isc_mem_t *mctx = NULL;
711*00b67f09SDavid van Moolenbroek 
712*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
713*00b67f09SDavid van Moolenbroek 	REQUIRE(!view->frozen);
714*00b67f09SDavid van Moolenbroek 	REQUIRE(view->resolver == NULL);
715*00b67f09SDavid van Moolenbroek 
716*00b67f09SDavid van Moolenbroek 	result = isc_task_create(taskmgr, 0, &view->task);
717*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
718*00b67f09SDavid van Moolenbroek 		return (result);
719*00b67f09SDavid van Moolenbroek 	isc_task_setname(view->task, "view", view);
720*00b67f09SDavid van Moolenbroek 
721*00b67f09SDavid van Moolenbroek 	result = dns_resolver_create(view, taskmgr, ntasks, ndisp, socketmgr,
722*00b67f09SDavid van Moolenbroek 				     timermgr, options, dispatchmgr,
723*00b67f09SDavid van Moolenbroek 				     dispatchv4, dispatchv6,
724*00b67f09SDavid van Moolenbroek 				     &view->resolver);
725*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
726*00b67f09SDavid van Moolenbroek 		isc_task_detach(&view->task);
727*00b67f09SDavid van Moolenbroek 		return (result);
728*00b67f09SDavid van Moolenbroek 	}
729*00b67f09SDavid van Moolenbroek 	event = &view->resevent;
730*00b67f09SDavid van Moolenbroek 	dns_resolver_whenshutdown(view->resolver, view->task, &event);
731*00b67f09SDavid van Moolenbroek 	view->attributes &= ~DNS_VIEWATTR_RESSHUTDOWN;
732*00b67f09SDavid van Moolenbroek 
733*00b67f09SDavid van Moolenbroek 	result = isc_mem_create(0, 0, &mctx);
734*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
735*00b67f09SDavid van Moolenbroek 		dns_resolver_shutdown(view->resolver);
736*00b67f09SDavid van Moolenbroek 		return (result);
737*00b67f09SDavid van Moolenbroek 	}
738*00b67f09SDavid van Moolenbroek 
739*00b67f09SDavid van Moolenbroek 	result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb);
740*00b67f09SDavid van Moolenbroek 	isc_mem_setname(mctx, "ADB", NULL);
741*00b67f09SDavid van Moolenbroek 	isc_mem_detach(&mctx);
742*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
743*00b67f09SDavid van Moolenbroek 		dns_resolver_shutdown(view->resolver);
744*00b67f09SDavid van Moolenbroek 		return (result);
745*00b67f09SDavid van Moolenbroek 	}
746*00b67f09SDavid van Moolenbroek 	event = &view->adbevent;
747*00b67f09SDavid van Moolenbroek 	dns_adb_whenshutdown(view->adb, view->task, &event);
748*00b67f09SDavid van Moolenbroek 	view->attributes &= ~DNS_VIEWATTR_ADBSHUTDOWN;
749*00b67f09SDavid van Moolenbroek 
750*00b67f09SDavid van Moolenbroek 	result = dns_requestmgr_create(view->mctx, timermgr, socketmgr,
751*00b67f09SDavid van Moolenbroek 				      dns_resolver_taskmgr(view->resolver),
752*00b67f09SDavid van Moolenbroek 				      dns_resolver_dispatchmgr(view->resolver),
753*00b67f09SDavid van Moolenbroek 				      dispatchv4, dispatchv6,
754*00b67f09SDavid van Moolenbroek 				      &view->requestmgr);
755*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
756*00b67f09SDavid van Moolenbroek 		dns_adb_shutdown(view->adb);
757*00b67f09SDavid van Moolenbroek 		dns_resolver_shutdown(view->resolver);
758*00b67f09SDavid van Moolenbroek 		return (result);
759*00b67f09SDavid van Moolenbroek 	}
760*00b67f09SDavid van Moolenbroek 	event = &view->reqevent;
761*00b67f09SDavid van Moolenbroek 	dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event);
762*00b67f09SDavid van Moolenbroek 	view->attributes &= ~DNS_VIEWATTR_REQSHUTDOWN;
763*00b67f09SDavid van Moolenbroek 
764*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
765*00b67f09SDavid van Moolenbroek }
766*00b67f09SDavid van Moolenbroek 
767*00b67f09SDavid van Moolenbroek void
dns_view_setcache(dns_view_t * view,dns_cache_t * cache)768*00b67f09SDavid van Moolenbroek dns_view_setcache(dns_view_t *view, dns_cache_t *cache) {
769*00b67f09SDavid van Moolenbroek 	dns_view_setcache2(view, cache, ISC_FALSE);
770*00b67f09SDavid van Moolenbroek }
771*00b67f09SDavid van Moolenbroek 
772*00b67f09SDavid van Moolenbroek void
dns_view_setcache2(dns_view_t * view,dns_cache_t * cache,isc_boolean_t shared)773*00b67f09SDavid van Moolenbroek dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared) {
774*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
775*00b67f09SDavid van Moolenbroek 	REQUIRE(!view->frozen);
776*00b67f09SDavid van Moolenbroek 
777*00b67f09SDavid van Moolenbroek 	view->cacheshared = shared;
778*00b67f09SDavid van Moolenbroek 	if (view->cache != NULL) {
779*00b67f09SDavid van Moolenbroek 		if (view->acache != NULL)
780*00b67f09SDavid van Moolenbroek 			dns_acache_putdb(view->acache, view->cachedb);
781*00b67f09SDavid van Moolenbroek 		dns_db_detach(&view->cachedb);
782*00b67f09SDavid van Moolenbroek 		dns_cache_detach(&view->cache);
783*00b67f09SDavid van Moolenbroek 	}
784*00b67f09SDavid van Moolenbroek 	dns_cache_attach(cache, &view->cache);
785*00b67f09SDavid van Moolenbroek 	dns_cache_attachdb(cache, &view->cachedb);
786*00b67f09SDavid van Moolenbroek 	INSIST(DNS_DB_VALID(view->cachedb));
787*00b67f09SDavid van Moolenbroek 
788*00b67f09SDavid van Moolenbroek 	if (view->acache != NULL)
789*00b67f09SDavid van Moolenbroek 		dns_acache_setdb(view->acache, view->cachedb);
790*00b67f09SDavid van Moolenbroek }
791*00b67f09SDavid van Moolenbroek 
792*00b67f09SDavid van Moolenbroek isc_boolean_t
dns_view_iscacheshared(dns_view_t * view)793*00b67f09SDavid van Moolenbroek dns_view_iscacheshared(dns_view_t *view) {
794*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
795*00b67f09SDavid van Moolenbroek 
796*00b67f09SDavid van Moolenbroek 	return (view->cacheshared);
797*00b67f09SDavid van Moolenbroek }
798*00b67f09SDavid van Moolenbroek 
799*00b67f09SDavid van Moolenbroek void
dns_view_sethints(dns_view_t * view,dns_db_t * hints)800*00b67f09SDavid van Moolenbroek dns_view_sethints(dns_view_t *view, dns_db_t *hints) {
801*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
802*00b67f09SDavid van Moolenbroek 	REQUIRE(!view->frozen);
803*00b67f09SDavid van Moolenbroek 	REQUIRE(view->hints == NULL);
804*00b67f09SDavid van Moolenbroek 	REQUIRE(dns_db_iszone(hints));
805*00b67f09SDavid van Moolenbroek 
806*00b67f09SDavid van Moolenbroek 	dns_db_attach(hints, &view->hints);
807*00b67f09SDavid van Moolenbroek }
808*00b67f09SDavid van Moolenbroek 
809*00b67f09SDavid van Moolenbroek void
dns_view_setkeyring(dns_view_t * view,dns_tsig_keyring_t * ring)810*00b67f09SDavid van Moolenbroek dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
811*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
812*00b67f09SDavid van Moolenbroek 	REQUIRE(ring != NULL);
813*00b67f09SDavid van Moolenbroek 	if (view->statickeys != NULL)
814*00b67f09SDavid van Moolenbroek 		dns_tsigkeyring_detach(&view->statickeys);
815*00b67f09SDavid van Moolenbroek 	dns_tsigkeyring_attach(ring, &view->statickeys);
816*00b67f09SDavid van Moolenbroek }
817*00b67f09SDavid van Moolenbroek 
818*00b67f09SDavid van Moolenbroek void
dns_view_setdynamickeyring(dns_view_t * view,dns_tsig_keyring_t * ring)819*00b67f09SDavid van Moolenbroek dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
820*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
821*00b67f09SDavid van Moolenbroek 	REQUIRE(ring != NULL);
822*00b67f09SDavid van Moolenbroek 	if (view->dynamickeys != NULL)
823*00b67f09SDavid van Moolenbroek 		dns_tsigkeyring_detach(&view->dynamickeys);
824*00b67f09SDavid van Moolenbroek 	dns_tsigkeyring_attach(ring, &view->dynamickeys);
825*00b67f09SDavid van Moolenbroek }
826*00b67f09SDavid van Moolenbroek 
827*00b67f09SDavid van Moolenbroek void
dns_view_getdynamickeyring(dns_view_t * view,dns_tsig_keyring_t ** ringp)828*00b67f09SDavid van Moolenbroek dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp) {
829*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
830*00b67f09SDavid van Moolenbroek 	REQUIRE(ringp != NULL && *ringp == NULL);
831*00b67f09SDavid van Moolenbroek 	if (view->dynamickeys != NULL)
832*00b67f09SDavid van Moolenbroek 		dns_tsigkeyring_attach(view->dynamickeys, ringp);
833*00b67f09SDavid van Moolenbroek }
834*00b67f09SDavid van Moolenbroek 
835*00b67f09SDavid van Moolenbroek void
dns_view_restorekeyring(dns_view_t * view)836*00b67f09SDavid van Moolenbroek dns_view_restorekeyring(dns_view_t *view) {
837*00b67f09SDavid van Moolenbroek 	FILE *fp;
838*00b67f09SDavid van Moolenbroek 	char keyfile[20];
839*00b67f09SDavid van Moolenbroek 	int n;
840*00b67f09SDavid van Moolenbroek 
841*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
842*00b67f09SDavid van Moolenbroek 
843*00b67f09SDavid van Moolenbroek 	if (view->dynamickeys != NULL) {
844*00b67f09SDavid van Moolenbroek 		n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys",
845*00b67f09SDavid van Moolenbroek 			     view->name);
846*00b67f09SDavid van Moolenbroek 		if (n > 0 && (size_t)n < sizeof(keyfile)) {
847*00b67f09SDavid van Moolenbroek 			fp = fopen(keyfile, "r");
848*00b67f09SDavid van Moolenbroek 			if (fp != NULL) {
849*00b67f09SDavid van Moolenbroek 				dns_keyring_restore(view->dynamickeys, fp);
850*00b67f09SDavid van Moolenbroek 				(void)fclose(fp);
851*00b67f09SDavid van Moolenbroek 			}
852*00b67f09SDavid van Moolenbroek 		}
853*00b67f09SDavid van Moolenbroek 	}
854*00b67f09SDavid van Moolenbroek }
855*00b67f09SDavid van Moolenbroek 
856*00b67f09SDavid van Moolenbroek void
dns_view_setdstport(dns_view_t * view,in_port_t dstport)857*00b67f09SDavid van Moolenbroek dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
858*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
859*00b67f09SDavid van Moolenbroek 	view->dstport = dstport;
860*00b67f09SDavid van Moolenbroek }
861*00b67f09SDavid van Moolenbroek 
862*00b67f09SDavid van Moolenbroek void
dns_view_freeze(dns_view_t * view)863*00b67f09SDavid van Moolenbroek dns_view_freeze(dns_view_t *view) {
864*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
865*00b67f09SDavid van Moolenbroek 	REQUIRE(!view->frozen);
866*00b67f09SDavid van Moolenbroek 
867*00b67f09SDavid van Moolenbroek 	if (view->resolver != NULL) {
868*00b67f09SDavid van Moolenbroek 		INSIST(view->cachedb != NULL);
869*00b67f09SDavid van Moolenbroek 		dns_resolver_freeze(view->resolver);
870*00b67f09SDavid van Moolenbroek 	}
871*00b67f09SDavid van Moolenbroek 	view->frozen = ISC_TRUE;
872*00b67f09SDavid van Moolenbroek }
873*00b67f09SDavid van Moolenbroek 
874*00b67f09SDavid van Moolenbroek void
dns_view_thaw(dns_view_t * view)875*00b67f09SDavid van Moolenbroek dns_view_thaw(dns_view_t *view) {
876*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
877*00b67f09SDavid van Moolenbroek 	REQUIRE(view->frozen);
878*00b67f09SDavid van Moolenbroek 
879*00b67f09SDavid van Moolenbroek 	view->frozen = ISC_FALSE;
880*00b67f09SDavid van Moolenbroek }
881*00b67f09SDavid van Moolenbroek 
882*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_addzone(dns_view_t * view,dns_zone_t * zone)883*00b67f09SDavid van Moolenbroek dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
884*00b67f09SDavid van Moolenbroek 	isc_result_t result;
885*00b67f09SDavid van Moolenbroek 
886*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
887*00b67f09SDavid van Moolenbroek 	REQUIRE(!view->frozen);
888*00b67f09SDavid van Moolenbroek 	REQUIRE(view->zonetable != NULL);
889*00b67f09SDavid van Moolenbroek 
890*00b67f09SDavid van Moolenbroek 	result = dns_zt_mount(view->zonetable, zone);
891*00b67f09SDavid van Moolenbroek 
892*00b67f09SDavid van Moolenbroek 	return (result);
893*00b67f09SDavid van Moolenbroek }
894*00b67f09SDavid van Moolenbroek 
895*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_findzone(dns_view_t * view,dns_name_t * name,dns_zone_t ** zonep)896*00b67f09SDavid van Moolenbroek dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) {
897*00b67f09SDavid van Moolenbroek 	isc_result_t result;
898*00b67f09SDavid van Moolenbroek 
899*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
900*00b67f09SDavid van Moolenbroek 
901*00b67f09SDavid van Moolenbroek 	LOCK(&view->lock);
902*00b67f09SDavid van Moolenbroek 	if (view->zonetable != NULL) {
903*00b67f09SDavid van Moolenbroek 		result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
904*00b67f09SDavid van Moolenbroek 		if (result == DNS_R_PARTIALMATCH) {
905*00b67f09SDavid van Moolenbroek 			dns_zone_detach(zonep);
906*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOTFOUND;
907*00b67f09SDavid van Moolenbroek 		}
908*00b67f09SDavid van Moolenbroek 	} else
909*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOTFOUND;
910*00b67f09SDavid van Moolenbroek 	UNLOCK(&view->lock);
911*00b67f09SDavid van Moolenbroek 
912*00b67f09SDavid van Moolenbroek 	return (result);
913*00b67f09SDavid van Moolenbroek }
914*00b67f09SDavid van Moolenbroek 
915*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_find(dns_view_t * view,dns_name_t * name,dns_rdatatype_t type,isc_stdtime_t now,unsigned int options,isc_boolean_t use_hints,dns_db_t ** dbp,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)916*00b67f09SDavid van Moolenbroek dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
917*00b67f09SDavid van Moolenbroek 	      isc_stdtime_t now, unsigned int options, isc_boolean_t use_hints,
918*00b67f09SDavid van Moolenbroek 	      dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
919*00b67f09SDavid van Moolenbroek 	      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
920*00b67f09SDavid van Moolenbroek 	return (dns_view_find2(view, name, type, now, options, use_hints,
921*00b67f09SDavid van Moolenbroek 			       ISC_FALSE, dbp, nodep, foundname, rdataset,
922*00b67f09SDavid van Moolenbroek 			       sigrdataset));
923*00b67f09SDavid van Moolenbroek }
924*00b67f09SDavid van Moolenbroek 
925*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_find2(dns_view_t * view,dns_name_t * name,dns_rdatatype_t type,isc_stdtime_t now,unsigned int options,isc_boolean_t use_hints,isc_boolean_t use_static_stub,dns_db_t ** dbp,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)926*00b67f09SDavid van Moolenbroek dns_view_find2(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
927*00b67f09SDavid van Moolenbroek 	       isc_stdtime_t now, unsigned int options,
928*00b67f09SDavid van Moolenbroek 	       isc_boolean_t use_hints, isc_boolean_t use_static_stub,
929*00b67f09SDavid van Moolenbroek 	       dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
930*00b67f09SDavid van Moolenbroek 	       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
931*00b67f09SDavid van Moolenbroek {
932*00b67f09SDavid van Moolenbroek 	isc_result_t result;
933*00b67f09SDavid van Moolenbroek 	dns_db_t *db, *zdb;
934*00b67f09SDavid van Moolenbroek 	dns_dbnode_t *node, *znode;
935*00b67f09SDavid van Moolenbroek 	isc_boolean_t is_cache, is_staticstub_zone;
936*00b67f09SDavid van Moolenbroek 	dns_rdataset_t zrdataset, zsigrdataset;
937*00b67f09SDavid van Moolenbroek 	dns_zone_t *zone;
938*00b67f09SDavid van Moolenbroek 
939*00b67f09SDavid van Moolenbroek 	/*
940*00b67f09SDavid van Moolenbroek 	 * Find an rdataset whose owner name is 'name', and whose type is
941*00b67f09SDavid van Moolenbroek 	 * 'type'.
942*00b67f09SDavid van Moolenbroek 	 */
943*00b67f09SDavid van Moolenbroek 
944*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
945*00b67f09SDavid van Moolenbroek 	REQUIRE(view->frozen);
946*00b67f09SDavid van Moolenbroek 	REQUIRE(type != dns_rdatatype_rrsig);
947*00b67f09SDavid van Moolenbroek 	REQUIRE(rdataset != NULL);  /* XXXBEW - remove this */
948*00b67f09SDavid van Moolenbroek 	REQUIRE(nodep == NULL || *nodep == NULL);
949*00b67f09SDavid van Moolenbroek 
950*00b67f09SDavid van Moolenbroek 	/*
951*00b67f09SDavid van Moolenbroek 	 * Initialize.
952*00b67f09SDavid van Moolenbroek 	 */
953*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&zrdataset);
954*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&zsigrdataset);
955*00b67f09SDavid van Moolenbroek 	zdb = NULL;
956*00b67f09SDavid van Moolenbroek 	znode = NULL;
957*00b67f09SDavid van Moolenbroek 
958*00b67f09SDavid van Moolenbroek 	/*
959*00b67f09SDavid van Moolenbroek 	 * Find a database to answer the query.
960*00b67f09SDavid van Moolenbroek 	 */
961*00b67f09SDavid van Moolenbroek 	db = NULL;
962*00b67f09SDavid van Moolenbroek 	node = NULL;
963*00b67f09SDavid van Moolenbroek 	is_staticstub_zone = ISC_FALSE;
964*00b67f09SDavid van Moolenbroek 	zone = NULL;
965*00b67f09SDavid van Moolenbroek 	LOCK(&view->lock);
966*00b67f09SDavid van Moolenbroek 	if (view->zonetable != NULL)
967*00b67f09SDavid van Moolenbroek 		result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
968*00b67f09SDavid van Moolenbroek 	else
969*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOTFOUND;
970*00b67f09SDavid van Moolenbroek 	UNLOCK(&view->lock);
971*00b67f09SDavid van Moolenbroek 	if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub &&
972*00b67f09SDavid van Moolenbroek 	    !use_static_stub)
973*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOTFOUND;
974*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
975*00b67f09SDavid van Moolenbroek 		result = dns_zone_getdb(zone, &db);
976*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS && view->cachedb != NULL)
977*00b67f09SDavid van Moolenbroek 			dns_db_attach(view->cachedb, &db);
978*00b67f09SDavid van Moolenbroek 		else if (result != ISC_R_SUCCESS)
979*00b67f09SDavid van Moolenbroek 			goto cleanup;
980*00b67f09SDavid van Moolenbroek 		if (dns_zone_gettype(zone) == dns_zone_staticstub &&
981*00b67f09SDavid van Moolenbroek 		    dns_name_equal(name, dns_zone_getorigin(zone))) {
982*00b67f09SDavid van Moolenbroek 			is_staticstub_zone = ISC_TRUE;
983*00b67f09SDavid van Moolenbroek 		}
984*00b67f09SDavid van Moolenbroek 	} else if (result == ISC_R_NOTFOUND && view->cachedb != NULL)
985*00b67f09SDavid van Moolenbroek 		dns_db_attach(view->cachedb, &db);
986*00b67f09SDavid van Moolenbroek 	else
987*00b67f09SDavid van Moolenbroek 		goto cleanup;
988*00b67f09SDavid van Moolenbroek 
989*00b67f09SDavid van Moolenbroek 	is_cache = dns_db_iscache(db);
990*00b67f09SDavid van Moolenbroek 
991*00b67f09SDavid van Moolenbroek  db_find:
992*00b67f09SDavid van Moolenbroek 	/*
993*00b67f09SDavid van Moolenbroek 	 * Now look for an answer in the database.
994*00b67f09SDavid van Moolenbroek 	 */
995*00b67f09SDavid van Moolenbroek 	result = dns_db_find(db, name, NULL, type, options,
996*00b67f09SDavid van Moolenbroek 			     now, &node, foundname, rdataset, sigrdataset);
997*00b67f09SDavid van Moolenbroek 
998*00b67f09SDavid van Moolenbroek 	if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) {
999*00b67f09SDavid van Moolenbroek 		if (dns_rdataset_isassociated(rdataset))
1000*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(rdataset);
1001*00b67f09SDavid van Moolenbroek 		if (sigrdataset != NULL &&
1002*00b67f09SDavid van Moolenbroek 		    dns_rdataset_isassociated(sigrdataset))
1003*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(sigrdataset);
1004*00b67f09SDavid van Moolenbroek 		if (node != NULL)
1005*00b67f09SDavid van Moolenbroek 			dns_db_detachnode(db, &node);
1006*00b67f09SDavid van Moolenbroek 		if (!is_cache) {
1007*00b67f09SDavid van Moolenbroek 			dns_db_detach(&db);
1008*00b67f09SDavid van Moolenbroek 			if (view->cachedb != NULL && !is_staticstub_zone) {
1009*00b67f09SDavid van Moolenbroek 				/*
1010*00b67f09SDavid van Moolenbroek 				 * Either the answer is in the cache, or we
1011*00b67f09SDavid van Moolenbroek 				 * don't know it.
1012*00b67f09SDavid van Moolenbroek 				 * Note that if the result comes from a
1013*00b67f09SDavid van Moolenbroek 				 * static-stub zone we stop the search here
1014*00b67f09SDavid van Moolenbroek 				 * (see the function description in view.h).
1015*00b67f09SDavid van Moolenbroek 				 */
1016*00b67f09SDavid van Moolenbroek 				is_cache = ISC_TRUE;
1017*00b67f09SDavid van Moolenbroek 				dns_db_attach(view->cachedb, &db);
1018*00b67f09SDavid van Moolenbroek 				goto db_find;
1019*00b67f09SDavid van Moolenbroek 			}
1020*00b67f09SDavid van Moolenbroek 		} else {
1021*00b67f09SDavid van Moolenbroek 			/*
1022*00b67f09SDavid van Moolenbroek 			 * We don't have the data in the cache.  If we've got
1023*00b67f09SDavid van Moolenbroek 			 * glue from the zone, use it.
1024*00b67f09SDavid van Moolenbroek 			 */
1025*00b67f09SDavid van Moolenbroek 			if (dns_rdataset_isassociated(&zrdataset)) {
1026*00b67f09SDavid van Moolenbroek 				dns_rdataset_clone(&zrdataset, rdataset);
1027*00b67f09SDavid van Moolenbroek 				if (sigrdataset != NULL &&
1028*00b67f09SDavid van Moolenbroek 				    dns_rdataset_isassociated(&zsigrdataset))
1029*00b67f09SDavid van Moolenbroek 					dns_rdataset_clone(&zsigrdataset,
1030*00b67f09SDavid van Moolenbroek 							   sigrdataset);
1031*00b67f09SDavid van Moolenbroek 				result = DNS_R_GLUE;
1032*00b67f09SDavid van Moolenbroek 				if (db != NULL)
1033*00b67f09SDavid van Moolenbroek 					dns_db_detach(&db);
1034*00b67f09SDavid van Moolenbroek 				dns_db_attach(zdb, &db);
1035*00b67f09SDavid van Moolenbroek 				dns_db_attachnode(db, znode, &node);
1036*00b67f09SDavid van Moolenbroek 				goto cleanup;
1037*00b67f09SDavid van Moolenbroek 			}
1038*00b67f09SDavid van Moolenbroek 		}
1039*00b67f09SDavid van Moolenbroek 		/*
1040*00b67f09SDavid van Moolenbroek 		 * We don't know the answer.
1041*00b67f09SDavid van Moolenbroek 		 */
1042*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOTFOUND;
1043*00b67f09SDavid van Moolenbroek 	} else if (result == DNS_R_GLUE) {
1044*00b67f09SDavid van Moolenbroek 		if (view->cachedb != NULL && !is_staticstub_zone) {
1045*00b67f09SDavid van Moolenbroek 			/*
1046*00b67f09SDavid van Moolenbroek 			 * We found an answer, but the cache may be better.
1047*00b67f09SDavid van Moolenbroek 			 * Remember what we've got and go look in the cache.
1048*00b67f09SDavid van Moolenbroek 			 */
1049*00b67f09SDavid van Moolenbroek 			is_cache = ISC_TRUE;
1050*00b67f09SDavid van Moolenbroek 			dns_rdataset_clone(rdataset, &zrdataset);
1051*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(rdataset);
1052*00b67f09SDavid van Moolenbroek 			if (sigrdataset != NULL &&
1053*00b67f09SDavid van Moolenbroek 			    dns_rdataset_isassociated(sigrdataset)) {
1054*00b67f09SDavid van Moolenbroek 				dns_rdataset_clone(sigrdataset, &zsigrdataset);
1055*00b67f09SDavid van Moolenbroek 				dns_rdataset_disassociate(sigrdataset);
1056*00b67f09SDavid van Moolenbroek 			}
1057*00b67f09SDavid van Moolenbroek 			dns_db_attach(db, &zdb);
1058*00b67f09SDavid van Moolenbroek 			dns_db_attachnode(zdb, node, &znode);
1059*00b67f09SDavid van Moolenbroek 			dns_db_detachnode(db, &node);
1060*00b67f09SDavid van Moolenbroek 			dns_db_detach(&db);
1061*00b67f09SDavid van Moolenbroek 			dns_db_attach(view->cachedb, &db);
1062*00b67f09SDavid van Moolenbroek 			goto db_find;
1063*00b67f09SDavid van Moolenbroek 		}
1064*00b67f09SDavid van Moolenbroek 		/*
1065*00b67f09SDavid van Moolenbroek 		 * Otherwise, the glue is the best answer.
1066*00b67f09SDavid van Moolenbroek 		 */
1067*00b67f09SDavid van Moolenbroek 		result = ISC_R_SUCCESS;
1068*00b67f09SDavid van Moolenbroek 	}
1069*00b67f09SDavid van Moolenbroek 
1070*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
1071*00b67f09SDavid van Moolenbroek 		if (dns_rdataset_isassociated(rdataset))
1072*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(rdataset);
1073*00b67f09SDavid van Moolenbroek 		if (sigrdataset != NULL &&
1074*00b67f09SDavid van Moolenbroek 		    dns_rdataset_isassociated(sigrdataset))
1075*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(sigrdataset);
1076*00b67f09SDavid van Moolenbroek 		if (db != NULL) {
1077*00b67f09SDavid van Moolenbroek 			if (node != NULL)
1078*00b67f09SDavid van Moolenbroek 				dns_db_detachnode(db, &node);
1079*00b67f09SDavid van Moolenbroek 			dns_db_detach(&db);
1080*00b67f09SDavid van Moolenbroek 		}
1081*00b67f09SDavid van Moolenbroek 		result = dns_db_find(view->hints, name, NULL, type, options,
1082*00b67f09SDavid van Moolenbroek 				     now, &node, foundname,
1083*00b67f09SDavid van Moolenbroek 				     rdataset, sigrdataset);
1084*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) {
1085*00b67f09SDavid van Moolenbroek 			/*
1086*00b67f09SDavid van Moolenbroek 			 * We just used a hint.  Let the resolver know it
1087*00b67f09SDavid van Moolenbroek 			 * should consider priming.
1088*00b67f09SDavid van Moolenbroek 			 */
1089*00b67f09SDavid van Moolenbroek 			dns_resolver_prime(view->resolver);
1090*00b67f09SDavid van Moolenbroek 			dns_db_attach(view->hints, &db);
1091*00b67f09SDavid van Moolenbroek 			result = DNS_R_HINT;
1092*00b67f09SDavid van Moolenbroek 		} else if (result == DNS_R_NXRRSET) {
1093*00b67f09SDavid van Moolenbroek 			dns_db_attach(view->hints, &db);
1094*00b67f09SDavid van Moolenbroek 			result = DNS_R_HINTNXRRSET;
1095*00b67f09SDavid van Moolenbroek 		} else if (result == DNS_R_NXDOMAIN)
1096*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOTFOUND;
1097*00b67f09SDavid van Moolenbroek 
1098*00b67f09SDavid van Moolenbroek 		/*
1099*00b67f09SDavid van Moolenbroek 		 * Cleanup if non-standard hints are used.
1100*00b67f09SDavid van Moolenbroek 		 */
1101*00b67f09SDavid van Moolenbroek 		if (db == NULL && node != NULL)
1102*00b67f09SDavid van Moolenbroek 			dns_db_detachnode(view->hints, &node);
1103*00b67f09SDavid van Moolenbroek 	}
1104*00b67f09SDavid van Moolenbroek 
1105*00b67f09SDavid van Moolenbroek  cleanup:
1106*00b67f09SDavid van Moolenbroek 	if (dns_rdataset_isassociated(&zrdataset)) {
1107*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&zrdataset);
1108*00b67f09SDavid van Moolenbroek 		if (dns_rdataset_isassociated(&zsigrdataset))
1109*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(&zsigrdataset);
1110*00b67f09SDavid van Moolenbroek 	}
1111*00b67f09SDavid van Moolenbroek 
1112*00b67f09SDavid van Moolenbroek 	if (zdb != NULL) {
1113*00b67f09SDavid van Moolenbroek 		if (znode != NULL)
1114*00b67f09SDavid van Moolenbroek 			dns_db_detachnode(zdb, &znode);
1115*00b67f09SDavid van Moolenbroek 		dns_db_detach(&zdb);
1116*00b67f09SDavid van Moolenbroek 	}
1117*00b67f09SDavid van Moolenbroek 
1118*00b67f09SDavid van Moolenbroek 	if (db != NULL) {
1119*00b67f09SDavid van Moolenbroek 		if (node != NULL) {
1120*00b67f09SDavid van Moolenbroek 			if (nodep != NULL)
1121*00b67f09SDavid van Moolenbroek 				*nodep = node;
1122*00b67f09SDavid van Moolenbroek 			else
1123*00b67f09SDavid van Moolenbroek 				dns_db_detachnode(db, &node);
1124*00b67f09SDavid van Moolenbroek 		}
1125*00b67f09SDavid van Moolenbroek 		if (dbp != NULL)
1126*00b67f09SDavid van Moolenbroek 			*dbp = db;
1127*00b67f09SDavid van Moolenbroek 		else
1128*00b67f09SDavid van Moolenbroek 			dns_db_detach(&db);
1129*00b67f09SDavid van Moolenbroek 	} else
1130*00b67f09SDavid van Moolenbroek 		INSIST(node == NULL);
1131*00b67f09SDavid van Moolenbroek 
1132*00b67f09SDavid van Moolenbroek 	if (zone != NULL)
1133*00b67f09SDavid van Moolenbroek 		dns_zone_detach(&zone);
1134*00b67f09SDavid van Moolenbroek 
1135*00b67f09SDavid van Moolenbroek 	return (result);
1136*00b67f09SDavid van Moolenbroek }
1137*00b67f09SDavid van Moolenbroek 
1138*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_simplefind(dns_view_t * view,dns_name_t * name,dns_rdatatype_t type,isc_stdtime_t now,unsigned int options,isc_boolean_t use_hints,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)1139*00b67f09SDavid van Moolenbroek dns_view_simplefind(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
1140*00b67f09SDavid van Moolenbroek 		    isc_stdtime_t now, unsigned int options,
1141*00b67f09SDavid van Moolenbroek 		    isc_boolean_t use_hints,
1142*00b67f09SDavid van Moolenbroek 		    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
1143*00b67f09SDavid van Moolenbroek {
1144*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1145*00b67f09SDavid van Moolenbroek 	dns_fixedname_t foundname;
1146*00b67f09SDavid van Moolenbroek 
1147*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&foundname);
1148*00b67f09SDavid van Moolenbroek 	result = dns_view_find(view, name, type, now, options, use_hints,
1149*00b67f09SDavid van Moolenbroek 			       NULL, NULL, dns_fixedname_name(&foundname),
1150*00b67f09SDavid van Moolenbroek 			       rdataset, sigrdataset);
1151*00b67f09SDavid van Moolenbroek 	if (result == DNS_R_NXDOMAIN) {
1152*00b67f09SDavid van Moolenbroek 		/*
1153*00b67f09SDavid van Moolenbroek 		 * The rdataset and sigrdataset of the relevant NSEC record
1154*00b67f09SDavid van Moolenbroek 		 * may be returned, but the caller cannot use them because
1155*00b67f09SDavid van Moolenbroek 		 * foundname is not returned by this simplified API.  We
1156*00b67f09SDavid van Moolenbroek 		 * disassociate them here to prevent any misuse by the caller.
1157*00b67f09SDavid van Moolenbroek 		 */
1158*00b67f09SDavid van Moolenbroek 		if (dns_rdataset_isassociated(rdataset))
1159*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(rdataset);
1160*00b67f09SDavid van Moolenbroek 		if (sigrdataset != NULL &&
1161*00b67f09SDavid van Moolenbroek 		    dns_rdataset_isassociated(sigrdataset))
1162*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(sigrdataset);
1163*00b67f09SDavid van Moolenbroek 	} else if (result != ISC_R_SUCCESS &&
1164*00b67f09SDavid van Moolenbroek 		   result != DNS_R_GLUE &&
1165*00b67f09SDavid van Moolenbroek 		   result != DNS_R_HINT &&
1166*00b67f09SDavid van Moolenbroek 		   result != DNS_R_NCACHENXDOMAIN &&
1167*00b67f09SDavid van Moolenbroek 		   result != DNS_R_NCACHENXRRSET &&
1168*00b67f09SDavid van Moolenbroek 		   result != DNS_R_NXRRSET &&
1169*00b67f09SDavid van Moolenbroek 		   result != DNS_R_HINTNXRRSET &&
1170*00b67f09SDavid van Moolenbroek 		   result != ISC_R_NOTFOUND) {
1171*00b67f09SDavid van Moolenbroek 		if (dns_rdataset_isassociated(rdataset))
1172*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(rdataset);
1173*00b67f09SDavid van Moolenbroek 		if (sigrdataset != NULL &&
1174*00b67f09SDavid van Moolenbroek 		    dns_rdataset_isassociated(sigrdataset))
1175*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(sigrdataset);
1176*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOTFOUND;
1177*00b67f09SDavid van Moolenbroek 	}
1178*00b67f09SDavid van Moolenbroek 
1179*00b67f09SDavid van Moolenbroek 	return (result);
1180*00b67f09SDavid van Moolenbroek }
1181*00b67f09SDavid van Moolenbroek 
1182*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_findzonecut(dns_view_t * view,dns_name_t * name,dns_name_t * fname,isc_stdtime_t now,unsigned int options,isc_boolean_t use_hints,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)1183*00b67f09SDavid van Moolenbroek dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
1184*00b67f09SDavid van Moolenbroek 		     isc_stdtime_t now, unsigned int options,
1185*00b67f09SDavid van Moolenbroek 		     isc_boolean_t use_hints,
1186*00b67f09SDavid van Moolenbroek 		     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
1187*00b67f09SDavid van Moolenbroek {
1188*00b67f09SDavid van Moolenbroek 	return(dns_view_findzonecut2(view, name, fname, now, options,
1189*00b67f09SDavid van Moolenbroek 				     use_hints, ISC_TRUE,
1190*00b67f09SDavid van Moolenbroek 				     rdataset, sigrdataset));
1191*00b67f09SDavid van Moolenbroek }
1192*00b67f09SDavid van Moolenbroek 
1193*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_findzonecut2(dns_view_t * view,dns_name_t * name,dns_name_t * fname,isc_stdtime_t now,unsigned int options,isc_boolean_t use_hints,isc_boolean_t use_cache,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)1194*00b67f09SDavid van Moolenbroek dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
1195*00b67f09SDavid van Moolenbroek 		      isc_stdtime_t now, unsigned int options,
1196*00b67f09SDavid van Moolenbroek 		      isc_boolean_t use_hints,	isc_boolean_t use_cache,
1197*00b67f09SDavid van Moolenbroek 		      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
1198*00b67f09SDavid van Moolenbroek {
1199*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1200*00b67f09SDavid van Moolenbroek 	dns_db_t *db;
1201*00b67f09SDavid van Moolenbroek 	isc_boolean_t is_cache, use_zone, try_hints;
1202*00b67f09SDavid van Moolenbroek 	dns_zone_t *zone;
1203*00b67f09SDavid van Moolenbroek 	dns_name_t *zfname;
1204*00b67f09SDavid van Moolenbroek 	dns_rdataset_t zrdataset, zsigrdataset;
1205*00b67f09SDavid van Moolenbroek 	dns_fixedname_t zfixedname;
1206*00b67f09SDavid van Moolenbroek 	unsigned int ztoptions = 0;
1207*00b67f09SDavid van Moolenbroek 
1208*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1209*00b67f09SDavid van Moolenbroek 	REQUIRE(view->frozen);
1210*00b67f09SDavid van Moolenbroek 
1211*00b67f09SDavid van Moolenbroek 	db = NULL;
1212*00b67f09SDavid van Moolenbroek 	use_zone = ISC_FALSE;
1213*00b67f09SDavid van Moolenbroek 	try_hints = ISC_FALSE;
1214*00b67f09SDavid van Moolenbroek 	zfname = NULL;
1215*00b67f09SDavid van Moolenbroek 
1216*00b67f09SDavid van Moolenbroek 	/*
1217*00b67f09SDavid van Moolenbroek 	 * Initialize.
1218*00b67f09SDavid van Moolenbroek 	 */
1219*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&zfixedname);
1220*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&zrdataset);
1221*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&zsigrdataset);
1222*00b67f09SDavid van Moolenbroek 
1223*00b67f09SDavid van Moolenbroek 	/*
1224*00b67f09SDavid van Moolenbroek 	 * Find the right database.
1225*00b67f09SDavid van Moolenbroek 	 */
1226*00b67f09SDavid van Moolenbroek 	zone = NULL;
1227*00b67f09SDavid van Moolenbroek 	LOCK(&view->lock);
1228*00b67f09SDavid van Moolenbroek 	if (view->zonetable != NULL) {
1229*00b67f09SDavid van Moolenbroek 		if ((options & DNS_DBFIND_NOEXACT) != 0)
1230*00b67f09SDavid van Moolenbroek 			ztoptions |= DNS_ZTFIND_NOEXACT;
1231*00b67f09SDavid van Moolenbroek 		result = dns_zt_find(view->zonetable, name, ztoptions,
1232*00b67f09SDavid van Moolenbroek 				     NULL, &zone);
1233*00b67f09SDavid van Moolenbroek 	} else
1234*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOTFOUND;
1235*00b67f09SDavid van Moolenbroek 	UNLOCK(&view->lock);
1236*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
1237*00b67f09SDavid van Moolenbroek 		result = dns_zone_getdb(zone, &db);
1238*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_NOTFOUND) {
1239*00b67f09SDavid van Moolenbroek 		/*
1240*00b67f09SDavid van Moolenbroek 		 * We're not directly authoritative for this query name, nor
1241*00b67f09SDavid van Moolenbroek 		 * is it a subdomain of any zone for which we're
1242*00b67f09SDavid van Moolenbroek 		 * authoritative.
1243*00b67f09SDavid van Moolenbroek 		 */
1244*00b67f09SDavid van Moolenbroek 		if (use_cache && view->cachedb != NULL) {
1245*00b67f09SDavid van Moolenbroek 			/*
1246*00b67f09SDavid van Moolenbroek 			 * We have a cache; try it.
1247*00b67f09SDavid van Moolenbroek 			 */
1248*00b67f09SDavid van Moolenbroek 			dns_db_attach(view->cachedb, &db);
1249*00b67f09SDavid van Moolenbroek 		} else {
1250*00b67f09SDavid van Moolenbroek 			/*
1251*00b67f09SDavid van Moolenbroek 			 * Maybe we have hints...
1252*00b67f09SDavid van Moolenbroek 			 */
1253*00b67f09SDavid van Moolenbroek 			try_hints = ISC_TRUE;
1254*00b67f09SDavid van Moolenbroek 			goto finish;
1255*00b67f09SDavid van Moolenbroek 		}
1256*00b67f09SDavid van Moolenbroek 	} else if (result != ISC_R_SUCCESS) {
1257*00b67f09SDavid van Moolenbroek 		/*
1258*00b67f09SDavid van Moolenbroek 		 * Something is broken.
1259*00b67f09SDavid van Moolenbroek 		 */
1260*00b67f09SDavid van Moolenbroek 		goto cleanup;
1261*00b67f09SDavid van Moolenbroek 	}
1262*00b67f09SDavid van Moolenbroek 	is_cache = dns_db_iscache(db);
1263*00b67f09SDavid van Moolenbroek 
1264*00b67f09SDavid van Moolenbroek  db_find:
1265*00b67f09SDavid van Moolenbroek 	/*
1266*00b67f09SDavid van Moolenbroek 	 * Look for the zonecut.
1267*00b67f09SDavid van Moolenbroek 	 */
1268*00b67f09SDavid van Moolenbroek 	if (!is_cache) {
1269*00b67f09SDavid van Moolenbroek 		result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options,
1270*00b67f09SDavid van Moolenbroek 				     now, NULL, fname, rdataset, sigrdataset);
1271*00b67f09SDavid van Moolenbroek 		if (result == DNS_R_DELEGATION)
1272*00b67f09SDavid van Moolenbroek 			result = ISC_R_SUCCESS;
1273*00b67f09SDavid van Moolenbroek 		else if (result != ISC_R_SUCCESS)
1274*00b67f09SDavid van Moolenbroek 			goto cleanup;
1275*00b67f09SDavid van Moolenbroek 		if (use_cache && view->cachedb != NULL && db != view->hints) {
1276*00b67f09SDavid van Moolenbroek 			/*
1277*00b67f09SDavid van Moolenbroek 			 * We found an answer, but the cache may be better.
1278*00b67f09SDavid van Moolenbroek 			 */
1279*00b67f09SDavid van Moolenbroek 			zfname = dns_fixedname_name(&zfixedname);
1280*00b67f09SDavid van Moolenbroek 			result = dns_name_copy(fname, zfname, NULL);
1281*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
1282*00b67f09SDavid van Moolenbroek 				goto cleanup;
1283*00b67f09SDavid van Moolenbroek 			dns_rdataset_clone(rdataset, &zrdataset);
1284*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(rdataset);
1285*00b67f09SDavid van Moolenbroek 			if (sigrdataset != NULL &&
1286*00b67f09SDavid van Moolenbroek 			    dns_rdataset_isassociated(sigrdataset)) {
1287*00b67f09SDavid van Moolenbroek 				dns_rdataset_clone(sigrdataset, &zsigrdataset);
1288*00b67f09SDavid van Moolenbroek 				dns_rdataset_disassociate(sigrdataset);
1289*00b67f09SDavid van Moolenbroek 			}
1290*00b67f09SDavid van Moolenbroek 			dns_db_detach(&db);
1291*00b67f09SDavid van Moolenbroek 			dns_db_attach(view->cachedb, &db);
1292*00b67f09SDavid van Moolenbroek 			is_cache = ISC_TRUE;
1293*00b67f09SDavid van Moolenbroek 			goto db_find;
1294*00b67f09SDavid van Moolenbroek 		}
1295*00b67f09SDavid van Moolenbroek 	} else {
1296*00b67f09SDavid van Moolenbroek 		result = dns_db_findzonecut(db, name, options, now, NULL,
1297*00b67f09SDavid van Moolenbroek 					    fname, rdataset, sigrdataset);
1298*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS) {
1299*00b67f09SDavid van Moolenbroek 			if (zfname != NULL &&
1300*00b67f09SDavid van Moolenbroek 			    (!dns_name_issubdomain(fname, zfname) ||
1301*00b67f09SDavid van Moolenbroek 			     (dns_zone_staticstub &&
1302*00b67f09SDavid van Moolenbroek 			      dns_name_equal(fname, zfname)))) {
1303*00b67f09SDavid van Moolenbroek 				/*
1304*00b67f09SDavid van Moolenbroek 				 * We found a zonecut in the cache, but our
1305*00b67f09SDavid van Moolenbroek 				 * zone delegation is better.
1306*00b67f09SDavid van Moolenbroek 				 */
1307*00b67f09SDavid van Moolenbroek 				use_zone = ISC_TRUE;
1308*00b67f09SDavid van Moolenbroek 			}
1309*00b67f09SDavid van Moolenbroek 		} else if (result == ISC_R_NOTFOUND) {
1310*00b67f09SDavid van Moolenbroek 			if (zfname != NULL) {
1311*00b67f09SDavid van Moolenbroek 				/*
1312*00b67f09SDavid van Moolenbroek 				 * We didn't find anything in the cache, but we
1313*00b67f09SDavid van Moolenbroek 				 * have a zone delegation, so use it.
1314*00b67f09SDavid van Moolenbroek 				 */
1315*00b67f09SDavid van Moolenbroek 				use_zone = ISC_TRUE;
1316*00b67f09SDavid van Moolenbroek 			} else {
1317*00b67f09SDavid van Moolenbroek 				/*
1318*00b67f09SDavid van Moolenbroek 				 * Maybe we have hints...
1319*00b67f09SDavid van Moolenbroek 				 */
1320*00b67f09SDavid van Moolenbroek 				try_hints = ISC_TRUE;
1321*00b67f09SDavid van Moolenbroek 			}
1322*00b67f09SDavid van Moolenbroek 		} else {
1323*00b67f09SDavid van Moolenbroek 			/*
1324*00b67f09SDavid van Moolenbroek 			 * Something bad happened.
1325*00b67f09SDavid van Moolenbroek 			 */
1326*00b67f09SDavid van Moolenbroek 			goto cleanup;
1327*00b67f09SDavid van Moolenbroek 		}
1328*00b67f09SDavid van Moolenbroek 	}
1329*00b67f09SDavid van Moolenbroek 
1330*00b67f09SDavid van Moolenbroek  finish:
1331*00b67f09SDavid van Moolenbroek 	if (use_zone) {
1332*00b67f09SDavid van Moolenbroek 		if (dns_rdataset_isassociated(rdataset)) {
1333*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(rdataset);
1334*00b67f09SDavid van Moolenbroek 			if (sigrdataset != NULL &&
1335*00b67f09SDavid van Moolenbroek 			    dns_rdataset_isassociated(sigrdataset))
1336*00b67f09SDavid van Moolenbroek 				dns_rdataset_disassociate(sigrdataset);
1337*00b67f09SDavid van Moolenbroek 		}
1338*00b67f09SDavid van Moolenbroek 		result = dns_name_copy(zfname, fname, NULL);
1339*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
1340*00b67f09SDavid van Moolenbroek 			goto cleanup;
1341*00b67f09SDavid van Moolenbroek 		dns_rdataset_clone(&zrdataset, rdataset);
1342*00b67f09SDavid van Moolenbroek 		if (sigrdataset != NULL &&
1343*00b67f09SDavid van Moolenbroek 		    dns_rdataset_isassociated(&zrdataset))
1344*00b67f09SDavid van Moolenbroek 			dns_rdataset_clone(&zsigrdataset, sigrdataset);
1345*00b67f09SDavid van Moolenbroek 	} else if (try_hints && use_hints && view->hints != NULL) {
1346*00b67f09SDavid van Moolenbroek 		/*
1347*00b67f09SDavid van Moolenbroek 		 * We've found nothing so far, but we have hints.
1348*00b67f09SDavid van Moolenbroek 		 */
1349*00b67f09SDavid van Moolenbroek 		result = dns_db_find(view->hints, dns_rootname, NULL,
1350*00b67f09SDavid van Moolenbroek 				     dns_rdatatype_ns, 0, now, NULL, fname,
1351*00b67f09SDavid van Moolenbroek 				     rdataset, NULL);
1352*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
1353*00b67f09SDavid van Moolenbroek 			/*
1354*00b67f09SDavid van Moolenbroek 			 * We can't even find the hints for the root
1355*00b67f09SDavid van Moolenbroek 			 * nameservers!
1356*00b67f09SDavid van Moolenbroek 			 */
1357*00b67f09SDavid van Moolenbroek 			if (dns_rdataset_isassociated(rdataset))
1358*00b67f09SDavid van Moolenbroek 				dns_rdataset_disassociate(rdataset);
1359*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOTFOUND;
1360*00b67f09SDavid van Moolenbroek 		}
1361*00b67f09SDavid van Moolenbroek 	}
1362*00b67f09SDavid van Moolenbroek 
1363*00b67f09SDavid van Moolenbroek  cleanup:
1364*00b67f09SDavid van Moolenbroek 	if (dns_rdataset_isassociated(&zrdataset)) {
1365*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&zrdataset);
1366*00b67f09SDavid van Moolenbroek 		if (dns_rdataset_isassociated(&zsigrdataset))
1367*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(&zsigrdataset);
1368*00b67f09SDavid van Moolenbroek 	}
1369*00b67f09SDavid van Moolenbroek 	if (db != NULL)
1370*00b67f09SDavid van Moolenbroek 		dns_db_detach(&db);
1371*00b67f09SDavid van Moolenbroek 	if (zone != NULL)
1372*00b67f09SDavid van Moolenbroek 		dns_zone_detach(&zone);
1373*00b67f09SDavid van Moolenbroek 
1374*00b67f09SDavid van Moolenbroek 	return (result);
1375*00b67f09SDavid van Moolenbroek }
1376*00b67f09SDavid van Moolenbroek 
1377*00b67f09SDavid van Moolenbroek isc_result_t
dns_viewlist_find(dns_viewlist_t * list,const char * name,dns_rdataclass_t rdclass,dns_view_t ** viewp)1378*00b67f09SDavid van Moolenbroek dns_viewlist_find(dns_viewlist_t *list, const char *name,
1379*00b67f09SDavid van Moolenbroek 		  dns_rdataclass_t rdclass, dns_view_t **viewp)
1380*00b67f09SDavid van Moolenbroek {
1381*00b67f09SDavid van Moolenbroek 	dns_view_t *view;
1382*00b67f09SDavid van Moolenbroek 
1383*00b67f09SDavid van Moolenbroek 	REQUIRE(list != NULL);
1384*00b67f09SDavid van Moolenbroek 
1385*00b67f09SDavid van Moolenbroek 	for (view = ISC_LIST_HEAD(*list);
1386*00b67f09SDavid van Moolenbroek 	     view != NULL;
1387*00b67f09SDavid van Moolenbroek 	     view = ISC_LIST_NEXT(view, link)) {
1388*00b67f09SDavid van Moolenbroek 		if (strcmp(view->name, name) == 0 && view->rdclass == rdclass)
1389*00b67f09SDavid van Moolenbroek 			break;
1390*00b67f09SDavid van Moolenbroek 	}
1391*00b67f09SDavid van Moolenbroek 	if (view == NULL)
1392*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTFOUND);
1393*00b67f09SDavid van Moolenbroek 
1394*00b67f09SDavid van Moolenbroek 	dns_view_attach(view, viewp);
1395*00b67f09SDavid van Moolenbroek 
1396*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
1397*00b67f09SDavid van Moolenbroek }
1398*00b67f09SDavid van Moolenbroek 
1399*00b67f09SDavid van Moolenbroek isc_result_t
dns_viewlist_findzone(dns_viewlist_t * list,dns_name_t * name,isc_boolean_t allclasses,dns_rdataclass_t rdclass,dns_zone_t ** zonep)1400*00b67f09SDavid van Moolenbroek dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name,
1401*00b67f09SDavid van Moolenbroek 		      isc_boolean_t allclasses, dns_rdataclass_t rdclass,
1402*00b67f09SDavid van Moolenbroek 		      dns_zone_t **zonep)
1403*00b67f09SDavid van Moolenbroek {
1404*00b67f09SDavid van Moolenbroek 	dns_view_t *view;
1405*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1406*00b67f09SDavid van Moolenbroek 	dns_zone_t *zone1 = NULL, *zone2 = NULL;
1407*00b67f09SDavid van Moolenbroek 	dns_zone_t **zp = NULL;;
1408*00b67f09SDavid van Moolenbroek 
1409*00b67f09SDavid van Moolenbroek 	REQUIRE(list != NULL);
1410*00b67f09SDavid van Moolenbroek 	REQUIRE(zonep != NULL && *zonep == NULL);
1411*00b67f09SDavid van Moolenbroek 
1412*00b67f09SDavid van Moolenbroek 	for (view = ISC_LIST_HEAD(*list);
1413*00b67f09SDavid van Moolenbroek 	     view != NULL;
1414*00b67f09SDavid van Moolenbroek 	     view = ISC_LIST_NEXT(view, link)) {
1415*00b67f09SDavid van Moolenbroek 		if (allclasses == ISC_FALSE && view->rdclass != rdclass)
1416*00b67f09SDavid van Moolenbroek 			continue;
1417*00b67f09SDavid van Moolenbroek 
1418*00b67f09SDavid van Moolenbroek 		/*
1419*00b67f09SDavid van Moolenbroek 		 * If the zone is defined in more than one view,
1420*00b67f09SDavid van Moolenbroek 		 * treat it as not found.
1421*00b67f09SDavid van Moolenbroek 		 */
1422*00b67f09SDavid van Moolenbroek 		zp = (zone1 == NULL) ? &zone1 : &zone2;
1423*00b67f09SDavid van Moolenbroek 		LOCK(&view->lock);
1424*00b67f09SDavid van Moolenbroek 		if (view->zonetable != NULL)
1425*00b67f09SDavid van Moolenbroek 			result = dns_zt_find(view->zonetable, name, 0,
1426*00b67f09SDavid van Moolenbroek 					     NULL, zp);
1427*00b67f09SDavid van Moolenbroek 		else
1428*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOTFOUND;
1429*00b67f09SDavid van Moolenbroek 		UNLOCK(&view->lock);
1430*00b67f09SDavid van Moolenbroek 		INSIST(result == ISC_R_SUCCESS ||
1431*00b67f09SDavid van Moolenbroek 		       result == ISC_R_NOTFOUND ||
1432*00b67f09SDavid van Moolenbroek 		       result == DNS_R_PARTIALMATCH);
1433*00b67f09SDavid van Moolenbroek 
1434*00b67f09SDavid van Moolenbroek 		/* Treat a partial match as no match */
1435*00b67f09SDavid van Moolenbroek 		if (result == DNS_R_PARTIALMATCH) {
1436*00b67f09SDavid van Moolenbroek 			dns_zone_detach(zp);
1437*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOTFOUND;
1438*00b67f09SDavid van Moolenbroek 			POST(result);
1439*00b67f09SDavid van Moolenbroek 		}
1440*00b67f09SDavid van Moolenbroek 
1441*00b67f09SDavid van Moolenbroek 		if (zone2 != NULL) {
1442*00b67f09SDavid van Moolenbroek 			dns_zone_detach(&zone1);
1443*00b67f09SDavid van Moolenbroek 			dns_zone_detach(&zone2);
1444*00b67f09SDavid van Moolenbroek 			return (ISC_R_MULTIPLE);
1445*00b67f09SDavid van Moolenbroek 		}
1446*00b67f09SDavid van Moolenbroek 	}
1447*00b67f09SDavid van Moolenbroek 
1448*00b67f09SDavid van Moolenbroek 	if (zone1 != NULL) {
1449*00b67f09SDavid van Moolenbroek 		dns_zone_attach(zone1, zonep);
1450*00b67f09SDavid van Moolenbroek 		dns_zone_detach(&zone1);
1451*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
1452*00b67f09SDavid van Moolenbroek 	}
1453*00b67f09SDavid van Moolenbroek 
1454*00b67f09SDavid van Moolenbroek 	return (ISC_R_NOTFOUND);
1455*00b67f09SDavid van Moolenbroek }
1456*00b67f09SDavid van Moolenbroek 
1457*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_load(dns_view_t * view,isc_boolean_t stop)1458*00b67f09SDavid van Moolenbroek dns_view_load(dns_view_t *view, isc_boolean_t stop) {
1459*00b67f09SDavid van Moolenbroek 
1460*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1461*00b67f09SDavid van Moolenbroek 	REQUIRE(view->zonetable != NULL);
1462*00b67f09SDavid van Moolenbroek 
1463*00b67f09SDavid van Moolenbroek 	return (dns_zt_load(view->zonetable, stop));
1464*00b67f09SDavid van Moolenbroek }
1465*00b67f09SDavid van Moolenbroek 
1466*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_loadnew(dns_view_t * view,isc_boolean_t stop)1467*00b67f09SDavid van Moolenbroek dns_view_loadnew(dns_view_t *view, isc_boolean_t stop) {
1468*00b67f09SDavid van Moolenbroek 
1469*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1470*00b67f09SDavid van Moolenbroek 	REQUIRE(view->zonetable != NULL);
1471*00b67f09SDavid van Moolenbroek 
1472*00b67f09SDavid van Moolenbroek 	return (dns_zt_loadnew(view->zonetable, stop));
1473*00b67f09SDavid van Moolenbroek }
1474*00b67f09SDavid van Moolenbroek 
1475*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_asyncload(dns_view_t * view,dns_zt_allloaded_t callback,void * arg)1476*00b67f09SDavid van Moolenbroek dns_view_asyncload(dns_view_t *view, dns_zt_allloaded_t callback, void *arg) {
1477*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1478*00b67f09SDavid van Moolenbroek 	REQUIRE(view->zonetable != NULL);
1479*00b67f09SDavid van Moolenbroek 
1480*00b67f09SDavid van Moolenbroek 	return (dns_zt_asyncload(view->zonetable, callback, arg));
1481*00b67f09SDavid van Moolenbroek }
1482*00b67f09SDavid van Moolenbroek 
1483*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_gettsig(dns_view_t * view,dns_name_t * keyname,dns_tsigkey_t ** keyp)1484*00b67f09SDavid van Moolenbroek dns_view_gettsig(dns_view_t *view, dns_name_t *keyname, dns_tsigkey_t **keyp)
1485*00b67f09SDavid van Moolenbroek {
1486*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1487*00b67f09SDavid van Moolenbroek 	REQUIRE(keyp != NULL && *keyp == NULL);
1488*00b67f09SDavid van Moolenbroek 
1489*00b67f09SDavid van Moolenbroek 	result = dns_tsigkey_find(keyp, keyname, NULL,
1490*00b67f09SDavid van Moolenbroek 				  view->statickeys);
1491*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_NOTFOUND)
1492*00b67f09SDavid van Moolenbroek 		result = dns_tsigkey_find(keyp, keyname, NULL,
1493*00b67f09SDavid van Moolenbroek 					  view->dynamickeys);
1494*00b67f09SDavid van Moolenbroek 	return (result);
1495*00b67f09SDavid van Moolenbroek }
1496*00b67f09SDavid van Moolenbroek 
1497*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_getpeertsig(dns_view_t * view,isc_netaddr_t * peeraddr,dns_tsigkey_t ** keyp)1498*00b67f09SDavid van Moolenbroek dns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr,
1499*00b67f09SDavid van Moolenbroek 		     dns_tsigkey_t **keyp)
1500*00b67f09SDavid van Moolenbroek {
1501*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1502*00b67f09SDavid van Moolenbroek 	dns_name_t *keyname = NULL;
1503*00b67f09SDavid van Moolenbroek 	dns_peer_t *peer = NULL;
1504*00b67f09SDavid van Moolenbroek 
1505*00b67f09SDavid van Moolenbroek 	result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer);
1506*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1507*00b67f09SDavid van Moolenbroek 		return (result);
1508*00b67f09SDavid van Moolenbroek 
1509*00b67f09SDavid van Moolenbroek 	result = dns_peer_getkey(peer, &keyname);
1510*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1511*00b67f09SDavid van Moolenbroek 		return (result);
1512*00b67f09SDavid van Moolenbroek 
1513*00b67f09SDavid van Moolenbroek 	result = dns_view_gettsig(view, keyname, keyp);
1514*00b67f09SDavid van Moolenbroek 	return ((result == ISC_R_NOTFOUND) ? ISC_R_FAILURE : result);
1515*00b67f09SDavid van Moolenbroek }
1516*00b67f09SDavid van Moolenbroek 
1517*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_checksig(dns_view_t * view,isc_buffer_t * source,dns_message_t * msg)1518*00b67f09SDavid van Moolenbroek dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
1519*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1520*00b67f09SDavid van Moolenbroek 	REQUIRE(source != NULL);
1521*00b67f09SDavid van Moolenbroek 
1522*00b67f09SDavid van Moolenbroek 	return (dns_tsig_verify(source, msg, view->statickeys,
1523*00b67f09SDavid van Moolenbroek 				view->dynamickeys));
1524*00b67f09SDavid van Moolenbroek }
1525*00b67f09SDavid van Moolenbroek 
1526*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_dumpdbtostream(dns_view_t * view,FILE * fp)1527*00b67f09SDavid van Moolenbroek dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
1528*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1529*00b67f09SDavid van Moolenbroek 
1530*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1531*00b67f09SDavid van Moolenbroek 
1532*00b67f09SDavid van Moolenbroek 	(void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name);
1533*00b67f09SDavid van Moolenbroek 	result = dns_master_dumptostream(view->mctx, view->cachedb, NULL,
1534*00b67f09SDavid van Moolenbroek 					 &dns_master_style_cache, fp);
1535*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1536*00b67f09SDavid van Moolenbroek 		return (result);
1537*00b67f09SDavid van Moolenbroek 	dns_adb_dump(view->adb, fp);
1538*00b67f09SDavid van Moolenbroek 	dns_resolver_printbadcache(view->resolver, fp);
1539*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
1540*00b67f09SDavid van Moolenbroek }
1541*00b67f09SDavid van Moolenbroek 
1542*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_flushcache(dns_view_t * view)1543*00b67f09SDavid van Moolenbroek dns_view_flushcache(dns_view_t *view) {
1544*00b67f09SDavid van Moolenbroek 	return (dns_view_flushcache2(view, ISC_FALSE));
1545*00b67f09SDavid van Moolenbroek }
1546*00b67f09SDavid van Moolenbroek 
1547*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_flushcache2(dns_view_t * view,isc_boolean_t fixuponly)1548*00b67f09SDavid van Moolenbroek dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) {
1549*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1550*00b67f09SDavid van Moolenbroek 
1551*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1552*00b67f09SDavid van Moolenbroek 
1553*00b67f09SDavid van Moolenbroek 	if (view->cachedb == NULL)
1554*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
1555*00b67f09SDavid van Moolenbroek 	if (!fixuponly) {
1556*00b67f09SDavid van Moolenbroek 		result = dns_cache_flush(view->cache);
1557*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
1558*00b67f09SDavid van Moolenbroek 			return (result);
1559*00b67f09SDavid van Moolenbroek 	}
1560*00b67f09SDavid van Moolenbroek 	if (view->acache != NULL)
1561*00b67f09SDavid van Moolenbroek 		dns_acache_putdb(view->acache, view->cachedb);
1562*00b67f09SDavid van Moolenbroek 	dns_db_detach(&view->cachedb);
1563*00b67f09SDavid van Moolenbroek 	dns_cache_attachdb(view->cache, &view->cachedb);
1564*00b67f09SDavid van Moolenbroek 	if (view->acache != NULL)
1565*00b67f09SDavid van Moolenbroek 		dns_acache_setdb(view->acache, view->cachedb);
1566*00b67f09SDavid van Moolenbroek 	if (view->resolver != NULL)
1567*00b67f09SDavid van Moolenbroek 		dns_resolver_flushbadcache(view->resolver, NULL);
1568*00b67f09SDavid van Moolenbroek 
1569*00b67f09SDavid van Moolenbroek 	dns_adb_flush(view->adb);
1570*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
1571*00b67f09SDavid van Moolenbroek }
1572*00b67f09SDavid van Moolenbroek 
1573*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_flushname(dns_view_t * view,dns_name_t * name)1574*00b67f09SDavid van Moolenbroek dns_view_flushname(dns_view_t *view, dns_name_t *name) {
1575*00b67f09SDavid van Moolenbroek 	return (dns_view_flushnode(view, name, ISC_FALSE));
1576*00b67f09SDavid van Moolenbroek }
1577*00b67f09SDavid van Moolenbroek 
1578*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_flushnode(dns_view_t * view,dns_name_t * name,isc_boolean_t tree)1579*00b67f09SDavid van Moolenbroek dns_view_flushnode(dns_view_t *view, dns_name_t *name, isc_boolean_t tree) {
1580*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
1581*00b67f09SDavid van Moolenbroek 
1582*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1583*00b67f09SDavid van Moolenbroek 
1584*00b67f09SDavid van Moolenbroek 	if (tree) {
1585*00b67f09SDavid van Moolenbroek 		if (view->adb != NULL)
1586*00b67f09SDavid van Moolenbroek 			dns_adb_flushnames(view->adb, name);
1587*00b67f09SDavid van Moolenbroek 		if (view->resolver != NULL)
1588*00b67f09SDavid van Moolenbroek 			dns_resolver_flushbadnames(view->resolver, name);
1589*00b67f09SDavid van Moolenbroek 	} else {
1590*00b67f09SDavid van Moolenbroek 		if (view->adb != NULL)
1591*00b67f09SDavid van Moolenbroek 			dns_adb_flushname(view->adb, name);
1592*00b67f09SDavid van Moolenbroek 		if (view->resolver != NULL)
1593*00b67f09SDavid van Moolenbroek 			dns_resolver_flushbadcache(view->resolver, name);
1594*00b67f09SDavid van Moolenbroek 	}
1595*00b67f09SDavid van Moolenbroek 
1596*00b67f09SDavid van Moolenbroek 	if (view->cache != NULL)
1597*00b67f09SDavid van Moolenbroek 		result = dns_cache_flushnode(view->cache, name, tree);
1598*00b67f09SDavid van Moolenbroek 
1599*00b67f09SDavid van Moolenbroek 	return (result);
1600*00b67f09SDavid van Moolenbroek }
1601*00b67f09SDavid van Moolenbroek 
1602*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_adddelegationonly(dns_view_t * view,dns_name_t * name)1603*00b67f09SDavid van Moolenbroek dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name) {
1604*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1605*00b67f09SDavid van Moolenbroek 	dns_name_t *new;
1606*00b67f09SDavid van Moolenbroek 	isc_uint32_t hash;
1607*00b67f09SDavid van Moolenbroek 
1608*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1609*00b67f09SDavid van Moolenbroek 
1610*00b67f09SDavid van Moolenbroek 	if (view->delonly == NULL) {
1611*00b67f09SDavid van Moolenbroek 		view->delonly = isc_mem_get(view->mctx,
1612*00b67f09SDavid van Moolenbroek 					    sizeof(dns_namelist_t) *
1613*00b67f09SDavid van Moolenbroek 					    DNS_VIEW_DELONLYHASH);
1614*00b67f09SDavid van Moolenbroek 		if (view->delonly == NULL)
1615*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOMEMORY);
1616*00b67f09SDavid van Moolenbroek 		for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
1617*00b67f09SDavid van Moolenbroek 			ISC_LIST_INIT(view->delonly[hash]);
1618*00b67f09SDavid van Moolenbroek 	}
1619*00b67f09SDavid van Moolenbroek 	hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
1620*00b67f09SDavid van Moolenbroek 	new = ISC_LIST_HEAD(view->delonly[hash]);
1621*00b67f09SDavid van Moolenbroek 	while (new != NULL && !dns_name_equal(new, name))
1622*00b67f09SDavid van Moolenbroek 		new = ISC_LIST_NEXT(new, link);
1623*00b67f09SDavid van Moolenbroek 	if (new != NULL)
1624*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
1625*00b67f09SDavid van Moolenbroek 	new = isc_mem_get(view->mctx, sizeof(*new));
1626*00b67f09SDavid van Moolenbroek 	if (new == NULL)
1627*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
1628*00b67f09SDavid van Moolenbroek 	dns_name_init(new, NULL);
1629*00b67f09SDavid van Moolenbroek 	result = dns_name_dup(name, view->mctx, new);
1630*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
1631*00b67f09SDavid van Moolenbroek 		ISC_LIST_APPEND(view->delonly[hash], new, link);
1632*00b67f09SDavid van Moolenbroek 	else
1633*00b67f09SDavid van Moolenbroek 		isc_mem_put(view->mctx, new, sizeof(*new));
1634*00b67f09SDavid van Moolenbroek 	return (result);
1635*00b67f09SDavid van Moolenbroek }
1636*00b67f09SDavid van Moolenbroek 
1637*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_excludedelegationonly(dns_view_t * view,dns_name_t * name)1638*00b67f09SDavid van Moolenbroek dns_view_excludedelegationonly(dns_view_t *view, dns_name_t *name) {
1639*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1640*00b67f09SDavid van Moolenbroek 	dns_name_t *new;
1641*00b67f09SDavid van Moolenbroek 	isc_uint32_t hash;
1642*00b67f09SDavid van Moolenbroek 
1643*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1644*00b67f09SDavid van Moolenbroek 
1645*00b67f09SDavid van Moolenbroek 	if (view->rootexclude == NULL) {
1646*00b67f09SDavid van Moolenbroek 		view->rootexclude = isc_mem_get(view->mctx,
1647*00b67f09SDavid van Moolenbroek 					    sizeof(dns_namelist_t) *
1648*00b67f09SDavid van Moolenbroek 					    DNS_VIEW_DELONLYHASH);
1649*00b67f09SDavid van Moolenbroek 		if (view->rootexclude == NULL)
1650*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOMEMORY);
1651*00b67f09SDavid van Moolenbroek 		for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
1652*00b67f09SDavid van Moolenbroek 			ISC_LIST_INIT(view->rootexclude[hash]);
1653*00b67f09SDavid van Moolenbroek 	}
1654*00b67f09SDavid van Moolenbroek 	hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
1655*00b67f09SDavid van Moolenbroek 	new = ISC_LIST_HEAD(view->rootexclude[hash]);
1656*00b67f09SDavid van Moolenbroek 	while (new != NULL && !dns_name_equal(new, name))
1657*00b67f09SDavid van Moolenbroek 		new = ISC_LIST_NEXT(new, link);
1658*00b67f09SDavid van Moolenbroek 	if (new != NULL)
1659*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
1660*00b67f09SDavid van Moolenbroek 	new = isc_mem_get(view->mctx, sizeof(*new));
1661*00b67f09SDavid van Moolenbroek 	if (new == NULL)
1662*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
1663*00b67f09SDavid van Moolenbroek 	dns_name_init(new, NULL);
1664*00b67f09SDavid van Moolenbroek 	result = dns_name_dup(name, view->mctx, new);
1665*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
1666*00b67f09SDavid van Moolenbroek 		ISC_LIST_APPEND(view->rootexclude[hash], new, link);
1667*00b67f09SDavid van Moolenbroek 	else
1668*00b67f09SDavid van Moolenbroek 		isc_mem_put(view->mctx, new, sizeof(*new));
1669*00b67f09SDavid van Moolenbroek 	return (result);
1670*00b67f09SDavid van Moolenbroek }
1671*00b67f09SDavid van Moolenbroek 
1672*00b67f09SDavid van Moolenbroek isc_boolean_t
dns_view_isdelegationonly(dns_view_t * view,dns_name_t * name)1673*00b67f09SDavid van Moolenbroek dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name) {
1674*00b67f09SDavid van Moolenbroek 	dns_name_t *new;
1675*00b67f09SDavid van Moolenbroek 	isc_uint32_t hash;
1676*00b67f09SDavid van Moolenbroek 
1677*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1678*00b67f09SDavid van Moolenbroek 
1679*00b67f09SDavid van Moolenbroek 	if (!view->rootdelonly && view->delonly == NULL)
1680*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
1681*00b67f09SDavid van Moolenbroek 
1682*00b67f09SDavid van Moolenbroek 	hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
1683*00b67f09SDavid van Moolenbroek 	if (view->rootdelonly && dns_name_countlabels(name) <= 2) {
1684*00b67f09SDavid van Moolenbroek 		if (view->rootexclude == NULL)
1685*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
1686*00b67f09SDavid van Moolenbroek 		new = ISC_LIST_HEAD(view->rootexclude[hash]);
1687*00b67f09SDavid van Moolenbroek 		while (new != NULL && !dns_name_equal(new, name))
1688*00b67f09SDavid van Moolenbroek 			new = ISC_LIST_NEXT(new, link);
1689*00b67f09SDavid van Moolenbroek 		if (new == NULL)
1690*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
1691*00b67f09SDavid van Moolenbroek 	}
1692*00b67f09SDavid van Moolenbroek 
1693*00b67f09SDavid van Moolenbroek 	if (view->delonly == NULL)
1694*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
1695*00b67f09SDavid van Moolenbroek 
1696*00b67f09SDavid van Moolenbroek 	new = ISC_LIST_HEAD(view->delonly[hash]);
1697*00b67f09SDavid van Moolenbroek 	while (new != NULL && !dns_name_equal(new, name))
1698*00b67f09SDavid van Moolenbroek 		new = ISC_LIST_NEXT(new, link);
1699*00b67f09SDavid van Moolenbroek 	if (new == NULL)
1700*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
1701*00b67f09SDavid van Moolenbroek 	return (ISC_TRUE);
1702*00b67f09SDavid van Moolenbroek }
1703*00b67f09SDavid van Moolenbroek 
1704*00b67f09SDavid van Moolenbroek void
dns_view_setrootdelonly(dns_view_t * view,isc_boolean_t value)1705*00b67f09SDavid van Moolenbroek dns_view_setrootdelonly(dns_view_t *view, isc_boolean_t value) {
1706*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1707*00b67f09SDavid van Moolenbroek 	view->rootdelonly = value;
1708*00b67f09SDavid van Moolenbroek }
1709*00b67f09SDavid van Moolenbroek 
1710*00b67f09SDavid van Moolenbroek isc_boolean_t
dns_view_getrootdelonly(dns_view_t * view)1711*00b67f09SDavid van Moolenbroek dns_view_getrootdelonly(dns_view_t *view) {
1712*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1713*00b67f09SDavid van Moolenbroek 	return (view->rootdelonly);
1714*00b67f09SDavid van Moolenbroek }
1715*00b67f09SDavid van Moolenbroek 
1716*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_freezezones(dns_view_t * view,isc_boolean_t value)1717*00b67f09SDavid van Moolenbroek dns_view_freezezones(dns_view_t *view, isc_boolean_t value) {
1718*00b67f09SDavid van Moolenbroek 
1719*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1720*00b67f09SDavid van Moolenbroek 	REQUIRE(view->zonetable != NULL);
1721*00b67f09SDavid van Moolenbroek 
1722*00b67f09SDavid van Moolenbroek 	return (dns_zt_freezezones(view->zonetable, value));
1723*00b67f09SDavid van Moolenbroek }
1724*00b67f09SDavid van Moolenbroek 
1725*00b67f09SDavid van Moolenbroek void
dns_view_setadbstats(dns_view_t * view,isc_stats_t * stats)1726*00b67f09SDavid van Moolenbroek dns_view_setadbstats(dns_view_t *view, isc_stats_t *stats) {
1727*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1728*00b67f09SDavid van Moolenbroek 	REQUIRE(!view->frozen);
1729*00b67f09SDavid van Moolenbroek 	REQUIRE(view->adbstats == NULL);
1730*00b67f09SDavid van Moolenbroek 
1731*00b67f09SDavid van Moolenbroek 	isc_stats_attach(stats, &view->adbstats);
1732*00b67f09SDavid van Moolenbroek }
1733*00b67f09SDavid van Moolenbroek 
1734*00b67f09SDavid van Moolenbroek void
dns_view_getadbstats(dns_view_t * view,isc_stats_t ** statsp)1735*00b67f09SDavid van Moolenbroek dns_view_getadbstats(dns_view_t *view, isc_stats_t **statsp) {
1736*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1737*00b67f09SDavid van Moolenbroek 	REQUIRE(statsp != NULL && *statsp == NULL);
1738*00b67f09SDavid van Moolenbroek 
1739*00b67f09SDavid van Moolenbroek 	if (view->adbstats != NULL)
1740*00b67f09SDavid van Moolenbroek 		isc_stats_attach(view->adbstats, statsp);
1741*00b67f09SDavid van Moolenbroek }
1742*00b67f09SDavid van Moolenbroek 
1743*00b67f09SDavid van Moolenbroek void
dns_view_setresstats(dns_view_t * view,isc_stats_t * stats)1744*00b67f09SDavid van Moolenbroek dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) {
1745*00b67f09SDavid van Moolenbroek 
1746*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1747*00b67f09SDavid van Moolenbroek 	REQUIRE(!view->frozen);
1748*00b67f09SDavid van Moolenbroek 	REQUIRE(view->resstats == NULL);
1749*00b67f09SDavid van Moolenbroek 
1750*00b67f09SDavid van Moolenbroek 	isc_stats_attach(stats, &view->resstats);
1751*00b67f09SDavid van Moolenbroek }
1752*00b67f09SDavid van Moolenbroek 
1753*00b67f09SDavid van Moolenbroek void
dns_view_getresstats(dns_view_t * view,isc_stats_t ** statsp)1754*00b67f09SDavid van Moolenbroek dns_view_getresstats(dns_view_t *view, isc_stats_t **statsp) {
1755*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1756*00b67f09SDavid van Moolenbroek 	REQUIRE(statsp != NULL && *statsp == NULL);
1757*00b67f09SDavid van Moolenbroek 
1758*00b67f09SDavid van Moolenbroek 	if (view->resstats != NULL)
1759*00b67f09SDavid van Moolenbroek 		isc_stats_attach(view->resstats, statsp);
1760*00b67f09SDavid van Moolenbroek }
1761*00b67f09SDavid van Moolenbroek 
1762*00b67f09SDavid van Moolenbroek void
dns_view_setresquerystats(dns_view_t * view,dns_stats_t * stats)1763*00b67f09SDavid van Moolenbroek dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats) {
1764*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1765*00b67f09SDavid van Moolenbroek 	REQUIRE(!view->frozen);
1766*00b67f09SDavid van Moolenbroek 	REQUIRE(view->resquerystats == NULL);
1767*00b67f09SDavid van Moolenbroek 
1768*00b67f09SDavid van Moolenbroek 	dns_stats_attach(stats, &view->resquerystats);
1769*00b67f09SDavid van Moolenbroek }
1770*00b67f09SDavid van Moolenbroek 
1771*00b67f09SDavid van Moolenbroek void
dns_view_getresquerystats(dns_view_t * view,dns_stats_t ** statsp)1772*00b67f09SDavid van Moolenbroek dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
1773*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1774*00b67f09SDavid van Moolenbroek 	REQUIRE(statsp != NULL && *statsp == NULL);
1775*00b67f09SDavid van Moolenbroek 
1776*00b67f09SDavid van Moolenbroek 	if (view->resquerystats != NULL)
1777*00b67f09SDavid van Moolenbroek 		dns_stats_attach(view->resquerystats, statsp);
1778*00b67f09SDavid van Moolenbroek }
1779*00b67f09SDavid van Moolenbroek 
1780*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_initsecroots(dns_view_t * view,isc_mem_t * mctx)1781*00b67f09SDavid van Moolenbroek dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) {
1782*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1783*00b67f09SDavid van Moolenbroek 	if (view->secroots_priv != NULL)
1784*00b67f09SDavid van Moolenbroek 		dns_keytable_detach(&view->secroots_priv);
1785*00b67f09SDavid van Moolenbroek 	return (dns_keytable_create(mctx, &view->secroots_priv));
1786*00b67f09SDavid van Moolenbroek }
1787*00b67f09SDavid van Moolenbroek 
1788*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_getsecroots(dns_view_t * view,dns_keytable_t ** ktp)1789*00b67f09SDavid van Moolenbroek dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) {
1790*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1791*00b67f09SDavid van Moolenbroek 	REQUIRE(ktp != NULL && *ktp == NULL);
1792*00b67f09SDavid van Moolenbroek 	if (view->secroots_priv == NULL)
1793*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTFOUND);
1794*00b67f09SDavid van Moolenbroek 	dns_keytable_attach(view->secroots_priv, ktp);
1795*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
1796*00b67f09SDavid van Moolenbroek }
1797*00b67f09SDavid van Moolenbroek 
1798*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_issecuredomain(dns_view_t * view,dns_name_t * name,isc_boolean_t * secure_domain)1799*00b67f09SDavid van Moolenbroek dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
1800*00b67f09SDavid van Moolenbroek 			 isc_boolean_t *secure_domain) {
1801*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1802*00b67f09SDavid van Moolenbroek 
1803*00b67f09SDavid van Moolenbroek 	if (view->secroots_priv == NULL)
1804*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTFOUND);
1805*00b67f09SDavid van Moolenbroek 	return (dns_keytable_issecuredomain(view->secroots_priv, name,
1806*00b67f09SDavid van Moolenbroek 					    secure_domain));
1807*00b67f09SDavid van Moolenbroek }
1808*00b67f09SDavid van Moolenbroek 
1809*00b67f09SDavid van Moolenbroek void
dns_view_untrust(dns_view_t * view,dns_name_t * keyname,dns_rdata_dnskey_t * dnskey,isc_mem_t * mctx)1810*00b67f09SDavid van Moolenbroek dns_view_untrust(dns_view_t *view, dns_name_t *keyname,
1811*00b67f09SDavid van Moolenbroek 		 dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx)
1812*00b67f09SDavid van Moolenbroek {
1813*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1814*00b67f09SDavid van Moolenbroek 	unsigned char data[4096];
1815*00b67f09SDavid van Moolenbroek 	dns_rdata_t rdata = DNS_RDATA_INIT;
1816*00b67f09SDavid van Moolenbroek 	isc_buffer_t buffer;
1817*00b67f09SDavid van Moolenbroek 	dst_key_t *key = NULL;
1818*00b67f09SDavid van Moolenbroek 	dns_keytable_t *sr = NULL;
1819*00b67f09SDavid van Moolenbroek 
1820*00b67f09SDavid van Moolenbroek 	/*
1821*00b67f09SDavid van Moolenbroek 	 * Clear the revoke bit, if set, so that the key will match what's
1822*00b67f09SDavid van Moolenbroek 	 * in secroots now.
1823*00b67f09SDavid van Moolenbroek 	 */
1824*00b67f09SDavid van Moolenbroek 	dnskey->flags &= ~DNS_KEYFLAG_REVOKE;
1825*00b67f09SDavid van Moolenbroek 
1826*00b67f09SDavid van Moolenbroek 	/* Convert dnskey to DST key. */
1827*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&buffer, data, sizeof(data));
1828*00b67f09SDavid van Moolenbroek 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
1829*00b67f09SDavid van Moolenbroek 			     dns_rdatatype_dnskey, dnskey, &buffer);
1830*00b67f09SDavid van Moolenbroek 	result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key);
1831*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1832*00b67f09SDavid van Moolenbroek 		return;
1833*00b67f09SDavid van Moolenbroek 	result = dns_view_getsecroots(view, &sr);
1834*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS) {
1835*00b67f09SDavid van Moolenbroek 		dns_keytable_deletekeynode(sr, key);
1836*00b67f09SDavid van Moolenbroek 		dns_keytable_detach(&sr);
1837*00b67f09SDavid van Moolenbroek 	}
1838*00b67f09SDavid van Moolenbroek 	dst_key_free(&key);
1839*00b67f09SDavid van Moolenbroek }
1840*00b67f09SDavid van Moolenbroek 
1841*00b67f09SDavid van Moolenbroek #define NZF ".nzf"
1842*00b67f09SDavid van Moolenbroek 
1843*00b67f09SDavid van Moolenbroek void
dns_view_setnewzones(dns_view_t * view,isc_boolean_t allow,void * cfgctx,void (* cfg_destroy)(void **))1844*00b67f09SDavid van Moolenbroek dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
1845*00b67f09SDavid van Moolenbroek 		     void (*cfg_destroy)(void **))
1846*00b67f09SDavid van Moolenbroek {
1847*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1848*00b67f09SDavid van Moolenbroek 	REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow);
1849*00b67f09SDavid van Moolenbroek 
1850*00b67f09SDavid van Moolenbroek 	if (view->new_zone_file != NULL) {
1851*00b67f09SDavid van Moolenbroek 		isc_mem_free(view->mctx, view->new_zone_file);
1852*00b67f09SDavid van Moolenbroek 		view->new_zone_file = NULL;
1853*00b67f09SDavid van Moolenbroek 	}
1854*00b67f09SDavid van Moolenbroek 
1855*00b67f09SDavid van Moolenbroek 	if (view->new_zone_config != NULL) {
1856*00b67f09SDavid van Moolenbroek 		view->cfg_destroy(&view->new_zone_config);
1857*00b67f09SDavid van Moolenbroek 		view->cfg_destroy = NULL;
1858*00b67f09SDavid van Moolenbroek 	}
1859*00b67f09SDavid van Moolenbroek 
1860*00b67f09SDavid van Moolenbroek 	if (allow) {
1861*00b67f09SDavid van Moolenbroek 		char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(NZF)];
1862*00b67f09SDavid van Moolenbroek 		isc_sha256_data((void *)view->name, strlen(view->name), buffer);
1863*00b67f09SDavid van Moolenbroek 		/* Truncate the hash at 16 chars; full length is overkill */
1864*00b67f09SDavid van Moolenbroek 		isc_string_printf(buffer + 16, sizeof(NZF), "%s", NZF);
1865*00b67f09SDavid van Moolenbroek 		view->new_zone_file = isc_mem_strdup(view->mctx, buffer);
1866*00b67f09SDavid van Moolenbroek 		view->new_zone_config = cfgctx;
1867*00b67f09SDavid van Moolenbroek 		view->cfg_destroy = cfg_destroy;
1868*00b67f09SDavid van Moolenbroek 	}
1869*00b67f09SDavid van Moolenbroek }
1870*00b67f09SDavid van Moolenbroek 
1871*00b67f09SDavid van Moolenbroek isc_result_t
dns_view_searchdlz(dns_view_t * view,dns_name_t * name,unsigned int minlabels,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo,dns_db_t ** dbp)1872*00b67f09SDavid van Moolenbroek dns_view_searchdlz(dns_view_t *view, dns_name_t *name, unsigned int minlabels,
1873*00b67f09SDavid van Moolenbroek 		   dns_clientinfomethods_t *methods,
1874*00b67f09SDavid van Moolenbroek 		   dns_clientinfo_t *clientinfo,
1875*00b67f09SDavid van Moolenbroek 		   dns_db_t **dbp)
1876*00b67f09SDavid van Moolenbroek {
1877*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fname;
1878*00b67f09SDavid van Moolenbroek 	dns_name_t *zonename;
1879*00b67f09SDavid van Moolenbroek 	unsigned int namelabels;
1880*00b67f09SDavid van Moolenbroek 	unsigned int i;
1881*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1882*00b67f09SDavid van Moolenbroek 	dns_dlzfindzone_t findzone;
1883*00b67f09SDavid van Moolenbroek 	dns_dlzdb_t *dlzdb;
1884*00b67f09SDavid van Moolenbroek 	dns_db_t *db, *best = NULL;
1885*00b67f09SDavid van Moolenbroek 
1886*00b67f09SDavid van Moolenbroek 	/*
1887*00b67f09SDavid van Moolenbroek 	 * Performs checks to make sure data is as we expect it to be.
1888*00b67f09SDavid van Moolenbroek 	 */
1889*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_VIEW_VALID(view));
1890*00b67f09SDavid van Moolenbroek 	REQUIRE(name != NULL);
1891*00b67f09SDavid van Moolenbroek 	REQUIRE(dbp != NULL && *dbp == NULL);
1892*00b67f09SDavid van Moolenbroek 
1893*00b67f09SDavid van Moolenbroek 	/* setup a "fixed" dns name */
1894*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fname);
1895*00b67f09SDavid van Moolenbroek 	zonename = dns_fixedname_name(&fname);
1896*00b67f09SDavid van Moolenbroek 
1897*00b67f09SDavid van Moolenbroek 	/* count the number of labels in the name */
1898*00b67f09SDavid van Moolenbroek 	namelabels = dns_name_countlabels(name);
1899*00b67f09SDavid van Moolenbroek 
1900*00b67f09SDavid van Moolenbroek 	for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
1901*00b67f09SDavid van Moolenbroek 	     dlzdb != NULL;
1902*00b67f09SDavid van Moolenbroek 	     dlzdb = ISC_LIST_NEXT(dlzdb, link))
1903*00b67f09SDavid van Moolenbroek 	{
1904*00b67f09SDavid van Moolenbroek 		REQUIRE(DNS_DLZ_VALID(dlzdb));
1905*00b67f09SDavid van Moolenbroek 
1906*00b67f09SDavid van Moolenbroek 		/*
1907*00b67f09SDavid van Moolenbroek 		 * loop through starting with the longest domain name and
1908*00b67f09SDavid van Moolenbroek 		 * trying shorter names portions of the name until we find a
1909*00b67f09SDavid van Moolenbroek 		 * match, have an error, or are below the 'minlabels'
1910*00b67f09SDavid van Moolenbroek 		 * threshold.  minlabels is 0, if neither the standard
1911*00b67f09SDavid van Moolenbroek 		 * database nor any previous DLZ database had a zone name
1912*00b67f09SDavid van Moolenbroek 		 * match. Otherwise minlabels is the number of labels
1913*00b67f09SDavid van Moolenbroek 		 * in that name.  We need to beat that for a "better"
1914*00b67f09SDavid van Moolenbroek 		 * match for this DLZ database to be authoritative.
1915*00b67f09SDavid van Moolenbroek 		 */
1916*00b67f09SDavid van Moolenbroek 		for (i = namelabels; i > minlabels && i > 1; i--) {
1917*00b67f09SDavid van Moolenbroek 			if (i == namelabels) {
1918*00b67f09SDavid van Moolenbroek 				result = dns_name_copy(name, zonename, NULL);
1919*00b67f09SDavid van Moolenbroek 				if (result != ISC_R_SUCCESS)
1920*00b67f09SDavid van Moolenbroek 					return (result);
1921*00b67f09SDavid van Moolenbroek 			} else
1922*00b67f09SDavid van Moolenbroek 				dns_name_split(name, i, NULL, zonename);
1923*00b67f09SDavid van Moolenbroek 
1924*00b67f09SDavid van Moolenbroek 			/* ask SDLZ driver if the zone is supported */
1925*00b67f09SDavid van Moolenbroek 			db = NULL;
1926*00b67f09SDavid van Moolenbroek 			findzone = dlzdb->implementation->methods->findzone;
1927*00b67f09SDavid van Moolenbroek 			result = (*findzone)(dlzdb->implementation->driverarg,
1928*00b67f09SDavid van Moolenbroek 					     dlzdb->dbdata, dlzdb->mctx,
1929*00b67f09SDavid van Moolenbroek 					     view->rdclass, zonename,
1930*00b67f09SDavid van Moolenbroek 					     methods, clientinfo, &db);
1931*00b67f09SDavid van Moolenbroek 
1932*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_NOTFOUND) {
1933*00b67f09SDavid van Moolenbroek 				if (best != NULL)
1934*00b67f09SDavid van Moolenbroek 					dns_db_detach(&best);
1935*00b67f09SDavid van Moolenbroek 				if (result == ISC_R_SUCCESS) {
1936*00b67f09SDavid van Moolenbroek 					INSIST(db != NULL);
1937*00b67f09SDavid van Moolenbroek 					dns_db_attach(db, &best);
1938*00b67f09SDavid van Moolenbroek 					dns_db_detach(&db);
1939*00b67f09SDavid van Moolenbroek 					minlabels = i;
1940*00b67f09SDavid van Moolenbroek 				} else {
1941*00b67f09SDavid van Moolenbroek 					if (db != NULL)
1942*00b67f09SDavid van Moolenbroek 						dns_db_detach(&db);
1943*00b67f09SDavid van Moolenbroek 					break;
1944*00b67f09SDavid van Moolenbroek 				}
1945*00b67f09SDavid van Moolenbroek 			} else if (db != NULL)
1946*00b67f09SDavid van Moolenbroek 				dns_db_detach(&db);
1947*00b67f09SDavid van Moolenbroek 		}
1948*00b67f09SDavid van Moolenbroek 	}
1949*00b67f09SDavid van Moolenbroek 
1950*00b67f09SDavid van Moolenbroek 	if (best != NULL) {
1951*00b67f09SDavid van Moolenbroek 		dns_db_attach(best, dbp);
1952*00b67f09SDavid van Moolenbroek 		dns_db_detach(&best);
1953*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
1954*00b67f09SDavid van Moolenbroek 	}
1955*00b67f09SDavid van Moolenbroek 
1956*00b67f09SDavid van Moolenbroek 	return (ISC_R_NOTFOUND);
1957*00b67f09SDavid van Moolenbroek }
1958