view.c revision 135446
1/*
2 * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003  Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* $Id: view.c,v 1.103.2.5.2.14 2004/03/10 02:55:58 marka Exp $ */
19
20#include <config.h>
21
22#include <isc/hash.h>
23#include <isc/task.h>
24#include <isc/string.h>		/* Required for HP/UX (and others?) */
25#include <isc/util.h>
26
27#include <dns/acl.h>
28#include <dns/adb.h>
29#include <dns/cache.h>
30#include <dns/db.h>
31#include <dns/events.h>
32#include <dns/forward.h>
33#include <dns/keytable.h>
34#include <dns/master.h>
35#include <dns/masterdump.h>
36#include <dns/order.h>
37#include <dns/peer.h>
38#include <dns/rdataset.h>
39#include <dns/request.h>
40#include <dns/resolver.h>
41#include <dns/result.h>
42#include <dns/tsig.h>
43#include <dns/zone.h>
44#include <dns/zt.h>
45
46#define RESSHUTDOWN(v)	(((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0)
47#define ADBSHUTDOWN(v)	(((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
48#define REQSHUTDOWN(v)	(((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0)
49
50#define DNS_VIEW_DELONLYHASH 111
51
52static void resolver_shutdown(isc_task_t *task, isc_event_t *event);
53static void adb_shutdown(isc_task_t *task, isc_event_t *event);
54static void req_shutdown(isc_task_t *task, isc_event_t *event);
55
56isc_result_t
57dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
58		const char *name, dns_view_t **viewp)
59{
60	dns_view_t *view;
61	isc_result_t result;
62
63	/*
64	 * Create a view.
65	 */
66
67	REQUIRE(name != NULL);
68	REQUIRE(viewp != NULL && *viewp == NULL);
69
70	view = isc_mem_get(mctx, sizeof(*view));
71	if (view == NULL)
72		return (ISC_R_NOMEMORY);
73	view->name = isc_mem_strdup(mctx, name);
74	if (view->name == NULL) {
75		result = ISC_R_NOMEMORY;
76		goto cleanup_view;
77	}
78	result = isc_mutex_init(&view->lock);
79	if (result != ISC_R_SUCCESS) {
80		UNEXPECTED_ERROR(__FILE__, __LINE__,
81				 "isc_mutex_init() failed: %s",
82				 isc_result_totext(result));
83		result = ISC_R_UNEXPECTED;
84		goto cleanup_name;
85	}
86	view->zonetable = NULL;
87	result = dns_zt_create(mctx, rdclass, &view->zonetable);
88	if (result != ISC_R_SUCCESS) {
89		UNEXPECTED_ERROR(__FILE__, __LINE__,
90				 "dns_zt_create() failed: %s",
91				 isc_result_totext(result));
92		result = ISC_R_UNEXPECTED;
93		goto cleanup_mutex;
94	}
95	view->secroots = NULL;
96	result = dns_keytable_create(mctx, &view->secroots);
97	if (result != ISC_R_SUCCESS) {
98		UNEXPECTED_ERROR(__FILE__, __LINE__,
99				 "dns_keytable_create() failed: %s",
100				 isc_result_totext(result));
101		result = ISC_R_UNEXPECTED;
102		goto cleanup_zt;
103	}
104	view->trustedkeys = NULL;
105	result = dns_keytable_create(mctx, &view->trustedkeys);
106	if (result != ISC_R_SUCCESS) {
107		UNEXPECTED_ERROR(__FILE__, __LINE__,
108				 "dns_keytable_create() failed: %s",
109				 isc_result_totext(result));
110		result = ISC_R_UNEXPECTED;
111		goto cleanup_secroots;
112	}
113	view->fwdtable = NULL;
114	result = dns_fwdtable_create(mctx, &view->fwdtable);
115	if (result != ISC_R_SUCCESS) {
116		UNEXPECTED_ERROR(__FILE__, __LINE__,
117				 "dns_fwdtable_create() failed: %s",
118				 isc_result_totext(result));
119		result = ISC_R_UNEXPECTED;
120		goto cleanup_trustedkeys;
121	}
122
123	view->cache = NULL;
124	view->cachedb = NULL;
125	view->hints = NULL;
126	view->resolver = NULL;
127	view->adb = NULL;
128	view->requestmgr = NULL;
129	view->mctx = mctx;
130	view->rdclass = rdclass;
131	view->frozen = ISC_FALSE;
132	view->task = NULL;
133	isc_refcount_init(&view->references, 1);
134	view->weakrefs = 0;
135	view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
136			    DNS_VIEWATTR_REQSHUTDOWN);
137	view->statickeys = NULL;
138	view->dynamickeys = NULL;
139	view->matchclients = NULL;
140	view->matchdestinations = NULL;
141	view->matchrecursiveonly = ISC_FALSE;
142	result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
143	if (result != ISC_R_SUCCESS)
144		goto cleanup_fwdtable;
145	view->peers = NULL;
146	view->order = NULL;
147	view->delonly = NULL;
148	view->rootdelonly = ISC_FALSE;
149	view->rootexclude = NULL;
150
151	/*
152	 * Initialize configuration data with default values.
153	 */
154	view->recursion = ISC_TRUE;
155	view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */
156	view->additionalfromcache = ISC_TRUE;
157	view->additionalfromauth = ISC_TRUE;
158	view->enablednssec = ISC_TRUE;
159	view->minimalresponses = ISC_FALSE;
160	view->transfer_format = dns_one_answer;
161	view->queryacl = NULL;
162	view->recursionacl = NULL;
163	view->sortlist = NULL;
164	view->requestixfr = ISC_TRUE;
165	view->provideixfr = ISC_TRUE;
166	view->maxcachettl = 7 * 24 * 3600;
167	view->maxncachettl = 3 * 3600;
168	view->dstport = 53;
169	view->preferred_glue = 0;
170	view->flush = ISC_FALSE;
171	view->dlv = NULL;
172	dns_fixedname_init(&view->dlv_fixed);
173
174	result = dns_order_create(view->mctx, &view->order);
175	if (result != ISC_R_SUCCESS)
176		goto cleanup_dynkeys;
177
178	result = dns_peerlist_new(view->mctx, &view->peers);
179	if (result != ISC_R_SUCCESS)
180		goto cleanup_order;
181
182	result = dns_aclenv_init(view->mctx, &view->aclenv);
183	if (result != ISC_R_SUCCESS)
184		goto cleanup_peerlist;
185
186	ISC_LINK_INIT(view, link);
187	ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL,
188		       DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown,
189		       view, NULL, NULL, NULL);
190	ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL,
191		       DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown,
192		       view, NULL, NULL, NULL);
193	ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL,
194		       DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown,
195		       view, NULL, NULL, NULL);
196	view->magic = DNS_VIEW_MAGIC;
197
198	*viewp = view;
199
200	return (ISC_R_SUCCESS);
201
202 cleanup_peerlist:
203	dns_peerlist_detach(&view->peers);
204
205 cleanup_order:
206	dns_order_detach(&view->order);
207
208 cleanup_dynkeys:
209	dns_tsigkeyring_destroy(&view->dynamickeys);
210
211 cleanup_fwdtable:
212	dns_fwdtable_destroy(&view->fwdtable);
213
214 cleanup_trustedkeys:
215	dns_keytable_detach(&view->trustedkeys);
216
217 cleanup_secroots:
218	dns_keytable_detach(&view->secroots);
219
220 cleanup_zt:
221	dns_zt_detach(&view->zonetable);
222
223 cleanup_mutex:
224	DESTROYLOCK(&view->lock);
225
226 cleanup_name:
227	isc_mem_free(mctx, view->name);
228
229 cleanup_view:
230	isc_mem_put(mctx, view, sizeof(*view));
231
232	return (result);
233}
234
235static inline void
236destroy(dns_view_t *view) {
237	REQUIRE(!ISC_LINK_LINKED(view, link));
238	REQUIRE(isc_refcount_current(&view->references) == 0);
239	REQUIRE(view->weakrefs == 0);
240	REQUIRE(RESSHUTDOWN(view));
241	REQUIRE(ADBSHUTDOWN(view));
242	REQUIRE(REQSHUTDOWN(view));
243
244	if (view->order != NULL)
245		dns_order_detach(&view->order);
246	if (view->peers != NULL)
247		dns_peerlist_detach(&view->peers);
248	if (view->dynamickeys != NULL)
249		dns_tsigkeyring_destroy(&view->dynamickeys);
250	if (view->statickeys != NULL)
251		dns_tsigkeyring_destroy(&view->statickeys);
252	if (view->adb != NULL)
253		dns_adb_detach(&view->adb);
254	if (view->resolver != NULL)
255		dns_resolver_detach(&view->resolver);
256	if (view->requestmgr != NULL)
257		dns_requestmgr_detach(&view->requestmgr);
258	if (view->task != NULL)
259		isc_task_detach(&view->task);
260	if (view->hints != NULL)
261		dns_db_detach(&view->hints);
262	if (view->cachedb != NULL)
263		dns_db_detach(&view->cachedb);
264	if (view->cache != NULL)
265		dns_cache_detach(&view->cache);
266	if (view->matchclients != NULL)
267		dns_acl_detach(&view->matchclients);
268	if (view->matchdestinations != NULL)
269		dns_acl_detach(&view->matchdestinations);
270	if (view->queryacl != NULL)
271		dns_acl_detach(&view->queryacl);
272	if (view->recursionacl != NULL)
273		dns_acl_detach(&view->recursionacl);
274	if (view->sortlist != NULL)
275		dns_acl_detach(&view->sortlist);
276	if (view->delonly != NULL) {
277		dns_name_t *name;
278		int i;
279
280		for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
281			name = ISC_LIST_HEAD(view->delonly[i]);
282			while (name != NULL) {
283				ISC_LIST_UNLINK(view->delonly[i], name, link);
284				dns_name_free(name, view->mctx);
285				isc_mem_put(view->mctx, name, sizeof(*name));
286				name = ISC_LIST_HEAD(view->delonly[i]);
287			}
288		}
289		isc_mem_put(view->mctx, view->delonly, sizeof(dns_namelist_t) *
290			    DNS_VIEW_DELONLYHASH);
291		view->delonly = NULL;
292	}
293	if (view->rootexclude != NULL) {
294		dns_name_t *name;
295		int i;
296
297		for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
298			name = ISC_LIST_HEAD(view->rootexclude[i]);
299			while (name != NULL) {
300				ISC_LIST_UNLINK(view->rootexclude[i],
301					 	name, link);
302				dns_name_free(name, view->mctx);
303				isc_mem_put(view->mctx, name, sizeof(*name));
304				name = ISC_LIST_HEAD(view->rootexclude[i]);
305			}
306		}
307		isc_mem_put(view->mctx, view->rootexclude,
308			    sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH);
309		view->rootexclude = NULL;
310	}
311	dns_keytable_detach(&view->trustedkeys);
312	dns_keytable_detach(&view->secroots);
313	dns_fwdtable_destroy(&view->fwdtable);
314	dns_aclenv_destroy(&view->aclenv);
315	DESTROYLOCK(&view->lock);
316	isc_refcount_destroy(&view->references);
317	isc_mem_free(view->mctx, view->name);
318	isc_mem_put(view->mctx, view, sizeof(*view));
319}
320
321/*
322 * Return true iff 'view' may be freed.
323 * The caller must be holding the view lock.
324 */
325static isc_boolean_t
326all_done(dns_view_t *view) {
327
328	if (isc_refcount_current(&view->references) == 0 &&
329	    view->weakrefs == 0 &&
330	    RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view))
331		return (ISC_TRUE);
332
333	return (ISC_FALSE);
334}
335
336void
337dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
338
339	REQUIRE(DNS_VIEW_VALID(source));
340	REQUIRE(targetp != NULL && *targetp == NULL);
341
342	isc_refcount_increment(&source->references, NULL);
343
344	*targetp = source;
345}
346
347static void
348view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) {
349	dns_view_t *view;
350	unsigned int refs;
351	isc_boolean_t done = ISC_FALSE;
352
353	REQUIRE(viewp != NULL);
354	view = *viewp;
355	REQUIRE(DNS_VIEW_VALID(view));
356
357	if (flush)
358		view->flush = ISC_TRUE;
359	isc_refcount_decrement(&view->references, &refs);
360	if (refs == 0) {
361		LOCK(&view->lock);
362		if (!RESSHUTDOWN(view))
363			dns_resolver_shutdown(view->resolver);
364		if (!ADBSHUTDOWN(view))
365			dns_adb_shutdown(view->adb);
366		if (!REQSHUTDOWN(view))
367			dns_requestmgr_shutdown(view->requestmgr);
368		if (view->flush)
369			dns_zt_flushanddetach(&view->zonetable);
370		else
371			dns_zt_detach(&view->zonetable);
372		done = all_done(view);
373		UNLOCK(&view->lock);
374	}
375
376	*viewp = NULL;
377
378	if (done)
379		destroy(view);
380}
381
382void
383dns_view_flushanddetach(dns_view_t **viewp) {
384	view_flushanddetach(viewp, ISC_TRUE);
385}
386
387void
388dns_view_detach(dns_view_t **viewp) {
389	view_flushanddetach(viewp, ISC_FALSE);
390}
391
392static isc_result_t
393dialup(dns_zone_t *zone, void *dummy) {
394	UNUSED(dummy);
395	dns_zone_dialup(zone);
396	return (ISC_R_SUCCESS);
397}
398
399void
400dns_view_dialup(dns_view_t *view) {
401	REQUIRE(DNS_VIEW_VALID(view));
402	(void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL);
403}
404
405void
406dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) {
407
408	REQUIRE(DNS_VIEW_VALID(source));
409	REQUIRE(targetp != NULL && *targetp == NULL);
410
411	LOCK(&source->lock);
412	source->weakrefs++;
413	UNLOCK(&source->lock);
414
415	*targetp = source;
416}
417
418void
419dns_view_weakdetach(dns_view_t **viewp) {
420	dns_view_t *view;
421	isc_boolean_t done = ISC_FALSE;
422
423	REQUIRE(viewp != NULL);
424	view = *viewp;
425	REQUIRE(DNS_VIEW_VALID(view));
426
427	LOCK(&view->lock);
428
429	INSIST(view->weakrefs > 0);
430	view->weakrefs--;
431	done = all_done(view);
432
433	UNLOCK(&view->lock);
434
435	*viewp = NULL;
436
437	if (done)
438		destroy(view);
439}
440
441static void
442resolver_shutdown(isc_task_t *task, isc_event_t *event) {
443	dns_view_t *view = event->ev_arg;
444	isc_boolean_t done;
445
446	REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN);
447	REQUIRE(DNS_VIEW_VALID(view));
448	REQUIRE(view->task == task);
449
450	UNUSED(task);
451
452	LOCK(&view->lock);
453
454	view->attributes |= DNS_VIEWATTR_RESSHUTDOWN;
455	done = all_done(view);
456
457	UNLOCK(&view->lock);
458
459	isc_event_free(&event);
460
461	if (done)
462		destroy(view);
463}
464
465static void
466adb_shutdown(isc_task_t *task, isc_event_t *event) {
467	dns_view_t *view = event->ev_arg;
468	isc_boolean_t done;
469
470	REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN);
471	REQUIRE(DNS_VIEW_VALID(view));
472	REQUIRE(view->task == task);
473
474	UNUSED(task);
475
476	LOCK(&view->lock);
477
478	view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN;
479	done = all_done(view);
480
481	UNLOCK(&view->lock);
482
483	isc_event_free(&event);
484
485	if (done)
486		destroy(view);
487}
488
489static void
490req_shutdown(isc_task_t *task, isc_event_t *event) {
491	dns_view_t *view = event->ev_arg;
492	isc_boolean_t done;
493
494	REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN);
495	REQUIRE(DNS_VIEW_VALID(view));
496	REQUIRE(view->task == task);
497
498	UNUSED(task);
499
500	LOCK(&view->lock);
501
502	view->attributes |= DNS_VIEWATTR_REQSHUTDOWN;
503	done = all_done(view);
504
505	UNLOCK(&view->lock);
506
507	isc_event_free(&event);
508
509	if (done)
510		destroy(view);
511}
512
513isc_result_t
514dns_view_createresolver(dns_view_t *view,
515			isc_taskmgr_t *taskmgr, unsigned int ntasks,
516			isc_socketmgr_t *socketmgr,
517			isc_timermgr_t *timermgr,
518			unsigned int options,
519			dns_dispatchmgr_t *dispatchmgr,
520			dns_dispatch_t *dispatchv4,
521			dns_dispatch_t *dispatchv6)
522{
523	isc_result_t result;
524	isc_event_t *event;
525	isc_mem_t *mctx = NULL;
526
527	REQUIRE(DNS_VIEW_VALID(view));
528	REQUIRE(!view->frozen);
529	REQUIRE(view->resolver == NULL);
530
531	result = isc_task_create(taskmgr, 0, &view->task);
532	if (result != ISC_R_SUCCESS)
533		return (result);
534	isc_task_setname(view->task, "view", view);
535
536	result = dns_resolver_create(view, taskmgr, ntasks, socketmgr,
537				     timermgr, options, dispatchmgr,
538				     dispatchv4, dispatchv6,
539				     &view->resolver);
540	if (result != ISC_R_SUCCESS) {
541		isc_task_detach(&view->task);
542		return (result);
543	}
544	event = &view->resevent;
545	dns_resolver_whenshutdown(view->resolver, view->task, &event);
546	view->attributes &= ~DNS_VIEWATTR_RESSHUTDOWN;
547
548	result = isc_mem_create(0, 0, &mctx);
549	if (result != ISC_R_SUCCESS) {
550		dns_resolver_shutdown(view->resolver);
551		return (result);
552	}
553
554	result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb);
555	isc_mem_detach(&mctx);
556	if (result != ISC_R_SUCCESS) {
557		dns_resolver_shutdown(view->resolver);
558		return (result);
559	}
560	event = &view->adbevent;
561	dns_adb_whenshutdown(view->adb, view->task, &event);
562	view->attributes &= ~DNS_VIEWATTR_ADBSHUTDOWN;
563
564	result = dns_requestmgr_create(view->mctx, timermgr, socketmgr,
565				      dns_resolver_taskmgr(view->resolver),
566				      dns_resolver_dispatchmgr(view->resolver),
567				      dns_resolver_dispatchv4(view->resolver),
568				      dns_resolver_dispatchv6(view->resolver),
569				      &view->requestmgr);
570	if (result != ISC_R_SUCCESS) {
571		dns_adb_shutdown(view->adb);
572		dns_resolver_shutdown(view->resolver);
573		return (result);
574	}
575	event = &view->reqevent;
576	dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event);
577	view->attributes &= ~DNS_VIEWATTR_REQSHUTDOWN;
578
579	return (ISC_R_SUCCESS);
580}
581
582void
583dns_view_setcache(dns_view_t *view, dns_cache_t *cache) {
584	REQUIRE(DNS_VIEW_VALID(view));
585	REQUIRE(!view->frozen);
586
587	if (view->cache != NULL) {
588		dns_db_detach(&view->cachedb);
589		dns_cache_detach(&view->cache);
590	}
591	dns_cache_attach(cache, &view->cache);
592	dns_cache_attachdb(cache, &view->cachedb);
593	INSIST(DNS_DB_VALID(view->cachedb));
594}
595
596void
597dns_view_sethints(dns_view_t *view, dns_db_t *hints) {
598	REQUIRE(DNS_VIEW_VALID(view));
599	REQUIRE(!view->frozen);
600	REQUIRE(view->hints == NULL);
601	REQUIRE(dns_db_iszone(hints));
602
603	dns_db_attach(hints, &view->hints);
604}
605
606void
607dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
608	REQUIRE(DNS_VIEW_VALID(view));
609	REQUIRE(ring != NULL);
610	if (view->statickeys != NULL)
611		dns_tsigkeyring_destroy(&view->statickeys);
612	view->statickeys = ring;
613}
614
615void
616dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
617	REQUIRE(DNS_VIEW_VALID(view));
618	view->dstport = dstport;
619}
620
621isc_result_t
622dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
623	isc_result_t result;
624
625	REQUIRE(DNS_VIEW_VALID(view));
626	REQUIRE(!view->frozen);
627
628	result = dns_zt_mount(view->zonetable, zone);
629
630	return (result);
631}
632
633void
634dns_view_freeze(dns_view_t *view) {
635	REQUIRE(DNS_VIEW_VALID(view));
636	REQUIRE(!view->frozen);
637
638	if (view->resolver != NULL) {
639		INSIST(view->cachedb != NULL);
640		dns_resolver_freeze(view->resolver);
641	}
642	view->frozen = ISC_TRUE;
643}
644
645isc_result_t
646dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) {
647	isc_result_t result;
648
649	REQUIRE(DNS_VIEW_VALID(view));
650
651	result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
652	if (result == DNS_R_PARTIALMATCH) {
653		dns_zone_detach(zonep);
654		result = ISC_R_NOTFOUND;
655	}
656
657	return (result);
658}
659
660isc_result_t
661dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
662	      isc_stdtime_t now, unsigned int options, isc_boolean_t use_hints,
663	      dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
664	      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
665{
666	isc_result_t result;
667	dns_db_t *db, *zdb;
668	dns_dbnode_t *node, *znode;
669	isc_boolean_t is_cache;
670	dns_rdataset_t zrdataset, zsigrdataset;
671	dns_zone_t *zone;
672
673	/*
674	 * Find an rdataset whose owner name is 'name', and whose type is
675	 * 'type'.
676	 */
677
678	REQUIRE(DNS_VIEW_VALID(view));
679	REQUIRE(view->frozen);
680	REQUIRE(type != dns_rdatatype_rrsig);
681	REQUIRE(rdataset != NULL);  /* XXXBEW - remove this */
682
683	/*
684	 * Initialize.
685	 */
686	dns_rdataset_init(&zrdataset);
687	dns_rdataset_init(&zsigrdataset);
688	zdb = NULL;
689	znode = NULL;
690
691	/*
692	 * Find a database to answer the query.
693	 */
694	zone = NULL;
695	db = NULL;
696	node = NULL;
697	result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
698	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
699		result = dns_zone_getdb(zone, &db);
700		if (result != ISC_R_SUCCESS && view->cachedb != NULL)
701			dns_db_attach(view->cachedb, &db);
702		else if (result != ISC_R_SUCCESS)
703			goto cleanup;
704	} else if (result == ISC_R_NOTFOUND && view->cachedb != NULL)
705		dns_db_attach(view->cachedb, &db);
706	else
707		goto cleanup;
708
709	is_cache = dns_db_iscache(db);
710
711 db_find:
712	/*
713	 * Now look for an answer in the database.
714	 */
715	result = dns_db_find(db, name, NULL, type, options,
716			     now, &node, foundname, rdataset, sigrdataset);
717
718	if (result == DNS_R_DELEGATION ||
719	    result == ISC_R_NOTFOUND) {
720		if (dns_rdataset_isassociated(rdataset))
721			dns_rdataset_disassociate(rdataset);
722		if (sigrdataset != NULL &&
723		    dns_rdataset_isassociated(sigrdataset))
724			dns_rdataset_disassociate(sigrdataset);
725		if (node != NULL)
726			dns_db_detachnode(db, &node);
727		if (!is_cache) {
728			dns_db_detach(&db);
729			if (view->cachedb != NULL) {
730				/*
731				 * Either the answer is in the cache, or we
732				 * don't know it.
733				 */
734				is_cache = ISC_TRUE;
735				dns_db_attach(view->cachedb, &db);
736				goto db_find;
737			}
738		} else {
739			/*
740			 * We don't have the data in the cache.  If we've got
741			 * glue from the zone, use it.
742			 */
743			if (dns_rdataset_isassociated(&zrdataset)) {
744				dns_rdataset_clone(&zrdataset, rdataset);
745				if (sigrdataset != NULL &&
746				    dns_rdataset_isassociated(&zsigrdataset))
747					dns_rdataset_clone(&zsigrdataset,
748							   sigrdataset);
749				result = DNS_R_GLUE;
750				if (db != NULL)
751					dns_db_detach(&db);
752				dns_db_attach(zdb, &db);
753				dns_db_attachnode(db, znode, &node);
754				goto cleanup;
755			}
756		}
757		/*
758		 * We don't know the answer.
759		 */
760		result = ISC_R_NOTFOUND;
761	} else if (result == DNS_R_GLUE) {
762		if (view->cachedb != NULL) {
763			/*
764			 * We found an answer, but the cache may be better.
765			 * Remember what we've got and go look in the cache.
766			 */
767			is_cache = ISC_TRUE;
768			dns_rdataset_clone(rdataset, &zrdataset);
769			dns_rdataset_disassociate(rdataset);
770			if (sigrdataset != NULL &&
771			    dns_rdataset_isassociated(sigrdataset)) {
772				dns_rdataset_clone(sigrdataset, &zsigrdataset);
773				dns_rdataset_disassociate(sigrdataset);
774			}
775			dns_db_attach(db, &zdb);
776			dns_db_attachnode(zdb, node, &znode);
777			dns_db_detachnode(db, &node);
778			dns_db_detach(&db);
779			dns_db_attach(view->cachedb, &db);
780			goto db_find;
781		}
782		/*
783		 * Otherwise, the glue is the best answer.
784		 */
785		result = ISC_R_SUCCESS;
786	}
787
788	if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
789		if (dns_rdataset_isassociated(rdataset))
790			dns_rdataset_disassociate(rdataset);
791		if (sigrdataset != NULL &&
792		    dns_rdataset_isassociated(sigrdataset))
793			dns_rdataset_disassociate(sigrdataset);
794		if (db != NULL) {
795			if (node != NULL)
796				dns_db_detachnode(db, &node);
797			dns_db_detach(&db);
798		}
799		result = dns_db_find(view->hints, name, NULL, type, options,
800				     now, &node, foundname,
801				     rdataset, sigrdataset);
802		if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) {
803			/*
804			 * We just used a hint.  Let the resolver know it
805			 * should consider priming.
806			 */
807			dns_resolver_prime(view->resolver);
808			dns_db_attach(view->hints, &db);
809			result = DNS_R_HINT;
810		} else if (result == DNS_R_NXRRSET) {
811			dns_db_attach(view->hints, &db);
812			result = DNS_R_HINTNXRRSET;
813		} else if (result == DNS_R_NXDOMAIN)
814			result = ISC_R_NOTFOUND;
815
816		/*
817		 * Cleanup if non-standard hints are used.
818		 */
819		if (db == NULL && node != NULL)
820			dns_db_detachnode(view->hints, &node);
821	}
822
823 cleanup:
824	if (result == DNS_R_NXDOMAIN || result == DNS_R_NXRRSET) {
825		/*
826		 * We don't care about any DNSSEC proof data in these cases.
827		 */
828		if (dns_rdataset_isassociated(rdataset))
829			dns_rdataset_disassociate(rdataset);
830		if (sigrdataset != NULL &&
831		    dns_rdataset_isassociated(sigrdataset))
832			dns_rdataset_disassociate(sigrdataset);
833	}
834
835	if (dns_rdataset_isassociated(&zrdataset)) {
836		dns_rdataset_disassociate(&zrdataset);
837		if (dns_rdataset_isassociated(&zsigrdataset))
838			dns_rdataset_disassociate(&zsigrdataset);
839	}
840
841	if (zdb != NULL) {
842		if (znode != NULL)
843			dns_db_detachnode(zdb, &znode);
844		dns_db_detach(&zdb);
845	}
846
847	if (db != NULL) {
848		if (node != NULL) {
849			if (nodep != NULL)
850				*nodep = node;
851			else
852				dns_db_detachnode(db, &node);
853		}
854		if (dbp != NULL)
855			*dbp = db;
856		else
857			dns_db_detach(&db);
858	} else
859		INSIST(node == NULL);
860
861	if (zone != NULL)
862		dns_zone_detach(&zone);
863
864	return (result);
865}
866
867isc_result_t
868dns_view_simplefind(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
869		    isc_stdtime_t now, unsigned int options,
870		    isc_boolean_t use_hints,
871		    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
872{
873	isc_result_t result;
874	dns_fixedname_t foundname;
875
876	dns_fixedname_init(&foundname);
877	result = dns_view_find(view, name, type, now, options, use_hints,
878			       NULL, NULL, dns_fixedname_name(&foundname),
879			       rdataset, sigrdataset);
880	if (result == DNS_R_NXDOMAIN) {
881		/*
882		 * The rdataset and sigrdataset of the relevant NSEC record
883		 * may be returned, but the caller cannot use them because
884		 * foundname is not returned by this simplified API.  We
885		 * disassociate them here to prevent any misuse by the caller.
886		 */
887		if (dns_rdataset_isassociated(rdataset))
888			dns_rdataset_disassociate(rdataset);
889		if (sigrdataset != NULL &&
890		    dns_rdataset_isassociated(sigrdataset))
891			dns_rdataset_disassociate(sigrdataset);
892	} else if (result != ISC_R_SUCCESS &&
893		   result != DNS_R_GLUE &&
894		   result != DNS_R_HINT &&
895		   result != DNS_R_NCACHENXDOMAIN &&
896		   result != DNS_R_NCACHENXRRSET &&
897		   result != DNS_R_NXRRSET &&
898		   result != DNS_R_HINTNXRRSET &&
899		   result != ISC_R_NOTFOUND) {
900		if (dns_rdataset_isassociated(rdataset))
901			dns_rdataset_disassociate(rdataset);
902		if (sigrdataset != NULL &&
903		    dns_rdataset_isassociated(sigrdataset))
904			dns_rdataset_disassociate(sigrdataset);
905		result = ISC_R_NOTFOUND;
906	}
907
908	return (result);
909}
910
911isc_result_t
912dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
913		     isc_stdtime_t now, unsigned int options,
914		     isc_boolean_t use_hints,
915		     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
916{
917	return(dns_view_findzonecut2(view, name, fname, now, options,
918				     use_hints, ISC_TRUE,
919				     rdataset, sigrdataset));
920}
921
922isc_result_t
923dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
924		      isc_stdtime_t now, unsigned int options,
925		      isc_boolean_t use_hints,  isc_boolean_t use_cache,
926		      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
927{
928	isc_result_t result;
929	dns_db_t *db;
930	isc_boolean_t is_cache, use_zone, try_hints;
931	dns_zone_t *zone;
932	dns_name_t *zfname;
933	dns_rdataset_t zrdataset, zsigrdataset;
934	dns_fixedname_t zfixedname;
935
936	REQUIRE(DNS_VIEW_VALID(view));
937	REQUIRE(view->frozen);
938
939	db = NULL;
940	zone = NULL;
941	use_zone = ISC_FALSE;
942	try_hints = ISC_FALSE;
943	zfname = NULL;
944
945	/*
946	 * Initialize.
947	 */
948	dns_fixedname_init(&zfixedname);
949	dns_rdataset_init(&zrdataset);
950	dns_rdataset_init(&zsigrdataset);
951
952	/*
953	 * Find the right database.
954	 */
955	result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
956	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
957		result = dns_zone_getdb(zone, &db);
958	if (result == ISC_R_NOTFOUND) {
959		/*
960		 * We're not directly authoritative for this query name, nor
961		 * is it a subdomain of any zone for which we're
962		 * authoritative.
963		 */
964		if (use_cache && view->cachedb != NULL) {
965			/*
966			 * We have a cache; try it.
967			 */
968			dns_db_attach(view->cachedb, &db);
969		} else {
970			/*
971			 * Maybe we have hints...
972			 */
973			try_hints = ISC_TRUE;
974			goto finish;
975		}
976	} else if (result != ISC_R_SUCCESS) {
977		/*
978		 * Something is broken.
979		 */
980		goto cleanup;
981	}
982	is_cache = dns_db_iscache(db);
983
984 db_find:
985	/*
986	 * Look for the zonecut.
987	 */
988	if (!is_cache) {
989		result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options,
990				     now, NULL, fname, rdataset, sigrdataset);
991		if (result == DNS_R_DELEGATION)
992			result = ISC_R_SUCCESS;
993		else if (result != ISC_R_SUCCESS)
994			goto cleanup;
995		if (use_cache && view->cachedb != NULL && db != view->hints) {
996			/*
997			 * We found an answer, but the cache may be better.
998			 */
999			zfname = dns_fixedname_name(&zfixedname);
1000			result = dns_name_copy(fname, zfname, NULL);
1001			if (result != ISC_R_SUCCESS)
1002				goto cleanup;
1003			dns_rdataset_clone(rdataset, &zrdataset);
1004			dns_rdataset_disassociate(rdataset);
1005			if (sigrdataset != NULL &&
1006			    dns_rdataset_isassociated(sigrdataset)) {
1007				dns_rdataset_clone(sigrdataset, &zsigrdataset);
1008				dns_rdataset_disassociate(sigrdataset);
1009			}
1010			dns_db_detach(&db);
1011			dns_db_attach(view->cachedb, &db);
1012			is_cache = ISC_TRUE;
1013			goto db_find;
1014		}
1015	} else {
1016		result = dns_db_findzonecut(db, name, options, now, NULL,
1017					    fname, rdataset, sigrdataset);
1018		if (result == ISC_R_SUCCESS) {
1019			if (zfname != NULL &&
1020			    !dns_name_issubdomain(fname, zfname)) {
1021				/*
1022				 * We found a zonecut in the cache, but our
1023				 * zone delegation is better.
1024				 */
1025				use_zone = ISC_TRUE;
1026			}
1027		} else if (result == ISC_R_NOTFOUND) {
1028			if (zfname != NULL) {
1029				/*
1030				 * We didn't find anything in the cache, but we
1031				 * have a zone delegation, so use it.
1032				 */
1033				use_zone = ISC_TRUE;
1034			} else {
1035				/*
1036				 * Maybe we have hints...
1037				 */
1038				try_hints = ISC_TRUE;
1039			}
1040		} else {
1041			/*
1042			 * Something bad happened.
1043			 */
1044			goto cleanup;
1045		}
1046	}
1047
1048 finish:
1049	if (use_zone) {
1050		if (dns_rdataset_isassociated(rdataset)) {
1051			dns_rdataset_disassociate(rdataset);
1052			if (sigrdataset != NULL &&
1053			    dns_rdataset_isassociated(sigrdataset))
1054				dns_rdataset_disassociate(sigrdataset);
1055		}
1056		result = dns_name_copy(zfname, fname, NULL);
1057		if (result != ISC_R_SUCCESS)
1058			goto cleanup;
1059		dns_rdataset_clone(&zrdataset, rdataset);
1060		if (sigrdataset != NULL &&
1061		    dns_rdataset_isassociated(&zrdataset))
1062			dns_rdataset_clone(&zsigrdataset, sigrdataset);
1063	} else if (try_hints && use_hints && view->hints != NULL) {
1064		/*
1065		 * We've found nothing so far, but we have hints.
1066		 */
1067		result = dns_db_find(view->hints, dns_rootname, NULL,
1068				     dns_rdatatype_ns, 0, now, NULL, fname,
1069				     rdataset, NULL);
1070		if (result != ISC_R_SUCCESS) {
1071			/*
1072			 * We can't even find the hints for the root
1073			 * nameservers!
1074			 */
1075			if (dns_rdataset_isassociated(rdataset))
1076				dns_rdataset_disassociate(rdataset);
1077			result = ISC_R_NOTFOUND;
1078		}
1079	}
1080
1081 cleanup:
1082	if (dns_rdataset_isassociated(&zrdataset)) {
1083		dns_rdataset_disassociate(&zrdataset);
1084		if (dns_rdataset_isassociated(&zsigrdataset))
1085			dns_rdataset_disassociate(&zsigrdataset);
1086	}
1087	if (db != NULL)
1088		dns_db_detach(&db);
1089	if (zone != NULL)
1090		dns_zone_detach(&zone);
1091
1092	return (result);
1093}
1094
1095isc_result_t
1096dns_viewlist_find(dns_viewlist_t *list, const char *name,
1097		  dns_rdataclass_t rdclass, dns_view_t **viewp)
1098{
1099	dns_view_t *view;
1100
1101	REQUIRE(list != NULL);
1102
1103	for (view = ISC_LIST_HEAD(*list);
1104	     view != NULL;
1105	     view = ISC_LIST_NEXT(view, link)) {
1106		if (strcmp(view->name, name) == 0 && view->rdclass == rdclass)
1107			break;
1108	}
1109	if (view == NULL)
1110		return (ISC_R_NOTFOUND);
1111
1112	dns_view_attach(view, viewp);
1113
1114	return (ISC_R_SUCCESS);
1115}
1116
1117isc_result_t
1118dns_view_load(dns_view_t *view, isc_boolean_t stop) {
1119
1120	REQUIRE(DNS_VIEW_VALID(view));
1121
1122	return (dns_zt_load(view->zonetable, stop));
1123}
1124
1125isc_result_t
1126dns_view_loadnew(dns_view_t *view, isc_boolean_t stop) {
1127
1128	REQUIRE(DNS_VIEW_VALID(view));
1129
1130	return (dns_zt_loadnew(view->zonetable, stop));
1131}
1132
1133isc_result_t
1134dns_view_gettsig(dns_view_t *view, dns_name_t *keyname, dns_tsigkey_t **keyp)
1135{
1136	isc_result_t result;
1137	REQUIRE(keyp != NULL && *keyp == NULL);
1138
1139	result = dns_tsigkey_find(keyp, keyname, NULL,
1140				  view->statickeys);
1141	if (result == ISC_R_NOTFOUND)
1142		result = dns_tsigkey_find(keyp, keyname, NULL,
1143					  view->dynamickeys);
1144	return (result);
1145}
1146
1147isc_result_t
1148dns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr,
1149		     dns_tsigkey_t **keyp)
1150{
1151	isc_result_t result;
1152	dns_name_t *keyname = NULL;
1153	dns_peer_t *peer = NULL;
1154
1155	result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer);
1156	if (result != ISC_R_SUCCESS)
1157		return (result);
1158
1159	result = dns_peer_getkey(peer, &keyname);
1160	if (result != ISC_R_SUCCESS)
1161		return (result);
1162
1163	return (dns_view_gettsig(view, keyname, keyp));
1164}
1165
1166isc_result_t
1167dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
1168	REQUIRE(DNS_VIEW_VALID(view));
1169	REQUIRE(source != NULL);
1170
1171	return (dns_tsig_verify(source, msg, view->statickeys,
1172				view->dynamickeys));
1173}
1174
1175isc_result_t
1176dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
1177	isc_result_t result;
1178
1179	REQUIRE(DNS_VIEW_VALID(view));
1180
1181	(void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name);
1182	result = dns_master_dumptostream(view->mctx, view->cachedb, NULL,
1183					  &dns_master_style_cache, fp);
1184	if (result != ISC_R_SUCCESS)
1185		return (result);
1186	dns_adb_dump(view->adb, fp);
1187	return (ISC_R_SUCCESS);
1188}
1189
1190isc_result_t
1191dns_view_flushcache(dns_view_t *view) {
1192	isc_result_t result;
1193
1194	REQUIRE(DNS_VIEW_VALID(view));
1195
1196	if (view->cachedb == NULL)
1197		return (ISC_R_SUCCESS);
1198	result = dns_cache_flush(view->cache);
1199	if (result != ISC_R_SUCCESS)
1200		return (result);
1201	dns_db_detach(&view->cachedb);
1202	dns_cache_attachdb(view->cache, &view->cachedb);
1203
1204	dns_adb_flush(view->adb);
1205	return (ISC_R_SUCCESS);
1206}
1207
1208isc_result_t
1209dns_view_flushname(dns_view_t *view, dns_name_t *name) {
1210
1211	REQUIRE(DNS_VIEW_VALID(view));
1212
1213	if (view->adb != NULL)
1214		dns_adb_flushname(view->adb, name);
1215	if (view->cache == NULL)
1216		return (ISC_R_SUCCESS);
1217	return (dns_cache_flushname(view->cache, name));
1218}
1219
1220isc_result_t
1221dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name) {
1222	isc_result_t result;
1223	dns_name_t *new;
1224	isc_uint32_t hash;
1225
1226	REQUIRE(DNS_VIEW_VALID(view));
1227
1228	if (view->delonly == NULL) {
1229		view->delonly = isc_mem_get(view->mctx,
1230					    sizeof(dns_namelist_t) *
1231					    DNS_VIEW_DELONLYHASH);
1232		if (view->delonly == NULL)
1233			return (ISC_R_NOMEMORY);
1234		for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
1235			ISC_LIST_INIT(view->delonly[hash]);
1236	}
1237	hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
1238	new = ISC_LIST_HEAD(view->delonly[hash]);
1239	while (new != NULL && !dns_name_equal(new, name))
1240		new = ISC_LIST_NEXT(new, link);
1241	if (new != NULL)
1242		return (ISC_R_SUCCESS);
1243	new = isc_mem_get(view->mctx, sizeof(*new));
1244	if (new == NULL)
1245		return (ISC_R_NOMEMORY);
1246	dns_name_init(new, NULL);
1247	result = dns_name_dup(name, view->mctx, new);
1248	if (result == ISC_R_SUCCESS)
1249		ISC_LIST_APPEND(view->delonly[hash], new, link);
1250	else
1251		isc_mem_put(view->mctx, new, sizeof(*new));
1252	return (result);
1253}
1254
1255isc_result_t
1256dns_view_excludedelegationonly(dns_view_t *view, dns_name_t *name) {
1257	isc_result_t result;
1258	dns_name_t *new;
1259	isc_uint32_t hash;
1260
1261	REQUIRE(DNS_VIEW_VALID(view));
1262
1263	if (view->rootexclude == NULL) {
1264		view->rootexclude = isc_mem_get(view->mctx,
1265					    sizeof(dns_namelist_t) *
1266					    DNS_VIEW_DELONLYHASH);
1267		if (view->rootexclude == NULL)
1268			return (ISC_R_NOMEMORY);
1269		for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
1270			ISC_LIST_INIT(view->rootexclude[hash]);
1271	}
1272	hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
1273	new = ISC_LIST_HEAD(view->rootexclude[hash]);
1274	while (new != NULL && !dns_name_equal(new, name))
1275		new = ISC_LIST_NEXT(new, link);
1276	if (new != NULL)
1277		return (ISC_R_SUCCESS);
1278	new = isc_mem_get(view->mctx, sizeof(*new));
1279	if (new == NULL)
1280		return (ISC_R_NOMEMORY);
1281	dns_name_init(new, NULL);
1282	result = dns_name_dup(name, view->mctx, new);
1283	if (result == ISC_R_SUCCESS)
1284		ISC_LIST_APPEND(view->rootexclude[hash], new, link);
1285	else
1286		isc_mem_put(view->mctx, new, sizeof(*new));
1287	return (result);
1288}
1289
1290isc_boolean_t
1291dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name) {
1292	dns_name_t *new;
1293	isc_uint32_t hash;
1294
1295	REQUIRE(DNS_VIEW_VALID(view));
1296
1297	if (!view->rootdelonly && view->delonly == NULL)
1298		return (ISC_FALSE);
1299
1300	hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
1301	if (view->rootdelonly && dns_name_countlabels(name) <= 2) {
1302		if (view->rootexclude == NULL)
1303			return (ISC_TRUE);
1304		new = ISC_LIST_HEAD(view->rootexclude[hash]);
1305		while (new != NULL && !dns_name_equal(new, name))
1306			new = ISC_LIST_NEXT(new, link);
1307		if (new == NULL)
1308			return (ISC_TRUE);
1309	}
1310
1311	if (view->delonly == NULL)
1312		return (ISC_FALSE);
1313
1314	new = ISC_LIST_HEAD(view->delonly[hash]);
1315	while (new != NULL && !dns_name_equal(new, name))
1316		new = ISC_LIST_NEXT(new, link);
1317	if (new == NULL)
1318		return (ISC_FALSE);
1319	return (ISC_TRUE);
1320}
1321
1322void
1323dns_view_setrootdelonly(dns_view_t *view, isc_boolean_t value) {
1324	REQUIRE(DNS_VIEW_VALID(view));
1325	view->rootdelonly = value;
1326}
1327
1328isc_boolean_t
1329dns_view_getrootdelonly(dns_view_t *view) {
1330	REQUIRE(DNS_VIEW_VALID(view));
1331	return (view->rootdelonly);
1332}
1333