view.c 29.2 KB
Newer Older
Bob Halley's avatar
add  
Bob Halley committed
1
/*
Brian Wellington's avatar
Brian Wellington committed
2
 * Copyright (C) 1999-2001  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.115 2003/02/26 22:54:28 marka 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/order.h>
36
#include <dns/peer.h>
Bob Halley's avatar
Bob Halley committed
37
#include <dns/rdataset.h>
Mark Andrews's avatar
Mark Andrews committed
38
#include <dns/request.h>
39 40
#include <dns/resolver.h>
#include <dns/result.h>
Brian Wellington's avatar
Brian Wellington committed
41
#include <dns/tsig.h>
42
#include <dns/zone.h>
43
#include <dns/zt.h>
Bob Halley's avatar
add  
Bob Halley committed
44

45 46
#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
47
#define REQSHUTDOWN(v)	(((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0)
48 49 50

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
51
static void req_shutdown(isc_task_t *task, isc_event_t *event);
52

Bob Halley's avatar
add  
Bob Halley committed
53
isc_result_t
54 55
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
56 57 58 59 60 61 62 63 64 65 66
{
	dns_view_t *view;
	isc_result_t result;

	/*
	 * Create a view.
	 */

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

Andreas Gustafsson's avatar
Andreas Gustafsson committed
67
	view = isc_mem_get(mctx, sizeof(*view));
Bob Halley's avatar
add  
Bob Halley committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
	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;
	}
83 84
	view->zonetable = NULL;
	result = dns_zt_create(mctx, rdclass, &view->zonetable);
Bob Halley's avatar
add  
Bob Halley committed
85 86
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
87
				 "dns_zt_create() failed: %s",
Bob Halley's avatar
add  
Bob Halley committed
88 89
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
90
		goto cleanup_mutex;
Bob Halley's avatar
add  
Bob Halley committed
91
	}
Bob Halley's avatar
Bob Halley committed
92
	view->secroots = NULL;
93
	result = dns_keytable_create(mctx, &view->secroots);
Bob Halley's avatar
Bob Halley committed
94 95
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
96
				 "dns_keytable_create() failed: %s",
Bob Halley's avatar
Bob Halley committed
97 98
				 isc_result_totext(result));
		result = ISC_R_UNEXPECTED;
99
		goto cleanup_zt;
Bob Halley's avatar
Bob Halley committed
100
	}
101 102 103 104 105 106 107 108 109
	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;
	}
110 111 112 113 114 115 116 117 118
	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;
	}
119

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

145 146
	/*
	 * Initialize configuration data with default values.
147
	 */
148 149
	view->recursion = ISC_TRUE;
	view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */
Michael Graff's avatar
 
Michael Graff committed
150 151
	view->additionalfromcache = ISC_TRUE;
	view->additionalfromauth = ISC_TRUE;
Bob Halley's avatar
Bob Halley committed
152
	view->minimalresponses = ISC_FALSE;
153
	view->transfer_format = dns_one_answer;
154 155
	view->queryacl = NULL;
	view->recursionacl = NULL;
156
	view->sortlist = NULL;
157 158
	view->requestixfr = ISC_TRUE;
	view->provideixfr = ISC_TRUE;
159 160
	view->maxcachettl = 7 * 24 * 3600;
	view->maxncachettl = 3 * 3600;
161
	view->dstport = 53;
162
	view->preferred_glue = 0;
163
	view->flush = ISC_FALSE;
164

165
	result = dns_order_create(view->mctx, &view->order);
166
	if (result != ISC_R_SUCCESS)
167
		goto cleanup_dynkeys;
168

169 170 171 172
	result = dns_peerlist_new(view->mctx, &view->peers);
	if (result != ISC_R_SUCCESS)
		goto cleanup_order;

173 174 175 176
	result = dns_aclenv_init(view->mctx, &view->aclenv);
	if (result != ISC_R_SUCCESS)
		goto cleanup_peerlist;

Michael Graff's avatar
Michael Graff committed
177
	ISC_LINK_INIT(view, link);
Andreas Gustafsson's avatar
Andreas Gustafsson committed
178
	ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL,
179 180
		       DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown,
		       view, NULL, NULL, NULL);
Andreas Gustafsson's avatar
Andreas Gustafsson committed
181
	ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL,
182 183
		       DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown,
		       view, NULL, NULL, NULL);
Andreas Gustafsson's avatar
Andreas Gustafsson committed
184
	ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL,
Mark Andrews's avatar
Mark Andrews committed
185 186
		       DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown,
		       view, NULL, NULL, NULL);
