mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-28 17:46:40 -04:00
removes some unused code in view.c and uncomments some code in cache.c. This still isn't really usable, since the trust level of cached data is not persistent, so all data in the persistent cache will be promoted to "ultimate" trust on reload.
1115 lines
28 KiB
C
1115 lines
28 KiB
C
/*
|
|
* Copyright (C) 1999-2001 Internet Software Consortium.
|
|
*
|
|
* 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.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
/* $Id: view.c,v 1.92 2001/01/12 22:22:16 bwelling Exp $ */
|
|
|
|
#include <config.h>
|
|
|
|
#include <isc/task.h>
|
|
#include <isc/string.h> /* Required for HP/UX (and others?) */
|
|
#include <isc/util.h>
|
|
|
|
#include <dns/acl.h>
|
|
#include <dns/adb.h>
|
|
#include <dns/cache.h>
|
|
#include <dns/db.h>
|
|
#include <dns/events.h>
|
|
#include <dns/forward.h>
|
|
#include <dns/keytable.h>
|
|
#include <dns/master.h>
|
|
#include <dns/masterdump.h>
|
|
#include <dns/peer.h>
|
|
#include <dns/rdataset.h>
|
|
#include <dns/request.h>
|
|
#include <dns/resolver.h>
|
|
#include <dns/result.h>
|
|
#include <dns/tsig.h>
|
|
#include <dns/zone.h>
|
|
#include <dns/zt.h>
|
|
|
|
#define RESSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0)
|
|
#define ADBSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
|
|
#define REQSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0)
|
|
|
|
static void resolver_shutdown(isc_task_t *task, isc_event_t *event);
|
|
static void adb_shutdown(isc_task_t *task, isc_event_t *event);
|
|
static void req_shutdown(isc_task_t *task, isc_event_t *event);
|
|
|
|
isc_result_t
|
|
dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
|
const char *name, dns_view_t **viewp)
|
|
{
|
|
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;
|
|
}
|
|
result = isc_rwlock_init(&view->conflock, 1, 1);
|
|
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;
|
|
}
|
|
view->zonetable = NULL;
|
|
result = dns_zt_create(mctx, rdclass, &view->zonetable);
|
|
if (result != ISC_R_SUCCESS) {
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
"dns_zt_create() failed: %s",
|
|
isc_result_totext(result));
|
|
result = ISC_R_UNEXPECTED;
|
|
goto cleanup_rwlock;
|
|
}
|
|
view->secroots = NULL;
|
|
result = dns_keytable_create(mctx, &view->secroots);
|
|
if (result != ISC_R_SUCCESS) {
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
"dns_keytable_create() failed: %s",
|
|
isc_result_totext(result));
|
|
result = ISC_R_UNEXPECTED;
|
|
goto cleanup_zt;
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
|
|
view->cache = NULL;
|
|
view->cachedb = NULL;
|
|
view->hints = NULL;
|
|
view->resolver = NULL;
|
|
view->adb = NULL;
|
|
view->loadmgr = NULL;
|
|
view->requestmgr = NULL;
|
|
view->mctx = mctx;
|
|
view->rdclass = rdclass;
|
|
view->frozen = ISC_FALSE;
|
|
view->task = NULL;
|
|
view->references = 1;
|
|
view->weakrefs = 0;
|
|
view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
|
|
DNS_VIEWATTR_REQSHUTDOWN);
|
|
view->statickeys = NULL;
|
|
view->dynamickeys = NULL;
|
|
view->matchclients = NULL;
|
|
result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
|
|
if (result != ISC_R_SUCCESS)
|
|
goto cleanup_fwdtable;
|
|
view->peers = NULL;
|
|
|
|
/*
|
|
* Initialize configuration data with default values.
|
|
*/
|
|
view->recursion = ISC_TRUE;
|
|
view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */
|
|
view->additionalfromcache = ISC_TRUE;
|
|
view->additionalfromauth = ISC_TRUE;
|
|
view->transfer_format = dns_one_answer;
|
|
view->queryacl = NULL;
|
|
view->recursionacl = NULL;
|
|
view->v6synthesisacl = NULL;
|
|
view->sortlist = NULL;
|
|
view->requestixfr = ISC_TRUE;
|
|
view->provideixfr = ISC_TRUE;
|
|
view->maxcachettl = 7 * 24 * 3600;
|
|
view->maxncachettl = 3 * 3600;
|
|
view->dstport = 53;
|
|
|
|
result = dns_peerlist_new(view->mctx, &view->peers);
|
|
if (result != ISC_R_SUCCESS)
|
|
goto cleanup_dynkeys;
|
|
ISC_LINK_INIT(view, link);
|
|
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);
|
|
ISC_EVENT_INIT(&view->reqevent, sizeof view->reqevent, 0, NULL,
|
|
DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown,
|
|
view, NULL, NULL, NULL);
|
|
view->magic = DNS_VIEW_MAGIC;
|
|
|
|
*viewp = view;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
cleanup_dynkeys:
|
|
dns_tsigkeyring_destroy(&view->dynamickeys);
|
|
|
|
cleanup_fwdtable:
|
|
dns_fwdtable_destroy(&view->fwdtable);
|
|
|
|
cleanup_trustedkeys:
|
|
dns_keytable_detach(&view->trustedkeys);
|
|
|
|
cleanup_secroots:
|
|
dns_keytable_detach(&view->secroots);
|
|
|
|
cleanup_zt:
|
|
dns_zt_detach(&view->zonetable);
|
|
|
|
cleanup_rwlock:
|
|
isc_rwlock_destroy(&view->conflock);
|
|
|
|
cleanup_mutex:
|
|
DESTROYLOCK(&view->lock);
|
|
|
|
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));
|
|
REQUIRE(view->references == 0);
|
|
REQUIRE(view->weakrefs == 0);
|
|
REQUIRE(RESSHUTDOWN(view));
|
|
REQUIRE(ADBSHUTDOWN(view));
|
|
REQUIRE(REQSHUTDOWN(view));
|
|
|
|
if (view->peers != NULL)
|
|
dns_peerlist_detach(&view->peers);
|
|
if (view->dynamickeys != NULL)
|
|
dns_tsigkeyring_destroy(&view->dynamickeys);
|
|
if (view->statickeys != NULL)
|
|
dns_tsigkeyring_destroy(&view->statickeys);
|
|
if (view->adb != NULL)
|
|
dns_adb_detach(&view->adb);
|
|
if (view->resolver != NULL)
|
|
dns_resolver_detach(&view->resolver);
|
|
if (view->loadmgr != NULL)
|
|
dns_loadmgr_detach(&view->loadmgr);
|
|
if (view->requestmgr != NULL)
|
|
dns_requestmgr_detach(&view->requestmgr);
|
|
if (view->task != NULL)
|
|
isc_task_detach(&view->task);
|
|
if (view->hints != NULL)
|
|
dns_db_detach(&view->hints);
|
|
if (view->cachedb != NULL)
|
|
dns_db_detach(&view->cachedb);
|
|
if (view->cache != NULL)
|
|
dns_cache_detach(&view->cache);
|
|
if (view->matchclients != NULL)
|
|
dns_acl_detach(&view->matchclients);
|
|
if (view->queryacl != NULL)
|
|
dns_acl_detach(&view->queryacl);
|
|
if (view->recursionacl != NULL)
|
|
dns_acl_detach(&view->recursionacl);
|
|
if (view->v6synthesisacl != NULL)
|
|
dns_acl_detach(&view->v6synthesisacl);
|
|
if (view->sortlist != NULL)
|
|
dns_acl_detach(&view->sortlist);
|
|
dns_keytable_detach(&view->trustedkeys);
|
|
dns_keytable_detach(&view->secroots);
|
|
dns_fwdtable_destroy(&view->fwdtable);
|
|
isc_rwlock_destroy(&view->conflock);
|
|
DESTROYLOCK(&view->lock);
|
|
isc_mem_free(view->mctx, view->name);
|
|
isc_mem_put(view->mctx, view, sizeof *view);
|
|
}
|
|
|
|
/*
|
|
* Return true iff 'view' may be freed.
|
|
* The caller must be holding the view lock.
|
|
*/
|
|
static isc_boolean_t
|
|
all_done(dns_view_t *view) {
|
|
|
|
if (view->references == 0 && view->weakrefs == 0 &&
|
|
RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view))
|
|
return (ISC_TRUE);
|
|
|
|
return (ISC_FALSE);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
static void
|
|
view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) {
|
|
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->references > 0);
|
|
view->references--;
|
|
if (view->references == 0) {
|
|
if (!RESSHUTDOWN(view))
|
|
dns_resolver_shutdown(view->resolver);
|
|
if (!ADBSHUTDOWN(view))
|
|
dns_adb_shutdown(view->adb);
|
|
if (!REQSHUTDOWN(view))
|
|
dns_requestmgr_shutdown(view->requestmgr);
|
|
if (flush)
|
|
dns_zt_flushanddetach(&view->zonetable);
|
|
else
|
|
dns_zt_detach(&view->zonetable);
|
|
done = all_done(view);
|
|
}
|
|
UNLOCK(&view->lock);
|
|
|
|
*viewp = NULL;
|
|
|
|
if (done)
|
|
destroy(view);
|
|
}
|
|
|
|
void
|
|
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);
|
|
}
|
|
|
|
static isc_result_t
|
|
dialup(dns_zone_t *zone, void *dummy) {
|
|
UNUSED(dummy);
|
|
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);
|
|
}
|
|
|
|
void
|
|
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);
|
|
}
|
|
|
|
static void
|
|
resolver_shutdown(isc_task_t *task, isc_event_t *event) {
|
|
dns_view_t *view = event->ev_arg;
|
|
isc_boolean_t done;
|
|
|
|
REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN);
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
REQUIRE(view->task == task);
|
|
|
|
UNUSED(task);
|
|
|
|
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) {
|
|
dns_view_t *view = event->ev_arg;
|
|
isc_boolean_t done;
|
|
|
|
REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN);
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
REQUIRE(view->task == task);
|
|
|
|
UNUSED(task);
|
|
|
|
LOCK(&view->lock);
|
|
|
|
view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN;
|
|
done = all_done(view);
|
|
|
|
UNLOCK(&view->lock);
|
|
|
|
isc_event_free(&event);
|
|
|
|
if (done)
|
|
destroy(view);
|
|
}
|
|
|
|
static void
|
|
req_shutdown(isc_task_t *task, isc_event_t *event) {
|
|
dns_view_t *view = event->ev_arg;
|
|
isc_boolean_t done;
|
|
|
|
REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN);
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
REQUIRE(view->task == task);
|
|
|
|
UNUSED(task);
|
|
|
|
LOCK(&view->lock);
|
|
|
|
view->attributes |= DNS_VIEWATTR_REQSHUTDOWN;
|
|
done = all_done(view);
|
|
|
|
UNLOCK(&view->lock);
|
|
|
|
isc_event_free(&event);
|
|
|
|
if (done)
|
|
destroy(view);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_view_createresolver(dns_view_t *view,
|
|
isc_taskmgr_t *taskmgr, unsigned int ntasks,
|
|
isc_socketmgr_t *socketmgr,
|
|
isc_timermgr_t *timermgr,
|
|
unsigned int options,
|
|
dns_dispatchmgr_t *dispatchmgr,
|
|
dns_dispatch_t *dispatchv4,
|
|
dns_dispatch_t *dispatchv6)
|
|
{
|
|
isc_result_t result;
|
|
isc_event_t *event;
|
|
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
REQUIRE(!view->frozen);
|
|
REQUIRE(view->resolver == NULL);
|
|
|
|
result = isc_task_create(taskmgr, 0, &view->task);
|
|
if (result != ISC_R_SUCCESS)
|
|
return (result);
|
|
isc_task_setname(view->task, "view", view);
|
|
|
|
result = dns_resolver_create(view, taskmgr, ntasks, socketmgr,
|
|
timermgr, options, dispatchmgr,
|
|
dispatchv4, dispatchv6,
|
|
&view->resolver);
|
|
if (result != ISC_R_SUCCESS) {
|
|
isc_task_detach(&view->task);
|
|
return (result);
|
|
}
|
|
event = &view->resevent;
|
|
dns_resolver_whenshutdown(view->resolver, view->task, &event);
|
|
view->attributes &= ~DNS_VIEWATTR_RESSHUTDOWN;
|
|
|
|
result = dns_adb_create(view->mctx, view, timermgr, taskmgr,
|
|
&view->adb);
|
|
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;
|
|
|
|
result = dns_requestmgr_create(view->mctx, timermgr, socketmgr,
|
|
dns_resolver_taskmgr(view->resolver),
|
|
dns_resolver_dispatchmgr(view->resolver),
|
|
dns_resolver_dispatchv4(view->resolver),
|
|
dns_resolver_dispatchv6(view->resolver),
|
|
&view->requestmgr);
|
|
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;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
}
|
|
|
|
void
|
|
dns_view_setcache(dns_view_t *view, dns_cache_t *cache) {
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
REQUIRE(!view->frozen);
|
|
|
|
if (view->cache != NULL) {
|
|
dns_db_detach(&view->cachedb);
|
|
dns_cache_detach(&view->cache);
|
|
}
|
|
dns_cache_attach(cache, &view->cache);
|
|
dns_cache_attachdb(cache, &view->cachedb);
|
|
INSIST(DNS_DB_VALID(view->cachedb));
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
void
|
|
dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
REQUIRE(ring != NULL);
|
|
if (view->statickeys != NULL)
|
|
dns_tsigkeyring_destroy(&view->statickeys);
|
|
view->statickeys = ring;
|
|
}
|
|
|
|
void
|
|
dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
view->dstport = dstport;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
|
|
isc_result_t result;
|
|
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
REQUIRE(!view->frozen);
|
|
|
|
result = dns_zt_mount(view->zonetable, zone);
|
|
|
|
return (result);
|
|
}
|
|
|
|
void
|
|
dns_view_freeze(dns_view_t *view) {
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
REQUIRE(!view->frozen);
|
|
|
|
if (view->resolver != NULL) {
|
|
INSIST(view->cachedb != NULL);
|
|
dns_resolver_freeze(view->resolver);
|
|
}
|
|
view->frozen = ISC_TRUE;
|
|
}
|
|
|
|
isc_result_t
|
|
dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) {
|
|
isc_result_t result;
|
|
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
|
|
result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
|
|
if (result == DNS_R_PARTIALMATCH) {
|
|
dns_zone_detach(zonep);
|
|
result = ISC_R_NOTFOUND;
|
|
}
|
|
|
|
return (result);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_view_find(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_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
|
|
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
|
|
{
|
|
isc_result_t result;
|
|
dns_db_t *db, *zdb;
|
|
dns_dbnode_t *node, *znode;
|
|
isc_boolean_t is_cache;
|
|
dns_rdataset_t zrdataset, zsigrdataset;
|
|
dns_zone_t *zone;
|
|
|
|
/*
|
|
* Find an rdataset whose owner name is 'name', and whose type is
|
|
* 'type'.
|
|
*/
|
|
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
REQUIRE(view->frozen);
|
|
REQUIRE(type != dns_rdatatype_sig);
|
|
REQUIRE(rdataset != NULL); /* XXXBEW - remove this */
|
|
|
|
/*
|
|
* Initialize.
|
|
*/
|
|
dns_rdataset_init(&zrdataset);
|
|
dns_rdataset_init(&zsigrdataset);
|
|
zdb = NULL;
|
|
znode = NULL;
|
|
|
|
/*
|
|
* Find a database to answer the query.
|
|
*/
|
|
zone = NULL;
|
|
db = NULL;
|
|
node = NULL;
|
|
result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
|
|
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
|
|
result = dns_zone_getdb(zone, &db);
|
|
if (result != ISC_R_SUCCESS && view->cachedb != NULL)
|
|
dns_db_attach(view->cachedb, &db);
|
|
else if (result != ISC_R_SUCCESS)
|
|
goto cleanup;
|
|
} else if (result == ISC_R_NOTFOUND && view->cachedb != NULL)
|
|
dns_db_attach(view->cachedb, &db);
|
|
else
|
|
goto cleanup;
|
|
|
|
is_cache = dns_db_iscache(db);
|
|
|
|
db_find:
|
|
/*
|
|
* Now look for an answer in the database.
|
|
*/
|
|
result = dns_db_find(db, name, NULL, type, options,
|
|
now, &node, foundname, rdataset, sigrdataset);
|
|
|
|
if (result == DNS_R_DELEGATION ||
|
|
result == ISC_R_NOTFOUND) {
|
|
if (dns_rdataset_isassociated(rdataset))
|
|
dns_rdataset_disassociate(rdataset);
|
|
if (sigrdataset != NULL &&
|
|
dns_rdataset_isassociated(sigrdataset))
|
|
dns_rdataset_disassociate(sigrdataset);
|
|
if (node != NULL)
|
|
dns_db_detachnode(db, &node);
|
|
if (!is_cache) {
|
|
dns_db_detach(&db);
|
|
if (view->cachedb != NULL) {
|
|
/*
|
|
* Either the answer is in the cache, or we
|
|
* don't know it.
|
|
*/
|
|
is_cache = ISC_TRUE;
|
|
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.
|
|
*/
|
|
if (dns_rdataset_isassociated(&zrdataset)) {
|
|
dns_rdataset_clone(&zrdataset, rdataset);
|
|
if (sigrdataset != NULL &&
|
|
dns_rdataset_isassociated(&zsigrdataset))
|
|
dns_rdataset_clone(&zsigrdataset,
|
|
sigrdataset);
|
|
result = DNS_R_GLUE;
|
|
if (db != NULL)
|
|
dns_db_detach(&db);
|
|
dns_db_attach(zdb, &db);
|
|
dns_db_attachnode(db, znode, &node);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
/*
|
|
* We don't know the answer.
|
|
*/
|
|
result = ISC_R_NOTFOUND;
|
|
} 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.
|
|
*/
|
|
is_cache = ISC_TRUE;
|
|
dns_rdataset_clone(rdataset, &zrdataset);
|
|
dns_rdataset_disassociate(rdataset);
|
|
if (sigrdataset != NULL &&
|
|
dns_rdataset_isassociated(sigrdataset)) {
|
|
dns_rdataset_clone(sigrdataset, &zsigrdataset);
|
|
dns_rdataset_disassociate(sigrdataset);
|
|
}
|
|
dns_db_attach(db, &zdb);
|
|
dns_db_attachnode(zdb, node, &znode);
|
|
dns_db_detachnode(db, &node);
|
|
dns_db_detach(&db);
|
|
dns_db_attach(view->cachedb, &db);
|
|
goto db_find;
|
|
}
|
|
/*
|
|
* Otherwise, the glue is the best answer.
|
|
*/
|
|
result = ISC_R_SUCCESS;
|
|
}
|
|
|
|
if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
|
|
if (dns_rdataset_isassociated(rdataset))
|
|
dns_rdataset_disassociate(rdataset);
|
|
if (sigrdataset != NULL &&
|
|
dns_rdataset_isassociated(sigrdataset))
|
|
dns_rdataset_disassociate(sigrdataset);
|
|
if (db != NULL) {
|
|
if (node != NULL)
|
|
dns_db_detachnode(db, &node);
|
|
dns_db_detach(&db);
|
|
}
|
|
result = dns_db_find(view->hints, name, NULL, type, options,
|
|
now, &node, foundname,
|
|
rdataset, sigrdataset);
|
|
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);
|
|
dns_db_attach(view->hints, &db);
|
|
result = DNS_R_HINT;
|
|
} else if (result == DNS_R_NXRRSET) {
|
|
dns_db_attach(view->hints, &db);
|
|
result = DNS_R_HINTNXRRSET;
|
|
} else if (result == DNS_R_NXDOMAIN)
|
|
result = ISC_R_NOTFOUND;
|
|
}
|
|
|
|
cleanup:
|
|
if (result == DNS_R_NXDOMAIN || result == DNS_R_NXRRSET) {
|
|
/*
|
|
* We don't care about any DNSSEC proof data in these cases.
|
|
*/
|
|
if (dns_rdataset_isassociated(rdataset))
|
|
dns_rdataset_disassociate(rdataset);
|
|
if (sigrdataset != NULL &&
|
|
dns_rdataset_isassociated(sigrdataset))
|
|
dns_rdataset_disassociate(sigrdataset);
|
|
}
|
|
|
|
if (dns_rdataset_isassociated(&zrdataset)) {
|
|
dns_rdataset_disassociate(&zrdataset);
|
|
if (dns_rdataset_isassociated(&zsigrdataset))
|
|
dns_rdataset_disassociate(&zsigrdataset);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
if (zone != NULL)
|
|
dns_zone_detach(&zone);
|
|
|
|
return (result);
|
|
}
|
|
|
|
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,
|
|
NULL, NULL, dns_fixedname_name(&foundname),
|
|
rdataset, sigrdataset);
|
|
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.
|
|
*/
|
|
if (dns_rdataset_isassociated(rdataset))
|
|
dns_rdataset_disassociate(rdataset);
|
|
if (sigrdataset != NULL &&
|
|
dns_rdataset_isassociated(sigrdataset))
|
|
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 &&
|
|
result != DNS_R_HINTNXRRSET &&
|
|
result != ISC_R_NOTFOUND) {
|
|
if (dns_rdataset_isassociated(rdataset))
|
|
dns_rdataset_disassociate(rdataset);
|
|
if (sigrdataset != NULL &&
|
|
dns_rdataset_isassociated(sigrdataset))
|
|
dns_rdataset_disassociate(sigrdataset);
|
|
result = ISC_R_NOTFOUND;
|
|
}
|
|
|
|
return (result);
|
|
}
|
|
|
|
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;
|
|
isc_boolean_t is_cache, use_zone, try_hints;
|
|
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.
|
|
*/
|
|
result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
|
|
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
|
|
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;
|
|
}
|
|
is_cache = dns_db_iscache(db);
|
|
|
|
db_find:
|
|
/*
|
|
* Look for the zonecut.
|
|
*/
|
|
if (!is_cache) {
|
|
result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options,
|
|
now, NULL, fname, rdataset, sigrdataset);
|
|
if (result == DNS_R_DELEGATION)
|
|
result = ISC_R_SUCCESS;
|
|
else if (result != ISC_R_SUCCESS)
|
|
goto cleanup;
|
|
if (view->cachedb != NULL && db != view->hints) {
|
|
/*
|
|
* We found an answer, but the cache may be better.
|
|
*/
|
|
zfname = dns_fixedname_name(&zfixedname);
|
|
result = dns_name_concatenate(fname, NULL, zfname,
|
|
NULL);
|
|
if (result != ISC_R_SUCCESS)
|
|
goto cleanup;
|
|
dns_rdataset_clone(rdataset, &zrdataset);
|
|
dns_rdataset_disassociate(rdataset);
|
|
if (sigrdataset != NULL &&
|
|
dns_rdataset_isassociated(sigrdataset)) {
|
|
dns_rdataset_clone(sigrdataset, &zsigrdataset);
|
|
dns_rdataset_disassociate(sigrdataset);
|
|
}
|
|
dns_db_detach(&db);
|
|
dns_db_attach(view->cachedb, &db);
|
|
is_cache = ISC_TRUE;
|
|
goto db_find;
|
|
}
|
|
} else {
|
|
result = dns_db_findzonecut(db, name, options, now, NULL,
|
|
fname, rdataset, sigrdataset);
|
|
if (result == ISC_R_SUCCESS) {
|
|
if (zfname != NULL &&
|
|
!dns_name_issubdomain(fname, zfname)) {
|
|
/*
|
|
* We found a zonecut in the cache, but our
|
|
* zone delegation is better.
|
|
*/
|
|
use_zone = ISC_TRUE;
|
|
}
|
|
} else if (result == ISC_R_NOTFOUND) {
|
|
if (zfname != NULL) {
|
|
/*
|
|
* We didn't find anything in the cache, but we
|
|
* have a zone delegation, so use it.
|
|
*/
|
|
use_zone = ISC_TRUE;
|
|
} else {
|
|
/*
|
|
* Maybe we have hints...
|
|
*/
|
|
try_hints = ISC_TRUE;
|
|
}
|
|
} else {
|
|
/*
|
|
* Something bad happened.
|
|
*/
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
finish:
|
|
if (use_zone) {
|
|
if (dns_rdataset_isassociated(rdataset)) {
|
|
dns_rdataset_disassociate(rdataset);
|
|
if (sigrdataset != NULL &&
|
|
dns_rdataset_isassociated(sigrdataset))
|
|
dns_rdataset_disassociate(sigrdataset);
|
|
}
|
|
result = dns_name_concatenate(zfname, NULL, fname, NULL);
|
|
if (result != ISC_R_SUCCESS)
|
|
goto cleanup;
|
|
dns_rdataset_clone(&zrdataset, rdataset);
|
|
if (sigrdataset != NULL &&
|
|
dns_rdataset_isassociated(&zrdataset))
|
|
dns_rdataset_clone(&zsigrdataset, sigrdataset);
|
|
} else if (try_hints && use_hints && view->hints != NULL) {
|
|
/*
|
|
* We've found nothing so far, but we have hints.
|
|
*/
|
|
result = dns_db_find(view->hints, dns_rootname, NULL,
|
|
dns_rdatatype_ns, 0, now, NULL, fname,
|
|
rdataset, NULL);
|
|
if (result != ISC_R_SUCCESS) {
|
|
/*
|
|
* We can't even find the hints for the root
|
|
* nameservers!
|
|
*/
|
|
result = ISC_R_NOTFOUND;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
if (dns_rdataset_isassociated(&zrdataset)) {
|
|
dns_rdataset_disassociate(&zrdataset);
|
|
if (dns_rdataset_isassociated(&zsigrdataset))
|
|
dns_rdataset_disassociate(&zsigrdataset);
|
|
}
|
|
if (db != NULL)
|
|
dns_db_detach(&db);
|
|
if (zone != NULL)
|
|
dns_zone_detach(&zone);
|
|
|
|
return (result);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_viewlist_find(dns_viewlist_t *list, const char *name,
|
|
dns_rdataclass_t rdclass, dns_view_t **viewp)
|
|
{
|
|
dns_view_t *view;
|
|
|
|
REQUIRE(list != NULL);
|
|
|
|
for (view = ISC_LIST_HEAD(*list);
|
|
view != NULL;
|
|
view = ISC_LIST_NEXT(view, link)) {
|
|
if (strcmp(view->name, name) == 0 && view->rdclass == rdclass)
|
|
break;
|
|
}
|
|
if (view == NULL)
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
dns_view_attach(view, viewp);
|
|
|
|
return (ISC_R_SUCCESS);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_view_load(dns_view_t *view, isc_boolean_t stop) {
|
|
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
|
|
return (dns_zt_load(view->zonetable, stop));
|
|
}
|
|
|
|
isc_result_t
|
|
dns_view_gettsig(dns_view_t *view, dns_name_t *keyname, dns_tsigkey_t **keyp)
|
|
{
|
|
isc_result_t result;
|
|
REQUIRE(keyp != NULL && *keyp == NULL);
|
|
|
|
result = dns_tsigkey_find(keyp, keyname, NULL,
|
|
view->statickeys);
|
|
if (result == ISC_R_NOTFOUND)
|
|
result = dns_tsigkey_find(keyp, keyname, NULL,
|
|
view->dynamickeys);
|
|
return (result);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr,
|
|
dns_tsigkey_t **keyp)
|
|
{
|
|
isc_result_t result;
|
|
dns_name_t *keyname = NULL;
|
|
dns_peer_t *peer = NULL;
|
|
|
|
result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer);
|
|
if (result != ISC_R_SUCCESS)
|
|
return (result);
|
|
|
|
result = dns_peer_getkey(peer, &keyname);
|
|
if (result != ISC_R_SUCCESS)
|
|
return (result);
|
|
|
|
return (dns_view_gettsig(view, keyname, keyp));
|
|
}
|
|
|
|
isc_result_t
|
|
dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
REQUIRE(source != NULL);
|
|
|
|
return (dns_tsig_verify(source, msg, view->statickeys,
|
|
view->dynamickeys));
|
|
}
|
|
|
|
isc_result_t
|
|
dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
|
|
isc_result_t result;
|
|
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
|
|
|
(void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name);
|
|
result = dns_master_dumptostream(view->mctx, view->cachedb, NULL,
|
|
&dns_master_style_cache, fp);
|
|
if (result != ISC_R_SUCCESS)
|
|
return (result);
|
|
#ifdef notyet /* clean up adb dump format first */
|
|
dns_adb_dump(view->adb, fp);
|
|
#endif
|
|
return (ISC_R_SUCCESS);
|
|
}
|