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