view.c 60.2 KB
Newer Older
Bob Halley's avatar
add  
Bob Halley committed
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4 5 6
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 8 9
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
Bob Halley's avatar
add  
Bob Halley committed
10 11
 */

12
/*! \file */
David Lawrence's avatar
David Lawrence committed
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/file.h>
24
#include <isc/hash.h>
25
#include <isc/lex.h>
26
#include <isc/print.h>
27
#include <isc/stats.h>
28
#include <isc/string.h> /* Required for HP/UX (and others?) */
29
#include <isc/task.h>
Michael Graff's avatar
Michael Graff committed
30
#include <isc/util.h>
Bob Halley's avatar
add  
Bob Halley committed
31

32
#include <dns/acl.h>
Bob Halley's avatar
add adb  
Bob Halley committed
33
#include <dns/adb.h>
Evan Hunt's avatar
Evan Hunt committed
34
#include <dns/badcache.h>
35
#include <dns/cache.h>
Bob Halley's avatar
Bob Halley committed
36
#include <dns/db.h>
37
#include <dns/dispatch.h>
38
#include <dns/dlz.h>
39
#include <dns/dns64.h>
40
#include <dns/dnssec.h>
41
#include <dns/events.h>
42
#include <dns/forward.h>
43
#include <dns/keytable.h>
44
#include <dns/keyvalues.h>
45
#include <dns/master.h>
46
#include <dns/masterdump.h>
Evan Hunt's avatar
Evan Hunt committed
47
#include <dns/nta.h>
48
#include <dns/order.h>
49
#include <dns/peer.h>
50
#include <dns/rbt.h>
Bob Halley's avatar
Bob Halley committed
51
#include <dns/rdataset.h>
Mark Andrews's avatar
Mark Andrews committed
52
#include <dns/request.h>
53 54
#include <dns/resolver.h>
#include <dns/result.h>
55
#include <dns/rpz.h>
56
#include <dns/rrl.h>
57
#include <dns/stats.h>
58
#include <dns/time.h>
Brian Wellington's avatar
Brian Wellington committed
59
#include <dns/tsig.h>
60
#include <dns/zone.h>
61
#include <dns/zt.h>
Bob Halley's avatar
add  
Bob Halley committed
62

63 64 65 66 67
#define CHECK(op)                            \
	do {                                 \
		result = (op);               \
		if (result != ISC_R_SUCCESS) \
			goto cleanup;        \
68 69
	} while (0)

70 71 72 73 74 75
#define RESSHUTDOWN(v) \
	((atomic_load(&(v)->attributes) & DNS_VIEWATTR_RESSHUTDOWN) != 0)
#define ADBSHUTDOWN(v) \
	((atomic_load(&(v)->attributes) & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
#define REQSHUTDOWN(v) \
	((atomic_load(&(v)->attributes) & DNS_VIEWATTR_REQSHUTDOWN) != 0)
76

Evan Hunt's avatar
Evan Hunt committed
77
#define DNS_VIEW_DELONLYHASH   111
Evan Hunt's avatar
Evan Hunt committed
78
#define DNS_VIEW_FAILCACHESIZE 1021
79

Ondřej Surý's avatar
Ondřej Surý committed
80 81 82 83 84 85
static void
resolver_shutdown(isc_task_t *task, isc_event_t *event);
static void
adb_shutdown(isc_task_t *task, isc_event_t *event);
static void
req_shutdown(isc_task_t *task, isc_event_t *event);
86

Bob Halley's avatar
add  
Bob Halley committed
87
isc_result_t
88
dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, const char *name,
Evan Hunt's avatar
Evan Hunt committed
89 90
		dns_view_t **viewp) {
	dns_view_t *view;
Bob Halley's avatar
add  
Bob Halley committed
91
	isc_result_t result;
Evan Hunt's avatar
Evan Hunt committed
92
	char buffer[1024];
Bob Halley's avatar
add  
Bob Halley committed
93 94 95 96 97 98 99 100

	/*
	 * Create a view.
	 */

	REQUIRE(name != NULL);
	REQUIRE(viewp != NULL && *viewp == NULL);

Andreas Gustafsson's avatar
Andreas Gustafsson committed
101
	view = isc_mem_get(mctx, sizeof(*view));
102

103
	view->nta_file = NULL;
104 105
	view->mctx = NULL;
	isc_mem_attach(mctx, &view->mctx);
Bob Halley's avatar
add  
Bob Halley committed
106
	view->name = isc_mem_strdup(mctx, name);
107

108 109
	result = isc_file_sanitize(NULL, view->name, "nta", buffer,
				   sizeof(buffer));
110
	if (result != ISC_R_SUCCESS) {
111
		goto cleanup_name;
112
	}
113 114
	view->nta_file = isc_mem_strdup(mctx, buffer);

Ondřej Surý's avatar
Ondřej Surý committed
115
	isc_mutex_init(&view->lock);
116

117
	view->zonetable = NULL;
Evan Hunt's avatar
Evan Hunt committed
118 119 120 121 122 123 124
	result = dns_zt_create(mctx, rdclass, &view->zonetable);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "dns_zt_create() failed: %s",
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
		goto cleanup_mutex;
Bob Halley's avatar
add  
Bob Halley committed
125
	}
Evan Hunt's avatar
Evan Hunt committed
126

127
	view->secroots_priv = NULL;
Evan Hunt's avatar
Evan Hunt committed
128
	view->ntatable_priv = NULL;
129 130 131 132 133 134 135
	view->fwdtable = NULL;
	result = dns_fwdtable_create(mctx, &view->fwdtable);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "dns_fwdtable_create() failed: %s",
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
136
		goto cleanup_zt;
137
	}
