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