xref: /netbsd-src/external/mpl/bind/dist/lib/dns/view.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: view.c,v 1.17 2025/01/26 16:25:26 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 /*! \file */
17 
18 #include <inttypes.h>
19 #include <limits.h>
20 #include <stdbool.h>
21 
22 #ifdef HAVE_LMDB
23 #include <lmdb.h>
24 #endif /* ifdef HAVE_LMDB */
25 
26 #include <isc/atomic.h>
27 #include <isc/dir.h>
28 #include <isc/file.h>
29 #include <isc/hash.h>
30 #include <isc/lex.h>
31 #include <isc/md.h>
32 #include <isc/result.h>
33 #include <isc/stats.h>
34 #include <isc/string.h>
35 #include <isc/urcu.h>
36 #include <isc/util.h>
37 
38 #include <dns/acl.h>
39 #include <dns/adb.h>
40 #include <dns/badcache.h>
41 #include <dns/cache.h>
42 #include <dns/db.h>
43 #include <dns/dispatch.h>
44 #include <dns/dlz.h>
45 #include <dns/dns64.h>
46 #include <dns/dnssec.h>
47 #include <dns/forward.h>
48 #include <dns/keytable.h>
49 #include <dns/keyvalues.h>
50 #include <dns/master.h>
51 #include <dns/masterdump.h>
52 #include <dns/nametree.h>
53 #include <dns/nta.h>
54 #include <dns/order.h>
55 #include <dns/peer.h>
56 #include <dns/rbt.h>
57 #include <dns/rdataset.h>
58 #include <dns/request.h>
59 #include <dns/resolver.h>
60 #include <dns/rpz.h>
61 #include <dns/rrl.h>
62 #include <dns/stats.h>
63 #include <dns/time.h>
64 #include <dns/transport.h>
65 #include <dns/tsig.h>
66 #include <dns/view.h>
67 #include <dns/zone.h>
68 #include <dns/zt.h>
69 
70 #define CHECK(op)                            \
71 	do {                                 \
72 		result = (op);               \
73 		if (result != ISC_R_SUCCESS) \
74 			goto cleanup;        \
75 	} while (0)
76 
77 #define DNS_VIEW_DELONLYHASH 111
78 
79 /*%
80  * Default maximum number of chained queries before we give up
81  * to prevent CNAME loops.
82  */
83 #define DEFAULT_MAX_RESTARTS 11
84 
85 /*%
86  * Default EDNS0 buffer size
87  */
88 #define DEFAULT_EDNS_BUFSIZE 1232
89 
90 isc_result_t
91 dns_view_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
92 		dns_dispatchmgr_t *dispatchmgr, dns_rdataclass_t rdclass,
93 		const char *name, dns_view_t **viewp) {
94 	dns_view_t *view = NULL;
95 	isc_result_t result;
96 	char buffer[1024];
97 
98 	REQUIRE(name != NULL);
99 	REQUIRE(viewp != NULL && *viewp == NULL);
100 
101 	result = isc_file_sanitize(NULL, name, "nta", buffer, sizeof(buffer));
102 	if (result != ISC_R_SUCCESS) {
103 		return result;
104 	}
105 
106 	view = isc_mem_get(mctx, sizeof(*view));
107 	*view = (dns_view_t){
108 		.rdclass = rdclass,
109 		.name = isc_mem_strdup(mctx, name),
110 		.nta_file = isc_mem_strdup(mctx, buffer),
111 		.recursion = true,
112 		.enablevalidation = true,
113 		.minimalresponses = dns_minimal_no,
114 		.transfer_format = dns_one_answer,
115 		.msgcompression = true,
116 		.provideixfr = true,
117 		.maxcachettl = 7 * 24 * 3600,
118 		.maxncachettl = 3 * 3600,
119 		.dstport = 53,
120 		.staleanswerttl = 1,
121 		.staleanswersok = dns_stale_answer_conf,
122 		.sendcookie = true,
123 		.synthfromdnssec = true,
124 		.trust_anchor_telemetry = true,
125 		.root_key_sentinel = true,
126 		.udpsize = DEFAULT_EDNS_BUFSIZE,
127 		.max_restarts = DEFAULT_MAX_RESTARTS,
128 	};
129 
130 	isc_refcount_init(&view->references, 1);
131 	isc_refcount_init(&view->weakrefs, 1);
132 
133 	dns_fixedname_init(&view->redirectfixed);
134 
135 	ISC_LIST_INIT(view->dlz_searched);
136 	ISC_LIST_INIT(view->dlz_unsearched);
137 	ISC_LIST_INIT(view->dns64);
138 
139 	ISC_LINK_INIT(view, link);
140 
141 	isc_mem_attach(mctx, &view->mctx);
142 
143 	if (dispatchmgr != NULL) {
144 		dns_dispatchmgr_attach(dispatchmgr, &view->dispatchmgr);
145 	}
146 
147 	isc_mutex_init(&view->lock);
148 
149 	dns_zt_create(mctx, view, &view->zonetable);
150 
151 	dns_fwdtable_create(mctx, view, &view->fwdtable);
152 
153 	dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
154 
155 	view->failcache = dns_badcache_new(view->mctx, loopmgr);
156 
157 	isc_mutex_init(&view->new_zone_lock);
158 
159 	result = dns_order_create(view->mctx, &view->order);
160 	if (result != ISC_R_SUCCESS) {
161 		goto cleanup_new_zone_lock;
162 	}
163 
164 	result = dns_peerlist_new(view->mctx, &view->peers);
165 	if (result != ISC_R_SUCCESS) {
166 		goto cleanup_order;
167 	}
168 
169 	dns_aclenv_create(view->mctx, &view->aclenv);
170 
171 	dns_nametree_create(view->mctx, DNS_NAMETREE_COUNT, "sfd", &view->sfd);
172 
173 	view->magic = DNS_VIEW_MAGIC;
174 	*viewp = view;
175 
176 	return ISC_R_SUCCESS;
177 
178 cleanup_order:
179 	if (view->order != NULL) {
180 		dns_order_detach(&view->order);
181 	}
182 
183 cleanup_new_zone_lock:
184 	isc_mutex_destroy(&view->new_zone_lock);
185 	dns_badcache_destroy(&view->failcache);
186 
187 	if (view->dynamickeys != NULL) {
188 		dns_tsigkeyring_detach(&view->dynamickeys);
189 	}
190 
191 	isc_refcount_decrementz(&view->weakrefs);
192 	isc_refcount_destroy(&view->weakrefs);
193 
194 	isc_refcount_decrementz(&view->references);
195 	isc_refcount_destroy(&view->references);
196 
197 	dns_fwdtable_destroy(&view->fwdtable);
198 	dns_zt_detach(&view->zonetable);
199 
200 	isc_mutex_destroy(&view->lock);
201 
202 	if (view->nta_file != NULL) {
203 		isc_mem_free(mctx, view->nta_file);
204 	}
205 
206 	isc_mem_free(mctx, view->name);
207 	isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
208 
209 	return result;
210 }
211 
212 static void
213 destroy(dns_view_t *view) {
214 	dns_dns64_t *dns64;
215 	dns_dlzdb_t *dlzdb;
216 
217 	REQUIRE(!ISC_LINK_LINKED(view, link));
218 
219 	isc_refcount_destroy(&view->references);
220 	isc_refcount_destroy(&view->weakrefs);
221 
222 	if (view->order != NULL) {
223 		dns_order_detach(&view->order);
224 	}
225 	if (view->peers != NULL) {
226 		dns_peerlist_detach(&view->peers);
227 	}
228 
229 	if (view->dynamickeys != NULL) {
230 		isc_result_t result;
231 		char template[PATH_MAX];
232 		char keyfile[PATH_MAX];
233 		FILE *fp = NULL;
234 
235 		result = isc_file_mktemplate(NULL, template, sizeof(template));
236 		if (result == ISC_R_SUCCESS) {
237 			(void)isc_file_openuniqueprivate(template, &fp);
238 		}
239 		if (fp != NULL) {
240 			result = dns_tsigkeyring_dump(view->dynamickeys, fp);
241 			if (result == ISC_R_SUCCESS) {
242 				if (fclose(fp) == 0) {
243 					result = isc_file_sanitize(
244 						NULL, view->name, "tsigkeys",
245 						keyfile, sizeof(keyfile));
246 					if (result == ISC_R_SUCCESS) {
247 						result = isc_file_rename(
248 							template, keyfile);
249 					}
250 				}
251 				if (result != ISC_R_SUCCESS) {
252 					(void)remove(template);
253 				}
254 			} else {
255 				(void)fclose(fp);
256 				(void)remove(template);
257 			}
258 		}
259 		dns_tsigkeyring_detach(&view->dynamickeys);
260 	}
261 	if (view->transports != NULL) {
262 		dns_transport_list_detach(&view->transports);
263 	}
264 	if (view->statickeys != NULL) {
265 		dns_tsigkeyring_detach(&view->statickeys);
266 	}
267 
268 	/* These must have been detached in dns_view_detach() */
269 	INSIST(view->adb == NULL);
270 	INSIST(view->resolver == NULL);
271 	INSIST(view->requestmgr == NULL);
272 
273 	dns_rrl_view_destroy(view);
274 	if (view->rpzs != NULL) {
275 		dns_rpz_zones_shutdown(view->rpzs);
276 		dns_rpz_zones_detach(&view->rpzs);
277 	}
278 	if (view->catzs != NULL) {
279 		dns_catz_zones_shutdown(view->catzs);
280 		dns_catz_zones_detach(&view->catzs);
281 	}
282 	for (dlzdb = ISC_LIST_HEAD(view->dlz_searched); dlzdb != NULL;
283 	     dlzdb = ISC_LIST_HEAD(view->dlz_searched))
284 	{
285 		ISC_LIST_UNLINK(view->dlz_searched, dlzdb, link);
286 		dns_dlzdestroy(&dlzdb);
287 	}
288 	for (dlzdb = ISC_LIST_HEAD(view->dlz_unsearched); dlzdb != NULL;
289 	     dlzdb = ISC_LIST_HEAD(view->dlz_unsearched))
290 	{
291 		ISC_LIST_UNLINK(view->dlz_unsearched, dlzdb, link);
292 		dns_dlzdestroy(&dlzdb);
293 	}
294 	if (view->hints != NULL) {
295 		dns_db_detach(&view->hints);
296 	}
297 	if (view->cachedb != NULL) {
298 		dns_db_detach(&view->cachedb);
299 	}
300 	if (view->cache != NULL) {
301 		dns_cache_detach(&view->cache);
302 	}
303 	if (view->nocasecompress != NULL) {
304 		dns_acl_detach(&view->nocasecompress);
305 	}
306 	if (view->matchclients != NULL) {
307 		dns_acl_detach(&view->matchclients);
308 	}
309 	if (view->matchdestinations != NULL) {
310 		dns_acl_detach(&view->matchdestinations);
311 	}
312 	if (view->cacheacl != NULL) {
313 		dns_acl_detach(&view->cacheacl);
314 	}
315 	if (view->cacheonacl != NULL) {
316 		dns_acl_detach(&view->cacheonacl);
317 	}
318 	if (view->queryacl != NULL) {
319 		dns_acl_detach(&view->queryacl);
320 	}
321 	if (view->queryonacl != NULL) {
322 		dns_acl_detach(&view->queryonacl);
323 	}
324 	if (view->recursionacl != NULL) {
325 		dns_acl_detach(&view->recursionacl);
326 	}
327 	if (view->recursiononacl != NULL) {
328 		dns_acl_detach(&view->recursiononacl);
329 	}
330 	if (view->sortlist != NULL) {
331 		dns_acl_detach(&view->sortlist);
332 	}
333 	if (view->transferacl != NULL) {
334 		dns_acl_detach(&view->transferacl);
335 	}
336 	if (view->notifyacl != NULL) {
337 		dns_acl_detach(&view->notifyacl);
338 	}
339 	if (view->updateacl != NULL) {
340 		dns_acl_detach(&view->updateacl);
341 	}
342 	if (view->upfwdacl != NULL) {
343 		dns_acl_detach(&view->upfwdacl);
344 	}
345 	if (view->denyansweracl != NULL) {
346 		dns_acl_detach(&view->denyansweracl);
347 	}
348 	if (view->pad_acl != NULL) {
349 		dns_acl_detach(&view->pad_acl);
350 	}
351 	if (view->proxyacl != NULL) {
352 		dns_acl_detach(&view->proxyacl);
353 	}
354 	if (view->proxyonacl != NULL) {
355 		dns_acl_detach(&view->proxyonacl);
356 	}
357 	if (view->answeracl_exclude != NULL) {
358 		dns_nametree_detach(&view->answeracl_exclude);
359 	}
360 	if (view->denyanswernames != NULL) {
361 		dns_nametree_detach(&view->denyanswernames);
362 	}
363 	if (view->answernames_exclude != NULL) {
364 		dns_nametree_detach(&view->answernames_exclude);
365 	}
366 	if (view->sfd != NULL) {
367 		dns_nametree_detach(&view->sfd);
368 	}
369 	if (view->secroots_priv != NULL) {
370 		dns_keytable_detach(&view->secroots_priv);
371 	}
372 	if (view->ntatable_priv != NULL) {
373 		dns_ntatable_detach(&view->ntatable_priv);
374 	}
375 	for (dns64 = ISC_LIST_HEAD(view->dns64); dns64 != NULL;
376 	     dns64 = ISC_LIST_HEAD(view->dns64))
377 	{
378 		dns_dns64_unlink(&view->dns64, dns64);
379 		dns_dns64_destroy(&dns64);
380 	}
381 	if (view->managed_keys != NULL) {
382 		dns_zone_detach(&view->managed_keys);
383 	}
384 	if (view->redirect != NULL) {
385 		dns_zone_detach(&view->redirect);
386 	}
387 #ifdef HAVE_DNSTAP
388 	if (view->dtenv != NULL) {
389 		dns_dt_detach(&view->dtenv);
390 	}
391 #endif /* HAVE_DNSTAP */
392 	dns_view_setnewzones(view, false, NULL, NULL, 0ULL);
393 	if (view->new_zone_file != NULL) {
394 		isc_mem_free(view->mctx, view->new_zone_file);
395 		view->new_zone_file = NULL;
396 	}
397 	if (view->new_zone_dir != NULL) {
398 		isc_mem_free(view->mctx, view->new_zone_dir);
399 		view->new_zone_dir = NULL;
400 	}
401 #ifdef HAVE_LMDB
402 	if (view->new_zone_dbenv != NULL) {
403 		mdb_env_close((MDB_env *)view->new_zone_dbenv);
404 		view->new_zone_dbenv = NULL;
405 	}
406 	if (view->new_zone_db != NULL) {
407 		isc_mem_free(view->mctx, view->new_zone_db);
408 		view->new_zone_db = NULL;
409 	}
410 #endif /* HAVE_LMDB */
411 	dns_fwdtable_destroy(&view->fwdtable);
412 	dns_aclenv_detach(&view->aclenv);
413 	if (view->failcache != NULL) {
414 		dns_badcache_destroy(&view->failcache);
415 	}
416 	isc_mutex_destroy(&view->new_zone_lock);
417 	isc_mutex_destroy(&view->lock);
418 	isc_refcount_destroy(&view->references);
419 	isc_refcount_destroy(&view->weakrefs);
420 	isc_mem_free(view->mctx, view->nta_file);
421 	isc_mem_free(view->mctx, view->name);
422 	if (view->hooktable != NULL && view->hooktable_free != NULL) {
423 		view->hooktable_free(view->mctx, &view->hooktable);
424 	}
425 	if (view->plugins != NULL && view->plugins_free != NULL) {
426 		view->plugins_free(view->mctx, &view->plugins);
427 	}
428 	isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
429 }
430 
431 void
432 dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
433 	REQUIRE(DNS_VIEW_VALID(source));
434 	REQUIRE(targetp != NULL && *targetp == NULL);
435 
436 	isc_refcount_increment(&source->references);
437 
438 	*targetp = source;
439 }
440 
441 void
442 dns_view_detach(dns_view_t **viewp) {
443 	dns_view_t *view = NULL;
444 
445 	REQUIRE(viewp != NULL && DNS_VIEW_VALID(*viewp));
446 
447 	view = *viewp;
448 	*viewp = NULL;
449 
450 	if (isc_refcount_decrement(&view->references) == 1) {
451 		dns_zone_t *mkzone = NULL, *rdzone = NULL;
452 		dns_zt_t *zonetable = NULL;
453 		dns_resolver_t *resolver = NULL;
454 		dns_adb_t *adb = NULL;
455 		dns_requestmgr_t *requestmgr = NULL;
456 		dns_dispatchmgr_t *dispatchmgr = NULL;
457 
458 		isc_refcount_destroy(&view->references);
459 
460 		/* Shutdown the attached objects first */
461 		if (view->resolver != NULL) {
462 			dns_resolver_shutdown(view->resolver);
463 		}
464 
465 		rcu_read_lock();
466 		adb = rcu_dereference(view->adb);
467 		if (adb != NULL) {
468 			dns_adb_shutdown(adb);
469 		}
470 		rcu_read_unlock();
471 
472 		if (view->requestmgr != NULL) {
473 			dns_requestmgr_shutdown(view->requestmgr);
474 		}
475 
476 		/* Swap the pointers under the lock */
477 		LOCK(&view->lock);
478 
479 		if (view->resolver != NULL) {
480 			resolver = view->resolver;
481 			view->resolver = NULL;
482 		}
483 
484 		rcu_read_lock();
485 		zonetable = rcu_xchg_pointer(&view->zonetable, NULL);
486 		if (zonetable != NULL) {
487 			if (view->flush) {
488 				dns_zt_flush(zonetable);
489 			}
490 		}
491 		adb = rcu_xchg_pointer(&view->adb, NULL);
492 		dispatchmgr = rcu_xchg_pointer(&view->dispatchmgr, NULL);
493 		rcu_read_unlock();
494 
495 		if (view->requestmgr != NULL) {
496 			requestmgr = view->requestmgr;
497 			view->requestmgr = NULL;
498 		}
499 		if (view->managed_keys != NULL) {
500 			mkzone = view->managed_keys;
501 			view->managed_keys = NULL;
502 			if (view->flush) {
503 				dns_zone_flush(mkzone);
504 			}
505 		}
506 		if (view->redirect != NULL) {
507 			rdzone = view->redirect;
508 			view->redirect = NULL;
509 			if (view->flush) {
510 				dns_zone_flush(rdzone);
511 			}
512 		}
513 		if (view->catzs != NULL) {
514 			dns_catz_zones_shutdown(view->catzs);
515 			dns_catz_zones_detach(&view->catzs);
516 		}
517 		if (view->ntatable_priv != NULL) {
518 			dns_ntatable_shutdown(view->ntatable_priv);
519 		}
520 		UNLOCK(&view->lock);
521 
522 		/* Detach outside view lock */
523 		if (resolver != NULL) {
524 			dns_resolver_detach(&resolver);
525 		}
526 		synchronize_rcu();
527 		if (dispatchmgr != NULL) {
528 			dns_dispatchmgr_detach(&dispatchmgr);
529 		}
530 		if (adb != NULL) {
531 			dns_adb_detach(&adb);
532 		}
533 		if (zonetable != NULL) {
534 			dns_zt_detach(&zonetable);
535 		}
536 		if (requestmgr != NULL) {
537 			dns_requestmgr_detach(&requestmgr);
538 		}
539 		if (mkzone != NULL) {
540 			dns_zone_detach(&mkzone);
541 		}
542 		if (rdzone != NULL) {
543 			dns_zone_detach(&rdzone);
544 		}
545 
546 		dns_view_weakdetach(&view);
547 	}
548 }
549 
550 static isc_result_t
551 dialup(dns_zone_t *zone, void *dummy) {
552 	UNUSED(dummy);
553 	dns_zone_dialup(zone);
554 	return ISC_R_SUCCESS;
555 }
556 
557 void
558 dns_view_dialup(dns_view_t *view) {
559 	dns_zt_t *zonetable = NULL;
560 
561 	REQUIRE(DNS_VIEW_VALID(view));
562 
563 	rcu_read_lock();
564 	zonetable = rcu_dereference(view->zonetable);
565 	if (zonetable != NULL) {
566 		(void)dns_zt_apply(zonetable, false, NULL, dialup, NULL);
567 	}
568 	rcu_read_unlock();
569 }
570 
571 void
572 dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) {
573 	REQUIRE(DNS_VIEW_VALID(source));
574 	REQUIRE(targetp != NULL && *targetp == NULL);
575 
576 	isc_refcount_increment(&source->weakrefs);
577 
578 	*targetp = source;
579 }
580 
581 void
582 dns_view_weakdetach(dns_view_t **viewp) {
583 	dns_view_t *view = NULL;
584 
585 	REQUIRE(viewp != NULL);
586 
587 	view = *viewp;
588 	*viewp = NULL;
589 
590 	REQUIRE(DNS_VIEW_VALID(view));
591 
592 	if (isc_refcount_decrement(&view->weakrefs) == 1) {
593 		destroy(view);
594 	}
595 }
596 
597 isc_result_t
598 dns_view_createresolver(dns_view_t *view, isc_nm_t *netmgr,
599 			unsigned int options, isc_tlsctx_cache_t *tlsctx_cache,
600 			dns_dispatch_t *dispatchv4,
601 			dns_dispatch_t *dispatchv6) {
602 	isc_result_t result;
603 	isc_mem_t *mctx = NULL;
604 	isc_loopmgr_t *loopmgr = isc_loop_getloopmgr(isc_loop());
605 
606 	REQUIRE(DNS_VIEW_VALID(view));
607 	REQUIRE(!view->frozen);
608 	REQUIRE(view->resolver == NULL);
609 	REQUIRE(view->dispatchmgr != NULL);
610 
611 	result = dns_resolver_create(view, loopmgr, netmgr, options,
612 				     tlsctx_cache, dispatchv4, dispatchv6,
613 				     &view->resolver);
614 	if (result != ISC_R_SUCCESS) {
615 		return result;
616 	}
617 
618 	isc_mem_create(&mctx);
619 	isc_mem_setname(mctx, "ADB");
620 	dns_adb_create(mctx, view, &view->adb);
621 	isc_mem_detach(&mctx);
622 
623 	result = dns_requestmgr_create(view->mctx, loopmgr, view->dispatchmgr,
624 				       dispatchv4, dispatchv6,
625 				       &view->requestmgr);
626 	if (result != ISC_R_SUCCESS) {
627 		goto cleanup_adb;
628 	}
629 
630 	return ISC_R_SUCCESS;
631 
632 cleanup_adb:
633 	dns_adb_shutdown(view->adb);
634 	dns_adb_detach(&view->adb);
635 
636 	dns_resolver_shutdown(view->resolver);
637 	dns_resolver_detach(&view->resolver);
638 
639 	return result;
640 }
641 
642 void
643 dns_view_setcache(dns_view_t *view, dns_cache_t *cache, bool shared) {
644 	REQUIRE(DNS_VIEW_VALID(view));
645 	REQUIRE(!view->frozen);
646 
647 	view->cacheshared = shared;
648 	if (view->cache != NULL) {
649 		dns_db_detach(&view->cachedb);
650 		dns_cache_detach(&view->cache);
651 	}
652 	dns_cache_attach(cache, &view->cache);
653 	dns_cache_attachdb(cache, &view->cachedb);
654 	INSIST(DNS_DB_VALID(view->cachedb));
655 
656 	dns_cache_setmaxrrperset(view->cache, view->maxrrperset);
657 	dns_cache_setmaxtypepername(view->cache, view->maxtypepername);
658 }
659 
660 bool
661 dns_view_iscacheshared(dns_view_t *view) {
662 	REQUIRE(DNS_VIEW_VALID(view));
663 
664 	return view->cacheshared;
665 }
666 
667 void
668 dns_view_sethints(dns_view_t *view, dns_db_t *hints) {
669 	REQUIRE(DNS_VIEW_VALID(view));
670 	REQUIRE(!view->frozen);
671 	REQUIRE(view->hints == NULL);
672 	REQUIRE(dns_db_iszone(hints));
673 
674 	dns_db_attach(hints, &view->hints);
675 }
676 
677 void
678 dns_view_settransports(dns_view_t *view, dns_transport_list_t *list) {
679 	REQUIRE(DNS_VIEW_VALID(view));
680 	REQUIRE(list != NULL);
681 	if (view->transports != NULL) {
682 		dns_transport_list_detach(&view->transports);
683 	}
684 	dns_transport_list_attach(list, &view->transports);
685 }
686 
687 void
688 dns_view_setkeyring(dns_view_t *view, dns_tsigkeyring_t *ring) {
689 	REQUIRE(DNS_VIEW_VALID(view));
690 	REQUIRE(ring != NULL);
691 	if (view->statickeys != NULL) {
692 		dns_tsigkeyring_detach(&view->statickeys);
693 	}
694 	dns_tsigkeyring_attach(ring, &view->statickeys);
695 }
696 
697 void
698 dns_view_setdynamickeyring(dns_view_t *view, dns_tsigkeyring_t *ring) {
699 	REQUIRE(DNS_VIEW_VALID(view));
700 	REQUIRE(ring != NULL);
701 	if (view->dynamickeys != NULL) {
702 		dns_tsigkeyring_detach(&view->dynamickeys);
703 	}
704 	dns_tsigkeyring_attach(ring, &view->dynamickeys);
705 }
706 
707 void
708 dns_view_getdynamickeyring(dns_view_t *view, dns_tsigkeyring_t **ringp) {
709 	REQUIRE(DNS_VIEW_VALID(view));
710 	REQUIRE(ringp != NULL && *ringp == NULL);
711 	if (view->dynamickeys != NULL) {
712 		dns_tsigkeyring_attach(view->dynamickeys, ringp);
713 	}
714 }
715 
716 void
717 dns_view_restorekeyring(dns_view_t *view) {
718 	FILE *fp;
719 	char keyfile[PATH_MAX];
720 	isc_result_t result;
721 
722 	REQUIRE(DNS_VIEW_VALID(view));
723 
724 	if (view->dynamickeys != NULL) {
725 		result = isc_file_sanitize(NULL, view->name, "tsigkeys",
726 					   keyfile, sizeof(keyfile));
727 		if (result == ISC_R_SUCCESS) {
728 			fp = fopen(keyfile, "r");
729 			if (fp != NULL) {
730 				dns_tsigkeyring_restore(view->dynamickeys, fp);
731 				(void)fclose(fp);
732 			}
733 		}
734 	}
735 }
736 
737 void
738 dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
739 	REQUIRE(DNS_VIEW_VALID(view));
740 	view->dstport = dstport;
741 }
742 
743 void
744 dns_view_freeze(dns_view_t *view) {
745 	REQUIRE(DNS_VIEW_VALID(view));
746 	REQUIRE(!view->frozen);
747 
748 	if (view->resolver != NULL) {
749 		INSIST(view->cachedb != NULL);
750 		dns_resolver_freeze(view->resolver);
751 	}
752 	view->frozen = true;
753 }
754 
755 void
756 dns_view_thaw(dns_view_t *view) {
757 	REQUIRE(DNS_VIEW_VALID(view));
758 	REQUIRE(view->frozen);
759 
760 	view->frozen = false;
761 }
762 
763 isc_result_t
764 dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
765 	isc_result_t result;
766 	dns_zt_t *zonetable = NULL;
767 
768 	REQUIRE(DNS_VIEW_VALID(view));
769 	REQUIRE(!view->frozen);
770 
771 	rcu_read_lock();
772 	zonetable = rcu_dereference(view->zonetable);
773 	if (zonetable != NULL) {
774 		result = dns_zt_mount(zonetable, zone);
775 	} else {
776 		result = ISC_R_SHUTTINGDOWN;
777 	}
778 	rcu_read_unlock();
779 
780 	return result;
781 }
782 
783 isc_result_t
784 dns_view_delzone(dns_view_t *view, dns_zone_t *zone) {
785 	isc_result_t result;
786 	dns_zt_t *zonetable = NULL;
787 
788 	REQUIRE(DNS_VIEW_VALID(view));
789 
790 	rcu_read_lock();
791 	zonetable = rcu_dereference(view->zonetable);
792 	if (zonetable != NULL) {
793 		result = dns_zt_unmount(zonetable, zone);
794 	} else {
795 		result = ISC_R_SUCCESS;
796 	}
797 	rcu_read_unlock();
798 
799 	return result;
800 }
801 
802 isc_result_t
803 dns_view_findzone(dns_view_t *view, const dns_name_t *name,
804 		  unsigned int options, dns_zone_t **zonep) {
805 	isc_result_t result;
806 	dns_zt_t *zonetable = NULL;
807 
808 	REQUIRE(DNS_VIEW_VALID(view));
809 
810 	rcu_read_lock();
811 	zonetable = rcu_dereference(view->zonetable);
812 	if (zonetable != NULL) {
813 		result = dns_zt_find(zonetable, name, options, zonep);
814 	} else {
815 		result = ISC_R_NOTFOUND;
816 	}
817 	rcu_read_unlock();
818 
819 	return result;
820 }
821 
822 isc_result_t
823 dns_view_find(dns_view_t *view, const dns_name_t *name, dns_rdatatype_t type,
824 	      isc_stdtime_t now, unsigned int options, bool use_hints,
825 	      bool use_static_stub, dns_db_t **dbp, dns_dbnode_t **nodep,
826 	      dns_name_t *foundname, dns_rdataset_t *rdataset,
827 	      dns_rdataset_t *sigrdataset) {
828 	isc_result_t result;
829 	dns_db_t *db = NULL, *zdb = NULL;
830 	dns_dbnode_t *node = NULL, *znode = NULL;
831 	bool is_cache, is_staticstub_zone;
832 	dns_rdataset_t zrdataset, zsigrdataset;
833 	dns_zone_t *zone = NULL;
834 	dns_zt_t *zonetable = NULL;
835 
836 	/*
837 	 * Find an rdataset whose owner name is 'name', and whose type is
838 	 * 'type'.
839 	 */
840 
841 	REQUIRE(DNS_VIEW_VALID(view));
842 	REQUIRE(view->frozen);
843 	REQUIRE(type != dns_rdatatype_rrsig);
844 	REQUIRE(rdataset != NULL); /* XXXBEW - remove this */
845 	REQUIRE(nodep == NULL || *nodep == NULL);
846 
847 	/*
848 	 * Initialize.
849 	 */
850 	dns_rdataset_init(&zrdataset);
851 	dns_rdataset_init(&zsigrdataset);
852 
853 	/*
854 	 * Find a database to answer the query.
855 	 */
856 	is_staticstub_zone = false;
857 	rcu_read_lock();
858 	zonetable = rcu_dereference(view->zonetable);
859 	if (zonetable != NULL) {
860 		result = dns_zt_find(zonetable, name, DNS_ZTFIND_MIRROR, &zone);
861 	} else {
862 		result = ISC_R_SHUTTINGDOWN;
863 	}
864 	rcu_read_unlock();
865 	if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub &&
866 	    !use_static_stub)
867 	{
868 		result = ISC_R_NOTFOUND;
869 	}
870 	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
871 		result = dns_zone_getdb(zone, &db);
872 		if (result != ISC_R_SUCCESS && view->cachedb != NULL) {
873 			dns_db_attach(view->cachedb, &db);
874 		} else if (result != ISC_R_SUCCESS) {
875 			goto cleanup;
876 		}
877 		if (dns_zone_gettype(zone) == dns_zone_staticstub &&
878 		    dns_name_equal(name, dns_zone_getorigin(zone)))
879 		{
880 			is_staticstub_zone = true;
881 		}
882 	} else if (result == ISC_R_NOTFOUND && view->cachedb != NULL) {
883 		dns_db_attach(view->cachedb, &db);
884 	} else {
885 		goto cleanup;
886 	}
887 
888 	is_cache = dns_db_iscache(db);
889 
890 db_find:
891 	/*
892 	 * Now look for an answer in the database.
893 	 */
894 	result = dns_db_find(db, name, NULL, type, options, now, &node,
895 			     foundname, rdataset, sigrdataset);
896 
897 	if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) {
898 		if (dns_rdataset_isassociated(rdataset)) {
899 			dns_rdataset_disassociate(rdataset);
900 		}
901 		if (sigrdataset != NULL &&
902 		    dns_rdataset_isassociated(sigrdataset))
903 		{
904 			dns_rdataset_disassociate(sigrdataset);
905 		}
906 		if (node != NULL) {
907 			dns_db_detachnode(db, &node);
908 		}
909 		if (!is_cache) {
910 			dns_db_detach(&db);
911 			if (view->cachedb != NULL && !is_staticstub_zone) {
912 				/*
913 				 * Either the answer is in the cache, or we
914 				 * don't know it.
915 				 * Note that if the result comes from a
916 				 * static-stub zone we stop the search here
917 				 * (see the function description in view.h).
918 				 */
919 				is_cache = true;
920 				dns_db_attach(view->cachedb, &db);
921 				goto db_find;
922 			}
923 		} else {
924 			/*
925 			 * We don't have the data in the cache.  If we've got
926 			 * glue from the zone, use it.
927 			 */
928 			if (dns_rdataset_isassociated(&zrdataset)) {
929 				dns_rdataset_clone(&zrdataset, rdataset);
930 				if (sigrdataset != NULL &&
931 				    dns_rdataset_isassociated(&zsigrdataset))
932 				{
933 					dns_rdataset_clone(&zsigrdataset,
934 							   sigrdataset);
935 				}
936 				result = DNS_R_GLUE;
937 				if (db != NULL) {
938 					dns_db_detach(&db);
939 				}
940 				dns_db_attach(zdb, &db);
941 				dns_db_attachnode(db, znode, &node);
942 				goto cleanup;
943 			}
944 		}
945 		/*
946 		 * We don't know the answer.
947 		 */
948 		result = ISC_R_NOTFOUND;
949 	} else if (result == DNS_R_GLUE) {
950 		/*
951 		 * Glue is the answer wanted.
952 		 */
953 		result = ISC_R_SUCCESS;
954 	}
955 
956 	if (result == ISC_R_NOTFOUND && !is_staticstub_zone && use_hints &&
957 	    view->hints != NULL)
958 	{
959 		if (dns_rdataset_isassociated(rdataset)) {
960 			dns_rdataset_disassociate(rdataset);
961 		}
962 		if (sigrdataset != NULL &&
963 		    dns_rdataset_isassociated(sigrdataset))
964 		{
965 			dns_rdataset_disassociate(sigrdataset);
966 		}
967 		if (db != NULL) {
968 			if (node != NULL) {
969 				dns_db_detachnode(db, &node);
970 			}
971 			dns_db_detach(&db);
972 		}
973 		result = dns_db_find(view->hints, name, NULL, type, options,
974 				     now, &node, foundname, rdataset,
975 				     sigrdataset);
976 		if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) {
977 			/*
978 			 * We just used a hint.  Let the resolver know it
979 			 * should consider priming.
980 			 */
981 			dns_resolver_t *res = NULL;
982 			result = dns_view_getresolver(view, &res);
983 			if (result == ISC_R_SUCCESS) {
984 				dns_resolver_prime(res);
985 				dns_db_attach(view->hints, &db);
986 				dns_resolver_detach(&res);
987 				result = DNS_R_HINT;
988 			}
989 		} else if (result == DNS_R_NXRRSET) {
990 			dns_db_attach(view->hints, &db);
991 			result = DNS_R_HINTNXRRSET;
992 		} else if (result == DNS_R_NXDOMAIN) {
993 			result = ISC_R_NOTFOUND;
994 		}
995 
996 		/*
997 		 * Cleanup if non-standard hints are used.
998 		 */
999 		if (db == NULL && node != NULL) {
1000 			dns_db_detachnode(view->hints, &node);
1001 		}
1002 	}
1003 
1004 cleanup:
1005 	if (dns_rdataset_isassociated(&zrdataset)) {
1006 		dns_rdataset_disassociate(&zrdataset);
1007 		if (dns_rdataset_isassociated(&zsigrdataset)) {
1008 			dns_rdataset_disassociate(&zsigrdataset);
1009 		}
1010 	}
1011 
1012 	if (zdb != NULL) {
1013 		if (znode != NULL) {
1014 			dns_db_detachnode(zdb, &znode);
1015 		}
1016 		dns_db_detach(&zdb);
1017 	}
1018 
1019 	if (db != NULL) {
1020 		if (node != NULL) {
1021 			if (nodep != NULL) {
1022 				*nodep = node;
1023 			} else {
1024 				dns_db_detachnode(db, &node);
1025 			}
1026 		}
1027 		if (dbp != NULL) {
1028 			*dbp = db;
1029 		} else {
1030 			dns_db_detach(&db);
1031 		}
1032 	} else {
1033 		INSIST(node == NULL);
1034 	}
1035 
1036 	if (zone != NULL) {
1037 		dns_zone_detach(&zone);
1038 	}
1039 
1040 	return result;
1041 }
1042 
1043 isc_result_t
1044 dns_view_simplefind(dns_view_t *view, const dns_name_t *name,
1045 		    dns_rdatatype_t type, isc_stdtime_t now,
1046 		    unsigned int options, bool use_hints,
1047 		    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
1048 	isc_result_t result;
1049 	dns_fixedname_t foundname;
1050 
1051 	dns_fixedname_init(&foundname);
1052 	result = dns_view_find(view, name, type, now, options, use_hints, false,
1053 			       NULL, NULL, dns_fixedname_name(&foundname),
1054 			       rdataset, sigrdataset);
1055 	if (result == DNS_R_NXDOMAIN) {
1056 		/*
1057 		 * The rdataset and sigrdataset of the relevant NSEC record
1058 		 * may be returned, but the caller cannot use them because
1059 		 * foundname is not returned by this simplified API.  We
1060 		 * disassociate them here to prevent any misuse by the caller.
1061 		 */
1062 		if (dns_rdataset_isassociated(rdataset)) {
1063 			dns_rdataset_disassociate(rdataset);
1064 		}
1065 		if (sigrdataset != NULL &&
1066 		    dns_rdataset_isassociated(sigrdataset))
1067 		{
1068 			dns_rdataset_disassociate(sigrdataset);
1069 		}
1070 	} else if (result != ISC_R_SUCCESS && result != DNS_R_GLUE &&
1071 		   result != DNS_R_HINT && result != DNS_R_NCACHENXDOMAIN &&
1072 		   result != DNS_R_NCACHENXRRSET && result != DNS_R_NXRRSET &&
1073 		   result != DNS_R_HINTNXRRSET && result != ISC_R_NOTFOUND)
1074 	{
1075 		if (dns_rdataset_isassociated(rdataset)) {
1076 			dns_rdataset_disassociate(rdataset);
1077 		}
1078 		if (sigrdataset != NULL &&
1079 		    dns_rdataset_isassociated(sigrdataset))
1080 		{
1081 			dns_rdataset_disassociate(sigrdataset);
1082 		}
1083 		result = ISC_R_NOTFOUND;
1084 	}
1085 
1086 	return result;
1087 }
1088 
1089 isc_result_t
1090 dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
1091 		     dns_name_t *fname, dns_name_t *dcname, isc_stdtime_t now,
1092 		     unsigned int options, bool use_hints, bool use_cache,
1093 		     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
1094 	isc_result_t result;
1095 	dns_db_t *db = NULL;
1096 	bool is_cache, use_zone = false, try_hints = false;
1097 	dns_zone_t *zone = NULL;
1098 	dns_name_t *zfname = NULL;
1099 	dns_zt_t *zonetable = NULL;
1100 	dns_rdataset_t zrdataset, zsigrdataset;
1101 	dns_fixedname_t zfixedname;
1102 	unsigned int ztoptions = DNS_ZTFIND_MIRROR;
1103 
1104 	REQUIRE(DNS_VIEW_VALID(view));
1105 	REQUIRE(view->frozen);
1106 
1107 	/*
1108 	 * Initialize.
1109 	 */
1110 	dns_fixedname_init(&zfixedname);
1111 	dns_rdataset_init(&zrdataset);
1112 	dns_rdataset_init(&zsigrdataset);
1113 
1114 	/*
1115 	 * Find the right database.
1116 	 */
1117 	if ((options & DNS_DBFIND_NOEXACT) != 0) {
1118 		ztoptions |= DNS_ZTFIND_NOEXACT;
1119 	}
1120 	rcu_read_lock();
1121 	zonetable = rcu_dereference(view->zonetable);
1122 	if (zonetable != NULL) {
1123 		result = dns_zt_find(zonetable, name, ztoptions, &zone);
1124 	} else {
1125 		result = ISC_R_SHUTTINGDOWN;
1126 	}
1127 	rcu_read_unlock();
1128 	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
1129 		result = dns_zone_getdb(zone, &db);
1130 	}
1131 	if (result == ISC_R_NOTFOUND) {
1132 		/*
1133 		 * We're not directly authoritative for this query name, nor
1134 		 * is it a subdomain of any zone for which we're
1135 		 * authoritative.
1136 		 */
1137 		if (use_cache && view->cachedb != NULL) {
1138 			/*
1139 			 * We have a cache; try it.
1140 			 */
1141 			dns_db_attach(view->cachedb, &db);
1142 		} else if (use_hints && view->hints != NULL) {
1143 			/*
1144 			 * Maybe we have hints...
1145 			 */
1146 			try_hints = true;
1147 			goto finish;
1148 		} else {
1149 			result = DNS_R_NXDOMAIN;
1150 			goto cleanup;
1151 		}
1152 	} else if (result != ISC_R_SUCCESS) {
1153 		/*
1154 		 * Something is broken.
1155 		 */
1156 		goto cleanup;
1157 	}
1158 	is_cache = dns_db_iscache(db);
1159 
1160 db_find:
1161 	/*
1162 	 * Look for the zonecut.
1163 	 */
1164 	if (!is_cache) {
1165 		result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options,
1166 				     now, NULL, fname, rdataset, sigrdataset);
1167 		if (result == DNS_R_DELEGATION) {
1168 			result = ISC_R_SUCCESS;
1169 		} else if (result != ISC_R_SUCCESS) {
1170 			goto cleanup;
1171 		}
1172 
1173 		/*
1174 		 * Tag static stub NS RRset so that when we look for
1175 		 * addresses we use the configured server addresses.
1176 		 */
1177 		if (dns_zone_gettype(zone) == dns_zone_staticstub) {
1178 			rdataset->attributes |= DNS_RDATASETATTR_STATICSTUB;
1179 		}
1180 
1181 		if (use_cache && view->cachedb != NULL && db != view->hints) {
1182 			/*
1183 			 * We found an answer, but the cache may be better.
1184 			 */
1185 			zfname = dns_fixedname_name(&zfixedname);
1186 			dns_name_copy(fname, zfname);
1187 			dns_rdataset_clone(rdataset, &zrdataset);
1188 			dns_rdataset_disassociate(rdataset);
1189 			if (sigrdataset != NULL &&
1190 			    dns_rdataset_isassociated(sigrdataset))
1191 			{
1192 				dns_rdataset_clone(sigrdataset, &zsigrdataset);
1193 				dns_rdataset_disassociate(sigrdataset);
1194 			}
1195 			dns_db_detach(&db);
1196 			dns_db_attach(view->cachedb, &db);
1197 			is_cache = true;
1198 			goto db_find;
1199 		}
1200 	} else {
1201 		result = dns_db_findzonecut(db, name, options, now, NULL, fname,
1202 					    dcname, rdataset, sigrdataset);
1203 		if (result == ISC_R_SUCCESS) {
1204 			if (zfname != NULL &&
1205 			    (!dns_name_issubdomain(fname, zfname) ||
1206 			     (dns_zone_gettype(zone) == dns_zone_staticstub &&
1207 			      dns_name_equal(fname, zfname))))
1208 			{
1209 				/*
1210 				 * We found a zonecut in the cache, but our
1211 				 * zone delegation is better.
1212 				 */
1213 				use_zone = true;
1214 			}
1215 		} else if (result == ISC_R_NOTFOUND) {
1216 			if (zfname != NULL) {
1217 				/*
1218 				 * We didn't find anything in the cache, but we
1219 				 * have a zone delegation, so use it.
1220 				 */
1221 				use_zone = true;
1222 				result = ISC_R_SUCCESS;
1223 			} else if (use_hints && view->hints != NULL) {
1224 				/*
1225 				 * Maybe we have hints...
1226 				 */
1227 				try_hints = true;
1228 				result = ISC_R_SUCCESS;
1229 			} else {
1230 				result = DNS_R_NXDOMAIN;
1231 			}
1232 		} else {
1233 			/*
1234 			 * Something bad happened.
1235 			 */
1236 			goto cleanup;
1237 		}
1238 	}
1239 
1240 finish:
1241 	if (use_zone) {
1242 		if (dns_rdataset_isassociated(rdataset)) {
1243 			dns_rdataset_disassociate(rdataset);
1244 			if (sigrdataset != NULL &&
1245 			    dns_rdataset_isassociated(sigrdataset))
1246 			{
1247 				dns_rdataset_disassociate(sigrdataset);
1248 			}
1249 		}
1250 		dns_name_copy(zfname, fname);
1251 		if (dcname != NULL) {
1252 			dns_name_copy(zfname, dcname);
1253 		}
1254 		dns_rdataset_clone(&zrdataset, rdataset);
1255 		if (sigrdataset != NULL &&
1256 		    dns_rdataset_isassociated(&zrdataset))
1257 		{
1258 			dns_rdataset_clone(&zsigrdataset, sigrdataset);
1259 		}
1260 	} else if (try_hints) {
1261 		/*
1262 		 * We've found nothing so far, but we have hints.
1263 		 */
1264 		result = dns_db_find(view->hints, dns_rootname, NULL,
1265 				     dns_rdatatype_ns, 0, now, NULL, fname,
1266 				     rdataset, NULL);
1267 		if (result != ISC_R_SUCCESS) {
1268 			/*
1269 			 * We can't even find the hints for the root
1270 			 * nameservers!
1271 			 */
1272 			if (dns_rdataset_isassociated(rdataset)) {
1273 				dns_rdataset_disassociate(rdataset);
1274 			}
1275 			result = ISC_R_NOTFOUND;
1276 		} else if (dcname != NULL) {
1277 			dns_name_copy(fname, dcname);
1278 		}
1279 	}
1280 
1281 cleanup:
1282 	if (dns_rdataset_isassociated(&zrdataset)) {
1283 		dns_rdataset_disassociate(&zrdataset);
1284 		if (dns_rdataset_isassociated(&zsigrdataset)) {
1285 			dns_rdataset_disassociate(&zsigrdataset);
1286 		}
1287 	}
1288 	if (db != NULL) {
1289 		dns_db_detach(&db);
1290 	}
1291 	if (zone != NULL) {
1292 		dns_zone_detach(&zone);
1293 	}
1294 
1295 	return result;
1296 }
1297 
1298 isc_result_t
1299 dns_viewlist_find(dns_viewlist_t *list, const char *name,
1300 		  dns_rdataclass_t rdclass, dns_view_t **viewp) {
1301 	dns_view_t *view;
1302 
1303 	REQUIRE(list != NULL);
1304 
1305 	for (view = ISC_LIST_HEAD(*list); view != NULL;
1306 	     view = ISC_LIST_NEXT(view, link))
1307 	{
1308 		if (strcmp(view->name, name) == 0 && view->rdclass == rdclass) {
1309 			break;
1310 		}
1311 	}
1312 	if (view == NULL) {
1313 		return ISC_R_NOTFOUND;
1314 	}
1315 
1316 	dns_view_attach(view, viewp);
1317 
1318 	return ISC_R_SUCCESS;
1319 }
1320 
1321 isc_result_t
1322 dns_viewlist_findzone(dns_viewlist_t *list, const dns_name_t *name,
1323 		      bool allclasses, dns_rdataclass_t rdclass,
1324 		      dns_zone_t **zonep) {
1325 	dns_view_t *view;
1326 	isc_result_t result;
1327 	dns_zone_t *zone1 = NULL, *zone2 = NULL;
1328 
1329 	REQUIRE(list != NULL);
1330 	REQUIRE(zonep != NULL && *zonep == NULL);
1331 
1332 	for (view = ISC_LIST_HEAD(*list); view != NULL;
1333 	     view = ISC_LIST_NEXT(view, link))
1334 	{
1335 		dns_zt_t *zonetable = NULL;
1336 		if (!allclasses && view->rdclass != rdclass) {
1337 			continue;
1338 		}
1339 		rcu_read_lock();
1340 		zonetable = rcu_dereference(view->zonetable);
1341 		if (zonetable != NULL) {
1342 			result = dns_zt_find(zonetable, name, DNS_ZTFIND_EXACT,
1343 					     (zone1 == NULL) ? &zone1 : &zone2);
1344 		} else {
1345 			result = ISC_R_NOTFOUND;
1346 		}
1347 		rcu_read_unlock();
1348 		INSIST(result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND);
1349 		if (zone2 != NULL) {
1350 			dns_zone_detach(&zone1);
1351 			dns_zone_detach(&zone2);
1352 			return ISC_R_MULTIPLE;
1353 		}
1354 	}
1355 
1356 	if (zone1 != NULL) {
1357 		dns_zone_attach(zone1, zonep);
1358 		dns_zone_detach(&zone1);
1359 		return ISC_R_SUCCESS;
1360 	}
1361 
1362 	return ISC_R_NOTFOUND;
1363 }
1364 
1365 isc_result_t
1366 dns_view_load(dns_view_t *view, bool stop, bool newonly) {
1367 	isc_result_t result;
1368 	dns_zt_t *zonetable = NULL;
1369 
1370 	REQUIRE(DNS_VIEW_VALID(view));
1371 
1372 	rcu_read_lock();
1373 	zonetable = rcu_dereference(view->zonetable);
1374 	if (zonetable != NULL) {
1375 		result = dns_zt_load(zonetable, stop, newonly);
1376 	} else {
1377 		result = ISC_R_SUCCESS;
1378 	}
1379 	rcu_read_unlock();
1380 	return result;
1381 }
1382 
1383 isc_result_t
1384 dns_view_asyncload(dns_view_t *view, bool newonly, dns_zt_callback_t *callback,
1385 		   void *arg) {
1386 	isc_result_t result;
1387 	dns_zt_t *zonetable = NULL;
1388 
1389 	REQUIRE(DNS_VIEW_VALID(view));
1390 
1391 	rcu_read_lock();
1392 	zonetable = rcu_dereference(view->zonetable);
1393 	if (zonetable != NULL) {
1394 		result = dns_zt_asyncload(zonetable, newonly, callback, arg);
1395 	} else {
1396 		result = ISC_R_SUCCESS;
1397 	}
1398 	rcu_read_unlock();
1399 	return result;
1400 }
1401 
1402 isc_result_t
1403 dns_view_gettsig(dns_view_t *view, const dns_name_t *keyname,
1404 		 dns_tsigkey_t **keyp) {
1405 	isc_result_t result;
1406 	REQUIRE(keyp != NULL && *keyp == NULL);
1407 
1408 	result = dns_tsigkey_find(keyp, keyname, NULL, view->statickeys);
1409 	if (result == ISC_R_NOTFOUND) {
1410 		result = dns_tsigkey_find(keyp, keyname, NULL,
1411 					  view->dynamickeys);
1412 	}
1413 	return result;
1414 }
1415 
1416 isc_result_t
1417 dns_view_gettransport(dns_view_t *view, const dns_transport_type_t type,
1418 		      const dns_name_t *name, dns_transport_t **transportp) {
1419 	REQUIRE(DNS_VIEW_VALID(view));
1420 	REQUIRE(transportp != NULL && *transportp == NULL);
1421 
1422 	dns_transport_t *transport = dns_transport_find(type, name,
1423 							view->transports);
1424 	if (transport == NULL) {
1425 		return ISC_R_NOTFOUND;
1426 	}
1427 
1428 	*transportp = transport;
1429 	return ISC_R_SUCCESS;
1430 }
1431 
1432 isc_result_t
1433 dns_view_getpeertsig(dns_view_t *view, const isc_netaddr_t *peeraddr,
1434 		     dns_tsigkey_t **keyp) {
1435 	isc_result_t result;
1436 	dns_name_t *keyname = NULL;
1437 	dns_peer_t *peer = NULL;
1438 
1439 	result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer);
1440 	if (result != ISC_R_SUCCESS) {
1441 		return result;
1442 	}
1443 
1444 	result = dns_peer_getkey(peer, &keyname);
1445 	if (result != ISC_R_SUCCESS) {
1446 		return result;
1447 	}
1448 
1449 	result = dns_view_gettsig(view, keyname, keyp);
1450 	return (result == ISC_R_NOTFOUND) ? ISC_R_FAILURE : result;
1451 }
1452 
1453 isc_result_t
1454 dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
1455 	REQUIRE(DNS_VIEW_VALID(view));
1456 	REQUIRE(source != NULL);
1457 
1458 	return dns_tsig_verify(source, msg, view->statickeys,
1459 			       view->dynamickeys);
1460 }
1461 
1462 isc_result_t
1463 dns_view_flushcache(dns_view_t *view, bool fixuponly) {
1464 	isc_result_t result;
1465 	dns_adb_t *adb = NULL;
1466 
1467 	REQUIRE(DNS_VIEW_VALID(view));
1468 
1469 	if (view->cachedb == NULL) {
1470 		return ISC_R_SUCCESS;
1471 	}
1472 	if (!fixuponly) {
1473 		result = dns_cache_flush(view->cache);
1474 		if (result != ISC_R_SUCCESS) {
1475 			return result;
1476 		}
1477 	}
1478 	dns_db_detach(&view->cachedb);
1479 	dns_cache_attachdb(view->cache, &view->cachedb);
1480 	if (view->failcache != NULL) {
1481 		dns_badcache_flush(view->failcache);
1482 	}
1483 
1484 	rcu_read_lock();
1485 	adb = rcu_dereference(view->adb);
1486 	if (adb != NULL) {
1487 		dns_adb_flush(adb);
1488 	}
1489 	rcu_read_unlock();
1490 
1491 	return ISC_R_SUCCESS;
1492 }
1493 
1494 isc_result_t
1495 dns_view_flushname(dns_view_t *view, const dns_name_t *name) {
1496 	return dns_view_flushnode(view, name, false);
1497 }
1498 
1499 isc_result_t
1500 dns_view_flushnode(dns_view_t *view, const dns_name_t *name, bool tree) {
1501 	isc_result_t result = ISC_R_SUCCESS;
1502 	dns_adb_t *adb = NULL;
1503 
1504 	REQUIRE(DNS_VIEW_VALID(view));
1505 
1506 	if (tree) {
1507 		rcu_read_lock();
1508 		adb = rcu_dereference(view->adb);
1509 		if (adb != NULL) {
1510 			dns_adb_flushnames(adb, name);
1511 		}
1512 		rcu_read_unlock();
1513 		if (view->failcache != NULL) {
1514 			dns_badcache_flushtree(view->failcache, name);
1515 		}
1516 	} else {
1517 		rcu_read_lock();
1518 		adb = rcu_dereference(view->adb);
1519 		if (adb != NULL) {
1520 			dns_adb_flushname(adb, name);
1521 		}
1522 		rcu_read_unlock();
1523 		if (view->failcache != NULL) {
1524 			dns_badcache_flushname(view->failcache, name);
1525 		}
1526 	}
1527 
1528 	if (view->cache != NULL) {
1529 		result = dns_cache_flushnode(view->cache, name, tree);
1530 	}
1531 
1532 	return result;
1533 }
1534 
1535 isc_result_t
1536 dns_view_freezezones(dns_view_t *view, bool value) {
1537 	isc_result_t result;
1538 	dns_zt_t *zonetable = NULL;
1539 
1540 	REQUIRE(DNS_VIEW_VALID(view));
1541 
1542 	rcu_read_lock();
1543 	zonetable = rcu_dereference(view->zonetable);
1544 	if (zonetable != NULL) {
1545 		result = dns_zt_freezezones(zonetable, view, value);
1546 	} else {
1547 		result = ISC_R_SUCCESS;
1548 	}
1549 	rcu_read_unlock();
1550 
1551 	return result;
1552 }
1553 
1554 void
1555 dns_view_initntatable(dns_view_t *view, isc_loopmgr_t *loopmgr) {
1556 	REQUIRE(DNS_VIEW_VALID(view));
1557 	if (view->ntatable_priv != NULL) {
1558 		dns_ntatable_detach(&view->ntatable_priv);
1559 	}
1560 	dns_ntatable_create(view, loopmgr, &view->ntatable_priv);
1561 }
1562 
1563 isc_result_t
1564 dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp) {
1565 	REQUIRE(DNS_VIEW_VALID(view));
1566 	REQUIRE(ntp != NULL && *ntp == NULL);
1567 	if (view->ntatable_priv == NULL) {
1568 		return ISC_R_NOTFOUND;
1569 	}
1570 	dns_ntatable_attach(view->ntatable_priv, ntp);
1571 	return ISC_R_SUCCESS;
1572 }
1573 
1574 void
1575 dns_view_initsecroots(dns_view_t *view) {
1576 	REQUIRE(DNS_VIEW_VALID(view));
1577 	if (view->secroots_priv != NULL) {
1578 		dns_keytable_detach(&view->secroots_priv);
1579 	}
1580 	dns_keytable_create(view, &view->secroots_priv);
1581 }
1582 
1583 isc_result_t
1584 dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) {
1585 	REQUIRE(DNS_VIEW_VALID(view));
1586 	REQUIRE(ktp != NULL && *ktp == NULL);
1587 	if (view->secroots_priv == NULL) {
1588 		return ISC_R_NOTFOUND;
1589 	}
1590 	dns_keytable_attach(view->secroots_priv, ktp);
1591 	return ISC_R_SUCCESS;
1592 }
1593 
1594 bool
1595 dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now, const dns_name_t *name,
1596 		   const dns_name_t *anchor) {
1597 	REQUIRE(DNS_VIEW_VALID(view));
1598 
1599 	if (view->ntatable_priv == NULL) {
1600 		return false;
1601 	}
1602 
1603 	return dns_ntatable_covered(view->ntatable_priv, now, name, anchor);
1604 }
1605 
1606 isc_result_t
1607 dns_view_issecuredomain(dns_view_t *view, const dns_name_t *name,
1608 			isc_stdtime_t now, bool checknta, bool *ntap,
1609 			bool *secure_domain) {
1610 	isc_result_t result;
1611 	bool secure = false;
1612 	dns_fixedname_t fn;
1613 	dns_name_t *anchor;
1614 
1615 	REQUIRE(DNS_VIEW_VALID(view));
1616 
1617 	if (view->secroots_priv == NULL) {
1618 		return ISC_R_NOTFOUND;
1619 	}
1620 
1621 	anchor = dns_fixedname_initname(&fn);
1622 
1623 	result = dns_keytable_issecuredomain(view->secroots_priv, name, anchor,
1624 					     &secure);
1625 	if (result != ISC_R_SUCCESS) {
1626 		return result;
1627 	}
1628 
1629 	if (ntap != NULL) {
1630 		*ntap = false;
1631 	}
1632 	if (checknta && secure && view->ntatable_priv != NULL &&
1633 	    dns_ntatable_covered(view->ntatable_priv, now, name, anchor))
1634 	{
1635 		if (ntap != NULL) {
1636 			*ntap = true;
1637 		}
1638 		secure = false;
1639 	}
1640 
1641 	*secure_domain = secure;
1642 	return ISC_R_SUCCESS;
1643 }
1644 
1645 void
1646 dns_view_untrust(dns_view_t *view, const dns_name_t *keyname,
1647 		 const dns_rdata_dnskey_t *dnskey) {
1648 	isc_result_t result;
1649 	dns_keytable_t *sr = NULL;
1650 	dns_rdata_dnskey_t tmpkey;
1651 
1652 	REQUIRE(DNS_VIEW_VALID(view));
1653 	REQUIRE(keyname != NULL);
1654 	REQUIRE(dnskey != NULL);
1655 
1656 	result = dns_view_getsecroots(view, &sr);
1657 	if (result != ISC_R_SUCCESS) {
1658 		return;
1659 	}
1660 
1661 	/*
1662 	 * Clear the revoke bit, if set, so that the key will match what's
1663 	 * in secroots now.
1664 	 */
1665 	tmpkey = *dnskey;
1666 	tmpkey.flags &= ~DNS_KEYFLAG_REVOKE;
1667 
1668 	result = dns_keytable_deletekey(sr, keyname, &tmpkey);
1669 	if (result == ISC_R_SUCCESS) {
1670 		/*
1671 		 * If key was found in secroots, then it was a
1672 		 * configured trust anchor, and we want to fail
1673 		 * secure. If there are no other configured keys,
1674 		 * then leave a null key so that we can't validate
1675 		 * anymore.
1676 		 */
1677 		dns_keytable_marksecure(sr, keyname);
1678 	}
1679 
1680 	dns_keytable_detach(&sr);
1681 }
1682 
1683 bool
1684 dns_view_istrusted(dns_view_t *view, const dns_name_t *keyname,
1685 		   const dns_rdata_dnskey_t *dnskey) {
1686 	isc_result_t result;
1687 	dns_keytable_t *sr = NULL;
1688 	dns_keynode_t *knode = NULL;
1689 	bool answer = false;
1690 	dns_rdataset_t dsset;
1691 
1692 	REQUIRE(DNS_VIEW_VALID(view));
1693 	REQUIRE(keyname != NULL);
1694 	REQUIRE(dnskey != NULL);
1695 
1696 	result = dns_view_getsecroots(view, &sr);
1697 	if (result != ISC_R_SUCCESS) {
1698 		return false;
1699 	}
1700 
1701 	dns_rdataset_init(&dsset);
1702 	result = dns_keytable_find(sr, keyname, &knode);
1703 	if (result == ISC_R_SUCCESS) {
1704 		if (dns_keynode_dsset(knode, &dsset)) {
1705 			dns_rdata_t rdata = DNS_RDATA_INIT;
1706 			unsigned char data[4096], digest[DNS_DS_BUFFERSIZE];
1707 			dns_rdata_dnskey_t tmpkey = *dnskey;
1708 			dns_rdata_ds_t ds;
1709 			isc_buffer_t b;
1710 			dns_rdataclass_t rdclass = tmpkey.common.rdclass;
1711 
1712 			/*
1713 			 * Clear the revoke bit, if set, so that the key
1714 			 * will match what's in secroots now.
1715 			 */
1716 			tmpkey.flags &= ~DNS_KEYFLAG_REVOKE;
1717 
1718 			isc_buffer_init(&b, data, sizeof(data));
1719 			result = dns_rdata_fromstruct(&rdata, rdclass,
1720 						      dns_rdatatype_dnskey,
1721 						      &tmpkey, &b);
1722 			if (result != ISC_R_SUCCESS) {
1723 				goto finish;
1724 			}
1725 
1726 			result = dns_ds_fromkeyrdata(keyname, &rdata,
1727 						     DNS_DSDIGEST_SHA256,
1728 						     digest, &ds);
1729 			if (result != ISC_R_SUCCESS) {
1730 				goto finish;
1731 			}
1732 
1733 			dns_rdata_reset(&rdata);
1734 			isc_buffer_init(&b, data, sizeof(data));
1735 			result = dns_rdata_fromstruct(
1736 				&rdata, rdclass, dns_rdatatype_ds, &ds, &b);
1737 			if (result != ISC_R_SUCCESS) {
1738 				goto finish;
1739 			}
1740 
1741 			result = dns_rdataset_first(&dsset);
1742 			while (result == ISC_R_SUCCESS) {
1743 				dns_rdata_t this = DNS_RDATA_INIT;
1744 				dns_rdataset_current(&dsset, &this);
1745 				if (dns_rdata_compare(&rdata, &this) == 0) {
1746 					answer = true;
1747 					break;
1748 				}
1749 				result = dns_rdataset_next(&dsset);
1750 			}
1751 		}
1752 	}
1753 
1754 finish:
1755 	if (dns_rdataset_isassociated(&dsset)) {
1756 		dns_rdataset_disassociate(&dsset);
1757 	}
1758 	if (knode != NULL) {
1759 		dns_keynode_detach(&knode);
1760 	}
1761 	dns_keytable_detach(&sr);
1762 	return answer;
1763 }
1764 
1765 /*
1766  * Create path to a directory and a filename constructed from viewname.
1767  * This is a front-end to isc_file_sanitize(), allowing backward
1768  * compatibility to older versions when a file couldn't be expected
1769  * to be in the specified directory but might be in the current working
1770  * directory instead.
1771  *
1772  * It first tests for the existence of a file <viewname>.<suffix> in
1773  * 'directory'. If the file does not exist, it checks again in the
1774  * current working directory. If it does not exist there either,
1775  * return the path inside the directory.
1776  *
1777  * Returns ISC_R_SUCCESS if a path to an existing file is found or
1778  * a new path is created; returns ISC_R_NOSPACE if the path won't
1779  * fit in 'buflen'.
1780  */
1781 
1782 static isc_result_t
1783 nz_legacy(const char *directory, const char *viewname, const char *suffix,
1784 	  char *buffer, size_t buflen) {
1785 	isc_result_t result;
1786 	char newbuf[PATH_MAX];
1787 
1788 	result = isc_file_sanitize(directory, viewname, suffix, buffer, buflen);
1789 	if (result != ISC_R_SUCCESS) {
1790 		return result;
1791 	} else if (directory == NULL || isc_file_exists(buffer)) {
1792 		return ISC_R_SUCCESS;
1793 	} else {
1794 		/* Save buffer */
1795 		strlcpy(newbuf, buffer, sizeof(newbuf));
1796 	}
1797 
1798 	/*
1799 	 * It isn't in the specified directory; check CWD.
1800 	 */
1801 	result = isc_file_sanitize(NULL, viewname, suffix, buffer, buflen);
1802 	if (result != ISC_R_SUCCESS || isc_file_exists(buffer)) {
1803 		return result;
1804 	}
1805 
1806 	/*
1807 	 * File does not exist in either 'directory' or CWD,
1808 	 * so use the path in 'directory'.
1809 	 */
1810 	strlcpy(buffer, newbuf, buflen);
1811 	return ISC_R_SUCCESS;
1812 }
1813 
1814 isc_result_t
1815 dns_view_setnewzones(dns_view_t *view, bool allow, void *cfgctx,
1816 		     void (*cfg_destroy)(void **), uint64_t mapsize) {
1817 	isc_result_t result = ISC_R_SUCCESS;
1818 	char buffer[1024];
1819 #ifdef HAVE_LMDB
1820 	MDB_env *env = NULL;
1821 	int status;
1822 #endif /* ifdef HAVE_LMDB */
1823 
1824 #ifndef HAVE_LMDB
1825 	UNUSED(mapsize);
1826 #endif /* ifndef HAVE_LMDB */
1827 
1828 	REQUIRE(DNS_VIEW_VALID(view));
1829 	REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow);
1830 
1831 	if (view->new_zone_file != NULL) {
1832 		isc_mem_free(view->mctx, view->new_zone_file);
1833 		view->new_zone_file = NULL;
1834 	}
1835 
1836 #ifdef HAVE_LMDB
1837 	if (view->new_zone_dbenv != NULL) {
1838 		mdb_env_close((MDB_env *)view->new_zone_dbenv);
1839 		view->new_zone_dbenv = NULL;
1840 	}
1841 
1842 	if (view->new_zone_db != NULL) {
1843 		isc_mem_free(view->mctx, view->new_zone_db);
1844 		view->new_zone_db = NULL;
1845 	}
1846 #endif /* HAVE_LMDB */
1847 
1848 	if (view->new_zone_config != NULL) {
1849 		view->cfg_destroy(&view->new_zone_config);
1850 		view->cfg_destroy = NULL;
1851 	}
1852 
1853 	if (!allow) {
1854 		return ISC_R_SUCCESS;
1855 	}
1856 
1857 	CHECK(nz_legacy(view->new_zone_dir, view->name, "nzf", buffer,
1858 			sizeof(buffer)));
1859 
1860 	view->new_zone_file = isc_mem_strdup(view->mctx, buffer);
1861 
1862 #ifdef HAVE_LMDB
1863 	CHECK(nz_legacy(view->new_zone_dir, view->name, "nzd", buffer,
1864 			sizeof(buffer)));
1865 
1866 	view->new_zone_db = isc_mem_strdup(view->mctx, buffer);
1867 
1868 	status = mdb_env_create(&env);
1869 	if (status != MDB_SUCCESS) {
1870 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
1871 			      ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
1872 			      "mdb_env_create failed: %s",
1873 			      mdb_strerror(status));
1874 		CHECK(ISC_R_FAILURE);
1875 	}
1876 
1877 	if (mapsize != 0ULL) {
1878 		status = mdb_env_set_mapsize(env, mapsize);
1879 		if (status != MDB_SUCCESS) {
1880 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
1881 				      ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
1882 				      "mdb_env_set_mapsize failed: %s",
1883 				      mdb_strerror(status));
1884 			CHECK(ISC_R_FAILURE);
1885 		}
1886 		view->new_zone_mapsize = mapsize;
1887 	}
1888 
1889 	status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600);
1890 	if (status != MDB_SUCCESS) {
1891 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
1892 			      ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
1893 			      "mdb_env_open of '%s' failed: %s",
1894 			      view->new_zone_db, mdb_strerror(status));
1895 		CHECK(ISC_R_FAILURE);
1896 	}
1897 
1898 	view->new_zone_dbenv = env;
1899 	env = NULL;
1900 #endif /* HAVE_LMDB */
1901 
1902 	view->new_zone_config = cfgctx;
1903 	view->cfg_destroy = cfg_destroy;
1904 
1905 cleanup:
1906 	if (result != ISC_R_SUCCESS) {
1907 		if (view->new_zone_file != NULL) {
1908 			isc_mem_free(view->mctx, view->new_zone_file);
1909 			view->new_zone_file = NULL;
1910 		}
1911 
1912 #ifdef HAVE_LMDB
1913 		if (view->new_zone_db != NULL) {
1914 			isc_mem_free(view->mctx, view->new_zone_db);
1915 			view->new_zone_db = NULL;
1916 		}
1917 		if (env != NULL) {
1918 			mdb_env_close(env);
1919 		}
1920 #endif /* HAVE_LMDB */
1921 		view->new_zone_config = NULL;
1922 		view->cfg_destroy = NULL;
1923 	}
1924 
1925 	return result;
1926 }
1927 
1928 void
1929 dns_view_setnewzonedir(dns_view_t *view, const char *dir) {
1930 	REQUIRE(DNS_VIEW_VALID(view));
1931 
1932 	if (view->new_zone_dir != NULL) {
1933 		isc_mem_free(view->mctx, view->new_zone_dir);
1934 		view->new_zone_dir = NULL;
1935 	}
1936 
1937 	if (dir == NULL) {
1938 		return;
1939 	}
1940 
1941 	view->new_zone_dir = isc_mem_strdup(view->mctx, dir);
1942 }
1943 
1944 const char *
1945 dns_view_getnewzonedir(dns_view_t *view) {
1946 	REQUIRE(DNS_VIEW_VALID(view));
1947 
1948 	return view->new_zone_dir;
1949 }
1950 
1951 isc_result_t
1952 dns_view_searchdlz(dns_view_t *view, const dns_name_t *name,
1953 		   unsigned int minlabels, dns_clientinfomethods_t *methods,
1954 		   dns_clientinfo_t *clientinfo, dns_db_t **dbp) {
1955 	dns_fixedname_t fname;
1956 	dns_name_t *zonename;
1957 	unsigned int namelabels;
1958 	unsigned int i;
1959 	isc_result_t result;
1960 	dns_dlzfindzone_t findzone;
1961 	dns_dlzdb_t *dlzdb;
1962 	dns_db_t *db, *best = NULL;
1963 
1964 	/*
1965 	 * Performs checks to make sure data is as we expect it to be.
1966 	 */
1967 	REQUIRE(DNS_VIEW_VALID(view));
1968 	REQUIRE(name != NULL);
1969 	REQUIRE(dbp != NULL && *dbp == NULL);
1970 
1971 	/* setup a "fixed" dns name */
1972 	zonename = dns_fixedname_initname(&fname);
1973 
1974 	/* count the number of labels in the name */
1975 	namelabels = dns_name_countlabels(name);
1976 
1977 	for (dlzdb = ISC_LIST_HEAD(view->dlz_searched); dlzdb != NULL;
1978 	     dlzdb = ISC_LIST_NEXT(dlzdb, link))
1979 	{
1980 		REQUIRE(DNS_DLZ_VALID(dlzdb));
1981 
1982 		/*
1983 		 * loop through starting with the longest domain name and
1984 		 * trying shorter names portions of the name until we find a
1985 		 * match, have an error, or are below the 'minlabels'
1986 		 * threshold.  minlabels is 0, if neither the standard
1987 		 * database nor any previous DLZ database had a zone name
1988 		 * match. Otherwise minlabels is the number of labels
1989 		 * in that name.  We need to beat that for a "better"
1990 		 * match for this DLZ database to be authoritative.
1991 		 */
1992 		for (i = namelabels; i > minlabels && i > 1; i--) {
1993 			if (i == namelabels) {
1994 				dns_name_copy(name, zonename);
1995 			} else {
1996 				dns_name_split(name, i, NULL, zonename);
1997 			}
1998 
1999 			/* ask SDLZ driver if the zone is supported */
2000 			db = NULL;
2001 			findzone = dlzdb->implementation->methods->findzone;
2002 			result = (*findzone)(dlzdb->implementation->driverarg,
2003 					     dlzdb->dbdata, dlzdb->mctx,
2004 					     view->rdclass, zonename, methods,
2005 					     clientinfo, &db);
2006 
2007 			if (result != ISC_R_NOTFOUND) {
2008 				if (best != NULL) {
2009 					dns_db_detach(&best);
2010 				}
2011 				if (result == ISC_R_SUCCESS) {
2012 					INSIST(db != NULL);
2013 					dns_db_attach(db, &best);
2014 					dns_db_detach(&db);
2015 					minlabels = i;
2016 				} else {
2017 					if (db != NULL) {
2018 						dns_db_detach(&db);
2019 					}
2020 					break;
2021 				}
2022 			} else if (db != NULL) {
2023 				dns_db_detach(&db);
2024 			}
2025 		}
2026 	}
2027 
2028 	if (best != NULL) {
2029 		dns_db_attach(best, dbp);
2030 		dns_db_detach(&best);
2031 		return ISC_R_SUCCESS;
2032 	}
2033 
2034 	return ISC_R_NOTFOUND;
2035 }
2036 
2037 uint32_t
2038 dns_view_getfailttl(dns_view_t *view) {
2039 	REQUIRE(DNS_VIEW_VALID(view));
2040 	return view->fail_ttl;
2041 }
2042 
2043 void
2044 dns_view_setfailttl(dns_view_t *view, uint32_t fail_ttl) {
2045 	REQUIRE(DNS_VIEW_VALID(view));
2046 	view->fail_ttl = fail_ttl;
2047 }
2048 
2049 isc_result_t
2050 dns_view_saventa(dns_view_t *view) {
2051 	isc_result_t result;
2052 	bool removefile = false;
2053 	dns_ntatable_t *ntatable = NULL;
2054 	FILE *fp = NULL;
2055 
2056 	REQUIRE(DNS_VIEW_VALID(view));
2057 
2058 	if (view->nta_lifetime == 0) {
2059 		return ISC_R_SUCCESS;
2060 	}
2061 
2062 	/* Open NTA save file for overwrite. */
2063 	CHECK(isc_stdio_open(view->nta_file, "w", &fp));
2064 
2065 	result = dns_view_getntatable(view, &ntatable);
2066 	if (result == ISC_R_NOTFOUND) {
2067 		removefile = true;
2068 		result = ISC_R_SUCCESS;
2069 		goto cleanup;
2070 	} else {
2071 		CHECK(result);
2072 	}
2073 
2074 	result = dns_ntatable_save(ntatable, fp);
2075 	if (result == ISC_R_NOTFOUND) {
2076 		removefile = true;
2077 		result = ISC_R_SUCCESS;
2078 	} else if (result == ISC_R_SUCCESS) {
2079 		result = isc_stdio_close(fp);
2080 		fp = NULL;
2081 	}
2082 
2083 cleanup:
2084 	if (ntatable != NULL) {
2085 		dns_ntatable_detach(&ntatable);
2086 	}
2087 
2088 	if (fp != NULL) {
2089 		(void)isc_stdio_close(fp);
2090 	}
2091 
2092 	/* Don't leave half-baked NTA save files lying around. */
2093 	if (result != ISC_R_SUCCESS || removefile) {
2094 		(void)isc_file_remove(view->nta_file);
2095 	}
2096 
2097 	return result;
2098 }
2099 
2100 #define TSTR(t) ((t).value.as_textregion.base)
2101 #define TLEN(t) ((t).value.as_textregion.length)
2102 
2103 isc_result_t
2104 dns_view_loadnta(dns_view_t *view) {
2105 	isc_result_t result;
2106 	dns_ntatable_t *ntatable = NULL;
2107 	isc_lex_t *lex = NULL;
2108 	isc_token_t token;
2109 	isc_stdtime_t now = isc_stdtime_now();
2110 
2111 	REQUIRE(DNS_VIEW_VALID(view));
2112 
2113 	if (view->nta_lifetime == 0) {
2114 		return ISC_R_SUCCESS;
2115 	}
2116 
2117 	isc_lex_create(view->mctx, 1025, &lex);
2118 	CHECK(isc_lex_openfile(lex, view->nta_file));
2119 	CHECK(dns_view_getntatable(view, &ntatable));
2120 
2121 	for (;;) {
2122 		int options = (ISC_LEXOPT_EOL | ISC_LEXOPT_EOF);
2123 		char *name, *type, *timestamp;
2124 		size_t len;
2125 		dns_fixedname_t fn;
2126 		const dns_name_t *ntaname;
2127 		isc_buffer_t b;
2128 		isc_stdtime_t t;
2129 		bool forced;
2130 
2131 		CHECK(isc_lex_gettoken(lex, options, &token));
2132 		if (token.type == isc_tokentype_eof) {
2133 			break;
2134 		} else if (token.type != isc_tokentype_string) {
2135 			CHECK(ISC_R_UNEXPECTEDTOKEN);
2136 		}
2137 		name = TSTR(token);
2138 		len = TLEN(token);
2139 
2140 		if (strcmp(name, ".") == 0) {
2141 			ntaname = dns_rootname;
2142 		} else {
2143 			dns_name_t *fname;
2144 			fname = dns_fixedname_initname(&fn);
2145 
2146 			isc_buffer_init(&b, name, (unsigned int)len);
2147 			isc_buffer_add(&b, (unsigned int)len);
2148 			CHECK(dns_name_fromtext(fname, &b, dns_rootname, 0,
2149 						NULL));
2150 			ntaname = fname;
2151 		}
2152 
2153 		CHECK(isc_lex_gettoken(lex, options, &token));
2154 		if (token.type != isc_tokentype_string) {
2155 			CHECK(ISC_R_UNEXPECTEDTOKEN);
2156 		}
2157 		type = TSTR(token);
2158 
2159 		if (strcmp(type, "regular") == 0) {
2160 			forced = false;
2161 		} else if (strcmp(type, "forced") == 0) {
2162 			forced = true;
2163 		} else {
2164 			CHECK(ISC_R_UNEXPECTEDTOKEN);
2165 		}
2166 
2167 		CHECK(isc_lex_gettoken(lex, options, &token));
2168 		if (token.type != isc_tokentype_string) {
2169 			CHECK(ISC_R_UNEXPECTEDTOKEN);
2170 		}
2171 		timestamp = TSTR(token);
2172 		CHECK(dns_time32_fromtext(timestamp, &t));
2173 
2174 		CHECK(isc_lex_gettoken(lex, options, &token));
2175 		if (token.type != isc_tokentype_eol &&
2176 		    token.type != isc_tokentype_eof)
2177 		{
2178 			CHECK(ISC_R_UNEXPECTEDTOKEN);
2179 		}
2180 
2181 		if (now <= t) {
2182 			if (t > (now + 604800)) {
2183 				t = now + 604800;
2184 			}
2185 
2186 			(void)dns_ntatable_add(ntatable, ntaname, forced, 0, t);
2187 		} else {
2188 			char nb[DNS_NAME_FORMATSIZE];
2189 			dns_name_format(ntaname, nb, sizeof(nb));
2190 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
2191 				      DNS_LOGMODULE_NTA, ISC_LOG_INFO,
2192 				      "ignoring expired NTA at %s", nb);
2193 		}
2194 	}
2195 
2196 cleanup:
2197 	if (ntatable != NULL) {
2198 		dns_ntatable_detach(&ntatable);
2199 	}
2200 
2201 	if (lex != NULL) {
2202 		isc_lex_close(lex);
2203 		isc_lex_destroy(&lex);
2204 	}
2205 
2206 	return result;
2207 }
2208 
2209 void
2210 dns_view_setviewcommit(dns_view_t *view) {
2211 	dns_zone_t *redirect = NULL, *managed_keys = NULL;
2212 	dns_zt_t *zonetable = NULL;
2213 
2214 	REQUIRE(DNS_VIEW_VALID(view));
2215 
2216 	LOCK(&view->lock);
2217 
2218 	if (view->redirect != NULL) {
2219 		dns_zone_attach(view->redirect, &redirect);
2220 	}
2221 	if (view->managed_keys != NULL) {
2222 		dns_zone_attach(view->managed_keys, &managed_keys);
2223 	}
2224 
2225 	UNLOCK(&view->lock);
2226 
2227 	rcu_read_lock();
2228 	zonetable = rcu_dereference(view->zonetable);
2229 	if (zonetable != NULL) {
2230 		dns_zt_setviewcommit(zonetable);
2231 	}
2232 	rcu_read_unlock();
2233 
2234 	if (redirect != NULL) {
2235 		dns_zone_setviewcommit(redirect);
2236 		dns_zone_detach(&redirect);
2237 	}
2238 	if (managed_keys != NULL) {
2239 		dns_zone_setviewcommit(managed_keys);
2240 		dns_zone_detach(&managed_keys);
2241 	}
2242 }
2243 
2244 void
2245 dns_view_setviewrevert(dns_view_t *view) {
2246 	dns_zone_t *redirect = NULL, *managed_keys = NULL;
2247 	dns_zt_t *zonetable = NULL;
2248 
2249 	REQUIRE(DNS_VIEW_VALID(view));
2250 
2251 	/*
2252 	 * dns_zt_setviewrevert() attempts to lock this view, so we must
2253 	 * release the lock.
2254 	 */
2255 	LOCK(&view->lock);
2256 	if (view->redirect != NULL) {
2257 		dns_zone_attach(view->redirect, &redirect);
2258 	}
2259 	if (view->managed_keys != NULL) {
2260 		dns_zone_attach(view->managed_keys, &managed_keys);
2261 	}
2262 	UNLOCK(&view->lock);
2263 
2264 	if (redirect != NULL) {
2265 		dns_zone_setviewrevert(redirect);
2266 		dns_zone_detach(&redirect);
2267 	}
2268 	if (managed_keys != NULL) {
2269 		dns_zone_setviewrevert(managed_keys);
2270 		dns_zone_detach(&managed_keys);
2271 	}
2272 	rcu_read_lock();
2273 	zonetable = rcu_dereference(view->zonetable);
2274 	if (zonetable != NULL) {
2275 		dns_zt_setviewrevert(zonetable);
2276 	}
2277 	rcu_read_unlock();
2278 }
2279 
2280 bool
2281 dns_view_staleanswerenabled(dns_view_t *view) {
2282 	uint32_t stale_ttl = 0;
2283 	bool result = false;
2284 
2285 	REQUIRE(DNS_VIEW_VALID(view));
2286 
2287 	if (dns_db_getservestalettl(view->cachedb, &stale_ttl) != ISC_R_SUCCESS)
2288 	{
2289 		return false;
2290 	}
2291 	if (stale_ttl > 0) {
2292 		if (view->staleanswersok == dns_stale_answer_yes) {
2293 			result = true;
2294 		} else if (view->staleanswersok == dns_stale_answer_conf) {
2295 			result = view->staleanswersenable;
2296 		}
2297 	}
2298 
2299 	return result;
2300 }
2301 
2302 void
2303 dns_view_flushonshutdown(dns_view_t *view, bool flush) {
2304 	REQUIRE(DNS_VIEW_VALID(view));
2305 
2306 	view->flush = flush;
2307 }
2308 
2309 void
2310 dns_view_sfd_add(dns_view_t *view, const dns_name_t *name) {
2311 	isc_result_t result;
2312 
2313 	REQUIRE(DNS_VIEW_VALID(view));
2314 
2315 	result = dns_nametree_add(view->sfd, name, 0);
2316 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
2317 }
2318 
2319 void
2320 dns_view_sfd_del(dns_view_t *view, const dns_name_t *name) {
2321 	REQUIRE(DNS_VIEW_VALID(view));
2322 
2323 	dns_nametree_delete(view->sfd, name);
2324 }
2325 
2326 void
2327 dns_view_sfd_find(dns_view_t *view, const dns_name_t *name,
2328 		  dns_name_t *foundname) {
2329 	REQUIRE(DNS_VIEW_VALID(view));
2330 
2331 	if (!dns_nametree_covered(view->sfd, name, foundname, 0)) {
2332 		dns_name_copy(dns_rootname, foundname);
2333 	}
2334 }
2335 
2336 isc_result_t
2337 dns_view_getresolver(dns_view_t *view, dns_resolver_t **resolverp) {
2338 	isc_result_t result;
2339 	REQUIRE(DNS_VIEW_VALID(view));
2340 	REQUIRE(resolverp != NULL && *resolverp == NULL);
2341 	LOCK(&view->lock);
2342 	if (view->resolver != NULL) {
2343 		dns_resolver_attach(view->resolver, resolverp);
2344 		result = ISC_R_SUCCESS;
2345 	} else {
2346 		result = ISC_R_SHUTTINGDOWN;
2347 	}
2348 	UNLOCK(&view->lock);
2349 	return result;
2350 }
2351 
2352 void
2353 dns_view_setmaxrrperset(dns_view_t *view, uint32_t value) {
2354 	REQUIRE(DNS_VIEW_VALID(view));
2355 	view->maxrrperset = value;
2356 	if (view->cache != NULL) {
2357 		dns_cache_setmaxrrperset(view->cache, value);
2358 	}
2359 }
2360 
2361 void
2362 dns_view_setmaxtypepername(dns_view_t *view, uint32_t value) {
2363 	REQUIRE(DNS_VIEW_VALID(view));
2364 	view->maxtypepername = value;
2365 	if (view->cache != NULL) {
2366 		dns_cache_setmaxtypepername(view->cache, value);
2367 	}
2368 }
2369 
2370 void
2371 dns_view_setudpsize(dns_view_t *view, uint16_t udpsize) {
2372 	REQUIRE(DNS_VIEW_VALID(view));
2373 	view->udpsize = udpsize;
2374 }
2375 
2376 uint16_t
2377 dns_view_getudpsize(dns_view_t *view) {
2378 	REQUIRE(DNS_VIEW_VALID(view));
2379 	return view->udpsize;
2380 }
2381 
2382 dns_dispatchmgr_t *
2383 dns_view_getdispatchmgr(dns_view_t *view) {
2384 	REQUIRE(DNS_VIEW_VALID(view));
2385 
2386 	rcu_read_lock();
2387 	dns_dispatchmgr_t *dispatchmgr = rcu_dereference(view->dispatchmgr);
2388 	if (dispatchmgr != NULL) {
2389 		dns_dispatchmgr_ref(dispatchmgr);
2390 	}
2391 	rcu_read_unlock();
2392 
2393 	return dispatchmgr;
2394 }
2395 
2396 isc_result_t
2397 dns_view_addtrustedkey(dns_view_t *view, dns_rdatatype_t rdtype,
2398 		       const dns_name_t *keyname, isc_buffer_t *databuf) {
2399 	isc_result_t result;
2400 	dns_name_t *name = UNCONST(keyname);
2401 	char rdatabuf[DST_KEY_MAXSIZE];
2402 	unsigned char digest[ISC_MAX_MD_SIZE];
2403 	dns_rdata_ds_t ds;
2404 	dns_rdata_t rdata;
2405 	isc_buffer_t b;
2406 
2407 	REQUIRE(DNS_VIEW_VALID(view));
2408 	REQUIRE(view->rdclass == dns_rdataclass_in);
2409 
2410 	if (rdtype != dns_rdatatype_dnskey && rdtype != dns_rdatatype_ds) {
2411 		result = ISC_R_NOTIMPLEMENTED;
2412 		goto cleanup;
2413 	}
2414 
2415 	isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
2416 	dns_rdata_init(&rdata);
2417 	isc_buffer_setactive(databuf, isc_buffer_usedlength(databuf));
2418 	CHECK(dns_rdata_fromwire(&rdata, view->rdclass, rdtype, databuf,
2419 				 DNS_DECOMPRESS_NEVER, &b));
2420 
2421 	if (rdtype == dns_rdatatype_ds) {
2422 		CHECK(dns_rdata_tostruct(&rdata, &ds, NULL));
2423 	} else {
2424 		CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
2425 					  digest, &ds));
2426 	}
2427 
2428 	CHECK(dns_keytable_add(view->secroots_priv, false, false, name, &ds,
2429 			       NULL, NULL));
2430 
2431 cleanup:
2432 	return result;
2433 }
2434 
2435 isc_result_t
2436 dns_view_apply(dns_view_t *view, bool stop, isc_result_t *sub,
2437 	       isc_result_t (*action)(dns_zone_t *, void *), void *uap) {
2438 	isc_result_t result;
2439 	dns_zt_t *zonetable = NULL;
2440 
2441 	REQUIRE(DNS_VIEW_VALID(view));
2442 
2443 	rcu_read_lock();
2444 	zonetable = rcu_dereference(view->zonetable);
2445 	if (zonetable != NULL) {
2446 		result = dns_zt_apply(zonetable, stop, sub, action, uap);
2447 	} else {
2448 		result = ISC_R_SHUTTINGDOWN;
2449 	}
2450 	rcu_read_unlock();
2451 	return result;
2452 }
2453 
2454 void
2455 dns_view_getadb(dns_view_t *view, dns_adb_t **adbp) {
2456 	dns_adb_t *adb = NULL;
2457 
2458 	REQUIRE(DNS_VIEW_VALID(view));
2459 	REQUIRE(adbp != NULL && *adbp == NULL);
2460 
2461 	rcu_read_lock();
2462 	adb = rcu_dereference(view->adb);
2463 	if (adb != NULL) {
2464 		dns_adb_attach(adb, adbp);
2465 	}
2466 	rcu_read_unlock();
2467 }
2468 
2469 void
2470 dns_view_setmaxrestarts(dns_view_t *view, uint8_t max_restarts) {
2471 	REQUIRE(DNS_VIEW_VALID(view));
2472 	REQUIRE(max_restarts > 0);
2473 
2474 	view->max_restarts = max_restarts;
2475 }
2476