view.c 28.1 KB
Newer Older
Bob Halley's avatar
add  
Bob Halley committed
1
/*
Bob Halley's avatar
Bob Halley committed
2
 * Copyright (C) 1999, 2000  Internet Software Consortium.
3
 *
Bob Halley's avatar
add  
Bob Halley committed
4 5 6
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
7
 *
8 9 10 11 12 13 14 15
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Bob Halley's avatar
add  
Bob Halley committed
16 17
 */

18
/* $Id: view.c,v 1.90 2001/01/09 18:25:51 gson Exp $ */
David Lawrence's avatar
David Lawrence committed
19

Bob Halley's avatar
add  
Bob Halley committed
20 21
#include <config.h>

22
#include <isc/task.h>
23
#include <isc/string.h>		/* Required for HP/UX (and others?) */
Michael Graff's avatar
Michael Graff committed
24
#include <isc/util.h>
Bob Halley's avatar
add  
Bob Halley committed
25

26
#include <dns/acl.h>
Bob Halley's avatar
add adb  
Bob Halley committed
27
#include <dns/adb.h>
28
#include <dns/cache.h>
Bob Halley's avatar
Bob Halley committed
29
#include <dns/db.h>
30
#include <dns/events.h>
31
#include <dns/forward.h>
32
#include <dns/keytable.h>
33
#include <dns/master.h>
34
#include <dns/masterdump.h>
35
#include <dns/peer.h>
Bob Halley's avatar
Bob Halley committed
36
#include <dns/rdataset.h>
Mark Andrews's avatar
Mark Andrews committed
37
#include <dns/request.h>
38 39
#include <dns/resolver.h>
#include <dns/result.h>
Brian Wellington's avatar
Brian Wellington committed
40
#include <dns/tsig.h>
41
#include <dns/zone.h>
42
#include <dns/zt.h>
Bob Halley's avatar
add  
Bob Halley committed
43

44 45
#define RESSHUTDOWN(v)	(((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0)
#define ADBSHUTDOWN(v)	(((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
Mark Andrews's avatar
Mark Andrews committed
46
#define REQSHUTDOWN(v)	(((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0)
47 48 49

static void resolver_shutdown(isc_task_t *task, isc_event_t *event);
static void adb_shutdown(isc_task_t *task, isc_event_t *event);
Mark Andrews's avatar
Mark Andrews committed
50
static void req_shutdown(isc_task_t *task, isc_event_t *event);
51

Bob Halley's avatar
add  
Bob Halley committed
52
isc_result_t
53 54
dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
		const char *name, dns_view_t **viewp)
Bob Halley's avatar
add  
Bob Halley committed
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
{
	dns_view_t *view;
	isc_result_t result;

	/*
	 * Create a view.
	 */

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

	view = isc_mem_get(mctx, sizeof *view);
	if (view == NULL)
		return (ISC_R_NOMEMORY);
	view->name = isc_mem_strdup(mctx, name);
	if (view->name == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup_view;
	}
	result = isc_mutex_init(&view->lock);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_mutex_init() failed: %s",
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
		goto cleanup_name;
	}
82
	result = isc_rwlock_init(&view->conflock, 1, 1);
83 84 85 86 87 88 89
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_rwlock_init() failed: %s",
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
		goto cleanup_mutex;
	}
90 91
	view->zonetable = NULL;
	result = dns_zt_create(mctx, rdclass, &view->zonetable);
Bob Halley's avatar
add  
Bob Halley committed
92 93
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
94
				 "dns_zt_create() failed: %s",
Bob Halley's avatar
add  
Bob Halley committed
95 96
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
97
		goto cleanup_rwlock;
Bob Halley's avatar
add  
Bob Halley committed
98
	}
Bob Halley's avatar
Bob Halley committed
99
	view->secroots = NULL;
100
	result = dns_keytable_create(mctx, &view->secroots);
Bob Halley's avatar
Bob Halley committed
101 102
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
103
				 "dns_keytable_create() failed: %s",
Bob Halley's avatar
Bob Halley committed
104 105
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
106
		goto cleanup_zt;
Bob Halley's avatar
Bob Halley committed
107
	}
108 109 110 111 112 113 114 115 116
	view->trustedkeys = NULL;
	result = dns_keytable_create(mctx, &view->trustedkeys);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "dns_keytable_create() failed: %s",
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
		goto cleanup_secroots;
	}
117 118 119 120 121 122 123 124 125
	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;
		goto cleanup_trustedkeys;
	}
126

127
	view->cache = NULL;
Bob Halley's avatar
Bob Halley committed
128
	view->cachedb = NULL;
Bob Halley's avatar
Bob Halley committed
129
	view->hints = NULL;
Bob Halley's avatar
add  
Bob Halley committed
130
	view->resolver = NULL;
