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