ecdb.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2009-2015  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 #include "config.h"
00018 
00019 #include <isc/result.h>
00020 #include <isc/util.h>
00021 #include <isc/mutex.h>
00022 #include <isc/mem.h>
00023 
00024 #include <dns/db.h>
00025 #include <dns/ecdb.h>
00026 #include <dns/rdata.h>
00027 #include <dns/rdataset.h>
00028 #include <dns/rdatasetiter.h>
00029 #include <dns/rdataslab.h>
00030 
00031 #define ECDB_MAGIC              ISC_MAGIC('E', 'C', 'D', 'B')
00032 #define VALID_ECDB(db)          ((db) != NULL && \
00033                                  (db)->common.impmagic == ECDB_MAGIC)
00034 
00035 #define ECDBNODE_MAGIC          ISC_MAGIC('E', 'C', 'D', 'N')
00036 #define VALID_ECDBNODE(ecdbn)   ISC_MAGIC_VALID(ecdbn, ECDBNODE_MAGIC)
00037 
00038 /*%
00039  * The 'ephemeral' cache DB (ecdb) implementation.  An ecdb just provides
00040  * temporary storage for ongoing name resolution with the common DB interfaces.
00041  * It actually doesn't cache anything.  The implementation expects any stored
00042  * data is released within a short period, and does not care about the
00043  * scalability in terms of the number of nodes.
00044  */
00045 
00046 typedef struct dns_ecdb {
00047         /* Unlocked */
00048         dns_db_t                        common;
00049         isc_mutex_t                     lock;
00050 
00051         /* Locked */
00052         unsigned int                    references;
00053         ISC_LIST(struct dns_ecdbnode)   nodes;
00054 } dns_ecdb_t;
00055 
00056 typedef struct dns_ecdbnode {
00057         /* Unlocked */
00058         unsigned int                    magic;
00059         isc_mutex_t                     lock;
00060         dns_ecdb_t                      *ecdb;
00061         dns_name_t                      name;
00062         ISC_LINK(struct dns_ecdbnode)   link;
00063 
00064         /* Locked */
00065         ISC_LIST(struct rdatasetheader) rdatasets;
00066         unsigned int                    references;
00067 } dns_ecdbnode_t;
00068 
00069 typedef struct rdatasetheader {
00070         dns_rdatatype_t                 type;
00071         dns_ttl_t                       ttl;
00072         dns_trust_t                     trust;
00073         dns_rdatatype_t                 covers;
00074         unsigned int                    attributes;
00075 
00076         ISC_LINK(struct rdatasetheader) link;
00077 } rdatasetheader_t;
00078 
00079 /* Copied from rbtdb.c */
00080 #define RDATASET_ATTR_NXDOMAIN          0x0010
00081 #define RDATASET_ATTR_NEGATIVE          0x0100
00082 #define NXDOMAIN(header) \
00083         (((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
00084 #define NEGATIVE(header) \
00085         (((header)->attributes & RDATASET_ATTR_NEGATIVE) != 0)
00086 
00087 static isc_result_t dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin,
00088                                     dns_dbtype_t type,
00089                                     dns_rdataclass_t rdclass,
00090                                     unsigned int argc, char *argv[],
00091                                     void *driverarg, dns_db_t **dbp);
00092 
00093 static void rdataset_disassociate(dns_rdataset_t *rdataset);
00094 static isc_result_t rdataset_first(dns_rdataset_t *rdataset);
00095 static isc_result_t rdataset_next(dns_rdataset_t *rdataset);
00096 static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
00097 static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);
00098 static unsigned int rdataset_count(dns_rdataset_t *rdataset);
00099 static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
00100 
00101 static dns_rdatasetmethods_t rdataset_methods = {
00102         rdataset_disassociate,
00103         rdataset_first,
00104         rdataset_next,
00105         rdataset_current,
00106         rdataset_clone,
00107         rdataset_count,
00108         NULL,                   /* addnoqname */
00109         NULL,                   /* getnoqname */
00110         NULL,                   /* addclosest */
00111         NULL,                   /* getclosest */
00112         NULL,                   /* getadditional */
00113         NULL,                   /* setadditional */
00114         NULL,                   /* putadditional */
00115         rdataset_settrust,      /* settrust */
00116         NULL,                   /* expire */
00117         NULL,                   /* clearprefetch */
00118         NULL,                   /* setownercase */
00119         NULL                    /* getownercase */
00120 };
00121 
00122 typedef struct ecdb_rdatasetiter {
00123         dns_rdatasetiter_t              common;
00124         rdatasetheader_t               *current;
00125 } ecdb_rdatasetiter_t;
00126 
00127 static void             rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
00128 static isc_result_t     rdatasetiter_first(dns_rdatasetiter_t *iterator);
00129 static isc_result_t     rdatasetiter_next(dns_rdatasetiter_t *iterator);
00130 static void             rdatasetiter_current(dns_rdatasetiter_t *iterator,
00131                                              dns_rdataset_t *rdataset);
00132 
00133 static dns_rdatasetitermethods_t rdatasetiter_methods = {
00134         rdatasetiter_destroy,
00135         rdatasetiter_first,
00136         rdatasetiter_next,
00137         rdatasetiter_current
00138 };
00139 
00140 isc_result_t
00141 dns_ecdb_register(isc_mem_t *mctx, dns_dbimplementation_t **dbimp) {
00142         REQUIRE(mctx != NULL);
00143         REQUIRE(dbimp != NULL && *dbimp == NULL);
00144 
00145         return (dns_db_register("ecdb", dns_ecdb_create, NULL, mctx, dbimp));
00146 }
00147 
00148 void
00149 dns_ecdb_unregister(dns_dbimplementation_t **dbimp) {
00150         REQUIRE(dbimp != NULL && *dbimp != NULL);
00151 
00152         dns_db_unregister(dbimp);
00153 }
00154 
00155 /*%
00156  * DB routines
00157  */
00158 
00159 static void
00160 attach(dns_db_t *source, dns_db_t **targetp) {
00161         dns_ecdb_t *ecdb = (dns_ecdb_t *)source;
00162 
00163         REQUIRE(VALID_ECDB(ecdb));
00164         REQUIRE(targetp != NULL && *targetp == NULL);
00165 
00166         LOCK(&ecdb->lock);
00167         ecdb->references++;
00168         UNLOCK(&ecdb->lock);
00169 
00170         *targetp = source;
00171 }
00172 
00173 static void
00174 destroy_ecdb(dns_ecdb_t **ecdbp) {
00175         dns_ecdb_t *ecdb = *ecdbp;
00176         isc_mem_t *mctx = ecdb->common.mctx;
00177 
00178         if (dns_name_dynamic(&ecdb->common.origin))
00179                 dns_name_free(&ecdb->common.origin, mctx);
00180 
00181         DESTROYLOCK(&ecdb->lock);
00182 
00183         ecdb->common.impmagic = 0;
00184         ecdb->common.magic = 0;
00185 
00186         isc_mem_putanddetach(&mctx, ecdb, sizeof(*ecdb));
00187 
00188         *ecdbp = NULL;
00189 }
00190 
00191 static void
00192 detach(dns_db_t **dbp) {
00193         dns_ecdb_t *ecdb;
00194         isc_boolean_t need_destroy = ISC_FALSE;
00195 
00196         REQUIRE(dbp != NULL);
00197         ecdb = (dns_ecdb_t *)*dbp;
00198         REQUIRE(VALID_ECDB(ecdb));
00199 
00200         LOCK(&ecdb->lock);
00201         ecdb->references--;
00202         if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
00203                 need_destroy = ISC_TRUE;
00204         UNLOCK(&ecdb->lock);
00205 
00206         if (need_destroy)
00207                 destroy_ecdb(&ecdb);
00208 
00209         *dbp = NULL;
00210 }
00211 
00212 static void
00213 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
00214         dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
00215         dns_ecdbnode_t *node = (dns_ecdbnode_t *)source;
00216 
00217         REQUIRE(VALID_ECDB(ecdb));
00218         REQUIRE(VALID_ECDBNODE(node));
00219         REQUIRE(targetp != NULL && *targetp == NULL);
00220 
00221         LOCK(&node->lock);
00222         INSIST(node->references > 0);
00223         node->references++;
00224         INSIST(node->references != 0);          /* Catch overflow. */
00225         UNLOCK(&node->lock);
00226 
00227         *targetp = node;
00228 }
00229 
00230 static void
00231 destroynode(dns_ecdbnode_t *node) {
00232         isc_mem_t *mctx;
00233         dns_ecdb_t *ecdb = node->ecdb;
00234         isc_boolean_t need_destroydb = ISC_FALSE;
00235         rdatasetheader_t *header;
00236 
00237         mctx = ecdb->common.mctx;
00238 
00239         LOCK(&ecdb->lock);
00240         ISC_LIST_UNLINK(ecdb->nodes, node, link);
00241         if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
00242                 need_destroydb = ISC_TRUE;
00243         UNLOCK(&ecdb->lock);
00244 
00245         dns_name_free(&node->name, mctx);
00246 
00247         while ((header = ISC_LIST_HEAD(node->rdatasets)) != NULL) {
00248                 unsigned int headersize;
00249 
00250                 ISC_LIST_UNLINK(node->rdatasets, header, link);
00251                 headersize =
00252                         dns_rdataslab_size((unsigned char *)header,
00253                                            sizeof(*header));
00254                 isc_mem_put(mctx, header, headersize);
00255         }
00256 
00257         DESTROYLOCK(&node->lock);
00258 
00259         node->magic = 0;
00260         isc_mem_put(mctx, node, sizeof(*node));
00261 
00262         if (need_destroydb)
00263                 destroy_ecdb(&ecdb);
00264 }
00265 
00266 static void
00267 detachnode(dns_db_t *db, dns_dbnode_t **nodep) {
00268         dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
00269         dns_ecdbnode_t *node;
00270         isc_boolean_t need_destroy = ISC_FALSE;
00271 
00272         REQUIRE(VALID_ECDB(ecdb));
00273         REQUIRE(nodep != NULL);
00274         node = (dns_ecdbnode_t *)*nodep;
00275         REQUIRE(VALID_ECDBNODE(node));
00276 
00277         UNUSED(ecdb);           /* in case REQUIRE() is empty */
00278 
00279         LOCK(&node->lock);
00280         INSIST(node->references > 0);
00281         node->references--;
00282         if (node->references == 0)
00283                 need_destroy = ISC_TRUE;
00284         UNLOCK(&node->lock);
00285 
00286         if (need_destroy)
00287                 destroynode(node);
00288 
00289         *nodep = NULL;
00290 }
00291 
00292 static isc_result_t
00293 find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
00294     dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
00295     dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset,
00296     dns_rdataset_t *sigrdataset)
00297 {
00298         dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
00299 
00300         REQUIRE(VALID_ECDB(ecdb));
00301 
00302         UNUSED(name);
00303         UNUSED(version);
00304         UNUSED(type);
00305         UNUSED(options);
00306         UNUSED(now);
00307         UNUSED(nodep);
00308         UNUSED(foundname);
00309         UNUSED(rdataset);
00310         UNUSED(sigrdataset);
00311 
00312         return (ISC_R_NOTFOUND);
00313 }
00314 
00315 static isc_result_t
00316 findzonecut(dns_db_t *db, dns_name_t *name,
00317             unsigned int options, isc_stdtime_t now,
00318             dns_dbnode_t **nodep, dns_name_t *foundname,
00319             dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
00320 {
00321         dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
00322 
00323         REQUIRE(VALID_ECDB(ecdb));
00324 
00325         UNUSED(name);
00326         UNUSED(options);
00327         UNUSED(now);
00328         UNUSED(nodep);
00329         UNUSED(foundname);
00330         UNUSED(rdataset);
00331         UNUSED(sigrdataset);
00332 
00333         return (ISC_R_NOTFOUND);
00334 }
00335 
00336 static isc_result_t
00337 findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
00338          dns_dbnode_t **nodep)
00339 {
00340         dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
00341         isc_mem_t *mctx;
00342         dns_ecdbnode_t *node;
00343         isc_result_t result;
00344 
00345         REQUIRE(VALID_ECDB(ecdb));
00346         REQUIRE(nodep != NULL && *nodep == NULL);
00347 
00348         UNUSED(name);
00349 
00350         if (create != ISC_TRUE) {
00351                 /* an 'ephemeral' node is never reused. */
00352                 return (ISC_R_NOTFOUND);
00353         }
00354 
00355         mctx = ecdb->common.mctx;
00356         node = isc_mem_get(mctx, sizeof(*node));
00357         if (node == NULL)
00358                 return (ISC_R_NOMEMORY);
00359 
00360         result = isc_mutex_init(&node->lock);
00361         if (result != ISC_R_SUCCESS) {
00362                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00363                                  "isc_mutex_init() failed: %s",
00364                                  isc_result_totext(result));
00365                 isc_mem_put(mctx, node, sizeof(*node));
00366                 return (ISC_R_UNEXPECTED);
00367         }
00368 
00369         dns_name_init(&node->name, NULL);
00370         result = dns_name_dup(name, mctx, &node->name);
00371         if (result != ISC_R_SUCCESS) {
00372                 DESTROYLOCK(&node->lock);
00373                 isc_mem_put(mctx, node, sizeof(*node));
00374                 return (result);
00375         }
00376         node->ecdb= ecdb;
00377         node->references = 1;
00378         ISC_LIST_INIT(node->rdatasets);
00379 
00380         ISC_LINK_INIT(node, link);
00381 
00382         LOCK(&ecdb->lock);
00383         ISC_LIST_APPEND(ecdb->nodes, node, link);
00384         UNLOCK(&ecdb->lock);
00385 
00386         node->magic = ECDBNODE_MAGIC;
00387 
00388         *nodep = node;
00389 
00390         return (ISC_R_SUCCESS);
00391 }
00392 
00393 static void
00394 bind_rdataset(dns_ecdb_t *ecdb, dns_ecdbnode_t *node,
00395               rdatasetheader_t *header, dns_rdataset_t *rdataset)
00396 {
00397         unsigned char *raw;
00398 
00399         /*
00400          * Caller must be holding the node lock.
00401          */
00402 
00403         REQUIRE(!dns_rdataset_isassociated(rdataset));
00404 
00405         rdataset->methods = &rdataset_methods;
00406         rdataset->rdclass = ecdb->common.rdclass;
00407         rdataset->type = header->type;
00408         rdataset->covers = header->covers;
00409         rdataset->ttl = header->ttl;
00410         rdataset->trust = header->trust;
00411         if (NXDOMAIN(header))
00412                 rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN;
00413         if (NEGATIVE(header))
00414                 rdataset->attributes |= DNS_RDATASETATTR_NEGATIVE;
00415 
00416         rdataset->private1 = ecdb;
00417         rdataset->private2 = node;
00418         raw = (unsigned char *)header + sizeof(*header);
00419         rdataset->private3 = raw;
00420         rdataset->count = 0;
00421 
00422         /*
00423          * Reset iterator state.
00424          */
00425         rdataset->privateuint4 = 0;
00426         rdataset->private5 = NULL;
00427 
00428         INSIST(node->references > 0);
00429         node->references++;
00430 }
00431 
00432 static isc_result_t
00433 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
00434             isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
00435             dns_rdataset_t *addedrdataset)
00436 {
00437         dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
00438         isc_region_t r;
00439         isc_result_t result = ISC_R_SUCCESS;
00440         isc_mem_t *mctx;
00441         dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node;
00442         rdatasetheader_t *header;
00443 
00444         REQUIRE(VALID_ECDB(ecdb));
00445         REQUIRE(VALID_ECDBNODE(ecdbnode));
00446 
00447         UNUSED(version);
00448         UNUSED(now);
00449         UNUSED(options);
00450 
00451         mctx = ecdb->common.mctx;
00452 
00453         LOCK(&ecdbnode->lock);
00454 
00455         /*
00456          * Sanity check: this implementation does not allow overriding an
00457          * existing rdataset of the same type.
00458          */
00459         for (header = ISC_LIST_HEAD(ecdbnode->rdatasets); header != NULL;
00460              header = ISC_LIST_NEXT(header, link)) {
00461                 INSIST(header->type != rdataset->type ||
00462                        header->covers != rdataset->covers);
00463         }
00464 
00465         result = dns_rdataslab_fromrdataset(rdataset, mctx,
00466                                             &r, sizeof(rdatasetheader_t));
00467         if (result != ISC_R_SUCCESS)
00468                 goto unlock;
00469 
00470         header = (rdatasetheader_t *)r.base;
00471         header->type = rdataset->type;
00472         header->ttl = rdataset->ttl;
00473         header->trust = rdataset->trust;
00474         header->covers = rdataset->covers;
00475         header->attributes = 0;
00476         if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
00477                 header->attributes |= RDATASET_ATTR_NXDOMAIN;
00478         if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
00479                 header->attributes |= RDATASET_ATTR_NEGATIVE;
00480         ISC_LINK_INIT(header, link);
00481         ISC_LIST_APPEND(ecdbnode->rdatasets, header, link);
00482 
00483         if (addedrdataset == NULL)
00484                 goto unlock;
00485 
00486         bind_rdataset(ecdb, ecdbnode, header, addedrdataset);
00487 
00488  unlock:
00489         UNLOCK(&ecdbnode->lock);
00490 
00491         return (result);
00492 }
00493 
00494 static isc_result_t
00495 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
00496                dns_rdatatype_t type, dns_rdatatype_t covers)
00497 {
00498         UNUSED(db);
00499         UNUSED(node);
00500         UNUSED(version);
00501         UNUSED(type);
00502         UNUSED(covers);
00503 
00504         return (ISC_R_NOTIMPLEMENTED);
00505 }
00506 
00507 static isc_result_t
00508 createiterator(dns_db_t *db, unsigned int options,
00509                dns_dbiterator_t **iteratorp)
00510 {
00511         UNUSED(db);
00512         UNUSED(options);
00513         UNUSED(iteratorp);
00514 
00515         return (ISC_R_NOTIMPLEMENTED);
00516 }
00517 
00518 static isc_result_t
00519 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
00520              isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
00521 {
00522         dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
00523         dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node;
00524         isc_mem_t *mctx;
00525         ecdb_rdatasetiter_t *iterator;
00526 
00527         REQUIRE(VALID_ECDB(ecdb));
00528         REQUIRE(VALID_ECDBNODE(ecdbnode));
00529 
00530         mctx = ecdb->common.mctx;
00531 
00532         iterator = isc_mem_get(mctx, sizeof(ecdb_rdatasetiter_t));
00533         if (iterator == NULL)
00534                 return (ISC_R_NOMEMORY);
00535 
00536         iterator->common.magic = DNS_RDATASETITER_MAGIC;
00537         iterator->common.methods = &rdatasetiter_methods;
00538         iterator->common.db = db;
00539         iterator->common.node = NULL;
00540         attachnode(db, node, &iterator->common.node);
00541         iterator->common.version = version;
00542         iterator->common.now = now;
00543 
00544         *iteratorp = (dns_rdatasetiter_t *)iterator;
00545 
00546         return (ISC_R_SUCCESS);
00547 }
00548 
00549 static dns_dbmethods_t ecdb_methods = {
00550         attach,
00551         detach,
00552         NULL,                   /* beginload */
00553         NULL,                   /* endload */
00554         NULL,                   /* serialize */
00555         NULL,                   /* dump */
00556         NULL,                   /* currentversion */
00557         NULL,                   /* newversion */
00558         NULL,                   /* attachversion */
00559         NULL,                   /* closeversion */
00560         findnode,
00561         find,
00562         findzonecut,
00563         attachnode,
00564         detachnode,
00565         NULL,                   /* expirenode */
00566         NULL,                   /* printnode */
00567         createiterator,         /* createiterator */
00568         NULL,                   /* findrdataset */
00569         allrdatasets,
00570         addrdataset,
00571         NULL,                   /* subtractrdataset */
00572         deleterdataset,
00573         NULL,                   /* issecure */
00574         NULL,                   /* nodecount */
00575         NULL,                   /* ispersistent */
00576         NULL,                   /* overmem */
00577         NULL,                   /* settask */
00578         NULL,                   /* getoriginnode */
00579         NULL,                   /* transfernode */
00580         NULL,                   /* getnsec3parameters */
00581         NULL,                   /* findnsec3node */
00582         NULL,                   /* setsigningtime */
00583         NULL,                   /* getsigningtime */
00584         NULL,                   /* resigned */
00585         NULL,                   /* isdnssec */
00586         NULL,                   /* getrrsetstats */
00587         NULL,                   /* rpz_attach */
00588         NULL,                   /* rpz_ready */
00589         NULL,                   /* findnodeext */
00590         NULL,                   /* findext */
00591         NULL,                   /* setcachestats */
00592         NULL                    /* hashsize */
00593 };
00594 
00595 static isc_result_t
00596 dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
00597                 dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
00598                 void *driverarg, dns_db_t **dbp)
00599 {
00600         dns_ecdb_t *ecdb;
00601         isc_result_t result;
00602 
00603         REQUIRE(mctx != NULL);
00604         REQUIRE(origin == dns_rootname);
00605         REQUIRE(type == dns_dbtype_cache);
00606         REQUIRE(dbp != NULL && *dbp == NULL);
00607 
00608         UNUSED(argc);
00609         UNUSED(argv);
00610         UNUSED(driverarg);
00611 
00612         ecdb = isc_mem_get(mctx, sizeof(*ecdb));
00613         if (ecdb == NULL)
00614                 return (ISC_R_NOMEMORY);
00615 
00616         ecdb->common.attributes = DNS_DBATTR_CACHE;
00617         ecdb->common.rdclass = rdclass;
00618         ecdb->common.methods = &ecdb_methods;
00619         dns_name_init(&ecdb->common.origin, NULL);
00620         result = dns_name_dupwithoffsets(origin, mctx, &ecdb->common.origin);
00621         if (result != ISC_R_SUCCESS) {
00622                 isc_mem_put(mctx, ecdb, sizeof(*ecdb));
00623                 return (result);
00624         }
00625 
00626         result = isc_mutex_init(&ecdb->lock);
00627         if (result != ISC_R_SUCCESS) {
00628                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00629                                  "isc_mutex_init() failed: %s",
00630                                  isc_result_totext(result));
00631                 if (dns_name_dynamic(&ecdb->common.origin))
00632                         dns_name_free(&ecdb->common.origin, mctx);
00633                 isc_mem_put(mctx, ecdb, sizeof(*ecdb));
00634                 return (ISC_R_UNEXPECTED);
00635         }
00636 
00637         ecdb->references = 1;
00638         ISC_LIST_INIT(ecdb->nodes);
00639 
00640         ecdb->common.mctx = NULL;
00641         isc_mem_attach(mctx, &ecdb->common.mctx);
00642         ecdb->common.impmagic = ECDB_MAGIC;
00643         ecdb->common.magic = DNS_DB_MAGIC;
00644 
00645         *dbp = (dns_db_t *)ecdb;
00646 
00647         return (ISC_R_SUCCESS);
00648 }
00649 
00650 /*%
00651  * Rdataset Methods
00652  */
00653 
00654 static void
00655 rdataset_disassociate(dns_rdataset_t *rdataset) {
00656         dns_db_t *db = rdataset->private1;
00657         dns_dbnode_t *node = rdataset->private2;
00658 
00659         dns_db_detachnode(db, &node);
00660 }
00661 
00662 static isc_result_t
00663 rdataset_first(dns_rdataset_t *rdataset) {
00664         unsigned char *raw = rdataset->private3;
00665         unsigned int count;
00666 
00667         count = raw[0] * 256 + raw[1];
00668         if (count == 0) {
00669                 rdataset->private5 = NULL;
00670                 return (ISC_R_NOMORE);
00671         }
00672 #if DNS_RDATASET_FIXED
00673         raw += 2 + (4 * count);
00674 #else
00675         raw += 2;
00676 #endif
00677         /*
00678          * The privateuint4 field is the number of rdata beyond the cursor
00679          * position, so we decrement the total count by one before storing
00680          * it.
00681          */
00682         count--;
00683         rdataset->privateuint4 = count;
00684         rdataset->private5 = raw;
00685 
00686         return (ISC_R_SUCCESS);
00687 }
00688 
00689 static isc_result_t
00690 rdataset_next(dns_rdataset_t *rdataset) {
00691         unsigned int count;
00692         unsigned int length;
00693         unsigned char *raw;
00694 
00695         count = rdataset->privateuint4;
00696         if (count == 0)
00697                 return (ISC_R_NOMORE);
00698         count--;
00699         rdataset->privateuint4 = count;
00700         raw = rdataset->private5;
00701         length = raw[0] * 256 + raw[1];
00702 #if DNS_RDATASET_FIXED
00703         raw += length + 4;
00704 #else
00705         raw += length + 2;
00706 #endif
00707         rdataset->private5 = raw;
00708 
00709         return (ISC_R_SUCCESS);
00710 }
00711 
00712 static void
00713 rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
00714         unsigned char *raw = rdataset->private5;
00715         isc_region_t r;
00716         unsigned int length;
00717         unsigned int flags = 0;
00718 
00719         REQUIRE(raw != NULL);
00720 
00721         length = raw[0] * 256 + raw[1];
00722 #if DNS_RDATASET_FIXED
00723         raw += 4;
00724 #else
00725         raw += 2;
00726 #endif
00727         if (rdataset->type == dns_rdatatype_rrsig) {
00728                 if (*raw & DNS_RDATASLAB_OFFLINE)
00729                         flags |= DNS_RDATA_OFFLINE;
00730                 length--;
00731                 raw++;
00732         }
00733         r.length = length;
00734         r.base = raw;
00735         dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
00736         rdata->flags |= flags;
00737 }
00738 
00739 static void
00740 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
00741         dns_db_t *db = source->private1;
00742         dns_dbnode_t *node = source->private2;
00743         dns_dbnode_t *cloned_node = NULL;
00744 
00745         attachnode(db, node, &cloned_node);
00746         *target = *source;
00747 
00748         /*
00749          * Reset iterator state.
00750          */
00751         target->privateuint4 = 0;
00752         target->private5 = NULL;
00753 }
00754 
00755 static unsigned int
00756 rdataset_count(dns_rdataset_t *rdataset) {
00757         unsigned char *raw = rdataset->private3;
00758         unsigned int count;
00759 
00760         count = raw[0] * 256 + raw[1];
00761 
00762         return (count);
00763 }
00764 
00765 static void
00766 rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
00767         rdatasetheader_t *header = rdataset->private3;
00768 
00769         header--;
00770         header->trust = rdataset->trust = trust;
00771 }
00772 
00773 /*
00774  * Rdataset Iterator Methods
00775  */
00776 
00777 static void
00778 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
00779         isc_mem_t *mctx;
00780         union {
00781                 dns_rdatasetiter_t *rdatasetiterator;
00782                 ecdb_rdatasetiter_t *ecdbiterator;
00783         } u;
00784 
00785         REQUIRE(iteratorp != NULL);
00786         REQUIRE(DNS_RDATASETITER_VALID(*iteratorp));
00787 
00788         u.rdatasetiterator = *iteratorp;
00789 
00790         mctx = u.ecdbiterator->common.db->mctx;
00791         u.ecdbiterator->common.magic = 0;
00792 
00793         dns_db_detachnode(u.ecdbiterator->common.db,
00794                           &u.ecdbiterator->common.node);
00795         isc_mem_put(mctx, u.ecdbiterator,
00796                     sizeof(ecdb_rdatasetiter_t));
00797 
00798         *iteratorp = NULL;
00799 }
00800 
00801 static isc_result_t
00802 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
00803         ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
00804         dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)iterator->node;
00805 
00806         REQUIRE(DNS_RDATASETITER_VALID(iterator));
00807 
00808         if (ISC_LIST_EMPTY(ecdbnode->rdatasets))
00809                 return (ISC_R_NOMORE);
00810         ecdbiterator->current = ISC_LIST_HEAD(ecdbnode->rdatasets);
00811         return (ISC_R_SUCCESS);
00812 }
00813 
00814 static isc_result_t
00815 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
00816         ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
00817 
00818         REQUIRE(DNS_RDATASETITER_VALID(iterator));
00819 
00820         ecdbiterator->current = ISC_LIST_NEXT(ecdbiterator->current, link);
00821         if (ecdbiterator->current == NULL)
00822                 return (ISC_R_NOMORE);
00823         else
00824                 return (ISC_R_SUCCESS);
00825 }
00826 
00827 static void
00828 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
00829         ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
00830         dns_ecdb_t *ecdb;
00831 
00832         ecdb = (dns_ecdb_t *)iterator->db;
00833         REQUIRE(VALID_ECDB(ecdb));
00834 
00835         bind_rdataset(ecdb, iterator->node, ecdbiterator->current, rdataset);
00836 }

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