Bob Halley's avatar
add adb  
Bob Halley committed
131
	view->adb = NULL;
132
	view->loadmgr = NULL;
Mark Andrews's avatar
Mark Andrews committed
133
	view->requestmgr = NULL;
Bob Halley's avatar
add  
Bob Halley committed
134 135
	view->mctx = mctx;
	view->rdclass = rdclass;
Bob Halley's avatar
Bob Halley committed
136
	view->frozen = ISC_FALSE;
137
	view->task = NULL;
Bob Halley's avatar
add  
Bob Halley committed
138
	view->references = 1;
139
	view->weakrefs = 0;
Mark Andrews's avatar
Mark Andrews committed
140 141
	view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
			    DNS_VIEWATTR_REQSHUTDOWN);
Brian Wellington's avatar
Brian Wellington committed
142 143
	view->statickeys = NULL;
	view->dynamickeys = NULL;
144
	view->matchclients = NULL;
145
	result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
146
	if (result != ISC_R_SUCCESS)
147
		goto cleanup_fwdtable;
148
	view->peers = NULL;
149

150 151
	/*
	 * Initialize configuration data with default values.
152
	 */
153 154
	view->recursion = ISC_TRUE;
	view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */
Michael Graff's avatar
 
Michael Graff committed
155 156
	view->additionalfromcache = ISC_TRUE;
	view->additionalfromauth = ISC_TRUE;
157
	view->transfer_format = dns_one_answer;
158 159
	view->queryacl = NULL;
	view->recursionacl = NULL;
160
	view->v6synthesisacl = NULL;
161
	view->sortlist = NULL;
162 163
	view->requestixfr = ISC_TRUE;
	view->provideixfr = ISC_TRUE;
164 165
	view->maxcachettl = 7 * 24 * 3600;
	view->maxncachettl = 3 * 3600;
166
	view->dstport = 53;
167
	view->cachefile = NULL;
168

169
	result = dns_peerlist_new(view->mctx, &view->peers);
170
	if (result != ISC_R_SUCCESS)
171
		goto cleanup_dynkeys;
Michael Graff's avatar
Michael Graff committed
172
	ISC_LINK_INIT(view, link);
173 174 175 176 177 178
	ISC_EVENT_INIT(&view->resevent, sizeof view->resevent, 0, NULL,
		       DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown,
		       view, NULL, NULL, NULL);
	ISC_EVENT_INIT(&view->adbevent, sizeof view->adbevent, 0, NULL,
		       DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown,
		       view, NULL, NULL, NULL);
Mark Andrews's avatar
Mark Andrews committed
179 180 181
	ISC_EVENT_INIT(&view->reqevent, sizeof view->reqevent, 0, NULL,
		       DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown,
		       view, NULL, NULL, NULL);
Bob Halley's avatar
add  
Bob Halley committed
182
	view->magic = DNS_VIEW_MAGIC;
183

Bob Halley's avatar
add  
Bob Halley committed
184 185 186 187
	*viewp = view;

	return (ISC_R_SUCCESS);

188
 cleanup_dynkeys:
189
	dns_tsigkeyring_destroy(&view->dynamickeys);
190

191 192 193
 cleanup_fwdtable:
	dns_fwdtable_destroy(&view->fwdtable);

194 195 196
 cleanup_trustedkeys:
	dns_keytable_detach(&view->trustedkeys);

197
 cleanup_secroots:
198
	dns_keytable_detach(&view->secroots);
199

200 201
 cleanup_zt:
	dns_zt_detach(&view->zonetable);
Bob Halley's avatar
Bob Halley committed
202

203 204 205
 cleanup_rwlock:
	isc_rwlock_destroy(&view->conflock);

Bob Halley's avatar
add  
Bob Halley committed
206
 cleanup_mutex:
207
	DESTROYLOCK(&view->lock);
Bob Halley's avatar
add  
Bob Halley committed
208 209 210 211 212 213 214 215 216 217 218 219 220

 cleanup_name:
	isc_mem_free(mctx, view->name);

 cleanup_view:
	isc_mem_put(mctx, view, sizeof *view);

	return (result);
}