Bob Halley's avatar
add  
Bob Halley committed
187
	view->magic = DNS_VIEW_MAGIC;
188

Bob Halley's avatar
add  
Bob Halley committed
189 190 191 192
	*viewp = view;

	return (ISC_R_SUCCESS);

193 194 195
 cleanup_peerlist:
	dns_peerlist_detach(&view->peers);

196 197 198
 cleanup_order:
	dns_order_detach(&view->order);

199
 cleanup_dynkeys:
200
	dns_tsigkeyring_destroy(&view->dynamickeys);
201

202 203 204
 cleanup_fwdtable:
	dns_fwdtable_destroy(&view->fwdtable);

205 206 207
 cleanup_trustedkeys:
	dns_keytable_detach(&view->trustedkeys);

208
 cleanup_secroots:
209
	dns_keytable_detach(&view->secroots);
210

211 212
 cleanup_zt:
	dns_zt_detach(&view->zonetable);
Bob Halley's avatar
Bob Halley committed
213

Bob Halley's avatar
add  
Bob Halley committed
214
 cleanup_mutex:
215
	DESTROYLOCK(&view->lock);
Bob Halley's avatar
add  
Bob Halley committed
216 217 218 219 220

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

 cleanup_view:
Andreas Gustafsson's avatar
Andreas Gustafsson committed
221
	isc_mem_put(mctx, view, sizeof(*view));
Bob Halley's avatar
add  
Bob Halley committed
222 223 224 225 226 227 228

	return (result);
}

static inline void
destroy(dns_view_t *view) {
	REQUIRE(!ISC_LINK_LINKED(view, link));
229
	REQUIRE(isc_refcount_current(&view->references) == 0);
230
	REQUIRE(view->weakrefs == 0);
231 232
	REQUIRE(RESSHUTDOWN(view));
	REQUIRE(ADBSHUTDOWN(view));
Mark Andrews's avatar
Mark Andrews committed
233
	REQUIRE(REQSHUTDOWN(view));
Bob Halley's avatar
add  
Bob Halley committed
234

235 236
	if (view->order != NULL)
		dns_order_detach(&view->order);
237 238
	if (view->peers != NULL)
		dns_peerlist_detach(&view->peers);
239
	if (view->dynamickeys != NULL)
240
		dns_tsigkeyring_destroy(&view->dynamickeys);
241
	if (view->statickeys != NULL)
242
		dns_tsigkeyring_destroy(&view->statickeys);
Bob Halley's avatar
add adb  
Bob Halley committed
243 244
	if (view->adb != NULL)
		dns_adb_detach(&view->adb);
Bob Halley's avatar
add  
Bob Halley committed
245 246
	if (view->resolver != NULL)
		dns_resolver_detach(&view->resolver);
Mark Andrews's avatar
Mark Andrews committed
247 248
	if (view->requestmgr != NULL)
		dns_requestmgr_detach(&view->requestmgr);
249 250
	if (view->task != NULL)
		isc_task_detach(&view->task);
Bob Halley's avatar
Bob Halley committed
251 252
	if (view->hints != NULL)
		dns_db_detach(&view->hints);
Bob Halley's avatar
Bob Halley committed
253 254
	if (view->cachedb != NULL)
		dns_db_detach(&view->cachedb);
255 256
	if (view->cache != NULL)
		dns_cache_detach(&view->cache);
257 258
	if (view->matchclients != NULL)
		dns_acl_detach(&view->matchclients);
259 260
	if (view->matchdestinations != NULL)
		dns_acl_detach(&view->matchdestinations);
261 262 263 264
	if (view->queryacl != NULL)
		dns_acl_detach(&view->queryacl);
	if (view->recursionacl != NULL)
		dns_acl_detach(&view->recursionacl);
265 266
	if (view->sortlist != NULL)
		dns_acl_detach(&view->sortlist);
267 268
	dns_keytable_detach(&view->trustedkeys);
	dns_keytable_detach(&view->secroots);
269
	dns_fwdtable_destroy(&view->fwdtable);
270
	dns_aclenv_destroy(&view->aclenv);
271
	DESTROYLOCK(&view->lock);
272
	isc_refcount_destroy(&view->references);
Bob Halley's avatar
add  
Bob Halley committed
273
	isc_mem_free(view->mctx, view->name);
Andreas Gustafsson's avatar
Andreas Gustafsson committed
274
	isc_mem_put(view->mctx, view, sizeof(*view));
Bob Halley's avatar
add  
Bob Halley committed
275 276
}

