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