static inline void
destroy(dns_view_t *view) {
	REQUIRE(!ISC_LINK_LINKED(view, link));
221
	REQUIRE(view->references == 0);
222
	REQUIRE(view->weakrefs == 0);
223 224
	REQUIRE(RESSHUTDOWN(view));
	REQUIRE(ADBSHUTDOWN(view));
Mark Andrews's avatar
Mark Andrews committed
225
	REQUIRE(REQSHUTDOWN(view));
Bob Halley's avatar
add  
Bob Halley committed
226

227 228
	if (view->peers != NULL)
		dns_peerlist_detach(&view->peers);
229
	if (view->dynamickeys != NULL)
230
		dns_tsigkeyring_destroy(&view->dynamickeys);
231
	if (view->statickeys != NULL)
232
		dns_tsigkeyring_destroy(&view->statickeys);
Bob Halley's avatar
add adb  
Bob Halley committed
233 234
	if (view->adb != NULL)
		dns_adb_detach(&view->adb);
Bob Halley's avatar
add  
Bob Halley committed
235 236
	if (view->resolver != NULL)
		dns_resolver_detach(&view->resolver);
237 238
	if (view->loadmgr != NULL)
		dns_loadmgr_detach(&view->loadmgr);
Mark Andrews's avatar
Mark Andrews committed
239 240
	if (view->requestmgr != NULL)
		dns_requestmgr_detach(&view->requestmgr);
241 242
	if (view->task != NULL)
		isc_task_detach(&view->task);
Bob Halley's avatar
Bob Halley committed
243 244
	if (view->hints != NULL)
		dns_db_detach(&view->hints);
Bob Halley's avatar
Bob Halley committed
245 246
	if (view->cachedb != NULL)
		dns_db_detach(&view->cachedb);
247 248
	if (view->cache != NULL)
		dns_cache_detach(&view->cache);
249 250
	if (view->matchclients != NULL)
		dns_acl_detach(&view->matchclients);
251 252 253 254
	if (view->queryacl != NULL)
		dns_acl_detach(&view->queryacl);
	if (view->recursionacl != NULL)
		dns_acl_detach(&view->recursionacl);
255 256
	if (view->v6synthesisacl != NULL)
		dns_acl_detach(&view->v6synthesisacl);
257 258
	if (view->sortlist != NULL)
		dns_acl_detach(&view->sortlist);
259 260
	if (view->cachefile != NULL)
		isc_mem_free(view->mctx, view->cachefile);
261 262
	dns_keytable_detach(&view->trustedkeys);
	dns_keytable_detach(&view->secroots);
263
	dns_fwdtable_destroy(&view->fwdtable);
264
	isc_rwlock_destroy(&view->conflock);
265
	DESTROYLOCK(&view->lock);
Bob Halley's avatar
add  
Bob Halley committed
266 267 268 269
	isc_mem_free(view->mctx, view->name);
	isc_mem_put(view->mctx, view, sizeof *view);
}

270 271 272 273
/*
 * Return true iff 'view' may be freed.
 * The caller must be holding the view lock.
 */
274 275 276
static isc_boolean_t
all_done(dns_view_t *view) {

277 278
	if (view->references == 0 && view->weakrefs == 0 &&
	    RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view))
279 280 281 282 283
		return (ISC_TRUE);

	return (ISC_FALSE);
}

284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
void
dns_view_attach(dns_view_t *source, dns_view_t **targetp) {

	REQUIRE(DNS_VIEW_VALID(source));
	REQUIRE(targetp != NULL && *targetp == NULL);

	LOCK(&source->lock);

	INSIST(source->references > 0);
	source->references++;
	INSIST(source->references != 0);

	UNLOCK(&source->lock);

	*targetp = source;
}

301 302
static void
view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) {
Bob Halley's avatar
add  
Bob Halley committed
303
	dns_view_t *view;
304
	isc_boolean_t done = ISC_FALSE;
Bob Halley's avatar
add  
Bob Halley committed
305 306 307 308 309 310 311 312 313

	REQUIRE(viewp != NULL);
	view = *viewp;
	REQUIRE(DNS_VIEW_VALID(view));

	LOCK(&view->lock);

	INSIST(view->references > 0);
	view->references--;
314 315 316 317 318
	if (view->references == 0) {
		if (!RESSHUTDOWN(view))
			dns_resolver_shutdown(view->resolver);
		if (!ADBSHUTDOWN(view))
			dns_adb_shutdown(view->adb);
Mark Andrews's avatar
Mark Andrews committed
319 320
		if (!REQSHUTDOWN(view))
			dns_requestmgr_shutdown(view->requestmgr);
321 322 323 324
		if (flush)
			dns_zt_flushanddetach(&view->zonetable);
		else
			dns_zt_detach(&view->zonetable);
325 326
		done = all_done(view);
	}
Bob Halley's avatar
add  
Bob Halley committed
327 328 329 330
	UNLOCK(&view->lock);

	*viewp = NULL;

331 332 333 334
	if (done)
		destroy(view);
}

335
void
336 337 338 339 340 341 342 343 344
dns_view_flushanddetach(dns_view_t **viewp) {
	view_flushanddetach(viewp, ISC_TRUE);
}

void
dns_view_detach(dns_view_t **viewp) {
	view_flushanddetach(viewp, ISC_FALSE);
}

