1 /* $NetBSD: ecdb.c,v 1.9 2015/07/08 17:28:58 christos Exp $ */
4 * Copyright (C) 2009-2014 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.
21 #include <isc/result.h>
23 #include <isc/mutex.h>
28 #include <dns/rdata.h>
29 #include <dns/rdataset.h>
30 #include <dns/rdatasetiter.h>
31 #include <dns/rdataslab.h>
33 #define ECDB_MAGIC ISC_MAGIC('E', 'C', 'D', 'B')
34 #define VALID_ECDB(db) ((db) != NULL && \
35 (db)->common.impmagic == ECDB_MAGIC)
37 #define ECDBNODE_MAGIC ISC_MAGIC('E', 'C', 'D', 'N')
38 #define VALID_ECDBNODE(ecdbn) ISC_MAGIC_VALID(ecdbn, ECDBNODE_MAGIC)
41 * The 'ephemeral' cache DB (ecdb) implementation. An ecdb just provides
42 * temporary storage for ongoing name resolution with the common DB interfaces.
43 * It actually doesn't cache anything. The implementation expects any stored
44 * data is released within a short period, and does not care about the
45 * scalability in terms of the number of nodes.
48 typedef struct dns_ecdb
{
54 unsigned int references
;
55 ISC_LIST(struct dns_ecdbnode
) nodes
;
58 typedef struct dns_ecdbnode
{
64 ISC_LINK(struct dns_ecdbnode
) link
;
67 ISC_LIST(struct rdatasetheader
) rdatasets
;
68 unsigned int references
;
71 typedef struct rdatasetheader
{
75 dns_rdatatype_t covers
;
76 unsigned int attributes
;
78 ISC_LINK(struct rdatasetheader
) link
;
81 /* Copied from rbtdb.c */
82 #define RDATASET_ATTR_NXDOMAIN 0x0010
83 #define RDATASET_ATTR_NEGATIVE 0x0100
84 #define NXDOMAIN(header) \
85 (((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
86 #define NEGATIVE(header) \
87 (((header)->attributes & RDATASET_ATTR_NEGATIVE) != 0)
89 static isc_result_t
dns_ecdb_create(isc_mem_t
*mctx
, dns_name_t
*origin
,
91 dns_rdataclass_t rdclass
,
92 unsigned int argc
, char *argv
[],
93 void *driverarg
, dns_db_t
**dbp
);
95 static void rdataset_disassociate(dns_rdataset_t
*rdataset
);
96 static isc_result_t
rdataset_first(dns_rdataset_t
*rdataset
);
97 static isc_result_t
rdataset_next(dns_rdataset_t
*rdataset
);
98 static void rdataset_current(dns_rdataset_t
*rdataset
, dns_rdata_t
*rdata
);
99 static void rdataset_clone(dns_rdataset_t
*source
, dns_rdataset_t
*target
);
100 static unsigned int rdataset_count(dns_rdataset_t
*rdataset
);
101 static void rdataset_settrust(dns_rdataset_t
*rdataset
, dns_trust_t trust
);
103 static dns_rdatasetmethods_t rdataset_methods
= {
104 rdataset_disassociate
,
110 NULL
, /* addnoqname */
111 NULL
, /* getnoqname */
112 NULL
, /* addclosest */
113 NULL
, /* getclosest */
114 NULL
, /* getadditional */
115 NULL
, /* setadditional */
116 NULL
, /* putadditional */
117 rdataset_settrust
, /* settrust */
119 NULL
/* clearprefetch */
122 typedef struct ecdb_rdatasetiter
{
123 dns_rdatasetiter_t common
;
124 rdatasetheader_t
*current
;
125 } ecdb_rdatasetiter_t
;
127 static void rdatasetiter_destroy(dns_rdatasetiter_t
**iteratorp
);
128 static isc_result_t
rdatasetiter_first(dns_rdatasetiter_t
*iterator
);
129 static isc_result_t
rdatasetiter_next(dns_rdatasetiter_t
*iterator
);
130 static void rdatasetiter_current(dns_rdatasetiter_t
*iterator
,
131 dns_rdataset_t
*rdataset
);
133 static dns_rdatasetitermethods_t rdatasetiter_methods
= {
134 rdatasetiter_destroy
,
141 dns_ecdb_register(isc_mem_t
*mctx
, dns_dbimplementation_t
**dbimp
) {
142 REQUIRE(mctx
!= NULL
);
143 REQUIRE(dbimp
!= NULL
&& *dbimp
== NULL
);
145 return (dns_db_register("ecdb", dns_ecdb_create
, NULL
, mctx
, dbimp
));
149 dns_ecdb_unregister(dns_dbimplementation_t
**dbimp
) {
150 REQUIRE(dbimp
!= NULL
&& *dbimp
!= NULL
);
152 dns_db_unregister(dbimp
);
160 attach(dns_db_t
*source
, dns_db_t
**targetp
) {
161 dns_ecdb_t
*ecdb
= (dns_ecdb_t
*)source
;
163 REQUIRE(VALID_ECDB(ecdb
));
164 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
174 destroy_ecdb(dns_ecdb_t
**ecdbp
) {
175 dns_ecdb_t
*ecdb
= *ecdbp
;
176 isc_mem_t
*mctx
= ecdb
->common
.mctx
;
178 if (dns_name_dynamic(&ecdb
->common
.origin
))
179 dns_name_free(&ecdb
->common
.origin
, mctx
);
181 DESTROYLOCK(&ecdb
->lock
);
183 ecdb
->common
.impmagic
= 0;
184 ecdb
->common
.magic
= 0;
186 isc_mem_putanddetach(&mctx
, ecdb
, sizeof(*ecdb
));
192 detach(dns_db_t
**dbp
) {
194 isc_boolean_t need_destroy
= ISC_FALSE
;
196 REQUIRE(dbp
!= NULL
);
197 ecdb
= (dns_ecdb_t
*)*dbp
;
198 REQUIRE(VALID_ECDB(ecdb
));
202 if (ecdb
->references
== 0 && ISC_LIST_EMPTY(ecdb
->nodes
))
203 need_destroy
= ISC_TRUE
;
213 attachnode(dns_db_t
*db
, dns_dbnode_t
*source
, dns_dbnode_t
**targetp
) {
214 dns_ecdb_t
*ecdb
= (dns_ecdb_t
*)db
;
215 dns_ecdbnode_t
*node
= (dns_ecdbnode_t
*)source
;
217 REQUIRE(VALID_ECDB(ecdb
));
218 REQUIRE(VALID_ECDBNODE(node
));
219 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
222 INSIST(node
->references
> 0);
224 INSIST(node
->references
!= 0); /* Catch overflow. */
231 destroynode(dns_ecdbnode_t
*node
) {
233 dns_ecdb_t
*ecdb
= node
->ecdb
;
234 isc_boolean_t need_destroydb
= ISC_FALSE
;
235 rdatasetheader_t
*header
;
237 mctx
= ecdb
->common
.mctx
;
240 ISC_LIST_UNLINK(ecdb
->nodes
, node
, link
);
241 if (ecdb
->references
== 0 && ISC_LIST_EMPTY(ecdb
->nodes
))
242 need_destroydb
= ISC_TRUE
;
245 dns_name_free(&node
->name
, mctx
);
247 while ((header
= ISC_LIST_HEAD(node
->rdatasets
)) != NULL
) {
248 unsigned int headersize
;
250 ISC_LIST_UNLINK(node
->rdatasets
, header
, link
);
252 dns_rdataslab_size((unsigned char *)header
,
254 isc_mem_put(mctx
, header
, headersize
);
257 DESTROYLOCK(&node
->lock
);
260 isc_mem_put(mctx
, node
, sizeof(*node
));
267 detachnode(dns_db_t
*db
, dns_dbnode_t
**nodep
) {
268 dns_ecdb_t
*ecdb
= (dns_ecdb_t
*)db
;
269 dns_ecdbnode_t
*node
;
270 isc_boolean_t need_destroy
= ISC_FALSE
;
272 REQUIRE(VALID_ECDB(ecdb
));
273 REQUIRE(nodep
!= NULL
);
274 node
= (dns_ecdbnode_t
*)*nodep
;
275 REQUIRE(VALID_ECDBNODE(node
));
277 UNUSED(ecdb
); /* in case REQUIRE() is empty */
280 INSIST(node
->references
> 0);
282 if (node
->references
== 0)
283 need_destroy
= ISC_TRUE
;
293 find(dns_db_t
*db
, dns_name_t
*name
, dns_dbversion_t
*version
,
294 dns_rdatatype_t type
, unsigned int options
, isc_stdtime_t now
,
295 dns_dbnode_t
**nodep
, dns_name_t
*foundname
, dns_rdataset_t
*rdataset
,
296 dns_rdataset_t
*sigrdataset
)
298 dns_ecdb_t
*ecdb
= (dns_ecdb_t
*)db
;
300 REQUIRE(VALID_ECDB(ecdb
));
312 return (ISC_R_NOTFOUND
);
316 findzonecut(dns_db_t
*db
, dns_name_t
*name
,
317 unsigned int options
, isc_stdtime_t now
,
318 dns_dbnode_t
**nodep
, dns_name_t
*foundname
,
319 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
321 dns_ecdb_t
*ecdb
= (dns_ecdb_t
*)db
;
323 REQUIRE(VALID_ECDB(ecdb
));
333 return (ISC_R_NOTFOUND
);
337 findnode(dns_db_t
*db
, dns_name_t
*name
, isc_boolean_t create
,
338 dns_dbnode_t
**nodep
)
340 dns_ecdb_t
*ecdb
= (dns_ecdb_t
*)db
;
342 dns_ecdbnode_t
*node
;
345 REQUIRE(VALID_ECDB(ecdb
));
346 REQUIRE(nodep
!= NULL
&& *nodep
== NULL
);
350 if (create
!= ISC_TRUE
) {
351 /* an 'ephemeral' node is never reused. */
352 return (ISC_R_NOTFOUND
);
355 mctx
= ecdb
->common
.mctx
;
356 node
= isc_mem_get(mctx
, sizeof(*node
));
358 return (ISC_R_NOMEMORY
);
360 result
= isc_mutex_init(&node
->lock
);
361 if (result
!= ISC_R_SUCCESS
) {
362 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
363 "isc_mutex_init() failed: %s",
364 isc_result_totext(result
));
365 isc_mem_put(mctx
, node
, sizeof(*node
));
366 return (ISC_R_UNEXPECTED
);
369 dns_name_init(&node
->name
, NULL
);
370 result
= dns_name_dup(name
, mctx
, &node
->name
);
371 if (result
!= ISC_R_SUCCESS
) {
372 DESTROYLOCK(&node
->lock
);
373 isc_mem_put(mctx
, node
, sizeof(*node
));
377 node
->references
= 1;
378 ISC_LIST_INIT(node
->rdatasets
);
380 ISC_LINK_INIT(node
, link
);
383 ISC_LIST_APPEND(ecdb
->nodes
, node
, link
);
386 node
->magic
= ECDBNODE_MAGIC
;
390 return (ISC_R_SUCCESS
);
394 bind_rdataset(dns_ecdb_t
*ecdb
, dns_ecdbnode_t
*node
,
395 rdatasetheader_t
*header
, dns_rdataset_t
*rdataset
)
400 * Caller must be holding the node lock.
403 REQUIRE(!dns_rdataset_isassociated(rdataset
));
405 rdataset
->methods
= &rdataset_methods
;
406 rdataset
->rdclass
= ecdb
->common
.rdclass
;
407 rdataset
->type
= header
->type
;
408 rdataset
->covers
= header
->covers
;
409 rdataset
->ttl
= header
->ttl
;
410 rdataset
->trust
= header
->trust
;
411 if (NXDOMAIN(header
))
412 rdataset
->attributes
|= DNS_RDATASETATTR_NXDOMAIN
;
413 if (NEGATIVE(header
))
414 rdataset
->attributes
|= DNS_RDATASETATTR_NEGATIVE
;
416 rdataset
->private1
= ecdb
;
417 rdataset
->private2
= node
;
418 raw
= (unsigned char *)header
+ sizeof(*header
);
419 rdataset
->private3
= raw
;
423 * Reset iterator state.
425 rdataset
->privateuint4
= 0;
426 rdataset
->private5
= NULL
;
428 INSIST(node
->references
> 0);
433 addrdataset(dns_db_t
*db
, dns_dbnode_t
*node
, dns_dbversion_t
*version
,
434 isc_stdtime_t now
, dns_rdataset_t
*rdataset
, unsigned int options
,
435 dns_rdataset_t
*addedrdataset
)
437 dns_ecdb_t
*ecdb
= (dns_ecdb_t
*)db
;
439 isc_result_t result
= ISC_R_SUCCESS
;
441 dns_ecdbnode_t
*ecdbnode
= (dns_ecdbnode_t
*)node
;
442 rdatasetheader_t
*header
;
444 REQUIRE(VALID_ECDB(ecdb
));
445 REQUIRE(VALID_ECDBNODE(ecdbnode
));
451 mctx
= ecdb
->common
.mctx
;
453 LOCK(&ecdbnode
->lock
);
456 * Sanity check: this implementation does not allow overriding an
457 * existing rdataset of the same type.
459 for (header
= ISC_LIST_HEAD(ecdbnode
->rdatasets
); header
!= NULL
;
460 header
= ISC_LIST_NEXT(header
, link
)) {
461 INSIST(header
->type
!= rdataset
->type
||
462 header
->covers
!= rdataset
->covers
);
465 result
= dns_rdataslab_fromrdataset(rdataset
, mctx
,
466 &r
, sizeof(rdatasetheader_t
));
467 if (result
!= ISC_R_SUCCESS
)
470 header
= (rdatasetheader_t
*)r
.base
;
471 header
->type
= rdataset
->type
;
472 header
->ttl
= rdataset
->ttl
;
473 header
->trust
= rdataset
->trust
;
474 header
->covers
= rdataset
->covers
;
475 header
->attributes
= 0;
476 if ((rdataset
->attributes
& DNS_RDATASETATTR_NXDOMAIN
) != 0)
477 header
->attributes
|= RDATASET_ATTR_NXDOMAIN
;
478 if ((rdataset
->attributes
& DNS_RDATASETATTR_NEGATIVE
) != 0)
479 header
->attributes
|= RDATASET_ATTR_NEGATIVE
;
480 ISC_LINK_INIT(header
, link
);
481 ISC_LIST_APPEND(ecdbnode
->rdatasets
, header
, link
);
483 if (addedrdataset
== NULL
)
486 bind_rdataset(ecdb
, ecdbnode
, header
, addedrdataset
);
489 UNLOCK(&ecdbnode
->lock
);
495 deleterdataset(dns_db_t
*db
, dns_dbnode_t
*node
, dns_dbversion_t
*version
,
496 dns_rdatatype_t type
, dns_rdatatype_t covers
)
504 return (ISC_R_NOTIMPLEMENTED
);
508 createiterator(dns_db_t
*db
, unsigned int options
,
509 dns_dbiterator_t
**iteratorp
)
515 return (ISC_R_NOTIMPLEMENTED
);
519 allrdatasets(dns_db_t
*db
, dns_dbnode_t
*node
, dns_dbversion_t
*version
,
520 isc_stdtime_t now
, dns_rdatasetiter_t
**iteratorp
)
522 dns_ecdb_t
*ecdb
= (dns_ecdb_t
*)db
;
523 dns_ecdbnode_t
*ecdbnode
= (dns_ecdbnode_t
*)node
;
525 ecdb_rdatasetiter_t
*iterator
;
527 REQUIRE(VALID_ECDB(ecdb
));
528 REQUIRE(VALID_ECDBNODE(ecdbnode
));
530 mctx
= ecdb
->common
.mctx
;
532 iterator
= isc_mem_get(mctx
, sizeof(ecdb_rdatasetiter_t
));
533 if (iterator
== NULL
)
534 return (ISC_R_NOMEMORY
);
536 iterator
->common
.magic
= DNS_RDATASETITER_MAGIC
;
537 iterator
->common
.methods
= &rdatasetiter_methods
;
538 iterator
->common
.db
= db
;
539 iterator
->common
.node
= NULL
;
540 attachnode(db
, node
, &iterator
->common
.node
);
541 iterator
->common
.version
= version
;
542 iterator
->common
.now
= now
;
544 *iteratorp
= (dns_rdatasetiter_t
*)iterator
;
546 return (ISC_R_SUCCESS
);
549 static dns_dbmethods_t ecdb_methods
= {
552 NULL
, /* beginload */
554 NULL
, /* serialize */
556 NULL
, /* currentversion */
557 NULL
, /* newversion */
558 NULL
, /* attachversion */
559 NULL
, /* closeversion */
565 NULL
, /* expirenode */
566 NULL
, /* printnode */
567 createiterator
, /* createiterator */
568 NULL
, /* findrdataset */
571 NULL
, /* subtractrdataset */
574 NULL
, /* nodecount */
575 NULL
, /* ispersistent */
578 NULL
, /* getoriginnode */
579 NULL
, /* transfernode */
580 NULL
, /* getnsec3parameters */
581 NULL
, /* findnsec3node */
582 NULL
, /* setsigningtime */
583 NULL
, /* getsigningtime */
586 NULL
, /* getrrsetstats */
587 NULL
, /* rpz_attach */
588 NULL
, /* rpz_ready */
589 NULL
, /* findnodeext */
591 NULL
, /* setcachestats */
596 dns_ecdb_create(isc_mem_t
*mctx
, dns_name_t
*origin
, dns_dbtype_t type
,
597 dns_rdataclass_t rdclass
, unsigned int argc
, char *argv
[],
598 void *driverarg
, dns_db_t
**dbp
)
603 REQUIRE(mctx
!= NULL
);
604 REQUIRE(origin
== dns_rootname
);
605 REQUIRE(type
== dns_dbtype_cache
);
606 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
612 ecdb
= isc_mem_get(mctx
, sizeof(*ecdb
));
614 return (ISC_R_NOMEMORY
);
616 ecdb
->common
.attributes
= DNS_DBATTR_CACHE
;
617 ecdb
->common
.rdclass
= rdclass
;
618 ecdb
->common
.methods
= &ecdb_methods
;
619 dns_name_init(&ecdb
->common
.origin
, NULL
);
620 result
= dns_name_dupwithoffsets(origin
, mctx
, &ecdb
->common
.origin
);
621 if (result
!= ISC_R_SUCCESS
) {
622 isc_mem_put(mctx
, ecdb
, sizeof(*ecdb
));
626 result
= isc_mutex_init(&ecdb
->lock
);
627 if (result
!= ISC_R_SUCCESS
) {
628 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
629 "isc_mutex_init() failed: %s",
630 isc_result_totext(result
));
631 if (dns_name_dynamic(&ecdb
->common
.origin
))
632 dns_name_free(&ecdb
->common
.origin
, mctx
);
633 isc_mem_put(mctx
, ecdb
, sizeof(*ecdb
));
634 return (ISC_R_UNEXPECTED
);
637 ecdb
->references
= 1;
638 ISC_LIST_INIT(ecdb
->nodes
);
640 ecdb
->common
.mctx
= NULL
;
641 isc_mem_attach(mctx
, &ecdb
->common
.mctx
);
642 ecdb
->common
.impmagic
= ECDB_MAGIC
;
643 ecdb
->common
.magic
= DNS_DB_MAGIC
;
645 *dbp
= (dns_db_t
*)ecdb
;
647 return (ISC_R_SUCCESS
);
655 rdataset_disassociate(dns_rdataset_t
*rdataset
) {
656 dns_db_t
*db
= rdataset
->private1
;
657 dns_dbnode_t
*node
= rdataset
->private2
;
659 dns_db_detachnode(db
, &node
);
663 rdataset_first(dns_rdataset_t
*rdataset
) {
664 unsigned char *raw
= rdataset
->private3
;
667 count
= raw
[0] * 256 + raw
[1];
669 rdataset
->private5
= NULL
;
670 return (ISC_R_NOMORE
);
672 #if DNS_RDATASET_FIXED
673 raw
+= 2 + (4 * count
);
678 * The privateuint4 field is the number of rdata beyond the cursor
679 * position, so we decrement the total count by one before storing
683 rdataset
->privateuint4
= count
;
684 rdataset
->private5
= raw
;
686 return (ISC_R_SUCCESS
);
690 rdataset_next(dns_rdataset_t
*rdataset
) {
695 count
= rdataset
->privateuint4
;
697 return (ISC_R_NOMORE
);
699 rdataset
->privateuint4
= count
;
700 raw
= rdataset
->private5
;
701 length
= raw
[0] * 256 + raw
[1];
702 #if DNS_RDATASET_FIXED
707 rdataset
->private5
= raw
;
709 return (ISC_R_SUCCESS
);
713 rdataset_current(dns_rdataset_t
*rdataset
, dns_rdata_t
*rdata
) {
714 unsigned char *raw
= rdataset
->private5
;
717 unsigned int flags
= 0;
719 REQUIRE(raw
!= NULL
);
721 length
= raw
[0] * 256 + raw
[1];
722 #if DNS_RDATASET_FIXED
727 if (rdataset
->type
== dns_rdatatype_rrsig
) {
728 if (*raw
& DNS_RDATASLAB_OFFLINE
)
729 flags
|= DNS_RDATA_OFFLINE
;
735 dns_rdata_fromregion(rdata
, rdataset
->rdclass
, rdataset
->type
, &r
);
736 rdata
->flags
|= flags
;
740 rdataset_clone(dns_rdataset_t
*source
, dns_rdataset_t
*target
) {
741 dns_db_t
*db
= source
->private1
;
742 dns_dbnode_t
*node
= source
->private2
;
743 dns_dbnode_t
*cloned_node
= NULL
;
745 attachnode(db
, node
, &cloned_node
);
749 * Reset iterator state.
751 target
->privateuint4
= 0;
752 target
->private5
= NULL
;
756 rdataset_count(dns_rdataset_t
*rdataset
) {
757 unsigned char *raw
= rdataset
->private3
;
760 count
= raw
[0] * 256 + raw
[1];
766 rdataset_settrust(dns_rdataset_t
*rdataset
, dns_trust_t trust
) {
767 rdatasetheader_t
*header
= rdataset
->private3
;
770 header
->trust
= rdataset
->trust
= trust
;
774 * Rdataset Iterator Methods
778 rdatasetiter_destroy(dns_rdatasetiter_t
**iteratorp
) {
781 dns_rdatasetiter_t
*rdatasetiterator
;
782 ecdb_rdatasetiter_t
*ecdbiterator
;
785 REQUIRE(iteratorp
!= NULL
);
786 REQUIRE(DNS_RDATASETITER_VALID(*iteratorp
));
788 u
.rdatasetiterator
= *iteratorp
;
790 mctx
= u
.ecdbiterator
->common
.db
->mctx
;
791 u
.ecdbiterator
->common
.magic
= 0;
793 dns_db_detachnode(u
.ecdbiterator
->common
.db
,
794 &u
.ecdbiterator
->common
.node
);
795 isc_mem_put(mctx
, u
.ecdbiterator
,
796 sizeof(ecdb_rdatasetiter_t
));
802 rdatasetiter_first(dns_rdatasetiter_t
*iterator
) {
803 ecdb_rdatasetiter_t
*ecdbiterator
= (ecdb_rdatasetiter_t
*)iterator
;
804 dns_ecdbnode_t
*ecdbnode
= (dns_ecdbnode_t
*)iterator
->node
;
806 REQUIRE(DNS_RDATASETITER_VALID(iterator
));
808 if (ISC_LIST_EMPTY(ecdbnode
->rdatasets
))
809 return (ISC_R_NOMORE
);
810 ecdbiterator
->current
= ISC_LIST_HEAD(ecdbnode
->rdatasets
);
811 return (ISC_R_SUCCESS
);
815 rdatasetiter_next(dns_rdatasetiter_t
*iterator
) {
816 ecdb_rdatasetiter_t
*ecdbiterator
= (ecdb_rdatasetiter_t
*)iterator
;
818 REQUIRE(DNS_RDATASETITER_VALID(iterator
));
820 ecdbiterator
->current
= ISC_LIST_NEXT(ecdbiterator
->current
, link
);
821 if (ecdbiterator
->current
== NULL
)
822 return (ISC_R_NOMORE
);
824 return (ISC_R_SUCCESS
);
828 rdatasetiter_current(dns_rdatasetiter_t
*iterator
, dns_rdataset_t
*rdataset
) {
829 ecdb_rdatasetiter_t
*ecdbiterator
= (ecdb_rdatasetiter_t
*)iterator
;
832 ecdb
= (dns_ecdb_t
*)iterator
->db
;
833 REQUIRE(VALID_ECDB(ecdb
));
835 bind_rdataset(ecdb
, iterator
->node
, ecdbiterator
->current
, rdataset
);