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