Mark Andrews's avatar
Mark Andrews committed
345
static isc_result_t
346 347
dialup(dns_zone_t *zone, void *dummy) {
	UNUSED(dummy);
Mark Andrews's avatar
Mark Andrews committed
348 349 350 351 352 353 354 355 356 357
	dns_zone_dialup(zone);
	return (ISC_R_SUCCESS);
}

void
dns_view_dialup(dns_view_t *view) {
	REQUIRE(DNS_VIEW_VALID(view));
	dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL);
}

358
void
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) {

	REQUIRE(DNS_VIEW_VALID(source));
	REQUIRE(targetp != NULL && *targetp == NULL);

	LOCK(&source->lock);
	source->weakrefs++;
	UNLOCK(&source->lock);

	*targetp = source;
}

void
dns_view_weakdetach(dns_view_t **viewp) {
	dns_view_t *view;
	isc_boolean_t done = ISC_FALSE;

	REQUIRE(viewp != NULL);
	view = *viewp;
	REQUIRE(DNS_VIEW_VALID(view));

	LOCK(&view->lock);

	INSIST(view->weakrefs > 0);
	view->weakrefs--;
	done = all_done(view);

	UNLOCK(&view->lock);

	*viewp = NULL;

	if (done)
		destroy(view);
}

394 395
static void
resolver_shutdown(isc_task_t *task, isc_event_t *event) {
396
	dns_view_t *view = event->ev_arg;
397
	isc_boolean_t done;
398

399
	REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN);
400 401 402
	REQUIRE(DNS_VIEW_VALID(view));
	REQUIRE(view->task == task);

403
	UNUSED(task);
404

405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
	LOCK(&view->lock);

	view->attributes |= DNS_VIEWATTR_RESSHUTDOWN;
	done = all_done(view);

	UNLOCK(&view->lock);

	isc_event_free(&event);

	if (done)
		destroy(view);
}

static void
adb_shutdown(isc_task_t *task, isc_event_t *event) {
420
	dns_view_t *view = event->ev_arg;
421
	isc_boolean_t done;
422

423
	REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN);
424 425 426
	REQUIRE(DNS_VIEW_VALID(view));
	REQUIRE(view->task == task);

427
	UNUSED(task);
428

429 430 431 432 433 434 435 436 437 438
	LOCK(&view->lock);

	view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN;
	done = all_done(view);

	UNLOCK(&view->lock);

	isc_event_free(&event);

	if (done)
Bob Halley's avatar
add  
Bob Halley committed
439 440
		destroy(view);
}
441

Mark Andrews's avatar
Mark Andrews committed
442 443 444 445
static void
req_shutdown(isc_task_t *task, isc_event_t *event) {
	dns_view_t *view = event->ev_arg;
	isc_boolean_t done;
446

Mark Andrews's avatar
Mark Andrews committed
447 448 449 450
	REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN);
	REQUIRE(DNS_VIEW_VALID(view));
	REQUIRE(view->task == task);

451
	UNUSED(task);
452

Mark Andrews's avatar
Mark Andrews committed
453 454 455 456 457 458 459 460 461 462 463 464 465
	LOCK(&view->lock);

	view->attributes |= DNS_VIEWATTR_REQSHUTDOWN;
	done = all_done(view);

	UNLOCK(&view->lock);

	isc_event_free(&event);

	if (done)
		destroy(view);
}

Bob Halley's avatar
Bob Halley committed
466
isc_result_t
Bob Halley's avatar
Bob Halley committed
467 468 469 470
dns_view_createresolver(dns_view_t *view,
			isc_taskmgr_t *taskmgr, unsigned int ntasks,
			isc_socketmgr_t *socketmgr,
			isc_timermgr_t *timermgr,
471
			unsigned int options,
472
			dns_dispatchmgr_t *dispatchmgr,
473 474
			dns_dispatch_t *dispatchv4,
			dns_dispatch_t *dispatchv6)
Bob Halley's avatar
Bob Halley committed
475
{
Bob Halley's avatar
add adb  
Bob Halley committed
476
	isc_result_t result;
477
	isc_event_t *event;
Bob Halley's avatar
add adb  
Bob Halley committed
478

479
	REQUIRE(DNS_VIEW_VALID(view));
Bob Halley's avatar
Bob Halley committed
480
	REQUIRE(!view->frozen);
481
	REQUIRE(view->resolver == NULL);
482

Bob Halley's avatar
Bob Halley committed
483
	result = isc_task_create(taskmgr, 0, &view->task);
484 485
	if (result != ISC_R_SUCCESS)
		return (result);
Bob Halley's avatar
Bob Halley committed
486
	isc_task_setname(view->task, "view", view);
487

Bob Halley's avatar
add adb  
Bob Halley committed
488
	result = dns_resolver_create(view, taskmgr, ntasks, socketmgr,
489 490
				     timermgr, options, dispatchmgr,
				     dispatchv4, dispatchv6,
491
				     &view->resolver);
492 493
	if (result != ISC_R_SUCCESS) {
		isc_task_detach(&view->task);
Bob Halley's avatar
add adb  
Bob Halley committed
494
		return (result);
495 496 497 498 499
	}
	event = &view->resevent;
	dns_resolver_whenshutdown(view->resolver, view->task, &event);
	view->attributes &= ~DNS_VIEWATTR_RESSHUTDOWN;

Bob Halley's avatar
add adb  
Bob Halley committed
500 501
	result = dns_adb_create(view->mctx, view, timermgr, taskmgr,
				&view->adb);
502 503 504 505 506 507 508
	if (result != ISC_R_SUCCESS) {
		dns_resolver_shutdown(view->resolver);
		return (result);
	}
	event = &view->adbevent;
	dns_adb_whenshutdown(view->adb, view->task, &event);
	view->attributes &= ~DNS_VIEWATTR_ADBSHUTDOWN;
Bob Halley's avatar
add adb  
Bob Halley committed
509

Mark Andrews's avatar
Mark Andrews committed
510
	result = dns_requestmgr_create(view->mctx, timermgr, socketmgr,
David Lawrence's avatar
David Lawrence committed
511 512 513 514 515
				      dns_resolver_taskmgr(view->resolver),
				      dns_resolver_dispatchmgr(view->resolver),
				      dns_resolver_dispatchv4(view->resolver),
				      dns_resolver_dispatchv6(view->resolver),
				      &view->requestmgr);
Mark Andrews's avatar
Mark Andrews committed
516 517 518 519 520 521 522 523 524
	if (result != ISC_R_SUCCESS) {
		dns_adb_shutdown(view->adb);
		dns_resolver_shutdown(view->resolver);
		return (result);
	}
	event = &view->reqevent;
	dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event);
	view->attributes &= ~DNS_VIEWATTR_REQSHUTDOWN;

525
	return (ISC_R_SUCCESS);
526 527 528
}

void
529
dns_view_setcache(dns_view_t *view, dns_cache_t *cache) {
530
	REQUIRE(DNS_VIEW_VALID(view));
Bob Halley's avatar
Bob Halley committed
531
	REQUIRE(!view->frozen);
532

533
	if (view->cache != NULL) {
Bob Halley's avatar
add adb  
Bob Halley committed
534
		dns_db_detach(&view->cachedb);
535 536 537 538 539
		dns_cache_detach(&view->cache);
	}
	dns_cache_attach(cache, &view->cache);
	dns_cache_attachdb(cache, &view->cachedb);
	INSIST(DNS_DB_VALID(view->cachedb));
540 541
}

Bob Halley's avatar
Bob Halley committed
542 543 544 545 546 547 548 549 550 551
void
dns_view_sethints(dns_view_t *view, dns_db_t *hints) {
	REQUIRE(DNS_VIEW_VALID(view));
	REQUIRE(!view->frozen);
	REQUIRE(view->hints == NULL);
	REQUIRE(dns_db_iszone(hints));

	dns_db_attach(hints, &view->hints);
}

Brian Wellington's avatar
Brian Wellington committed
552 553 554 555
void
dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
	REQUIRE(DNS_VIEW_VALID(view));
	REQUIRE(ring != NULL);
556
	if (view->statickeys != NULL)
557
		dns_tsigkeyring_destroy(&view->statickeys);
Brian Wellington's avatar
Brian Wellington committed
558 559 560
	view->statickeys = ring;
}

561 562 563 564 565 566
void
dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
	REQUIRE(DNS_VIEW_VALID(view));
	view->dstport = dstport;
}

567 568 569 570 571 572 573 574 575
void
dns_view_setloadmgr(dns_view_t *view, dns_loadmgr_t *loadmgr) {
	REQUIRE(DNS_VIEW_VALID(view));

	if (view->loadmgr != NULL)
		dns_loadmgr_detach(&view->loadmgr);
	dns_loadmgr_attach(loadmgr, &view->loadmgr);
}

576
isc_result_t
577
dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
Bob Halley's avatar
Bob Halley committed
578 579
	isc_result_t result;

580
	REQUIRE(DNS_VIEW_VALID(view));
Bob Halley's avatar
Bob Halley committed
581 582
	REQUIRE(!view->frozen);

583
	result = dns_zt_mount(view->zonetable, zone);
584

Bob Halley's avatar
Bob Halley committed
585
	return (result);
586 587 588 589
}