277 278 279 280
/*
 * Return true iff 'view' may be freed.
 * The caller must be holding the view lock.
 */
281 282 283
static isc_boolean_t
all_done(dns_view_t *view) {

284 285
	if (isc_refcount_current(&view->references) == 0 &&
	    view->weakrefs == 0 &&
286
	    RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view))
287 288 289 290 291
		return (ISC_TRUE);

	return (ISC_FALSE);
}

292 293 294 295 296 297
void
dns_view_attach(dns_view_t *source, dns_view_t **targetp) {

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

298
	isc_refcount_increment(&source->references, NULL);
299 300 301 302

	*targetp = source;
}

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

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

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

	*viewp = NULL;

334 335 336 337
	if (done)
		destroy(view);
}

338
void
339 340 341 342 343 344 345 346 347
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
348
static isc_result_t
349 350
dialup(dns_zone_t *zone, void *dummy) {
	UNUSED(dummy);
Mark Andrews's avatar
Mark Andrews committed
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));
358
	(void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL);
Mark Andrews's avatar
Mark Andrews committed
359 360
}

361
void
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 394 395 396
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);
}

397 398
static void
resolver_shutdown(isc_task_t *task, isc_event_t *event) {
399
	dns_view_t *view = event->ev_arg;
400
	isc_boolean_t done;
401

402
	REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN);
403 404 405
	REQUIRE(DNS_VIEW_VALID(view));
	REQUIRE(view->task == task);

406
	UNUSED(task);
407

408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
	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) {
423
	dns_view_t *view = event->ev_arg;
424
	isc_boolean_t done;
425

426
	REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN);
427 428 429
	REQUIRE(DNS_VIEW_VALID(view));
	REQUIRE(view->task == task);

430
	UNUSED(task);
431

432 433 434 435 436 437 438 439 440 441
	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
442 443
		destroy(view);
}
444

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

Mark Andrews's avatar
Mark Andrews committed
450 451 452 453
	REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN);
	REQUIRE(DNS_VIEW_VALID(view));
	REQUIRE(view->task == task);

454
	UNUSED(task);
455

Mark Andrews's avatar
Mark Andrews committed
456 457 458 459 460 461 462 463 464 465 466 467 468
	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
469
isc_result_t
Bob Halley's avatar
Bob Halley committed
470 471 472 473
dns_view_createresolver(dns_view_t *view,
			isc_taskmgr_t *taskmgr, unsigned int ntasks,
			isc_socketmgr_t *socketmgr,
			isc_timermgr_t *timermgr,
474
			unsigned int options,
475
			dns_dispatchmgr_t *dispatchmgr,
476 477
			dns_dispatch_t *dispatchv4,
			dns_dispatch_t *dispatchv6)
Bob Halley's avatar
Bob Halley committed
478
{
Bob Halley's avatar
add adb  
Bob Halley committed
479
	isc_result_t result;
480
	isc_event_t *event;
481
	isc_mem_t *mctx = NULL;
Bob Halley's avatar
add adb  
Bob Halley committed
482

483
	REQUIRE(DNS_VIEW_VALID(view));
Bob Halley's avatar
Bob Halley committed
484
	REQUIRE(!view->frozen);
485
	REQUIRE(view->resolver == NULL);
486

Bob Halley's avatar
Bob Halley committed
487
	result = isc_task_create(taskmgr, 0, &view->task);
488 489
	if (result != ISC_R_SUCCESS)
		return (result);
Bob Halley's avatar
Bob Halley committed
490
	isc_task_setname(view->task, "view", view);
491

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

504 505 506
	isc_mem_create(0, 0, &mctx);
	result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb);
	isc_mem_detach(&mctx);
507 508 509 510 511 512 513
	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
514

Mark Andrews's avatar
Mark Andrews committed
515
	result = dns_requestmgr_create(view->mctx, timermgr, socketmgr,
David Lawrence's avatar
David Lawrence committed
516 517 518 519 520
				      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
521 522 523 524 525 526 527 528 529
	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;

530
	return (ISC_R_SUCCESS);
531 532 533
}

void
534
dns_view_setcache(dns_view_t *view, dns_cache_t *cache) {
535
	REQUIRE(DNS_VIEW_VALID(view));
Bob Halley's avatar
Bob Halley committed
536
	REQUIRE(!view->frozen);
537

538
	if (view->cache != NULL) {
Bob Halley's avatar
add adb  
Bob Halley committed
539
		dns_db_detach(&view->cachedb);
540 541 542 543 544
		dns_cache_detach(&view->cache);
	}
	dns_cache_attach(cache, &view->cache);
	dns_cache_attachdb(cache, &view->cachedb);
	INSIST(DNS_DB_VALID(view->cachedb));
545 546
}

Bob Halley's avatar
Bob Halley committed
547 548 549 550 551 552 553 554 555 556
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
557 558 559 560
void
dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
	REQUIRE(DNS_VIEW_VALID(view));
	REQUIRE(ring != NULL);
561
	if (view->statickeys != NULL)
562
		dns_tsigkeyring_destroy(&view->statickeys);
Brian Wellington's avatar
Brian Wellington committed
563 564 565
	view->statickeys = ring;
}

566 567 568 569 570 571
void
dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
	REQUIRE(DNS_VIEW_VALID(view));
	view->dstport = dstport;
}

572
isc_result_t
573
dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
Bob Halley's avatar
Bob Halley committed
574 575
	isc_result_t result;

576
	REQUIRE(DNS_VIEW_VALID(view));
Bob Halley's avatar
Bob Halley committed
577 578
	REQUIRE(!view->frozen);

579
	result = dns_zt_mount(view->zonetable, zone);
580

Bob Halley's avatar
Bob Halley committed
581
	return (result);
582 583 584 585
}

void
dns_view_freeze(dns_view_t *view) {
Bob Halley's avatar
Bob Halley committed
586 587 588
	REQUIRE(DNS_VIEW_VALID(view));
	REQUIRE(!view->frozen);

589 590
	if (view->resolver != NULL) {
		INSIST(view->cachedb != NULL);
Bob Halley's avatar
Bob Halley committed
591
		dns_resolver_freeze(view->resolver);
592
	}
Bob Halley's avatar
Bob Halley committed
593 594 595
	view->frozen = ISC_TRUE;
}

596
isc_result_t
597
dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) {
598 599 600 601
	isc_result_t result;

	REQUIRE(DNS_VIEW_VALID(view));

Bob Halley's avatar
Bob Halley committed
602
	result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
603
	if (result == DNS_R_PARTIALMATCH) {
604
		dns_zone_detach(zonep);
605
		result = ISC_R_NOTFOUND;
606
	}
607

608 609 610
	return (result);
}

Bob Halley's avatar
Bob Halley committed
611 612
isc_result_t
dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
613 614
	      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
615 616 617
	      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
	isc_result_t result;
618 619
	dns_db_t *db, *zdb;
	dns_dbnode_t *node, *znode;
620
	isc_boolean_t is_cache;
Bob Halley's avatar
Bob Halley committed
621
	dns_rdataset_t zrdataset, zsigrdataset;
622
	dns_zone_t *zone;
Bob Halley's avatar
Bob Halley committed
623 624 625 626 627 628

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

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

	/*
	 * Initialize.
	 */
	dns_rdataset_init(&zrdataset);
	dns_rdataset_init(&zsigrdataset);
639 640
	zdb = NULL;
	znode = NULL;
Bob Halley's avatar
Bob Halley committed
641 642 643 644

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

660
	is_cache = dns_db_iscache(db);
661

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

	if (result == DNS_R_DELEGATION ||
670
	    result == ISC_R_NOTFOUND) {
671
		if (dns_rdataset_isassociated(rdataset))
Bob Halley's avatar
Bob Halley committed
672
			dns_rdataset_disassociate(rdataset);
673 674
		if (sigrdataset != NULL &&
		    dns_rdataset_isassociated(sigrdataset))
Bob Halley's avatar
Bob Halley committed
675
			dns_rdataset_disassociate(sigrdataset);
676 677
		if (node != NULL)
			dns_db_detachnode(db, &node);
678
		if (!is_cache) {
679
			dns_db_detach(&db);
Bob Halley's avatar
Bob Halley committed
680 681 682 683 684
			if (view->cachedb != NULL) {
				/*
				 * Either the answer is in the cache, or we
				 * don't know it.
				 */
685
				is_cache = ISC_TRUE;
Bob Halley's avatar
Bob Halley committed
686 687 688 689 690 691 692 693
				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.
			 */
694
			if (dns_rdataset_isassociated(&zrdataset)) {
Bob Halley's avatar
Bob Halley committed
695
				dns_rdataset_clone(&zrdataset, rdataset);
Bob Halley's avatar
Bob Halley committed
696
				if (sigrdataset != NULL &&
697
				    dns_rdataset_isassociated(&zsigrdataset))
Bob Halley's avatar
Bob Halley committed
698 699 700
					dns_rdataset_clone(&zsigrdataset,
							   sigrdataset);
				result = DNS_R_GLUE;
701 702 703 704
				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
705 706 707 708 709 710
				goto cleanup;
			}
		}
		/*
		 * We don't know the answer.
		 */
711
		result = ISC_R_NOTFOUND;
Bob Halley's avatar
Bob Halley committed
712 713 714 715 716 717
	} 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.
			 */
718
			is_cache = ISC_TRUE;
Bob Halley's avatar
Bob Halley committed
719 720
			dns_rdataset_clone(rdataset, &zrdataset);
			dns_rdataset_disassociate(rdataset);
Bob Halley's avatar
Bob Halley committed
721
			if (sigrdataset != NULL &&
722
			    dns_rdataset_isassociated(sigrdataset)) {
Bob Halley's avatar
Bob Halley committed
723 724 725
				dns_rdataset_clone(sigrdataset, &zsigrdataset);
				dns_rdataset_disassociate(sigrdataset);
			}
726 727 728
			dns_db_attach(db, &zdb);
			dns_db_attachnode(zdb, node, &znode);
			dns_db_detachnode(db, &node);
Bob Halley's avatar
Bob Halley committed
729 730 731 732 733 734 735 736
			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
737 738
	}