138

139
	view->cache = NULL;
Bob Halley's avatar
Bob Halley committed
140
	view->cachedb = NULL;
Evan Hunt's avatar
Evan Hunt committed
141 142
	ISC_LIST_INIT(view->dlz_searched);
	ISC_LIST_INIT(view->dlz_unsearched);
Bob Halley's avatar
Bob Halley committed
143
	view->hints = NULL;
Bob Halley's avatar
add  
Bob Halley committed
144
	view->resolver = NULL;
Bob Halley's avatar
add adb  
Bob Halley committed
145
	view->adb = NULL;
Mark Andrews's avatar
Mark Andrews committed
146
	view->requestmgr = NULL;
Bob Halley's avatar
add  
Bob Halley committed
147
	view->rdclass = rdclass;
148
	view->frozen = false;
149
	view->task = NULL;
150
	isc_refcount_init(&view->references, 1);
151
	isc_refcount_init(&view->weakrefs, 1);
152 153 154
	atomic_init(&view->attributes,
		    (DNS_VIEWATTR_RESSHUTDOWN | DNS_VIEWATTR_ADBSHUTDOWN |
		     DNS_VIEWATTR_REQSHUTDOWN));
Brian Wellington's avatar
Brian Wellington committed
155 156
	view->statickeys = NULL;
	view->dynamickeys = NULL;
157
	view->matchclients = NULL;
158
	view->matchdestinations = NULL;
159
	view->matchrecursiveonly = false;
160
	result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
161
	if (result != ISC_R_SUCCESS) {
162
		goto cleanup_weakrefs;
163
	}
164
	view->peers = NULL;
165
	view->order = NULL;
166
	view->delonly = NULL;
167
	view->rootdelonly = false;
Mark Andrews's avatar
Mark Andrews committed
168
	view->rootexclude = NULL;
169
	view->adbstats = NULL;
170 171
	view->resstats = NULL;
	view->resquerystats = NULL;
172
	view->cacheshared = false;
173 174
	ISC_LIST_INIT(view->dns64);
	view->dns64cnt = 0;
175

176 177
	/*
	 * Initialize configuration data with default values.
178
	 */
179 180 181 182 183 184 185 186
	view->recursion = true;
	view->qminimization = false;
	view->qmin_strict = false;
	view->auth_nxdomain = false; /* Was true in BIND 8 */
	view->enablevalidation = true;
	view->acceptexpired = false;
	view->use_glue_cache = false;
	view->minimal_any = false;
187
	view->minimalresponses = dns_minimal_no;
188
	view->transfer_format = dns_one_answer;
189 190
	view->cacheacl = NULL;
	view->cacheonacl = NULL;
191
	view->queryacl = NULL;
192
	view->queryonacl = NULL;
193
	view->recursionacl = NULL;
194
	view->recursiononacl = NULL;
195
	view->sortlist = NULL;
196 197 198 199
	view->transferacl = NULL;
	view->notifyacl = NULL;
	view->updateacl = NULL;
	view->upfwdacl = NULL;
200
	view->denyansweracl = NULL;
Evan Hunt's avatar
Evan Hunt committed
201
	view->nocasecompress = NULL;
202
	view->msgcompression = true;
203 204 205
	view->answeracl_exclude = NULL;
	view->denyanswernames = NULL;
	view->answernames_exclude = NULL;
Evan Hunt's avatar
Evan Hunt committed
206
	view->rrl = NULL;
207
	view->provideixfr = true;
208 209
	view->maxcachettl = 7 * 24 * 3600;
	view->maxncachettl = 3 * 3600;
210 211
	view->mincachettl = 0;
	view->minncachettl = 0;
Evan Hunt's avatar
Evan Hunt committed
212 213
	view->nta_lifetime = 0;
	view->nta_recheck = 0;
Evan Hunt's avatar
Evan Hunt committed
214 215
	view->prefetch_eligible = 0;
	view->prefetch_trigger = 0;
216
	view->dstport = 53;
217
	view->preferred_glue = 0;
218
	view->flush = false;
219
	view->maxudp = 0;
220 221
	view->staleanswerttl = 1;
	view->staleanswersok = dns_stale_answer_conf;
222
	view->staleanswersenable = false;
223
	view->nocookieudp = 0;
224 225
	view->padding = 0;
	view->pad_acl = NULL;
226
	view->maxbits = 0;
227
	view->rpzs = NULL;
228
	view->catzs = NULL;
229
	view->managed_keys = NULL;
230
	view->redirect = NULL;
231 232
	view->redirectzone = NULL;
	dns_fixedname_init(&view->redirectfixed);
233 234 235 236 237 238
	view->requestnsid = false;
	view->sendcookie = true;
	view->requireservercookie = false;
	view->synthfromdnssec = true;
	view->trust_anchor_telemetry = true;
	view->root_key_sentinel = true;
239
	view->new_zone_dir = NULL;
240
	view->new_zone_file = NULL;
241 242
	view->new_zone_db = NULL;
	view->new_zone_dbenv = NULL;
243
	view->new_zone_mapsize = 0ULL;
244 245
	view->new_zone_config = NULL;
	view->cfg_destroy = NULL;
Evan Hunt's avatar
Evan Hunt committed
246 247
	view->fail_ttl = 0;
	view->failcache = NULL;
248
	result = dns_badcache_init(view->mctx, DNS_VIEW_FAILCACHESIZE,
249
				   &view->failcache);
250 251 252
	if (result != ISC_R_SUCCESS) {
		goto cleanup_dynkeys;
	}
253
	view->v6bias = 0;
Evan Hunt's avatar
Evan Hunt committed
254 255
	view->dtenv = NULL;
	view->dttypes = 0;
256

257 258
	view->plugins = NULL;
	view->plugins_free = NULL;
259 260 261
	view->hooktable = NULL;
	view->hooktable_free = NULL;

Ondřej Surý's avatar
Ondřej Surý committed
262
	isc_mutex_init(&view->new_zone_lock);
263

Evan Hunt's avatar
Evan Hunt committed
264 265 266
	result = dns_order_create(view->mctx, &view->order);
	if (result != ISC_R_SUCCESS) {
		goto cleanup_new_zone_lock;
267
	}
268

269
	result = dns_peerlist_new(view->mctx, &view->peers);
270
	if (result != ISC_R_SUCCESS) {
271
		goto cleanup_order;
272
	}
273

274
	result = dns_aclenv_init(view->mctx, &view->aclenv);
275
	if (result != ISC_R_SUCCESS) {
276
		goto cleanup_peerlist;
277
	}
278

Michael Graff's avatar
Michael Graff committed
279
	ISC_LINK_INIT(view, link);
Andreas Gustafsson's avatar
Andreas Gustafsson committed
280
	ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL,
281 282
		       DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown, view, NULL,
		       NULL, NULL);
Andreas Gustafsson's avatar
Andreas Gustafsson committed
283
	ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL,
284 285
		       DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown, view, NULL,
		       NULL, NULL);
Andreas Gustafsson's avatar
Andreas Gustafsson committed
286
	ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL,
287 288
		       DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown, view, NULL,
		       NULL, NULL);
289
	view->viewlist = NULL;
Bob Halley's avatar
add  
Bob Halley committed
290
	view->magic = DNS_VIEW_MAGIC;
291

Bob Halley's avatar
add  
Bob Halley committed
292 293 294 295
	*viewp = view;

	return (ISC_R_SUCCESS);

296
cleanup_peerlist:
297
	if (view->peers != NULL) {
298
		dns_peerlist_detach(&view->peers);
299
	}
300

301
cleanup_order:
302
	if (view->order != NULL) {
303
		dns_order_detach(&view->order);
304
	}
305

306
cleanup_new_zone_lock:
307
	isc_mutex_destroy(&view->new_zone_lock);
308

309 310
	dns_badcache_destroy(&view->failcache);

311
cleanup_dynkeys:
312
	if (view->dynamickeys != NULL) {
313
		dns_tsigkeyring_detach(&view->dynamickeys);
314
	}
315

316
cleanup_weakrefs:
317
	isc_refcount_decrement(&view->weakrefs);
318 319 320
	isc_refcount_destroy(&view->weakrefs);

	isc_refcount_decrement(&view->references);
321 322
	isc_refcount_destroy(&view->references);

323
	if (view->fwdtable != NULL) {
324
		dns_fwdtable_destroy(&view->fwdtable);
325
	}
326

327
cleanup_zt:
328
	if (view->zonetable != NULL) {
329
		dns_zt_detach(&view->zonetable);
330
	}
Bob Halley's avatar
Bob Halley committed
331

332
cleanup_mutex:
333
	isc_mutex_destroy(&view->lock);
Bob Halley's avatar
add  
Bob Halley committed
334

335
	if (view->nta_file != NULL) {
336
		isc_mem_free(mctx, view->nta_file);
337
	}
338

339
cleanup_name:
Bob Halley's avatar
add  
Bob Halley committed
340
	isc_mem_free(mctx, view->name);
341
	isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
Bob Halley's avatar
add  
Bob Halley committed
342 343 344 345 346

	return (result);
}

static inline void
Evan Hunt's avatar
Evan Hunt committed
347
destroy(dns_view_t *view) {
348
	dns_dns64_t *dns64;
Evan Hunt's avatar
Evan Hunt committed
349
	dns_dlzdb_t *dlzdb;
350

Bob Halley's avatar
add  
Bob Halley committed
351
	REQUIRE(!ISC_LINK_LINKED(view, link));
352 353
	REQUIRE(RESSHUTDOWN(view));
	REQUIRE(ADBSHUTDOWN(view));
Mark Andrews's avatar
Mark Andrews committed
354
	REQUIRE(REQSHUTDOWN(view));
Bob Halley's avatar
add  
Bob Halley committed
355

356 357 358
	isc_refcount_destroy(&view->references);
	isc_refcount_destroy(&view->weakrefs);

359
	if (view->order != NULL) {
360
		dns_order_detach(&view->order);
361 362
	}
	if (view->peers != NULL) {
363
		dns_peerlist_detach(&view->peers);
364
	}
365 366 367

	if (view->dynamickeys != NULL) {
		isc_result_t result;
368
		char template[PATH_MAX];
Evan Hunt's avatar
Evan Hunt committed
369
		char keyfile[PATH_MAX];
370
		FILE *fp = NULL;
371 372 373 374

		result = isc_file_mktemplate(NULL, template, sizeof(template));
		if (result == ISC_R_SUCCESS) {
			(void)isc_file_openuniqueprivate(template, &fp);
375
		}
376
		if (fp == NULL) {
377
			dns_tsigkeyring_detach(&view->dynamickeys);
378
		} else {
379 380
			result = dns_tsigkeyring_dumpanddetach(
				&view->dynamickeys, fp);
381
			if (result == ISC_R_SUCCESS) {
382
				if (fclose(fp) == 0) {
383 384 385
					result = isc_file_sanitize(
						NULL, view->name, "tsigkeys",
						keyfile, sizeof(keyfile));
386
					if (result == ISC_R_SUCCESS) {
387 388
						result = isc_file_rename(
							template, keyfile);
389
					}
390
				}
391
				if (result != ISC_R_SUCCESS) {
392
					(void)remove(template);
393
				}
394 395 396 397 398 399
			} else {
				(void)fclose(fp);
				(void)remove(template);
			}
		}
	}
400
	if (view->statickeys != NULL) {
401
		dns_tsigkeyring_detach(&view->statickeys);
402 403
	}
	if (view->adb != NULL) {
Bob Halley's avatar
add adb  
Bob Halley committed
404
		dns_adb_detach(&view->adb);
405 406
	}
	if (view->resolver != NULL) {
Bob Halley's avatar
add  
Bob Halley committed
407
		dns_resolver_detach(&view->resolver);
408
	}
Evan Hunt's avatar
Evan Hunt committed
409
	dns_rrl_view_destroy(view);
410
	if (view->rpzs != NULL) {
411
		dns_rpz_detach_rpzs(&view->rpzs);
412 413
	}
	if (view->catzs != NULL) {
414
		dns_catz_catzs_detach(&view->catzs);
415
	}
416
	for (dlzdb = ISC_LIST_HEAD(view->dlz_searched); dlzdb != NULL;
Evan Hunt's avatar
Evan Hunt committed
417 418
	     dlzdb = ISC_LIST_HEAD(view->dlz_searched))
	{
Evan Hunt's avatar
Evan Hunt committed
419 420 421
		ISC_LIST_UNLINK(view->dlz_searched, dlzdb, link);
		dns_dlzdestroy(&dlzdb);
	}
422
	for (dlzdb = ISC_LIST_HEAD(view->dlz_unsearched); dlzdb != NULL;
Evan Hunt's avatar
Evan Hunt committed
423 424
	     dlzdb = ISC_LIST_HEAD(view->dlz_unsearched))
	{
Evan Hunt's avatar
Evan Hunt committed
425 426 427
		ISC_LIST_UNLINK(view->dlz_unsearched, dlzdb, link);
		dns_dlzdestroy(&dlzdb);
	}
428
	if (view->requestmgr != NULL) {
Mark Andrews's avatar
Mark Andrews committed
429
		dns_requestmgr_detach(&view->requestmgr);
430 431
	}
	if (view->task != NULL) {
432
		isc_task_detach(&view->task);
433 434
	}
	if (view->hints != NULL) {
Bob Halley's avatar
Bob Halley committed
435
		dns_db_detach(&view->hints);
436 437
	}
	if (view->cachedb != NULL) {
Bob Halley's avatar
Bob Halley committed
438
		dns_db_detach(&view->cachedb);
439 440
	}
	if (view->cache != NULL) {
441
		dns_cache_detach(&view->cache);
442 443
	}
	if (view->nocasecompress != NULL) {
Evan Hunt's avatar
Evan Hunt committed
444
		dns_acl_detach(&view->nocasecompress);
445 446
	}
	if (view->matchclients != NULL) {
447
		dns_acl_detach(&view->matchclients);
448 449
	}
	if (view->matchdestinations != NULL) {
450
		dns_acl_detach(&view->matchdestinations);
451 452
	}
	if (view->cacheacl != NULL) {
453
		dns_acl_detach(&view->cacheacl);
454 455
	}
	if (view->cacheonacl != NULL) {
456
		dns_acl_detach(&view->cacheonacl);
457 458
	}
	if (view->queryacl != NULL) {
459
		dns_acl_detach(&view->queryacl);
460 461
	}
	if (view->queryonacl != NULL) {
462
		dns_acl_detach(&view->queryonacl);
463 464
	}
	if (view->recursionacl != NULL) {
465
		dns_acl_detach(&view->recursionacl);
466 467
	}
	if (view->recursiononacl != NULL) {
468
		dns_acl_detach(&view->recursiononacl);
469 470
	}
	if (view->sortlist != NULL) {
471
		dns_acl_detach(&view->sortlist);
472 473
	}
	if (view->transferacl != NULL) {
474
		dns_acl_detach(&view->transferacl);
475 476
	}
	if (view->notifyacl != NULL) {
477
		dns_acl_detach(&view->notifyacl);
478 479
	}
	if (view->updateacl != NULL) {
480
		dns_acl_detach(&view->updateacl);
481 482
	}
	if (view->upfwdacl != NULL) {
483
		dns_acl_detach(&view->upfwdacl);
484 485
	}
	if (view->denyansweracl != NULL) {
486
		dns_acl_detach(&view->denyansweracl);
487 488
	}
	if (view->pad_acl != NULL) {
489
		dns_acl_detach(&view->pad_acl);
490 491
	}
	if (view->answeracl_exclude != NULL) {
492
		dns_rbt_destroy(&view->answeracl_exclude);
493 494
	}
	if (view->denyanswernames != NULL) {
495
		dns_rbt_destroy(&view->denyanswernames);
496 497
	}
	if (view->answernames_exclude != NULL) {
498
		dns_rbt_destroy(&view->answernames_exclude);
499
	}
500 501
	if (view->delonly != NULL) {
		dns_name_t *name;
Evan Hunt's avatar
Evan Hunt committed
502
		int i;
503 504 505 506 507 508 509 510 511 512

		for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
			name = ISC_LIST_HEAD(view->delonly[i]);
			while (name != NULL) {
				ISC_LIST_UNLINK(view->delonly[i], name, link);
				dns_name_free(name, view->mctx);
				isc_mem_put(view->mctx, name, sizeof(*name));
				name = ISC_LIST_HEAD(view->delonly[i]);
			}
		}
513 514
		isc_mem_put(view->mctx, view->delonly,
			    sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH);
515 516
		view->delonly = NULL;
	}
