2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.
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.
18 /* $Id: view.c,v 1.103.2.10 2004/03/09 06:11:10 marka Exp $ */
24 #include <isc/string.h> /* Required for HP/UX (and others?) */
29 #include <dns/cache.h>
31 #include <dns/events.h>
32 #include <dns/forward.h>
33 #include <dns/keytable.h>
34 #include <dns/master.h>
35 #include <dns/masterdump.h>
37 #include <dns/rdataset.h>
38 #include <dns/request.h>
39 #include <dns/resolver.h>
40 #include <dns/result.h>
45 #define RESSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0)
46 #define ADBSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
47 #define REQSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0)
49 #define DNS_VIEW_DELONLYHASH 111
51 static void resolver_shutdown(isc_task_t
*task
, isc_event_t
*event
);
52 static void adb_shutdown(isc_task_t
*task
, isc_event_t
*event
);
53 static void req_shutdown(isc_task_t
*task
, isc_event_t
*event
);
56 dns_view_create(isc_mem_t
*mctx
, dns_rdataclass_t rdclass
,
57 const char *name
, dns_view_t
**viewp
)
66 REQUIRE(name
!= NULL
);
67 REQUIRE(viewp
!= NULL
&& *viewp
== NULL
);
69 view
= isc_mem_get(mctx
, sizeof *view
);
71 return (ISC_R_NOMEMORY
);
72 view
->name
= isc_mem_strdup(mctx
, name
);
73 if (view
->name
== NULL
) {
74 result
= ISC_R_NOMEMORY
;
77 result
= isc_mutex_init(&view
->lock
);
78 if (result
!= ISC_R_SUCCESS
) {
79 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
80 "isc_mutex_init() failed: %s",
81 isc_result_totext(result
));
82 result
= ISC_R_UNEXPECTED
;
85 view
->zonetable
= NULL
;
86 result
= dns_zt_create(mctx
, rdclass
, &view
->zonetable
);
87 if (result
!= ISC_R_SUCCESS
) {
88 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
89 "dns_zt_create() failed: %s",
90 isc_result_totext(result
));
91 result
= ISC_R_UNEXPECTED
;
94 view
->secroots
= NULL
;
95 result
= dns_keytable_create(mctx
, &view
->secroots
);
96 if (result
!= ISC_R_SUCCESS
) {
97 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
98 "dns_keytable_create() failed: %s",
99 isc_result_totext(result
));
100 result
= ISC_R_UNEXPECTED
;
103 view
->trustedkeys
= NULL
;
104 result
= dns_keytable_create(mctx
, &view
->trustedkeys
);
105 if (result
!= ISC_R_SUCCESS
) {
106 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
107 "dns_keytable_create() failed: %s",
108 isc_result_totext(result
));
109 result
= ISC_R_UNEXPECTED
;
110 goto cleanup_secroots
;
112 view
->fwdtable
= NULL
;
113 result
= dns_fwdtable_create(mctx
, &view
->fwdtable
);
114 if (result
!= ISC_R_SUCCESS
) {
115 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
116 "dns_fwdtable_create() failed: %s",
117 isc_result_totext(result
));
118 result
= ISC_R_UNEXPECTED
;
119 goto cleanup_trustedkeys
;
123 view
->cachedb
= NULL
;
125 view
->resolver
= NULL
;
127 view
->requestmgr
= NULL
;
129 view
->rdclass
= rdclass
;
130 view
->frozen
= ISC_FALSE
;
132 isc_refcount_init(&view
->references
, 1);
134 view
->attributes
= (DNS_VIEWATTR_RESSHUTDOWN
|DNS_VIEWATTR_ADBSHUTDOWN
|
135 DNS_VIEWATTR_REQSHUTDOWN
);
136 view
->statickeys
= NULL
;
137 view
->dynamickeys
= NULL
;
138 view
->matchclients
= NULL
;
139 view
->matchdestinations
= NULL
;
140 view
->matchrecursiveonly
= ISC_FALSE
;
141 result
= dns_tsigkeyring_create(view
->mctx
, &view
->dynamickeys
);
142 if (result
!= ISC_R_SUCCESS
)
143 goto cleanup_fwdtable
;
147 * Initialize configuration data with default values.
149 view
->recursion
= ISC_TRUE
;
150 view
->auth_nxdomain
= ISC_FALSE
; /* Was true in BIND 8 */
151 view
->additionalfromcache
= ISC_TRUE
;
152 view
->additionalfromauth
= ISC_TRUE
;
153 view
->minimalresponses
= ISC_FALSE
;
154 view
->transfer_format
= dns_one_answer
;
155 view
->queryacl
= NULL
;
156 view
->recursionacl
= NULL
;
157 view
->v6synthesisacl
= NULL
;
158 view
->sortlist
= NULL
;
159 view
->requestixfr
= ISC_TRUE
;
160 view
->provideixfr
= ISC_TRUE
;
161 view
->maxcachettl
= 7 * 24 * 3600;
162 view
->maxncachettl
= 3 * 3600;
164 view
->flush
= ISC_FALSE
;
165 view
->delonly
= NULL
;
166 view
->rootdelonly
= ISC_FALSE
;
167 view
->rootexclude
= NULL
;
169 result
= dns_peerlist_new(view
->mctx
, &view
->peers
);
170 if (result
!= ISC_R_SUCCESS
)
171 goto cleanup_dynkeys
;
173 result
= dns_aclenv_init(view
->mctx
, &view
->aclenv
);
174 if (result
!= ISC_R_SUCCESS
)
175 goto cleanup_peerlist
;
177 ISC_LINK_INIT(view
, link
);
178 ISC_EVENT_INIT(&view
->resevent
, sizeof view
->resevent
, 0, NULL
,
179 DNS_EVENT_VIEWRESSHUTDOWN
, resolver_shutdown
,
180 view
, NULL
, NULL
, NULL
);
181 ISC_EVENT_INIT(&view
->adbevent
, sizeof view
->adbevent
, 0, NULL
,
182 DNS_EVENT_VIEWADBSHUTDOWN
, adb_shutdown
,
183 view
, NULL
, NULL
, NULL
);
184 ISC_EVENT_INIT(&view
->reqevent
, sizeof view
->reqevent
, 0, NULL
,
185 DNS_EVENT_VIEWREQSHUTDOWN
, req_shutdown
,
186 view
, NULL
, NULL
, NULL
);
187 view
->magic
= DNS_VIEW_MAGIC
;
191 return (ISC_R_SUCCESS
);
194 dns_peerlist_detach(&view
->peers
);
197 dns_tsigkeyring_destroy(&view
->dynamickeys
);
200 dns_fwdtable_destroy(&view
->fwdtable
);
203 dns_keytable_detach(&view
->trustedkeys
);
206 dns_keytable_detach(&view
->secroots
);
209 dns_zt_detach(&view
->zonetable
);
212 DESTROYLOCK(&view
->lock
);
215 isc_mem_free(mctx
, view
->name
);
218 isc_mem_put(mctx
, view
, sizeof *view
);
224 destroy(dns_view_t
*view
) {
225 REQUIRE(!ISC_LINK_LINKED(view
, link
));
226 REQUIRE(isc_refcount_current(&view
->references
) == 0);
227 REQUIRE(view
->weakrefs
== 0);
228 REQUIRE(RESSHUTDOWN(view
));
229 REQUIRE(ADBSHUTDOWN(view
));
230 REQUIRE(REQSHUTDOWN(view
));
232 if (view
->peers
!= NULL
)
233 dns_peerlist_detach(&view
->peers
);
234 if (view
->dynamickeys
!= NULL
)
235 dns_tsigkeyring_destroy(&view
->dynamickeys
);
236 if (view
->statickeys
!= NULL
)
237 dns_tsigkeyring_destroy(&view
->statickeys
);
238 if (view
->adb
!= NULL
)
239 dns_adb_detach(&view
->adb
);
240 if (view
->resolver
!= NULL
)
241 dns_resolver_detach(&view
->resolver
);
242 if (view
->requestmgr
!= NULL
)
243 dns_requestmgr_detach(&view
->requestmgr
);
244 if (view
->task
!= NULL
)
245 isc_task_detach(&view
->task
);
246 if (view
->hints
!= NULL
)
247 dns_db_detach(&view
->hints
);
248 if (view
->cachedb
!= NULL
)
249 dns_db_detach(&view
->cachedb
);
250 if (view
->cache
!= NULL
)
251 dns_cache_detach(&view
->cache
);
252 if (view
->matchclients
!= NULL
)
253 dns_acl_detach(&view
->matchclients
);
254 if (view
->matchdestinations
!= NULL
)
255 dns_acl_detach(&view
->matchdestinations
);
256 if (view
->queryacl
!= NULL
)
257 dns_acl_detach(&view
->queryacl
);
258 if (view
->recursionacl
!= NULL
)
259 dns_acl_detach(&view
->recursionacl
);
260 if (view
->v6synthesisacl
!= NULL
)
261 dns_acl_detach(&view
->v6synthesisacl
);
262 if (view
->sortlist
!= NULL
)
263 dns_acl_detach(&view
->sortlist
);
264 if (view
->delonly
!= NULL
) {
268 for (i
= 0; i
< DNS_VIEW_DELONLYHASH
; i
++) {
269 name
= ISC_LIST_HEAD(view
->delonly
[i
]);
270 while (name
!= NULL
) {
271 ISC_LIST_UNLINK(view
->delonly
[i
], name
, link
);
272 dns_name_free(name
, view
->mctx
);
273 isc_mem_put(view
->mctx
, name
, sizeof(*name
));
274 name
= ISC_LIST_HEAD(view
->delonly
[i
]);
277 isc_mem_put(view
->mctx
, view
->delonly
, sizeof(dns_namelist_t
) *
278 DNS_VIEW_DELONLYHASH
);
279 view
->delonly
= NULL
;
281 if (view
->rootexclude
!= NULL
) {
285 for (i
= 0; i
< DNS_VIEW_DELONLYHASH
; i
++) {
286 name
= ISC_LIST_HEAD(view
->rootexclude
[i
]);
287 while (name
!= NULL
) {
288 ISC_LIST_UNLINK(view
->rootexclude
[i
],
290 dns_name_free(name
, view
->mctx
);
291 isc_mem_put(view
->mctx
, name
, sizeof(*name
));
292 name
= ISC_LIST_HEAD(view
->rootexclude
[i
]);
295 isc_mem_put(view
->mctx
, view
->rootexclude
,
296 sizeof(dns_namelist_t
) * DNS_VIEW_DELONLYHASH
);
297 view
->rootexclude
= NULL
;
299 dns_keytable_detach(&view
->trustedkeys
);
300 dns_keytable_detach(&view
->secroots
);
301 dns_fwdtable_destroy(&view
->fwdtable
);
302 dns_aclenv_destroy(&view
->aclenv
);
303 DESTROYLOCK(&view
->lock
);
304 isc_refcount_destroy(&view
->references
);
305 isc_mem_free(view
->mctx
, view
->name
);
306 isc_mem_put(view
->mctx
, view
, sizeof *view
);
310 * Return true iff 'view' may be freed.
311 * The caller must be holding the view lock.
314 all_done(dns_view_t
*view
) {
316 if (isc_refcount_current(&view
->references
) == 0 &&
317 view
->weakrefs
== 0 &&
318 RESSHUTDOWN(view
) && ADBSHUTDOWN(view
) && REQSHUTDOWN(view
))
325 dns_view_attach(dns_view_t
*source
, dns_view_t
**targetp
) {
327 REQUIRE(DNS_VIEW_VALID(source
));
328 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
330 isc_refcount_increment(&source
->references
, NULL
);
336 view_flushanddetach(dns_view_t
**viewp
, isc_boolean_t flush
) {
339 isc_boolean_t done
= ISC_FALSE
;
341 REQUIRE(viewp
!= NULL
);
343 REQUIRE(DNS_VIEW_VALID(view
));
346 view
->flush
= ISC_TRUE
;
347 isc_refcount_decrement(&view
->references
, &refs
);
350 if (!RESSHUTDOWN(view
))
351 dns_resolver_shutdown(view
->resolver
);
352 if (!ADBSHUTDOWN(view
))
353 dns_adb_shutdown(view
->adb
);
354 if (!REQSHUTDOWN(view
))
355 dns_requestmgr_shutdown(view
->requestmgr
);
357 dns_zt_flushanddetach(&view
->zonetable
);
359 dns_zt_detach(&view
->zonetable
);
360 done
= all_done(view
);
371 dns_view_flushanddetach(dns_view_t
**viewp
) {
372 view_flushanddetach(viewp
, ISC_TRUE
);
376 dns_view_detach(dns_view_t
**viewp
) {
377 view_flushanddetach(viewp
, ISC_FALSE
);
381 dialup(dns_zone_t
*zone
, void *dummy
) {
383 dns_zone_dialup(zone
);
384 return (ISC_R_SUCCESS
);
388 dns_view_dialup(dns_view_t
*view
) {
389 REQUIRE(DNS_VIEW_VALID(view
));
390 dns_zt_apply(view
->zonetable
, ISC_FALSE
, dialup
, NULL
);
394 dns_view_weakattach(dns_view_t
*source
, dns_view_t
**targetp
) {
396 REQUIRE(DNS_VIEW_VALID(source
));
397 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
401 UNLOCK(&source
->lock
);
407 dns_view_weakdetach(dns_view_t
**viewp
) {
409 isc_boolean_t done
= ISC_FALSE
;
411 REQUIRE(viewp
!= NULL
);
413 REQUIRE(DNS_VIEW_VALID(view
));
417 INSIST(view
->weakrefs
> 0);
419 done
= all_done(view
);
430 resolver_shutdown(isc_task_t
*task
, isc_event_t
*event
) {
431 dns_view_t
*view
= event
->ev_arg
;
434 REQUIRE(event
->ev_type
== DNS_EVENT_VIEWRESSHUTDOWN
);
435 REQUIRE(DNS_VIEW_VALID(view
));
436 REQUIRE(view
->task
== task
);
442 view
->attributes
|= DNS_VIEWATTR_RESSHUTDOWN
;
443 done
= all_done(view
);
447 isc_event_free(&event
);
454 adb_shutdown(isc_task_t
*task
, isc_event_t
*event
) {
455 dns_view_t
*view
= event
->ev_arg
;
458 REQUIRE(event
->ev_type
== DNS_EVENT_VIEWADBSHUTDOWN
);
459 REQUIRE(DNS_VIEW_VALID(view
));
460 REQUIRE(view
->task
== task
);
466 view
->attributes
|= DNS_VIEWATTR_ADBSHUTDOWN
;
467 done
= all_done(view
);
471 isc_event_free(&event
);
478 req_shutdown(isc_task_t
*task
, isc_event_t
*event
) {
479 dns_view_t
*view
= event
->ev_arg
;
482 REQUIRE(event
->ev_type
== DNS_EVENT_VIEWREQSHUTDOWN
);
483 REQUIRE(DNS_VIEW_VALID(view
));
484 REQUIRE(view
->task
== task
);
490 view
->attributes
|= DNS_VIEWATTR_REQSHUTDOWN
;
491 done
= all_done(view
);
495 isc_event_free(&event
);
502 dns_view_createresolver(dns_view_t
*view
,
503 isc_taskmgr_t
*taskmgr
, unsigned int ntasks
,
504 isc_socketmgr_t
*socketmgr
,
505 isc_timermgr_t
*timermgr
,
506 unsigned int options
,
507 dns_dispatchmgr_t
*dispatchmgr
,
508 dns_dispatch_t
*dispatchv4
,
509 dns_dispatch_t
*dispatchv6
)
514 REQUIRE(DNS_VIEW_VALID(view
));
515 REQUIRE(!view
->frozen
);
516 REQUIRE(view
->resolver
== NULL
);
518 result
= isc_task_create(taskmgr
, 0, &view
->task
);
519 if (result
!= ISC_R_SUCCESS
)
521 isc_task_setname(view
->task
, "view", view
);
523 result
= dns_resolver_create(view
, taskmgr
, ntasks
, socketmgr
,
524 timermgr
, options
, dispatchmgr
,
525 dispatchv4
, dispatchv6
,
527 if (result
!= ISC_R_SUCCESS
) {
528 isc_task_detach(&view
->task
);
531 event
= &view
->resevent
;
532 dns_resolver_whenshutdown(view
->resolver
, view
->task
, &event
);
533 view
->attributes
&= ~DNS_VIEWATTR_RESSHUTDOWN
;
535 result
= dns_adb_create(view
->mctx
, view
, timermgr
, taskmgr
,
537 if (result
!= ISC_R_SUCCESS
) {
538 dns_resolver_shutdown(view
->resolver
);
541 event
= &view
->adbevent
;
542 dns_adb_whenshutdown(view
->adb
, view
->task
, &event
);
543 view
->attributes
&= ~DNS_VIEWATTR_ADBSHUTDOWN
;
545 result
= dns_requestmgr_create(view
->mctx
, timermgr
, socketmgr
,
546 dns_resolver_taskmgr(view
->resolver
),
547 dns_resolver_dispatchmgr(view
->resolver
),
548 dns_resolver_dispatchv4(view
->resolver
),
549 dns_resolver_dispatchv6(view
->resolver
),
551 if (result
!= ISC_R_SUCCESS
) {
552 dns_adb_shutdown(view
->adb
);
553 dns_resolver_shutdown(view
->resolver
);
556 event
= &view
->reqevent
;
557 dns_requestmgr_whenshutdown(view
->requestmgr
, view
->task
, &event
);
558 view
->attributes
&= ~DNS_VIEWATTR_REQSHUTDOWN
;
560 return (ISC_R_SUCCESS
);
564 dns_view_setcache(dns_view_t
*view
, dns_cache_t
*cache
) {
565 REQUIRE(DNS_VIEW_VALID(view
));
566 REQUIRE(!view
->frozen
);
568 if (view
->cache
!= NULL
) {
569 dns_db_detach(&view
->cachedb
);
570 dns_cache_detach(&view
->cache
);
572 dns_cache_attach(cache
, &view
->cache
);
573 dns_cache_attachdb(cache
, &view
->cachedb
);
574 INSIST(DNS_DB_VALID(view
->cachedb
));
578 dns_view_sethints(dns_view_t
*view
, dns_db_t
*hints
) {
579 REQUIRE(DNS_VIEW_VALID(view
));
580 REQUIRE(!view
->frozen
);
581 REQUIRE(view
->hints
== NULL
);
582 REQUIRE(dns_db_iszone(hints
));
584 dns_db_attach(hints
, &view
->hints
);
588 dns_view_setkeyring(dns_view_t
*view
, dns_tsig_keyring_t
*ring
) {
589 REQUIRE(DNS_VIEW_VALID(view
));
590 REQUIRE(ring
!= NULL
);
591 if (view
->statickeys
!= NULL
)
592 dns_tsigkeyring_destroy(&view
->statickeys
);
593 view
->statickeys
= ring
;
597 dns_view_setdstport(dns_view_t
*view
, in_port_t dstport
) {
598 REQUIRE(DNS_VIEW_VALID(view
));
599 view
->dstport
= dstport
;
603 dns_view_addzone(dns_view_t
*view
, dns_zone_t
*zone
) {
606 REQUIRE(DNS_VIEW_VALID(view
));
607 REQUIRE(!view
->frozen
);
609 result
= dns_zt_mount(view
->zonetable
, zone
);
615 dns_view_freeze(dns_view_t
*view
) {
616 REQUIRE(DNS_VIEW_VALID(view
));
617 REQUIRE(!view
->frozen
);
619 if (view
->resolver
!= NULL
) {
620 INSIST(view
->cachedb
!= NULL
);
621 dns_resolver_freeze(view
->resolver
);
623 view
->frozen
= ISC_TRUE
;
627 dns_view_findzone(dns_view_t
*view
, dns_name_t
*name
, dns_zone_t
**zonep
) {
630 REQUIRE(DNS_VIEW_VALID(view
));
632 result
= dns_zt_find(view
->zonetable
, name
, 0, NULL
, zonep
);
633 if (result
== DNS_R_PARTIALMATCH
) {
634 dns_zone_detach(zonep
);
635 result
= ISC_R_NOTFOUND
;
642 dns_view_find(dns_view_t
*view
, dns_name_t
*name
, dns_rdatatype_t type
,
643 isc_stdtime_t now
, unsigned int options
, isc_boolean_t use_hints
,
644 dns_db_t
**dbp
, dns_dbnode_t
**nodep
, dns_name_t
*foundname
,
645 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
649 dns_dbnode_t
*node
, *znode
;
650 isc_boolean_t is_cache
;
651 dns_rdataset_t zrdataset
, zsigrdataset
;
655 * Find an rdataset whose owner name is 'name', and whose type is
659 REQUIRE(DNS_VIEW_VALID(view
));
660 REQUIRE(view
->frozen
);
661 REQUIRE(type
!= dns_rdatatype_sig
);
662 REQUIRE(rdataset
!= NULL
); /* XXXBEW - remove this */
667 dns_rdataset_init(&zrdataset
);
668 dns_rdataset_init(&zsigrdataset
);
673 * Find a database to answer the query.
678 result
= dns_zt_find(view
->zonetable
, name
, 0, NULL
, &zone
);
679 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
) {
680 result
= dns_zone_getdb(zone
, &db
);
681 if (result
!= ISC_R_SUCCESS
&& view
->cachedb
!= NULL
)
682 dns_db_attach(view
->cachedb
, &db
);
683 else if (result
!= ISC_R_SUCCESS
)
685 } else if (result
== ISC_R_NOTFOUND
&& view
->cachedb
!= NULL
)
686 dns_db_attach(view
->cachedb
, &db
);
690 is_cache
= dns_db_iscache(db
);
694 * Now look for an answer in the database.
696 result
= dns_db_find(db
, name
, NULL
, type
, options
,
697 now
, &node
, foundname
, rdataset
, sigrdataset
);
699 if (result
== DNS_R_DELEGATION
||
700 result
== ISC_R_NOTFOUND
) {
701 if (dns_rdataset_isassociated(rdataset
))
702 dns_rdataset_disassociate(rdataset
);
703 if (sigrdataset
!= NULL
&&
704 dns_rdataset_isassociated(sigrdataset
))
705 dns_rdataset_disassociate(sigrdataset
);
707 dns_db_detachnode(db
, &node
);
710 if (view
->cachedb
!= NULL
) {
712 * Either the answer is in the cache, or we
716 dns_db_attach(view
->cachedb
, &db
);
721 * We don't have the data in the cache. If we've got
722 * glue from the zone, use it.
724 if (dns_rdataset_isassociated(&zrdataset
)) {
725 dns_rdataset_clone(&zrdataset
, rdataset
);
726 if (sigrdataset
!= NULL
&&
727 dns_rdataset_isassociated(&zsigrdataset
))
728 dns_rdataset_clone(&zsigrdataset
,
733 dns_db_attach(zdb
, &db
);
734 dns_db_attachnode(db
, znode
, &node
);
739 * We don't know the answer.
741 result
= ISC_R_NOTFOUND
;
742 } else if (result
== DNS_R_GLUE
) {
743 if (view
->cachedb
!= NULL
) {
745 * We found an answer, but the cache may be better.
746 * Remember what we've got and go look in the cache.
749 dns_rdataset_clone(rdataset
, &zrdataset
);
750 dns_rdataset_disassociate(rdataset
);
751 if (sigrdataset
!= NULL
&&
752 dns_rdataset_isassociated(sigrdataset
)) {
753 dns_rdataset_clone(sigrdataset
, &zsigrdataset
);
754 dns_rdataset_disassociate(sigrdataset
);
756 dns_db_attach(db
, &zdb
);
757 dns_db_attachnode(zdb
, node
, &znode
);
758 dns_db_detachnode(db
, &node
);
760 dns_db_attach(view
->cachedb
, &db
);
764 * Otherwise, the glue is the best answer.
766 result
= ISC_R_SUCCESS
;
769 if (result
== ISC_R_NOTFOUND
&& use_hints
&& view
->hints
!= NULL
) {
770 if (dns_rdataset_isassociated(rdataset
))
771 dns_rdataset_disassociate(rdataset
);
772 if (sigrdataset
!= NULL
&&
773 dns_rdataset_isassociated(sigrdataset
))
774 dns_rdataset_disassociate(sigrdataset
);
777 dns_db_detachnode(db
, &node
);
780 result
= dns_db_find(view
->hints
, name
, NULL
, type
, options
,
781 now
, &node
, foundname
,
782 rdataset
, sigrdataset
);
783 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_GLUE
) {
785 * We just used a hint. Let the resolver know it
786 * should consider priming.
788 dns_resolver_prime(view
->resolver
);
789 dns_db_attach(view
->hints
, &db
);
791 } else if (result
== DNS_R_NXRRSET
) {
792 dns_db_attach(view
->hints
, &db
);
793 result
= DNS_R_HINTNXRRSET
;
794 } else if (result
== DNS_R_NXDOMAIN
)
795 result
= ISC_R_NOTFOUND
;
798 * Cleanup if non-standard hints are used.
800 if (db
== NULL
&& node
!= NULL
)
801 dns_db_detachnode(view
->hints
, &node
);
805 if (result
== DNS_R_NXDOMAIN
|| result
== DNS_R_NXRRSET
) {
807 * We don't care about any DNSSEC proof data in these cases.
809 if (dns_rdataset_isassociated(rdataset
))
810 dns_rdataset_disassociate(rdataset
);
811 if (sigrdataset
!= NULL
&&
812 dns_rdataset_isassociated(sigrdataset
))
813 dns_rdataset_disassociate(sigrdataset
);
816 if (dns_rdataset_isassociated(&zrdataset
)) {
817 dns_rdataset_disassociate(&zrdataset
);
818 if (dns_rdataset_isassociated(&zsigrdataset
))
819 dns_rdataset_disassociate(&zsigrdataset
);
824 dns_db_detachnode(zdb
, &znode
);
833 dns_db_detachnode(db
, &node
);
840 INSIST(node
== NULL
);
843 dns_zone_detach(&zone
);
849 dns_view_simplefind(dns_view_t
*view
, dns_name_t
*name
, dns_rdatatype_t type
,
850 isc_stdtime_t now
, unsigned int options
,
851 isc_boolean_t use_hints
,
852 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
855 dns_fixedname_t foundname
;
857 dns_fixedname_init(&foundname
);
858 result
= dns_view_find(view
, name
, type
, now
, options
, use_hints
,
859 NULL
, NULL
, dns_fixedname_name(&foundname
),
860 rdataset
, sigrdataset
);
861 if (result
== DNS_R_NXDOMAIN
) {
863 * The rdataset and sigrdataset of the relevant NXT record
864 * may be returned, but the caller cannot use them because
865 * foundname is not returned by this simplified API. We
866 * disassociate them here to prevent any misuse by the caller.
868 if (dns_rdataset_isassociated(rdataset
))
869 dns_rdataset_disassociate(rdataset
);
870 if (sigrdataset
!= NULL
&&
871 dns_rdataset_isassociated(sigrdataset
))
872 dns_rdataset_disassociate(sigrdataset
);
873 } else if (result
!= ISC_R_SUCCESS
&&
874 result
!= DNS_R_GLUE
&&
875 result
!= DNS_R_HINT
&&
876 result
!= DNS_R_NCACHENXDOMAIN
&&
877 result
!= DNS_R_NCACHENXRRSET
&&
878 result
!= DNS_R_NXRRSET
&&
879 result
!= DNS_R_HINTNXRRSET
&&
880 result
!= ISC_R_NOTFOUND
) {
881 if (dns_rdataset_isassociated(rdataset
))
882 dns_rdataset_disassociate(rdataset
);
883 if (sigrdataset
!= NULL
&&
884 dns_rdataset_isassociated(sigrdataset
))
885 dns_rdataset_disassociate(sigrdataset
);
886 result
= ISC_R_NOTFOUND
;
893 dns_view_findzonecut(dns_view_t
*view
, dns_name_t
*name
, dns_name_t
*fname
,
894 isc_stdtime_t now
, unsigned int options
,
895 isc_boolean_t use_hints
,
896 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
898 return(dns_view_findzonecut2(view
, name
, fname
, now
, options
,
900 rdataset
, sigrdataset
));
904 dns_view_findzonecut2(dns_view_t
*view
, dns_name_t
*name
, dns_name_t
*fname
,
905 isc_stdtime_t now
, unsigned int options
,
906 isc_boolean_t use_hints
, isc_boolean_t use_cache
,
907 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
911 isc_boolean_t is_cache
, use_zone
, try_hints
;
914 dns_rdataset_t zrdataset
, zsigrdataset
;
915 dns_fixedname_t zfixedname
;
917 REQUIRE(DNS_VIEW_VALID(view
));
918 REQUIRE(view
->frozen
);
922 use_zone
= ISC_FALSE
;
923 try_hints
= ISC_FALSE
;
929 dns_fixedname_init(&zfixedname
);
930 dns_rdataset_init(&zrdataset
);
931 dns_rdataset_init(&zsigrdataset
);
934 * Find the right database.
936 result
= dns_zt_find(view
->zonetable
, name
, 0, NULL
, &zone
);
937 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
938 result
= dns_zone_getdb(zone
, &db
);
939 if (result
== ISC_R_NOTFOUND
) {
941 * We're not directly authoritative for this query name, nor
942 * is it a subdomain of any zone for which we're
945 if (use_cache
&& view
->cachedb
!= NULL
) {
947 * We have a cache; try it.
949 dns_db_attach(view
->cachedb
, &db
);
952 * Maybe we have hints...
954 try_hints
= ISC_TRUE
;
957 } else if (result
!= ISC_R_SUCCESS
) {
959 * Something is broken.
963 is_cache
= dns_db_iscache(db
);
967 * Look for the zonecut.
970 result
= dns_db_find(db
, name
, NULL
, dns_rdatatype_ns
, options
,
971 now
, NULL
, fname
, rdataset
, sigrdataset
);
972 if (result
== DNS_R_DELEGATION
)
973 result
= ISC_R_SUCCESS
;
974 else if (result
!= ISC_R_SUCCESS
)
976 if (use_cache
&& view
->cachedb
!= NULL
&& db
!= view
->hints
) {
978 * We found an answer, but the cache may be better.
980 zfname
= dns_fixedname_name(&zfixedname
);
981 result
= dns_name_copy(fname
, zfname
, NULL
);
982 if (result
!= ISC_R_SUCCESS
)
984 dns_rdataset_clone(rdataset
, &zrdataset
);
985 dns_rdataset_disassociate(rdataset
);
986 if (sigrdataset
!= NULL
&&
987 dns_rdataset_isassociated(sigrdataset
)) {
988 dns_rdataset_clone(sigrdataset
, &zsigrdataset
);
989 dns_rdataset_disassociate(sigrdataset
);
992 dns_db_attach(view
->cachedb
, &db
);
997 result
= dns_db_findzonecut(db
, name
, options
, now
, NULL
,
998 fname
, rdataset
, sigrdataset
);
999 if (result
== ISC_R_SUCCESS
) {
1000 if (zfname
!= NULL
&&
1001 !dns_name_issubdomain(fname
, zfname
)) {
1003 * We found a zonecut in the cache, but our
1004 * zone delegation is better.
1006 use_zone
= ISC_TRUE
;
1008 } else if (result
== ISC_R_NOTFOUND
) {
1009 if (zfname
!= NULL
) {
1011 * We didn't find anything in the cache, but we
1012 * have a zone delegation, so use it.
1014 use_zone
= ISC_TRUE
;
1017 * Maybe we have hints...
1019 try_hints
= ISC_TRUE
;
1023 * Something bad happened.
1031 if (dns_rdataset_isassociated(rdataset
)) {
1032 dns_rdataset_disassociate(rdataset
);
1033 if (sigrdataset
!= NULL
&&
1034 dns_rdataset_isassociated(sigrdataset
))
1035 dns_rdataset_disassociate(sigrdataset
);
1037 result
= dns_name_copy(zfname
, fname
, NULL
);
1038 if (result
!= ISC_R_SUCCESS
)
1040 dns_rdataset_clone(&zrdataset
, rdataset
);
1041 if (sigrdataset
!= NULL
&&
1042 dns_rdataset_isassociated(&zrdataset
))
1043 dns_rdataset_clone(&zsigrdataset
, sigrdataset
);
1044 } else if (try_hints
&& use_hints
&& view
->hints
!= NULL
) {
1046 * We've found nothing so far, but we have hints.
1048 result
= dns_db_find(view
->hints
, dns_rootname
, NULL
,
1049 dns_rdatatype_ns
, 0, now
, NULL
, fname
,
1051 if (result
!= ISC_R_SUCCESS
) {
1053 * We can't even find the hints for the root
1056 if (dns_rdataset_isassociated(rdataset
))
1057 dns_rdataset_disassociate(rdataset
);
1058 result
= ISC_R_NOTFOUND
;
1063 if (dns_rdataset_isassociated(&zrdataset
)) {
1064 dns_rdataset_disassociate(&zrdataset
);
1065 if (dns_rdataset_isassociated(&zsigrdataset
))
1066 dns_rdataset_disassociate(&zsigrdataset
);
1071 dns_zone_detach(&zone
);
1077 dns_viewlist_find(dns_viewlist_t
*list
, const char *name
,
1078 dns_rdataclass_t rdclass
, dns_view_t
**viewp
)
1082 REQUIRE(list
!= NULL
);
1084 for (view
= ISC_LIST_HEAD(*list
);
1086 view
= ISC_LIST_NEXT(view
, link
)) {
1087 if (strcmp(view
->name
, name
) == 0 && view
->rdclass
== rdclass
)
1091 return (ISC_R_NOTFOUND
);
1093 dns_view_attach(view
, viewp
);
1095 return (ISC_R_SUCCESS
);
1099 dns_view_load(dns_view_t
*view
, isc_boolean_t stop
) {
1101 REQUIRE(DNS_VIEW_VALID(view
));
1103 return (dns_zt_load(view
->zonetable
, stop
));
1107 dns_view_loadnew(dns_view_t
*view
, isc_boolean_t stop
) {
1109 REQUIRE(DNS_VIEW_VALID(view
));
1111 return (dns_zt_loadnew(view
->zonetable
, stop
));
1115 dns_view_gettsig(dns_view_t
*view
, dns_name_t
*keyname
, dns_tsigkey_t
**keyp
)
1117 isc_result_t result
;
1118 REQUIRE(keyp
!= NULL
&& *keyp
== NULL
);
1120 result
= dns_tsigkey_find(keyp
, keyname
, NULL
,
1122 if (result
== ISC_R_NOTFOUND
)
1123 result
= dns_tsigkey_find(keyp
, keyname
, NULL
,
1129 dns_view_getpeertsig(dns_view_t
*view
, isc_netaddr_t
*peeraddr
,
1130 dns_tsigkey_t
**keyp
)
1132 isc_result_t result
;
1133 dns_name_t
*keyname
= NULL
;
1134 dns_peer_t
*peer
= NULL
;
1136 result
= dns_peerlist_peerbyaddr(view
->peers
, peeraddr
, &peer
);
1137 if (result
!= ISC_R_SUCCESS
)
1140 result
= dns_peer_getkey(peer
, &keyname
);
1141 if (result
!= ISC_R_SUCCESS
)
1144 return (dns_view_gettsig(view
, keyname
, keyp
));
1148 dns_view_checksig(dns_view_t
*view
, isc_buffer_t
*source
, dns_message_t
*msg
) {
1149 REQUIRE(DNS_VIEW_VALID(view
));
1150 REQUIRE(source
!= NULL
);
1152 return (dns_tsig_verify(source
, msg
, view
->statickeys
,
1153 view
->dynamickeys
));
1157 dns_view_dumpdbtostream(dns_view_t
*view
, FILE *fp
) {
1158 isc_result_t result
;
1160 REQUIRE(DNS_VIEW_VALID(view
));
1162 (void)fprintf(fp
, ";\n; Cache dump of view '%s'\n;\n", view
->name
);
1163 result
= dns_master_dumptostream(view
->mctx
, view
->cachedb
, NULL
,
1164 &dns_master_style_cache
, fp
);
1165 if (result
!= ISC_R_SUCCESS
)
1167 #ifdef notyet /* clean up adb dump format first */
1168 dns_adb_dump(view
->adb
, fp
);
1170 return (ISC_R_SUCCESS
);
1174 dns_view_flushcache(dns_view_t
*view
) {
1175 isc_result_t result
;
1177 REQUIRE(DNS_VIEW_VALID(view
));
1179 if (view
->cachedb
== NULL
)
1180 return (ISC_R_SUCCESS
);
1181 result
= dns_cache_flush(view
->cache
);
1182 if (result
!= ISC_R_SUCCESS
)
1184 dns_db_detach(&view
->cachedb
);
1185 dns_cache_attachdb(view
->cache
, &view
->cachedb
);
1187 dns_adb_flush(view
->adb
);
1188 return (ISC_R_SUCCESS
);
1192 dns_view_adddelegationonly(dns_view_t
*view
, dns_name_t
*name
) {
1193 isc_result_t result
;
1197 REQUIRE(DNS_VIEW_VALID(view
));
1199 if (view
->delonly
== NULL
) {
1200 view
->delonly
= isc_mem_get(view
->mctx
,
1201 sizeof(dns_namelist_t
) *
1202 DNS_VIEW_DELONLYHASH
);
1203 if (view
->delonly
== NULL
)
1204 return (ISC_R_NOMEMORY
);
1205 for (hash
= 0; hash
< DNS_VIEW_DELONLYHASH
; hash
++)
1206 ISC_LIST_INIT(view
->delonly
[hash
]);
1208 hash
= dns_name_hash(name
, ISC_FALSE
) % DNS_VIEW_DELONLYHASH
;
1209 new = ISC_LIST_HEAD(view
->delonly
[hash
]);
1210 while (new != NULL
&& !dns_name_equal(new, name
))
1211 new = ISC_LIST_NEXT(new, link
);
1213 return (ISC_R_SUCCESS
);
1214 new = isc_mem_get(view
->mctx
, sizeof(*new));
1216 return (ISC_R_NOMEMORY
);
1217 dns_name_init(new, NULL
);
1218 result
= dns_name_dup(name
, view
->mctx
, new);
1219 if (result
== ISC_R_SUCCESS
)
1220 ISC_LIST_APPEND(view
->delonly
[hash
], new, link
);
1222 isc_mem_put(view
->mctx
, new, sizeof(*new));
1227 dns_view_excludedelegationonly(dns_view_t
*view
, dns_name_t
*name
) {
1228 isc_result_t result
;
1232 REQUIRE(DNS_VIEW_VALID(view
));
1234 if (view
->rootexclude
== NULL
) {
1235 view
->rootexclude
= isc_mem_get(view
->mctx
,
1236 sizeof(dns_namelist_t
) *
1237 DNS_VIEW_DELONLYHASH
);
1238 if (view
->rootexclude
== NULL
)
1239 return (ISC_R_NOMEMORY
);
1240 for (hash
= 0; hash
< DNS_VIEW_DELONLYHASH
; hash
++)
1241 ISC_LIST_INIT(view
->rootexclude
[hash
]);
1243 hash
= dns_name_hash(name
, ISC_FALSE
) % DNS_VIEW_DELONLYHASH
;
1244 new = ISC_LIST_HEAD(view
->rootexclude
[hash
]);
1245 while (new != NULL
&& !dns_name_equal(new, name
))
1246 new = ISC_LIST_NEXT(new, link
);
1248 return (ISC_R_SUCCESS
);
1249 new = isc_mem_get(view
->mctx
, sizeof(*new));
1251 return (ISC_R_NOMEMORY
);
1252 dns_name_init(new, NULL
);
1253 result
= dns_name_dup(name
, view
->mctx
, new);
1254 if (result
== ISC_R_SUCCESS
)
1255 ISC_LIST_APPEND(view
->rootexclude
[hash
], new, link
);
1257 isc_mem_put(view
->mctx
, new, sizeof(*new));
1262 dns_view_isdelegationonly(dns_view_t
*view
, dns_name_t
*name
) {
1266 REQUIRE(DNS_VIEW_VALID(view
));
1268 if (!view
->rootdelonly
&& view
->delonly
== NULL
)
1271 hash
= dns_name_hash(name
, ISC_FALSE
) % DNS_VIEW_DELONLYHASH
;
1272 if (view
->rootdelonly
&& dns_name_countlabels(name
) <= 2) {
1273 if (view
->rootexclude
== NULL
)
1275 new = ISC_LIST_HEAD(view
->rootexclude
[hash
]);
1276 while (new != NULL
&& !dns_name_equal(new, name
))
1277 new = ISC_LIST_NEXT(new, link
);
1282 if (view
->delonly
== NULL
)
1285 new = ISC_LIST_HEAD(view
->delonly
[hash
]);
1286 while (new != NULL
&& !dns_name_equal(new, name
))
1287 new = ISC_LIST_NEXT(new, link
);
1294 dns_view_setrootdelonly(dns_view_t
*view
, isc_boolean_t value
) {
1295 REQUIRE(DNS_VIEW_VALID(view
));
1296 view
->rootdelonly
= value
;
1300 dns_view_getrootdelonly(dns_view_t
*view
) {
1301 REQUIRE(DNS_VIEW_VALID(view
));
1302 return (view
->rootdelonly
);