void
dns_view_freeze(dns_view_t *view) {
Bob Halley's avatar
Bob Halley committed
590 591 592
	REQUIRE(DNS_VIEW_VALID(view));
	REQUIRE(!view->frozen);

593 594
	if (view->resolver != NULL) {
		INSIST(view->cachedb != NULL);
Bob Halley's avatar
Bob Halley committed
595
		dns_resolver_freeze(view->resolver);
596
	}
Bob Halley's avatar
Bob Halley committed
597 598 599
	view->frozen = ISC_TRUE;
}

600
isc_result_t
601
dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) {
602 603 604 605
	isc_result_t result;

	REQUIRE(DNS_VIEW_VALID(view));

Bob Halley's avatar
Bob Halley committed
606
	result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
607
	if (result == DNS_R_PARTIALMATCH) {
608
		dns_zone_detach(zonep);
609
		result = ISC_R_NOTFOUND;
610
	}
611

612 613 614
	return (result);
}

Bob Halley's avatar
Bob Halley committed
615 616
isc_result_t
dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
617 618
	      isc_stdtime_t now, unsigned int options, isc_boolean_t use_hints,
	      dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
Bob Halley's avatar
Bob Halley committed
619 620 621
	      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
	isc_result_t result;
622 623
	dns_db_t *db, *zdb;
	dns_dbnode_t *node, *znode;
624
	isc_boolean_t is_cache;
Bob Halley's avatar
Bob Halley committed
625
	dns_rdataset_t zrdataset, zsigrdataset;
626
	dns_zone_t *zone;
Bob Halley's avatar
Bob Halley committed
627 628 629 630 631 632

	/*
	 * Find an rdataset whose owner name is 'name', and whose type is
	 * 'type'.
	 */

633
	REQUIRE(DNS_VIEW_VALID(view));
Bob Halley's avatar
Bob Halley committed
634
	REQUIRE(view->frozen);
635 636
	REQUIRE(type != dns_rdatatype_sig);
	REQUIRE(rdataset != NULL);  /* XXXBEW - remove this */
Bob Halley's avatar
Bob Halley committed
637 638 639 640 641 642

	/*
	 * Initialize.
	 */
	dns_rdataset_init(&zrdataset);
	dns_rdataset_init(&zsigrdataset);
643 644
	zdb = NULL;
	znode = NULL;
Bob Halley's avatar
Bob Halley committed
645 646 647 648

	/*
	 * Find a database to answer the query.
	 */
649
	zone = NULL;
Bob Halley's avatar
Bob Halley committed
650
	db = NULL;
651
	node = NULL;
Bob Halley's avatar
Bob Halley committed
652
	result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
653 654
	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
		result = dns_zone_getdb(zone, &db);
655
		if (result != ISC_R_SUCCESS && view->cachedb != NULL)
656
			dns_db_attach(view->cachedb, &db);
657
		else if (result != ISC_R_SUCCESS)
658 659
			goto cleanup;
	} else if (result == ISC_R_NOTFOUND && view->cachedb != NULL)
Bob Halley's avatar
Bob Halley committed
660
		dns_db_attach(view->cachedb, &db);
661
	else
Bob Halley's avatar
Bob Halley committed
662 663
		goto cleanup;

664
	is_cache = dns_db_iscache(db);
665

Bob Halley's avatar
Bob Halley committed
666 667 668 669 670
 db_find:
	/*
	 * Now look for an answer in the database.
	 */
	result = dns_db_find(db, name, NULL, type, options,
671
			     now, &node, foundname, rdataset, sigrdataset);