Mark Andrews's avatar
Mark Andrews committed
517 518
	if (view->rootexclude != NULL) {
		dns_name_t *name;
Evan Hunt's avatar
Evan Hunt committed
519
		int i;
Mark Andrews's avatar
Mark Andrews committed
520 521 522 523

		for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
			name = ISC_LIST_HEAD(view->rootexclude[i]);
			while (name != NULL) {
524 525
				ISC_LIST_UNLINK(view->rootexclude[i], name,
						link);
Mark Andrews's avatar
Mark Andrews committed
526 527 528 529 530 531 532 533 534
				dns_name_free(name, view->mctx);
				isc_mem_put(view->mctx, name, sizeof(*name));
				name = ISC_LIST_HEAD(view->rootexclude[i]);
			}
		}
		isc_mem_put(view->mctx, view->rootexclude,
			    sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH);
		view->rootexclude = NULL;
	}
535
	if (view->adbstats != NULL) {
536
		isc_stats_detach(&view->adbstats);
537 538
	}
	if (view->resstats != NULL) {
539
		isc_stats_detach(&view->resstats);
540 541
	}
	if (view->resquerystats != NULL) {
542
		dns_stats_detach(&view->resquerystats);
543 544
	}
	if (view->secroots_priv != NULL) {
545
		dns_keytable_detach(&view->secroots_priv);
546 547
	}
	if (view->ntatable_priv != NULL) {
Evan Hunt's avatar
Evan Hunt committed
548
		dns_ntatable_detach(&view->ntatable_priv);
549
	}
550
	for (dns64 = ISC_LIST_HEAD(view->dns64); dns64 != NULL;
Evan Hunt's avatar
Evan Hunt committed
551 552
	     dns64 = ISC_LIST_HEAD(view->dns64))
	{
553 554 555
		dns_dns64_unlink(&view->dns64, dns64);
		dns_dns64_destroy(&dns64);
	}
556
	if (view->managed_keys != NULL) {
557
		dns_zone_detach(&view->managed_keys);
558 559
	}
	if (view->redirect != NULL) {
560
		dns_zone_detach(&view->redirect);
561
	}
Evan Hunt's avatar
Evan Hunt committed
562
#ifdef HAVE_DNSTAP
563
	if (view->dtenv != NULL) {
Evan Hunt's avatar
Evan Hunt committed
564
		dns_dt_detach(&view->dtenv);
565
	}
Evan Hunt's avatar
Evan Hunt committed
566
#endif /* HAVE_DNSTAP */
567
	dns_view_setnewzones(view, false, NULL, NULL, 0ULL);
568 569 570 571
	if (view->new_zone_file != NULL) {
		isc_mem_free(view->mctx, view->new_zone_file);
		view->new_zone_file = NULL;
	}
