view.c 28.8 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.110 2002/03/07 13:46:33 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->v6synthesisacl = NULL;
157
	view->sortlist = NULL;
158 159
	view->requestixfr = ISC_TRUE;
	view->provideixfr = ISC_TRUE;
160 161
	view->maxcachettl = 7 * 24 * 3600;
	view->maxncachettl = 3 * 3600;
162
	view->dstport = 53;
163

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

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

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

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

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

	return (ISC_R_SUCCESS);

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

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

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

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

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

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

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

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

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

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

	return (result);
}

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

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

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

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

	return (ISC_FALSE);
}

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

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

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

	*targetp = source;
}

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

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

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

	*viewp = NULL;

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

337
void
338 339 340 341 342 343 344 345 346
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
347
static isc_result_t
348 349
dialup(dns_zone_t *zone, void *dummy) {
	UNUSED(dummy);
Mark Andrews's avatar
Mark Andrews committed
350 351 352 353 354 355 356
	dns_zone_dialup(zone);
	return (ISC_R_SUCCESS);
}

void
dns_view_dialup(dns_view_t *view) {
	REQUIRE(DNS_VIEW_VALID(view));
357
	(void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL);
Mark Andrews's avatar
Mark Andrews committed
358 359
}

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

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

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

405
	UNUSED(task);
406

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

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

429
	UNUSED(task);
430

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

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

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

453
	UNUSED(task);
454

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

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

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

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

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

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

529
	return (ISC_R_SUCCESS);
530 531 532
}

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

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

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

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

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

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

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

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

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

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

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

	REQUIRE(DNS_VIEW_VALID(view));

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

607 608 609
	return (result);
}

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

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

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

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

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

659
	is_cache = dns_db_iscache(db);
660

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

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

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

		/*
		 * 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
771
	}
Bob Halley's avatar
Bob Halley committed
772 773

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

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

	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);
808 809
	} else
		INSIST(node == NULL);
810

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

	return (result);
815
}
816

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

	return (result);
}

Bob Halley's avatar
Bob Halley committed
861 862 863 864 865 866 867 868
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