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