Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / ecdb.c
blobfe67880fefe4222c9f7a7f66fb819ea18aaee2e2
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id: ecdb.c,v 1.4 2009/11/06 04:19:28 marka Exp */
21 #include "config.h"
23 #include <isc/result.h>
24 #include <isc/util.h>
25 #include <isc/mutex.h>
26 #include <isc/mem.h>
28 #include <dns/db.h>
29 #include <dns/ecdb.h>
30 #include <dns/rdata.h>
31 #include <dns/rdataset.h>
32 #include <dns/rdatasetiter.h>
33 #include <dns/rdataslab.h>
35 #define ECDB_MAGIC ISC_MAGIC('E', 'C', 'D', 'B')
36 #define VALID_ECDB(db) ((db) != NULL && \
37 (db)->common.impmagic == ECDB_MAGIC)
39 #define ECDBNODE_MAGIC ISC_MAGIC('E', 'C', 'D', 'N')
40 #define VALID_ECDBNODE(ecdbn) ISC_MAGIC_VALID(ecdbn, ECDBNODE_MAGIC)
42 #if DNS_RDATASET_FIXED
43 #error "Fixed rdataset isn't supported in this implementation"
44 #endif
46 /*%
47 * The 'ephemeral' cache DB (ecdb) implementation. An ecdb just provides
48 * temporary storage for ongoing name resolution with the common DB interfaces.
49 * It actually doesn't cache anything. The implementation expects any stored
50 * data is released within a short period, and does not care about the
51 * scalability in terms of the number of nodes.
54 typedef struct dns_ecdb {
55 /* Unlocked */
56 dns_db_t common;
57 isc_mutex_t lock;
59 /* Locked */
60 unsigned int references;
61 ISC_LIST(struct dns_ecdbnode) nodes;
62 } dns_ecdb_t;
64 typedef struct dns_ecdbnode {
65 /* Unlocked */
66 unsigned int magic;
67 isc_mutex_t lock;
68 dns_ecdb_t *ecdb;
69 dns_name_t name;
70 ISC_LINK(struct dns_ecdbnode) link;
72 /* Locked */
73 ISC_LIST(struct rdatasetheader) rdatasets;
74 unsigned int references;
75 } dns_ecdbnode_t;
77 typedef struct rdatasetheader {
78 dns_rdatatype_t type;
79 dns_ttl_t ttl;
80 dns_trust_t trust;
81 dns_rdatatype_t covers;
82 unsigned int attributes;
84 ISC_LINK(struct rdatasetheader) link;
85 } rdatasetheader_t;
87 /* Copied from rbtdb.c */
88 #define RDATASET_ATTR_NXDOMAIN 0x0010
89 #define NXDOMAIN(header) \
90 (((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
92 static isc_result_t dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin,
93 dns_dbtype_t type,
94 dns_rdataclass_t rdclass,
95 unsigned int argc, char *argv[],
96 void *driverarg, dns_db_t **dbp);
98 static void rdataset_disassociate(dns_rdataset_t *rdataset);
99 static isc_result_t rdataset_first(dns_rdataset_t *rdataset);
100 static isc_result_t rdataset_next(dns_rdataset_t *rdataset);
101 static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
102 static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);
103 static unsigned int rdataset_count(dns_rdataset_t *rdataset);
105 static dns_rdatasetmethods_t rdataset_methods = {
106 rdataset_disassociate,
107 rdataset_first,
108 rdataset_next,
109 rdataset_current,
110 rdataset_clone,
111 rdataset_count,
112 NULL, /* addnoqname */
113 NULL, /* getnoqname */
114 NULL, /* addclosest */
115 NULL, /* getclosest */
116 NULL, /* getadditional */
117 NULL, /* setadditional */
118 NULL /* putadditional */
121 typedef struct ecdb_rdatasetiter {
122 dns_rdatasetiter_t common;
123 rdatasetheader_t *current;
124 } ecdb_rdatasetiter_t;
126 static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
127 static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator);
128 static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator);
129 static void rdatasetiter_current(dns_rdatasetiter_t *iterator,
130 dns_rdataset_t *rdataset);
132 static dns_rdatasetitermethods_t rdatasetiter_methods = {
133 rdatasetiter_destroy,
134 rdatasetiter_first,
135 rdatasetiter_next,
136 rdatasetiter_current
139 isc_result_t
140 dns_ecdb_register(isc_mem_t *mctx, dns_dbimplementation_t **dbimp) {
141 REQUIRE(mctx != NULL);
142 REQUIRE(dbimp != NULL && *dbimp == NULL);
144 return (dns_db_register("ecdb", dns_ecdb_create, NULL, mctx, dbimp));
147 void
148 dns_ecdb_unregister(dns_dbimplementation_t **dbimp) {
149 REQUIRE(dbimp != NULL && *dbimp != NULL);
151 dns_db_unregister(dbimp);
155 * DB routines
158 static void
159 attach(dns_db_t *source, dns_db_t **targetp) {
160 dns_ecdb_t *ecdb = (dns_ecdb_t *)source;
162 REQUIRE(VALID_ECDB(ecdb));
163 REQUIRE(targetp != NULL && *targetp == NULL);
165 LOCK(&ecdb->lock);
166 ecdb->references++;
167 UNLOCK(&ecdb->lock);
169 *targetp = source;
172 static void
173 destroy_ecdb(dns_ecdb_t **ecdbp) {
174 dns_ecdb_t *ecdb = *ecdbp;
175 isc_mem_t *mctx = ecdb->common.mctx;
177 if (dns_name_dynamic(&ecdb->common.origin))
178 dns_name_free(&ecdb->common.origin, mctx);
180 DESTROYLOCK(&ecdb->lock);
182 ecdb->common.impmagic = 0;
183 ecdb->common.magic = 0;
185 isc_mem_putanddetach(&mctx, ecdb, sizeof(*ecdb));
187 *ecdbp = NULL;
190 static void
191 detach(dns_db_t **dbp) {
192 dns_ecdb_t *ecdb;
193 isc_boolean_t need_destroy = ISC_FALSE;
195 REQUIRE(dbp != NULL);
196 ecdb = (dns_ecdb_t *)*dbp;
197 REQUIRE(VALID_ECDB(ecdb));
199 LOCK(&ecdb->lock);
200 ecdb->references--;
201 if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
202 need_destroy = ISC_TRUE;
203 UNLOCK(&ecdb->lock);
205 if (need_destroy)
206 destroy_ecdb(&ecdb);
208 *dbp = NULL;
211 static void
212 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
213 dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
214 dns_ecdbnode_t *node = (dns_ecdbnode_t *)source;
216 REQUIRE(VALID_ECDB(ecdb));
217 REQUIRE(VALID_ECDBNODE(node));
218 REQUIRE(targetp != NULL && *targetp == NULL);
220 LOCK(&node->lock);
221 INSIST(node->references > 0);
222 node->references++;
223 INSIST(node->references != 0); /* Catch overflow. */
224 UNLOCK(&node->lock);
226 *targetp = node;
229 static void
230 destroynode(dns_ecdbnode_t *node) {
231 isc_mem_t *mctx;
232 dns_ecdb_t *ecdb = node->ecdb;
233 isc_boolean_t need_destroydb = ISC_FALSE;
234 rdatasetheader_t *header;
236 mctx = ecdb->common.mctx;
238 LOCK(&ecdb->lock);
239 ISC_LIST_UNLINK(ecdb->nodes, node, link);
240 if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
241 need_destroydb = ISC_TRUE;
242 UNLOCK(&ecdb->lock);
244 dns_name_free(&node->name, mctx);
246 while ((header = ISC_LIST_HEAD(node->rdatasets)) != NULL) {
247 unsigned int headersize;
249 ISC_LIST_UNLINK(node->rdatasets, header, link);
250 headersize =
251 dns_rdataslab_size((unsigned char *)header,
252 sizeof(*header));
253 isc_mem_put(mctx, header, headersize);
256 DESTROYLOCK(&node->lock);
258 node->magic = 0;
259 isc_mem_put(mctx, node, sizeof(*node));
261 if (need_destroydb)
262 destroy_ecdb(&ecdb);
265 static void
266 detachnode(dns_db_t *db, dns_dbnode_t **nodep) {
267 dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
268 dns_ecdbnode_t *node;
269 isc_boolean_t need_destroy = ISC_FALSE;
271 REQUIRE(VALID_ECDB(ecdb));
272 REQUIRE(nodep != NULL);
273 node = (dns_ecdbnode_t *)*nodep;
274 REQUIRE(VALID_ECDBNODE(node));
276 UNUSED(ecdb); /* in case REQUIRE() is empty */
278 LOCK(&node->lock);
279 INSIST(node->references > 0);
280 node->references--;
281 if (node->references == 0)
282 need_destroy = ISC_TRUE;
283 UNLOCK(&node->lock);
285 if (need_destroy)
286 destroynode(node);
288 *nodep = NULL;
291 static isc_result_t
292 find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
293 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
294 dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset,
295 dns_rdataset_t *sigrdataset)
297 dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
299 REQUIRE(VALID_ECDB(ecdb));
301 UNUSED(name);
302 UNUSED(version);
303 UNUSED(type);
304 UNUSED(options);
305 UNUSED(now);
306 UNUSED(nodep);
307 UNUSED(foundname);
308 UNUSED(rdataset);
309 UNUSED(sigrdataset);
311 return (ISC_R_NOTFOUND);
314 static isc_result_t
315 findzonecut(dns_db_t *db, dns_name_t *name,
316 unsigned int options, isc_stdtime_t now,
317 dns_dbnode_t **nodep, dns_name_t *foundname,
318 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
320 dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
322 REQUIRE(VALID_ECDB(ecdb));
324 UNUSED(name);
325 UNUSED(options);
326 UNUSED(now);
327 UNUSED(nodep);
328 UNUSED(foundname);
329 UNUSED(rdataset);
330 UNUSED(sigrdataset);
332 return (ISC_R_NOTFOUND);
335 static isc_result_t
336 findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
337 dns_dbnode_t **nodep)
339 dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
340 isc_mem_t *mctx;
341 dns_ecdbnode_t *node;
342 isc_result_t result;
344 REQUIRE(VALID_ECDB(ecdb));
345 REQUIRE(nodep != NULL && *nodep == NULL);
347 UNUSED(name);
349 if (create != ISC_TRUE) {
350 /* an 'ephemeral' node is never reused. */
351 return (ISC_R_NOTFOUND);
354 mctx = ecdb->common.mctx;
355 node = isc_mem_get(mctx, sizeof(*node));
356 if (node == NULL)
357 return (ISC_R_NOMEMORY);
359 result = isc_mutex_init(&node->lock);
360 if (result != ISC_R_SUCCESS) {
361 UNEXPECTED_ERROR(__FILE__, __LINE__,
362 "isc_mutex_init() failed: %s",
363 isc_result_totext(result));
364 isc_mem_put(mctx, node, sizeof(*node));
365 return (ISC_R_UNEXPECTED);
368 dns_name_init(&node->name, NULL);
369 result = dns_name_dup(name, mctx, &node->name);
370 if (result != ISC_R_SUCCESS) {
371 DESTROYLOCK(&node->lock);
372 isc_mem_put(mctx, node, sizeof(*node));
373 return (result);
375 node->ecdb= ecdb;
376 node->references = 1;
377 ISC_LIST_INIT(node->rdatasets);
379 ISC_LINK_INIT(node, link);
381 LOCK(&ecdb->lock);
382 ISC_LIST_APPEND(ecdb->nodes, node, link);
383 UNLOCK(&ecdb->lock);
385 node->magic = ECDBNODE_MAGIC;
387 *nodep = node;
389 return (ISC_R_SUCCESS);
392 static void
393 bind_rdataset(dns_ecdb_t *ecdb, dns_ecdbnode_t *node,
394 rdatasetheader_t *header, dns_rdataset_t *rdataset)
396 unsigned char *raw;
399 * Caller must be holding the node lock.
402 REQUIRE(!dns_rdataset_isassociated(rdataset));
404 rdataset->methods = &rdataset_methods;
405 rdataset->rdclass = ecdb->common.rdclass;
406 rdataset->type = header->type;
407 rdataset->covers = header->covers;
408 rdataset->ttl = header->ttl;
409 rdataset->trust = header->trust;
410 if (NXDOMAIN(header))
411 rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN;
413 rdataset->private1 = ecdb;
414 rdataset->private2 = node;
415 raw = (unsigned char *)header + sizeof(*header);
416 rdataset->private3 = raw;
417 rdataset->count = 0;
420 * Reset iterator state.
422 rdataset->privateuint4 = 0;
423 rdataset->private5 = NULL;
425 INSIST(node->references > 0);
426 node->references++;
429 static isc_result_t
430 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
431 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
432 dns_rdataset_t *addedrdataset)
434 dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
435 isc_region_t r;
436 isc_result_t result = ISC_R_SUCCESS;
437 isc_mem_t *mctx;
438 dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node;
439 rdatasetheader_t *header;
441 REQUIRE(VALID_ECDB(ecdb));
442 REQUIRE(VALID_ECDBNODE(ecdbnode));
444 UNUSED(version);
445 UNUSED(now);
446 UNUSED(options);
448 mctx = ecdb->common.mctx;
450 LOCK(&ecdbnode->lock);
453 * Sanity check: this implementation does not allow overriding an
454 * existing rdataset of the same type.
456 for (header = ISC_LIST_HEAD(ecdbnode->rdatasets); header != NULL;
457 header = ISC_LIST_NEXT(header, link)) {
458 INSIST(header->type != rdataset->type ||
459 header->covers != rdataset->covers);
462 result = dns_rdataslab_fromrdataset(rdataset, mctx,
463 &r, sizeof(rdatasetheader_t));
464 if (result != ISC_R_SUCCESS)
465 goto unlock;
467 header = (rdatasetheader_t *)r.base;
468 header->type = rdataset->type;
469 header->ttl = rdataset->ttl;
470 header->trust = rdataset->trust;
471 header->covers = rdataset->covers;
472 header->attributes = 0;
473 if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
474 header->attributes |= RDATASET_ATTR_NXDOMAIN;
475 ISC_LINK_INIT(header, link);
476 ISC_LIST_APPEND(ecdbnode->rdatasets, header, link);
478 if (addedrdataset == NULL)
479 goto unlock;
481 bind_rdataset(ecdb, ecdbnode, header, addedrdataset);
483 unlock:
484 UNLOCK(&ecdbnode->lock);
486 return (result);
489 static isc_result_t
490 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
491 dns_rdatatype_t type, dns_rdatatype_t covers)
493 UNUSED(db);
494 UNUSED(node);
495 UNUSED(version);
496 UNUSED(type);
497 UNUSED(covers);
499 return (ISC_R_NOTIMPLEMENTED);
502 static isc_result_t
503 createiterator(dns_db_t *db, unsigned int options,
504 dns_dbiterator_t **iteratorp)
506 UNUSED(db);
507 UNUSED(options);
508 UNUSED(iteratorp);
510 return (ISC_R_NOTIMPLEMENTED);
513 static isc_result_t
514 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
515 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
517 dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
518 dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node;
519 isc_mem_t *mctx;
520 ecdb_rdatasetiter_t *iterator;
522 REQUIRE(VALID_ECDB(ecdb));
523 REQUIRE(VALID_ECDBNODE(ecdbnode));
525 mctx = ecdb->common.mctx;
527 iterator = isc_mem_get(mctx, sizeof(ecdb_rdatasetiter_t));
528 if (iterator == NULL)
529 return (ISC_R_NOMEMORY);
531 iterator->common.magic = DNS_RDATASETITER_MAGIC;
532 iterator->common.methods = &rdatasetiter_methods;
533 iterator->common.db = db;
534 iterator->common.node = NULL;
535 attachnode(db, node, &iterator->common.node);
536 iterator->common.version = version;
537 iterator->common.now = now;
539 *iteratorp = (dns_rdatasetiter_t *)iterator;
541 return (ISC_R_SUCCESS);
544 static dns_dbmethods_t ecdb_methods = {
545 attach,
546 detach,
547 NULL, /* beginload */
548 NULL, /* endload */
549 NULL, /* dump */
550 NULL, /* currentversion */
551 NULL, /* newversion */
552 NULL, /* attachversion */
553 NULL, /* closeversion */
554 findnode,
555 find,
556 findzonecut,
557 attachnode,
558 detachnode,
559 NULL, /* expirenode */
560 NULL, /* printnode */
561 createiterator, /* createiterator */
562 NULL, /* findrdataset */
563 allrdatasets,
564 addrdataset,
565 NULL, /* subtractrdataset */
566 deleterdataset,
567 NULL, /* issecure */
568 NULL, /* nodecount */
569 NULL, /* ispersistent */
570 NULL, /* overmem */
571 NULL, /* settask */
572 NULL, /* getoriginnode */
573 NULL, /* transfernode */
574 NULL, /* getnsec3parameters */
575 NULL, /* findnsec3node */
576 NULL, /* setsigningtime */
577 NULL, /* getsigningtime */
578 NULL, /* resigned */
579 NULL, /* isdnssec */
580 NULL /* getrrsetstats */
583 static isc_result_t
584 dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
585 dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
586 void *driverarg, dns_db_t **dbp)
588 dns_ecdb_t *ecdb;
589 isc_result_t result;
591 REQUIRE(mctx != NULL);
592 REQUIRE(origin == dns_rootname);
593 REQUIRE(type == dns_dbtype_cache);
594 REQUIRE(dbp != NULL && *dbp == NULL);
596 UNUSED(argc);
597 UNUSED(argv);
598 UNUSED(driverarg);
600 ecdb = isc_mem_get(mctx, sizeof(*ecdb));
601 if (ecdb == NULL)
602 return (ISC_R_NOMEMORY);
604 ecdb->common.attributes = DNS_DBATTR_CACHE;
605 ecdb->common.rdclass = rdclass;
606 ecdb->common.methods = &ecdb_methods;
607 dns_name_init(&ecdb->common.origin, NULL);
608 result = dns_name_dupwithoffsets(origin, mctx, &ecdb->common.origin);
609 if (result != ISC_R_SUCCESS) {
610 isc_mem_put(mctx, ecdb, sizeof(*ecdb));
611 return (result);
614 result = isc_mutex_init(&ecdb->lock);
615 if (result != ISC_R_SUCCESS) {
616 UNEXPECTED_ERROR(__FILE__, __LINE__,
617 "isc_mutex_init() failed: %s",
618 isc_result_totext(result));
619 if (dns_name_dynamic(&ecdb->common.origin))
620 dns_name_free(&ecdb->common.origin, mctx);
621 isc_mem_put(mctx, ecdb, sizeof(*ecdb));
622 return (ISC_R_UNEXPECTED);
625 ecdb->references = 1;
626 ISC_LIST_INIT(ecdb->nodes);
628 ecdb->common.mctx = NULL;
629 isc_mem_attach(mctx, &ecdb->common.mctx);
630 ecdb->common.impmagic = ECDB_MAGIC;
631 ecdb->common.magic = DNS_DB_MAGIC;
633 *dbp = (dns_db_t *)ecdb;
635 return (ISC_R_SUCCESS);
639 * Rdataset Methods
642 static void
643 rdataset_disassociate(dns_rdataset_t *rdataset) {
644 dns_db_t *db = rdataset->private1;
645 dns_dbnode_t *node = rdataset->private2;
647 dns_db_detachnode(db, &node);
650 static isc_result_t
651 rdataset_first(dns_rdataset_t *rdataset) {
652 unsigned char *raw = rdataset->private3;
653 unsigned int count;
655 count = raw[0] * 256 + raw[1];
656 if (count == 0) {
657 rdataset->private5 = NULL;
658 return (ISC_R_NOMORE);
660 raw += 2;
662 * The privateuint4 field is the number of rdata beyond the cursor
663 * position, so we decrement the total count by one before storing
664 * it.
666 count--;
667 rdataset->privateuint4 = count;
668 rdataset->private5 = raw;
670 return (ISC_R_SUCCESS);
673 static isc_result_t
674 rdataset_next(dns_rdataset_t *rdataset) {
675 unsigned int count;
676 unsigned int length;
677 unsigned char *raw;
679 count = rdataset->privateuint4;
680 if (count == 0)
681 return (ISC_R_NOMORE);
682 count--;
683 rdataset->privateuint4 = count;
684 raw = rdataset->private5;
685 length = raw[0] * 256 + raw[1];
686 raw += length + 2;
687 rdataset->private5 = raw;
689 return (ISC_R_SUCCESS);
692 static void
693 rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
694 unsigned char *raw = rdataset->private5;
695 isc_region_t r;
696 unsigned int length;
697 unsigned int flags = 0;
699 REQUIRE(raw != NULL);
701 length = raw[0] * 256 + raw[1];
702 raw += 2;
703 if (rdataset->type == dns_rdatatype_rrsig) {
704 if (*raw & DNS_RDATASLAB_OFFLINE)
705 flags |= DNS_RDATA_OFFLINE;
706 length--;
707 raw++;
709 r.length = length;
710 r.base = raw;
711 dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
712 rdata->flags |= flags;
715 static void
716 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
717 dns_db_t *db = source->private1;
718 dns_dbnode_t *node = source->private2;
719 dns_dbnode_t *cloned_node = NULL;
721 attachnode(db, node, &cloned_node);
722 *target = *source;
725 * Reset iterator state.
727 target->privateuint4 = 0;
728 target->private5 = NULL;
731 static unsigned int
732 rdataset_count(dns_rdataset_t *rdataset) {
733 unsigned char *raw = rdataset->private3;
734 unsigned int count;
736 count = raw[0] * 256 + raw[1];
738 return (count);
742 * Rdataset Iterator Methods
745 static void
746 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
747 ecdb_rdatasetiter_t *ecdbiterator;
748 isc_mem_t *mctx;
750 REQUIRE(iteratorp != NULL);
751 ecdbiterator = (ecdb_rdatasetiter_t *)*iteratorp;
752 REQUIRE(DNS_RDATASETITER_VALID(&ecdbiterator->common));
754 mctx = ecdbiterator->common.db->mctx;
756 ecdbiterator->common.magic = 0;
758 dns_db_detachnode(ecdbiterator->common.db, &ecdbiterator->common.node);
759 isc_mem_put(mctx, ecdbiterator, sizeof(ecdb_rdatasetiter_t));
761 *iteratorp = NULL;
764 static isc_result_t
765 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
766 ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
767 dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)iterator->node;
769 REQUIRE(DNS_RDATASETITER_VALID(iterator));
771 if (ISC_LIST_EMPTY(ecdbnode->rdatasets))
772 return (ISC_R_NOMORE);
773 ecdbiterator->current = ISC_LIST_HEAD(ecdbnode->rdatasets);
774 return (ISC_R_SUCCESS);
777 static isc_result_t
778 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
779 ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
781 REQUIRE(DNS_RDATASETITER_VALID(iterator));
783 ecdbiterator->current = ISC_LIST_NEXT(ecdbiterator->current, link);
784 if (ecdbiterator->current == NULL)
785 return (ISC_R_NOMORE);
786 else
787 return (ISC_R_SUCCESS);
790 static void
791 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
792 ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
793 dns_ecdb_t *ecdb;
795 ecdb = (dns_ecdb_t *)iterator->db;
796 REQUIRE(VALID_ECDB(ecdb));
798 bind_rdataset(ecdb, iterator->node, ecdbiterator->current, rdataset);