📄 sdb.c
字号:
/* * Copyright (C) 2000, 2001, 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 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: sdb.c,v 1.35.2.2 2003/10/09 07:32:38 marka Exp $ */#include <config.h>#include <string.h>#include <isc/buffer.h>#include <isc/lex.h>#include <isc/log.h>#include <isc/magic.h>#include <isc/mem.h>#include <isc/once.h>#include <isc/print.h>#include <isc/region.h>#include <isc/util.h>#include <dns/callbacks.h>#include <dns/db.h>#include <dns/dbiterator.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/sdb.h>#include <dns/types.h>#include "rdatalist_p.h"struct dns_sdbimplementation { const dns_sdbmethods_t *methods; void *driverdata; unsigned int flags; isc_mem_t *mctx; isc_mutex_t driverlock; dns_dbimplementation_t *dbimp;};struct dns_sdb { /* Unlocked */ dns_db_t common; char *zone; dns_sdbimplementation_t *implementation; void *dbdata; isc_mutex_t lock; /* Locked */ unsigned int references;};struct dns_sdblookup { /* Unlocked */ unsigned int magic; dns_sdb_t *sdb; ISC_LIST(dns_rdatalist_t) lists; ISC_LIST(isc_buffer_t) buffers; dns_name_t *name; ISC_LINK(dns_sdblookup_t) link; isc_mutex_t lock; dns_rdatacallbacks_t callbacks; /* Locked */ unsigned int references;};typedef struct dns_sdblookup dns_sdbnode_t;struct dns_sdballnodes { dns_dbiterator_t common; ISC_LIST(dns_sdbnode_t) nodelist; dns_sdbnode_t *current; dns_sdbnode_t *origin;};typedef dns_sdballnodes_t sdb_dbiterator_t;typedef struct sdb_rdatasetiter { dns_rdatasetiter_t common; dns_rdatalist_t *current;} sdb_rdatasetiter_t;#define SDB_MAGIC ISC_MAGIC('S', 'D', 'B', '-')/* * Note that "impmagic" is not the first four bytes of the struct, so * ISC_MAGIC_VALID cannot be used. */#define VALID_SDB(sdb) ((sdb) != NULL && \ (sdb)->common.impmagic == SDB_MAGIC)#define SDBLOOKUP_MAGIC ISC_MAGIC('S','D','B','L')#define VALID_SDBLOOKUP(sdbl) ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)#define VALID_SDBNODE(sdbn) VALID_SDBLOOKUP(sdbn)/* These values are taken from RFC 1537 */#define SDB_DEFAULT_REFRESH (60 * 60 * 8)#define SDB_DEFAULT_RETRY (60 * 60 * 2)#define SDB_DEFAULT_EXPIRE (60 * 60 * 24 * 7)#define SDB_DEFAULT_MINIMUM (60 * 60 * 24)/* This is a reasonable value */#define SDB_DEFAULT_TTL (60 * 60 * 24)#define MAYBE_LOCK(sdb) \ do { \ unsigned int flags = sdb->implementation->flags; \ if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \ LOCK(&sdb->implementation->driverlock); \ } while (0)#define MAYBE_UNLOCK(sdb) \ do { \ unsigned int flags = sdb->implementation->flags; \ if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \ UNLOCK(&sdb->implementation->driverlock); \ } while (0)static int dummy;static isc_result_t dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type, dns_rdataclass_t rdclass, unsigned int argc, char *argv[], void *driverarg, dns_db_t **dbp);static isc_result_t findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);static isc_result_t createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep);static void destroynode(dns_sdbnode_t *node);static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);static void list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node, dns_rdataset_t *rdataset);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};static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator);static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator);static void rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset);static dns_rdatasetitermethods_t rdatasetiter_methods = { rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next, rdatasetiter_current};/* * Functions used by implementors of simple databases */isc_result_tdns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods, void *driverdata, unsigned int flags, isc_mem_t *mctx, dns_sdbimplementation_t **sdbimp){ dns_sdbimplementation_t *imp; isc_result_t result; REQUIRE(drivername != NULL); REQUIRE(methods != NULL); REQUIRE(methods->lookup != NULL); REQUIRE(mctx != NULL); REQUIRE(sdbimp != NULL && *sdbimp == NULL); REQUIRE((flags & ~(DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA | DNS_SDBFLAG_THREADSAFE)) == 0); imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t)); if (imp == NULL) return (ISC_R_NOMEMORY); imp->methods = methods; imp->driverdata = driverdata; imp->flags = flags; imp->mctx = NULL; isc_mem_attach(mctx, &imp->mctx); result = isc_mutex_init(&imp->driverlock); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_mutex_init() failed: %s", isc_result_totext(result)); goto cleanup_mctx; } imp->dbimp = NULL; result = dns_db_register(drivername, dns_sdb_create, imp, mctx, &imp->dbimp); if (result != ISC_R_SUCCESS) goto cleanup_mutex; *sdbimp = imp; return (ISC_R_SUCCESS); cleanup_mutex: DESTROYLOCK(&imp->driverlock); cleanup_mctx: isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t)); return (result);}voiddns_sdb_unregister(dns_sdbimplementation_t **sdbimp) { dns_sdbimplementation_t *imp; isc_mem_t *mctx; REQUIRE(sdbimp != NULL && *sdbimp != NULL); imp = *sdbimp; dns_db_unregister(&imp->dbimp); DESTROYLOCK(&imp->driverlock); mctx = imp->mctx; isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t)); isc_mem_detach(&mctx); *sdbimp = NULL;}static inline unsigned intinitial_size(const char *data) { unsigned int len = strlen(data); unsigned int size; for (size = 64; size < (64 * 1024); size *= 2) if (len < size) return (size); return (64 * 1024);}isc_result_tdns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl, const char *data){ dns_rdatalist_t *rdatalist; dns_rdata_t *rdata; dns_rdatatype_t typeval; isc_consttextregion_t r; isc_buffer_t b; isc_buffer_t *rdatabuf; isc_lex_t *lex; isc_result_t result; unsigned int size; isc_mem_t *mctx; dns_sdbimplementation_t *imp; dns_name_t *origin; REQUIRE(VALID_SDBLOOKUP(lookup)); REQUIRE(type != NULL); REQUIRE(data != NULL); mctx = lookup->sdb->common.mctx; r.base = type; r.length = strlen(type); result = dns_rdatatype_fromtext(&typeval, (isc_textregion_t *)&r); if (result != ISC_R_SUCCESS) return (result); rdatalist = ISC_LIST_HEAD(lookup->lists); while (rdatalist != NULL) { if (rdatalist->type == typeval) break; rdatalist = ISC_LIST_NEXT(rdatalist, link); } if (rdatalist == NULL) { rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t)); if (rdatalist == NULL) return (ISC_R_NOMEMORY); rdatalist->rdclass = lookup->sdb->common.rdclass; rdatalist->type = typeval; rdatalist->covers = 0; rdatalist->ttl = ttl; ISC_LIST_INIT(rdatalist->rdata); ISC_LINK_INIT(rdatalist, link); ISC_LIST_APPEND(lookup->lists, rdatalist, link); } else if (rdatalist->ttl != ttl) return (DNS_R_BADTTL); rdata = isc_mem_get(mctx, sizeof(dns_rdata_t)); if (rdata == NULL) return (ISC_R_NOMEMORY); dns_rdata_init(rdata); imp = lookup->sdb->implementation; if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0) origin = &lookup->sdb->common.origin; else origin = dns_rootname; lex = NULL; result = isc_lex_create(mctx, 64, &lex); if (result != ISC_R_SUCCESS) goto failure; size = initial_size(data); do { isc_buffer_init(&b, data, strlen(data)); isc_buffer_add(&b, strlen(data)); result = isc_lex_openbuffer(lex, &b); if (result != ISC_R_SUCCESS) goto failure; rdatabuf = NULL; result = isc_buffer_allocate(mctx, &rdatabuf, size); if (result != ISC_R_SUCCESS) goto failure; result = dns_rdata_fromtext(rdata, rdatalist->rdclass, rdatalist->type, lex, origin, ISC_FALSE, mctx, rdatabuf, &lookup->callbacks); if (result != ISC_R_SUCCESS) isc_buffer_free(&rdatabuf); size *= 2; } while (result == ISC_R_NOSPACE); if (result != ISC_R_SUCCESS) goto failure; ISC_LIST_APPEND(rdatalist->rdata, rdata, link); ISC_LIST_APPEND(lookup->buffers, rdatabuf, link); if (lex != NULL) isc_lex_destroy(&lex); return (ISC_R_SUCCESS); failure: if (rdatabuf != NULL) isc_buffer_free(&rdatabuf); if (lex != NULL) isc_lex_destroy(&lex); isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); return (result);}isc_result_tdns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name, const char *type, dns_ttl_t ttl, const char *data){ dns_name_t *newname, *origin; dns_fixedname_t fnewname; dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db; dns_sdbimplementation_t *imp = sdb->implementation; dns_sdbnode_t *sdbnode; isc_mem_t *mctx = sdb->common.mctx; isc_buffer_t b; isc_result_t result; dns_fixedname_init(&fnewname); newname = dns_fixedname_name(&fnewname); if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0) origin = &sdb->common.origin; else origin = dns_rootname; isc_buffer_init(&b, name, strlen(name)); isc_buffer_add(&b, strlen(name)); result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL); if (result != ISC_R_SUCCESS) return (result); if (allnodes->common.relative_names) { /* All names are relative to the root */ unsigned int nlabels = dns_name_countlabels(newname); dns_name_getlabelsequence(newname, 0, nlabels - 1, newname); } sdbnode = ISC_LIST_HEAD(allnodes->nodelist); if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) { sdbnode = NULL; result = createnode(sdb, &sdbnode); if (result != ISC_R_SUCCESS) return (result); sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t)); if (sdbnode->name == NULL) { destroynode(sdbnode); return (ISC_R_NOMEMORY); } dns_name_init(sdbnode->name, NULL); result = dns_name_dup(newname, mctx, sdbnode->name); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, sdbnode->name, sizeof(dns_name_t)); destroynode(sdbnode); return (result); } ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link); if (allnodes->origin == NULL && dns_name_equal(newname, &sdb->common.origin)) allnodes->origin = sdbnode; } return (dns_sdb_putrr(sdbnode, type, ttl, data));}isc_result_tdns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname, isc_uint32_t serial){ char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7]; int n; REQUIRE(mname != NULL); REQUIRE(rname != NULL); n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", mname, rname, serial, SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY, SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM); if (n >= (int)sizeof(str) || n < 0) return (ISC_R_NOSPACE); return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));}/* * DB routines */static voidattach(dns_db_t *source, dns_db_t **targetp) { dns_sdb_t *sdb = (dns_sdb_t *) source; REQUIRE(VALID_SDB(sdb)); LOCK(&sdb->lock); REQUIRE(sdb->references > 0); sdb->references++; UNLOCK(&sdb->lock); *targetp = source;}static void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -