sdb.c revision 135446
1139749Simp/* 2119853Scg * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") 355639Scg * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. 455639Scg * 555639Scg * Permission to use, copy, modify, and distribute this software for any 655639Scg * purpose with or without fee is hereby granted, provided that the above 755639Scg * copyright notice and this permission notice appear in all copies. 855639Scg * 955639Scg * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 1055639Scg * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1155639Scg * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 1255639Scg * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 1355639Scg * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 1455639Scg * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 1555639Scg * PERFORMANCE OF THIS SOFTWARE. 1655639Scg */ 1755639Scg 1855639Scg/* $Id: sdb.c,v 1.35.12.8 2004/07/22 04:01:58 marka Exp $ */ 1955639Scg 2055639Scg#include <config.h> 2155639Scg 2255639Scg#include <string.h> 2355639Scg 2455639Scg#include <isc/buffer.h> 2555639Scg#include <isc/lex.h> 2655639Scg#include <isc/log.h> 2755639Scg#include <isc/magic.h> 2855639Scg#include <isc/mem.h> 29193640Sariff#include <isc/once.h> 30193640Sariff#include <isc/print.h> 31193640Sariff#include <isc/region.h> 32193640Sariff#include <isc/util.h> 3355639Scg 3455639Scg#include <dns/callbacks.h> 3555639Scg#include <dns/db.h> 3655639Scg#include <dns/dbiterator.h> 3755639Scg#include <dns/fixedname.h> 38119287Simp#include <dns/log.h> 39119287Simp#include <dns/rdata.h> 4055639Scg#include <dns/rdatalist.h> 4182180Scg#include <dns/rdataset.h> 4282180Scg#include <dns/rdatasetiter.h> 4355639Scg#include <dns/rdatatype.h> 4455639Scg#include <dns/result.h> 4555639Scg#include <dns/sdb.h> 4655639Scg#include <dns/types.h> 4755639Scg 4855639Scg#include "rdatalist_p.h" 4955639Scg 5055639Scgstruct dns_sdbimplementation { 5155639Scg const dns_sdbmethods_t *methods; 5255639Scg void *driverdata; 5355639Scg unsigned int flags; 5491607Sorion isc_mem_t *mctx; 5591607Sorion isc_mutex_t driverlock; 5674763Scg dns_dbimplementation_t *dbimp; 5774763Scg}; 5855639Scg 5955639Scgstruct dns_sdb { 6055639Scg /* Unlocked */ 6155639Scg dns_db_t common; 6255639Scg char *zone; 6355639Scg dns_sdbimplementation_t *implementation; 6455639Scg void *dbdata; 6555639Scg isc_mutex_t lock; 6655639Scg /* Locked */ 6755639Scg unsigned int references; 6855639Scg}; 6955639Scg 7055639Scgstruct dns_sdblookup { 7155639Scg /* Unlocked */ 7255639Scg unsigned int magic; 7355639Scg dns_sdb_t *sdb; 7455639Scg ISC_LIST(dns_rdatalist_t) lists; 7555639Scg ISC_LIST(isc_buffer_t) buffers; 7655639Scg dns_name_t *name; 7755639Scg ISC_LINK(dns_sdblookup_t) link; 7855639Scg isc_mutex_t lock; 7955639Scg dns_rdatacallbacks_t callbacks; 8055639Scg /* Locked */ 8155639Scg unsigned int references; 8255639Scg}; 8355639Scg 8455639Scgtypedef struct dns_sdblookup dns_sdbnode_t; 8555639Scg 8655639Scgstruct dns_sdballnodes { 8755639Scg dns_dbiterator_t common; 8855639Scg ISC_LIST(dns_sdbnode_t) nodelist; 8955639Scg dns_sdbnode_t *current; 9055639Scg dns_sdbnode_t *origin; 9155639Scg}; 9255639Scg 9355639Scgtypedef dns_sdballnodes_t sdb_dbiterator_t; 9455639Scg 9555639Scgtypedef struct sdb_rdatasetiter { 9655802Scg dns_rdatasetiter_t common; 9755802Scg dns_rdatalist_t *current; 9855802Scg} sdb_rdatasetiter_t; 9964461Scg 10075382Sgreid#define SDB_MAGIC ISC_MAGIC('S', 'D', 'B', '-') 10155802Scg 10255802Scg/* 10355802Scg * Note that "impmagic" is not the first four bytes of the struct, so 10455639Scg * ISC_MAGIC_VALID cannot be used. 10555639Scg */ 10655802Scg#define VALID_SDB(sdb) ((sdb) != NULL && \ 10755802Scg (sdb)->common.impmagic == SDB_MAGIC) 10855802Scg 10955802Scg#define SDBLOOKUP_MAGIC ISC_MAGIC('S','D','B','L') 11055802Scg#define VALID_SDBLOOKUP(sdbl) ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC) 11155802Scg#define VALID_SDBNODE(sdbn) VALID_SDBLOOKUP(sdbn) 11255802Scg 11355802Scg/* These values are taken from RFC 1537 */ 11455802Scg#define SDB_DEFAULT_REFRESH (60 * 60 * 8) 11555639Scg#define SDB_DEFAULT_RETRY (60 * 60 * 2) 11655639Scg#define SDB_DEFAULT_EXPIRE (60 * 60 * 24 * 7) 11755639Scg#define SDB_DEFAULT_MINIMUM (60 * 60 * 24) 11855639Scg 11964881Scg/* This is a reasonable value */ 120193640Sariff#define SDB_DEFAULT_TTL (60 * 60 * 24) 121193640Sariff 122193640Sariff#define MAYBE_LOCK(sdb) \ 123193640Sariff do { \ 12464881Scg unsigned int flags = sdb->implementation->flags; \ 12555639Scg if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \ 12674763Scg LOCK(&sdb->implementation->driverlock); \ 12755639Scg } while (0) 12855639Scg 12955639Scg#define MAYBE_UNLOCK(sdb) \ 13055639Scg do { \ 13155639Scg unsigned int flags = sdb->implementation->flags; \ 13255639Scg if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \ 13355639Scg UNLOCK(&sdb->implementation->driverlock); \ 13455639Scg } while (0) 13555639Scg 13655639Scgstatic int dummy; 13755639Scg 13855639Scgstatic isc_result_t dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin, 13955639Scg dns_dbtype_t type, dns_rdataclass_t rdclass, 14055639Scg unsigned int argc, char *argv[], 14155639Scg void *driverarg, dns_db_t **dbp); 14255639Scg 14355639Scgstatic isc_result_t findrdataset(dns_db_t *db, dns_dbnode_t *node, 14455639Scg dns_dbversion_t *version, 14555639Scg dns_rdatatype_t type, dns_rdatatype_t covers, 14655639Scg isc_stdtime_t now, dns_rdataset_t *rdataset, 14755639Scg dns_rdataset_t *sigrdataset); 14855639Scg 14955639Scgstatic isc_result_t createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep); 15055639Scg 15155639Scgstatic void destroynode(dns_sdbnode_t *node); 15255639Scg 15355639Scgstatic void detachnode(dns_db_t *db, dns_dbnode_t **targetp); 15455639Scg 15555639Scg 15655639Scgstatic void list_tordataset(dns_rdatalist_t *rdatalist, 15755639Scg dns_db_t *db, dns_dbnode_t *node, 15855639Scg dns_rdataset_t *rdataset); 15955639Scg 16055639Scgstatic void dbiterator_destroy(dns_dbiterator_t **iteratorp); 16155639Scgstatic isc_result_t dbiterator_first(dns_dbiterator_t *iterator); 16255639Scgstatic isc_result_t dbiterator_last(dns_dbiterator_t *iterator); 16355639Scgstatic isc_result_t dbiterator_seek(dns_dbiterator_t *iterator, 16455639Scg dns_name_t *name); 16555639Scgstatic isc_result_t dbiterator_prev(dns_dbiterator_t *iterator); 16655639Scgstatic isc_result_t dbiterator_next(dns_dbiterator_t *iterator); 16755639Scgstatic isc_result_t dbiterator_current(dns_dbiterator_t *iterator, 16855639Scg dns_dbnode_t **nodep, 16955639Scg dns_name_t *name); 17055639Scgstatic isc_result_t dbiterator_pause(dns_dbiterator_t *iterator); 17155639Scgstatic isc_result_t dbiterator_origin(dns_dbiterator_t *iterator, 17255639Scg dns_name_t *name); 17355639Scg 17455639Scgstatic dns_dbiteratormethods_t dbiterator_methods = { 17555639Scg dbiterator_destroy, 17655639Scg dbiterator_first, 17755639Scg dbiterator_last, 17855639Scg dbiterator_seek, 17955639Scg dbiterator_prev, 18055639Scg dbiterator_next, 18155639Scg dbiterator_current, 18255639Scg dbiterator_pause, 18355639Scg dbiterator_origin 18455639Scg}; 18555639Scg 18655639Scgstatic void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp); 18755639Scgstatic isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator); 18855639Scgstatic isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator); 18955639Scgstatic void rdatasetiter_current(dns_rdatasetiter_t *iterator, 19055639Scg dns_rdataset_t *rdataset); 19155639Scg 19255639Scgstatic dns_rdatasetitermethods_t rdatasetiter_methods = { 19355639Scg rdatasetiter_destroy, 19455639Scg rdatasetiter_first, 19555639Scg rdatasetiter_next, 19655639Scg rdatasetiter_current 19755639Scg}; 19855639Scg 19955639Scg/* 20055639Scg * Functions used by implementors of simple databases 20155639Scg */ 20255639Scgisc_result_t 20355639Scgdns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods, 20455639Scg void *driverdata, unsigned int flags, isc_mem_t *mctx, 20570134Scg dns_sdbimplementation_t **sdbimp) 20655639Scg{ 20755639Scg dns_sdbimplementation_t *imp; 20855639Scg isc_result_t result; 20955639Scg 21055639Scg REQUIRE(drivername != NULL); 21191607Sorion REQUIRE(methods != NULL); 21255639Scg REQUIRE(methods->lookup != NULL); 21355639Scg REQUIRE(mctx != NULL); 21491607Sorion REQUIRE(sdbimp != NULL && *sdbimp == NULL); 21555639Scg REQUIRE((flags & ~(DNS_SDBFLAG_RELATIVEOWNER | 21691607Sorion DNS_SDBFLAG_RELATIVERDATA | 21791607Sorion DNS_SDBFLAG_THREADSAFE)) == 0); 21855639Scg 21991607Sorion imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t)); 22055639Scg if (imp == NULL) 22191607Sorion return (ISC_R_NOMEMORY); 22255639Scg imp->methods = methods; 22355639Scg imp->driverdata = driverdata; 22455639Scg imp->flags = flags; 22570134Scg imp->mctx = NULL; 22658384Scg isc_mem_attach(mctx, &imp->mctx); 22758384Scg result = isc_mutex_init(&imp->driverlock); 22858384Scg if (result != ISC_R_SUCCESS) { 22958384Scg UNEXPECTED_ERROR(__FILE__, __LINE__, 230149997Snetchild "isc_mutex_init() failed: %s", 231149997Snetchild isc_result_totext(result)); 232149997Snetchild goto cleanup_mctx; 233149997Snetchild } 234149997Snetchild 235149997Snetchild imp->dbimp = NULL; 236149997Snetchild result = dns_db_register(drivername, dns_sdb_create, imp, mctx, 237149997Snetchild &imp->dbimp); 23858384Scg if (result != ISC_R_SUCCESS) 239149997Snetchild goto cleanup_mutex; 24058384Scg *sdbimp = imp; 24158384Scg 24265490Scg return (ISC_R_SUCCESS); 24358384Scg 24458384Scg cleanup_mutex: 24570134Scg DESTROYLOCK(&imp->driverlock); 24670134Scg cleanup_mctx: 24755639Scg isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t)); 24855639Scg return (result); 24955639Scg} 25055639Scg 25155639Scgvoid 25255639Scgdns_sdb_unregister(dns_sdbimplementation_t **sdbimp) { 25355639Scg dns_sdbimplementation_t *imp; 25455639Scg isc_mem_t *mctx; 25555639Scg 25655639Scg REQUIRE(sdbimp != NULL && *sdbimp != NULL); 25770134Scg 25855639Scg imp = *sdbimp; 25955639Scg dns_db_unregister(&imp->dbimp); 26055639Scg DESTROYLOCK(&imp->driverlock); 26170134Scg 26270134Scg mctx = imp->mctx; 26355639Scg isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t)); 26455639Scg isc_mem_detach(&mctx); 26555639Scg 26655639Scg *sdbimp = NULL; 26755639Scg} 26855639Scg 26955639Scgstatic inline unsigned int 27055639Scginitial_size(unsigned int len) { 27155639Scg unsigned int size; 27270134Scg for (size = 64; size < (64 * 1024); size *= 2) 27355639Scg if (len < size) 27455639Scg return (size); 27555639Scg return (64 * 1024); 27655639Scg} 27770134Scg 27855639Scgisc_result_t 27955639Scgdns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval, dns_ttl_t ttl, 28070134Scg const unsigned char *rdatap, unsigned int rdlen) 28170134Scg{ 28270134Scg dns_rdatalist_t *rdatalist; 28370134Scg dns_rdata_t *rdata; 284193640Sariff isc_buffer_t *rdatabuf = NULL; 28570134Scg isc_result_t result; 28670134Scg isc_mem_t *mctx; 28770134Scg isc_region_t region; 28870134Scg 28970134Scg mctx = lookup->sdb->common.mctx; 29055639Scg 29155639Scg rdatalist = ISC_LIST_HEAD(lookup->lists); 29255639Scg while (rdatalist != NULL) { 29355639Scg if (rdatalist->type == typeval) 29455639Scg break; 29555639Scg rdatalist = ISC_LIST_NEXT(rdatalist, link); 29655639Scg } 29755639Scg 29855639Scg if (rdatalist == NULL) { 29955639Scg rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t)); 30055639Scg if (rdatalist == NULL) 30155639Scg return (ISC_R_NOMEMORY); 30255639Scg rdatalist->rdclass = lookup->sdb->common.rdclass; 30355639Scg rdatalist->type = typeval; 30455639Scg rdatalist->covers = 0; 30555639Scg rdatalist->ttl = ttl; 30655639Scg ISC_LIST_INIT(rdatalist->rdata); 30755639Scg ISC_LINK_INIT(rdatalist, link); 30855639Scg ISC_LIST_APPEND(lookup->lists, rdatalist, link); 30955639Scg } else 31055639Scg if (rdatalist->ttl != ttl) 31155639Scg return (DNS_R_BADTTL); 31255639Scg 31355639Scg rdata = isc_mem_get(mctx, sizeof(dns_rdata_t)); 31455639Scg if (rdata == NULL) 31555639Scg return (ISC_R_NOMEMORY); 31655639Scg 31755639Scg result = isc_buffer_allocate(mctx, &rdatabuf, rdlen); 31855639Scg if (result != ISC_R_SUCCESS) 31955639Scg goto failure; 32055639Scg DE_CONST(rdatap, region.base); 32155639Scg region.length = rdlen; 32255639Scg isc_buffer_copyregion(rdatabuf, ®ion); 32355639Scg isc_buffer_usedregion(rdatabuf, ®ion); 32455639Scg dns_rdata_init(rdata); 32555639Scg dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type, 32655639Scg ®ion); 32755639Scg ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 32855639Scg ISC_LIST_APPEND(lookup->buffers, rdatabuf, link); 32955639Scg rdata = NULL; 33055639Scg 33155639Scg failure: 33255639Scg if (rdata != NULL) 33355639Scg isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); 33455639Scg return (result); 33555639Scg} 33655639Scg 33755639Scg 33855639Scgisc_result_t 33955639Scgdns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl, 34055639Scg const char *data) 341193640Sariff{ 34255639Scg unsigned int datalen; 34355639Scg dns_rdatatype_t typeval; 34455639Scg isc_textregion_t r; 34555639Scg isc_lex_t *lex = NULL; 34655639Scg isc_result_t result; 34755639Scg unsigned char *p = NULL; 34855639Scg unsigned int size = 0; /* Init to suppress compiler warning */ 34955639Scg isc_mem_t *mctx; 35074763Scg dns_sdbimplementation_t *imp; 35155639Scg dns_name_t *origin; 35255639Scg isc_buffer_t b; 35355639Scg isc_buffer_t rb; 35455639Scg 35555639Scg REQUIRE(VALID_SDBLOOKUP(lookup)); 35655639Scg REQUIRE(type != NULL); 35755639Scg REQUIRE(data != NULL); 35891607Sorion 35991607Sorion mctx = lookup->sdb->common.mctx; 36091607Sorion 36155639Scg DE_CONST(type, r.base); 36270291Scg r.length = strlen(type); 36355878Scg result = dns_rdatatype_fromtext(&typeval, &r); 36455878Scg if (result != ISC_R_SUCCESS) 36574763Scg return (result); 36655639Scg 36755639Scg imp = lookup->sdb->implementation; 36855639Scg if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0) 36955639Scg origin = &lookup->sdb->common.origin; 37055639Scg else 37155639Scg origin = dns_rootname; 37255639Scg 37370134Scg result = isc_lex_create(mctx, 64, &lex); 37465340Scg if (result != ISC_R_SUCCESS) 37565340Scg goto failure; 37665340Scg 37765340Scg datalen = strlen(data); 37865340Scg size = initial_size(datalen); 37970134Scg for (;;) { 38055639Scg isc_buffer_init(&b, data, datalen); 38155639Scg isc_buffer_add(&b, datalen); 38255639Scg result = isc_lex_openbuffer(lex, &b); 38355639Scg if (result != ISC_R_SUCCESS) 38455639Scg goto failure; 38555639Scg 38655639Scg p = isc_mem_get(mctx, size); 387193640Sariff if (p == NULL) { 38870134Scg result = ISC_R_NOMEMORY; 38955639Scg goto failure; 39055639Scg } 39155639Scg isc_buffer_init(&rb, p, size); 39255639Scg result = dns_rdata_fromtext(NULL, 39355700Scg lookup->sdb->common.rdclass, 39455639Scg typeval, lex, 39555639Scg origin, 0, 396193640Sariff mctx, &rb, 39770134Scg &lookup->callbacks); 39855639Scg if (result != ISC_R_NOSPACE) 39991607Sorion break; 40091607Sorion 40191607Sorion isc_mem_put(mctx, p, size); 40291607Sorion p = NULL; 40355639Scg size *= 2; 40455639Scg } while (result == ISC_R_NOSPACE); 40555639Scg 40655639Scg if (result != ISC_R_SUCCESS) 40770134Scg goto failure; 40855639Scg 40955639Scg result = dns_sdb_putrdata(lookup, typeval, ttl, 41055639Scg isc_buffer_base(&rb), 41155639Scg isc_buffer_usedlength(&rb)); 41255639Scg failure: 413170521Sariff if (p != NULL) 41460958Scg isc_mem_put(mctx, p, size); 41555639Scg if (lex != NULL) 41655639Scg isc_lex_destroy(&lex); 417193640Sariff 41855639Scg return (result); 41955639Scg} 42055639Scg 42155639Scgstatic isc_result_t 42291607Soriongetnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) { 42391607Sorion dns_name_t *newname, *origin; 42455639Scg dns_fixedname_t fnewname; 42555639Scg dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db; 42655639Scg dns_sdbimplementation_t *imp = sdb->implementation; 42791607Sorion dns_sdbnode_t *sdbnode; 42855639Scg isc_mem_t *mctx = sdb->common.mctx; 42955639Scg isc_buffer_t b; 43055639Scg isc_result_t result; 43155639Scg 43291607Sorion dns_fixedname_init(&fnewname); 43355639Scg newname = dns_fixedname_name(&fnewname); 43455639Scg 43555639Scg if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0) 43655639Scg origin = &sdb->common.origin; 43755639Scg else 43891607Sorion origin = dns_rootname; 43991607Sorion isc_buffer_init(&b, name, strlen(name)); 44055639Scg isc_buffer_add(&b, strlen(name)); 44155639Scg 44255639Scg result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL); 44355639Scg if (result != ISC_R_SUCCESS) 44455639Scg return (result); 44591607Sorion 44655639Scg if (allnodes->common.relative_names) { 44791607Sorion /* All names are relative to the root */ 44855639Scg unsigned int nlabels = dns_name_countlabels(newname); 44955639Scg dns_name_getlabelsequence(newname, 0, nlabels - 1, newname); 45055639Scg } 45155639Scg 45255639Scg sdbnode = ISC_LIST_HEAD(allnodes->nodelist); 45355639Scg if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) { 454193640Sariff sdbnode = NULL; 45570134Scg result = createnode(sdb, &sdbnode); 45655639Scg if (result != ISC_R_SUCCESS) 45755639Scg return (result); 45855639Scg sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t)); 45955639Scg if (sdbnode->name == NULL) { 46055639Scg destroynode(sdbnode); 46155639Scg return (ISC_R_NOMEMORY); 46255639Scg } 46355639Scg dns_name_init(sdbnode->name, NULL); 46455639Scg result = dns_name_dup(newname, mctx, sdbnode->name); 46555639Scg if (result != ISC_R_SUCCESS) { 46674763Scg isc_mem_put(mctx, sdbnode->name, sizeof(dns_name_t)); 46770134Scg destroynode(sdbnode); 46855639Scg return (result); 46955639Scg } 47055639Scg ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link); 47155639Scg if (allnodes->origin == NULL && 47270134Scg dns_name_equal(newname, &sdb->common.origin)) 47370134Scg allnodes->origin = sdbnode; 47470134Scg } 47570134Scg *nodep = sdbnode; 47670134Scg return (ISC_R_SUCCESS); 47770134Scg} 47870134Scg 47970134Scgisc_result_t 48070134Scgdns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name, 481193640Sariff const char *type, dns_ttl_t ttl, const char *data) 48270134Scg{ 48370134Scg isc_result_t result; 48470134Scg dns_sdbnode_t *sdbnode = NULL; 48555639Scg result = getnode(allnodes, name, &sdbnode); 48655639Scg if (result != ISC_R_SUCCESS) 48755639Scg return (result); 48855639Scg return (dns_sdb_putrr(sdbnode, type, ttl, data)); 48955639Scg} 49064461Scg 49155639Scgisc_result_t 49255639Scgdns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name, 49364461Scg dns_rdatatype_t type, dns_ttl_t ttl, 49455639Scg const void *rdata, unsigned int rdlen) 49555639Scg{ 49655639Scg isc_result_t result; 49755639Scg dns_sdbnode_t *sdbnode = NULL; 49891607Sorion result = getnode(allnodes, name, &sdbnode); 49991607Sorion if (result != ISC_R_SUCCESS) 50091607Sorion return (result); 50191607Sorion return (dns_sdb_putrdata(sdbnode, type, ttl, rdata, rdlen)); 50255639Scg} 50355639Scg 50455639Scgisc_result_t 50555639Scgdns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname, 50655639Scg isc_uint32_t serial) 50791607Sorion{ 50891607Sorion char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7]; 50991607Sorion int n; 51091607Sorion 51155639Scg REQUIRE(mname != NULL); 51255639Scg REQUIRE(rname != NULL); 51355639Scg 51455639Scg n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u", 51555639Scg mname, rname, serial, 51655639Scg SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY, 51755639Scg SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM); 51855639Scg if (n >= (int)sizeof(str) || n < 0) 51955639Scg return (ISC_R_NOSPACE); 52055639Scg return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str)); 52155639Scg} 52255639Scg 52355639Scg/* 52455639Scg * DB routines 52555639Scg */ 52655639Scg 52755639Scgstatic void 52855639Scgattach(dns_db_t *source, dns_db_t **targetp) { 52964461Scg dns_sdb_t *sdb = (dns_sdb_t *) source; 53055639Scg 53155639Scg REQUIRE(VALID_SDB(sdb)); 53255639Scg 53355639Scg LOCK(&sdb->lock); 53455639Scg REQUIRE(sdb->references > 0); 53555639Scg sdb->references++; 53655639Scg UNLOCK(&sdb->lock); 53755639Scg 53855639Scg *targetp = source; 53955639Scg} 54055639Scg 54155639Scgstatic void 54255639Scgdestroy(dns_sdb_t *sdb) { 54355639Scg isc_mem_t *mctx; 54455639Scg dns_sdbimplementation_t *imp = sdb->implementation; 54555639Scg 54655639Scg mctx = sdb->common.mctx; 54755639Scg 54855639Scg if (imp->methods->destroy != NULL) { 54955639Scg MAYBE_LOCK(sdb); 55055639Scg imp->methods->destroy(sdb->zone, imp->driverdata, 55155639Scg &sdb->dbdata); 55255639Scg MAYBE_UNLOCK(sdb); 55355639Scg } 55455639Scg 55555639Scg isc_mem_free(mctx, sdb->zone); 55655639Scg DESTROYLOCK(&sdb->lock); 55755639Scg 55855639Scg sdb->common.magic = 0; 55955639Scg sdb->common.impmagic = 0; 56055639Scg 56155639Scg dns_name_free(&sdb->common.origin, mctx); 56255639Scg 56355639Scg isc_mem_put(mctx, sdb, sizeof(dns_sdb_t)); 56455639Scg isc_mem_detach(&mctx); 56555639Scg} 56655639Scg 56755639Scgstatic void 56855639Scgdetach(dns_db_t **dbp) { 56955713Scg dns_sdb_t *sdb = (dns_sdb_t *)(*dbp); 57055639Scg isc_boolean_t need_destroy = ISC_FALSE; 57155639Scg 57255639Scg REQUIRE(VALID_SDB(sdb)); 57355639Scg LOCK(&sdb->lock); 57491607Sorion REQUIRE(sdb->references > 0); 57591607Sorion sdb->references--; 57655639Scg if (sdb->references == 0) 57755639Scg need_destroy = ISC_TRUE; 57891607Sorion UNLOCK(&sdb->lock); 57991607Sorion 58091607Sorion if (need_destroy) 58155639Scg destroy(sdb); 58291607Sorion 58355639Scg *dbp = NULL; 58455639Scg} 58555639Scg 58655639Scgstatic isc_result_t 58755639Scgbeginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) { 58855639Scg UNUSED(db); 58955639Scg UNUSED(addp); 59055639Scg UNUSED(dbloadp); 59155639Scg return (ISC_R_NOTIMPLEMENTED); 59255639Scg} 59355639Scg 59455639Scgstatic isc_result_t 59555639Scgendload(dns_db_t *db, dns_dbload_t **dbloadp) { 59655639Scg UNUSED(db); 59755639Scg UNUSED(dbloadp); 59855639Scg return (ISC_R_NOTIMPLEMENTED); 59955639Scg} 60075382Sgreid 60155639Scgstatic isc_result_t 602254263Sscottldump(dns_db_t *db, dns_dbversion_t *version, const char *filename) { 60355639Scg UNUSED(db); 60455802Scg UNUSED(version); 60555639Scg UNUSED(filename); 60655639Scg return (ISC_R_NOTIMPLEMENTED); 60755802Scg} 60855802Scg 60955802Scgstatic void 61075382Sgreidcurrentversion(dns_db_t *db, dns_dbversion_t **versionp) { 61175382Sgreid REQUIRE(versionp != NULL && *versionp == NULL); 61275382Sgreid 61375382Sgreid UNUSED(db); 61478564Sgreid 61575382Sgreid *versionp = (void *) &dummy; 61675382Sgreid return; 61775382Sgreid} 61875382Sgreid 619119690Sjhbstatic isc_result_t 620127135Snjlnewversion(dns_db_t *db, dns_dbversion_t **versionp) { 621127135Snjl UNUSED(db); 622127135Snjl UNUSED(versionp); 62375382Sgreid 62475382Sgreid return (ISC_R_NOTIMPLEMENTED); 62575382Sgreid} 62675382Sgreid 62775382Sgreidstatic void 62875382Sgreidattachversion(dns_db_t *db, dns_dbversion_t *source, 62975382Sgreid dns_dbversion_t **targetp) 63091607Sorion{ 63191607Sorion REQUIRE(source != NULL && source == (void *) &dummy); 63291607Sorion REQUIRE(targetp != NULL && *targetp == NULL); 63391607Sorion 63491607Sorion UNUSED(db); 63591607Sorion *targetp = source; 63678362Scg return; 63775382Sgreid} 63875382Sgreid 63975382Sgreidstatic void 64075382Sgreidcloseversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { 64175382Sgreid REQUIRE(versionp != NULL && *versionp == (void *) &dummy); 64275382Sgreid REQUIRE(commit == ISC_FALSE); 64375382Sgreid 64475382Sgreid UNUSED(db); 64575382Sgreid UNUSED(commit); 64675382Sgreid 64755802Scg *versionp = NULL; 64855802Scg} 64955878Scg 65055878Scgstatic isc_result_t 65175382Sgreidcreatenode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) { 65255639Scg dns_sdbnode_t *node; 65355639Scg isc_result_t result; 65455639Scg 65555639Scg node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t)); 65655639Scg if (node == NULL) 65755639Scg return (ISC_R_NOMEMORY); 65855639Scg 65955639Scg node->sdb = NULL; 66055639Scg attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb); 66155639Scg ISC_LIST_INIT(node->lists); 66255639Scg ISC_LIST_INIT(node->buffers); 66355639Scg ISC_LINK_INIT(node, link); 66455639Scg node->name = NULL; 66555639Scg result = isc_mutex_init(&node->lock); 66655639Scg if (result != ISC_R_SUCCESS) { 66765644Scg UNEXPECTED_ERROR(__FILE__, __LINE__, 66855639Scg "isc_mutex_init() failed: %s", 66955639Scg isc_result_totext(result)); 670170873Sariff isc_mem_put(sdb->common.mctx, node, sizeof(dns_sdbnode_t)); 67155639Scg return (ISC_R_UNEXPECTED); 67255639Scg } 67355639Scg dns_rdatacallbacks_init(&node->callbacks); 674254263Sscottl node->references = 1; 67555639Scg node->magic = SDBLOOKUP_MAGIC; 676119690Sjhb 677127135Snjl *nodep = node; 678127135Snjl return (ISC_R_SUCCESS); 679119690Sjhb} 680127135Snjl 681127135Snjlstatic void 68255639Scgdestroynode(dns_sdbnode_t *node) { 68355639Scg dns_rdatalist_t *list; 68455639Scg dns_rdata_t *rdata; 68555639Scg isc_buffer_t *b; 68655639Scg dns_sdb_t *sdb; 68755639Scg isc_mem_t *mctx; 68855639Scg 68955639Scg sdb = node->sdb; 69055639Scg mctx = sdb->common.mctx; 69155639Scg 69255639Scg while (!ISC_LIST_EMPTY(node->lists)) { 69370134Scg list = ISC_LIST_HEAD(node->lists); 69455639Scg while (!ISC_LIST_EMPTY(list->rdata)) { 69570134Scg rdata = ISC_LIST_HEAD(list->rdata); 69655639Scg ISC_LIST_UNLINK(list->rdata, rdata, link); 69755639Scg isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); 698127135Snjl } 699127135Snjl ISC_LIST_UNLINK(node->lists, list, link); 70074763Scg isc_mem_put(mctx, list, sizeof(dns_rdatalist_t)); 70155639Scg } 70255639Scg 70355639Scg while (!ISC_LIST_EMPTY(node->buffers)) { 70455639Scg b = ISC_LIST_HEAD(node->buffers); 705126695Smatk ISC_LIST_UNLINK(node->buffers, b, link); 70655639Scg isc_buffer_free(&b); 707126695Smatk } 70855639Scg 70955639Scg if (node->name != NULL) { 71070134Scg dns_name_free(node->name, mctx); 71170134Scg isc_mem_put(mctx, node->name, sizeof(dns_name_t)); 71255639Scg } 71355639Scg DESTROYLOCK(&node->lock); 71455639Scg node->magic = 0; 71555639Scg isc_mem_put(mctx, node, sizeof(dns_sdbnode_t)); 71655639Scg detach((dns_db_t **) (void *)&sdb); 71765644Scg} 71855639Scg 71955639Scgstatic isc_result_t 72055639Scgfindnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, 72155639Scg dns_dbnode_t **nodep) 72255639Scg{ 72355639Scg dns_sdb_t *sdb = (dns_sdb_t *)db; 72455639Scg dns_sdbnode_t *node = NULL; 72555639Scg isc_result_t result; 72658384Scg isc_buffer_t b; 72765644Scg char namestr[DNS_NAME_MAXTEXT + 1]; 72865644Scg isc_boolean_t isorigin; 72965644Scg dns_sdbimplementation_t *imp; 73065644Scg 73165644Scg REQUIRE(VALID_SDB(sdb)); 73265644Scg REQUIRE(create == ISC_FALSE); 73365644Scg REQUIRE(nodep != NULL && *nodep == NULL); 73465644Scg 73565644Scg UNUSED(name); 73665644Scg UNUSED(create); 73765644Scg 73865644Scg imp = sdb->implementation; 73965644Scg 74065644Scg isc_buffer_init(&b, namestr, sizeof(namestr)); 74165644Scg if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) { 74265644Scg dns_name_t relname; 74365644Scg unsigned int labels; 74465644Scg 74565644Scg labels = dns_name_countlabels(name) - 74665644Scg dns_name_countlabels(&db->origin); 74791607Sorion dns_name_init(&relname, NULL); 74891607Sorion dns_name_getlabelsequence(name, 0, labels, &relname); 74991607Sorion result = dns_name_totext(&relname, ISC_TRUE, &b); 75091607Sorion if (result != ISC_R_SUCCESS) 75191607Sorion return (result); 75291607Sorion } else { 75391607Sorion result = dns_name_totext(name, ISC_TRUE, &b); 75491607Sorion if (result != ISC_R_SUCCESS) 75591607Sorion return (result); 75691607Sorion } 75791607Sorion isc_buffer_putuint8(&b, 0); 75891607Sorion 75991607Sorion result = createnode(sdb, &node); 76091607Sorion if (result != ISC_R_SUCCESS) 76191607Sorion return (result); 76291607Sorion 76391607Sorion isorigin = dns_name_equal(name, &sdb->common.origin); 76491607Sorion 76591607Sorion MAYBE_LOCK(sdb); 76658384Scg result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata, node); 76758384Scg MAYBE_UNLOCK(sdb); 76858384Scg if (result != ISC_R_SUCCESS && 76958384Scg !(result == ISC_R_NOTFOUND && 77058384Scg isorigin && imp->methods->authority != NULL)) 77158384Scg { 77291607Sorion destroynode(node); 77391607Sorion return (result); 77491607Sorion } 77591607Sorion 77691607Sorion if (isorigin && imp->methods->authority != NULL) { 77791607Sorion MAYBE_LOCK(sdb); 77891607Sorion result = imp->methods->authority(sdb->zone, sdb->dbdata, node); 77991607Sorion MAYBE_UNLOCK(sdb); 78091607Sorion if (result != ISC_R_SUCCESS) { 78191607Sorion destroynode(node); 78291607Sorion return (result); 78358384Scg } 78465340Scg } 78558384Scg 78658384Scg *nodep = node; 78758384Scg return (ISC_R_SUCCESS); 78891607Sorion} 78991607Sorion 79091607Sorionstatic isc_result_t 79191607Sorionfind(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, 79291607Sorion dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 79391607Sorion dns_dbnode_t **nodep, dns_name_t *foundname, 79491607Sorion dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 79591607Sorion{ 79691607Sorion dns_sdb_t *sdb = (dns_sdb_t *)db; 79791607Sorion dns_dbnode_t *node = NULL; 79891607Sorion dns_fixedname_t fname; 79958384Scg dns_rdataset_t xrdataset; 80058384Scg dns_name_t *xname; 80158384Scg unsigned int nlabels, olabels; 80255639Scg isc_result_t result; 80355639Scg unsigned int i; 80455639Scg 80555639Scg REQUIRE(VALID_SDB(sdb)); 80666012Scg REQUIRE(nodep == NULL || *nodep == NULL); 80791607Sorion REQUIRE(version == NULL || version == (void *) &dummy); 80858384Scg 80955639Scg UNUSED(options); 81055639Scg UNUSED(sdb); 81155639Scg 81255639Scg if (!dns_name_issubdomain(name, &db->origin)) 81355639Scg return (DNS_R_NXDOMAIN); 81455639Scg 81582180Scg olabels = dns_name_countlabels(&db->origin); 81655639Scg nlabels = dns_name_countlabels(name); 81755639Scg 81862483Scg dns_fixedname_init(&fname); 819132236Stanimura xname = dns_fixedname_name(&fname); 82062483Scg 821 if (rdataset == NULL) { 822 dns_rdataset_init(&xrdataset); 823 rdataset = &xrdataset; 824 } 825 826 result = DNS_R_NXDOMAIN; 827 828 for (i = olabels; i <= nlabels; i++) { 829 /* 830 * Unless this is an explicit lookup at the origin, don't 831 * look at the origin. 832 */ 833 if (i == olabels && i != nlabels) 834 continue; 835 836 /* 837 * Look up the next label. 838 */ 839 dns_name_getlabelsequence(name, nlabels - i, i, xname); 840 result = findnode(db, xname, ISC_FALSE, &node); 841 if (result != ISC_R_SUCCESS) { 842 result = DNS_R_NXDOMAIN; 843 continue; 844 } 845 846 /* 847 * Look for a DNAME at the current label, unless this is 848 * the qname. 849 */ 850 if (i < nlabels) { 851 result = findrdataset(db, node, version, 852 dns_rdatatype_dname, 853 0, now, rdataset, sigrdataset); 854 if (result == ISC_R_SUCCESS) { 855 result = DNS_R_DNAME; 856 break; 857 } 858 } 859 860 /* 861 * Look for an NS at the current label, unless this is the 862 * origin or glue is ok. 863 */ 864 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) { 865 result = findrdataset(db, node, version, 866 dns_rdatatype_ns, 867 0, now, rdataset, sigrdataset); 868 if (result == ISC_R_SUCCESS) { 869 if (i == nlabels && type == dns_rdatatype_any) 870 { 871 result = DNS_R_ZONECUT; 872 dns_rdataset_disassociate(rdataset); 873 if (sigrdataset != NULL) 874 dns_rdataset_disassociate 875 (sigrdataset); 876 } else 877 result = DNS_R_DELEGATION; 878 break; 879 } 880 } 881 882 /* 883 * If the current name is not the qname, add another label 884 * and try again. 885 */ 886 if (i < nlabels) { 887 destroynode(node); 888 node = NULL; 889 continue; 890 } 891 892 /* 893 * If we're looking for ANY, we're done. 894 */ 895 if (type == dns_rdatatype_any) { 896 result = ISC_R_SUCCESS; 897 break; 898 } 899 900 /* 901 * Look for the qtype. 902 */ 903 result = findrdataset(db, node, version, type, 904 0, now, rdataset, sigrdataset); 905 if (result == ISC_R_SUCCESS) 906 break; 907 908 /* 909 * Look for a CNAME 910 */ 911 if (type != dns_rdatatype_cname) { 912 result = findrdataset(db, node, version, 913 dns_rdatatype_cname, 914 0, now, rdataset, sigrdataset); 915 if (result == ISC_R_SUCCESS) { 916 result = DNS_R_CNAME; 917 break; 918 } 919 } 920 921 result = DNS_R_NXRRSET; 922 break; 923 } 924 925 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) 926 dns_rdataset_disassociate(rdataset); 927 928 if (foundname != NULL) { 929 isc_result_t xresult; 930 931 xresult = dns_name_copy(xname, foundname, NULL); 932 if (xresult != ISC_R_SUCCESS) { 933 destroynode(node); 934 if (dns_rdataset_isassociated(rdataset)) 935 dns_rdataset_disassociate(rdataset); 936 return (DNS_R_BADDB); 937 } 938 } 939 940 if (nodep != NULL) 941 *nodep = node; 942 else if (node != NULL) 943 detachnode(db, &node); 944 945 return (result); 946} 947 948static isc_result_t 949findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options, 950 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname, 951 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 952{ 953 UNUSED(db); 954 UNUSED(name); 955 UNUSED(options); 956 UNUSED(now); 957 UNUSED(nodep); 958 UNUSED(foundname); 959 UNUSED(rdataset); 960 UNUSED(sigrdataset); 961 962 return (ISC_R_NOTIMPLEMENTED); 963} 964 965static void 966attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { 967 dns_sdb_t *sdb = (dns_sdb_t *)db; 968 dns_sdbnode_t *node = (dns_sdbnode_t *)source; 969 970 REQUIRE(VALID_SDB(sdb)); 971 972 UNUSED(sdb); 973 974 LOCK(&node->lock); 975 INSIST(node->references > 0); 976 node->references++; 977 INSIST(node->references != 0); /* Catch overflow. */ 978 UNLOCK(&node->lock); 979 980 *targetp = source; 981} 982 983static void 984detachnode(dns_db_t *db, dns_dbnode_t **targetp) { 985 dns_sdb_t *sdb = (dns_sdb_t *)db; 986 dns_sdbnode_t *node; 987 isc_boolean_t need_destroy = ISC_FALSE; 988 989 REQUIRE(VALID_SDB(sdb)); 990 REQUIRE(targetp != NULL && *targetp != NULL); 991 992 UNUSED(sdb); 993 994 node = (dns_sdbnode_t *)(*targetp); 995 996 LOCK(&node->lock); 997 INSIST(node->references > 0); 998 node->references--; 999 if (node->references == 0) 1000 need_destroy = ISC_TRUE; 1001 UNLOCK(&node->lock); 1002 1003 if (need_destroy) 1004 destroynode(node); 1005 1006 *targetp = NULL; 1007} 1008 1009static isc_result_t 1010expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) { 1011 UNUSED(db); 1012 UNUSED(node); 1013 UNUSED(now); 1014 INSIST(0); 1015 return (ISC_R_UNEXPECTED); 1016} 1017 1018static void 1019printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) { 1020 UNUSED(db); 1021 UNUSED(node); 1022 UNUSED(out); 1023 return; 1024} 1025 1026static isc_result_t 1027createiterator(dns_db_t *db, isc_boolean_t relative_names, 1028 dns_dbiterator_t **iteratorp) 1029{ 1030 dns_sdb_t *sdb = (dns_sdb_t *)db; 1031 sdb_dbiterator_t *sdbiter; 1032 dns_sdbimplementation_t *imp = sdb->implementation; 1033 isc_result_t result; 1034 1035 REQUIRE(VALID_SDB(sdb)); 1036 1037 if (imp->methods->allnodes == NULL) 1038 return (ISC_R_NOTIMPLEMENTED); 1039 1040 sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t)); 1041 if (sdbiter == NULL) 1042 return (ISC_R_NOMEMORY); 1043 1044 sdbiter->common.methods = &dbiterator_methods; 1045 sdbiter->common.db = NULL; 1046 dns_db_attach(db, &sdbiter->common.db); 1047 sdbiter->common.relative_names = relative_names; 1048 sdbiter->common.magic = DNS_DBITERATOR_MAGIC; 1049 ISC_LIST_INIT(sdbiter->nodelist); 1050 sdbiter->current = NULL; 1051 sdbiter->origin = NULL; 1052 1053 MAYBE_LOCK(sdb); 1054 result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter); 1055 MAYBE_UNLOCK(sdb); 1056 if (result != ISC_R_SUCCESS) { 1057 dbiterator_destroy((dns_dbiterator_t **) (void *)&sdbiter); 1058 return (result); 1059 } 1060 1061 if (sdbiter->origin != NULL) { 1062 ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link); 1063 ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link); 1064 } 1065 1066 *iteratorp = (dns_dbiterator_t *)sdbiter; 1067 1068 return (ISC_R_SUCCESS); 1069} 1070 1071static isc_result_t 1072findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1073 dns_rdatatype_t type, dns_rdatatype_t covers, 1074 isc_stdtime_t now, dns_rdataset_t *rdataset, 1075 dns_rdataset_t *sigrdataset) 1076{ 1077 dns_rdatalist_t *list; 1078 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node; 1079 1080 REQUIRE(VALID_SDBNODE(node)); 1081 1082 UNUSED(db); 1083 UNUSED(version); 1084 UNUSED(covers); 1085 UNUSED(now); 1086 UNUSED(sigrdataset); 1087 1088 if (type == dns_rdatatype_rrsig) 1089 return (ISC_R_NOTIMPLEMENTED); 1090 1091 list = ISC_LIST_HEAD(sdbnode->lists); 1092 while (list != NULL) { 1093 if (list->type == type) 1094 break; 1095 list = ISC_LIST_NEXT(list, link); 1096 } 1097 if (list == NULL) 1098 return (ISC_R_NOTFOUND); 1099 1100 list_tordataset(list, db, node, rdataset); 1101 1102 return (ISC_R_SUCCESS); 1103} 1104 1105static isc_result_t 1106allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1107 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) 1108{ 1109 sdb_rdatasetiter_t *iterator; 1110 1111 REQUIRE(version == NULL || version == &dummy); 1112 1113 UNUSED(version); 1114 UNUSED(now); 1115 1116 iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t)); 1117 if (iterator == NULL) 1118 return (ISC_R_NOMEMORY); 1119 1120 iterator->common.magic = DNS_RDATASETITER_MAGIC; 1121 iterator->common.methods = &rdatasetiter_methods; 1122 iterator->common.db = db; 1123 iterator->common.node = NULL; 1124 attachnode(db, node, &iterator->common.node); 1125 iterator->common.version = version; 1126 iterator->common.now = now; 1127 1128 *iteratorp = (dns_rdatasetiter_t *)iterator; 1129 1130 return (ISC_R_SUCCESS); 1131} 1132 1133static isc_result_t 1134addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1135 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, 1136 dns_rdataset_t *addedrdataset) 1137{ 1138 UNUSED(db); 1139 UNUSED(node); 1140 UNUSED(version); 1141 UNUSED(now); 1142 UNUSED(rdataset); 1143 UNUSED(options); 1144 UNUSED(addedrdataset); 1145 1146 return (ISC_R_NOTIMPLEMENTED); 1147} 1148 1149static isc_result_t 1150subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1151 dns_rdataset_t *rdataset, unsigned int options, 1152 dns_rdataset_t *newrdataset) 1153{ 1154 UNUSED(db); 1155 UNUSED(node); 1156 UNUSED(version); 1157 UNUSED(rdataset); 1158 UNUSED(options); 1159 UNUSED(newrdataset); 1160 1161 return (ISC_R_NOTIMPLEMENTED); 1162} 1163 1164static isc_result_t 1165deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1166 dns_rdatatype_t type, dns_rdatatype_t covers) 1167{ 1168 UNUSED(db); 1169 UNUSED(node); 1170 UNUSED(version); 1171 UNUSED(type); 1172 UNUSED(covers); 1173 1174 return (ISC_R_NOTIMPLEMENTED); 1175} 1176 1177static isc_boolean_t 1178issecure(dns_db_t *db) { 1179 UNUSED(db); 1180 1181 return (ISC_FALSE); 1182} 1183 1184static unsigned int 1185nodecount(dns_db_t *db) { 1186 UNUSED(db); 1187 1188 return (0); 1189} 1190 1191static isc_boolean_t 1192ispersistent(dns_db_t *db) { 1193 UNUSED(db); 1194 return (ISC_TRUE); 1195} 1196 1197static void 1198overmem(dns_db_t *db, isc_boolean_t overmem) { 1199 UNUSED(db); 1200 UNUSED(overmem); 1201} 1202 1203static void 1204settask(dns_db_t *db, isc_task_t *task) { 1205 UNUSED(db); 1206 UNUSED(task); 1207} 1208 1209 1210static dns_dbmethods_t sdb_methods = { 1211 attach, 1212 detach, 1213 beginload, 1214 endload, 1215 dump, 1216 currentversion, 1217 newversion, 1218 attachversion, 1219 closeversion, 1220 findnode, 1221 find, 1222 findzonecut, 1223 attachnode, 1224 detachnode, 1225 expirenode, 1226 printnode, 1227 createiterator, 1228 findrdataset, 1229 allrdatasets, 1230 addrdataset, 1231 subtractrdataset, 1232 deleterdataset, 1233 issecure, 1234 nodecount, 1235 ispersistent, 1236 overmem, 1237 settask 1238}; 1239 1240static isc_result_t 1241dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type, 1242 dns_rdataclass_t rdclass, unsigned int argc, char *argv[], 1243 void *driverarg, dns_db_t **dbp) 1244{ 1245 dns_sdb_t *sdb; 1246 isc_result_t result; 1247 char zonestr[DNS_NAME_MAXTEXT + 1]; 1248 isc_buffer_t b; 1249 dns_sdbimplementation_t *imp; 1250 1251 REQUIRE(driverarg != NULL); 1252 1253 imp = driverarg; 1254 1255 if (type != dns_dbtype_zone) 1256 return (ISC_R_NOTIMPLEMENTED); 1257 1258 sdb = isc_mem_get(mctx, sizeof(dns_sdb_t)); 1259 if (sdb == NULL) 1260 return (ISC_R_NOMEMORY); 1261 memset(sdb, 0, sizeof(dns_sdb_t)); 1262 1263 dns_name_init(&sdb->common.origin, NULL); 1264 sdb->common.attributes = 0; 1265 sdb->common.methods = &sdb_methods; 1266 sdb->common.rdclass = rdclass; 1267 sdb->common.mctx = NULL; 1268 sdb->implementation = imp; 1269 1270 isc_mem_attach(mctx, &sdb->common.mctx); 1271 1272 result = isc_mutex_init(&sdb->lock); 1273 if (result != ISC_R_SUCCESS) { 1274 UNEXPECTED_ERROR(__FILE__, __LINE__, 1275 "isc_mutex_init() failed: %s", 1276 isc_result_totext(result)); 1277 result = ISC_R_UNEXPECTED; 1278 goto cleanup_mctx; 1279 } 1280 1281 result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin); 1282 if (result != ISC_R_SUCCESS) 1283 goto cleanup_lock; 1284 1285 isc_buffer_init(&b, zonestr, sizeof(zonestr)); 1286 result = dns_name_totext(origin, ISC_TRUE, &b); 1287 if (result != ISC_R_SUCCESS) 1288 goto cleanup_origin; 1289 isc_buffer_putuint8(&b, 0); 1290 1291 sdb->zone = isc_mem_strdup(mctx, zonestr); 1292 if (sdb->zone == NULL) { 1293 result = ISC_R_NOMEMORY; 1294 goto cleanup_origin; 1295 } 1296 1297 sdb->dbdata = NULL; 1298 if (imp->methods->create != NULL) { 1299 MAYBE_LOCK(sdb); 1300 result = imp->methods->create(sdb->zone, argc, argv, 1301 imp->driverdata, &sdb->dbdata); 1302 MAYBE_UNLOCK(sdb); 1303 if (result != ISC_R_SUCCESS) 1304 goto cleanup_zonestr; 1305 } 1306 1307 sdb->references = 1; 1308 1309 sdb->common.magic = DNS_DB_MAGIC; 1310 sdb->common.impmagic = SDB_MAGIC; 1311 1312 *dbp = (dns_db_t *)sdb; 1313 1314 return (ISC_R_SUCCESS); 1315 1316 cleanup_zonestr: 1317 isc_mem_free(mctx, sdb->zone); 1318 cleanup_origin: 1319 dns_name_free(&sdb->common.origin, mctx); 1320 cleanup_lock: 1321 isc_mutex_destroy(&sdb->lock); 1322 cleanup_mctx: 1323 isc_mem_put(mctx, sdb, sizeof(dns_sdb_t)); 1324 isc_mem_detach(&mctx); 1325 1326 return (result); 1327} 1328 1329 1330/* 1331 * Rdataset Methods 1332 */ 1333 1334static void 1335disassociate(dns_rdataset_t *rdataset) { 1336 dns_dbnode_t *node = rdataset->private5; 1337 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node; 1338 dns_db_t *db = (dns_db_t *) sdbnode->sdb; 1339 1340 detachnode(db, &node); 1341 isc__rdatalist_disassociate(rdataset); 1342} 1343 1344static void 1345rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 1346 dns_dbnode_t *node = source->private5; 1347 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node; 1348 dns_db_t *db = (dns_db_t *) sdbnode->sdb; 1349 dns_dbnode_t *tempdb = NULL; 1350 1351 isc__rdatalist_clone(source, target); 1352 attachnode(db, node, &tempdb); 1353 source->private5 = tempdb; 1354} 1355 1356static dns_rdatasetmethods_t methods = { 1357 disassociate, 1358 isc__rdatalist_first, 1359 isc__rdatalist_next, 1360 isc__rdatalist_current, 1361 rdataset_clone, 1362 isc__rdatalist_count, 1363 isc__rdatalist_addnoqname, 1364 isc__rdatalist_getnoqname 1365}; 1366 1367static void 1368list_tordataset(dns_rdatalist_t *rdatalist, 1369 dns_db_t *db, dns_dbnode_t *node, 1370 dns_rdataset_t *rdataset) 1371{ 1372 /* 1373 * The sdb rdataset is an rdatalist with some additions. 1374 * - private1 & private2 are used by the rdatalist. 1375 * - private3 & private 4 are unused. 1376 * - private5 is the node. 1377 */ 1378 1379 /* This should never fail. */ 1380 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == 1381 ISC_R_SUCCESS); 1382 1383 rdataset->methods = &methods; 1384 dns_db_attachnode(db, node, &rdataset->private5); 1385} 1386 1387/* 1388 * Database Iterator Methods 1389 */ 1390static void 1391dbiterator_destroy(dns_dbiterator_t **iteratorp) { 1392 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp); 1393 dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db; 1394 1395 while (!ISC_LIST_EMPTY(sdbiter->nodelist)) { 1396 dns_sdbnode_t *node; 1397 node = ISC_LIST_HEAD(sdbiter->nodelist); 1398 ISC_LIST_UNLINK(sdbiter->nodelist, node, link); 1399 destroynode(node); 1400 } 1401 1402 dns_db_detach(&sdbiter->common.db); 1403 isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t)); 1404 1405 *iteratorp = NULL; 1406} 1407 1408static isc_result_t 1409dbiterator_first(dns_dbiterator_t *iterator) { 1410 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1411 1412 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist); 1413 if (sdbiter->current == NULL) 1414 return (ISC_R_NOMORE); 1415 else 1416 return (ISC_R_SUCCESS); 1417} 1418 1419static isc_result_t 1420dbiterator_last(dns_dbiterator_t *iterator) { 1421 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1422 1423 sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist); 1424 if (sdbiter->current == NULL) 1425 return (ISC_R_NOMORE); 1426 else 1427 return (ISC_R_SUCCESS); 1428} 1429 1430static isc_result_t 1431dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) { 1432 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1433 1434 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist); 1435 while (sdbiter->current != NULL) 1436 if (dns_name_equal(sdbiter->current->name, name)) 1437 return (ISC_R_SUCCESS); 1438 return (ISC_R_NOTFOUND); 1439} 1440 1441static isc_result_t 1442dbiterator_prev(dns_dbiterator_t *iterator) { 1443 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1444 1445 sdbiter->current = ISC_LIST_PREV(sdbiter->current, link); 1446 if (sdbiter->current == NULL) 1447 return (ISC_R_NOMORE); 1448 else 1449 return (ISC_R_SUCCESS); 1450} 1451 1452static isc_result_t 1453dbiterator_next(dns_dbiterator_t *iterator) { 1454 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1455 1456 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link); 1457 if (sdbiter->current == NULL) 1458 return (ISC_R_NOMORE); 1459 else 1460 return (ISC_R_SUCCESS); 1461} 1462 1463static isc_result_t 1464dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, 1465 dns_name_t *name) 1466{ 1467 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; 1468 1469 attachnode(iterator->db, sdbiter->current, nodep); 1470 if (name != NULL) 1471 return (dns_name_copy(sdbiter->current->name, name, NULL)); 1472 return (ISC_R_SUCCESS); 1473} 1474 1475static isc_result_t 1476dbiterator_pause(dns_dbiterator_t *iterator) { 1477 UNUSED(iterator); 1478 return (ISC_R_SUCCESS); 1479} 1480 1481static isc_result_t 1482dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) { 1483 UNUSED(iterator); 1484 return (dns_name_copy(dns_rootname, name, NULL)); 1485} 1486 1487/* 1488 * Rdataset Iterator Methods 1489 */ 1490 1491static void 1492rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { 1493 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp); 1494 detachnode(sdbiterator->common.db, &sdbiterator->common.node); 1495 isc_mem_put(sdbiterator->common.db->mctx, sdbiterator, 1496 sizeof(sdb_rdatasetiter_t)); 1497 *iteratorp = NULL; 1498} 1499 1500static isc_result_t 1501rdatasetiter_first(dns_rdatasetiter_t *iterator) { 1502 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator; 1503 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node; 1504 1505 if (ISC_LIST_EMPTY(sdbnode->lists)) 1506 return (ISC_R_NOMORE); 1507 sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists); 1508 return (ISC_R_SUCCESS); 1509} 1510 1511static isc_result_t 1512rdatasetiter_next(dns_rdatasetiter_t *iterator) { 1513 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator; 1514 1515 sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link); 1516 if (sdbiterator->current == NULL) 1517 return (ISC_R_NOMORE); 1518 else 1519 return (ISC_R_SUCCESS); 1520} 1521 1522static void 1523rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) { 1524 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator; 1525 1526 list_tordataset(sdbiterator->current, iterator->db, iterator->node, 1527 rdataset); 1528} 1529