739
	if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
740
		if (dns_rdataset_isassociated(rdataset))
Bob Halley's avatar
Bob Halley committed
741
			dns_rdataset_disassociate(rdataset);
742 743
		if (sigrdataset != NULL &&
		    dns_rdataset_isassociated(sigrdataset))
Bob Halley's avatar
Bob Halley committed
744
			dns_rdataset_disassociate(sigrdataset);
745 746 747 748 749
		if (db != NULL) {
			if (node != NULL)
				dns_db_detachnode(db, &node);
			dns_db_detach(&db);
		}
Bob Halley's avatar
Bob Halley committed
750
		result = dns_db_find(view->hints, name, NULL, type, options,
751
				     now, &node, foundname,
Bob Halley's avatar
Bob Halley committed
752
				     rdataset, sigrdataset);
Bob Halley's avatar
Bob Halley committed
753 754 755 756 757 758
		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);
759
			dns_db_attach(view->hints, &db);
Bob Halley's avatar
Bob Halley committed
760
			result = DNS_R_HINT;
761 762 763 764
		} else if (result == DNS_R_NXRRSET) {
			dns_db_attach(view->hints, &db);
			result = DNS_R_HINTNXRRSET;
		} else if (result == DNS_R_NXDOMAIN)
765
			result = ISC_R_NOTFOUND;
766 767 768 769 770 771

		/*
		 * Cleanup if non-standard hints are used.
		 */
		if (db == NULL && node != NULL)
			dns_db_detachnode(view->hints, &node);
Bob Halley's avatar
Bob Halley committed
772
	}
Bob Halley's avatar
Bob Halley committed
773 774

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

786
	if (dns_rdataset_isassociated(&zrdataset)) {
Bob Halley's avatar
Bob Halley committed
787
		dns_rdataset_disassociate(&zrdataset);
788
		if (dns_rdataset_isassociated(&zsigrdataset))
Bob Halley's avatar
Bob Halley committed
789 790
			dns_rdataset_disassociate(&zsigrdataset);
	}
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
	} else
		INSIST(node == NULL);
811

812 813
	if (zone != NULL)
		dns_zone_detach(&zone);
Bob Halley's avatar
Bob Halley committed
814 815

	return (result);
816
}
817

818 819 820 821 822 823 824 825 826 827 828
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,
829
			       NULL, NULL, dns_fixedname_name(&foundname),
830
			       rdataset, sigrdataset);
831 832 833 834 835 836 837
	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.
		 */
838
		if (dns_rdataset_isassociated(rdataset))
839
			dns_rdataset_disassociate(rdataset);
840 841
		if (sigrdataset != NULL &&
		    dns_rdataset_isassociated(sigrdataset))
842 843 844 845 846 847 848
			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 &&
849
		   result != DNS_R_HINTNXRRSET &&
850
		   result != ISC_R_NOTFOUND) {
851
		if (dns_rdataset_isassociated(rdataset))
852
			dns_rdataset_disassociate(rdataset);
853 854
		if (sigrdataset != NULL &&
		    dns_rdataset_isassociated(sigrdataset))
855
			dns_rdataset_disassociate(sigrdataset);
856
		result = ISC_R_NOTFOUND;
857 858 859 860 861
	}

	return (result);
}

Bob Halley's avatar
Bob Halley committed