Bob Halley's avatar
Bob Halley committed
672 673

	if (result == DNS_R_DELEGATION ||
674
	    result == ISC_R_NOTFOUND) {
675
		if (dns_rdataset_isassociated(rdataset))
Bob Halley's avatar
Bob Halley committed
676
			dns_rdataset_disassociate(rdataset);
677 678
		if (sigrdataset != NULL &&
		    dns_rdataset_isassociated(sigrdataset))
Bob Halley's avatar
Bob Halley committed
679
			dns_rdataset_disassociate(sigrdataset);
680 681
		if (node != NULL)
			dns_db_detachnode(db, &node);
682
		if (!is_cache) {
683
			dns_db_detach(&db);
Bob Halley's avatar
Bob Halley committed
684 685 686 687 688
			if (view->cachedb != NULL) {
				/*
				 * Either the answer is in the cache, or we
				 * don't know it.
				 */
689
				is_cache = ISC_TRUE;
Bob Halley's avatar
Bob Halley committed
690 691 692 693 694 695 696 697
				dns_db_attach(view->cachedb, &db);
				goto db_find;
			}
		} else {
			/*
			 * We don't have the data in the cache.  If we've got
			 * glue from the zone, use it.
			 */
698
			if (dns_rdataset_isassociated(&zrdataset)) {
Bob Halley's avatar
Bob Halley committed
699
				dns_rdataset_clone(&zrdataset, rdataset);
Bob Halley's avatar
Bob Halley committed
700
				if (sigrdataset != NULL &&
701
				    dns_rdataset_isassociated(&zsigrdataset))
Bob Halley's avatar
Bob Halley committed
702 703 704
					dns_rdataset_clone(&zsigrdataset,
							   sigrdataset);
				result = DNS_R_GLUE;
705 706 707 708
				if (db != NULL)
					dns_db_detach(&db);
				dns_db_attach(zdb, &db);
				dns_db_attachnode(db, znode, &node);
Bob Halley's avatar
Bob Halley committed
709 710 711 712 713 714
				goto cleanup;
			}
		}
		/*
		 * We don't know the answer.
		 */
715
		result = ISC_R_NOTFOUND;
Bob Halley's avatar
Bob Halley committed
716 717 718 719 720 721
	} else if (result == DNS_R_GLUE) {
		if (view->cachedb != NULL) {
			/*
			 * We found an answer, but the cache may be better.
			 * Remember what we've got and go look in the cache.
			 */
722
			is_cache = ISC_TRUE;
Bob Halley's avatar
Bob Halley committed
723 724
			dns_rdataset_clone(rdataset, &zrdataset);
			dns_rdataset_disassociate(rdataset);
Bob Halley's avatar
Bob Halley committed
725
			if (sigrdataset != NULL &&
726
			    dns_rdataset_isassociated(sigrdataset)) {
Bob Halley's avatar
Bob Halley committed
727 728 729
				dns_rdataset_clone(sigrdataset, &zsigrdataset);
				dns_rdataset_disassociate(sigrdataset);
			}
730 731 732
			dns_db_attach(db, &zdb);
			dns_db_attachnode(zdb, node, &znode);
			dns_db_detachnode(db, &node);
Bob Halley's avatar
Bob Halley committed
733 734 735 736 737 738 739 740
			dns_db_detach(&db);
			dns_db_attach(view->cachedb, &db);
			goto db_find;
		}
		/*
		 * Otherwise, the glue is the best answer.
		 */
		result = ISC_R_SUCCESS;
Bob Halley's avatar
Bob Halley committed
741 742
	}

743
	if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
744
		if (dns_rdataset_isassociated(rdataset))
Bob Halley's avatar
Bob Halley committed
745
			dns_rdataset_disassociate(rdataset);
746 747
		if (sigrdataset != NULL &&
		    dns_rdataset_isassociated(sigrdataset))
Bob Halley's avatar
Bob Halley committed
748
			dns_rdataset_disassociate(sigrdataset);
749 750 751 752 753
		if (db != NULL) {
			if (node != NULL)
				dns_db_detachnode(db, &node);
			dns_db_detach(&db);
		}
Bob Halley's avatar
Bob Halley committed
754
		result = dns_db_find(view->hints, name, NULL, type, options,
755
				     now, &node, foundname,
Bob Halley's avatar
Bob Halley committed
756
				     rdataset, sigrdataset);
Bob Halley's avatar
Bob Halley committed
757 758 759 760 761 762
		if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) {
			/*
			 * We just used a hint.  Let the resolver know it
			 * should consider priming.
			 */
			dns_resolver_prime(view->resolver);
763
			dns_db_attach(view->hints, &db);
Bob Halley's avatar
Bob Halley committed
764
			result = DNS_R_HINT;
765 766 767 768
		} else if (result == DNS_R_NXRRSET) {
			dns_db_attach(view->hints, &db);
			result = DNS_R_HINTNXRRSET;
		} else if (result == DNS_R_NXDOMAIN)
769
			result = ISC_R_NOTFOUND;
Bob Halley's avatar
Bob Halley committed
770
	}
Bob Halley's avatar
Bob Halley committed
771 772

 cleanup:
773 774 775 776
	if (result == DNS_R_NXDOMAIN || result == DNS_R_NXRRSET) {
		/*
		 * We don't care about any DNSSEC proof data in these cases.
		 */
777
		if (dns_rdataset_isassociated(rdataset))
778
			dns_rdataset_disassociate(rdataset);
779 780
		if (sigrdataset != NULL &&
		    dns_rdataset_isassociated(sigrdataset))
781 782
			dns_rdataset_disassociate(sigrdataset);
	}
Bob Halley's avatar
Bob Halley committed
783

784
	if (dns_rdataset_isassociated(&zrdataset)) {
Bob Halley's avatar
Bob Halley committed
785
		dns_rdataset_disassociate(&zrdataset);
786
		if (dns_rdataset_isassociated(&zsigrdataset))
Bob Halley's avatar
Bob Halley committed
787 788
			dns_rdataset_disassociate(&zsigrdataset);
	}
