sdb.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id$ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <string.h>
00025 
00026 #include <isc/buffer.h>
00027 #include <isc/lex.h>
00028 #include <isc/log.h>
00029 #include <isc/magic.h>
00030 #include <isc/mem.h>
00031 #include <isc/once.h>
00032 #include <isc/print.h>
00033 #include <isc/region.h>
00034 #include <isc/util.h>
00035 
00036 #include <dns/callbacks.h>
00037 #include <dns/db.h>
00038 #include <dns/dbiterator.h>
00039 #include <dns/fixedname.h>
00040 #include <dns/log.h>
00041 #include <dns/rdata.h>
00042 #include <dns/rdatalist.h>
00043 #include <dns/rdataset.h>
00044 #include <dns/rdatasetiter.h>
00045 #include <dns/rdatatype.h>
00046 #include <dns/result.h>
00047 #include <dns/sdb.h>
00048 #include <dns/types.h>
00049 
00050 #include "rdatalist_p.h"
00051 
00052 struct dns_sdbimplementation {
00053         const dns_sdbmethods_t          *methods;
00054         void                            *driverdata;
00055         unsigned int                    flags;
00056         isc_mem_t                       *mctx;
00057         isc_mutex_t                     driverlock;
00058         dns_dbimplementation_t          *dbimp;
00059 };
00060 
00061 struct dns_sdb {
00062         /* Unlocked */
00063         dns_db_t                        common;
00064         char                            *zone;
00065         dns_sdbimplementation_t         *implementation;
00066         void                            *dbdata;
00067         isc_mutex_t                     lock;
00068         /* Locked */
00069         unsigned int                    references;
00070 };
00071 
00072 struct dns_sdblookup {
00073         /* Unlocked */
00074         unsigned int                    magic;
00075         dns_sdb_t                       *sdb;
00076         ISC_LIST(dns_rdatalist_t)       lists;
00077         ISC_LIST(isc_buffer_t)          buffers;
00078         dns_name_t                      *name;
00079         ISC_LINK(dns_sdblookup_t)       link;
00080         isc_mutex_t                     lock;
00081         dns_rdatacallbacks_t            callbacks;
00082         /* Locked */
00083         unsigned int                    references;
00084 };
00085 
00086 typedef struct dns_sdblookup dns_sdbnode_t;
00087 
00088 struct dns_sdballnodes {
00089         dns_dbiterator_t                common;
00090         ISC_LIST(dns_sdbnode_t)         nodelist;
00091         dns_sdbnode_t                   *current;
00092         dns_sdbnode_t                   *origin;
00093 };
00094 
00095 typedef dns_sdballnodes_t sdb_dbiterator_t;
00096 
00097 typedef struct sdb_rdatasetiter {
00098         dns_rdatasetiter_t              common;
00099         dns_rdatalist_t                 *current;
00100 } sdb_rdatasetiter_t;
00101 
00102 #define SDB_MAGIC               ISC_MAGIC('S', 'D', 'B', '-')
00103 
00104 /*%
00105  * Note that "impmagic" is not the first four bytes of the struct, so
00106  * ISC_MAGIC_VALID cannot be used.
00107  */
00108 #define VALID_SDB(sdb)          ((sdb) != NULL && \
00109                                  (sdb)->common.impmagic == SDB_MAGIC)
00110 
00111 #define SDBLOOKUP_MAGIC         ISC_MAGIC('S','D','B','L')
00112 #define VALID_SDBLOOKUP(sdbl)   ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)
00113 #define VALID_SDBNODE(sdbn)     VALID_SDBLOOKUP(sdbn)
00114 
00115 /* These values are taken from RFC1537 */
00116 #define SDB_DEFAULT_REFRESH     (60 * 60 * 8)
00117 #define SDB_DEFAULT_RETRY       (60 * 60 * 2)
00118 #define SDB_DEFAULT_EXPIRE      (60 * 60 * 24 * 7)
00119 #define SDB_DEFAULT_MINIMUM     (60 * 60 * 24)
00120 
00121 /* This is a reasonable value */
00122 #define SDB_DEFAULT_TTL         (60 * 60 * 24)
00123 
00124 #ifdef __COVERITY__
00125 #define MAYBE_LOCK(sdb) LOCK(&sdb->implementation->driverlock)
00126 #define MAYBE_UNLOCK(sdb) UNLOCK(&sdb->implementation->driverlock)
00127 #else
00128 #define MAYBE_LOCK(sdb)                                                 \
00129         do {                                                            \
00130                 unsigned int flags = sdb->implementation->flags;        \
00131                 if ((flags & DNS_SDBFLAG_THREADSAFE) == 0)              \
00132                         LOCK(&sdb->implementation->driverlock);         \
00133         } while (0)
00134 
00135 #define MAYBE_UNLOCK(sdb)                                               \
00136         do {                                                            \
00137                 unsigned int flags = sdb->implementation->flags;        \
00138                 if ((flags & DNS_SDBFLAG_THREADSAFE) == 0)              \
00139                         UNLOCK(&sdb->implementation->driverlock);       \
00140         } while (0)
00141 #endif
00142 
00143 static int dummy;
00144 
00145 static isc_result_t dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin,
00146                                    dns_dbtype_t type, dns_rdataclass_t rdclass,
00147                                    unsigned int argc, char *argv[],
00148                                    void *driverarg, dns_db_t **dbp);
00149 
00150 static isc_result_t findrdataset(dns_db_t *db, dns_dbnode_t *node,
00151                                  dns_dbversion_t *version,
00152                                  dns_rdatatype_t type, dns_rdatatype_t covers,
00153                                  isc_stdtime_t now, dns_rdataset_t *rdataset,
00154                                  dns_rdataset_t *sigrdataset);
00155 
00156 static isc_result_t createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep);
00157 
00158 static void destroynode(dns_sdbnode_t *node);
00159 
00160 static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
00161 
00162 
00163 static void list_tordataset(dns_rdatalist_t *rdatalist,
00164                             dns_db_t *db, dns_dbnode_t *node,
00165                             dns_rdataset_t *rdataset);
00166 
00167 static void             dbiterator_destroy(dns_dbiterator_t **iteratorp);
00168 static isc_result_t     dbiterator_first(dns_dbiterator_t *iterator);
00169 static isc_result_t     dbiterator_last(dns_dbiterator_t *iterator);
00170 static isc_result_t     dbiterator_seek(dns_dbiterator_t *iterator,
00171                                         dns_name_t *name);
00172 static isc_result_t     dbiterator_prev(dns_dbiterator_t *iterator);
00173 static isc_result_t     dbiterator_next(dns_dbiterator_t *iterator);
00174 static isc_result_t     dbiterator_current(dns_dbiterator_t *iterator,
00175                                            dns_dbnode_t **nodep,
00176                                            dns_name_t *name);
00177 static isc_result_t     dbiterator_pause(dns_dbiterator_t *iterator);
00178 static isc_result_t     dbiterator_origin(dns_dbiterator_t *iterator,
00179                                           dns_name_t *name);
00180 
00181 static dns_dbiteratormethods_t dbiterator_methods = {
00182         dbiterator_destroy,
00183         dbiterator_first,
00184         dbiterator_last,
00185         dbiterator_seek,
00186         dbiterator_prev,
00187         dbiterator_next,
00188         dbiterator_current,
00189         dbiterator_pause,
00190         dbiterator_origin
00191 };
00192 
00193 static void             rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
00194 static isc_result_t     rdatasetiter_first(dns_rdatasetiter_t *iterator);
00195 static isc_result_t     rdatasetiter_next(dns_rdatasetiter_t *iterator);
00196 static void             rdatasetiter_current(dns_rdatasetiter_t *iterator,
00197                                              dns_rdataset_t *rdataset);
00198 
00199 static dns_rdatasetitermethods_t rdatasetiter_methods = {
00200         rdatasetiter_destroy,
00201         rdatasetiter_first,
00202         rdatasetiter_next,
00203         rdatasetiter_current
00204 };
00205 
00206 /*
00207  * Functions used by implementors of simple databases
00208  */
00209 isc_result_t
00210 dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
00211                  void *driverdata, unsigned int flags, isc_mem_t *mctx,
00212                  dns_sdbimplementation_t **sdbimp)
00213 {
00214         dns_sdbimplementation_t *imp;
00215         isc_result_t result;
00216 
00217         REQUIRE(drivername != NULL);
00218         REQUIRE(methods != NULL);
00219         REQUIRE(methods->lookup != NULL || methods->lookup2 != NULL);
00220         REQUIRE(mctx != NULL);
00221         REQUIRE(sdbimp != NULL && *sdbimp == NULL);
00222         REQUIRE((flags & ~(DNS_SDBFLAG_RELATIVEOWNER |
00223                            DNS_SDBFLAG_RELATIVERDATA |
00224                            DNS_SDBFLAG_THREADSAFE|
00225                            DNS_SDBFLAG_DNS64)) == 0);
00226 
00227         imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t));
00228         if (imp == NULL)
00229                 return (ISC_R_NOMEMORY);
00230         imp->methods = methods;
00231         imp->driverdata = driverdata;
00232         imp->flags = flags;
00233         imp->mctx = NULL;
00234         isc_mem_attach(mctx, &imp->mctx);
00235         result = isc_mutex_init(&imp->driverlock);
00236         if (result != ISC_R_SUCCESS)
00237                 goto cleanup_mctx;
00238 
00239         imp->dbimp = NULL;
00240         result = dns_db_register(drivername, dns_sdb_create, imp, mctx,
00241                                  &imp->dbimp);
00242         if (result != ISC_R_SUCCESS)
00243                 goto cleanup_mutex;
00244         *sdbimp = imp;
00245 
00246         return (ISC_R_SUCCESS);
00247 
00248  cleanup_mutex:
00249         DESTROYLOCK(&imp->driverlock);
00250  cleanup_mctx:
00251         isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
00252         return (result);
00253 }
00254 
00255 void
00256 dns_sdb_unregister(dns_sdbimplementation_t **sdbimp) {
00257         dns_sdbimplementation_t *imp;
00258         isc_mem_t *mctx;
00259 
00260         REQUIRE(sdbimp != NULL && *sdbimp != NULL);
00261 
00262         imp = *sdbimp;
00263         dns_db_unregister(&imp->dbimp);
00264         DESTROYLOCK(&imp->driverlock);
00265 
00266         mctx = imp->mctx;
00267         isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
00268         isc_mem_detach(&mctx);
00269 
00270         *sdbimp = NULL;
00271 }
00272 
00273 static inline unsigned int
00274 initial_size(unsigned int len) {
00275         unsigned int size;
00276 
00277         for (size = 1024; size < (64 * 1024); size *= 2)
00278                 if (len < size)
00279                         return (size);
00280         return (65535);
00281 }
00282 
00283 isc_result_t
00284 dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval,
00285                  dns_ttl_t ttl, const unsigned char *rdatap,
00286                  unsigned int rdlen)
00287 {
00288         dns_rdatalist_t *rdatalist;
00289         dns_rdata_t *rdata;
00290         isc_buffer_t *rdatabuf = NULL;
00291         isc_result_t result;
00292         isc_mem_t *mctx;
00293         isc_region_t region;
00294 
00295         mctx = lookup->sdb->common.mctx;
00296 
00297         rdatalist = ISC_LIST_HEAD(lookup->lists);
00298         while (rdatalist != NULL) {
00299                 if (rdatalist->type == typeval)
00300                         break;
00301                 rdatalist = ISC_LIST_NEXT(rdatalist, link);
00302         }
00303 
00304         if (rdatalist == NULL) {
00305                 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
00306                 if (rdatalist == NULL)
00307                         return (ISC_R_NOMEMORY);
00308                 dns_rdatalist_init(rdatalist);
00309                 rdatalist->rdclass = lookup->sdb->common.rdclass;
00310                 rdatalist->type = typeval;
00311                 rdatalist->ttl = ttl;
00312                 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
00313         } else
00314                 if (rdatalist->ttl != ttl)
00315                         return (DNS_R_BADTTL);
00316 
00317         rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
00318         if (rdata == NULL)
00319                 return (ISC_R_NOMEMORY);
00320 
00321         result = isc_buffer_allocate(mctx, &rdatabuf, rdlen);
00322         if (result != ISC_R_SUCCESS)
00323                 goto failure;
00324         DE_CONST(rdatap, region.base);
00325         region.length = rdlen;
00326         isc_buffer_copyregion(rdatabuf, &region);
00327         isc_buffer_usedregion(rdatabuf, &region);
00328         dns_rdata_init(rdata);
00329         dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type,
00330                              &region);
00331         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
00332         ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
00333         rdata = NULL;
00334 
00335  failure:
00336         if (rdata != NULL)
00337                 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
00338         return (result);
00339 }
00340 
00341 isc_result_t
00342 dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
00343               const char *data)
00344 {
00345         unsigned int datalen;
00346         dns_rdatatype_t typeval;
00347         isc_textregion_t r;
00348         isc_lex_t *lex = NULL;
00349         isc_result_t result;
00350         unsigned char *p = NULL;
00351         unsigned int size = 0; /* Init to suppress compiler warning */
00352         isc_mem_t *mctx;
00353         dns_sdbimplementation_t *imp;
00354         dns_name_t *origin;
00355         isc_buffer_t b;
00356         isc_buffer_t rb;
00357 
00358         REQUIRE(VALID_SDBLOOKUP(lookup));
00359         REQUIRE(type != NULL);
00360         REQUIRE(data != NULL);
00361 
00362         mctx = lookup->sdb->common.mctx;
00363 
00364         DE_CONST(type, r.base);
00365         r.length = strlen(type);
00366         result = dns_rdatatype_fromtext(&typeval, &r);
00367         if (result != ISC_R_SUCCESS)
00368                 return (result);
00369 
00370         imp = lookup->sdb->implementation;
00371         if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
00372                 origin = &lookup->sdb->common.origin;
00373         else
00374                 origin = dns_rootname;
00375 
00376         result = isc_lex_create(mctx, 64, &lex);
00377         if (result != ISC_R_SUCCESS)
00378                 goto failure;
00379 
00380         datalen = strlen(data);
00381         size = initial_size(datalen);
00382         do {
00383                 isc_buffer_constinit(&b, data, datalen);
00384                 isc_buffer_add(&b, datalen);
00385                 result = isc_lex_openbuffer(lex, &b);
00386                 if (result != ISC_R_SUCCESS)
00387                         goto failure;
00388 
00389                 if (size >= 65535)
00390                         size = 65535;
00391                 p = isc_mem_get(mctx, size);
00392                 if (p == NULL) {
00393                         result = ISC_R_NOMEMORY;
00394                         goto failure;
00395                 }
00396                 isc_buffer_init(&rb, p, size);
00397                 result = dns_rdata_fromtext(NULL,
00398                                             lookup->sdb->common.rdclass,
00399                                             typeval, lex,
00400                                             origin, 0,
00401                                             mctx, &rb,
00402                                             &lookup->callbacks);
00403                 if (result != ISC_R_NOSPACE)
00404                         break;
00405 
00406                 /*
00407                  * Is the RR too big?
00408                  */
00409                 if (size >= 65535)
00410                         break;
00411                 isc_mem_put(mctx, p, size);
00412                 p = NULL;
00413                 size *= 2;
00414         } while (result == ISC_R_NOSPACE);
00415 
00416         if (result != ISC_R_SUCCESS)
00417                 goto failure;
00418 
00419         result = dns_sdb_putrdata(lookup, typeval, ttl,
00420                                   isc_buffer_base(&rb),
00421                                   isc_buffer_usedlength(&rb));
00422  failure:
00423         if (p != NULL)
00424                 isc_mem_put(mctx, p, size);
00425         if (lex != NULL)
00426                 isc_lex_destroy(&lex);
00427 
00428         return (result);
00429 }
00430 
00431 static isc_result_t
00432 getnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) {
00433         dns_name_t *newname, *origin;
00434         dns_fixedname_t fnewname;
00435         dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db;
00436         dns_sdbimplementation_t *imp = sdb->implementation;
00437         dns_sdbnode_t *sdbnode;
00438         isc_mem_t *mctx = sdb->common.mctx;
00439         isc_buffer_t b;
00440         isc_result_t result;
00441 
00442         dns_fixedname_init(&fnewname);
00443         newname = dns_fixedname_name(&fnewname);
00444 
00445         if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
00446                 origin = &sdb->common.origin;
00447         else
00448                 origin = dns_rootname;
00449         isc_buffer_constinit(&b, name, strlen(name));
00450         isc_buffer_add(&b, strlen(name));
00451 
00452         result = dns_name_fromtext(newname, &b, origin, 0, NULL);
00453         if (result != ISC_R_SUCCESS)
00454                 return (result);
00455 
00456         if (allnodes->common.relative_names) {
00457                 /* All names are relative to the root */
00458                 unsigned int nlabels = dns_name_countlabels(newname);
00459                 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
00460         }
00461 
00462         sdbnode = ISC_LIST_HEAD(allnodes->nodelist);
00463         if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) {
00464                 sdbnode = NULL;
00465                 result = createnode(sdb, &sdbnode);
00466                 if (result != ISC_R_SUCCESS)
00467                         return (result);
00468                 sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t));
00469                 if (sdbnode->name == NULL) {
00470                         destroynode(sdbnode);
00471                         return (ISC_R_NOMEMORY);
00472                 }
00473                 dns_name_init(sdbnode->name, NULL);
00474                 result = dns_name_dup(newname, mctx, sdbnode->name);
00475                 if (result != ISC_R_SUCCESS) {
00476                         isc_mem_put(mctx, sdbnode->name, sizeof(dns_name_t));
00477                         destroynode(sdbnode);
00478                         return (result);
00479                 }
00480                 ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link);
00481                 if (allnodes->origin == NULL &&
00482                     dns_name_equal(newname, &sdb->common.origin))
00483                         allnodes->origin = sdbnode;
00484         }
00485         *nodep = sdbnode;
00486         return (ISC_R_SUCCESS);
00487 }
00488 
00489 isc_result_t
00490 dns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name,
00491                    const char *type, dns_ttl_t ttl, const char *data)
00492 {
00493         isc_result_t result;
00494         dns_sdbnode_t *sdbnode = NULL;
00495         result = getnode(allnodes, name, &sdbnode);
00496         if (result != ISC_R_SUCCESS)
00497                 return (result);
00498         return (dns_sdb_putrr(sdbnode, type, ttl, data));
00499 }
00500 
00501 isc_result_t
00502 dns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name,
00503                       dns_rdatatype_t type, dns_ttl_t ttl,
00504                       const void *rdata, unsigned int rdlen)
00505 {
00506         isc_result_t result;
00507         dns_sdbnode_t *sdbnode = NULL;
00508         result = getnode(allnodes, name, &sdbnode);
00509         if (result != ISC_R_SUCCESS)
00510                 return (result);
00511         return (dns_sdb_putrdata(sdbnode, type, ttl, rdata, rdlen));
00512 }
00513 
00514 isc_result_t
00515 dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
00516                isc_uint32_t serial)
00517 {
00518         char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
00519         int n;
00520 
00521         REQUIRE(mname != NULL);
00522         REQUIRE(rname != NULL);
00523 
00524         n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u",
00525                      mname, rname, serial,
00526                      SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY,
00527                      SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM);
00528         if (n >= (int)sizeof(str) || n < 0)
00529                 return (ISC_R_NOSPACE);
00530         return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));
00531 }
00532 
00533 /*
00534  * DB routines
00535  */
00536 
00537 static void
00538 attach(dns_db_t *source, dns_db_t **targetp) {
00539         dns_sdb_t *sdb = (dns_sdb_t *) source;
00540 
00541         REQUIRE(VALID_SDB(sdb));
00542 
00543         LOCK(&sdb->lock);
00544         REQUIRE(sdb->references > 0);
00545         sdb->references++;
00546         UNLOCK(&sdb->lock);
00547 
00548         *targetp = source;
00549 }
00550 
00551 static void
00552 destroy(dns_sdb_t *sdb) {
00553         isc_mem_t *mctx;
00554         dns_sdbimplementation_t *imp = sdb->implementation;
00555 
00556         mctx = sdb->common.mctx;
00557 
00558         if (imp->methods->destroy != NULL) {
00559                 MAYBE_LOCK(sdb);
00560                 imp->methods->destroy(sdb->zone, imp->driverdata,
00561                                       &sdb->dbdata);
00562                 MAYBE_UNLOCK(sdb);
00563         }
00564 
00565         isc_mem_free(mctx, sdb->zone);
00566         DESTROYLOCK(&sdb->lock);
00567 
00568         sdb->common.magic = 0;
00569         sdb->common.impmagic = 0;
00570 
00571         dns_name_free(&sdb->common.origin, mctx);
00572 
00573         isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
00574         isc_mem_detach(&mctx);
00575 }
00576 
00577 static void
00578 detach(dns_db_t **dbp) {
00579         dns_sdb_t *sdb = (dns_sdb_t *)(*dbp);
00580         isc_boolean_t need_destroy = ISC_FALSE;
00581 
00582         REQUIRE(VALID_SDB(sdb));
00583         LOCK(&sdb->lock);
00584         REQUIRE(sdb->references > 0);
00585         sdb->references--;
00586         if (sdb->references == 0)
00587                 need_destroy = ISC_TRUE;
00588         UNLOCK(&sdb->lock);
00589 
00590         if (need_destroy)
00591                 destroy(sdb);
00592 
00593         *dbp = NULL;
00594 }
00595 
00596 static isc_result_t
00597 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
00598         UNUSED(db);
00599         UNUSED(callbacks);
00600         return (ISC_R_NOTIMPLEMENTED);
00601 }
00602 
00603 static isc_result_t
00604 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
00605         UNUSED(db);
00606         UNUSED(callbacks);
00607         return (ISC_R_NOTIMPLEMENTED);
00608 }
00609 
00610 static isc_result_t
00611 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
00612      dns_masterformat_t masterformat) {
00613         UNUSED(db);
00614         UNUSED(version);
00615         UNUSED(filename);
00616         UNUSED(masterformat);
00617         return (ISC_R_NOTIMPLEMENTED);
00618 }
00619 
00620 static void
00621 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
00622         REQUIRE(versionp != NULL && *versionp == NULL);
00623 
00624         UNUSED(db);
00625 
00626         *versionp = (void *) &dummy;
00627         return;
00628 }
00629 
00630 static isc_result_t
00631 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
00632         UNUSED(db);
00633         UNUSED(versionp);
00634 
00635         return (ISC_R_NOTIMPLEMENTED);
00636 }
00637 
00638 static void
00639 attachversion(dns_db_t *db, dns_dbversion_t *source,
00640               dns_dbversion_t **targetp)
00641 {
00642         REQUIRE(source != NULL && source == (void *) &dummy);
00643         REQUIRE(targetp != NULL && *targetp == NULL);
00644 
00645         UNUSED(db);
00646         *targetp = source;
00647         return;
00648 }
00649 
00650 static void
00651 closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
00652         REQUIRE(versionp != NULL && *versionp == (void *) &dummy);
00653         REQUIRE(commit == ISC_FALSE);
00654 
00655         UNUSED(db);
00656         UNUSED(commit);
00657 
00658         *versionp = NULL;
00659 }
00660 
00661 static isc_result_t
00662 createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) {
00663         dns_sdbnode_t *node;
00664         isc_result_t result;
00665 
00666         node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t));
00667         if (node == NULL)
00668                 return (ISC_R_NOMEMORY);
00669 
00670         node->sdb = NULL;
00671         attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb);
00672         ISC_LIST_INIT(node->lists);
00673         ISC_LIST_INIT(node->buffers);
00674         ISC_LINK_INIT(node, link);
00675         node->name = NULL;
00676         result = isc_mutex_init(&node->lock);
00677         if (result != ISC_R_SUCCESS) {
00678                 isc_mem_put(sdb->common.mctx, node, sizeof(dns_sdbnode_t));
00679                 return (result);
00680         }
00681         dns_rdatacallbacks_init(&node->callbacks);
00682         node->references = 1;
00683         node->magic = SDBLOOKUP_MAGIC;
00684 
00685         *nodep = node;
00686         return (ISC_R_SUCCESS);
00687 }
00688 
00689 static void
00690 destroynode(dns_sdbnode_t *node) {
00691         dns_rdatalist_t *list;
00692         dns_rdata_t *rdata;
00693         isc_buffer_t *b;
00694         dns_sdb_t *sdb;
00695         isc_mem_t *mctx;
00696 
00697         sdb = node->sdb;
00698         mctx = sdb->common.mctx;
00699 
00700         while (!ISC_LIST_EMPTY(node->lists)) {
00701                 list = ISC_LIST_HEAD(node->lists);
00702                 while (!ISC_LIST_EMPTY(list->rdata)) {
00703                         rdata = ISC_LIST_HEAD(list->rdata);
00704                         ISC_LIST_UNLINK(list->rdata, rdata, link);
00705                         isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
00706                 }
00707                 ISC_LIST_UNLINK(node->lists, list, link);
00708                 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
00709         }
00710 
00711         while (!ISC_LIST_EMPTY(node->buffers)) {
00712                 b = ISC_LIST_HEAD(node->buffers);
00713                 ISC_LIST_UNLINK(node->buffers, b, link);
00714                 isc_buffer_free(&b);
00715         }
00716 
00717         if (node->name != NULL) {
00718                 dns_name_free(node->name, mctx);
00719                 isc_mem_put(mctx, node->name, sizeof(dns_name_t));
00720         }
00721         DESTROYLOCK(&node->lock);
00722         node->magic = 0;
00723         isc_mem_put(mctx, node, sizeof(dns_sdbnode_t));
00724         detach((dns_db_t **) (void *)&sdb);
00725 }
00726 
00727 static isc_result_t
00728 findnodeext(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
00729             dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
00730             dns_dbnode_t **nodep)
00731 {
00732         dns_sdb_t *sdb = (dns_sdb_t *)db;
00733         dns_sdbnode_t *node = NULL;
00734         isc_result_t result;
00735         isc_buffer_t b;
00736         char namestr[DNS_NAME_MAXTEXT + 1];
00737         isc_boolean_t isorigin;
00738         dns_sdbimplementation_t *imp;
00739         dns_name_t relname;
00740         unsigned int labels;
00741 
00742         REQUIRE(VALID_SDB(sdb));
00743         REQUIRE(create == ISC_FALSE);
00744         REQUIRE(nodep != NULL && *nodep == NULL);
00745 
00746         UNUSED(name);
00747         UNUSED(create);
00748 
00749         imp = sdb->implementation;
00750 
00751         isorigin = dns_name_equal(name, &sdb->common.origin);
00752 
00753         if (imp->methods->lookup2 != NULL) {
00754                 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
00755                         labels = dns_name_countlabels(name) -
00756                                  dns_name_countlabels(&db->origin);
00757                         dns_name_init(&relname, NULL);
00758                         dns_name_getlabelsequence(name, 0, labels, &relname);
00759                         name = &relname;
00760                 }
00761         } else {
00762                 isc_buffer_init(&b, namestr, sizeof(namestr));
00763                 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
00764 
00765                         labels = dns_name_countlabels(name) -
00766                                  dns_name_countlabels(&db->origin);
00767                         dns_name_init(&relname, NULL);
00768                         dns_name_getlabelsequence(name, 0, labels, &relname);
00769                         result = dns_name_totext(&relname, ISC_TRUE, &b);
00770                         if (result != ISC_R_SUCCESS)
00771                                 return (result);
00772                 } else {
00773                         result = dns_name_totext(name, ISC_TRUE, &b);
00774                         if (result != ISC_R_SUCCESS)
00775                                 return (result);
00776                 }
00777                 isc_buffer_putuint8(&b, 0);
00778         }
00779 
00780         result = createnode(sdb, &node);
00781         if (result != ISC_R_SUCCESS)
00782                 return (result);
00783 
00784         MAYBE_LOCK(sdb);
00785         if (imp->methods->lookup2 != NULL)
00786                 result = imp->methods->lookup2(&sdb->common.origin, name,
00787                                                sdb->dbdata, node, methods,
00788                                                clientinfo);
00789         else
00790                 result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata,
00791                                               node, methods, clientinfo);
00792         MAYBE_UNLOCK(sdb);
00793         if (result != ISC_R_SUCCESS &&
00794             !(result == ISC_R_NOTFOUND &&
00795               isorigin && imp->methods->authority != NULL))
00796         {
00797                 destroynode(node);
00798                 return (result);
00799         }
00800 
00801         if (isorigin && imp->methods->authority != NULL) {
00802                 MAYBE_LOCK(sdb);
00803                 result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
00804                 MAYBE_UNLOCK(sdb);
00805                 if (result != ISC_R_SUCCESS) {
00806                         destroynode(node);
00807                         return (result);
00808                 }
00809         }
00810 
00811         *nodep = node;
00812         return (ISC_R_SUCCESS);
00813 }
00814 
00815 static isc_result_t
00816 findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
00817         dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
00818         dns_dbnode_t **nodep, dns_name_t *foundname,
00819         dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
00820         dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
00821 {
00822         dns_sdb_t *sdb = (dns_sdb_t *)db;
00823         dns_dbnode_t *node = NULL;
00824         dns_fixedname_t fname;
00825         dns_rdataset_t xrdataset;
00826         dns_name_t *xname;
00827         unsigned int nlabels, olabels;
00828         isc_result_t result;
00829         unsigned int i;
00830         unsigned int flags;
00831 
00832         REQUIRE(VALID_SDB(sdb));
00833         REQUIRE(nodep == NULL || *nodep == NULL);
00834         REQUIRE(version == NULL || version == (void *) &dummy);
00835 
00836         UNUSED(options);
00837 
00838         if (!dns_name_issubdomain(name, &db->origin))
00839                 return (DNS_R_NXDOMAIN);
00840 
00841         olabels = dns_name_countlabels(&db->origin);
00842         nlabels = dns_name_countlabels(name);
00843 
00844         dns_fixedname_init(&fname);
00845         xname = dns_fixedname_name(&fname);
00846 
00847         if (rdataset == NULL) {
00848                 dns_rdataset_init(&xrdataset);
00849                 rdataset = &xrdataset;
00850         }
00851 
00852         result = DNS_R_NXDOMAIN;
00853         flags = sdb->implementation->flags;
00854         i = (flags & DNS_SDBFLAG_DNS64) != 0 ? nlabels : olabels;
00855         for (; i <= nlabels; i++) {
00856                 /*
00857                  * Look up the next label.
00858                  */
00859                 dns_name_getlabelsequence(name, nlabels - i, i, xname);
00860                 result = findnodeext(db, xname, ISC_FALSE, methods,
00861                                      clientinfo, &node);
00862                 if (result == ISC_R_NOTFOUND) {
00863                         /*
00864                          * No data at zone apex?
00865                          */
00866                         if (i == olabels)
00867                                 return (DNS_R_BADDB);
00868                         result = DNS_R_NXDOMAIN;
00869                         continue;
00870                 }
00871                 if (result != ISC_R_SUCCESS)
00872                         return (result);
00873 
00874                 /*
00875                  * DNS64 zone's don't have DNAME or NS records.
00876                  */
00877                 if ((flags & DNS_SDBFLAG_DNS64) != 0)
00878                         goto skip;
00879 
00880                 /*
00881                  * DNS64 zone's don't have DNAME or NS records.
00882                  */
00883                 if ((flags & DNS_SDBFLAG_DNS64) != 0)
00884                         goto skip;
00885 
00886                 /*
00887                  * Look for a DNAME at the current label, unless this is
00888                  * the qname.
00889                  */
00890                 if (i < nlabels) {
00891                         result = findrdataset(db, node, version,
00892                                               dns_rdatatype_dname,
00893                                               0, now, rdataset, sigrdataset);
00894                         if (result == ISC_R_SUCCESS) {
00895                                 result = DNS_R_DNAME;
00896                                 break;
00897                         }
00898                 }
00899 
00900                 /*
00901                  * Look for an NS at the current label, unless this is the
00902                  * origin or glue is ok.
00903                  */
00904                 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
00905                         result = findrdataset(db, node, version,
00906                                               dns_rdatatype_ns,
00907                                               0, now, rdataset, sigrdataset);
00908                         if (result == ISC_R_SUCCESS) {
00909                                 if (i == nlabels && type == dns_rdatatype_any)
00910                                 {
00911                                         result = DNS_R_ZONECUT;
00912                                         dns_rdataset_disassociate(rdataset);
00913                                         if (sigrdataset != NULL &&
00914                                             dns_rdataset_isassociated
00915                                                         (sigrdataset)) {
00916                                                 dns_rdataset_disassociate
00917                                                                 (sigrdataset);
00918                                         }
00919                                 } else
00920                                         result = DNS_R_DELEGATION;
00921                                 break;
00922                         }
00923                 }
00924 
00925                 /*
00926                  * If the current name is not the qname, add another label
00927                  * and try again.
00928                  */
00929                 if (i < nlabels) {
00930                         destroynode(node);
00931                         node = NULL;
00932                         continue;
00933                 }
00934 
00935  skip:
00936                 /*
00937                  * If we're looking for ANY, we're done.
00938                  */
00939                 if (type == dns_rdatatype_any) {
00940                         result = ISC_R_SUCCESS;
00941                         break;
00942                 }
00943 
00944                 /*
00945                  * Look for the qtype.
00946                  */
00947                 result = findrdataset(db, node, version, type,
00948                                       0, now, rdataset, sigrdataset);
00949                 if (result == ISC_R_SUCCESS)
00950                         break;
00951 
00952                 /*
00953                  * Look for a CNAME
00954                  */
00955                 if (type != dns_rdatatype_cname) {
00956                         result = findrdataset(db, node, version,
00957                                               dns_rdatatype_cname,
00958                                               0, now, rdataset, sigrdataset);
00959                         if (result == ISC_R_SUCCESS) {
00960                                 result = DNS_R_CNAME;
00961                                 break;
00962                         }
00963                 }
00964 
00965                 result = DNS_R_NXRRSET;
00966                 break;
00967         }
00968 
00969         if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
00970                 dns_rdataset_disassociate(rdataset);
00971 
00972         if (foundname != NULL) {
00973                 isc_result_t xresult;
00974 
00975                 xresult = dns_name_copy(xname, foundname, NULL);
00976                 if (xresult != ISC_R_SUCCESS) {
00977                         if (node != NULL)
00978                                 destroynode(node);
00979                         if (dns_rdataset_isassociated(rdataset))
00980                                 dns_rdataset_disassociate(rdataset);
00981                         return (DNS_R_BADDB);
00982                 }
00983         }
00984 
00985         if (nodep != NULL)
00986                 *nodep = node;
00987         else if (node != NULL)
00988                 detachnode(db, &node);
00989 
00990         return (result);
00991 }
00992 
00993 static isc_result_t
00994 findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
00995             isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
00996             dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
00997 {
00998         UNUSED(db);
00999         UNUSED(name);
01000         UNUSED(options);
01001         UNUSED(now);
01002         UNUSED(nodep);
01003         UNUSED(foundname);
01004         UNUSED(rdataset);
01005         UNUSED(sigrdataset);
01006 
01007         return (ISC_R_NOTIMPLEMENTED);
01008 }
01009 
01010 static void
01011 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
01012         dns_sdb_t *sdb = (dns_sdb_t *)db;
01013         dns_sdbnode_t *node = (dns_sdbnode_t *)source;
01014 
01015         REQUIRE(VALID_SDB(sdb));
01016 
01017         UNUSED(sdb);
01018 
01019         LOCK(&node->lock);
01020         INSIST(node->references > 0);
01021         node->references++;
01022         INSIST(node->references != 0);          /* Catch overflow. */
01023         UNLOCK(&node->lock);
01024 
01025         *targetp = source;
01026 }
01027 
01028 static void
01029 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
01030         dns_sdb_t *sdb = (dns_sdb_t *)db;
01031         dns_sdbnode_t *node;
01032         isc_boolean_t need_destroy = ISC_FALSE;
01033 
01034         REQUIRE(VALID_SDB(sdb));
01035         REQUIRE(targetp != NULL && *targetp != NULL);
01036 
01037         UNUSED(sdb);
01038 
01039         node = (dns_sdbnode_t *)(*targetp);
01040 
01041         LOCK(&node->lock);
01042         INSIST(node->references > 0);
01043         node->references--;
01044         if (node->references == 0)
01045                 need_destroy = ISC_TRUE;
01046         UNLOCK(&node->lock);
01047 
01048         if (need_destroy)
01049                 destroynode(node);
01050 
01051         *targetp = NULL;
01052 }
01053 
01054 static isc_result_t
01055 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
01056         UNUSED(db);
01057         UNUSED(node);
01058         UNUSED(now);
01059         INSIST(0);
01060         return (ISC_R_UNEXPECTED);
01061 }
01062 
01063 static void
01064 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
01065         UNUSED(db);
01066         UNUSED(node);
01067         UNUSED(out);
01068         return;
01069 }
01070 
01071 static isc_result_t
01072 createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
01073 {
01074         dns_sdb_t *sdb = (dns_sdb_t *)db;
01075         sdb_dbiterator_t *sdbiter;
01076         dns_sdbimplementation_t *imp = sdb->implementation;
01077         isc_result_t result;
01078 
01079         REQUIRE(VALID_SDB(sdb));
01080 
01081         if (imp->methods->allnodes == NULL)
01082                 return (ISC_R_NOTIMPLEMENTED);
01083 
01084         if ((options & DNS_DB_NSEC3ONLY) != 0 ||
01085             (options & DNS_DB_NONSEC3) != 0)
01086                 return (ISC_R_NOTIMPLEMENTED);
01087 
01088         sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t));
01089         if (sdbiter == NULL)
01090                 return (ISC_R_NOMEMORY);
01091 
01092         sdbiter->common.methods = &dbiterator_methods;
01093         sdbiter->common.db = NULL;
01094         dns_db_attach(db, &sdbiter->common.db);
01095         sdbiter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
01096         sdbiter->common.magic = DNS_DBITERATOR_MAGIC;
01097         ISC_LIST_INIT(sdbiter->nodelist);
01098         sdbiter->current = NULL;
01099         sdbiter->origin = NULL;
01100 
01101         MAYBE_LOCK(sdb);
01102         result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter);
01103         MAYBE_UNLOCK(sdb);
01104         if (result != ISC_R_SUCCESS) {
01105                 dbiterator_destroy((dns_dbiterator_t **) (void *)&sdbiter);
01106                 return (result);
01107         }
01108 
01109         if (sdbiter->origin != NULL) {
01110                 ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link);
01111                 ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link);
01112         }
01113 
01114         *iteratorp = (dns_dbiterator_t *)sdbiter;
01115 
01116         return (ISC_R_SUCCESS);
01117 }
01118 
01119 static isc_result_t
01120 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
01121              dns_rdatatype_t type, dns_rdatatype_t covers,
01122              isc_stdtime_t now, dns_rdataset_t *rdataset,
01123              dns_rdataset_t *sigrdataset)
01124 {
01125         dns_rdatalist_t *list;
01126         dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
01127 
01128         REQUIRE(VALID_SDBNODE(node));
01129 
01130         UNUSED(db);
01131         UNUSED(version);
01132         UNUSED(covers);
01133         UNUSED(now);
01134         UNUSED(sigrdataset);
01135 
01136         if (type == dns_rdatatype_rrsig)
01137                 return (ISC_R_NOTIMPLEMENTED);
01138 
01139         list = ISC_LIST_HEAD(sdbnode->lists);
01140         while (list != NULL) {
01141                 if (list->type == type)
01142                         break;
01143                 list = ISC_LIST_NEXT(list, link);
01144         }
01145         if (list == NULL)
01146                 return (ISC_R_NOTFOUND);
01147 
01148         list_tordataset(list, db, node, rdataset);
01149 
01150         return (ISC_R_SUCCESS);
01151 }
01152 
01153 static isc_result_t
01154 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
01155              isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
01156 {
01157         sdb_rdatasetiter_t *iterator;
01158 
01159         REQUIRE(version == NULL || version == &dummy);
01160 
01161         UNUSED(version);
01162         UNUSED(now);
01163 
01164         iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t));
01165         if (iterator == NULL)
01166                 return (ISC_R_NOMEMORY);
01167 
01168         iterator->common.magic = DNS_RDATASETITER_MAGIC;
01169         iterator->common.methods = &rdatasetiter_methods;
01170         iterator->common.db = db;
01171         iterator->common.node = NULL;
01172         attachnode(db, node, &iterator->common.node);
01173         iterator->common.version = version;
01174         iterator->common.now = now;
01175 
01176         *iteratorp = (dns_rdatasetiter_t *)iterator;
01177 
01178         return (ISC_R_SUCCESS);
01179 }
01180 
01181 static isc_result_t
01182 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
01183             isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
01184             dns_rdataset_t *addedrdataset)
01185 {
01186         UNUSED(db);
01187         UNUSED(node);
01188         UNUSED(version);
01189         UNUSED(now);
01190         UNUSED(rdataset);
01191         UNUSED(options);
01192         UNUSED(addedrdataset);
01193 
01194         return (ISC_R_NOTIMPLEMENTED);
01195 }
01196 
01197 static isc_result_t
01198 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
01199                  dns_rdataset_t *rdataset, unsigned int options,
01200                  dns_rdataset_t *newrdataset)
01201 {
01202         UNUSED(db);
01203         UNUSED(node);
01204         UNUSED(version);
01205         UNUSED(rdataset);
01206         UNUSED(options);
01207         UNUSED(newrdataset);
01208 
01209         return (ISC_R_NOTIMPLEMENTED);
01210 }
01211 
01212 static isc_result_t
01213 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
01214                dns_rdatatype_t type, dns_rdatatype_t covers)
01215 {
01216         UNUSED(db);
01217         UNUSED(node);
01218         UNUSED(version);
01219         UNUSED(type);
01220         UNUSED(covers);
01221 
01222         return (ISC_R_NOTIMPLEMENTED);
01223 }
01224 
01225 static isc_boolean_t
01226 issecure(dns_db_t *db) {
01227         UNUSED(db);
01228 
01229         return (ISC_FALSE);
01230 }
01231 
01232 static unsigned int
01233 nodecount(dns_db_t *db) {
01234         UNUSED(db);
01235 
01236         return (0);
01237 }
01238 
01239 static isc_boolean_t
01240 ispersistent(dns_db_t *db) {
01241         UNUSED(db);
01242         return (ISC_TRUE);
01243 }
01244 
01245 static void
01246 overmem(dns_db_t *db, isc_boolean_t over) {
01247         UNUSED(db);
01248         UNUSED(over);
01249 }
01250 
01251 static void
01252 settask(dns_db_t *db, isc_task_t *task) {
01253         UNUSED(db);
01254         UNUSED(task);
01255 }
01256 
01257 
01258 static dns_dbmethods_t sdb_methods = {
01259         attach,
01260         detach,
01261         beginload,
01262         endload,
01263         NULL,
01264         dump,
01265         currentversion,
01266         newversion,
01267         attachversion,
01268         closeversion,
01269         NULL,
01270         NULL,
01271         findzonecut,
01272         attachnode,
01273         detachnode,
01274         expirenode,
01275         printnode,
01276         createiterator,
01277         findrdataset,
01278         allrdatasets,
01279         addrdataset,
01280         subtractrdataset,
01281         deleterdataset,
01282         issecure,
01283         nodecount,
01284         ispersistent,
01285         overmem,
01286         settask,
01287         NULL,                   /* getoriginnode */
01288         NULL,                   /* transfernode */
01289         NULL,                   /* getnsec3parameters */
01290         NULL,                   /* findnsec3node */
01291         NULL,                   /* setsigningtime */
01292         NULL,                   /* getsigningtime */
01293         NULL,                   /* resigned */
01294         NULL,                   /* isdnssec */
01295         NULL,                   /* getrrsetstats */
01296         NULL,                   /* rpz_attach */
01297         NULL,                   /* rpz_ready */
01298         findnodeext,
01299         findext,
01300         NULL,                   /* setcachestats */
01301         NULL                    /* hashsize */
01302 };
01303 
01304 static isc_result_t
01305 dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
01306                dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
01307                void *driverarg, dns_db_t **dbp)
01308 {
01309         dns_sdb_t *sdb;
01310         isc_result_t result;
01311         char zonestr[DNS_NAME_MAXTEXT + 1];
01312         isc_buffer_t b;
01313         dns_sdbimplementation_t *imp;
01314 
01315         REQUIRE(driverarg != NULL);
01316 
01317         imp = driverarg;
01318 
01319         if (type != dns_dbtype_zone)
01320                 return (ISC_R_NOTIMPLEMENTED);
01321 
01322         sdb = isc_mem_get(mctx, sizeof(dns_sdb_t));
01323         if (sdb == NULL)
01324                 return (ISC_R_NOMEMORY);
01325         memset(sdb, 0, sizeof(dns_sdb_t));
01326 
01327         dns_name_init(&sdb->common.origin, NULL);
01328         sdb->common.attributes = 0;
01329         sdb->common.methods = &sdb_methods;
01330         sdb->common.rdclass = rdclass;
01331         sdb->common.mctx = NULL;
01332         sdb->implementation = imp;
01333 
01334         isc_mem_attach(mctx, &sdb->common.mctx);
01335 
01336         result = isc_mutex_init(&sdb->lock);
01337         if (result != ISC_R_SUCCESS)
01338                 goto cleanup_mctx;
01339 
01340         result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
01341         if (result != ISC_R_SUCCESS)
01342                 goto cleanup_lock;
01343 
01344         isc_buffer_init(&b, zonestr, sizeof(zonestr));
01345         result = dns_name_totext(origin, ISC_TRUE, &b);
01346         if (result != ISC_R_SUCCESS)
01347                 goto cleanup_origin;
01348         isc_buffer_putuint8(&b, 0);
01349 
01350         sdb->zone = isc_mem_strdup(mctx, zonestr);
01351         if (sdb->zone == NULL) {
01352                 result = ISC_R_NOMEMORY;
01353                 goto cleanup_origin;
01354         }
01355 
01356         sdb->dbdata = NULL;
01357         if (imp->methods->create != NULL) {
01358                 MAYBE_LOCK(sdb);
01359                 result = imp->methods->create(sdb->zone, argc, argv,
01360                                               imp->driverdata, &sdb->dbdata);
01361                 MAYBE_UNLOCK(sdb);
01362                 if (result != ISC_R_SUCCESS)
01363                         goto cleanup_zonestr;
01364         }
01365 
01366         sdb->references = 1;
01367 
01368         sdb->common.magic = DNS_DB_MAGIC;
01369         sdb->common.impmagic = SDB_MAGIC;
01370 
01371         *dbp = (dns_db_t *)sdb;
01372 
01373         return (ISC_R_SUCCESS);
01374 
01375  cleanup_zonestr:
01376         isc_mem_free(mctx, sdb->zone);
01377  cleanup_origin:
01378         dns_name_free(&sdb->common.origin, mctx);
01379  cleanup_lock:
01380         (void)isc_mutex_destroy(&sdb->lock);
01381  cleanup_mctx:
01382         isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
01383         isc_mem_detach(&mctx);
01384 
01385         return (result);
01386 }
01387 
01388 
01389 /*
01390  * Rdataset Methods
01391  */
01392 
01393 static void
01394 disassociate(dns_rdataset_t *rdataset) {
01395         dns_dbnode_t *node = rdataset->private5;
01396         dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
01397         dns_db_t *db = (dns_db_t *) sdbnode->sdb;
01398 
01399         detachnode(db, &node);
01400         isc__rdatalist_disassociate(rdataset);
01401 }
01402 
01403 static void
01404 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
01405         dns_dbnode_t *node = source->private5;
01406         dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
01407         dns_db_t *db = (dns_db_t *) sdbnode->sdb;
01408         dns_dbnode_t *tempdb = NULL;
01409 
01410         isc__rdatalist_clone(source, target);
01411         attachnode(db, node, &tempdb);
01412         source->private5 = tempdb;
01413 }
01414 
01415 static dns_rdatasetmethods_t methods = {
01416         disassociate,
01417         isc__rdatalist_first,
01418         isc__rdatalist_next,
01419         isc__rdatalist_current,
01420         rdataset_clone,
01421         isc__rdatalist_count,
01422         isc__rdatalist_addnoqname,
01423         isc__rdatalist_getnoqname,
01424         NULL,
01425         NULL,
01426         NULL,
01427         NULL,
01428         NULL,
01429         NULL,
01430         NULL,
01431         NULL,
01432         NULL,
01433         NULL
01434 };
01435 
01436 static void
01437 list_tordataset(dns_rdatalist_t *rdatalist,
01438                 dns_db_t *db, dns_dbnode_t *node,
01439                 dns_rdataset_t *rdataset)
01440 {
01441         /*
01442          * The sdb rdataset is an rdatalist with some additions.
01443          *      - private1 & private2 are used by the rdatalist.
01444          *      - private3 & private 4 are unused.
01445          *      - private5 is the node.
01446          */
01447 
01448         /* This should never fail. */
01449         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
01450                       ISC_R_SUCCESS);
01451 
01452         rdataset->methods = &methods;
01453         dns_db_attachnode(db, node, &rdataset->private5);
01454 }
01455 
01456 /*
01457  * Database Iterator Methods
01458  */
01459 static void
01460 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
01461         sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp);
01462         dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db;
01463 
01464         while (!ISC_LIST_EMPTY(sdbiter->nodelist)) {
01465                 dns_sdbnode_t *node;
01466                 node = ISC_LIST_HEAD(sdbiter->nodelist);
01467                 ISC_LIST_UNLINK(sdbiter->nodelist, node, link);
01468                 destroynode(node);
01469         }
01470 
01471         dns_db_detach(&sdbiter->common.db);
01472         isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t));
01473 
01474         *iteratorp = NULL;
01475 }
01476 
01477 static isc_result_t
01478 dbiterator_first(dns_dbiterator_t *iterator) {
01479         sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
01480 
01481         sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
01482         if (sdbiter->current == NULL)
01483                 return (ISC_R_NOMORE);
01484         else
01485                 return (ISC_R_SUCCESS);
01486 }
01487 
01488 static isc_result_t
01489 dbiterator_last(dns_dbiterator_t *iterator) {
01490         sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
01491 
01492         sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist);
01493         if (sdbiter->current == NULL)
01494                 return (ISC_R_NOMORE);
01495         else
01496                 return (ISC_R_SUCCESS);
01497 }
01498 
01499 static isc_result_t
01500 dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
01501         sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
01502 
01503         sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
01504         while (sdbiter->current != NULL) {
01505                 if (dns_name_equal(sdbiter->current->name, name))
01506                         return (ISC_R_SUCCESS);
01507                 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
01508         }
01509         return (ISC_R_NOTFOUND);
01510 }
01511 
01512 static isc_result_t
01513 dbiterator_prev(dns_dbiterator_t *iterator) {
01514         sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
01515 
01516         sdbiter->current = ISC_LIST_PREV(sdbiter->current, link);
01517         if (sdbiter->current == NULL)
01518                 return (ISC_R_NOMORE);
01519         else
01520                 return (ISC_R_SUCCESS);
01521 }
01522 
01523 static isc_result_t
01524 dbiterator_next(dns_dbiterator_t *iterator) {
01525         sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
01526 
01527         sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
01528         if (sdbiter->current == NULL)
01529                 return (ISC_R_NOMORE);
01530         else
01531                 return (ISC_R_SUCCESS);
01532 }
01533 
01534 static isc_result_t
01535 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
01536                    dns_name_t *name)
01537 {
01538         sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
01539 
01540         attachnode(iterator->db, sdbiter->current, nodep);
01541         if (name != NULL)
01542                 return (dns_name_copy(sdbiter->current->name, name, NULL));
01543         return (ISC_R_SUCCESS);
01544 }
01545 
01546 static isc_result_t
01547 dbiterator_pause(dns_dbiterator_t *iterator) {
01548         UNUSED(iterator);
01549         return (ISC_R_SUCCESS);
01550 }
01551 
01552 static isc_result_t
01553 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
01554         UNUSED(iterator);
01555         return (dns_name_copy(dns_rootname, name, NULL));
01556 }
01557 
01558 /*
01559  * Rdataset Iterator Methods
01560  */
01561 
01562 static void
01563 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
01564         sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp);
01565         detachnode(sdbiterator->common.db, &sdbiterator->common.node);
01566         isc_mem_put(sdbiterator->common.db->mctx, sdbiterator,
01567                     sizeof(sdb_rdatasetiter_t));
01568         *iteratorp = NULL;
01569 }
01570 
01571 static isc_result_t
01572 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
01573         sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
01574         dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node;
01575 
01576         if (ISC_LIST_EMPTY(sdbnode->lists))
01577                 return (ISC_R_NOMORE);
01578         sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists);
01579         return (ISC_R_SUCCESS);
01580 }
01581 
01582 static isc_result_t
01583 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
01584         sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
01585 
01586         sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link);
01587         if (sdbiterator->current == NULL)
01588                 return (ISC_R_NOMORE);
01589         else
01590                 return (ISC_R_SUCCESS);
01591 }
01592 
01593 static void
01594 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
01595         sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
01596 
01597         list_tordataset(sdbiterator->current, iterator->db, iterator->node,
01598                         rdataset);
01599 }

Generated on Tue Apr 28 17:41:01 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha