1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7  *
8  * See the COPYRIGHT file distributed with this work for additional
9  * information regarding copyright ownership.
10  */
11 
12 /*! \file */
13 
14 #include <inttypes.h>
15 #include <limits.h>
16 #include <stdbool.h>
17 
18 #ifdef HAVE_LMDB
19 #include <lmdb.h>
20 #endif /* ifdef HAVE_LMDB */
21 
22 #include <isc/atomic.h>
23 #include <isc/dir.h>
24 #include <isc/file.h>
25 #include <isc/hash.h>
26 #include <isc/lex.h>
27 #include <isc/print.h>
28 #include <isc/result.h>
29 #include <isc/stats.h>
30 #include <isc/string.h> /* Required for HP/UX (and others?) */
31 #include <isc/task.h>
32 #include <isc/util.h>
33 
34 #include <dns/acl.h>
35 #include <dns/adb.h>
36 #include <dns/badcache.h>
37 #include <dns/cache.h>
38 #include <dns/db.h>
39 #include <dns/dispatch.h>
40 #include <dns/dlz.h>
41 #include <dns/dns64.h>
42 #include <dns/dnssec.h>
43 #include <dns/events.h>
44 #include <dns/forward.h>
45 #include <dns/keytable.h>
46 #include <dns/keyvalues.h>
47 #include <dns/master.h>
48 #include <dns/masterdump.h>
49 #include <dns/nta.h>
50 #include <dns/order.h>
51 #include <dns/peer.h>
52 #include <dns/rbt.h>
53 #include <dns/rdataset.h>
54 #include <dns/request.h>
55 #include <dns/resolver.h>
56 #include <dns/rpz.h>
57 #include <dns/rrl.h>
58 #include <dns/stats.h>
59 #include <dns/time.h>
60 #include <dns/transport.h>
61 #include <dns/tsig.h>
62 #include <dns/zone.h>
63 #include <dns/zt.h>
64 
65 #define CHECK(op)                            \
66 	do {                                 \
67 		result = (op);               \
68 		if (result != ISC_R_SUCCESS) \
69 			goto cleanup;        \
70 	} while (0)
71 
72 #define RESSHUTDOWN(v) \
73 	((atomic_load(&(v)->attributes) & DNS_VIEWATTR_RESSHUTDOWN) != 0)
74 #define ADBSHUTDOWN(v) \
75 	((atomic_load(&(v)->attributes) & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
76 #define REQSHUTDOWN(v) \
77 	((atomic_load(&(v)->attributes) & DNS_VIEWATTR_REQSHUTDOWN) != 0)
78 
79 #define DNS_VIEW_DELONLYHASH   111
80 #define DNS_VIEW_FAILCACHESIZE 1021
81 
82 static void
83 resolver_shutdown(isc_task_t *task, isc_event_t *event);
84 static void
85 adb_shutdown(isc_task_t *task, isc_event_t *event);
86 static void
87 req_shutdown(isc_task_t *task, isc_event_t *event);
88 
89 isc_result_t
dns_view_create(isc_mem_t * mctx,dns_rdataclass_t rdclass,const char * name,dns_view_t ** viewp)90 dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, const char *name,
91 		dns_view_t **viewp) {
92 	dns_view_t *view;
93 	isc_result_t result;
94 	char buffer[1024];
95 
96 	/*
97 	 * Create a view.
98 	 */
99 
100 	REQUIRE(name != NULL);
101 	REQUIRE(viewp != NULL && *viewp == NULL);
102 
103 	view = isc_mem_get(mctx, sizeof(*view));
104 
105 	view->nta_file = NULL;
106 	view->mctx = NULL;
107 	isc_mem_attach(mctx, &view->mctx);
108 	view->name = isc_mem_strdup(mctx, name);
109 
110 	result = isc_file_sanitize(NULL, view->name, "nta", buffer,
111 				   sizeof(buffer));
112 	if (result != ISC_R_SUCCESS) {
113 		goto cleanup_name;
114 	}
115 	view->nta_file = isc_mem_strdup(mctx, buffer);
116 
117 	isc_mutex_init(&view->lock);
118 
119 	view->zonetable = NULL;
120 	result = dns_zt_create(mctx, rdclass, &view->zonetable);
121 	if (result != ISC_R_SUCCESS) {
122 		UNEXPECTED_ERROR(__FILE__, __LINE__,
123 				 "dns_zt_create() failed: %s",
124 				 isc_result_totext(result));
125 		result = ISC_R_UNEXPECTED;
126 		goto cleanup_mutex;
127 	}
128 
129 	view->secroots_priv = NULL;
130 	view->ntatable_priv = NULL;
131 	view->fwdtable = NULL;
132 	result = dns_fwdtable_create(mctx, &view->fwdtable);
133 	if (result != ISC_R_SUCCESS) {
134 		UNEXPECTED_ERROR(__FILE__, __LINE__,
135 				 "dns_fwdtable_create() failed: %s",
136 				 isc_result_totext(result));
137 		result = ISC_R_UNEXPECTED;
138 		goto cleanup_zt;
139 	}
140 
141 	view->cache = NULL;
142 	view->cachedb = NULL;
143 	ISC_LIST_INIT(view->dlz_searched);
144 	ISC_LIST_INIT(view->dlz_unsearched);
145 	view->hints = NULL;
146 	view->resolver = NULL;
147 	view->adb = NULL;
148 	view->requestmgr = NULL;
149 	view->rdclass = rdclass;
150 	view->frozen = false;
151 	view->task = NULL;
152 	isc_refcount_init(&view->references, 1);
153 	isc_refcount_init(&view->weakrefs, 1);
154 	atomic_init(&view->attributes,
155 		    (DNS_VIEWATTR_RESSHUTDOWN | DNS_VIEWATTR_ADBSHUTDOWN |
156 		     DNS_VIEWATTR_REQSHUTDOWN));
157 	view->transports = NULL;
158 	view->statickeys = NULL;
159 	view->dynamickeys = NULL;
160 	view->matchclients = NULL;
161 	view->matchdestinations = NULL;
162 	view->matchrecursiveonly = false;
163 	result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
164 	if (result != ISC_R_SUCCESS) {
165 		goto cleanup_weakrefs;
166 	}
167 	view->peers = NULL;
168 	view->order = NULL;
169 	view->delonly = NULL;
170 	view->rootdelonly = false;
171 	view->rootexclude = NULL;
172 	view->adbstats = NULL;
173 	view->resstats = NULL;
174 	view->resquerystats = NULL;
175 	view->cacheshared = false;
176 	ISC_LIST_INIT(view->dns64);
177 	view->dns64cnt = 0;
178 
179 	/*
180 	 * Initialize configuration data with default values.
181 	 */
182 	view->recursion = true;
183 	view->qminimization = false;
184 	view->qmin_strict = false;
185 	view->auth_nxdomain = false; /* Was true in BIND 8 */
186 	view->enablevalidation = true;
187 	view->acceptexpired = false;
188 	view->use_glue_cache = false;
189 	view->minimal_any = false;
190 	view->minimalresponses = dns_minimal_no;
191 	view->transfer_format = dns_one_answer;
192 	view->cacheacl = NULL;
193 	view->cacheonacl = NULL;
194 	view->checknames = false;
195 	view->queryacl = NULL;
196 	view->queryonacl = NULL;
197 	view->recursionacl = NULL;
198 	view->recursiononacl = NULL;
199 	view->sortlist = NULL;
200 	view->transferacl = NULL;
201 	view->notifyacl = NULL;
202 	view->updateacl = NULL;
203 	view->upfwdacl = NULL;
204 	view->denyansweracl = NULL;
205 	view->nocasecompress = NULL;
206 	view->msgcompression = true;
207 	view->answeracl_exclude = NULL;
208 	view->denyanswernames = NULL;
209 	view->answernames_exclude = NULL;
210 	view->rrl = NULL;
211 	view->provideixfr = true;
212 	view->maxcachettl = 7 * 24 * 3600;
213 	view->maxncachettl = 3 * 3600;
214 	view->mincachettl = 0;
215 	view->minncachettl = 0;
216 	view->nta_lifetime = 0;
217 	view->nta_recheck = 0;
218 	view->prefetch_eligible = 0;
219 	view->prefetch_trigger = 0;
220 	view->dstport = 53;
221 	view->preferred_glue = 0;
222 	view->flush = false;
223 	view->maxudp = 0;
224 	view->staleanswerttl = 1;
225 	view->staleanswersok = dns_stale_answer_conf;
226 	view->staleanswersenable = false;
227 	view->nocookieudp = 0;
228 	view->padding = 0;
229 	view->pad_acl = NULL;
230 	view->maxbits = 0;
231 	view->rpzs = NULL;
232 	view->catzs = NULL;
233 	view->managed_keys = NULL;
234 	view->redirect = NULL;
235 	view->redirectzone = NULL;
236 	dns_fixedname_init(&view->redirectfixed);
237 	view->requestnsid = false;
238 	view->sendcookie = true;
239 	view->requireservercookie = false;
240 	view->synthfromdnssec = true;
241 	view->trust_anchor_telemetry = true;
242 	view->root_key_sentinel = true;
243 	view->new_zone_dir = NULL;
244 	view->new_zone_file = NULL;
245 	view->new_zone_db = NULL;
246 	view->new_zone_dbenv = NULL;
247 	view->new_zone_mapsize = 0ULL;
248 	view->new_zone_config = NULL;
249 	view->cfg_destroy = NULL;
250 	view->fail_ttl = 0;
251 	view->failcache = NULL;
252 	result = dns_badcache_init(view->mctx, DNS_VIEW_FAILCACHESIZE,
253 				   &view->failcache);
254 	if (result != ISC_R_SUCCESS) {
255 		goto cleanup_dynkeys;
256 	}
257 	view->v6bias = 0;
258 	view->dtenv = NULL;
259 	view->dttypes = 0;
260 
261 	view->plugins = NULL;
262 	view->plugins_free = NULL;
263 	view->hooktable = NULL;
264 	view->hooktable_free = NULL;
265 
266 	isc_mutex_init(&view->new_zone_lock);
267 
268 	result = dns_order_create(view->mctx, &view->order);
269 	if (result != ISC_R_SUCCESS) {
270 		goto cleanup_new_zone_lock;
271 	}
272 
273 	result = dns_peerlist_new(view->mctx, &view->peers);
274 	if (result != ISC_R_SUCCESS) {
275 		goto cleanup_order;
276 	}
277 
278 	result = dns_aclenv_create(view->mctx, &view->aclenv);
279 	if (result != ISC_R_SUCCESS) {
280 		goto cleanup_peerlist;
281 	}
282 
283 	ISC_LINK_INIT(view, link);
284 	ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL,
285 		       DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown, view, NULL,
286 		       NULL, NULL);
287 	ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL,
288 		       DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown, view, NULL,
289 		       NULL, NULL);
290 	ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL,
291 		       DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown, view, NULL,
292 		       NULL, NULL);
293 	view->viewlist = NULL;
294 	view->magic = DNS_VIEW_MAGIC;
295 
296 	*viewp = view;
297 
298 	return (ISC_R_SUCCESS);
299 
300 cleanup_peerlist:
301 	if (view->peers != NULL) {
302 		dns_peerlist_detach(&view->peers);
303 	}
304 
305 cleanup_order:
306 	if (view->order != NULL) {
307 		dns_order_detach(&view->order);
308 	}
309 
310 cleanup_new_zone_lock:
311 	isc_mutex_destroy(&view->new_zone_lock);
312 
313 	dns_badcache_destroy(&view->failcache);
314 
315 cleanup_dynkeys:
316 	if (view->dynamickeys != NULL) {
317 		dns_tsigkeyring_detach(&view->dynamickeys);
318 	}
319 
320 cleanup_weakrefs:
321 	isc_refcount_decrementz(&view->weakrefs);
322 	isc_refcount_destroy(&view->weakrefs);
323 
324 	isc_refcount_decrementz(&view->references);
325 	isc_refcount_destroy(&view->references);
326 
327 	if (view->fwdtable != NULL) {
328 		dns_fwdtable_destroy(&view->fwdtable);
329 	}
330 
331 cleanup_zt:
332 	if (view->zonetable != NULL) {
333 		dns_zt_detach(&view->zonetable);
334 	}
335 
336 cleanup_mutex:
337 	isc_mutex_destroy(&view->lock);
338 
339 	if (view->nta_file != NULL) {
340 		isc_mem_free(mctx, view->nta_file);
341 	}
342 
343 cleanup_name:
344 	isc_mem_free(mctx, view->name);
345 	isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
346 
347 	return (result);
348 }
349 
350 static inline void
destroy(dns_view_t * view)351 destroy(dns_view_t *view) {
352 	dns_dns64_t *dns64;
353 	dns_dlzdb_t *dlzdb;
354 
355 	REQUIRE(!ISC_LINK_LINKED(view, link));
356 	REQUIRE(RESSHUTDOWN(view));
357 	REQUIRE(ADBSHUTDOWN(view));
358 	REQUIRE(REQSHUTDOWN(view));
359 
360 	isc_refcount_destroy(&view->references);
361 	isc_refcount_destroy(&view->weakrefs);
362 
363 	if (view->order != NULL) {
364 		dns_order_detach(&view->order);
365 	}
366 	if (view->peers != NULL) {
367 		dns_peerlist_detach(&view->peers);
368 	}
369 
370 	if (view->dynamickeys != NULL) {
371 		isc_result_t result;
372 		char template[PATH_MAX];
373 		char keyfile[PATH_MAX];
374 		FILE *fp = NULL;
375 
376 		result = isc_file_mktemplate(NULL, template, sizeof(template));
377 		if (result == ISC_R_SUCCESS) {
378 			(void)isc_file_openuniqueprivate(template, &fp);
379 		}
380 		if (fp == NULL) {
381 			dns_tsigkeyring_detach(&view->dynamickeys);
382 		} else {
383 			result = dns_tsigkeyring_dumpanddetach(
384 				&view->dynamickeys, fp);
385 			if (result == ISC_R_SUCCESS) {
386 				if (fclose(fp) == 0) {
387 					result = isc_file_sanitize(
388 						NULL, view->name, "tsigkeys",
389 						keyfile, sizeof(keyfile));
390 					if (result == ISC_R_SUCCESS) {
391 						result = isc_file_rename(
392 							template, keyfile);
393 					}
394 				}
395 				if (result != ISC_R_SUCCESS) {
396 					(void)remove(template);
397 				}
398 			} else {
399 				(void)fclose(fp);
400 				(void)remove(template);
401 			}
402 		}
403 	}
404 	if (view->transports != NULL) {
405 		dns_transport_list_detach(&view->transports);
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_detach(&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 
638 		if (!RESSHUTDOWN(view)) {
639 			dns_resolver_shutdown(view->resolver);
640 		}
641 		if (!ADBSHUTDOWN(view)) {
642 			dns_adb_shutdown(view->adb);
643 		}
644 		if (!REQSHUTDOWN(view)) {
645 			dns_requestmgr_shutdown(view->requestmgr);
646 		}
647 
648 		if (view->zonetable != NULL && view->flush) {
649 			dns_zt_flushanddetach(&view->zonetable);
650 		} else if (view->zonetable != NULL) {
651 			dns_zt_detach(&view->zonetable);
652 		}
653 
654 		LOCK(&view->lock);
655 		if (view->managed_keys != NULL) {
656 			mkzone = view->managed_keys;
657 			view->managed_keys = NULL;
658 			if (view->flush) {
659 				dns_zone_flush(mkzone);
660 			}
661 		}
662 		if (view->redirect != NULL) {
663 			rdzone = view->redirect;
664 			view->redirect = NULL;
665 			if (view->flush) {
666 				dns_zone_flush(rdzone);
667 			}
668 		}
669 		if (view->catzs != NULL) {
670 			dns_catz_catzs_detach(&view->catzs);
671 		}
672 		if (view->ntatable_priv != NULL) {
673 			dns_ntatable_shutdown(view->ntatable_priv);
674 		}
675 		UNLOCK(&view->lock);
676 
677 		/* Need to detach zones outside view lock */
678 		if (mkzone != NULL) {
679 			dns_zone_detach(&mkzone);
680 		}
681 
682 		if (rdzone != NULL) {
683 			dns_zone_detach(&rdzone);
684 		}
685 
686 		dns_view_weakdetach(&view);
687 	}
688 }
689 
690 void
dns_view_flushanddetach(dns_view_t ** viewp)691 dns_view_flushanddetach(dns_view_t **viewp) {
692 	view_flushanddetach(viewp, true);
693 }
694 
695 void
dns_view_detach(dns_view_t ** viewp)696 dns_view_detach(dns_view_t **viewp) {
697 	view_flushanddetach(viewp, false);
698 }
699 
700 static isc_result_t
dialup(dns_zone_t * zone,void * dummy)701 dialup(dns_zone_t *zone, void *dummy) {
702 	UNUSED(dummy);
703 	dns_zone_dialup(zone);
704 	return (ISC_R_SUCCESS);
705 }
706 
707 void
dns_view_dialup(dns_view_t * view)708 dns_view_dialup(dns_view_t *view) {
709 	REQUIRE(DNS_VIEW_VALID(view));
710 	REQUIRE(view->zonetable != NULL);
711 
712 	(void)dns_zt_apply(view->zonetable, false, NULL, 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_nm_t * nm,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, isc_nm_t *nm,
801 			isc_timermgr_t *timermgr, unsigned int options,
802 			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, nm, timermgr,
820 				     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");
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(
846 		view->mctx, dns_resolver_taskmgr(view->resolver),
847 		dns_resolver_dispatchmgr(view->resolver), dispatchv4,
848 		dispatchv6, &view->requestmgr);
849 	if (result != ISC_R_SUCCESS) {
850 		dns_adb_shutdown(view->adb);
851 		dns_resolver_shutdown(view->resolver);
852 		return (result);
853 	}
854 	event = &view->reqevent;
855 	dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event);
856 	atomic_fetch_and(&view->attributes, ~DNS_VIEWATTR_REQSHUTDOWN);
857 	isc_refcount_increment(&view->weakrefs);
858 
859 	return (ISC_R_SUCCESS);
860 }
861 
862 void
dns_view_setcache(dns_view_t * view,dns_cache_t * cache,bool shared)863 dns_view_setcache(dns_view_t *view, dns_cache_t *cache, bool shared) {
864 	REQUIRE(DNS_VIEW_VALID(view));
865 	REQUIRE(!view->frozen);
866 
867 	view->cacheshared = shared;
868 	if (view->cache != NULL) {
869 		dns_db_detach(&view->cachedb);
870 		dns_cache_detach(&view->cache);
871 	}
872 	dns_cache_attach(cache, &view->cache);
873 	dns_cache_attachdb(cache, &view->cachedb);
874 	INSIST(DNS_DB_VALID(view->cachedb));
875 }
876 
877 bool
dns_view_iscacheshared(dns_view_t * view)878 dns_view_iscacheshared(dns_view_t *view) {
879 	REQUIRE(DNS_VIEW_VALID(view));
880 
881 	return (view->cacheshared);
882 }
883 
884 void
dns_view_sethints(dns_view_t * view,dns_db_t * hints)885 dns_view_sethints(dns_view_t *view, dns_db_t *hints) {
886 	REQUIRE(DNS_VIEW_VALID(view));
887 	REQUIRE(!view->frozen);
888 	REQUIRE(view->hints == NULL);
889 	REQUIRE(dns_db_iszone(hints));
890 
891 	dns_db_attach(hints, &view->hints);
892 }
893 
894 void
dns_view_settransports(dns_view_t * view,dns_transport_list_t * list)895 dns_view_settransports(dns_view_t *view, dns_transport_list_t *list) {
896 	REQUIRE(DNS_VIEW_VALID(view));
897 	REQUIRE(list != NULL);
898 	if (view->transports != NULL) {
899 		dns_transport_list_detach(&view->transports);
900 	}
901 	dns_transport_list_attach(list, &view->transports);
902 }
903 
904 void
dns_view_setkeyring(dns_view_t * view,dns_tsig_keyring_t * ring)905 dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
906 	REQUIRE(DNS_VIEW_VALID(view));
907 	REQUIRE(ring != NULL);
908 	if (view->statickeys != NULL) {
909 		dns_tsigkeyring_detach(&view->statickeys);
910 	}
911 	dns_tsigkeyring_attach(ring, &view->statickeys);
912 }
913 
914 void
dns_view_setdynamickeyring(dns_view_t * view,dns_tsig_keyring_t * ring)915 dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
916 	REQUIRE(DNS_VIEW_VALID(view));
917 	REQUIRE(ring != NULL);
918 	if (view->dynamickeys != NULL) {
919 		dns_tsigkeyring_detach(&view->dynamickeys);
920 	}
921 	dns_tsigkeyring_attach(ring, &view->dynamickeys);
922 }
923 
924 void
dns_view_getdynamickeyring(dns_view_t * view,dns_tsig_keyring_t ** ringp)925 dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp) {
926 	REQUIRE(DNS_VIEW_VALID(view));
927 	REQUIRE(ringp != NULL && *ringp == NULL);
928 	if (view->dynamickeys != NULL) {
929 		dns_tsigkeyring_attach(view->dynamickeys, ringp);
930 	}
931 }
932 
933 void
dns_view_restorekeyring(dns_view_t * view)934 dns_view_restorekeyring(dns_view_t *view) {
935 	FILE *fp;
936 	char keyfile[PATH_MAX];
937 	isc_result_t result;
938 
939 	REQUIRE(DNS_VIEW_VALID(view));
940 
941 	if (view->dynamickeys != NULL) {
942 		result = isc_file_sanitize(NULL, view->name, "tsigkeys",
943 					   keyfile, sizeof(keyfile));
944 		if (result == ISC_R_SUCCESS) {
945 			fp = fopen(keyfile, "r");
946 			if (fp != NULL) {
947 				dns_keyring_restore(view->dynamickeys, fp);
948 				(void)fclose(fp);
949 			}
950 		}
951 	}
952 }
953 
954 void
dns_view_setdstport(dns_view_t * view,in_port_t dstport)955 dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
956 	REQUIRE(DNS_VIEW_VALID(view));
957 	view->dstport = dstport;
958 }
959 
960 void
dns_view_freeze(dns_view_t * view)961 dns_view_freeze(dns_view_t *view) {
962 	REQUIRE(DNS_VIEW_VALID(view));
963 	REQUIRE(!view->frozen);
964 
965 	if (view->resolver != NULL) {
966 		INSIST(view->cachedb != NULL);
967 		dns_resolver_freeze(view->resolver);
968 	}
969 	view->frozen = true;
970 }
971 
972 void
dns_view_thaw(dns_view_t * view)973 dns_view_thaw(dns_view_t *view) {
974 	REQUIRE(DNS_VIEW_VALID(view));
975 	REQUIRE(view->frozen);
976 
977 	view->frozen = false;
978 }
979 
980 isc_result_t
dns_view_addzone(dns_view_t * view,dns_zone_t * zone)981 dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
982 	isc_result_t result;
983 
984 	REQUIRE(DNS_VIEW_VALID(view));
985 	REQUIRE(!view->frozen);
986 	REQUIRE(view->zonetable != NULL);
987 
988 	result = dns_zt_mount(view->zonetable, zone);
989 
990 	return (result);
991 }
992 
993 isc_result_t
dns_view_findzone(dns_view_t * view,const dns_name_t * name,dns_zone_t ** zonep)994 dns_view_findzone(dns_view_t *view, const dns_name_t *name,
995 		  dns_zone_t **zonep) {
996 	isc_result_t result;
997 
998 	REQUIRE(DNS_VIEW_VALID(view));
999 
1000 	LOCK(&view->lock);
1001 	if (view->zonetable != NULL) {
1002 		result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
1003 		if (result == DNS_R_PARTIALMATCH) {
1004 			dns_zone_detach(zonep);
1005 			result = ISC_R_NOTFOUND;
1006 		}
1007 	} else {
1008 		result = ISC_R_NOTFOUND;
1009 	}
1010 	UNLOCK(&view->lock);
1011 
1012 	return (result);
1013 }
1014 
1015 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)1016 dns_view_find(dns_view_t *view, const dns_name_t *name, dns_rdatatype_t type,
1017 	      isc_stdtime_t now, unsigned int options, bool use_hints,
1018 	      bool use_static_stub, dns_db_t **dbp, dns_dbnode_t **nodep,
1019 	      dns_name_t *foundname, dns_rdataset_t *rdataset,
1020 	      dns_rdataset_t *sigrdataset) {
1021 	isc_result_t result;
1022 	dns_db_t *db, *zdb;
1023 	dns_dbnode_t *node, *znode;
1024 	bool is_cache, is_staticstub_zone;
1025 	dns_rdataset_t zrdataset, zsigrdataset;
1026 	dns_zone_t *zone;
1027 
1028 	/*
1029 	 * Find an rdataset whose owner name is 'name', and whose type is
1030 	 * 'type'.
1031 	 */
1032 
1033 	REQUIRE(DNS_VIEW_VALID(view));
1034 	REQUIRE(view->frozen);
1035 	REQUIRE(type != dns_rdatatype_rrsig);
1036 	REQUIRE(rdataset != NULL); /* XXXBEW - remove this */
1037 	REQUIRE(nodep == NULL || *nodep == NULL);
1038 
1039 	/*
1040 	 * Initialize.
1041 	 */
1042 	dns_rdataset_init(&zrdataset);
1043 	dns_rdataset_init(&zsigrdataset);
1044 	zdb = NULL;
1045 	znode = NULL;
1046 
1047 	/*
1048 	 * Find a database to answer the query.
1049 	 */
1050 	db = NULL;
1051 	node = NULL;
1052 	is_staticstub_zone = false;
1053 	zone = NULL;
1054 	LOCK(&view->lock);
1055 	if (view->zonetable != NULL) {
1056 		result = dns_zt_find(view->zonetable, name, DNS_ZTFIND_MIRROR,
1057 				     NULL, &zone);
1058 	} else {
1059 		result = ISC_R_NOTFOUND;
1060 	}
1061 	UNLOCK(&view->lock);
1062 	if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub &&
1063 	    !use_static_stub)
1064 	{
1065 		result = ISC_R_NOTFOUND;
1066 	}
1067 	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
1068 		result = dns_zone_getdb(zone, &db);
1069 		if (result != ISC_R_SUCCESS && view->cachedb != NULL) {
1070 			dns_db_attach(view->cachedb, &db);
1071 		} else if (result != ISC_R_SUCCESS) {
1072 			goto cleanup;
1073 		}
1074 		if (dns_zone_gettype(zone) == dns_zone_staticstub &&
1075 		    dns_name_equal(name, dns_zone_getorigin(zone)))
1076 		{
1077 			is_staticstub_zone = true;
1078 		}
1079 	} else if (result == ISC_R_NOTFOUND && view->cachedb != NULL) {
1080 		dns_db_attach(view->cachedb, &db);
1081 	} else {
1082 		goto cleanup;
1083 	}
1084 
1085 	is_cache = dns_db_iscache(db);
1086 
1087 db_find:
1088 	/*
1089 	 * Now look for an answer in the database.
1090 	 */
1091 	result = dns_db_find(db, name, NULL, type, options, now, &node,
1092 			     foundname, rdataset, sigrdataset);
1093 
1094 	if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) {
1095 		if (dns_rdataset_isassociated(rdataset)) {
1096 			dns_rdataset_disassociate(rdataset);
1097 		}
1098 		if (sigrdataset != NULL &&
1099 		    dns_rdataset_isassociated(sigrdataset)) {
1100 			dns_rdataset_disassociate(sigrdataset);
1101 		}
1102 		if (node != NULL) {
1103 			dns_db_detachnode(db, &node);
1104 		}
1105 		if (!is_cache) {
1106 			dns_db_detach(&db);
1107 			if (view->cachedb != NULL && !is_staticstub_zone) {
1108 				/*
1109 				 * Either the answer is in the cache, or we
1110 				 * don't know it.
1111 				 * Note that if the result comes from a
1112 				 * static-stub zone we stop the search here
1113 				 * (see the function description in view.h).
1114 				 */
1115 				is_cache = true;
1116 				dns_db_attach(view->cachedb, &db);
1117 				goto db_find;
1118 			}
1119 		} else {
1120 			/*
1121 			 * We don't have the data in the cache.  If we've got
1122 			 * glue from the zone, use it.
1123 			 */
1124 			if (dns_rdataset_isassociated(&zrdataset)) {
1125 				dns_rdataset_clone(&zrdataset, rdataset);
1126 				if (sigrdataset != NULL &&
1127 				    dns_rdataset_isassociated(&zsigrdataset)) {
1128 					dns_rdataset_clone(&zsigrdataset,
1129 							   sigrdataset);
1130 				}
1131 				result = DNS_R_GLUE;
1132 				if (db != NULL) {
1133 					dns_db_detach(&db);
1134 				}
1135 				dns_db_attach(zdb, &db);
1136 				dns_db_attachnode(db, znode, &node);
1137 				goto cleanup;
1138 			}
1139 		}
1140 		/*
1141 		 * We don't know the answer.
1142 		 */
1143 		result = ISC_R_NOTFOUND;
1144 	} else if (result == DNS_R_GLUE) {
1145 		if (view->cachedb != NULL && !is_staticstub_zone) {
1146 			/*
1147 			 * We found an answer, but the cache may be better.
1148 			 * Remember what we've got and go look in the cache.
1149 			 */
1150 			is_cache = true;
1151 			dns_rdataset_clone(rdataset, &zrdataset);
1152 			dns_rdataset_disassociate(rdataset);
1153 			if (sigrdataset != NULL &&
1154 			    dns_rdataset_isassociated(sigrdataset)) {
1155 				dns_rdataset_clone(sigrdataset, &zsigrdataset);
1156 				dns_rdataset_disassociate(sigrdataset);
1157 			}
1158 			dns_db_attach(db, &zdb);
1159 			dns_db_attachnode(zdb, node, &znode);
1160 			dns_db_detachnode(db, &node);
1161 			dns_db_detach(&db);
1162 			dns_db_attach(view->cachedb, &db);
1163 			goto db_find;
1164 		}
1165 		/*
1166 		 * Otherwise, the glue is the best answer.
1167 		 */
1168 		result = ISC_R_SUCCESS;
1169 	}
1170 
1171 	if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
1172 		if (dns_rdataset_isassociated(rdataset)) {
1173 			dns_rdataset_disassociate(rdataset);
1174 		}
1175 		if (sigrdataset != NULL &&
1176 		    dns_rdataset_isassociated(sigrdataset)) {
1177 			dns_rdataset_disassociate(sigrdataset);
1178 		}
1179 		if (db != NULL) {
1180 			if (node != NULL) {
1181 				dns_db_detachnode(db, &node);
1182 			}
1183 			dns_db_detach(&db);
1184 		}
1185 		result = dns_db_find(view->hints, name, NULL, type, options,
1186 				     now, &node, foundname, rdataset,
1187 				     sigrdataset);
1188 		if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) {
1189 			/*
1190 			 * We just used a hint.  Let the resolver know it
1191 			 * should consider priming.
1192 			 */
1193 			dns_resolver_prime(view->resolver);
1194 			dns_db_attach(view->hints, &db);
1195 			result = DNS_R_HINT;
1196 		} else if (result == DNS_R_NXRRSET) {
1197 			dns_db_attach(view->hints, &db);
1198 			result = DNS_R_HINTNXRRSET;
1199 		} else if (result == DNS_R_NXDOMAIN) {
1200 			result = ISC_R_NOTFOUND;
1201 		}
1202 
1203 		/*
1204 		 * Cleanup if non-standard hints are used.
1205 		 */
1206 		if (db == NULL && node != NULL) {
1207 			dns_db_detachnode(view->hints, &node);
1208 		}
1209 	}
1210 
1211 cleanup:
1212 	if (dns_rdataset_isassociated(&zrdataset)) {
1213 		dns_rdataset_disassociate(&zrdataset);
1214 		if (dns_rdataset_isassociated(&zsigrdataset)) {
1215 			dns_rdataset_disassociate(&zsigrdataset);
1216 		}
1217 	}
1218 
1219 	if (zdb != NULL) {
1220 		if (znode != NULL) {
1221 			dns_db_detachnode(zdb, &znode);
1222 		}
1223 		dns_db_detach(&zdb);
1224 	}
1225 
1226 	if (db != NULL) {
1227 		if (node != NULL) {
1228 			if (nodep != NULL) {
1229 				*nodep = node;
1230 			} else {
1231 				dns_db_detachnode(db, &node);
1232 			}
1233 		}
1234 		if (dbp != NULL) {
1235 			*dbp = db;
1236 		} else {
1237 			dns_db_detach(&db);
1238 		}
1239 	} else {
1240 		INSIST(node == NULL);
1241 	}
1242 
1243 	if (zone != NULL) {
1244 		dns_zone_detach(&zone);
1245 	}
1246 
1247 	return (result);
1248 }
1249 
1250 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)1251 dns_view_simplefind(dns_view_t *view, const dns_name_t *name,
1252 		    dns_rdatatype_t type, isc_stdtime_t now,
1253 		    unsigned int options, bool use_hints,
1254 		    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
1255 	isc_result_t result;
1256 	dns_fixedname_t foundname;
1257 
1258 	dns_fixedname_init(&foundname);
1259 	result = dns_view_find(view, name, type, now, options, use_hints, false,
1260 			       NULL, NULL, dns_fixedname_name(&foundname),
1261 			       rdataset, sigrdataset);
1262 	if (result == DNS_R_NXDOMAIN) {
1263 		/*
1264 		 * The rdataset and sigrdataset of the relevant NSEC record
1265 		 * may be returned, but the caller cannot use them because
1266 		 * foundname is not returned by this simplified API.  We
1267 		 * disassociate them here to prevent any misuse by the caller.
1268 		 */
1269 		if (dns_rdataset_isassociated(rdataset)) {
1270 			dns_rdataset_disassociate(rdataset);
1271 		}
1272 		if (sigrdataset != NULL &&
1273 		    dns_rdataset_isassociated(sigrdataset)) {
1274 			dns_rdataset_disassociate(sigrdataset);
1275 		}
1276 	} else if (result != ISC_R_SUCCESS && result != DNS_R_GLUE &&
1277 		   result != DNS_R_HINT && result != DNS_R_NCACHENXDOMAIN &&
1278 		   result != DNS_R_NCACHENXRRSET && result != DNS_R_NXRRSET &&
1279 		   result != DNS_R_HINTNXRRSET && result != ISC_R_NOTFOUND)
1280 	{
1281 		if (dns_rdataset_isassociated(rdataset)) {
1282 			dns_rdataset_disassociate(rdataset);
1283 		}
1284 		if (sigrdataset != NULL &&
1285 		    dns_rdataset_isassociated(sigrdataset)) {
1286 			dns_rdataset_disassociate(sigrdataset);
1287 		}
1288 		result = ISC_R_NOTFOUND;
1289 	}
1290 
1291 	return (result);
1292 }
1293 
1294 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)1295 dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
1296 		     dns_name_t *fname, dns_name_t *dcname, isc_stdtime_t now,
1297 		     unsigned int options, bool use_hints, bool use_cache,
1298 		     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
1299 	isc_result_t result;
1300 	dns_db_t *db;
1301 	bool is_cache, use_zone, try_hints;
1302 	dns_zone_t *zone;
1303 	dns_name_t *zfname;
1304 	dns_rdataset_t zrdataset, zsigrdataset;
1305 	dns_fixedname_t zfixedname;
1306 	unsigned int ztoptions = DNS_ZTFIND_MIRROR;
1307 
1308 	REQUIRE(DNS_VIEW_VALID(view));
1309 	REQUIRE(view->frozen);
1310 
1311 	db = NULL;
1312 	use_zone = false;
1313 	try_hints = false;
1314 	zfname = NULL;
1315 
1316 	/*
1317 	 * Initialize.
1318 	 */
1319 	dns_fixedname_init(&zfixedname);
1320 	dns_rdataset_init(&zrdataset);
1321 	dns_rdataset_init(&zsigrdataset);
1322 
1323 	/*
1324 	 * Find the right database.
1325 	 */
1326 	zone = NULL;
1327 	LOCK(&view->lock);
1328 	if (view->zonetable != NULL) {
1329 		if ((options & DNS_DBFIND_NOEXACT) != 0) {
1330 			ztoptions |= DNS_ZTFIND_NOEXACT;
1331 		}
1332 		result = dns_zt_find(view->zonetable, name, ztoptions, NULL,
1333 				     &zone);
1334 	} else {
1335 		result = ISC_R_NOTFOUND;
1336 	}
1337 	UNLOCK(&view->lock);
1338 	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
1339 		result = dns_zone_getdb(zone, &db);
1340 	}
1341 	if (result == ISC_R_NOTFOUND) {
1342 		/*
1343 		 * We're not directly authoritative for this query name, nor
1344 		 * is it a subdomain of any zone for which we're
1345 		 * authoritative.
1346 		 */
1347 		if (use_cache && view->cachedb != NULL) {
1348 			/*
1349 			 * We have a cache; try it.
1350 			 */
1351 			dns_db_attach(view->cachedb, &db);
1352 		} else if (use_hints && view->hints != NULL) {
1353 			/*
1354 			 * Maybe we have hints...
1355 			 */
1356 			try_hints = true;
1357 			goto finish;
1358 		} else {
1359 			result = DNS_R_NXDOMAIN;
1360 			goto cleanup;
1361 		}
1362 	} else if (result != ISC_R_SUCCESS) {
1363 		/*
1364 		 * Something is broken.
1365 		 */
1366 		goto cleanup;
1367 	}
1368 	is_cache = dns_db_iscache(db);
1369 
1370 db_find:
1371 	/*
1372 	 * Look for the zonecut.
1373 	 */
1374 	if (!is_cache) {
1375 		result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options,
1376 				     now, NULL, fname, rdataset, sigrdataset);
1377 		if (result == DNS_R_DELEGATION) {
1378 			result = ISC_R_SUCCESS;
1379 		} else if (result != ISC_R_SUCCESS) {
1380 			goto cleanup;
1381 		}
1382 
1383 		if (use_cache && view->cachedb != NULL && db != view->hints) {
1384 			/*
1385 			 * We found an answer, but the cache may be better.
1386 			 */
1387 			zfname = dns_fixedname_name(&zfixedname);
1388 			dns_name_copy(fname, zfname);
1389 			dns_rdataset_clone(rdataset, &zrdataset);
1390 			dns_rdataset_disassociate(rdataset);
1391 			if (sigrdataset != NULL &&
1392 			    dns_rdataset_isassociated(sigrdataset)) {
1393 				dns_rdataset_clone(sigrdataset, &zsigrdataset);
1394 				dns_rdataset_disassociate(sigrdataset);
1395 			}
1396 			dns_db_detach(&db);
1397 			dns_db_attach(view->cachedb, &db);
1398 			is_cache = true;
1399 			goto db_find;
1400 		}
1401 	} else {
1402 		result = dns_db_findzonecut(db, name, options, now, NULL, fname,
1403 					    dcname, rdataset, sigrdataset);
1404 		if (result == ISC_R_SUCCESS) {
1405 			if (zfname != NULL &&
1406 			    (!dns_name_issubdomain(fname, zfname) ||
1407 			     (dns_zone_gettype(zone) == dns_zone_staticstub &&
1408 			      dns_name_equal(fname, zfname))))
1409 			{
1410 				/*
1411 				 * We found a zonecut in the cache, but our
1412 				 * zone delegation is better.
1413 				 */
1414 				use_zone = true;
1415 			}
1416 		} else if (result == ISC_R_NOTFOUND) {
1417 			if (zfname != NULL) {
1418 				/*
1419 				 * We didn't find anything in the cache, but we
1420 				 * have a zone delegation, so use it.
1421 				 */
1422 				use_zone = true;
1423 				result = ISC_R_SUCCESS;
1424 			} else if (use_hints && view->hints != NULL) {
1425 				/*
1426 				 * Maybe we have hints...
1427 				 */
1428 				try_hints = true;
1429 				result = ISC_R_SUCCESS;
1430 			} else {
1431 				result = DNS_R_NXDOMAIN;
1432 			}
1433 		} else {
1434 			/*
1435 			 * Something bad happened.
1436 			 */
1437 			goto cleanup;
1438 		}
1439 	}
1440 
1441 finish:
1442 	if (use_zone) {
1443 		if (dns_rdataset_isassociated(rdataset)) {
1444 			dns_rdataset_disassociate(rdataset);
1445 			if (sigrdataset != NULL &&
1446 			    dns_rdataset_isassociated(sigrdataset)) {
1447 				dns_rdataset_disassociate(sigrdataset);
1448 			}
1449 		}
1450 		dns_name_copy(zfname, fname);
1451 		if (dcname != NULL) {
1452 			dns_name_copy(zfname, dcname);
1453 		}
1454 		dns_rdataset_clone(&zrdataset, rdataset);
1455 		if (sigrdataset != NULL &&
1456 		    dns_rdataset_isassociated(&zrdataset)) {
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_copy(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_gettransport(dns_view_t * view,const dns_transport_type_t type,const dns_name_t * name,dns_transport_t ** transportp)1610 dns_view_gettransport(dns_view_t *view, const dns_transport_type_t type,
1611 		      const dns_name_t *name, dns_transport_t **transportp) {
1612 	REQUIRE(DNS_VIEW_VALID(view));
1613 	REQUIRE(transportp != NULL && *transportp == NULL);
1614 
1615 	dns_transport_t *transport = dns_transport_find(type, name,
1616 							view->transports);
1617 	if (transport == NULL) {
1618 		return (ISC_R_NOTFOUND);
1619 	}
1620 
1621 	*transportp = transport;
1622 	return (ISC_R_SUCCESS);
1623 }
1624 
1625 isc_result_t
dns_view_getpeertsig(dns_view_t * view,const isc_netaddr_t * peeraddr,dns_tsigkey_t ** keyp)1626 dns_view_getpeertsig(dns_view_t *view, const isc_netaddr_t *peeraddr,
1627 		     dns_tsigkey_t **keyp) {
1628 	isc_result_t result;
1629 	dns_name_t *keyname = NULL;
1630 	dns_peer_t *peer = NULL;
1631 
1632 	result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer);
1633 	if (result != ISC_R_SUCCESS) {
1634 		return (result);
1635 	}
1636 
1637 	result = dns_peer_getkey(peer, &keyname);
1638 	if (result != ISC_R_SUCCESS) {
1639 		return (result);
1640 	}
1641 
1642 	result = dns_view_gettsig(view, keyname, keyp);
1643 	return ((result == ISC_R_NOTFOUND) ? ISC_R_FAILURE : result);
1644 }
1645 
1646 isc_result_t
dns_view_checksig(dns_view_t * view,isc_buffer_t * source,dns_message_t * msg)1647 dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
1648 	REQUIRE(DNS_VIEW_VALID(view));
1649 	REQUIRE(source != NULL);
1650 
1651 	return (dns_tsig_verify(source, msg, view->statickeys,
1652 				view->dynamickeys));
1653 }
1654 
1655 isc_result_t
dns_view_dumpdbtostream(dns_view_t * view,FILE * fp)1656 dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
1657 	isc_result_t result;
1658 
1659 	REQUIRE(DNS_VIEW_VALID(view));
1660 
1661 	(void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name);
1662 	result = dns_master_dumptostream(view->mctx, view->cachedb, NULL,
1663 					 &dns_master_style_cache,
1664 					 dns_masterformat_text, NULL, fp);
1665 	if (result != ISC_R_SUCCESS) {
1666 		return (result);
1667 	}
1668 	dns_adb_dump(view->adb, fp);
1669 	dns_resolver_printbadcache(view->resolver, fp);
1670 	dns_badcache_print(view->failcache, "SERVFAIL cache", fp);
1671 	return (ISC_R_SUCCESS);
1672 }
1673 
1674 isc_result_t
dns_view_flushcache(dns_view_t * view,bool fixuponly)1675 dns_view_flushcache(dns_view_t *view, bool fixuponly) {
1676 	isc_result_t result;
1677 
1678 	REQUIRE(DNS_VIEW_VALID(view));
1679 
1680 	if (view->cachedb == NULL) {
1681 		return (ISC_R_SUCCESS);
1682 	}
1683 	if (!fixuponly) {
1684 		result = dns_cache_flush(view->cache);
1685 		if (result != ISC_R_SUCCESS) {
1686 			return (result);
1687 		}
1688 	}
1689 	dns_db_detach(&view->cachedb);
1690 	dns_cache_attachdb(view->cache, &view->cachedb);
1691 	if (view->resolver != NULL) {
1692 		dns_resolver_flushbadcache(view->resolver, NULL);
1693 	}
1694 	if (view->failcache != NULL) {
1695 		dns_badcache_flush(view->failcache);
1696 	}
1697 
1698 	dns_adb_flush(view->adb);
1699 	return (ISC_R_SUCCESS);
1700 }
1701 
1702 isc_result_t
dns_view_flushname(dns_view_t * view,const dns_name_t * name)1703 dns_view_flushname(dns_view_t *view, const dns_name_t *name) {
1704 	return (dns_view_flushnode(view, name, false));
1705 }
1706 
1707 isc_result_t
dns_view_flushnode(dns_view_t * view,const dns_name_t * name,bool tree)1708 dns_view_flushnode(dns_view_t *view, const dns_name_t *name, bool tree) {
1709 	isc_result_t result = ISC_R_SUCCESS;
1710 
1711 	REQUIRE(DNS_VIEW_VALID(view));
1712 
1713 	if (tree) {
1714 		if (view->adb != NULL) {
1715 			dns_adb_flushnames(view->adb, name);
1716 		}
1717 		if (view->resolver != NULL) {
1718 			dns_resolver_flushbadnames(view->resolver, name);
1719 		}
1720 		if (view->failcache != NULL) {
1721 			dns_badcache_flushtree(view->failcache, name);
1722 		}
1723 	} else {
1724 		if (view->adb != NULL) {
1725 			dns_adb_flushname(view->adb, name);
1726 		}
1727 		if (view->resolver != NULL) {
1728 			dns_resolver_flushbadcache(view->resolver, name);
1729 		}
1730 		if (view->failcache != NULL) {
1731 			dns_badcache_flushname(view->failcache, name);
1732 		}
1733 	}
1734 
1735 	if (view->cache != NULL) {
1736 		result = dns_cache_flushnode(view->cache, name, tree);
1737 	}
1738 
1739 	return (result);
1740 }
1741 
1742 isc_result_t
dns_view_adddelegationonly(dns_view_t * view,const dns_name_t * name)1743 dns_view_adddelegationonly(dns_view_t *view, const dns_name_t *name) {
1744 	dns_name_t *item;
1745 	unsigned int hash;
1746 
1747 	REQUIRE(DNS_VIEW_VALID(view));
1748 
1749 	if (view->delonly == NULL) {
1750 		view->delonly = isc_mem_get(view->mctx,
1751 					    sizeof(dns_namelist_t) *
1752 						    DNS_VIEW_DELONLYHASH);
1753 		for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) {
1754 			ISC_LIST_INIT(view->delonly[hash]);
1755 		}
1756 	}
1757 	hash = dns_name_hash(name, false) % DNS_VIEW_DELONLYHASH;
1758 	item = ISC_LIST_HEAD(view->delonly[hash]);
1759 	while (item != NULL && !dns_name_equal(item, name)) {
1760 		item = ISC_LIST_NEXT(item, link);
1761 	}
1762 	if (item != NULL) {
1763 		return (ISC_R_SUCCESS);
1764 	}
1765 	item = isc_mem_get(view->mctx, sizeof(*item));
1766 	dns_name_init(item, NULL);
1767 	dns_name_dup(name, view->mctx, item);
1768 	ISC_LIST_APPEND(view->delonly[hash], item, link);
1769 	return (ISC_R_SUCCESS);
1770 }
1771 
1772 isc_result_t
dns_view_excludedelegationonly(dns_view_t * view,const dns_name_t * name)1773 dns_view_excludedelegationonly(dns_view_t *view, const dns_name_t *name) {
1774 	dns_name_t *item;
1775 	unsigned int hash;
1776 
1777 	REQUIRE(DNS_VIEW_VALID(view));
1778 
1779 	if (view->rootexclude == NULL) {
1780 		view->rootexclude = isc_mem_get(view->mctx,
1781 						sizeof(dns_namelist_t) *
1782 							DNS_VIEW_DELONLYHASH);
1783 		for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) {
1784 			ISC_LIST_INIT(view->rootexclude[hash]);
1785 		}
1786 	}
1787 	hash = dns_name_hash(name, false) % DNS_VIEW_DELONLYHASH;
1788 	item = ISC_LIST_HEAD(view->rootexclude[hash]);
1789 	while (item != NULL && !dns_name_equal(item, name)) {
1790 		item = ISC_LIST_NEXT(item, link);
1791 	}
1792 	if (item != NULL) {
1793 		return (ISC_R_SUCCESS);
1794 	}
1795 	item = isc_mem_get(view->mctx, sizeof(*item));
1796 	dns_name_init(item, NULL);
1797 	dns_name_dup(name, view->mctx, item);
1798 	ISC_LIST_APPEND(view->rootexclude[hash], item, link);
1799 	return (ISC_R_SUCCESS);
1800 }
1801 
1802 bool
dns_view_isdelegationonly(dns_view_t * view,const dns_name_t * name)1803 dns_view_isdelegationonly(dns_view_t *view, const dns_name_t *name) {
1804 	dns_name_t *item;
1805 	unsigned int hash;
1806 
1807 	REQUIRE(DNS_VIEW_VALID(view));
1808 
1809 	if (!view->rootdelonly && view->delonly == NULL) {
1810 		return (false);
1811 	}
1812 
1813 	hash = dns_name_hash(name, false) % DNS_VIEW_DELONLYHASH;
1814 	if (view->rootdelonly && dns_name_countlabels(name) <= 2) {
1815 		if (view->rootexclude == NULL) {
1816 			return (true);
1817 		}
1818 		item = ISC_LIST_HEAD(view->rootexclude[hash]);
1819 		while (item != NULL && !dns_name_equal(item, name)) {
1820 			item = ISC_LIST_NEXT(item, link);
1821 		}
1822 		if (item == NULL) {
1823 			return (true);
1824 		}
1825 	}
1826 
1827 	if (view->delonly == NULL) {
1828 		return (false);
1829 	}
1830 
1831 	item = ISC_LIST_HEAD(view->delonly[hash]);
1832 	while (item != NULL && !dns_name_equal(item, name)) {
1833 		item = ISC_LIST_NEXT(item, link);
1834 	}
1835 	if (item == NULL) {
1836 		return (false);
1837 	}
1838 	return (true);
1839 }
1840 
1841 void
dns_view_setrootdelonly(dns_view_t * view,bool value)1842 dns_view_setrootdelonly(dns_view_t *view, bool value) {
1843 	REQUIRE(DNS_VIEW_VALID(view));
1844 	view->rootdelonly = value;
1845 }
1846 
1847 bool
dns_view_getrootdelonly(dns_view_t * view)1848 dns_view_getrootdelonly(dns_view_t *view) {
1849 	REQUIRE(DNS_VIEW_VALID(view));
1850 	return (view->rootdelonly);
1851 }
1852 
1853 isc_result_t
dns_view_freezezones(dns_view_t * view,bool value)1854 dns_view_freezezones(dns_view_t *view, bool value) {
1855 	REQUIRE(DNS_VIEW_VALID(view));
1856 	REQUIRE(view->zonetable != NULL);
1857 
1858 	return (dns_zt_freezezones(view->zonetable, view, value));
1859 }
1860 
1861 void
dns_view_setadbstats(dns_view_t * view,isc_stats_t * stats)1862 dns_view_setadbstats(dns_view_t *view, isc_stats_t *stats) {
1863 	REQUIRE(DNS_VIEW_VALID(view));
1864 	REQUIRE(!view->frozen);
1865 	REQUIRE(view->adbstats == NULL);
1866 
1867 	isc_stats_attach(stats, &view->adbstats);
1868 }
1869 
1870 void
dns_view_getadbstats(dns_view_t * view,isc_stats_t ** statsp)1871 dns_view_getadbstats(dns_view_t *view, isc_stats_t **statsp) {
1872 	REQUIRE(DNS_VIEW_VALID(view));
1873 	REQUIRE(statsp != NULL && *statsp == NULL);
1874 
1875 	if (view->adbstats != NULL) {
1876 		isc_stats_attach(view->adbstats, statsp);
1877 	}
1878 }
1879 
1880 void
dns_view_setresstats(dns_view_t * view,isc_stats_t * stats)1881 dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) {
1882 	REQUIRE(DNS_VIEW_VALID(view));
1883 	REQUIRE(!view->frozen);
1884 	REQUIRE(view->resstats == NULL);
1885 
1886 	isc_stats_attach(stats, &view->resstats);
1887 }
1888 
1889 void
dns_view_getresstats(dns_view_t * view,isc_stats_t ** statsp)1890 dns_view_getresstats(dns_view_t *view, isc_stats_t **statsp) {
1891 	REQUIRE(DNS_VIEW_VALID(view));
1892 	REQUIRE(statsp != NULL && *statsp == NULL);
1893 
1894 	if (view->resstats != NULL) {
1895 		isc_stats_attach(view->resstats, statsp);
1896 	}
1897 }
1898 
1899 void
dns_view_setresquerystats(dns_view_t * view,dns_stats_t * stats)1900 dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats) {
1901 	REQUIRE(DNS_VIEW_VALID(view));
1902 	REQUIRE(!view->frozen);
1903 	REQUIRE(view->resquerystats == NULL);
1904 
1905 	dns_stats_attach(stats, &view->resquerystats);
1906 }
1907 
1908 void
dns_view_getresquerystats(dns_view_t * view,dns_stats_t ** statsp)1909 dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
1910 	REQUIRE(DNS_VIEW_VALID(view));
1911 	REQUIRE(statsp != NULL && *statsp == NULL);
1912 
1913 	if (view->resquerystats != NULL) {
1914 		dns_stats_attach(view->resquerystats, statsp);
1915 	}
1916 }
1917 
1918 isc_result_t
dns_view_initntatable(dns_view_t * view,isc_taskmgr_t * taskmgr,isc_timermgr_t * timermgr)1919 dns_view_initntatable(dns_view_t *view, isc_taskmgr_t *taskmgr,
1920 		      isc_timermgr_t *timermgr) {
1921 	REQUIRE(DNS_VIEW_VALID(view));
1922 	if (view->ntatable_priv != NULL) {
1923 		dns_ntatable_detach(&view->ntatable_priv);
1924 	}
1925 	return (dns_ntatable_create(view, taskmgr, timermgr,
1926 				    &view->ntatable_priv));
1927 }
1928 
1929 isc_result_t
dns_view_getntatable(dns_view_t * view,dns_ntatable_t ** ntp)1930 dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp) {
1931 	REQUIRE(DNS_VIEW_VALID(view));
1932 	REQUIRE(ntp != NULL && *ntp == NULL);
1933 	if (view->ntatable_priv == NULL) {
1934 		return (ISC_R_NOTFOUND);
1935 	}
1936 	dns_ntatable_attach(view->ntatable_priv, ntp);
1937 	return (ISC_R_SUCCESS);
1938 }
1939 
1940 isc_result_t
dns_view_initsecroots(dns_view_t * view,isc_mem_t * mctx)1941 dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) {
1942 	REQUIRE(DNS_VIEW_VALID(view));
1943 	if (view->secroots_priv != NULL) {
1944 		dns_keytable_detach(&view->secroots_priv);
1945 	}
1946 	return (dns_keytable_create(mctx, &view->secroots_priv));
1947 }
1948 
1949 isc_result_t
dns_view_getsecroots(dns_view_t * view,dns_keytable_t ** ktp)1950 dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) {
1951 	REQUIRE(DNS_VIEW_VALID(view));
1952 	REQUIRE(ktp != NULL && *ktp == NULL);
1953 	if (view->secroots_priv == NULL) {
1954 		return (ISC_R_NOTFOUND);
1955 	}
1956 	dns_keytable_attach(view->secroots_priv, ktp);
1957 	return (ISC_R_SUCCESS);
1958 }
1959 
1960 bool
dns_view_ntacovers(dns_view_t * view,isc_stdtime_t now,const dns_name_t * name,const dns_name_t * anchor)1961 dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now, const dns_name_t *name,
1962 		   const dns_name_t *anchor) {
1963 	REQUIRE(DNS_VIEW_VALID(view));
1964 
1965 	if (view->ntatable_priv == NULL) {
1966 		return (false);
1967 	}
1968 
1969 	return (dns_ntatable_covered(view->ntatable_priv, now, name, anchor));
1970 }
1971 
1972 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)1973 dns_view_issecuredomain(dns_view_t *view, const dns_name_t *name,
1974 			isc_stdtime_t now, bool checknta, bool *ntap,
1975 			bool *secure_domain) {
1976 	isc_result_t result;
1977 	bool secure = false;
1978 	dns_fixedname_t fn;
1979 	dns_name_t *anchor;
1980 
1981 	REQUIRE(DNS_VIEW_VALID(view));
1982 
1983 	if (view->secroots_priv == NULL) {
1984 		return (ISC_R_NOTFOUND);
1985 	}
1986 
1987 	anchor = dns_fixedname_initname(&fn);
1988 
1989 	result = dns_keytable_issecuredomain(view->secroots_priv, name, anchor,
1990 					     &secure);
1991 	if (result != ISC_R_SUCCESS) {
1992 		return (result);
1993 	}
1994 
1995 	if (ntap != NULL) {
1996 		*ntap = false;
1997 	}
1998 	if (checknta && secure && view->ntatable_priv != NULL &&
1999 	    dns_ntatable_covered(view->ntatable_priv, now, name, anchor))
2000 	{
2001 		if (ntap != NULL) {
2002 			*ntap = true;
2003 		}
2004 		secure = false;
2005 	}
2006 
2007 	*secure_domain = secure;
2008 	return (ISC_R_SUCCESS);
2009 }
2010 
2011 void
dns_view_untrust(dns_view_t * view,const dns_name_t * keyname,dns_rdata_dnskey_t * dnskey)2012 dns_view_untrust(dns_view_t *view, const dns_name_t *keyname,
2013 		 dns_rdata_dnskey_t *dnskey) {
2014 	isc_result_t result;
2015 	dns_keytable_t *sr = NULL;
2016 
2017 	REQUIRE(DNS_VIEW_VALID(view));
2018 	REQUIRE(keyname != NULL);
2019 	REQUIRE(dnskey != NULL);
2020 
2021 	/*
2022 	 * Clear the revoke bit, if set, so that the key will match what's
2023 	 * in secroots now.
2024 	 */
2025 	dnskey->flags &= ~DNS_KEYFLAG_REVOKE;
2026 
2027 	result = dns_view_getsecroots(view, &sr);
2028 	if (result != ISC_R_SUCCESS) {
2029 		return;
2030 	}
2031 
2032 	result = dns_keytable_deletekey(sr, keyname, dnskey);
2033 	if (result == ISC_R_SUCCESS) {
2034 		/*
2035 		 * If key was found in secroots, then it was a
2036 		 * configured trust anchor, and we want to fail
2037 		 * secure. If there are no other configured keys,
2038 		 * then leave a null key so that we can't validate
2039 		 * anymore.
2040 		 */
2041 		dns_keytable_marksecure(sr, keyname);
2042 	}
2043 
2044 	dns_keytable_detach(&sr);
2045 }
2046 
2047 /*
2048  * Create path to a directory and a filename constructed from viewname.
2049  * This is a front-end to isc_file_sanitize(), allowing backward
2050  * compatibility to older versions when a file couldn't be expected
2051  * to be in the specified directory but might be in the current working
2052  * directory instead.
2053  *
2054  * It first tests for the existence of a file <viewname>.<suffix> in
2055  * 'directory'. If the file does not exist, it checks again in the
2056  * current working directory. If it does not exist there either,
2057  * return the path inside the directory.
2058  *
2059  * Returns ISC_R_SUCCESS if a path to an existing file is found or
2060  * a new path is created; returns ISC_R_NOSPACE if the path won't
2061  * fit in 'buflen'.
2062  */
2063 
2064 static isc_result_t
nz_legacy(const char * directory,const char * viewname,const char * suffix,char * buffer,size_t buflen)2065 nz_legacy(const char *directory, const char *viewname, const char *suffix,
2066 	  char *buffer, size_t buflen) {
2067 	isc_result_t result;
2068 	char newbuf[PATH_MAX];
2069 
2070 	result = isc_file_sanitize(directory, viewname, suffix, buffer, buflen);
2071 	if (result != ISC_R_SUCCESS) {
2072 		return (result);
2073 	} else if (directory == NULL || isc_file_exists(buffer)) {
2074 		return (ISC_R_SUCCESS);
2075 	} else {
2076 		/* Save buffer */
2077 		strlcpy(newbuf, buffer, sizeof(newbuf));
2078 	}
2079 
2080 	/*
2081 	 * It isn't in the specified directory; check CWD.
2082 	 */
2083 	result = isc_file_sanitize(NULL, viewname, suffix, buffer, buflen);
2084 	if (result != ISC_R_SUCCESS || isc_file_exists(buffer)) {
2085 		return (result);
2086 	}
2087 
2088 	/*
2089 	 * File does not exist in either 'directory' or CWD,
2090 	 * so use the path in 'directory'.
2091 	 */
2092 	strlcpy(buffer, newbuf, buflen);
2093 	return (ISC_R_SUCCESS);
2094 }
2095 
2096 isc_result_t
dns_view_setnewzones(dns_view_t * view,bool allow,void * cfgctx,void (* cfg_destroy)(void **),uint64_t mapsize)2097 dns_view_setnewzones(dns_view_t *view, bool allow, void *cfgctx,
2098 		     void (*cfg_destroy)(void **), uint64_t mapsize) {
2099 	isc_result_t result = ISC_R_SUCCESS;
2100 	char buffer[1024];
2101 #ifdef HAVE_LMDB
2102 	MDB_env *env = NULL;
2103 	int status;
2104 #endif /* ifdef HAVE_LMDB */
2105 
2106 #ifndef HAVE_LMDB
2107 	UNUSED(mapsize);
2108 #endif /* ifndef HAVE_LMDB */
2109 
2110 	REQUIRE(DNS_VIEW_VALID(view));
2111 	REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow);
2112 
2113 	if (view->new_zone_file != NULL) {
2114 		isc_mem_free(view->mctx, view->new_zone_file);
2115 		view->new_zone_file = NULL;
2116 	}
2117 
2118 #ifdef HAVE_LMDB
2119 	if (view->new_zone_dbenv != NULL) {
2120 		mdb_env_close((MDB_env *)view->new_zone_dbenv);
2121 		view->new_zone_dbenv = NULL;
2122 	}
2123 
2124 	if (view->new_zone_db != NULL) {
2125 		isc_mem_free(view->mctx, view->new_zone_db);
2126 		view->new_zone_db = NULL;
2127 	}
2128 #endif /* HAVE_LMDB */
2129 
2130 	if (view->new_zone_config != NULL) {
2131 		view->cfg_destroy(&view->new_zone_config);
2132 		view->cfg_destroy = NULL;
2133 	}
2134 
2135 	if (!allow) {
2136 		return (ISC_R_SUCCESS);
2137 	}
2138 
2139 	CHECK(nz_legacy(view->new_zone_dir, view->name, "nzf", buffer,
2140 			sizeof(buffer)));
2141 
2142 	view->new_zone_file = isc_mem_strdup(view->mctx, buffer);
2143 
2144 #ifdef HAVE_LMDB
2145 	CHECK(nz_legacy(view->new_zone_dir, view->name, "nzd", buffer,
2146 			sizeof(buffer)));
2147 
2148 	view->new_zone_db = isc_mem_strdup(view->mctx, buffer);
2149 
2150 	status = mdb_env_create(&env);
2151 	if (status != MDB_SUCCESS) {
2152 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
2153 			      ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
2154 			      "mdb_env_create failed: %s",
2155 			      mdb_strerror(status));
2156 		CHECK(ISC_R_FAILURE);
2157 	}
2158 
2159 	if (mapsize != 0ULL) {
2160 		status = mdb_env_set_mapsize(env, mapsize);
2161 		if (status != MDB_SUCCESS) {
2162 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
2163 				      ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
2164 				      "mdb_env_set_mapsize failed: %s",
2165 				      mdb_strerror(status));
2166 			CHECK(ISC_R_FAILURE);
2167 		}
2168 		view->new_zone_mapsize = mapsize;
2169 	}
2170 
2171 	status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600);
2172 	if (status != MDB_SUCCESS) {
2173 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
2174 			      ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
2175 			      "mdb_env_open of '%s' failed: %s",
2176 			      view->new_zone_db, mdb_strerror(status));
2177 		CHECK(ISC_R_FAILURE);
2178 	}
2179 
2180 	view->new_zone_dbenv = env;
2181 	env = NULL;
2182 #endif /* HAVE_LMDB */
2183 
2184 	view->new_zone_config = cfgctx;
2185 	view->cfg_destroy = cfg_destroy;
2186 
2187 cleanup:
2188 	if (result != ISC_R_SUCCESS) {
2189 		if (view->new_zone_file != NULL) {
2190 			isc_mem_free(view->mctx, view->new_zone_file);
2191 			view->new_zone_file = NULL;
2192 		}
2193 
2194 #ifdef HAVE_LMDB
2195 		if (view->new_zone_db != NULL) {
2196 			isc_mem_free(view->mctx, view->new_zone_db);
2197 			view->new_zone_db = NULL;
2198 		}
2199 		if (env != NULL) {
2200 			mdb_env_close(env);
2201 		}
2202 #endif /* HAVE_LMDB */
2203 		view->new_zone_config = NULL;
2204 		view->cfg_destroy = NULL;
2205 	}
2206 
2207 	return (result);
2208 }
2209 
2210 void
dns_view_setnewzonedir(dns_view_t * view,const char * dir)2211 dns_view_setnewzonedir(dns_view_t *view, const char *dir) {
2212 	REQUIRE(DNS_VIEW_VALID(view));
2213 
2214 	if (view->new_zone_dir != NULL) {
2215 		isc_mem_free(view->mctx, view->new_zone_dir);
2216 		view->new_zone_dir = NULL;
2217 	}
2218 
2219 	if (dir == NULL) {
2220 		return;
2221 	}
2222 
2223 	view->new_zone_dir = isc_mem_strdup(view->mctx, dir);
2224 }
2225 
2226 const char *
dns_view_getnewzonedir(dns_view_t * view)2227 dns_view_getnewzonedir(dns_view_t *view) {
2228 	REQUIRE(DNS_VIEW_VALID(view));
2229 
2230 	return (view->new_zone_dir);
2231 }
2232 
2233 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)2234 dns_view_searchdlz(dns_view_t *view, const dns_name_t *name,
2235 		   unsigned int minlabels, dns_clientinfomethods_t *methods,
2236 		   dns_clientinfo_t *clientinfo, dns_db_t **dbp) {
2237 	dns_fixedname_t fname;
2238 	dns_name_t *zonename;
2239 	unsigned int namelabels;
2240 	unsigned int i;
2241 	isc_result_t result;
2242 	dns_dlzfindzone_t findzone;
2243 	dns_dlzdb_t *dlzdb;
2244 	dns_db_t *db, *best = NULL;
2245 
2246 	/*
2247 	 * Performs checks to make sure data is as we expect it to be.
2248 	 */
2249 	REQUIRE(DNS_VIEW_VALID(view));
2250 	REQUIRE(name != NULL);
2251 	REQUIRE(dbp != NULL && *dbp == NULL);
2252 
2253 	/* setup a "fixed" dns name */
2254 	zonename = dns_fixedname_initname(&fname);
2255 
2256 	/* count the number of labels in the name */
2257 	namelabels = dns_name_countlabels(name);
2258 
2259 	for (dlzdb = ISC_LIST_HEAD(view->dlz_searched); dlzdb != NULL;
2260 	     dlzdb = ISC_LIST_NEXT(dlzdb, link))
2261 	{
2262 		REQUIRE(DNS_DLZ_VALID(dlzdb));
2263 
2264 		/*
2265 		 * loop through starting with the longest domain name and
2266 		 * trying shorter names portions of the name until we find a
2267 		 * match, have an error, or are below the 'minlabels'
2268 		 * threshold.  minlabels is 0, if neither the standard
2269 		 * database nor any previous DLZ database had a zone name
2270 		 * match. Otherwise minlabels is the number of labels
2271 		 * in that name.  We need to beat that for a "better"
2272 		 * match for this DLZ database to be authoritative.
2273 		 */
2274 		for (i = namelabels; i > minlabels && i > 1; i--) {
2275 			if (i == namelabels) {
2276 				dns_name_copy(name, zonename);
2277 			} else {
2278 				dns_name_split(name, i, NULL, zonename);
2279 			}
2280 
2281 			/* ask SDLZ driver if the zone is supported */
2282 			db = NULL;
2283 			findzone = dlzdb->implementation->methods->findzone;
2284 			result = (*findzone)(dlzdb->implementation->driverarg,
2285 					     dlzdb->dbdata, dlzdb->mctx,
2286 					     view->rdclass, zonename, methods,
2287 					     clientinfo, &db);
2288 
2289 			if (result != ISC_R_NOTFOUND) {
2290 				if (best != NULL) {
2291 					dns_db_detach(&best);
2292 				}
2293 				if (result == ISC_R_SUCCESS) {
2294 					INSIST(db != NULL);
2295 					dns_db_attach(db, &best);
2296 					dns_db_detach(&db);
2297 					minlabels = i;
2298 				} else {
2299 					if (db != NULL) {
2300 						dns_db_detach(&db);
2301 					}
2302 					break;
2303 				}
2304 			} else if (db != NULL) {
2305 				dns_db_detach(&db);
2306 			}
2307 		}
2308 	}
2309 
2310 	if (best != NULL) {
2311 		dns_db_attach(best, dbp);
2312 		dns_db_detach(&best);
2313 		return (ISC_R_SUCCESS);
2314 	}
2315 
2316 	return (ISC_R_NOTFOUND);
2317 }
2318 
2319 uint32_t
dns_view_getfailttl(dns_view_t * view)2320 dns_view_getfailttl(dns_view_t *view) {
2321 	REQUIRE(DNS_VIEW_VALID(view));
2322 	return (view->fail_ttl);
2323 }
2324 
2325 void
dns_view_setfailttl(dns_view_t * view,uint32_t fail_ttl)2326 dns_view_setfailttl(dns_view_t *view, uint32_t fail_ttl) {
2327 	REQUIRE(DNS_VIEW_VALID(view));
2328 	view->fail_ttl = fail_ttl;
2329 }
2330 
2331 isc_result_t
dns_view_saventa(dns_view_t * view)2332 dns_view_saventa(dns_view_t *view) {
2333 	isc_result_t result;
2334 	bool removefile = false;
2335 	dns_ntatable_t *ntatable = NULL;
2336 	FILE *fp = NULL;
2337 
2338 	REQUIRE(DNS_VIEW_VALID(view));
2339 
2340 	if (view->nta_lifetime == 0) {
2341 		return (ISC_R_SUCCESS);
2342 	}
2343 
2344 	/* Open NTA save file for overwrite. */
2345 	CHECK(isc_stdio_open(view->nta_file, "w", &fp));
2346 
2347 	result = dns_view_getntatable(view, &ntatable);
2348 	if (result == ISC_R_NOTFOUND) {
2349 		removefile = true;
2350 		result = ISC_R_SUCCESS;
2351 		goto cleanup;
2352 	} else {
2353 		CHECK(result);
2354 	}
2355 
2356 	result = dns_ntatable_save(ntatable, fp);
2357 	if (result == ISC_R_NOTFOUND) {
2358 		removefile = true;
2359 		result = ISC_R_SUCCESS;
2360 	} else if (result == ISC_R_SUCCESS) {
2361 		result = isc_stdio_close(fp);
2362 		fp = NULL;
2363 	}
2364 
2365 cleanup:
2366 	if (ntatable != NULL) {
2367 		dns_ntatable_detach(&ntatable);
2368 	}
2369 
2370 	if (fp != NULL) {
2371 		(void)isc_stdio_close(fp);
2372 	}
2373 
2374 	/* Don't leave half-baked NTA save files lying around. */
2375 	if (result != ISC_R_SUCCESS || removefile) {
2376 		(void)isc_file_remove(view->nta_file);
2377 	}
2378 
2379 	return (result);
2380 }
2381 
2382 #define TSTR(t) ((t).value.as_textregion.base)
2383 #define TLEN(t) ((t).value.as_textregion.length)
2384 
2385 isc_result_t
dns_view_loadnta(dns_view_t * view)2386 dns_view_loadnta(dns_view_t *view) {
2387 	isc_result_t result;
2388 	dns_ntatable_t *ntatable = NULL;
2389 	isc_lex_t *lex = NULL;
2390 	isc_token_t token;
2391 	isc_stdtime_t now;
2392 
2393 	REQUIRE(DNS_VIEW_VALID(view));
2394 
2395 	if (view->nta_lifetime == 0) {
2396 		return (ISC_R_SUCCESS);
2397 	}
2398 
2399 	CHECK(isc_lex_create(view->mctx, 1025, &lex));
2400 	CHECK(isc_lex_openfile(lex, view->nta_file));
2401 	CHECK(dns_view_getntatable(view, &ntatable));
2402 	isc_stdtime_get(&now);
2403 
2404 	for (;;) {
2405 		int options = (ISC_LEXOPT_EOL | ISC_LEXOPT_EOF);
2406 		char *name, *type, *timestamp;
2407 		size_t len;
2408 		dns_fixedname_t fn;
2409 		const dns_name_t *ntaname;
2410 		isc_buffer_t b;
2411 		isc_stdtime_t t;
2412 		bool forced;
2413 
2414 		CHECK(isc_lex_gettoken(lex, options, &token));
2415 		if (token.type == isc_tokentype_eof) {
2416 			break;
2417 		} else if (token.type != isc_tokentype_string) {
2418 			CHECK(ISC_R_UNEXPECTEDTOKEN);
2419 		}
2420 		name = TSTR(token);
2421 		len = TLEN(token);
2422 
2423 		if (strcmp(name, ".") == 0) {
2424 			ntaname = dns_rootname;
2425 		} else {
2426 			dns_name_t *fname;
2427 			fname = dns_fixedname_initname(&fn);
2428 
2429 			isc_buffer_init(&b, name, (unsigned int)len);
2430 			isc_buffer_add(&b, (unsigned int)len);
2431 			CHECK(dns_name_fromtext(fname, &b, dns_rootname, 0,
2432 						NULL));
2433 			ntaname = fname;
2434 		}
2435 
2436 		CHECK(isc_lex_gettoken(lex, options, &token));
2437 		if (token.type != isc_tokentype_string) {
2438 			CHECK(ISC_R_UNEXPECTEDTOKEN);
2439 		}
2440 		type = TSTR(token);
2441 
2442 		if (strcmp(type, "regular") == 0) {
2443 			forced = false;
2444 		} else if (strcmp(type, "forced") == 0) {
2445 			forced = true;
2446 		} else {
2447 			CHECK(ISC_R_UNEXPECTEDTOKEN);
2448 		}
2449 
2450 		CHECK(isc_lex_gettoken(lex, options, &token));
2451 		if (token.type != isc_tokentype_string) {
2452 			CHECK(ISC_R_UNEXPECTEDTOKEN);
2453 		}
2454 		timestamp = TSTR(token);
2455 		CHECK(dns_time32_fromtext(timestamp, &t));
2456 
2457 		CHECK(isc_lex_gettoken(lex, options, &token));
2458 		if (token.type != isc_tokentype_eol &&
2459 		    token.type != isc_tokentype_eof) {
2460 			CHECK(ISC_R_UNEXPECTEDTOKEN);
2461 		}
2462 
2463 		if (now <= t) {
2464 			if (t > (now + 604800)) {
2465 				t = now + 604800;
2466 			}
2467 
2468 			(void)dns_ntatable_add(ntatable, ntaname, forced, 0, t);
2469 		} else {
2470 			char nb[DNS_NAME_FORMATSIZE];
2471 			dns_name_format(ntaname, nb, sizeof(nb));
2472 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
2473 				      DNS_LOGMODULE_NTA, ISC_LOG_INFO,
2474 				      "ignoring expired NTA at %s", nb);
2475 		}
2476 	}
2477 
2478 cleanup:
2479 	if (ntatable != NULL) {
2480 		dns_ntatable_detach(&ntatable);
2481 	}
2482 
2483 	if (lex != NULL) {
2484 		isc_lex_close(lex);
2485 		isc_lex_destroy(&lex);
2486 	}
2487 
2488 	return (result);
2489 }
2490 
2491 void
dns_view_setviewcommit(dns_view_t * view)2492 dns_view_setviewcommit(dns_view_t *view) {
2493 	dns_zone_t *redirect = NULL, *managed_keys = NULL;
2494 
2495 	REQUIRE(DNS_VIEW_VALID(view));
2496 
2497 	LOCK(&view->lock);
2498 
2499 	if (view->redirect != NULL) {
2500 		dns_zone_attach(view->redirect, &redirect);
2501 	}
2502 	if (view->managed_keys != NULL) {
2503 		dns_zone_attach(view->managed_keys, &managed_keys);
2504 	}
2505 
2506 	UNLOCK(&view->lock);
2507 
2508 	if (view->zonetable != NULL) {
2509 		dns_zt_setviewcommit(view->zonetable);
2510 	}
2511 	if (redirect != NULL) {
2512 		dns_zone_setviewcommit(redirect);
2513 		dns_zone_detach(&redirect);
2514 	}
2515 	if (managed_keys != NULL) {
2516 		dns_zone_setviewcommit(managed_keys);
2517 		dns_zone_detach(&managed_keys);
2518 	}
2519 }
2520 
2521 void
dns_view_setviewrevert(dns_view_t * view)2522 dns_view_setviewrevert(dns_view_t *view) {
2523 	dns_zone_t *redirect = NULL, *managed_keys = NULL;
2524 	dns_zt_t *zonetable;
2525 
2526 	REQUIRE(DNS_VIEW_VALID(view));
2527 
2528 	/*
2529 	 * dns_zt_setviewrevert() attempts to lock this view, so we must
2530 	 * release the lock.
2531 	 */
2532 	LOCK(&view->lock);
2533 	if (view->redirect != NULL) {
2534 		dns_zone_attach(view->redirect, &redirect);
2535 	}
2536 	if (view->managed_keys != NULL) {
2537 		dns_zone_attach(view->managed_keys, &managed_keys);
2538 	}
2539 	zonetable = view->zonetable;
2540 	UNLOCK(&view->lock);
2541 
2542 	if (redirect != NULL) {
2543 		dns_zone_setviewrevert(redirect);
2544 		dns_zone_detach(&redirect);
2545 	}
2546 	if (managed_keys != NULL) {
2547 		dns_zone_setviewrevert(managed_keys);
2548 		dns_zone_detach(&managed_keys);
2549 	}
2550 	if (zonetable != NULL) {
2551 		dns_zt_setviewrevert(zonetable);
2552 	}
2553 }
2554 
2555 bool
dns_view_staleanswerenabled(dns_view_t * view)2556 dns_view_staleanswerenabled(dns_view_t *view) {
2557 	uint32_t stale_ttl = 0;
2558 	bool result = false;
2559 
2560 	REQUIRE(DNS_VIEW_VALID(view));
2561 
2562 	if (dns_db_getservestalettl(view->cachedb, &stale_ttl) != ISC_R_SUCCESS)
2563 	{
2564 		return (false);
2565 	}
2566 	if (stale_ttl > 0) {
2567 		if (view->staleanswersok == dns_stale_answer_yes) {
2568 			result = true;
2569 		} else if (view->staleanswersok == dns_stale_answer_conf) {
2570 			result = view->staleanswersenable;
2571 		}
2572 	}
2573 
2574 	return (result);
2575 }
2576