📄 view.c
字号:
/* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 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 ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC 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.103.2.5.2.14 2004/03/10 02:55:58 marka Exp $ */#include <config.h>#include <isc/hash.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/order.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)#define DNS_VIEW_DELONLYHASH 111static 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_tdns_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; } 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_mutex; } 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->requestmgr = NULL; view->mctx = mctx; view->rdclass = rdclass; view->frozen = ISC_FALSE; view->task = NULL; isc_refcount_init(&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; view->matchdestinations = NULL; view->matchrecursiveonly = ISC_FALSE; result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys); if (result != ISC_R_SUCCESS) goto cleanup_fwdtable; view->peers = NULL; view->order = NULL; view->delonly = NULL; view->rootdelonly = ISC_FALSE; view->rootexclude = 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->enablednssec = ISC_TRUE; view->minimalresponses = ISC_FALSE; view->transfer_format = dns_one_answer; view->queryacl = NULL; view->recursionacl = NULL; view->sortlist = NULL; view->requestixfr = ISC_TRUE; view->provideixfr = ISC_TRUE; view->maxcachettl = 7 * 24 * 3600; view->maxncachettl = 3 * 3600; view->dstport = 53; view->preferred_glue = 0; view->flush = ISC_FALSE; view->dlv = NULL; dns_fixedname_init(&view->dlv_fixed); result = dns_order_create(view->mctx, &view->order); if (result != ISC_R_SUCCESS) goto cleanup_dynkeys; result = dns_peerlist_new(view->mctx, &view->peers); if (result != ISC_R_SUCCESS) goto cleanup_order; result = dns_aclenv_init(view->mctx, &view->aclenv); if (result != ISC_R_SUCCESS) goto cleanup_peerlist; 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_peerlist: dns_peerlist_detach(&view->peers); cleanup_order: dns_order_detach(&view->order); 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_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 voiddestroy(dns_view_t *view) { REQUIRE(!ISC_LINK_LINKED(view, link)); REQUIRE(isc_refcount_current(&view->references) == 0); REQUIRE(view->weakrefs == 0); REQUIRE(RESSHUTDOWN(view)); REQUIRE(ADBSHUTDOWN(view)); REQUIRE(REQSHUTDOWN(view)); if (view->order != NULL) dns_order_detach(&view->order); 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->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->matchdestinations != NULL) dns_acl_detach(&view->matchdestinations); if (view->queryacl != NULL) dns_acl_detach(&view->queryacl); if (view->recursionacl != NULL) dns_acl_detach(&view->recursionacl); if (view->sortlist != NULL) dns_acl_detach(&view->sortlist); if (view->delonly != NULL) { dns_name_t *name; int i; for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) { name = ISC_LIST_HEAD(view->delonly[i]); while (name != NULL) { ISC_LIST_UNLINK(view->delonly[i], name, link); dns_name_free(name, view->mctx); isc_mem_put(view->mctx, name, sizeof(*name)); name = ISC_LIST_HEAD(view->delonly[i]); } } isc_mem_put(view->mctx, view->delonly, sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH); view->delonly = NULL; } if (view->rootexclude != NULL) { dns_name_t *name; int i; for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) { name = ISC_LIST_HEAD(view->rootexclude[i]); while (name != NULL) { ISC_LIST_UNLINK(view->rootexclude[i], name, link); dns_name_free(name, view->mctx); isc_mem_put(view->mctx, name, sizeof(*name)); name = ISC_LIST_HEAD(view->rootexclude[i]); } } isc_mem_put(view->mctx, view->rootexclude, sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH); view->rootexclude = NULL; } dns_keytable_detach(&view->trustedkeys); dns_keytable_detach(&view->secroots); dns_fwdtable_destroy(&view->fwdtable); dns_aclenv_destroy(&view->aclenv); DESTROYLOCK(&view->lock); isc_refcount_destroy(&view->references); 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_tall_done(dns_view_t *view) { if (isc_refcount_current(&view->references) == 0 && view->weakrefs == 0 && RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view)) return (ISC_TRUE); return (ISC_FALSE);}voiddns_view_attach(dns_view_t *source, dns_view_t **targetp) { REQUIRE(DNS_VIEW_VALID(source)); REQUIRE(targetp != NULL && *targetp == NULL); isc_refcount_increment(&source->references, NULL); *targetp = source;}static voidview_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) { dns_view_t *view; unsigned int refs; isc_boolean_t done = ISC_FALSE; REQUIRE(viewp != NULL); view = *viewp; REQUIRE(DNS_VIEW_VALID(view)); if (flush) view->flush = ISC_TRUE; isc_refcount_decrement(&view->references, &refs); if (refs == 0) { LOCK(&view->lock); 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 (view->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);}voiddns_view_flushanddetach(dns_view_t **viewp) { view_flushanddetach(viewp, ISC_TRUE);}voiddns_view_detach(dns_view_t **viewp) { view_flushanddetach(viewp, ISC_FALSE);}static isc_result_tdialup(dns_zone_t *zone, void *dummy) { UNUSED(dummy); dns_zone_dialup(zone); return (ISC_R_SUCCESS);}voiddns_view_dialup(dns_view_t *view) { REQUIRE(DNS_VIEW_VALID(view)); (void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL);}voiddns_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;}voiddns_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 voidresolver_shutdown(isc_task_t *task, isc_event_t *event) { dns_view_t *view = event->ev_arg; isc_boolean_t done;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -