00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
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 
00040 
00041 
00042 
00043 
00044 
00045 
00046 typedef struct dns_ecdb {
00047         
00048         dns_db_t                        common;
00049         isc_mutex_t                     lock;
00050 
00051         
00052         unsigned int                    references;
00053         ISC_LIST(struct dns_ecdbnode)   nodes;
00054 } dns_ecdb_t;
00055 
00056 typedef struct dns_ecdbnode {
00057         
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         
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 
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,                   
00109         NULL,                   
00110         NULL,                   
00111         NULL,                   
00112         NULL,                   
00113         NULL,                   
00114         NULL,                   
00115         rdataset_settrust,      
00116         NULL,                   
00117         NULL,                   
00118         NULL,                   
00119         NULL                    
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 
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);          
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);           
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                 
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 
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 
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 
00457 
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,                   
00553         NULL,                   
00554         NULL,                   
00555         NULL,                   
00556         NULL,                   
00557         NULL,                   
00558         NULL,                   
00559         NULL,                   
00560         findnode,
00561         find,
00562         findzonecut,
00563         attachnode,
00564         detachnode,
00565         NULL,                   
00566         NULL,                   
00567         createiterator,         
00568         NULL,                   
00569         allrdatasets,
00570         addrdataset,
00571         NULL,                   
00572         deleterdataset,
00573         NULL,                   
00574         NULL,                   
00575         NULL,                   
00576         NULL,                   
00577         NULL,                   
00578         NULL,                   
00579         NULL,                   
00580         NULL,                   
00581         NULL,                   
00582         NULL,                   
00583         NULL,                   
00584         NULL,                   
00585         NULL,                   
00586         NULL,                   
00587         NULL,                   
00588         NULL,                   
00589         NULL,                   
00590         NULL,                   
00591         NULL,                   
00592         NULL                    
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 
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 
00679 
00680 
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 
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 
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 }