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