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