789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808

	if (zdb != NULL) {
		if (znode != NULL)
			dns_db_detachnode(zdb, &znode);
		dns_db_detach(&zdb);
	}

	if (db != NULL) {
		if (node != NULL) {
			if (nodep != NULL)
				*nodep = node;
			else
				dns_db_detachnode(db, &node);
		}
		if (dbp != NULL)
			*dbp = db;
		else
			dns_db_detach(&db);
	}

809 810
	if (zone != NULL)
		dns_zone_detach(&zone);
Bob Halley's avatar
Bob Halley committed
811 812

	return (result);
813
}
814

815 816 817 818 819 820 821 822 823 824 825
isc_result_t
dns_view_simplefind(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
		    isc_stdtime_t now, unsigned int options,
		    isc_boolean_t use_hints,
		    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
	isc_result_t result;
	dns_fixedname_t foundname;

	dns_fixedname_init(&foundname);
	result = dns_view_find(view, name, type, now, options, use_hints,
826
			       NULL, NULL, dns_fixedname_name(&foundname),
827
			       rdataset, sigrdataset);
828 829 830 831 832 833 834
	if (result == DNS_R_NXDOMAIN) {
		/*
		 * The rdataset and sigrdataset of the relevant NXT record
		 * may be returned, but the caller cannot use them because
		 * foundname is not returned by this simplified API.  We
		 * disassociate them here to prevent any misuse by the caller.
		 */
835
		if (dns_rdataset_isassociated(rdataset))
836
			dns_rdataset_disassociate(rdataset);
837 838
		if (sigrdataset != NULL &&
		    dns_rdataset_isassociated(sigrdataset))
839 840 841 842 843 844 845
			dns_rdataset_disassociate(sigrdataset);
	} else if (result != ISC_R_SUCCESS &&
		   result != DNS_R_GLUE &&
		   result != DNS_R_HINT &&
		   result != DNS_R_NCACHENXDOMAIN &&
		   result != DNS_R_NCACHENXRRSET &&
		   result != DNS_R_NXRRSET &&
846
		   result != DNS_R_HINTNXRRSET &&
847
		   result != ISC_R_NOTFOUND) {
848
		if (dns_rdataset_isassociated(rdataset))
849
			dns_rdataset_disassociate(rdataset);
850 851
		if (sigrdataset != NULL &&
		    dns_rdataset_isassociated(sigrdataset))
852
			dns_rdataset_disassociate(sigrdataset);
853
		result = ISC_R_NOTFOUND;
854 855 856 857 858
	}

	return (result);
}

Bob Halley's avatar
Bob Halley committed
859 860 861 862 863 864 865 866
isc_result_t
dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
		     isc_stdtime_t now, unsigned int options,
		     isc_boolean_t use_hints,
		     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
	isc_result_t result;
	dns_db_t *db;
867
	isc_boolean_t is_cache, use_zone, try_hints;
Bob Halley's avatar
Bob Halley committed
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891
	dns_zone_t *zone;
	dns_name_t *zfname;
	dns_rdataset_t zrdataset, zsigrdataset;
	dns_fixedname_t zfixedname;

	REQUIRE(DNS_VIEW_VALID(view));
	REQUIRE(view->frozen);

	db = NULL;
	zone = NULL;
	use_zone = ISC_FALSE;
	try_hints = ISC_FALSE;
	zfname = NULL;

	/*
	 * Initialize.
	 */
	dns_fixedname_init(&zfixedname);
	dns_rdataset_init(&zrdataset);
	dns_rdataset_init(&zsigrdataset);

	/*
	 * Find the right database.
	 */
Bob Halley's avatar
Bob Halley committed
892
	result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
893
	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
Bob Halley's avatar
Bob Halley committed
894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
		result = dns_zone_getdb(zone, &db);
	if (result == ISC_R_NOTFOUND) {
		/*
		 * We're not directly authoritative for this query name, nor
		 * is it a subdomain of any zone for which we're
		 * authoritative.
		 */
		if (view->cachedb != NULL) {
			/*
			 * We have a cache; try it.
			 */
			dns_db_attach(view->cachedb, &db);
		} else {
			/*
			 * Maybe we have hints...
			 */
			try_hints = ISC_TRUE;
			goto finish;
		}
	} else if (result != ISC_R_SUCCESS) {
		/*
		 * Something is broken.
		 */
		goto cleanup;
	}
919
	is_cache = dns_db_iscache(db);
Bob Halley's avatar
Bob Halley committed
920 921 922 923 924

 db_find:
	/*
	 * Look for the zonecut.
	 */
925
	if (!is_cache) {
Bob Halley's avatar
Bob Halley committed
926 927 928 929 930 931 932 933 934 935 936 937