📄 sdlz.c
字号:
/* * Portions Copyright (C) 2005-2007 Internet Systems Consortium, Inc. ("ISC") * Portions 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 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. *//* * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl. * * 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 STICHTING NLNET * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * STICHTING NLNET 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. * * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was * conceived and contributed by Rob Butler. * * 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 ROB BUTLER * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * ROB BUTLER 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: sdlz.c,v 1.2.2.9 2007/02/14 23:45:43 marka Exp $ *//*! \file */#include <config.h>#include <string.h>#include <isc/buffer.h>#include <isc/lex.h>#include <isc/log.h>#include <isc/rwlock.h>#include <isc/string.h>#include <isc/util.h>#include <isc/magic.h>#include <isc/mem.h>#include <isc/once.h>#include <isc/print.h>#include <isc/region.h>#include <dns/callbacks.h>#include <dns/db.h>#include <dns/dbiterator.h>#include <dns/dlz.h>#include <dns/fixedname.h>#include <dns/log.h>#include <dns/rdata.h>#include <dns/rdatalist.h>#include <dns/rdataset.h>#include <dns/rdatasetiter.h>#include <dns/rdatatype.h>#include <dns/result.h>#include <dns/master.h>#include <dns/sdlz.h>#include <dns/types.h>#include "rdatalist_p.h"/* * Private Types */struct dns_sdlzimplementation { const dns_sdlzmethods_t *methods; isc_mem_t *mctx; void *driverarg; unsigned int flags; isc_mutex_t driverlock; dns_dlzimplementation_t *dlz_imp;};struct dns_sdlz_db { /* Unlocked */ dns_db_t common; void *dbdata; dns_sdlzimplementation_t *dlzimp; isc_mutex_t refcnt_lock; /* Locked */ unsigned int references;};struct dns_sdlzlookup { /* Unlocked */ unsigned int magic; dns_sdlz_db_t *sdlz; ISC_LIST(dns_rdatalist_t) lists; ISC_LIST(isc_buffer_t) buffers; dns_name_t *name; ISC_LINK(dns_sdlzlookup_t) link; isc_mutex_t lock; dns_rdatacallbacks_t callbacks; /* Locked */ unsigned int references;};typedef struct dns_sdlzlookup dns_sdlznode_t;struct dns_sdlzallnodes { dns_dbiterator_t common; ISC_LIST(dns_sdlznode_t) nodelist; dns_sdlznode_t *current; dns_sdlznode_t *origin;};typedef dns_sdlzallnodes_t sdlz_dbiterator_t;typedef struct sdlz_rdatasetiter { dns_rdatasetiter_t common; dns_rdatalist_t *current;} sdlz_rdatasetiter_t;#define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S')/* * Note that "impmagic" is not the first four bytes of the struct, so * ISC_MAGIC_VALID cannot be used. */#define VALID_SDLZDB(sdlzdb) ((sdlzdb) != NULL && \ (sdlzdb)->common.impmagic == SDLZDB_MAGIC)#define SDLZLOOKUP_MAGIC ISC_MAGIC('D','L','Z','L')#define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)#define VALID_SDLZNODE(sdlzn) VALID_SDLZLOOKUP(sdlzn)/* These values are taken from RFC 1537 */#define SDLZ_DEFAULT_REFRESH (60 * 60 * 8)#define SDLZ_DEFAULT_RETRY (60 * 60 * 2)#define SDLZ_DEFAULT_EXPIRE (60 * 60 * 24 * 7)#define SDLZ_DEFAULT_MINIMUM (60 * 60 * 24)/* This is a reasonable value */#define SDLZ_DEFAULT_TTL (60 * 60 * 24)static int dummy;#define MAYBE_LOCK(imp) \ do { \ unsigned int flags = imp->flags; \ if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \ LOCK(&imp->driverlock); \ } while (0)#define MAYBE_UNLOCK(imp) \ do { \ unsigned int flags = imp->flags; \ if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \ UNLOCK(&imp->driverlock); \ } while (0)/* * Forward references. Try to keep these to a minimum. */static void list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node, dns_rdataset_t *rdataset);static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);static void dbiterator_destroy(dns_dbiterator_t **iteratorp);static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name);static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);static isc_result_t dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, dns_name_t *name);static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);static dns_dbiteratormethods_t dbiterator_methods = { dbiterator_destroy, dbiterator_first, dbiterator_last, dbiterator_seek, dbiterator_prev, dbiterator_next, dbiterator_current, dbiterator_pause, dbiterator_origin};/* * Utility functions *//*% Converts the input string to lowercase, in place. */static voiddns_sdlz_tolower(char *str) { unsigned int len = strlen(str); unsigned int i; for (i = 0; i < len; i++) { if (str[i] >= 'A' && str[i] <= 'Z') str[i] += 32; }}static inline unsigned intinitial_size(const char *data) { unsigned int len = (strlen(data) / 64) + 1; return (len * 64 + 64);}/* * Rdataset Iterator Methods. These methods were "borrowed" from the SDB * driver interface. See the SDB driver interface documentation for more info. */static voidrdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)(*iteratorp); detachnode(sdlziterator->common.db, &sdlziterator->common.node); isc_mem_put(sdlziterator->common.db->mctx, sdlziterator, sizeof(sdlz_rdatasetiter_t)); *iteratorp = NULL;}static isc_result_trdatasetiter_first(dns_rdatasetiter_t *iterator) { sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator; dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node; if (ISC_LIST_EMPTY(sdlznode->lists)) return (ISC_R_NOMORE); sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists); return (ISC_R_SUCCESS);}static isc_result_trdatasetiter_next(dns_rdatasetiter_t *iterator) { sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator; sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link); if (sdlziterator->current == NULL) return (ISC_R_NOMORE); else return (ISC_R_SUCCESS);}static voidrdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) { sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator; list_tordataset(sdlziterator->current, iterator->db, iterator->node, rdataset);}static dns_rdatasetitermethods_t rdatasetiter_methods = { rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next, rdatasetiter_current};/* * DB routines. These methods were "borrowed" from the SDB driver interface. * See the SDB driver interface documentation for more info. */static voidattach(dns_db_t *source, dns_db_t **targetp) { dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) source; REQUIRE(VALID_SDLZDB(sdlz)); LOCK(&sdlz->refcnt_lock); REQUIRE(sdlz->references > 0); sdlz->references++; UNLOCK(&sdlz->refcnt_lock); *targetp = source;}static voiddestroy(dns_sdlz_db_t *sdlz) { isc_mem_t *mctx; mctx = sdlz->common.mctx; sdlz->common.magic = 0; sdlz->common.impmagic = 0; isc_mutex_destroy(&sdlz->refcnt_lock); dns_name_free(&sdlz->common.origin, mctx); isc_mem_put(mctx, sdlz, sizeof(dns_sdlz_db_t)); isc_mem_detach(&mctx);}static voiddetach(dns_db_t **dbp) { dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp); isc_boolean_t need_destroy = ISC_FALSE; REQUIRE(VALID_SDLZDB(sdlz)); LOCK(&sdlz->refcnt_lock); REQUIRE(sdlz->references > 0); sdlz->references--; if (sdlz->references == 0) need_destroy = ISC_TRUE; UNLOCK(&sdlz->refcnt_lock); if (need_destroy) destroy(sdlz); *dbp = NULL;}static isc_result_tbeginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) { UNUSED(db); UNUSED(addp); UNUSED(dbloadp); return (ISC_R_NOTIMPLEMENTED);}static isc_result_tendload(dns_db_t *db, dns_dbload_t **dbloadp) { UNUSED(db); UNUSED(dbloadp); return (ISC_R_NOTIMPLEMENTED);}static isc_result_tdump(dns_db_t *db, dns_dbversion_t *version, const char *filename, dns_masterformat_t masterformat){ UNUSED(db); UNUSED(version); UNUSED(filename); UNUSED(masterformat); return (ISC_R_NOTIMPLEMENTED);}static voidcurrentversion(dns_db_t *db, dns_dbversion_t **versionp) { REQUIRE(versionp != NULL && *versionp == NULL); UNUSED(db); *versionp = (void *) &dummy; return;}static isc_result_tnewversion(dns_db_t *db, dns_dbversion_t **versionp) { UNUSED(db); UNUSED(versionp); return (ISC_R_NOTIMPLEMENTED);}static voidattachversion(dns_db_t *db, dns_dbversion_t *source, dns_dbversion_t **targetp){ REQUIRE(source != NULL && source == (void *) &dummy); UNUSED(db); UNUSED(source); UNUSED(targetp); *targetp = source;}static voidcloseversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { REQUIRE(versionp != NULL && *versionp == (void *) &dummy); REQUIRE(commit == ISC_FALSE); UNUSED(db); UNUSED(commit); *versionp = NULL;}static isc_result_tcreatenode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) { dns_sdlznode_t *node; isc_result_t result; node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t)); if (node == NULL) return (ISC_R_NOMEMORY); node->sdlz = NULL; attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz); ISC_LIST_INIT(node->lists); ISC_LIST_INIT(node->buffers); ISC_LINK_INIT(node, link); node->name = NULL; result = isc_mutex_init(&node->lock); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_mutex_init() failed: %s", isc_result_totext(result)); isc_mem_put(sdlz->common.mctx, node, sizeof(dns_sdlznode_t)); return (ISC_R_UNEXPECTED); } dns_rdatacallbacks_init(&node->callbacks); node->references = 1; node->magic = SDLZLOOKUP_MAGIC; *nodep = node; return (ISC_R_SUCCESS);}static voiddestroynode(dns_sdlznode_t *node) { dns_rdatalist_t *list; dns_rdata_t *rdata; isc_buffer_t *b; dns_sdlz_db_t *sdlz; dns_db_t *db; isc_mem_t *mctx; sdlz = node->sdlz; mctx = sdlz->common.mctx; while (!ISC_LIST_EMPTY(node->lists)) { list = ISC_LIST_HEAD(node->lists); while (!ISC_LIST_EMPTY(list->rdata)) { rdata = ISC_LIST_HEAD(list->rdata); ISC_LIST_UNLINK(list->rdata, rdata, link); isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); } ISC_LIST_UNLINK(node->lists, list, link); isc_mem_put(mctx, list, sizeof(dns_rdatalist_t)); } while (!ISC_LIST_EMPTY(node->buffers)) { b = ISC_LIST_HEAD(node->buffers); ISC_LIST_UNLINK(node->buffers, b, link); isc_buffer_free(&b); } if (node->name != NULL) { dns_name_free(node->name, mctx); isc_mem_put(mctx, node->name, sizeof(dns_name_t)); } DESTROYLOCK(&node->lock); node->magic = 0; isc_mem_put(mctx, node, sizeof(dns_sdlznode_t)); db = &sdlz->common; detach(&db);}static isc_result_tfindnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, dns_dbnode_t **nodep){ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; dns_sdlznode_t *node = NULL; isc_result_t result; isc_buffer_t b; char namestr[DNS_NAME_MAXTEXT + 1]; isc_buffer_t b2; char zonestr[DNS_NAME_MAXTEXT + 1]; isc_boolean_t isorigin; dns_sdlzauthorityfunc_t authority; REQUIRE(VALID_SDLZDB(sdlz)); REQUIRE(create == ISC_FALSE); REQUIRE(nodep != NULL && *nodep == NULL); UNUSED(name); UNUSED(create); isc_buffer_init(&b, namestr, sizeof(namestr)); if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) { dns_name_t relname; unsigned int labels; labels = dns_name_countlabels(name) - dns_name_countlabels(&db->origin); dns_name_init(&relname, NULL); dns_name_getlabelsequence(name, 0, labels, &relname); result = dns_name_totext(&relname, ISC_TRUE, &b); if (result != ISC_R_SUCCESS) return (result); } else { result = dns_name_totext(name, ISC_TRUE, &b); if (result != ISC_R_SUCCESS) return (result); } isc_buffer_putuint8(&b, 0); isc_buffer_init(&b2, zonestr, sizeof(zonestr)); result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b2); if (result != ISC_R_SUCCESS) return (result); isc_buffer_putuint8(&b2, 0); result = createnode(sdlz, &node); if (result != ISC_R_SUCCESS) return (result); isorigin = dns_name_equal(name, &sdlz->common.origin); /* make sure strings are always lowercase */ dns_sdlz_tolower(zonestr); dns_sdlz_tolower(namestr); MAYBE_LOCK(sdlz->dlzimp); /* try to lookup the host (namestr) */ result = sdlz->dlzimp->methods->lookup(zonestr, namestr, sdlz->dlzimp->driverarg, sdlz->dbdata, node); /* * if the host (namestr) was not found, try to lookup a * "wildcard" host. */ if (result != ISC_R_SUCCESS) { result = sdlz->dlzimp->methods->lookup(zonestr, "*", sdlz->dlzimp->driverarg, sdlz->dbdata, node); } MAYBE_UNLOCK(sdlz->dlzimp); if (result != ISC_R_SUCCESS && !isorigin) { destroynode(node); return (result); } if (isorigin && sdlz->dlzimp->methods->authority != NULL) { MAYBE_LOCK(sdlz->dlzimp); authority = sdlz->dlzimp->methods->authority; result = (*authority)(zonestr, sdlz->dlzimp->driverarg, sdlz->dbdata, node); MAYBE_UNLOCK(sdlz->dlzimp); if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) { destroynode(node); return (result); } } *nodep = node; return (ISC_R_SUCCESS);}static isc_result_tfindzonecut(dns_db_t *db, dns_name_t *name, unsigned int options, isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset){ UNUSED(db); UNUSED(name); UNUSED(options); UNUSED(now);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -