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