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