]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/lib/dns/view.c
Update BIND to 9.9.6-P1
[FreeBSD/stable/9.git] / contrib / bind9 / lib / dns / view.c
1 /*
2  * Copyright (C) 2004-2014  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$ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <isc/file.h>
25 #include <isc/hash.h>
26 #include <isc/print.h>
27 #include <isc/sha2.h>
28 #include <isc/stats.h>
29 #include <isc/string.h>         /* Required for HP/UX (and others?) */
30 #include <isc/task.h>
31 #include <isc/util.h>
32
33 #include <dns/acache.h>
34 #include <dns/acl.h>
35 #include <dns/adb.h>
36 #include <dns/cache.h>
37 #include <dns/db.h>
38 #include <dns/dispatch.h>
39 #include <dns/dlz.h>
40 #ifdef BIND9
41 #include <dns/dns64.h>
42 #endif
43 #include <dns/dnssec.h>
44 #include <dns/events.h>
45 #include <dns/forward.h>
46 #include <dns/keytable.h>
47 #include <dns/keyvalues.h>
48 #include <dns/master.h>
49 #include <dns/masterdump.h>
50 #include <dns/order.h>
51 #include <dns/peer.h>
52 #include <dns/rrl.h>
53 #include <dns/rbt.h>
54 #include <dns/rdataset.h>
55 #include <dns/request.h>
56 #include <dns/resolver.h>
57 #include <dns/result.h>
58 #include <dns/rpz.h>
59 #include <dns/stats.h>
60 #include <dns/tsig.h>
61 #include <dns/zone.h>
62 #include <dns/zt.h>
63
64 #define RESSHUTDOWN(v)  (((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0)
65 #define ADBSHUTDOWN(v)  (((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
66 #define REQSHUTDOWN(v)  (((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0)
67
68 #define DNS_VIEW_DELONLYHASH 111
69
70 static void resolver_shutdown(isc_task_t *task, isc_event_t *event);
71 static void adb_shutdown(isc_task_t *task, isc_event_t *event);
72 static void req_shutdown(isc_task_t *task, isc_event_t *event);
73
74 isc_result_t
75 dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
76                 const char *name, dns_view_t **viewp)
77 {
78         dns_view_t *view;
79         isc_result_t result;
80
81         /*
82          * Create a view.
83          */
84
85         REQUIRE(name != NULL);
86         REQUIRE(viewp != NULL && *viewp == NULL);
87
88         view = isc_mem_get(mctx, sizeof(*view));
89         if (view == NULL)
90                 return (ISC_R_NOMEMORY);
91
92         view->mctx = NULL;
93         isc_mem_attach(mctx, &view->mctx);
94         view->name = isc_mem_strdup(mctx, name);
95         if (view->name == NULL) {
96                 result = ISC_R_NOMEMORY;
97                 goto cleanup_view;
98         }
99         result = isc_mutex_init(&view->lock);
100         if (result != ISC_R_SUCCESS)
101                 goto cleanup_name;
102
103         view->zonetable = NULL;
104 #ifdef BIND9
105         result = dns_zt_create(mctx, rdclass, &view->zonetable);
106         if (result != ISC_R_SUCCESS) {
107                 UNEXPECTED_ERROR(__FILE__, __LINE__,
108                                  "dns_zt_create() failed: %s",
109                                  isc_result_totext(result));
110                 result = ISC_R_UNEXPECTED;
111                 goto cleanup_mutex;
112         }
113 #endif
114         view->secroots_priv = NULL;
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_zt;
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->rdclass = rdclass;
134         view->frozen = ISC_FALSE;
135         view->task = NULL;
136         result = isc_refcount_init(&view->references, 1);
137         if (result != ISC_R_SUCCESS)
138                 goto cleanup_fwdtable;
139         view->weakrefs = 0;
140         view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
141                             DNS_VIEWATTR_REQSHUTDOWN);
142         view->statickeys = NULL;
143         view->dynamickeys = NULL;
144         view->matchclients = NULL;
145         view->matchdestinations = NULL;
146         view->matchrecursiveonly = ISC_FALSE;
147         result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
148         if (result != ISC_R_SUCCESS)
149                 goto cleanup_references;
150         view->peers = NULL;
151         view->order = NULL;
152         view->delonly = NULL;
153         view->rootdelonly = ISC_FALSE;
154         view->rootexclude = NULL;
155         view->resstats = NULL;
156         view->resquerystats = NULL;
157         view->cacheshared = ISC_FALSE;
158         ISC_LIST_INIT(view->dns64);
159         view->dns64cnt = 0;
160
161         /*
162          * Initialize configuration data with default values.
163          */
164         view->recursion = ISC_TRUE;
165         view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */
166         view->additionalfromcache = ISC_TRUE;
167         view->additionalfromauth = ISC_TRUE;
168         view->enablednssec = ISC_TRUE;
169         view->enablevalidation = ISC_TRUE;
170         view->acceptexpired = ISC_FALSE;
171         view->minimalresponses = ISC_FALSE;
172         view->transfer_format = dns_one_answer;
173         view->cacheacl = NULL;
174         view->cacheonacl = NULL;
175         view->queryacl = NULL;
176         view->queryonacl = NULL;
177         view->recursionacl = NULL;
178         view->recursiononacl = NULL;
179         view->sortlist = NULL;
180         view->transferacl = NULL;
181         view->notifyacl = NULL;
182         view->updateacl = NULL;
183         view->upfwdacl = NULL;
184         view->denyansweracl = NULL;
185         view->nocasecompress = NULL;
186         view->answeracl_exclude = NULL;
187         view->denyanswernames = NULL;
188         view->answernames_exclude = NULL;
189         view->rrl = NULL;
190         view->provideixfr = ISC_TRUE;
191         view->maxcachettl = 7 * 24 * 3600;
192         view->maxncachettl = 3 * 3600;
193         view->dstport = 53;
194         view->preferred_glue = 0;
195         view->flush = ISC_FALSE;
196         view->dlv = NULL;
197         view->maxudp = 0;
198         view->maxbits = 0;
199         view->v4_aaaa = dns_v4_aaaa_ok;
200         view->v4_aaaa_acl = NULL;
201         ISC_LIST_INIT(view->rpz_zones);
202         view->rpz_recursive_only = ISC_TRUE;
203         view->rpz_break_dnssec = ISC_FALSE;
204         dns_fixedname_init(&view->dlv_fixed);
205         view->managed_keys = NULL;
206         view->redirect = NULL;
207 #ifdef BIND9
208         view->new_zone_file = NULL;
209         view->new_zone_config = NULL;
210         view->cfg_destroy = NULL;
211
212         result = dns_order_create(view->mctx, &view->order);
213         if (result != ISC_R_SUCCESS)
214                 goto cleanup_dynkeys;
215 #endif
216
217         result = dns_peerlist_new(view->mctx, &view->peers);
218         if (result != ISC_R_SUCCESS)
219                 goto cleanup_order;
220
221         result = dns_aclenv_init(view->mctx, &view->aclenv);
222         if (result != ISC_R_SUCCESS)
223                 goto cleanup_peerlist;
224
225         ISC_LINK_INIT(view, link);
226         ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL,
227                        DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown,
228                        view, NULL, NULL, NULL);
229         ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL,
230                        DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown,
231                        view, NULL, NULL, NULL);
232         ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL,
233                        DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown,
234                        view, NULL, NULL, NULL);
235         view->viewlist = NULL;
236         view->magic = DNS_VIEW_MAGIC;
237
238         *viewp = view;
239
240         return (ISC_R_SUCCESS);
241
242  cleanup_peerlist:
243         dns_peerlist_detach(&view->peers);
244
245  cleanup_order:
246 #ifdef BIND9
247         dns_order_detach(&view->order);
248
249  cleanup_dynkeys:
250 #endif
251         dns_tsigkeyring_detach(&view->dynamickeys);
252
253  cleanup_references:
254         isc_refcount_destroy(&view->references);
255
256  cleanup_fwdtable:
257         dns_fwdtable_destroy(&view->fwdtable);
258
259  cleanup_zt:
260 #ifdef BIND9
261         dns_zt_detach(&view->zonetable);
262
263  cleanup_mutex:
264 #endif
265         DESTROYLOCK(&view->lock);
266
267  cleanup_name:
268         isc_mem_free(mctx, view->name);
269
270  cleanup_view:
271         isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
272
273         return (result);
274 }
275
276 static inline void
277 destroy(dns_view_t *view) {
278 #ifdef BIND9
279         dns_dns64_t *dns64;
280 #endif
281
282         REQUIRE(!ISC_LINK_LINKED(view, link));
283         REQUIRE(isc_refcount_current(&view->references) == 0);
284         REQUIRE(view->weakrefs == 0);
285         REQUIRE(RESSHUTDOWN(view));
286         REQUIRE(ADBSHUTDOWN(view));
287         REQUIRE(REQSHUTDOWN(view));
288
289 #ifdef BIND9
290         if (view->order != NULL)
291                 dns_order_detach(&view->order);
292 #endif
293         if (view->peers != NULL)
294                 dns_peerlist_detach(&view->peers);
295
296         if (view->dynamickeys != NULL) {
297                 isc_result_t result;
298                 char template[20];
299                 char keyfile[20];
300                 FILE *fp = NULL;
301                 int n;
302
303                 n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys",
304                              view->name);
305                 if (n > 0 && (size_t)n < sizeof(keyfile)) {
306                         result = isc_file_mktemplate(keyfile, template,
307                                                      sizeof(template));
308                         if (result == ISC_R_SUCCESS)
309                                 (void)isc_file_openuniqueprivate(template, &fp);
310                 }
311                 if (fp == NULL)
312                         dns_tsigkeyring_detach(&view->dynamickeys);
313                 else {
314                         result = dns_tsigkeyring_dumpanddetach(
315                                                         &view->dynamickeys, fp);
316                         if (result == ISC_R_SUCCESS) {
317                                 if (fclose(fp) == 0)
318                                         result = isc_file_rename(template,
319                                                                  keyfile);
320                                 if (result != ISC_R_SUCCESS)
321                                         (void)remove(template);
322                         } else {
323                                 (void)fclose(fp);
324                                 (void)remove(template);
325                         }
326                 }
327         }
328         if (view->statickeys != NULL)
329                 dns_tsigkeyring_detach(&view->statickeys);
330         if (view->adb != NULL)
331                 dns_adb_detach(&view->adb);
332         if (view->resolver != NULL)
333                 dns_resolver_detach(&view->resolver);
334 #ifdef BIND9
335         if (view->acache != NULL) {
336                 if (view->cachedb != NULL)
337                         dns_acache_putdb(view->acache, view->cachedb);
338                 dns_acache_detach(&view->acache);
339         }
340         dns_rpz_view_destroy(view);
341 #ifdef USE_RRL
342         dns_rrl_view_destroy(view);
343 #else /* USE_RRL */
344         INSIST(view->rrl == NULL);
345 #endif /* USE_RRL */
346 #else /* BIND9 */
347         INSIST(view->acache == NULL);
348         INSIST(ISC_LIST_EMPTY(view->rpz_zones));
349         INSIST(view->rrl == NULL);
350 #endif /* BIND9 */
351         if (view->requestmgr != NULL)
352                 dns_requestmgr_detach(&view->requestmgr);
353         if (view->task != NULL)
354                 isc_task_detach(&view->task);
355         if (view->hints != NULL)
356                 dns_db_detach(&view->hints);
357         if (view->dlzdatabase != NULL)
358                 dns_dlzdestroy(&view->dlzdatabase);
359         if (view->cachedb != NULL)
360                 dns_db_detach(&view->cachedb);
361         if (view->cache != NULL)
362                 dns_cache_detach(&view->cache);
363         if (view->nocasecompress != NULL)
364                 dns_acl_detach(&view->nocasecompress);
365         if (view->matchclients != NULL)
366                 dns_acl_detach(&view->matchclients);
367         if (view->matchdestinations != NULL)
368                 dns_acl_detach(&view->matchdestinations);
369         if (view->cacheacl != NULL)
370                 dns_acl_detach(&view->cacheacl);
371         if (view->cacheonacl != NULL)
372                 dns_acl_detach(&view->cacheonacl);
373         if (view->queryacl != NULL)
374                 dns_acl_detach(&view->queryacl);
375         if (view->queryonacl != NULL)
376                 dns_acl_detach(&view->queryonacl);
377         if (view->recursionacl != NULL)
378                 dns_acl_detach(&view->recursionacl);
379         if (view->recursiononacl != NULL)
380                 dns_acl_detach(&view->recursiononacl);
381         if (view->sortlist != NULL)
382                 dns_acl_detach(&view->sortlist);
383         if (view->transferacl != NULL)
384                 dns_acl_detach(&view->transferacl);
385         if (view->notifyacl != NULL)
386                 dns_acl_detach(&view->notifyacl);
387         if (view->updateacl != NULL)
388                 dns_acl_detach(&view->updateacl);
389         if (view->upfwdacl != NULL)
390                 dns_acl_detach(&view->upfwdacl);
391         if (view->denyansweracl != NULL)
392                 dns_acl_detach(&view->denyansweracl);
393         if (view->v4_aaaa_acl != NULL)
394                 dns_acl_detach(&view->v4_aaaa_acl);
395         if (view->answeracl_exclude != NULL)
396                 dns_rbt_destroy(&view->answeracl_exclude);
397         if (view->denyanswernames != NULL)
398                 dns_rbt_destroy(&view->denyanswernames);
399         if (view->answernames_exclude != NULL)
400                 dns_rbt_destroy(&view->answernames_exclude);
401         if (view->delonly != NULL) {
402                 dns_name_t *name;
403                 int i;
404
405                 for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
406                         name = ISC_LIST_HEAD(view->delonly[i]);
407                         while (name != NULL) {
408                                 ISC_LIST_UNLINK(view->delonly[i], name, link);
409                                 dns_name_free(name, view->mctx);
410                                 isc_mem_put(view->mctx, name, sizeof(*name));
411                                 name = ISC_LIST_HEAD(view->delonly[i]);
412                         }
413                 }
414                 isc_mem_put(view->mctx, view->delonly, sizeof(dns_namelist_t) *
415                             DNS_VIEW_DELONLYHASH);
416                 view->delonly = NULL;
417         }
418         if (view->rootexclude != NULL) {
419                 dns_name_t *name;
420                 int i;
421
422                 for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
423                         name = ISC_LIST_HEAD(view->rootexclude[i]);
424                         while (name != NULL) {
425                                 ISC_LIST_UNLINK(view->rootexclude[i],
426                                                 name, link);
427                                 dns_name_free(name, view->mctx);
428                                 isc_mem_put(view->mctx, name, sizeof(*name));
429                                 name = ISC_LIST_HEAD(view->rootexclude[i]);
430                         }
431                 }
432                 isc_mem_put(view->mctx, view->rootexclude,
433                             sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH);
434                 view->rootexclude = NULL;
435         }
436         if (view->resstats != NULL)
437                 isc_stats_detach(&view->resstats);
438         if (view->resquerystats != NULL)
439                 dns_stats_detach(&view->resquerystats);
440         if (view->secroots_priv != NULL)
441                 dns_keytable_detach(&view->secroots_priv);
442 #ifdef BIND9
443         for (dns64 = ISC_LIST_HEAD(view->dns64);
444              dns64 != NULL;
445              dns64 = ISC_LIST_HEAD(view->dns64)) {
446                 dns_dns64_unlink(&view->dns64, dns64);
447                 dns_dns64_destroy(&dns64);
448         }
449         if (view->managed_keys != NULL)
450                 dns_zone_detach(&view->managed_keys);
451         if (view->redirect != NULL)
452                 dns_zone_detach(&view->redirect);
453         dns_view_setnewzones(view, ISC_FALSE, NULL, NULL);
454 #endif
455         dns_fwdtable_destroy(&view->fwdtable);
456         dns_aclenv_destroy(&view->aclenv);
457         DESTROYLOCK(&view->lock);
458         isc_refcount_destroy(&view->references);
459         isc_mem_free(view->mctx, view->name);
460         isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
461 }
462
463 /*
464  * Return true iff 'view' may be freed.
465  * The caller must be holding the view lock.
466  */
467 static isc_boolean_t
468 all_done(dns_view_t *view) {
469
470         if (isc_refcount_current(&view->references) == 0 &&
471             view->weakrefs == 0 &&
472             RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view))
473                 return (ISC_TRUE);
474
475         return (ISC_FALSE);
476 }
477
478 void
479 dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
480
481         REQUIRE(DNS_VIEW_VALID(source));
482         REQUIRE(targetp != NULL && *targetp == NULL);
483
484         isc_refcount_increment(&source->references, NULL);
485
486         *targetp = source;
487 }
488
489 static void
490 view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) {
491         dns_view_t *view;
492         unsigned int refs;
493         isc_boolean_t done = ISC_FALSE;
494
495         REQUIRE(viewp != NULL);
496         view = *viewp;
497         REQUIRE(DNS_VIEW_VALID(view));
498
499         if (flush)
500                 view->flush = ISC_TRUE;
501         isc_refcount_decrement(&view->references, &refs);
502         if (refs == 0) {
503 #ifdef BIND9
504                 dns_zone_t *mkzone = NULL, *rdzone = NULL;
505 #endif
506
507                 LOCK(&view->lock);
508                 if (!RESSHUTDOWN(view))
509                         dns_resolver_shutdown(view->resolver);
510                 if (!ADBSHUTDOWN(view))
511                         dns_adb_shutdown(view->adb);
512                 if (!REQSHUTDOWN(view))
513                         dns_requestmgr_shutdown(view->requestmgr);
514 #ifdef BIND9
515                 if (view->acache != NULL)
516                         dns_acache_shutdown(view->acache);
517                 if (view->flush)
518                         dns_zt_flushanddetach(&view->zonetable);
519                 else
520                         dns_zt_detach(&view->zonetable);
521                 if (view->managed_keys != NULL) {
522                         mkzone = view->managed_keys;
523                         view->managed_keys = NULL;
524                         if (view->flush)
525                                 dns_zone_flush(mkzone);
526                 }
527                 if (view->redirect != NULL) {
528                         rdzone = view->redirect;
529                         view->redirect = NULL;
530                         if (view->flush)
531                                 dns_zone_flush(rdzone);
532                 }
533 #endif
534                 done = all_done(view);
535                 UNLOCK(&view->lock);
536
537 #ifdef BIND9
538                 /* Need to detach zones outside view lock */
539                 if (mkzone != NULL)
540                         dns_zone_detach(&mkzone);
541
542                 if (rdzone != NULL)
543                         dns_zone_detach(&rdzone);
544 #endif
545         }
546
547         *viewp = NULL;
548
549         if (done)
550                 destroy(view);
551 }
552
553 void
554 dns_view_flushanddetach(dns_view_t **viewp) {
555         view_flushanddetach(viewp, ISC_TRUE);
556 }
557
558 void
559 dns_view_detach(dns_view_t **viewp) {
560         view_flushanddetach(viewp, ISC_FALSE);
561 }
562
563 #ifdef BIND9
564 static isc_result_t
565 dialup(dns_zone_t *zone, void *dummy) {
566         UNUSED(dummy);
567         dns_zone_dialup(zone);
568         return (ISC_R_SUCCESS);
569 }
570
571 void
572 dns_view_dialup(dns_view_t *view) {
573         REQUIRE(DNS_VIEW_VALID(view));
574         REQUIRE(view->zonetable != NULL);
575
576         (void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL);
577 }
578 #endif
579
580 void
581 dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) {
582
583         REQUIRE(DNS_VIEW_VALID(source));
584         REQUIRE(targetp != NULL && *targetp == NULL);
585
586         LOCK(&source->lock);
587         source->weakrefs++;
588         UNLOCK(&source->lock);
589
590         *targetp = source;
591 }
592
593 void
594 dns_view_weakdetach(dns_view_t **viewp) {
595         dns_view_t *view;
596         isc_boolean_t done = ISC_FALSE;
597
598         REQUIRE(viewp != NULL);
599         view = *viewp;
600         REQUIRE(DNS_VIEW_VALID(view));
601
602         LOCK(&view->lock);
603
604         INSIST(view->weakrefs > 0);
605         view->weakrefs--;
606         done = all_done(view);
607
608         UNLOCK(&view->lock);
609
610         *viewp = NULL;
611
612         if (done)
613                 destroy(view);
614 }
615
616 static void
617 resolver_shutdown(isc_task_t *task, isc_event_t *event) {
618         dns_view_t *view = event->ev_arg;
619         isc_boolean_t done;
620
621         REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN);
622         REQUIRE(DNS_VIEW_VALID(view));
623         REQUIRE(view->task == task);
624
625         UNUSED(task);
626
627         isc_event_free(&event);
628
629         LOCK(&view->lock);
630
631         view->attributes |= DNS_VIEWATTR_RESSHUTDOWN;
632         done = all_done(view);
633
634         UNLOCK(&view->lock);
635
636         if (done)
637                 destroy(view);
638 }
639
640 static void
641 adb_shutdown(isc_task_t *task, isc_event_t *event) {
642         dns_view_t *view = event->ev_arg;
643         isc_boolean_t done;
644
645         REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN);
646         REQUIRE(DNS_VIEW_VALID(view));
647         REQUIRE(view->task == task);
648
649         UNUSED(task);
650
651         isc_event_free(&event);
652
653         LOCK(&view->lock);
654
655         view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN;
656         done = all_done(view);
657
658         UNLOCK(&view->lock);
659
660         if (done)
661                 destroy(view);
662 }
663
664 static void
665 req_shutdown(isc_task_t *task, isc_event_t *event) {
666         dns_view_t *view = event->ev_arg;
667         isc_boolean_t done;
668
669         REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN);
670         REQUIRE(DNS_VIEW_VALID(view));
671         REQUIRE(view->task == task);
672
673         UNUSED(task);
674
675         isc_event_free(&event);
676
677         LOCK(&view->lock);
678
679         view->attributes |= DNS_VIEWATTR_REQSHUTDOWN;
680         done = all_done(view);
681
682         UNLOCK(&view->lock);
683
684         if (done)
685                 destroy(view);
686 }
687
688 isc_result_t
689 dns_view_createresolver(dns_view_t *view,
690                         isc_taskmgr_t *taskmgr,
691                         unsigned int ntasks, unsigned int ndisp,
692                         isc_socketmgr_t *socketmgr,
693                         isc_timermgr_t *timermgr,
694                         unsigned int options,
695                         dns_dispatchmgr_t *dispatchmgr,
696                         dns_dispatch_t *dispatchv4,
697                         dns_dispatch_t *dispatchv6)
698 {
699         isc_result_t result;
700         isc_event_t *event;
701         isc_mem_t *mctx = NULL;
702
703         REQUIRE(DNS_VIEW_VALID(view));
704         REQUIRE(!view->frozen);
705         REQUIRE(view->resolver == NULL);
706
707         result = isc_task_create(taskmgr, 0, &view->task);
708         if (result != ISC_R_SUCCESS)
709                 return (result);
710         isc_task_setname(view->task, "view", view);
711
712         result = dns_resolver_create(view, taskmgr, ntasks, ndisp, socketmgr,
713                                      timermgr, options, dispatchmgr,
714                                      dispatchv4, dispatchv6,
715                                      &view->resolver);
716         if (result != ISC_R_SUCCESS) {
717                 isc_task_detach(&view->task);
718                 return (result);
719         }
720         event = &view->resevent;
721         dns_resolver_whenshutdown(view->resolver, view->task, &event);
722         view->attributes &= ~DNS_VIEWATTR_RESSHUTDOWN;
723
724         result = isc_mem_create(0, 0, &mctx);
725         if (result != ISC_R_SUCCESS) {
726                 dns_resolver_shutdown(view->resolver);
727                 return (result);
728         }
729
730         result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb);
731         isc_mem_setname(mctx, "ADB", NULL);
732         isc_mem_detach(&mctx);
733         if (result != ISC_R_SUCCESS) {
734                 dns_resolver_shutdown(view->resolver);
735                 return (result);
736         }
737         event = &view->adbevent;
738         dns_adb_whenshutdown(view->adb, view->task, &event);
739         view->attributes &= ~DNS_VIEWATTR_ADBSHUTDOWN;
740
741         result = dns_requestmgr_create(view->mctx, timermgr, socketmgr,
742                                       dns_resolver_taskmgr(view->resolver),
743                                       dns_resolver_dispatchmgr(view->resolver),
744                                       dispatchv4, dispatchv6,
745                                       &view->requestmgr);
746         if (result != ISC_R_SUCCESS) {
747                 dns_adb_shutdown(view->adb);
748                 dns_resolver_shutdown(view->resolver);
749                 return (result);
750         }
751         event = &view->reqevent;
752         dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event);
753         view->attributes &= ~DNS_VIEWATTR_REQSHUTDOWN;
754
755         return (ISC_R_SUCCESS);
756 }
757
758 void
759 dns_view_setcache(dns_view_t *view, dns_cache_t *cache) {
760         dns_view_setcache2(view, cache, ISC_FALSE);
761 }
762
763 void
764 dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared) {
765         REQUIRE(DNS_VIEW_VALID(view));
766         REQUIRE(!view->frozen);
767
768         view->cacheshared = shared;
769         if (view->cache != NULL) {
770 #ifdef BIND9
771                 if (view->acache != NULL)
772                         dns_acache_putdb(view->acache, view->cachedb);
773 #endif
774                 dns_db_detach(&view->cachedb);
775                 dns_cache_detach(&view->cache);
776         }
777         dns_cache_attach(cache, &view->cache);
778         dns_cache_attachdb(cache, &view->cachedb);
779         INSIST(DNS_DB_VALID(view->cachedb));
780
781 #ifdef BIND9
782         if (view->acache != NULL)
783                 dns_acache_setdb(view->acache, view->cachedb);
784 #endif
785 }
786
787 isc_boolean_t
788 dns_view_iscacheshared(dns_view_t *view) {
789         REQUIRE(DNS_VIEW_VALID(view));
790
791         return (view->cacheshared);
792 }
793
794 void
795 dns_view_sethints(dns_view_t *view, dns_db_t *hints) {
796         REQUIRE(DNS_VIEW_VALID(view));
797         REQUIRE(!view->frozen);
798         REQUIRE(view->hints == NULL);
799         REQUIRE(dns_db_iszone(hints));
800
801         dns_db_attach(hints, &view->hints);
802 }
803
804 void
805 dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
806         REQUIRE(DNS_VIEW_VALID(view));
807         REQUIRE(ring != NULL);
808         if (view->statickeys != NULL)
809                 dns_tsigkeyring_detach(&view->statickeys);
810         dns_tsigkeyring_attach(ring, &view->statickeys);
811 }
812
813 void
814 dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
815         REQUIRE(DNS_VIEW_VALID(view));
816         REQUIRE(ring != NULL);
817         if (view->dynamickeys != NULL)
818                 dns_tsigkeyring_detach(&view->dynamickeys);
819         dns_tsigkeyring_attach(ring, &view->dynamickeys);
820 }
821
822 void
823 dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp) {
824         REQUIRE(DNS_VIEW_VALID(view));
825         REQUIRE(ringp != NULL && *ringp == NULL);
826         if (view->dynamickeys != NULL)
827                 dns_tsigkeyring_attach(view->dynamickeys, ringp);
828 }
829
830 void
831 dns_view_restorekeyring(dns_view_t *view) {
832         FILE *fp;
833         char keyfile[20];
834         int n;
835
836         REQUIRE(DNS_VIEW_VALID(view));
837
838         if (view->dynamickeys != NULL) {
839                 n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys",
840                              view->name);
841                 if (n > 0 && (size_t)n < sizeof(keyfile)) {
842                         fp = fopen(keyfile, "r");
843                         if (fp != NULL) {
844                                 dns_keyring_restore(view->dynamickeys, fp);
845                                 (void)fclose(fp);
846                         }
847                 }
848         }
849 }
850
851 void
852 dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
853         REQUIRE(DNS_VIEW_VALID(view));
854         view->dstport = dstport;
855 }
856
857 void
858 dns_view_freeze(dns_view_t *view) {
859         REQUIRE(DNS_VIEW_VALID(view));
860         REQUIRE(!view->frozen);
861
862         if (view->resolver != NULL) {
863                 INSIST(view->cachedb != NULL);
864                 dns_resolver_freeze(view->resolver);
865         }
866         view->frozen = ISC_TRUE;
867 }
868
869 #ifdef BIND9
870 void
871 dns_view_thaw(dns_view_t *view) {
872         REQUIRE(DNS_VIEW_VALID(view));
873         REQUIRE(view->frozen);
874
875         view->frozen = ISC_FALSE;
876 }
877
878 isc_result_t
879 dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
880         isc_result_t result;
881
882         REQUIRE(DNS_VIEW_VALID(view));
883         REQUIRE(!view->frozen);
884         REQUIRE(view->zonetable != NULL);
885
886         result = dns_zt_mount(view->zonetable, zone);
887
888         return (result);
889 }
890 #endif
891
892 #ifdef BIND9
893 isc_result_t
894 dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) {
895         isc_result_t result;
896
897         REQUIRE(DNS_VIEW_VALID(view));
898
899         LOCK(&view->lock);
900         if (view->zonetable != NULL) {
901                 result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
902                 if (result == DNS_R_PARTIALMATCH) {
903                         dns_zone_detach(zonep);
904                         result = ISC_R_NOTFOUND;
905                 }
906         } else
907                 result = ISC_R_NOTFOUND;
908         UNLOCK(&view->lock);
909
910         return (result);
911 }
912 #endif
913
914 isc_result_t
915 dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
916               isc_stdtime_t now, unsigned int options, isc_boolean_t use_hints,
917               dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
918               dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
919         return (dns_view_find2(view, name, type, now, options, use_hints,
920                                ISC_FALSE, dbp, nodep, foundname, rdataset,
921                                sigrdataset));
922 }
923
924 isc_result_t
925 dns_view_find2(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
926                isc_stdtime_t now, unsigned int options,
927                isc_boolean_t use_hints, isc_boolean_t use_static_stub,
928                dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
929                dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
930 {
931         isc_result_t result;
932         dns_db_t *db, *zdb;
933         dns_dbnode_t *node, *znode;
934         isc_boolean_t is_cache, is_staticstub_zone;
935         dns_rdataset_t zrdataset, zsigrdataset;
936         dns_zone_t *zone;
937
938 #ifndef BIND9
939         UNUSED(use_hints);
940         UNUSED(use_static_stub);
941         UNUSED(zone);
942 #endif
943
944         /*
945          * Find an rdataset whose owner name is 'name', and whose type is
946          * 'type'.
947          */
948
949         REQUIRE(DNS_VIEW_VALID(view));
950         REQUIRE(view->frozen);
951         REQUIRE(type != dns_rdatatype_rrsig);
952         REQUIRE(rdataset != NULL);  /* XXXBEW - remove this */
953         REQUIRE(nodep == NULL || *nodep == NULL);
954
955         /*
956          * Initialize.
957          */
958         dns_rdataset_init(&zrdataset);
959         dns_rdataset_init(&zsigrdataset);
960         zdb = NULL;
961         znode = NULL;
962
963         /*
964          * Find a database to answer the query.
965          */
966         db = NULL;
967         node = NULL;
968         is_staticstub_zone = ISC_FALSE;
969 #ifdef BIND9
970         zone = NULL;
971         LOCK(&view->lock);
972         if (view->zonetable != NULL)
973                 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
974         else
975                 result = ISC_R_NOTFOUND;
976         UNLOCK(&view->lock);
977         if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub &&
978             !use_static_stub) {
979                 result = ISC_R_NOTFOUND;
980         }
981         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
982                 result = dns_zone_getdb(zone, &db);
983                 if (result != ISC_R_SUCCESS && view->cachedb != NULL)
984                         dns_db_attach(view->cachedb, &db);
985                 else if (result != ISC_R_SUCCESS)
986                         goto cleanup;
987                 if (dns_zone_gettype(zone) == dns_zone_staticstub &&
988                     dns_name_equal(name, dns_zone_getorigin(zone))) {
989                         is_staticstub_zone = ISC_TRUE;
990                 }
991         } else if (result == ISC_R_NOTFOUND && view->cachedb != NULL)
992                 dns_db_attach(view->cachedb, &db);
993 #else
994         result = ISC_R_NOTFOUND;
995         if (view->cachedb != NULL)
996                 dns_db_attach(view->cachedb, &db);
997 #endif /* BIND9 */
998         else
999                 goto cleanup;
1000
1001         is_cache = dns_db_iscache(db);
1002
1003  db_find:
1004         /*
1005          * Now look for an answer in the database.
1006          */
1007         result = dns_db_find(db, name, NULL, type, options,
1008                              now, &node, foundname, rdataset, sigrdataset);
1009
1010         if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) {
1011                 if (dns_rdataset_isassociated(rdataset))
1012                         dns_rdataset_disassociate(rdataset);
1013                 if (sigrdataset != NULL &&
1014                     dns_rdataset_isassociated(sigrdataset))
1015                         dns_rdataset_disassociate(sigrdataset);
1016                 if (node != NULL)
1017                         dns_db_detachnode(db, &node);
1018                 if (!is_cache) {
1019                         dns_db_detach(&db);
1020                         if (view->cachedb != NULL && !is_staticstub_zone) {
1021                                 /*
1022                                  * Either the answer is in the cache, or we
1023                                  * don't know it.
1024                                  * Note that if the result comes from a
1025                                  * static-stub zone we stop the search here
1026                                  * (see the function description in view.h).
1027                                  */
1028                                 is_cache = ISC_TRUE;
1029                                 dns_db_attach(view->cachedb, &db);
1030                                 goto db_find;
1031                         }
1032                 } else {
1033                         /*
1034                          * We don't have the data in the cache.  If we've got
1035                          * glue from the zone, use it.
1036                          */
1037                         if (dns_rdataset_isassociated(&zrdataset)) {
1038                                 dns_rdataset_clone(&zrdataset, rdataset);
1039                                 if (sigrdataset != NULL &&
1040                                     dns_rdataset_isassociated(&zsigrdataset))
1041                                         dns_rdataset_clone(&zsigrdataset,
1042                                                            sigrdataset);
1043                                 result = DNS_R_GLUE;
1044                                 if (db != NULL)
1045                                         dns_db_detach(&db);
1046                                 dns_db_attach(zdb, &db);
1047                                 dns_db_attachnode(db, znode, &node);
1048                                 goto cleanup;
1049                         }
1050                 }
1051                 /*
1052                  * We don't know the answer.
1053                  */
1054                 result = ISC_R_NOTFOUND;
1055         } else if (result == DNS_R_GLUE) {
1056                 if (view->cachedb != NULL && !is_staticstub_zone) {
1057                         /*
1058                          * We found an answer, but the cache may be better.
1059                          * Remember what we've got and go look in the cache.
1060                          */
1061                         is_cache = ISC_TRUE;
1062                         dns_rdataset_clone(rdataset, &zrdataset);
1063                         dns_rdataset_disassociate(rdataset);
1064                         if (sigrdataset != NULL &&
1065                             dns_rdataset_isassociated(sigrdataset)) {
1066                                 dns_rdataset_clone(sigrdataset, &zsigrdataset);
1067                                 dns_rdataset_disassociate(sigrdataset);
1068                         }
1069                         dns_db_attach(db, &zdb);
1070                         dns_db_attachnode(zdb, node, &znode);
1071                         dns_db_detachnode(db, &node);
1072                         dns_db_detach(&db);
1073                         dns_db_attach(view->cachedb, &db);
1074                         goto db_find;
1075                 }
1076                 /*
1077                  * Otherwise, the glue is the best answer.
1078                  */
1079                 result = ISC_R_SUCCESS;
1080         }
1081
1082 #ifdef BIND9
1083         if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
1084                 if (dns_rdataset_isassociated(rdataset))
1085                         dns_rdataset_disassociate(rdataset);
1086                 if (sigrdataset != NULL &&
1087                     dns_rdataset_isassociated(sigrdataset))
1088                         dns_rdataset_disassociate(sigrdataset);
1089                 if (db != NULL) {
1090                         if (node != NULL)
1091                                 dns_db_detachnode(db, &node);
1092                         dns_db_detach(&db);
1093                 }
1094                 result = dns_db_find(view->hints, name, NULL, type, options,
1095                                      now, &node, foundname,
1096                                      rdataset, sigrdataset);
1097                 if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) {
1098                         /*
1099                          * We just used a hint.  Let the resolver know it
1100                          * should consider priming.
1101                          */
1102                         dns_resolver_prime(view->resolver);
1103                         dns_db_attach(view->hints, &db);
1104                         result = DNS_R_HINT;
1105                 } else if (result == DNS_R_NXRRSET) {
1106                         dns_db_attach(view->hints, &db);
1107                         result = DNS_R_HINTNXRRSET;
1108                 } else if (result == DNS_R_NXDOMAIN)
1109                         result = ISC_R_NOTFOUND;
1110
1111                 /*
1112                  * Cleanup if non-standard hints are used.
1113                  */
1114                 if (db == NULL && node != NULL)
1115                         dns_db_detachnode(view->hints, &node);
1116         }
1117 #endif /* BIND9 */
1118
1119  cleanup:
1120         if (dns_rdataset_isassociated(&zrdataset)) {
1121                 dns_rdataset_disassociate(&zrdataset);
1122                 if (dns_rdataset_isassociated(&zsigrdataset))
1123                         dns_rdataset_disassociate(&zsigrdataset);
1124         }
1125
1126         if (zdb != NULL) {
1127                 if (znode != NULL)
1128                         dns_db_detachnode(zdb, &znode);
1129                 dns_db_detach(&zdb);
1130         }
1131
1132         if (db != NULL) {
1133                 if (node != NULL) {
1134                         if (nodep != NULL)
1135                                 *nodep = node;
1136                         else
1137                                 dns_db_detachnode(db, &node);
1138                 }
1139                 if (dbp != NULL)
1140                         *dbp = db;
1141                 else
1142                         dns_db_detach(&db);
1143         } else
1144                 INSIST(node == NULL);
1145
1146 #ifdef BIND9
1147         if (zone != NULL)
1148                 dns_zone_detach(&zone);
1149 #endif
1150
1151         return (result);
1152 }
1153
1154 isc_result_t
1155 dns_view_simplefind(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
1156                     isc_stdtime_t now, unsigned int options,
1157                     isc_boolean_t use_hints,
1158                     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
1159 {
1160         isc_result_t result;
1161         dns_fixedname_t foundname;
1162
1163         dns_fixedname_init(&foundname);
1164         result = dns_view_find(view, name, type, now, options, use_hints,
1165                                NULL, NULL, dns_fixedname_name(&foundname),
1166                                rdataset, sigrdataset);
1167         if (result == DNS_R_NXDOMAIN) {
1168                 /*
1169                  * The rdataset and sigrdataset of the relevant NSEC record
1170                  * may be returned, but the caller cannot use them because
1171                  * foundname is not returned by this simplified API.  We
1172                  * disassociate them here to prevent any misuse by the caller.
1173                  */
1174                 if (dns_rdataset_isassociated(rdataset))
1175                         dns_rdataset_disassociate(rdataset);
1176                 if (sigrdataset != NULL &&
1177                     dns_rdataset_isassociated(sigrdataset))
1178                         dns_rdataset_disassociate(sigrdataset);
1179         } else if (result != ISC_R_SUCCESS &&
1180                    result != DNS_R_GLUE &&
1181                    result != DNS_R_HINT &&
1182                    result != DNS_R_NCACHENXDOMAIN &&
1183                    result != DNS_R_NCACHENXRRSET &&
1184                    result != DNS_R_NXRRSET &&
1185                    result != DNS_R_HINTNXRRSET &&
1186                    result != ISC_R_NOTFOUND) {
1187                 if (dns_rdataset_isassociated(rdataset))
1188                         dns_rdataset_disassociate(rdataset);
1189                 if (sigrdataset != NULL &&
1190                     dns_rdataset_isassociated(sigrdataset))
1191                         dns_rdataset_disassociate(sigrdataset);
1192                 result = ISC_R_NOTFOUND;
1193         }
1194
1195         return (result);
1196 }
1197
1198 isc_result_t
1199 dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
1200                      isc_stdtime_t now, unsigned int options,
1201                      isc_boolean_t use_hints,
1202                      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
1203 {
1204         return(dns_view_findzonecut2(view, name, fname, now, options,
1205                                      use_hints, ISC_TRUE,
1206                                      rdataset, sigrdataset));
1207 }
1208
1209 isc_result_t
1210 dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
1211                       isc_stdtime_t now, unsigned int options,
1212                       isc_boolean_t use_hints,  isc_boolean_t use_cache,
1213                       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
1214 {
1215         isc_result_t result;
1216         dns_db_t *db;
1217         isc_boolean_t is_cache, use_zone, try_hints;
1218         dns_zone_t *zone;
1219         dns_name_t *zfname;
1220         dns_rdataset_t zrdataset, zsigrdataset;
1221         dns_fixedname_t zfixedname;
1222 #ifdef BIND9
1223         unsigned int ztoptions = 0;
1224 #endif
1225
1226 #ifndef BIND9
1227         UNUSED(zone);
1228 #endif
1229
1230         REQUIRE(DNS_VIEW_VALID(view));
1231         REQUIRE(view->frozen);
1232
1233         db = NULL;
1234         use_zone = ISC_FALSE;
1235         try_hints = ISC_FALSE;
1236         zfname = NULL;
1237
1238         /*
1239          * Initialize.
1240          */
1241         dns_fixedname_init(&zfixedname);
1242         dns_rdataset_init(&zrdataset);
1243         dns_rdataset_init(&zsigrdataset);
1244
1245         /*
1246          * Find the right database.
1247          */
1248 #ifdef BIND9
1249         zone = NULL;
1250         LOCK(&view->lock);
1251         if (view->zonetable != NULL) {
1252                 if ((options & DNS_DBFIND_NOEXACT) != 0)
1253                         ztoptions |= DNS_ZTFIND_NOEXACT;
1254                 result = dns_zt_find(view->zonetable, name, ztoptions,
1255                                      NULL, &zone);
1256         } else
1257                 result = ISC_R_NOTFOUND;
1258         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
1259                 result = dns_zone_getdb(zone, &db);
1260         UNLOCK(&view->lock);
1261 #else
1262         result = ISC_R_NOTFOUND;
1263 #endif
1264         if (result == ISC_R_NOTFOUND) {
1265                 /*
1266                  * We're not directly authoritative for this query name, nor
1267                  * is it a subdomain of any zone for which we're
1268                  * authoritative.
1269                  */
1270                 if (use_cache && view->cachedb != NULL) {
1271                         /*
1272                          * We have a cache; try it.
1273                          */
1274                         dns_db_attach(view->cachedb, &db);
1275                 } else {
1276                         /*
1277                          * Maybe we have hints...
1278                          */
1279                         try_hints = ISC_TRUE;
1280                         goto finish;
1281                 }
1282         } else if (result != ISC_R_SUCCESS) {
1283                 /*
1284                  * Something is broken.
1285                  */
1286                 goto cleanup;
1287         }
1288         is_cache = dns_db_iscache(db);
1289
1290  db_find:
1291         /*
1292          * Look for the zonecut.
1293          */
1294         if (!is_cache) {
1295                 result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options,
1296                                      now, NULL, fname, rdataset, sigrdataset);
1297                 if (result == DNS_R_DELEGATION)
1298                         result = ISC_R_SUCCESS;
1299                 else if (result != ISC_R_SUCCESS)
1300                         goto cleanup;
1301                 if (use_cache && view->cachedb != NULL && db != view->hints) {
1302                         /*
1303                          * We found an answer, but the cache may be better.
1304                          */
1305                         zfname = dns_fixedname_name(&zfixedname);
1306                         result = dns_name_copy(fname, zfname, NULL);
1307                         if (result != ISC_R_SUCCESS)
1308                                 goto cleanup;
1309                         dns_rdataset_clone(rdataset, &zrdataset);
1310                         dns_rdataset_disassociate(rdataset);
1311                         if (sigrdataset != NULL &&
1312                             dns_rdataset_isassociated(sigrdataset)) {
1313                                 dns_rdataset_clone(sigrdataset, &zsigrdataset);
1314                                 dns_rdataset_disassociate(sigrdataset);
1315                         }
1316                         dns_db_detach(&db);
1317                         dns_db_attach(view->cachedb, &db);
1318                         is_cache = ISC_TRUE;
1319                         goto db_find;
1320                 }
1321         } else {
1322                 result = dns_db_findzonecut(db, name, options, now, NULL,
1323                                             fname, rdataset, sigrdataset);
1324                 if (result == ISC_R_SUCCESS) {
1325                         if (zfname != NULL &&
1326                             (!dns_name_issubdomain(fname, zfname) ||
1327                              (dns_zone_staticstub &&
1328                               dns_name_equal(fname, zfname)))) {
1329                                 /*
1330                                  * We found a zonecut in the cache, but our
1331                                  * zone delegation is better.
1332                                  */
1333                                 use_zone = ISC_TRUE;
1334                         }
1335                 } else if (result == ISC_R_NOTFOUND) {
1336                         if (zfname != NULL) {
1337                                 /*
1338                                  * We didn't find anything in the cache, but we
1339                                  * have a zone delegation, so use it.
1340                                  */
1341                                 use_zone = ISC_TRUE;
1342                         } else {
1343                                 /*
1344                                  * Maybe we have hints...
1345                                  */
1346                                 try_hints = ISC_TRUE;
1347                         }
1348                 } else {
1349                         /*
1350                          * Something bad happened.
1351                          */
1352                         goto cleanup;
1353                 }
1354         }
1355
1356  finish:
1357         if (use_zone) {
1358                 if (dns_rdataset_isassociated(rdataset)) {
1359                         dns_rdataset_disassociate(rdataset);
1360                         if (sigrdataset != NULL &&
1361                             dns_rdataset_isassociated(sigrdataset))
1362                                 dns_rdataset_disassociate(sigrdataset);
1363                 }
1364                 result = dns_name_copy(zfname, fname, NULL);
1365                 if (result != ISC_R_SUCCESS)
1366                         goto cleanup;
1367                 dns_rdataset_clone(&zrdataset, rdataset);
1368                 if (sigrdataset != NULL &&
1369                     dns_rdataset_isassociated(&zrdataset))
1370                         dns_rdataset_clone(&zsigrdataset, sigrdataset);
1371         } else if (try_hints && use_hints && view->hints != NULL) {
1372                 /*
1373                  * We've found nothing so far, but we have hints.
1374                  */
1375                 result = dns_db_find(view->hints, dns_rootname, NULL,
1376                                      dns_rdatatype_ns, 0, now, NULL, fname,
1377                                      rdataset, NULL);
1378                 if (result != ISC_R_SUCCESS) {
1379                         /*
1380                          * We can't even find the hints for the root
1381                          * nameservers!
1382                          */
1383                         if (dns_rdataset_isassociated(rdataset))
1384                                 dns_rdataset_disassociate(rdataset);
1385                         result = ISC_R_NOTFOUND;
1386                 }
1387         }
1388
1389  cleanup:
1390         if (dns_rdataset_isassociated(&zrdataset)) {
1391                 dns_rdataset_disassociate(&zrdataset);
1392                 if (dns_rdataset_isassociated(&zsigrdataset))
1393                         dns_rdataset_disassociate(&zsigrdataset);
1394         }
1395         if (db != NULL)
1396                 dns_db_detach(&db);
1397 #ifdef BIND9
1398         if (zone != NULL)
1399                 dns_zone_detach(&zone);
1400 #endif
1401
1402         return (result);
1403 }
1404
1405 isc_result_t
1406 dns_viewlist_find(dns_viewlist_t *list, const char *name,
1407                   dns_rdataclass_t rdclass, dns_view_t **viewp)
1408 {
1409         dns_view_t *view;
1410
1411         REQUIRE(list != NULL);
1412
1413         for (view = ISC_LIST_HEAD(*list);
1414              view != NULL;
1415              view = ISC_LIST_NEXT(view, link)) {
1416                 if (strcmp(view->name, name) == 0 && view->rdclass == rdclass)
1417                         break;
1418         }
1419         if (view == NULL)
1420                 return (ISC_R_NOTFOUND);
1421
1422         dns_view_attach(view, viewp);
1423
1424         return (ISC_R_SUCCESS);
1425 }
1426
1427 #ifdef BIND9
1428 isc_result_t
1429 dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name,
1430                       isc_boolean_t allclasses, dns_rdataclass_t rdclass,
1431                       dns_zone_t **zonep)
1432 {
1433         dns_view_t *view;
1434         isc_result_t result;
1435         dns_zone_t *zone1 = NULL, *zone2 = NULL;
1436         dns_zone_t **zp = NULL;;
1437
1438         REQUIRE(list != NULL);
1439         REQUIRE(zonep != NULL && *zonep == NULL);
1440
1441         for (view = ISC_LIST_HEAD(*list);
1442              view != NULL;
1443              view = ISC_LIST_NEXT(view, link)) {
1444                 if (allclasses == ISC_FALSE && view->rdclass != rdclass)
1445                         continue;
1446
1447                 /*
1448                  * If the zone is defined in more than one view,
1449                  * treat it as not found.
1450                  */
1451                 zp = (zone1 == NULL) ? &zone1 : &zone2;
1452                 LOCK(&view->lock);
1453                 if (view->zonetable != NULL)
1454                         result = dns_zt_find(view->zonetable, name, 0,
1455                                              NULL, zp);
1456                 else
1457                         result = ISC_R_NOTFOUND;
1458                 UNLOCK(&view->lock);
1459                 INSIST(result == ISC_R_SUCCESS ||
1460                        result == ISC_R_NOTFOUND ||
1461                        result == DNS_R_PARTIALMATCH);
1462
1463                 /* Treat a partial match as no match */
1464                 if (result == DNS_R_PARTIALMATCH) {
1465                         dns_zone_detach(zp);
1466                         result = ISC_R_NOTFOUND;
1467                         POST(result);
1468                 }
1469
1470                 if (zone2 != NULL) {
1471                         dns_zone_detach(&zone1);
1472                         dns_zone_detach(&zone2);
1473                         return (ISC_R_MULTIPLE);
1474                 }
1475         }
1476
1477         if (zone1 != NULL) {
1478                 dns_zone_attach(zone1, zonep);
1479                 dns_zone_detach(&zone1);
1480                 return (ISC_R_SUCCESS);
1481         }
1482
1483         return (ISC_R_NOTFOUND);
1484 }
1485
1486 isc_result_t
1487 dns_view_load(dns_view_t *view, isc_boolean_t stop) {
1488
1489         REQUIRE(DNS_VIEW_VALID(view));
1490         REQUIRE(view->zonetable != NULL);
1491
1492         return (dns_zt_load(view->zonetable, stop));
1493 }
1494
1495 isc_result_t
1496 dns_view_loadnew(dns_view_t *view, isc_boolean_t stop) {
1497
1498         REQUIRE(DNS_VIEW_VALID(view));
1499         REQUIRE(view->zonetable != NULL);
1500
1501         return (dns_zt_loadnew(view->zonetable, stop));
1502 }
1503
1504 isc_result_t
1505 dns_view_asyncload(dns_view_t *view, dns_zt_allloaded_t callback, void *arg) {
1506         REQUIRE(DNS_VIEW_VALID(view));
1507         REQUIRE(view->zonetable != NULL);
1508
1509         return (dns_zt_asyncload(view->zonetable, callback, arg));
1510 }
1511
1512
1513 #endif /* BIND9 */
1514
1515 isc_result_t
1516 dns_view_gettsig(dns_view_t *view, dns_name_t *keyname, dns_tsigkey_t **keyp)
1517 {
1518         isc_result_t result;
1519         REQUIRE(keyp != NULL && *keyp == NULL);
1520
1521         result = dns_tsigkey_find(keyp, keyname, NULL,
1522                                   view->statickeys);
1523         if (result == ISC_R_NOTFOUND)
1524                 result = dns_tsigkey_find(keyp, keyname, NULL,
1525                                           view->dynamickeys);
1526         return (result);
1527 }
1528
1529 isc_result_t
1530 dns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr,
1531                      dns_tsigkey_t **keyp)
1532 {
1533         isc_result_t result;
1534         dns_name_t *keyname = NULL;
1535         dns_peer_t *peer = NULL;
1536
1537         result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer);
1538         if (result != ISC_R_SUCCESS)
1539                 return (result);
1540
1541         result = dns_peer_getkey(peer, &keyname);
1542         if (result != ISC_R_SUCCESS)
1543                 return (result);
1544
1545         result = dns_view_gettsig(view, keyname, keyp);
1546         return ((result == ISC_R_NOTFOUND) ? ISC_R_FAILURE : result);
1547 }
1548
1549 isc_result_t
1550 dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
1551         REQUIRE(DNS_VIEW_VALID(view));
1552         REQUIRE(source != NULL);
1553
1554         return (dns_tsig_verify(source, msg, view->statickeys,
1555                                 view->dynamickeys));
1556 }
1557
1558 #ifdef BIND9
1559 isc_result_t
1560 dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
1561         isc_result_t result;
1562
1563         REQUIRE(DNS_VIEW_VALID(view));
1564
1565         (void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name);
1566         result = dns_master_dumptostream(view->mctx, view->cachedb, NULL,
1567                                          &dns_master_style_cache, fp);
1568         if (result != ISC_R_SUCCESS)
1569                 return (result);
1570         dns_adb_dump(view->adb, fp);
1571         dns_resolver_printbadcache(view->resolver, fp);
1572         return (ISC_R_SUCCESS);
1573 }
1574 #endif
1575
1576 isc_result_t
1577 dns_view_flushcache(dns_view_t *view) {
1578         return (dns_view_flushcache2(view, ISC_FALSE));
1579 }
1580
1581 isc_result_t
1582 dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) {
1583         isc_result_t result;
1584
1585         REQUIRE(DNS_VIEW_VALID(view));
1586
1587         if (view->cachedb == NULL)
1588                 return (ISC_R_SUCCESS);
1589         if (!fixuponly) {
1590                 result = dns_cache_flush(view->cache);
1591                 if (result != ISC_R_SUCCESS)
1592                         return (result);
1593         }
1594 #ifdef BIND9
1595         if (view->acache != NULL)
1596                 dns_acache_putdb(view->acache, view->cachedb);
1597 #endif
1598         dns_db_detach(&view->cachedb);
1599         dns_cache_attachdb(view->cache, &view->cachedb);
1600 #ifdef BIND9
1601         if (view->acache != NULL)
1602                 dns_acache_setdb(view->acache, view->cachedb);
1603         if (view->resolver != NULL)
1604                 dns_resolver_flushbadcache(view->resolver, NULL);
1605 #endif
1606
1607         dns_adb_flush(view->adb);
1608         return (ISC_R_SUCCESS);
1609 }
1610
1611 isc_result_t
1612 dns_view_flushname(dns_view_t *view, dns_name_t *name) {
1613         return (dns_view_flushnode(view, name, ISC_FALSE));
1614 }
1615
1616 isc_result_t
1617 dns_view_flushnode(dns_view_t *view, dns_name_t *name, isc_boolean_t tree) {
1618
1619         REQUIRE(DNS_VIEW_VALID(view));
1620
1621         if (!tree) {
1622                 if (view->adb != NULL)
1623                         dns_adb_flushname(view->adb, name);
1624                 if (view->cache == NULL)
1625                         return (ISC_R_SUCCESS);
1626                 if (view->resolver != NULL)
1627                         dns_resolver_flushbadcache(view->resolver, name);
1628         }
1629         return (dns_cache_flushnode(view->cache, name, tree));
1630 }
1631
1632 isc_result_t
1633 dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name) {
1634         isc_result_t result;
1635         dns_name_t *new;
1636         isc_uint32_t hash;
1637
1638         REQUIRE(DNS_VIEW_VALID(view));
1639
1640         if (view->delonly == NULL) {
1641                 view->delonly = isc_mem_get(view->mctx,
1642                                             sizeof(dns_namelist_t) *
1643                                             DNS_VIEW_DELONLYHASH);
1644                 if (view->delonly == NULL)
1645                         return (ISC_R_NOMEMORY);
1646                 for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
1647                         ISC_LIST_INIT(view->delonly[hash]);
1648         }
1649         hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
1650         new = ISC_LIST_HEAD(view->delonly[hash]);
1651         while (new != NULL && !dns_name_equal(new, name))
1652                 new = ISC_LIST_NEXT(new, link);
1653         if (new != NULL)
1654                 return (ISC_R_SUCCESS);
1655         new = isc_mem_get(view->mctx, sizeof(*new));
1656         if (new == NULL)
1657                 return (ISC_R_NOMEMORY);
1658         dns_name_init(new, NULL);
1659         result = dns_name_dup(name, view->mctx, new);
1660         if (result == ISC_R_SUCCESS)
1661                 ISC_LIST_APPEND(view->delonly[hash], new, link);
1662         else
1663                 isc_mem_put(view->mctx, new, sizeof(*new));
1664         return (result);
1665 }
1666
1667 isc_result_t
1668 dns_view_excludedelegationonly(dns_view_t *view, dns_name_t *name) {
1669         isc_result_t result;
1670         dns_name_t *new;
1671         isc_uint32_t hash;
1672
1673         REQUIRE(DNS_VIEW_VALID(view));
1674
1675         if (view->rootexclude == NULL) {
1676                 view->rootexclude = isc_mem_get(view->mctx,
1677                                             sizeof(dns_namelist_t) *
1678                                             DNS_VIEW_DELONLYHASH);
1679                 if (view->rootexclude == NULL)
1680                         return (ISC_R_NOMEMORY);
1681                 for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
1682                         ISC_LIST_INIT(view->rootexclude[hash]);
1683         }
1684         hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
1685         new = ISC_LIST_HEAD(view->rootexclude[hash]);
1686         while (new != NULL && !dns_name_equal(new, name))
1687                 new = ISC_LIST_NEXT(new, link);
1688         if (new != NULL)
1689                 return (ISC_R_SUCCESS);
1690         new = isc_mem_get(view->mctx, sizeof(*new));
1691         if (new == NULL)
1692                 return (ISC_R_NOMEMORY);
1693         dns_name_init(new, NULL);
1694         result = dns_name_dup(name, view->mctx, new);
1695         if (result == ISC_R_SUCCESS)
1696                 ISC_LIST_APPEND(view->rootexclude[hash], new, link);
1697         else
1698                 isc_mem_put(view->mctx, new, sizeof(*new));
1699         return (result);
1700 }
1701
1702 isc_boolean_t
1703 dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name) {
1704         dns_name_t *new;
1705         isc_uint32_t hash;
1706
1707         REQUIRE(DNS_VIEW_VALID(view));
1708
1709         if (!view->rootdelonly && view->delonly == NULL)
1710                 return (ISC_FALSE);
1711
1712         hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
1713         if (view->rootdelonly && dns_name_countlabels(name) <= 2) {
1714                 if (view->rootexclude == NULL)
1715                         return (ISC_TRUE);
1716                 new = ISC_LIST_HEAD(view->rootexclude[hash]);
1717                 while (new != NULL && !dns_name_equal(new, name))
1718                         new = ISC_LIST_NEXT(new, link);
1719                 if (new == NULL)
1720                         return (ISC_TRUE);
1721         }
1722
1723         if (view->delonly == NULL)
1724                 return (ISC_FALSE);
1725
1726         new = ISC_LIST_HEAD(view->delonly[hash]);
1727         while (new != NULL && !dns_name_equal(new, name))
1728                 new = ISC_LIST_NEXT(new, link);
1729         if (new == NULL)
1730                 return (ISC_FALSE);
1731         return (ISC_TRUE);
1732 }
1733
1734 void
1735 dns_view_setrootdelonly(dns_view_t *view, isc_boolean_t value) {
1736         REQUIRE(DNS_VIEW_VALID(view));
1737         view->rootdelonly = value;
1738 }
1739
1740 isc_boolean_t
1741 dns_view_getrootdelonly(dns_view_t *view) {
1742         REQUIRE(DNS_VIEW_VALID(view));
1743         return (view->rootdelonly);
1744 }
1745
1746 #ifdef BIND9
1747 isc_result_t
1748 dns_view_freezezones(dns_view_t *view, isc_boolean_t value) {
1749
1750         REQUIRE(DNS_VIEW_VALID(view));
1751         REQUIRE(view->zonetable != NULL);
1752
1753         return (dns_zt_freezezones(view->zonetable, value));
1754 }
1755 #endif
1756
1757 void
1758 dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) {
1759
1760         REQUIRE(DNS_VIEW_VALID(view));
1761         REQUIRE(!view->frozen);
1762         REQUIRE(view->resstats == NULL);
1763
1764         isc_stats_attach(stats, &view->resstats);
1765 }
1766
1767 void
1768 dns_view_getresstats(dns_view_t *view, isc_stats_t **statsp) {
1769         REQUIRE(DNS_VIEW_VALID(view));
1770         REQUIRE(statsp != NULL && *statsp == NULL);
1771
1772         if (view->resstats != NULL)
1773                 isc_stats_attach(view->resstats, statsp);
1774 }
1775
1776 void
1777 dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats) {
1778         REQUIRE(DNS_VIEW_VALID(view));
1779         REQUIRE(!view->frozen);
1780         REQUIRE(view->resquerystats == NULL);
1781
1782         dns_stats_attach(stats, &view->resquerystats);
1783 }
1784
1785 void
1786 dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
1787         REQUIRE(DNS_VIEW_VALID(view));
1788         REQUIRE(statsp != NULL && *statsp == NULL);
1789
1790         if (view->resquerystats != NULL)
1791                 dns_stats_attach(view->resquerystats, statsp);
1792 }
1793
1794 isc_result_t
1795 dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) {
1796         REQUIRE(DNS_VIEW_VALID(view));
1797         if (view->secroots_priv != NULL)
1798                 dns_keytable_detach(&view->secroots_priv);
1799         return (dns_keytable_create(mctx, &view->secroots_priv));
1800 }
1801
1802 isc_result_t
1803 dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) {
1804         REQUIRE(DNS_VIEW_VALID(view));
1805         REQUIRE(ktp != NULL && *ktp == NULL);
1806         if (view->secroots_priv == NULL)
1807                 return (ISC_R_NOTFOUND);
1808         dns_keytable_attach(view->secroots_priv, ktp);
1809         return (ISC_R_SUCCESS);
1810 }
1811
1812 isc_result_t
1813 dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
1814                          isc_boolean_t *secure_domain) {
1815         REQUIRE(DNS_VIEW_VALID(view));
1816
1817         if (view->secroots_priv == NULL)
1818                 return (ISC_R_NOTFOUND);
1819         return (dns_keytable_issecuredomain(view->secroots_priv, name,
1820                                             secure_domain));
1821 }
1822
1823 void
1824 dns_view_untrust(dns_view_t *view, dns_name_t *keyname,
1825                  dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx)
1826 {
1827         isc_result_t result;
1828         unsigned char data[4096];
1829         dns_rdata_t rdata = DNS_RDATA_INIT;
1830         isc_buffer_t buffer;
1831         dst_key_t *key = NULL;
1832         dns_keytable_t *sr = NULL;
1833
1834         /*
1835          * Clear the revoke bit, if set, so that the key will match what's
1836          * in secroots now.
1837          */
1838         dnskey->flags &= ~DNS_KEYFLAG_REVOKE;
1839
1840         /* Convert dnskey to DST key. */
1841         isc_buffer_init(&buffer, data, sizeof(data));
1842         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
1843                              dns_rdatatype_dnskey, dnskey, &buffer);
1844         result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key);
1845         if (result != ISC_R_SUCCESS)
1846                 return;
1847         result = dns_view_getsecroots(view, &sr);
1848         if (result == ISC_R_SUCCESS) {
1849                 dns_keytable_deletekeynode(sr, key);
1850                 dns_keytable_detach(&sr);
1851         }
1852         dst_key_free(&key);
1853 }
1854
1855 #define NZF ".nzf"
1856
1857 void
1858 dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
1859                      void (*cfg_destroy)(void **))
1860 {
1861         REQUIRE(DNS_VIEW_VALID(view));
1862         REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow);
1863
1864 #ifdef BIND9
1865         if (view->new_zone_file != NULL) {
1866                 isc_mem_free(view->mctx, view->new_zone_file);
1867                 view->new_zone_file = NULL;
1868         }
1869
1870         if (view->new_zone_config != NULL) {
1871                 view->cfg_destroy(&view->new_zone_config);
1872                 view->cfg_destroy = NULL;
1873         }
1874
1875         if (allow) {
1876                 char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(NZF)];
1877                 isc_sha256_data((void *)view->name, strlen(view->name), buffer);
1878                 /* Truncate the hash at 16 chars; full length is overkill */
1879                 isc_string_printf(buffer + 16, sizeof(NZF), "%s", NZF);
1880                 view->new_zone_file = isc_mem_strdup(view->mctx, buffer);
1881                 view->new_zone_config = cfgctx;
1882                 view->cfg_destroy = cfg_destroy;
1883         }
1884 #else
1885         UNUSED(allow);
1886         UNUSED(cfgctx);
1887         UNUSED(cfg_destroy);
1888 #endif
1889 }