Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / sdb.c
blobc810cd4236b428b63af4fbddde9533810fc6a608
1 /*
2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: sdb.c,v 1.35.2.6 2004/07/22 04:04:41 marka Exp $ */
20 #include <config.h>
22 #include <string.h>
24 #include <isc/buffer.h>
25 #include <isc/lex.h>
26 #include <isc/log.h>
27 #include <isc/magic.h>
28 #include <isc/mem.h>
29 #include <isc/once.h>
30 #include <isc/print.h>
31 #include <isc/region.h>
32 #include <isc/util.h>
34 #include <dns/callbacks.h>
35 #include <dns/db.h>
36 #include <dns/dbiterator.h>
37 #include <dns/fixedname.h>
38 #include <dns/log.h>
39 #include <dns/rdata.h>
40 #include <dns/rdatalist.h>
41 #include <dns/rdataset.h>
42 #include <dns/rdatasetiter.h>
43 #include <dns/rdatatype.h>
44 #include <dns/result.h>
45 #include <dns/sdb.h>
46 #include <dns/types.h>
48 #include "rdatalist_p.h"
50 struct dns_sdbimplementation {
51 const dns_sdbmethods_t *methods;
52 void *driverdata;
53 unsigned int flags;
54 isc_mem_t *mctx;
55 isc_mutex_t driverlock;
56 dns_dbimplementation_t *dbimp;
59 struct dns_sdb {
60 /* Unlocked */
61 dns_db_t common;
62 char *zone;
63 dns_sdbimplementation_t *implementation;
64 void *dbdata;
65 isc_mutex_t lock;
66 /* Locked */
67 unsigned int references;
70 struct dns_sdblookup {
71 /* Unlocked */
72 unsigned int magic;
73 dns_sdb_t *sdb;
74 ISC_LIST(dns_rdatalist_t) lists;
75 ISC_LIST(isc_buffer_t) buffers;
76 dns_name_t *name;
77 ISC_LINK(dns_sdblookup_t) link;
78 isc_mutex_t lock;
79 dns_rdatacallbacks_t callbacks;
80 /* Locked */
81 unsigned int references;
84 typedef struct dns_sdblookup dns_sdbnode_t;
86 struct dns_sdballnodes {
87 dns_dbiterator_t common;
88 ISC_LIST(dns_sdbnode_t) nodelist;
89 dns_sdbnode_t *current;
90 dns_sdbnode_t *origin;
93 typedef dns_sdballnodes_t sdb_dbiterator_t;
95 typedef struct sdb_rdatasetiter {
96 dns_rdatasetiter_t common;
97 dns_rdatalist_t *current;
98 } sdb_rdatasetiter_t;
100 #define SDB_MAGIC ISC_MAGIC('S', 'D', 'B', '-')
103 * Note that "impmagic" is not the first four bytes of the struct, so
104 * ISC_MAGIC_VALID cannot be used.
106 #define VALID_SDB(sdb) ((sdb) != NULL && \
107 (sdb)->common.impmagic == SDB_MAGIC)
109 #define SDBLOOKUP_MAGIC ISC_MAGIC('S','D','B','L')
110 #define VALID_SDBLOOKUP(sdbl) ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)
111 #define VALID_SDBNODE(sdbn) VALID_SDBLOOKUP(sdbn)
113 /* These values are taken from RFC 1537 */
114 #define SDB_DEFAULT_REFRESH (60 * 60 * 8)
115 #define SDB_DEFAULT_RETRY (60 * 60 * 2)
116 #define SDB_DEFAULT_EXPIRE (60 * 60 * 24 * 7)
117 #define SDB_DEFAULT_MINIMUM (60 * 60 * 24)
119 /* This is a reasonable value */
120 #define SDB_DEFAULT_TTL (60 * 60 * 24)
122 #define MAYBE_LOCK(sdb) \
123 do { \
124 unsigned int flags = sdb->implementation->flags; \
125 if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \
126 LOCK(&sdb->implementation->driverlock); \
127 } while (0)
129 #define MAYBE_UNLOCK(sdb) \
130 do { \
131 unsigned int flags = sdb->implementation->flags; \
132 if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \
133 UNLOCK(&sdb->implementation->driverlock); \
134 } while (0)
136 static int dummy;
138 static isc_result_t dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin,
139 dns_dbtype_t type, dns_rdataclass_t rdclass,
140 unsigned int argc, char *argv[],
141 void *driverarg, dns_db_t **dbp);
143 static isc_result_t findrdataset(dns_db_t *db, dns_dbnode_t *node,
144 dns_dbversion_t *version,
145 dns_rdatatype_t type, dns_rdatatype_t covers,
146 isc_stdtime_t now, dns_rdataset_t *rdataset,
147 dns_rdataset_t *sigrdataset);
149 static isc_result_t createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep);
151 static void destroynode(dns_sdbnode_t *node);
153 static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
156 static void list_tordataset(dns_rdatalist_t *rdatalist,
157 dns_db_t *db, dns_dbnode_t *node,
158 dns_rdataset_t *rdataset);
160 static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
161 static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
162 static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
163 static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
164 dns_name_t *name);
165 static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
166 static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
167 static isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
168 dns_dbnode_t **nodep,
169 dns_name_t *name);
170 static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
171 static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
172 dns_name_t *name);
174 static dns_dbiteratormethods_t dbiterator_methods = {
175 dbiterator_destroy,
176 dbiterator_first,
177 dbiterator_last,
178 dbiterator_seek,
179 dbiterator_prev,
180 dbiterator_next,
181 dbiterator_current,
182 dbiterator_pause,
183 dbiterator_origin
186 static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
187 static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator);
188 static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator);
189 static void rdatasetiter_current(dns_rdatasetiter_t *iterator,
190 dns_rdataset_t *rdataset);
192 static dns_rdatasetitermethods_t rdatasetiter_methods = {
193 rdatasetiter_destroy,
194 rdatasetiter_first,
195 rdatasetiter_next,
196 rdatasetiter_current
200 * Functions used by implementors of simple databases
202 isc_result_t
203 dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
204 void *driverdata, unsigned int flags, isc_mem_t *mctx,
205 dns_sdbimplementation_t **sdbimp)
207 dns_sdbimplementation_t *imp;
208 isc_result_t result;
210 REQUIRE(drivername != NULL);
211 REQUIRE(methods != NULL);
212 REQUIRE(methods->lookup != NULL);
213 REQUIRE(mctx != NULL);
214 REQUIRE(sdbimp != NULL && *sdbimp == NULL);
215 REQUIRE((flags & ~(DNS_SDBFLAG_RELATIVEOWNER |
216 DNS_SDBFLAG_RELATIVERDATA |
217 DNS_SDBFLAG_THREADSAFE)) == 0);
219 imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t));
220 if (imp == NULL)
221 return (ISC_R_NOMEMORY);
222 imp->methods = methods;
223 imp->driverdata = driverdata;
224 imp->flags = flags;
225 imp->mctx = NULL;
226 isc_mem_attach(mctx, &imp->mctx);
227 result = isc_mutex_init(&imp->driverlock);
228 if (result != ISC_R_SUCCESS) {
229 UNEXPECTED_ERROR(__FILE__, __LINE__,
230 "isc_mutex_init() failed: %s",
231 isc_result_totext(result));
232 goto cleanup_mctx;
235 imp->dbimp = NULL;
236 result = dns_db_register(drivername, dns_sdb_create, imp, mctx,
237 &imp->dbimp);
238 if (result != ISC_R_SUCCESS)
239 goto cleanup_mutex;
240 *sdbimp = imp;
242 return (ISC_R_SUCCESS);
244 cleanup_mutex:
245 DESTROYLOCK(&imp->driverlock);
246 cleanup_mctx:
247 isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
248 return (result);
251 void
252 dns_sdb_unregister(dns_sdbimplementation_t **sdbimp) {
253 dns_sdbimplementation_t *imp;
254 isc_mem_t *mctx;
256 REQUIRE(sdbimp != NULL && *sdbimp != NULL);
258 imp = *sdbimp;
259 dns_db_unregister(&imp->dbimp);
260 DESTROYLOCK(&imp->driverlock);
262 mctx = imp->mctx;
263 isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
264 isc_mem_detach(&mctx);
266 *sdbimp = NULL;
269 static inline unsigned int
270 initial_size(const char *data) {
271 unsigned int len = strlen(data);
272 unsigned int size;
273 for (size = 64; size < (64 * 1024); size *= 2)
274 if (len < size)
275 return (size);
276 return (64 * 1024);
279 isc_result_t
280 dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
281 const char *data)
283 dns_rdatalist_t *rdatalist;
284 dns_rdata_t *rdata;
285 dns_rdatatype_t typeval;
286 isc_textregion_t r;
287 isc_buffer_t b;
288 isc_buffer_t *rdatabuf;
289 isc_lex_t *lex;
290 isc_result_t result;
291 unsigned int size;
292 isc_mem_t *mctx;
293 dns_sdbimplementation_t *imp;
294 dns_name_t *origin;
296 REQUIRE(VALID_SDBLOOKUP(lookup));
297 REQUIRE(type != NULL);
298 REQUIRE(data != NULL);
300 mctx = lookup->sdb->common.mctx;
302 DE_CONST(type, r.base);
303 r.length = strlen(type);
304 result = dns_rdatatype_fromtext(&typeval, &r);
305 if (result != ISC_R_SUCCESS)
306 return (result);
308 rdatalist = ISC_LIST_HEAD(lookup->lists);
309 while (rdatalist != NULL) {
310 if (rdatalist->type == typeval)
311 break;
312 rdatalist = ISC_LIST_NEXT(rdatalist, link);
315 if (rdatalist == NULL) {
316 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
317 if (rdatalist == NULL)
318 return (ISC_R_NOMEMORY);
319 rdatalist->rdclass = lookup->sdb->common.rdclass;
320 rdatalist->type = typeval;
321 rdatalist->covers = 0;
322 rdatalist->ttl = ttl;
323 ISC_LIST_INIT(rdatalist->rdata);
324 ISC_LINK_INIT(rdatalist, link);
325 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
326 } else
327 if (rdatalist->ttl != ttl)
328 return (DNS_R_BADTTL);
330 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
331 if (rdata == NULL)
332 return (ISC_R_NOMEMORY);
333 dns_rdata_init(rdata);
335 imp = lookup->sdb->implementation;
336 if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
337 origin = &lookup->sdb->common.origin;
338 else
339 origin = dns_rootname;
341 lex = NULL;
342 result = isc_lex_create(mctx, 64, &lex);
343 if (result != ISC_R_SUCCESS)
344 goto failure;
346 size = initial_size(data);
347 do {
348 isc_buffer_init(&b, data, strlen(data));
349 isc_buffer_add(&b, strlen(data));
351 result = isc_lex_openbuffer(lex, &b);
352 if (result != ISC_R_SUCCESS)
353 goto failure;
355 rdatabuf = NULL;
356 result = isc_buffer_allocate(mctx, &rdatabuf, size);
357 if (result != ISC_R_SUCCESS)
358 goto failure;
360 result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
361 rdatalist->type, lex,
362 origin, ISC_FALSE,
363 mctx, rdatabuf,
364 &lookup->callbacks);
365 if (result != ISC_R_SUCCESS)
366 isc_buffer_free(&rdatabuf);
367 size *= 2;
368 } while (result == ISC_R_NOSPACE);
370 if (result != ISC_R_SUCCESS)
371 goto failure;
373 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
374 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
376 if (lex != NULL)
377 isc_lex_destroy(&lex);
379 return (ISC_R_SUCCESS);
381 failure:
383 if (rdatabuf != NULL)
384 isc_buffer_free(&rdatabuf);
385 if (lex != NULL)
386 isc_lex_destroy(&lex);
387 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
389 return (result);
392 isc_result_t
393 dns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name,
394 const char *type, dns_ttl_t ttl, const char *data)
396 dns_name_t *newname, *origin;
397 dns_fixedname_t fnewname;
398 dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db;
399 dns_sdbimplementation_t *imp = sdb->implementation;
400 dns_sdbnode_t *sdbnode;
401 isc_mem_t *mctx = sdb->common.mctx;
402 isc_buffer_t b;
403 isc_result_t result;
405 dns_fixedname_init(&fnewname);
406 newname = dns_fixedname_name(&fnewname);
408 if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
409 origin = &sdb->common.origin;
410 else
411 origin = dns_rootname;
412 isc_buffer_init(&b, name, strlen(name));
413 isc_buffer_add(&b, strlen(name));
415 result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL);
416 if (result != ISC_R_SUCCESS)
417 return (result);
419 if (allnodes->common.relative_names) {
420 /* All names are relative to the root */
421 unsigned int nlabels = dns_name_countlabels(newname);
422 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
425 sdbnode = ISC_LIST_HEAD(allnodes->nodelist);
426 if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) {
427 sdbnode = NULL;
428 result = createnode(sdb, &sdbnode);
429 if (result != ISC_R_SUCCESS)
430 return (result);
431 sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t));
432 if (sdbnode->name == NULL) {
433 destroynode(sdbnode);
434 return (ISC_R_NOMEMORY);
436 dns_name_init(sdbnode->name, NULL);
437 result = dns_name_dup(newname, mctx, sdbnode->name);
438 if (result != ISC_R_SUCCESS) {
439 isc_mem_put(mctx, sdbnode->name, sizeof(dns_name_t));
440 destroynode(sdbnode);
441 return (result);
443 ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link);
444 if (allnodes->origin == NULL &&
445 dns_name_equal(newname, &sdb->common.origin))
446 allnodes->origin = sdbnode;
448 return (dns_sdb_putrr(sdbnode, type, ttl, data));
452 isc_result_t
453 dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
454 isc_uint32_t serial)
456 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
457 int n;
459 REQUIRE(mname != NULL);
460 REQUIRE(rname != NULL);
462 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
463 mname, rname, serial,
464 SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY,
465 SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM);
466 if (n >= (int)sizeof(str) || n < 0)
467 return (ISC_R_NOSPACE);
468 return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));
472 * DB routines
475 static void
476 attach(dns_db_t *source, dns_db_t **targetp) {
477 dns_sdb_t *sdb = (dns_sdb_t *) source;
479 REQUIRE(VALID_SDB(sdb));
481 LOCK(&sdb->lock);
482 REQUIRE(sdb->references > 0);
483 sdb->references++;
484 UNLOCK(&sdb->lock);
486 *targetp = source;
489 static void
490 destroy(dns_sdb_t *sdb) {
491 isc_mem_t *mctx;
492 dns_sdbimplementation_t *imp = sdb->implementation;
494 mctx = sdb->common.mctx;
496 if (imp->methods->destroy != NULL) {
497 MAYBE_LOCK(sdb);
498 imp->methods->destroy(sdb->zone, imp->driverdata,
499 &sdb->dbdata);
500 MAYBE_UNLOCK(sdb);
503 isc_mem_free(mctx, sdb->zone);
504 DESTROYLOCK(&sdb->lock);
506 sdb->common.magic = 0;
507 sdb->common.impmagic = 0;
509 dns_name_free(&sdb->common.origin, mctx);
511 isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
512 isc_mem_detach(&mctx);
515 static void
516 detach(dns_db_t **dbp) {
517 dns_sdb_t *sdb = (dns_sdb_t *)(*dbp);
518 isc_boolean_t need_destroy = ISC_FALSE;
520 REQUIRE(VALID_SDB(sdb));
521 LOCK(&sdb->lock);
522 REQUIRE(sdb->references > 0);
523 sdb->references--;
524 if (sdb->references == 0)
525 need_destroy = ISC_TRUE;
526 UNLOCK(&sdb->lock);
528 if (need_destroy)
529 destroy(sdb);
531 *dbp = NULL;
534 static isc_result_t
535 beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
536 UNUSED(db);
537 UNUSED(addp);
538 UNUSED(dbloadp);
539 return (ISC_R_NOTIMPLEMENTED);
542 static isc_result_t
543 endload(dns_db_t *db, dns_dbload_t **dbloadp) {
544 UNUSED(db);
545 UNUSED(dbloadp);
546 return (ISC_R_NOTIMPLEMENTED);
549 static isc_result_t
550 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename) {
551 UNUSED(db);
552 UNUSED(version);
553 UNUSED(filename);
554 return (ISC_R_NOTIMPLEMENTED);
557 static void
558 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
559 REQUIRE(versionp != NULL && *versionp == NULL);
561 UNUSED(db);
563 *versionp = (void *) &dummy;
564 return;
567 static isc_result_t
568 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
569 UNUSED(db);
570 UNUSED(versionp);
572 return (ISC_R_NOTIMPLEMENTED);
575 static void
576 attachversion(dns_db_t *db, dns_dbversion_t *source,
577 dns_dbversion_t **targetp)
579 REQUIRE(source != NULL && source == (void *) &dummy);
580 REQUIRE(targetp != NULL && *targetp == NULL);
582 UNUSED(db);
583 *targetp = source;
584 return;
587 static void
588 closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
589 REQUIRE(versionp != NULL && *versionp == (void *) &dummy);
590 REQUIRE(commit == ISC_FALSE);
592 UNUSED(db);
593 UNUSED(commit);
595 *versionp = NULL;
598 static isc_result_t
599 createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) {
600 dns_sdbnode_t *node;
601 isc_result_t result;
603 node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t));
604 if (node == NULL)
605 return (ISC_R_NOMEMORY);
607 node->sdb = NULL;
608 attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb);
609 ISC_LIST_INIT(node->lists);
610 ISC_LIST_INIT(node->buffers);
611 ISC_LINK_INIT(node, link);
612 node->name = NULL;
613 result = isc_mutex_init(&node->lock);
614 if (result != ISC_R_SUCCESS) {
615 UNEXPECTED_ERROR(__FILE__, __LINE__,
616 "isc_mutex_init() failed: %s",
617 isc_result_totext(result));
618 isc_mem_put(sdb->common.mctx, node, sizeof(dns_sdbnode_t));
619 return (ISC_R_UNEXPECTED);
621 dns_rdatacallbacks_init(&node->callbacks);
622 node->references = 1;
623 node->magic = SDBLOOKUP_MAGIC;
625 *nodep = node;
626 return (ISC_R_SUCCESS);
629 static void
630 destroynode(dns_sdbnode_t *node) {
631 dns_rdatalist_t *list;
632 dns_rdata_t *rdata;
633 isc_buffer_t *b;
634 dns_sdb_t *sdb;
635 isc_mem_t *mctx;
637 sdb = node->sdb;
638 mctx = sdb->common.mctx;
640 while (!ISC_LIST_EMPTY(node->lists)) {
641 list = ISC_LIST_HEAD(node->lists);
642 while (!ISC_LIST_EMPTY(list->rdata)) {
643 rdata = ISC_LIST_HEAD(list->rdata);
644 ISC_LIST_UNLINK(list->rdata, rdata, link);
645 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
647 ISC_LIST_UNLINK(node->lists, list, link);
648 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
651 while (!ISC_LIST_EMPTY(node->buffers)) {
652 b = ISC_LIST_HEAD(node->buffers);
653 ISC_LIST_UNLINK(node->buffers, b, link);
654 isc_buffer_free(&b);
657 if (node->name != NULL) {
658 dns_name_free(node->name, mctx);
659 isc_mem_put(mctx, node->name, sizeof(dns_name_t));
661 DESTROYLOCK(&node->lock);
662 node->magic = 0;
663 isc_mem_put(mctx, node, sizeof(dns_sdbnode_t));
664 detach((dns_db_t **) (void *)&sdb);
667 static isc_result_t
668 findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
669 dns_dbnode_t **nodep)
671 dns_sdb_t *sdb = (dns_sdb_t *)db;
672 dns_sdbnode_t *node = NULL;
673 isc_result_t result;
674 isc_buffer_t b;
675 char namestr[DNS_NAME_MAXTEXT + 1];
676 isc_boolean_t isorigin;
677 dns_sdbimplementation_t *imp;
679 REQUIRE(VALID_SDB(sdb));
680 REQUIRE(create == ISC_FALSE);
681 REQUIRE(nodep != NULL && *nodep == NULL);
683 UNUSED(name);
684 UNUSED(create);
686 imp = sdb->implementation;
688 isc_buffer_init(&b, namestr, sizeof(namestr));
689 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
690 dns_name_t relname;
691 unsigned int labels;
693 labels = dns_name_countlabels(name) -
694 dns_name_countlabels(&db->origin);
695 dns_name_init(&relname, NULL);
696 dns_name_getlabelsequence(name, 0, labels, &relname);
697 result = dns_name_totext(&relname, ISC_TRUE, &b);
698 if (result != ISC_R_SUCCESS)
699 return (result);
700 } else {
701 result = dns_name_totext(name, ISC_TRUE, &b);
702 if (result != ISC_R_SUCCESS)
703 return (result);
705 isc_buffer_putuint8(&b, 0);
707 result = createnode(sdb, &node);
708 if (result != ISC_R_SUCCESS)
709 return (result);
711 isorigin = dns_name_equal(name, &sdb->common.origin);
713 MAYBE_LOCK(sdb);
714 result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata, node);
715 MAYBE_UNLOCK(sdb);
716 if (result != ISC_R_SUCCESS && !isorigin) {
717 destroynode(node);
718 return (result);
721 if (isorigin && imp->methods->authority != NULL) {
722 MAYBE_LOCK(sdb);
723 result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
724 MAYBE_UNLOCK(sdb);
725 if (result != ISC_R_SUCCESS) {
726 destroynode(node);
727 return (result);
731 *nodep = node;
732 return (ISC_R_SUCCESS);
735 static isc_result_t
736 find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
737 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
738 dns_dbnode_t **nodep, dns_name_t *foundname,
739 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
741 dns_sdb_t *sdb = (dns_sdb_t *)db;
742 dns_dbnode_t *node = NULL;
743 dns_fixedname_t fname;
744 dns_rdataset_t xrdataset;
745 dns_name_t *xname;
746 unsigned int nlabels, olabels;
747 isc_result_t result;
748 unsigned int i;
750 REQUIRE(VALID_SDB(sdb));
751 REQUIRE(nodep == NULL || *nodep == NULL);
752 REQUIRE(version == NULL || version == (void *) &dummy);
754 UNUSED(options);
755 UNUSED(sdb);
757 if (!dns_name_issubdomain(name, &db->origin))
758 return (DNS_R_NXDOMAIN);
760 olabels = dns_name_countlabels(&db->origin);
761 nlabels = dns_name_countlabels(name);
763 dns_fixedname_init(&fname);
764 xname = dns_fixedname_name(&fname);
766 if (rdataset == NULL) {
767 dns_rdataset_init(&xrdataset);
768 rdataset = &xrdataset;
771 result = DNS_R_NXDOMAIN;
773 for (i = olabels; i <= nlabels; i++) {
775 * Unless this is an explicit lookup at the origin, don't
776 * look at the origin.
778 if (i == olabels && i != nlabels)
779 continue;
782 * Look up the next label.
784 dns_name_getlabelsequence(name, nlabels - i, i, xname);
785 result = findnode(db, xname, ISC_FALSE, &node);
786 if (result != ISC_R_SUCCESS) {
787 result = DNS_R_NXDOMAIN;
788 continue;
792 * Look for a DNAME at the current label, unless this is
793 * the qname.
795 if (i < nlabels) {
796 result = findrdataset(db, node, version,
797 dns_rdatatype_dname,
798 0, now, rdataset, sigrdataset);
799 if (result == ISC_R_SUCCESS) {
800 result = DNS_R_DNAME;
801 break;
806 * Look for an NS at the current label, unless this is the
807 * origin or glue is ok.
809 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
810 result = findrdataset(db, node, version,
811 dns_rdatatype_ns,
812 0, now, rdataset, sigrdataset);
813 if (result == ISC_R_SUCCESS) {
814 if (i == nlabels && type == dns_rdatatype_any)
816 result = DNS_R_ZONECUT;
817 dns_rdataset_disassociate(rdataset);
818 if (sigrdataset != NULL)
819 dns_rdataset_disassociate
820 (sigrdataset);
821 } else
822 result = DNS_R_DELEGATION;
823 break;
828 * If the current name is not the qname, add another label
829 * and try again.
831 if (i < nlabels) {
832 destroynode(node);
833 node = NULL;
834 continue;
838 * If we're looking for ANY, we're done.
840 if (type == dns_rdatatype_any) {
841 result = ISC_R_SUCCESS;
842 break;
846 * Look for the qtype.
848 result = findrdataset(db, node, version, type,
849 0, now, rdataset, sigrdataset);
850 if (result == ISC_R_SUCCESS)
851 break;
854 * Look for a CNAME
856 if (type != dns_rdatatype_cname) {
857 result = findrdataset(db, node, version,
858 dns_rdatatype_cname,
859 0, now, rdataset, sigrdataset);
860 if (result == ISC_R_SUCCESS) {
861 result = DNS_R_CNAME;
862 break;
866 result = DNS_R_NXRRSET;
867 break;
870 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
871 dns_rdataset_disassociate(rdataset);
873 if (foundname != NULL) {
874 isc_result_t xresult;
876 xresult = dns_name_copy(xname, foundname, NULL);
877 if (xresult != ISC_R_SUCCESS) {
878 destroynode(node);
879 if (dns_rdataset_isassociated(rdataset))
880 dns_rdataset_disassociate(rdataset);
881 return (DNS_R_BADDB);
885 if (nodep != NULL)
886 *nodep = node;
887 else if (node != NULL)
888 detachnode(db, &node);
890 return (result);
893 static isc_result_t
894 findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
895 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
896 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
898 UNUSED(db);
899 UNUSED(name);
900 UNUSED(options);
901 UNUSED(now);
902 UNUSED(nodep);
903 UNUSED(foundname);
904 UNUSED(rdataset);
905 UNUSED(sigrdataset);
907 return (ISC_R_NOTIMPLEMENTED);
910 static void
911 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
912 dns_sdb_t *sdb = (dns_sdb_t *)db;
913 dns_sdbnode_t *node = (dns_sdbnode_t *)source;
915 REQUIRE(VALID_SDB(sdb));
917 UNUSED(sdb);
919 LOCK(&node->lock);
920 INSIST(node->references > 0);
921 node->references++;
922 INSIST(node->references != 0); /* Catch overflow. */
923 UNLOCK(&node->lock);
925 *targetp = source;
928 static void
929 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
930 dns_sdb_t *sdb = (dns_sdb_t *)db;
931 dns_sdbnode_t *node;
932 isc_boolean_t need_destroy = ISC_FALSE;
934 REQUIRE(VALID_SDB(sdb));
935 REQUIRE(targetp != NULL && *targetp != NULL);
937 UNUSED(sdb);
939 node = (dns_sdbnode_t *)(*targetp);
941 LOCK(&node->lock);
942 INSIST(node->references > 0);
943 node->references--;
944 if (node->references == 0)
945 need_destroy = ISC_TRUE;
946 UNLOCK(&node->lock);
948 if (need_destroy)
949 destroynode(node);
951 *targetp = NULL;
954 static isc_result_t
955 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
956 UNUSED(db);
957 UNUSED(node);
958 UNUSED(now);
959 INSIST(0);
960 return (ISC_R_UNEXPECTED);
963 static void
964 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
965 UNUSED(db);
966 UNUSED(node);
967 UNUSED(out);
968 return;
971 static isc_result_t
972 createiterator(dns_db_t *db, isc_boolean_t relative_names,
973 dns_dbiterator_t **iteratorp)
975 dns_sdb_t *sdb = (dns_sdb_t *)db;
976 sdb_dbiterator_t *sdbiter;
977 dns_sdbimplementation_t *imp = sdb->implementation;
978 isc_result_t result;
980 REQUIRE(VALID_SDB(sdb));
982 if (imp->methods->allnodes == NULL)
983 return (ISC_R_NOTIMPLEMENTED);
985 sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t));
986 if (sdbiter == NULL)
987 return (ISC_R_NOMEMORY);
989 sdbiter->common.methods = &dbiterator_methods;
990 sdbiter->common.db = NULL;
991 dns_db_attach(db, &sdbiter->common.db);
992 sdbiter->common.relative_names = relative_names;
993 sdbiter->common.magic = DNS_DBITERATOR_MAGIC;
994 ISC_LIST_INIT(sdbiter->nodelist);
995 sdbiter->current = NULL;
996 sdbiter->origin = NULL;
998 MAYBE_LOCK(sdb);
999 result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter);
1000 MAYBE_UNLOCK(sdb);
1001 if (result != ISC_R_SUCCESS) {
1002 dbiterator_destroy((dns_dbiterator_t **) (void *)&sdbiter);
1003 return (result);
1006 if (sdbiter->origin != NULL) {
1007 ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link);
1008 ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link);
1011 *iteratorp = (dns_dbiterator_t *)sdbiter;
1013 return (ISC_R_SUCCESS);
1016 static isc_result_t
1017 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1018 dns_rdatatype_t type, dns_rdatatype_t covers,
1019 isc_stdtime_t now, dns_rdataset_t *rdataset,
1020 dns_rdataset_t *sigrdataset)
1022 dns_rdatalist_t *list;
1023 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
1025 REQUIRE(VALID_SDBNODE(node));
1027 UNUSED(db);
1028 UNUSED(version);
1029 UNUSED(covers);
1030 UNUSED(now);
1031 UNUSED(sigrdataset);
1033 if (type == dns_rdatatype_sig)
1034 return (ISC_R_NOTIMPLEMENTED);
1036 list = ISC_LIST_HEAD(sdbnode->lists);
1037 while (list != NULL) {
1038 if (list->type == type)
1039 break;
1040 list = ISC_LIST_NEXT(list, link);
1042 if (list == NULL)
1043 return (ISC_R_NOTFOUND);
1045 list_tordataset(list, db, node, rdataset);
1047 return (ISC_R_SUCCESS);
1050 static isc_result_t
1051 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1052 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
1054 sdb_rdatasetiter_t *iterator;
1056 REQUIRE(version == NULL || version == &dummy);
1058 UNUSED(version);
1059 UNUSED(now);
1061 iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t));
1062 if (iterator == NULL)
1063 return (ISC_R_NOMEMORY);
1065 iterator->common.magic = DNS_RDATASETITER_MAGIC;
1066 iterator->common.methods = &rdatasetiter_methods;
1067 iterator->common.db = db;
1068 iterator->common.node = NULL;
1069 attachnode(db, node, &iterator->common.node);
1070 iterator->common.version = version;
1071 iterator->common.now = now;
1073 *iteratorp = (dns_rdatasetiter_t *)iterator;
1075 return (ISC_R_SUCCESS);
1078 static isc_result_t
1079 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1080 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
1081 dns_rdataset_t *addedrdataset)
1083 UNUSED(db);
1084 UNUSED(node);
1085 UNUSED(version);
1086 UNUSED(now);
1087 UNUSED(rdataset);
1088 UNUSED(options);
1089 UNUSED(addedrdataset);
1091 return (ISC_R_NOTIMPLEMENTED);
1094 static isc_result_t
1095 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1096 dns_rdataset_t *rdataset, unsigned int options,
1097 dns_rdataset_t *newrdataset)
1099 UNUSED(db);
1100 UNUSED(node);
1101 UNUSED(version);
1102 UNUSED(rdataset);
1103 UNUSED(options);
1104 UNUSED(newrdataset);
1106 return (ISC_R_NOTIMPLEMENTED);
1109 static isc_result_t
1110 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1111 dns_rdatatype_t type, dns_rdatatype_t covers)
1113 UNUSED(db);
1114 UNUSED(node);
1115 UNUSED(version);
1116 UNUSED(type);
1117 UNUSED(covers);
1119 return (ISC_R_NOTIMPLEMENTED);
1122 static isc_boolean_t
1123 issecure(dns_db_t *db) {
1124 UNUSED(db);
1126 return (ISC_FALSE);
1129 static unsigned int
1130 nodecount(dns_db_t *db) {
1131 UNUSED(db);
1133 return (0);
1136 static isc_boolean_t
1137 ispersistent(dns_db_t *db) {
1138 UNUSED(db);
1139 return (ISC_TRUE);
1142 static void
1143 overmem(dns_db_t *db, isc_boolean_t overmem) {
1144 UNUSED(db);
1145 UNUSED(overmem);
1148 static void
1149 settask(dns_db_t *db, isc_task_t *task) {
1150 UNUSED(db);
1151 UNUSED(task);
1155 static dns_dbmethods_t sdb_methods = {
1156 attach,
1157 detach,
1158 beginload,
1159 endload,
1160 dump,
1161 currentversion,
1162 newversion,
1163 attachversion,
1164 closeversion,
1165 findnode,
1166 find,
1167 findzonecut,
1168 attachnode,
1169 detachnode,
1170 expirenode,
1171 printnode,
1172 createiterator,
1173 findrdataset,
1174 allrdatasets,
1175 addrdataset,
1176 subtractrdataset,
1177 deleterdataset,
1178 issecure,
1179 nodecount,
1180 ispersistent,
1181 overmem,
1182 settask
1185 static isc_result_t
1186 dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
1187 dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
1188 void *driverarg, dns_db_t **dbp)
1190 dns_sdb_t *sdb;
1191 isc_result_t result;
1192 char zonestr[DNS_NAME_MAXTEXT + 1];
1193 isc_buffer_t b;
1194 dns_sdbimplementation_t *imp;
1196 REQUIRE(driverarg != NULL);
1198 imp = driverarg;
1200 if (type != dns_dbtype_zone)
1201 return (ISC_R_NOTIMPLEMENTED);
1203 sdb = isc_mem_get(mctx, sizeof(dns_sdb_t));
1204 if (sdb == NULL)
1205 return (ISC_R_NOMEMORY);
1206 memset(sdb, 0, sizeof(dns_sdb_t));
1208 dns_name_init(&sdb->common.origin, NULL);
1209 sdb->common.attributes = 0;
1210 sdb->common.methods = &sdb_methods;
1211 sdb->common.rdclass = rdclass;
1212 sdb->common.mctx = NULL;
1213 sdb->implementation = imp;
1215 isc_mem_attach(mctx, &sdb->common.mctx);
1217 result = isc_mutex_init(&sdb->lock);
1218 if (result != ISC_R_SUCCESS) {
1219 UNEXPECTED_ERROR(__FILE__, __LINE__,
1220 "isc_mutex_init() failed: %s",
1221 isc_result_totext(result));
1222 result = ISC_R_UNEXPECTED;
1223 goto cleanup_mctx;
1226 result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
1227 if (result != ISC_R_SUCCESS)
1228 goto cleanup_lock;
1230 isc_buffer_init(&b, zonestr, sizeof(zonestr));
1231 result = dns_name_totext(origin, ISC_TRUE, &b);
1232 if (result != ISC_R_SUCCESS)
1233 goto cleanup_origin;
1234 isc_buffer_putuint8(&b, 0);
1236 sdb->zone = isc_mem_strdup(mctx, zonestr);
1237 if (sdb->zone == NULL) {
1238 result = ISC_R_NOMEMORY;
1239 goto cleanup_origin;
1242 sdb->dbdata = NULL;
1243 if (imp->methods->create != NULL) {
1244 MAYBE_LOCK(sdb);
1245 result = imp->methods->create(sdb->zone, argc, argv,
1246 imp->driverdata, &sdb->dbdata);
1247 MAYBE_UNLOCK(sdb);
1248 if (result != ISC_R_SUCCESS)
1249 goto cleanup_zonestr;
1252 sdb->references = 1;
1254 sdb->common.magic = DNS_DB_MAGIC;
1255 sdb->common.impmagic = SDB_MAGIC;
1257 *dbp = (dns_db_t *)sdb;
1259 return (ISC_R_SUCCESS);
1261 cleanup_zonestr:
1262 isc_mem_free(mctx, sdb->zone);
1263 cleanup_origin:
1264 dns_name_free(&sdb->common.origin, mctx);
1265 cleanup_lock:
1266 isc_mutex_destroy(&sdb->lock);
1267 cleanup_mctx:
1268 isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
1269 isc_mem_detach(&mctx);
1271 return (result);
1276 * Rdataset Methods
1279 static void
1280 disassociate(dns_rdataset_t *rdataset) {
1281 dns_dbnode_t *node = rdataset->private5;
1282 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
1283 dns_db_t *db = (dns_db_t *) sdbnode->sdb;
1285 detachnode(db, &node);
1286 isc__rdatalist_disassociate(rdataset);
1289 static void
1290 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1291 dns_dbnode_t *node = source->private5;
1292 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
1293 dns_db_t *db = (dns_db_t *) sdbnode->sdb;
1294 dns_dbnode_t *tempdb = NULL;
1296 isc__rdatalist_clone(source, target);
1297 attachnode(db, node, &tempdb);
1298 source->private5 = tempdb;
1301 static dns_rdatasetmethods_t methods = {
1302 disassociate,
1303 isc__rdatalist_first,
1304 isc__rdatalist_next,
1305 isc__rdatalist_current,
1306 rdataset_clone,
1307 isc__rdatalist_count
1310 static void
1311 list_tordataset(dns_rdatalist_t *rdatalist,
1312 dns_db_t *db, dns_dbnode_t *node,
1313 dns_rdataset_t *rdataset)
1316 * The sdb rdataset is an rdatalist with some additions.
1317 * - private1 & private2 are used by the rdatalist.
1318 * - private3 & private 4 are unused.
1319 * - private5 is the node.
1322 /* This should never fail. */
1323 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1324 ISC_R_SUCCESS);
1326 rdataset->methods = &methods;
1327 dns_db_attachnode(db, node, &rdataset->private5);
1331 * Database Iterator Methods
1333 static void
1334 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1335 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp);
1336 dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db;
1338 while (!ISC_LIST_EMPTY(sdbiter->nodelist)) {
1339 dns_sdbnode_t *node;
1340 node = ISC_LIST_HEAD(sdbiter->nodelist);
1341 ISC_LIST_UNLINK(sdbiter->nodelist, node, link);
1342 destroynode(node);
1345 dns_db_detach(&sdbiter->common.db);
1346 isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t));
1348 *iteratorp = NULL;
1351 static isc_result_t
1352 dbiterator_first(dns_dbiterator_t *iterator) {
1353 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1355 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1356 if (sdbiter->current == NULL)
1357 return (ISC_R_NOMORE);
1358 else
1359 return (ISC_R_SUCCESS);
1362 static isc_result_t
1363 dbiterator_last(dns_dbiterator_t *iterator) {
1364 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1366 sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist);
1367 if (sdbiter->current == NULL)
1368 return (ISC_R_NOMORE);
1369 else
1370 return (ISC_R_SUCCESS);
1373 static isc_result_t
1374 dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
1375 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1377 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1378 while (sdbiter->current != NULL)
1379 if (dns_name_equal(sdbiter->current->name, name))
1380 return (ISC_R_SUCCESS);
1381 return (ISC_R_NOTFOUND);
1384 static isc_result_t
1385 dbiterator_prev(dns_dbiterator_t *iterator) {
1386 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1388 sdbiter->current = ISC_LIST_PREV(sdbiter->current, link);
1389 if (sdbiter->current == NULL)
1390 return (ISC_R_NOMORE);
1391 else
1392 return (ISC_R_SUCCESS);
1395 static isc_result_t
1396 dbiterator_next(dns_dbiterator_t *iterator) {
1397 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1399 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
1400 if (sdbiter->current == NULL)
1401 return (ISC_R_NOMORE);
1402 else
1403 return (ISC_R_SUCCESS);
1406 static isc_result_t
1407 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1408 dns_name_t *name)
1410 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1412 attachnode(iterator->db, sdbiter->current, nodep);
1413 if (name != NULL)
1414 return (dns_name_copy(sdbiter->current->name, name, NULL));
1415 return (ISC_R_SUCCESS);
1418 static isc_result_t
1419 dbiterator_pause(dns_dbiterator_t *iterator) {
1420 UNUSED(iterator);
1421 return (ISC_R_SUCCESS);
1424 static isc_result_t
1425 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1426 UNUSED(iterator);
1427 return (dns_name_copy(dns_rootname, name, NULL));
1431 * Rdataset Iterator Methods
1434 static void
1435 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
1436 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp);
1437 detachnode(sdbiterator->common.db, &sdbiterator->common.node);
1438 isc_mem_put(sdbiterator->common.db->mctx, sdbiterator,
1439 sizeof(sdb_rdatasetiter_t));
1440 *iteratorp = NULL;
1443 static isc_result_t
1444 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
1445 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1446 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node;
1448 if (ISC_LIST_EMPTY(sdbnode->lists))
1449 return (ISC_R_NOMORE);
1450 sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists);
1451 return (ISC_R_SUCCESS);
1454 static isc_result_t
1455 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
1456 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1458 sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link);
1459 if (sdbiterator->current == NULL)
1460 return (ISC_R_NOMORE);
1461 else
1462 return (ISC_R_SUCCESS);
1465 static void
1466 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
1467 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1469 list_tordataset(sdbiterator->current, iterator->db, iterator->node,
1470 rdataset);