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