572 573 574 575
	if (view->new_zone_dir != NULL) {
		isc_mem_free(view->mctx, view->new_zone_dir);
		view->new_zone_dir = NULL;
	}
576
#ifdef HAVE_LMDB
577
	if (view->new_zone_dbenv != NULL) {
578
		mdb_env_close((MDB_env *)view->new_zone_dbenv);
579 580
		view->new_zone_dbenv = NULL;
	}
581 582 583 584 585
	if (view->new_zone_db != NULL) {
		isc_mem_free(view->mctx, view->new_zone_db);
		view->new_zone_db = NULL;
	}
#endif /* HAVE_LMDB */
586
	dns_fwdtable_destroy(&view->fwdtable);
587
	dns_aclenv_destroy(&view->aclenv);
588
	if (view->failcache != NULL) {
589
		dns_badcache_destroy(&view->failcache);
590
	}
591 592
	isc_mutex_destroy(&view->new_zone_lock);
	isc_mutex_destroy(&view->lock);
593 594
	isc_refcount_destroy(&view->references);
	isc_refcount_destroy(&view->weakrefs);
595
	isc_mem_free(view->mctx, view->nta_file);
Bob Halley's avatar
add  
Bob Halley committed
596
	isc_mem_free(view->mctx, view->name);
597 598 599
	if (view->hooktable != NULL && view->hooktable_free != NULL) {
		view->hooktable_free(view->mctx, &view->hooktable);
	}
600 601
	if (view->plugins != NULL && view->plugins_free != NULL) {
		view->plugins_free(view->mctx, &view->plugins);
602
	}
603
	isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
Bob Halley's avatar
add  
Bob Halley committed
604 605
}

606
void
Evan Hunt's avatar
Evan Hunt committed
607
dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
608 609 610
	REQUIRE(DNS_VIEW_VALID(source));
	REQUIRE(targetp != NULL && *targetp == NULL);

611
	isc_refcount_increment(&source->references);
612 613 614 615

	*targetp = source;
}

616
static void
Evan Hunt's avatar
Evan Hunt committed
617
view_flushanddetach(dns_view_t **viewp, bool flush) {
618 619 620
	REQUIRE(viewp != NULL && DNS_VIEW_VALID(*viewp));
	dns_view_t *view = *viewp;
	*viewp = NULL;
Bob Halley's avatar
add  
Bob Halley committed
621

622 623 624
	if (flush) {
		view->flush = flush;
	}
Bob Halley's avatar
add  
Bob Halley committed
625

626
	if (isc_refcount_decrement(&view->references) == 1) {
Evan Hunt's avatar
Evan Hunt committed
627 628
		dns_zone_t *mkzone = NULL, *rdzone = NULL;

629
		isc_refcount_destroy(&view->references);
630
		LOCK(&view->lock);
631
		if (!RESSHUTDOWN(view)) {
632
			dns_resolver_shutdown(view->resolver);
633 634
		}
		if (!ADBSHUTDOWN(view)) {
635
			dns_adb_shutdown(view->adb);
636 637
		}
		if (!REQSHUTDOWN(view)) {
Mark Andrews's avatar
Mark Andrews committed
638
			dns_requestmgr_shutdown(view->requestmgr);
639
		}
640
		if (view->zonetable != NULL) {
641
			if (view->flush) {
642
				dns_zt_flushanddetach(&view->zonetable);
643
			} else {
644
				dns_zt_detach(&view->zonetable);
645
			}
646
		}
647
		if (view->managed_keys != NULL) {
Evan Hunt's avatar
Evan Hunt committed
648 649
			mkzone = view->managed_keys;
			view->managed_keys = NULL;
650
			if (view->flush) {
Evan Hunt's avatar
Evan Hunt committed
651
				dns_zone_flush(mkzone);
652
			}
653
		}
654
		if (view->redirect != NULL) {
Evan Hunt's avatar
Evan Hunt committed
655 656
			rdzone = view->redirect;
			view->redirect = NULL;
657
			if (view->flush) {
Evan Hunt's avatar
Evan Hunt committed
658
				dns_zone_flush(rdzone);
659
			}
660
		}
661 662 663
		if (view->catzs != NULL) {
			dns_catz_catzs_detach(&view->catzs);
		}
664
		UNLOCK(&view->lock);
Evan Hunt's avatar
Evan Hunt committed