vendor/BIND: Update to 9.5.2-P3
[dragonfly.git] / contrib / bind / lib / dns / sdb.c
blob5bf888d2f0f5a76844af39227520f38b04191a72
1 /*
2 * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or 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.59.94.8.2.2 2010/02/25 10:56:02 tbox Exp $ */
20 /*! \file */
22 #include <config.h>
24 #include <string.h>
26 #include <isc/buffer.h>
27 #include <isc/lex.h>
28 #include <isc/log.h>
29 #include <isc/magic.h>
30 #include <isc/mem.h>
31 #include <isc/once.h>
32 #include <isc/print.h>
33 #include <isc/region.h>
34 #include <isc/util.h>
36 #include <dns/callbacks.h>
37 #include <dns/db.h>
38 #include <dns/dbiterator.h>
39 #include <dns/fixedname.h>
40 #include <dns/log.h>
41 #include <dns/rdata.h>
42 #include <dns/rdatalist.h>
43 #include <dns/rdataset.h>
44 #include <dns/rdatasetiter.h>
45 #include <dns/rdatatype.h>
46 #include <dns/result.h>
47 #include <dns/sdb.h>
48 #include <dns/types.h>
50 #include "rdatalist_p.h"
52 struct dns_sdbimplementation {
53 const dns_sdbmethods_t *methods;
54 void *driverdata;
55 unsigned int flags;
56 isc_mem_t *mctx;
57 isc_mutex_t driverlock;
58 dns_dbimplementation_t *dbimp;
61 struct dns_sdb {
62 /* Unlocked */
63 dns_db_t common;
64 char *zone;
65 dns_sdbimplementation_t *implementation;
66 void *dbdata;
67 isc_mutex_t lock;
68 /* Locked */
69 unsigned int references;
72 struct dns_sdblookup {
73 /* Unlocked */
74 unsigned int magic;
75 dns_sdb_t *sdb;
76 ISC_LIST(dns_rdatalist_t) lists;
77 ISC_LIST(isc_buffer_t) buffers;
78 dns_name_t *name;
79 ISC_LINK(dns_sdblookup_t) link;
80 isc_mutex_t lock;
81 dns_rdatacallbacks_t callbacks;
82 /* Locked */
83 unsigned int references;
86 typedef struct dns_sdblookup dns_sdbnode_t;
88 struct dns_sdballnodes {
89 dns_dbiterator_t common;
90 ISC_LIST(dns_sdbnode_t) nodelist;
91 dns_sdbnode_t *current;
92 dns_sdbnode_t *origin;
95 typedef dns_sdballnodes_t sdb_dbiterator_t;
97 typedef struct sdb_rdatasetiter {
98 dns_rdatasetiter_t common;
99 dns_rdatalist_t *current;
100 } sdb_rdatasetiter_t;
102 #define SDB_MAGIC ISC_MAGIC('S', 'D', 'B', '-')
105 * Note that "impmagic" is not the first four bytes of the struct, so
106 * ISC_MAGIC_VALID cannot be used.
108 #define VALID_SDB(sdb) ((sdb) != NULL && \
109 (sdb)->common.impmagic == SDB_MAGIC)
111 #define SDBLOOKUP_MAGIC ISC_MAGIC('S','D','B','L')
112 #define VALID_SDBLOOKUP(sdbl) ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)
113 #define VALID_SDBNODE(sdbn) VALID_SDBLOOKUP(sdbn)
115 /* These values are taken from RFC1537 */
116 #define SDB_DEFAULT_REFRESH (60 * 60 * 8)
117 #define SDB_DEFAULT_RETRY (60 * 60 * 2)
118 #define SDB_DEFAULT_EXPIRE (60 * 60 * 24 * 7)
119 #define SDB_DEFAULT_MINIMUM (60 * 60 * 24)
121 /* This is a reasonable value */
122 #define SDB_DEFAULT_TTL (60 * 60 * 24)
124 #ifdef __COVERITY__
125 #define MAYBE_LOCK(sdb) LOCK(&sdb->implementation->driverlock)
126 #define MAYBE_UNLOCK(sdb) UNLOCK(&sdb->implementation->driverlock)
127 #else
128 #define MAYBE_LOCK(sdb) \
129 do { \
130 unsigned int flags = sdb->implementation->flags; \
131 if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \
132 LOCK(&sdb->implementation->driverlock); \
133 } while (0)
135 #define MAYBE_UNLOCK(sdb) \
136 do { \
137 unsigned int flags = sdb->implementation->flags; \
138 if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \
139 UNLOCK(&sdb->implementation->driverlock); \
140 } while (0)
141 #endif
143 static int dummy;
145 static isc_result_t dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin,
146 dns_dbtype_t type, dns_rdataclass_t rdclass,
147 unsigned int argc, char *argv[],
148 void *driverarg, dns_db_t **dbp);
150 static isc_result_t findrdataset(dns_db_t *db, dns_dbnode_t *node,
151 dns_dbversion_t *version,
152 dns_rdatatype_t type, dns_rdatatype_t covers,
153 isc_stdtime_t now, dns_rdataset_t *rdataset,
154 dns_rdataset_t *sigrdataset);
156 static isc_result_t createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep);
158 static void destroynode(dns_sdbnode_t *node);
160 static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
163 static void list_tordataset(dns_rdatalist_t *rdatalist,
164 dns_db_t *db, dns_dbnode_t *node,
165 dns_rdataset_t *rdataset);
167 static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
168 static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
169 static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
170 static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
171 dns_name_t *name);
172 static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
173 static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
174 static isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
175 dns_dbnode_t **nodep,
176 dns_name_t *name);
177 static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
178 static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
179 dns_name_t *name);
181 static dns_dbiteratormethods_t dbiterator_methods = {
182 dbiterator_destroy,
183 dbiterator_first,
184 dbiterator_last,
185 dbiterator_seek,
186 dbiterator_prev,
187 dbiterator_next,
188 dbiterator_current,
189 dbiterator_pause,
190 dbiterator_origin
193 static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
194 static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator);
195 static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator);
196 static void rdatasetiter_current(dns_rdatasetiter_t *iterator,
197 dns_rdataset_t *rdataset);
199 static dns_rdatasetitermethods_t rdatasetiter_methods = {
200 rdatasetiter_destroy,
201 rdatasetiter_first,
202 rdatasetiter_next,
203 rdatasetiter_current
207 * Functions used by implementors of simple databases
209 isc_result_t
210 dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
211 void *driverdata, unsigned int flags, isc_mem_t *mctx,
212 dns_sdbimplementation_t **sdbimp)
214 dns_sdbimplementation_t *imp;
215 isc_result_t result;
217 REQUIRE(drivername != NULL);
218 REQUIRE(methods != NULL);
219 REQUIRE(methods->lookup != NULL);
220 REQUIRE(mctx != NULL);
221 REQUIRE(sdbimp != NULL && *sdbimp == NULL);
222 REQUIRE((flags & ~(DNS_SDBFLAG_RELATIVEOWNER |
223 DNS_SDBFLAG_RELATIVERDATA |
224 DNS_SDBFLAG_THREADSAFE)) == 0);
226 imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t));
227 if (imp == NULL)
228 return (ISC_R_NOMEMORY);
229 imp->methods = methods;
230 imp->driverdata = driverdata;
231 imp->flags = flags;
232 imp->mctx = NULL;
233 isc_mem_attach(mctx, &imp->mctx);
234 result = isc_mutex_init(&imp->driverlock);
235 if (result != ISC_R_SUCCESS)
236 goto cleanup_mctx;
238 imp->dbimp = NULL;
239 result = dns_db_register(drivername, dns_sdb_create, imp, mctx,
240 &imp->dbimp);
241 if (result != ISC_R_SUCCESS)
242 goto cleanup_mutex;
243 *sdbimp = imp;
245 return (ISC_R_SUCCESS);
247 cleanup_mutex:
248 DESTROYLOCK(&imp->driverlock);
249 cleanup_mctx:
250 isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
251 return (result);
254 void
255 dns_sdb_unregister(dns_sdbimplementation_t **sdbimp) {
256 dns_sdbimplementation_t *imp;
257 isc_mem_t *mctx;
259 REQUIRE(sdbimp != NULL && *sdbimp != NULL);
261 imp = *sdbimp;
262 dns_db_unregister(&imp->dbimp);
263 DESTROYLOCK(&imp->driverlock);
265 mctx = imp->mctx;
266 isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
267 isc_mem_detach(&mctx);
269 *sdbimp = NULL;
272 static inline unsigned int
273 initial_size(unsigned int len) {
274 unsigned int size;
276 for (size = 1024; size < (64 * 1024); size *= 2)
277 if (len < size)
278 return (size);
279 return (65535);
282 isc_result_t
283 dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval, dns_ttl_t ttl,
284 const unsigned char *rdatap, unsigned int rdlen)
286 dns_rdatalist_t *rdatalist;
287 dns_rdata_t *rdata;
288 isc_buffer_t *rdatabuf = NULL;
289 isc_result_t result;
290 isc_mem_t *mctx;
291 isc_region_t region;
293 mctx = lookup->sdb->common.mctx;
295 rdatalist = ISC_LIST_HEAD(lookup->lists);
296 while (rdatalist != NULL) {
297 if (rdatalist->type == typeval)
298 break;
299 rdatalist = ISC_LIST_NEXT(rdatalist, link);
302 if (rdatalist == NULL) {
303 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
304 if (rdatalist == NULL)
305 return (ISC_R_NOMEMORY);
306 rdatalist->rdclass = lookup->sdb->common.rdclass;
307 rdatalist->type = typeval;
308 rdatalist->covers = 0;
309 rdatalist->ttl = ttl;
310 ISC_LIST_INIT(rdatalist->rdata);
311 ISC_LINK_INIT(rdatalist, link);
312 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
313 } else
314 if (rdatalist->ttl != ttl)
315 return (DNS_R_BADTTL);
317 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
318 if (rdata == NULL)
319 return (ISC_R_NOMEMORY);
321 result = isc_buffer_allocate(mctx, &rdatabuf, rdlen);
322 if (result != ISC_R_SUCCESS)
323 goto failure;
324 DE_CONST(rdatap, region.base);
325 region.length = rdlen;
326 isc_buffer_copyregion(rdatabuf, &region);
327 isc_buffer_usedregion(rdatabuf, &region);
328 dns_rdata_init(rdata);
329 dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type,
330 &region);
331 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
332 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
333 rdata = NULL;
335 failure:
336 if (rdata != NULL)
337 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
338 return (result);
342 isc_result_t
343 dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
344 const char *data)
346 unsigned int datalen;
347 dns_rdatatype_t typeval;
348 isc_textregion_t r;
349 isc_lex_t *lex = NULL;
350 isc_result_t result;
351 unsigned char *p = NULL;
352 unsigned int size = 0; /* Init to suppress compiler warning */
353 isc_mem_t *mctx;
354 dns_sdbimplementation_t *imp;
355 dns_name_t *origin;
356 isc_buffer_t b;
357 isc_buffer_t rb;
359 REQUIRE(VALID_SDBLOOKUP(lookup));
360 REQUIRE(type != NULL);
361 REQUIRE(data != NULL);
363 mctx = lookup->sdb->common.mctx;
365 DE_CONST(type, r.base);
366 r.length = strlen(type);
367 result = dns_rdatatype_fromtext(&typeval, &r);
368 if (result != ISC_R_SUCCESS)
369 return (result);
371 imp = lookup->sdb->implementation;
372 if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
373 origin = &lookup->sdb->common.origin;
374 else
375 origin = dns_rootname;
377 result = isc_lex_create(mctx, 64, &lex);
378 if (result != ISC_R_SUCCESS)
379 goto failure;
381 datalen = strlen(data);
382 size = initial_size(datalen);
383 do {
384 isc_buffer_init(&b, data, datalen);
385 isc_buffer_add(&b, datalen);
386 result = isc_lex_openbuffer(lex, &b);
387 if (result != ISC_R_SUCCESS)
388 goto failure;
390 if (size >= 65535)
391 size = 65535;
392 p = isc_mem_get(mctx, size);
393 if (p == NULL) {
394 result = ISC_R_NOMEMORY;
395 goto failure;
397 isc_buffer_init(&rb, p, size);
398 result = dns_rdata_fromtext(NULL,
399 lookup->sdb->common.rdclass,
400 typeval, lex,
401 origin, 0,
402 mctx, &rb,
403 &lookup->callbacks);
404 if (result != ISC_R_NOSPACE)
405 break;
408 * Is the RR too big?
410 if (size >= 65535)
411 break;
412 isc_mem_put(mctx, p, size);
413 p = NULL;
414 size *= 2;
415 } while (result == ISC_R_NOSPACE);
417 if (result != ISC_R_SUCCESS)
418 goto failure;
420 result = dns_sdb_putrdata(lookup, typeval, ttl,
421 isc_buffer_base(&rb),
422 isc_buffer_usedlength(&rb));
423 failure:
424 if (p != NULL)
425 isc_mem_put(mctx, p, size);
426 if (lex != NULL)
427 isc_lex_destroy(&lex);
429 return (result);
432 static isc_result_t
433 getnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) {
434 dns_name_t *newname, *origin;
435 dns_fixedname_t fnewname;
436 dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db;
437 dns_sdbimplementation_t *imp = sdb->implementation;
438 dns_sdbnode_t *sdbnode;
439 isc_mem_t *mctx = sdb->common.mctx;
440 isc_buffer_t b;
441 isc_result_t result;
443 dns_fixedname_init(&fnewname);
444 newname = dns_fixedname_name(&fnewname);
446 if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
447 origin = &sdb->common.origin;
448 else
449 origin = dns_rootname;
450 isc_buffer_init(&b, name, strlen(name));
451 isc_buffer_add(&b, strlen(name));
453 result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL);
454 if (result != ISC_R_SUCCESS)
455 return (result);
457 if (allnodes->common.relative_names) {
458 /* All names are relative to the root */
459 unsigned int nlabels = dns_name_countlabels(newname);
460 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
463 sdbnode = ISC_LIST_HEAD(allnodes->nodelist);
464 if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) {
465 sdbnode = NULL;
466 result = createnode(sdb, &sdbnode);
467 if (result != ISC_R_SUCCESS)
468 return (result);
469 sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t));
470 if (sdbnode->name == NULL) {
471 destroynode(sdbnode);
472 return (ISC_R_NOMEMORY);
474 dns_name_init(sdbnode->name, NULL);
475 result = dns_name_dup(newname, mctx, sdbnode->name);
476 if (result != ISC_R_SUCCESS) {
477 isc_mem_put(mctx, sdbnode->name, sizeof(dns_name_t));
478 destroynode(sdbnode);
479 return (result);
481 ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link);
482 if (allnodes->origin == NULL &&
483 dns_name_equal(newname, &sdb->common.origin))
484 allnodes->origin = sdbnode;
486 *nodep = sdbnode;
487 return (ISC_R_SUCCESS);
490 isc_result_t
491 dns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name,
492 const char *type, dns_ttl_t ttl, const char *data)
494 isc_result_t result;
495 dns_sdbnode_t *sdbnode = NULL;
496 result = getnode(allnodes, name, &sdbnode);
497 if (result != ISC_R_SUCCESS)
498 return (result);
499 return (dns_sdb_putrr(sdbnode, type, ttl, data));
502 isc_result_t
503 dns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name,
504 dns_rdatatype_t type, dns_ttl_t ttl,
505 const void *rdata, unsigned int rdlen)
507 isc_result_t result;
508 dns_sdbnode_t *sdbnode = NULL;
509 result = getnode(allnodes, name, &sdbnode);
510 if (result != ISC_R_SUCCESS)
511 return (result);
512 return (dns_sdb_putrdata(sdbnode, type, ttl, rdata, rdlen));
515 isc_result_t
516 dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
517 isc_uint32_t serial)
519 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
520 int n;
522 REQUIRE(mname != NULL);
523 REQUIRE(rname != NULL);
525 n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u",
526 mname, rname, serial,
527 SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY,
528 SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM);
529 if (n >= (int)sizeof(str) || n < 0)
530 return (ISC_R_NOSPACE);
531 return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));
535 * DB routines
538 static void
539 attach(dns_db_t *source, dns_db_t **targetp) {
540 dns_sdb_t *sdb = (dns_sdb_t *) source;
542 REQUIRE(VALID_SDB(sdb));
544 LOCK(&sdb->lock);
545 REQUIRE(sdb->references > 0);
546 sdb->references++;
547 UNLOCK(&sdb->lock);
549 *targetp = source;
552 static void
553 destroy(dns_sdb_t *sdb) {
554 isc_mem_t *mctx;
555 dns_sdbimplementation_t *imp = sdb->implementation;
557 mctx = sdb->common.mctx;
559 if (imp->methods->destroy != NULL) {
560 MAYBE_LOCK(sdb);
561 imp->methods->destroy(sdb->zone, imp->driverdata,
562 &sdb->dbdata);
563 MAYBE_UNLOCK(sdb);
566 isc_mem_free(mctx, sdb->zone);
567 DESTROYLOCK(&sdb->lock);
569 sdb->common.magic = 0;
570 sdb->common.impmagic = 0;
572 dns_name_free(&sdb->common.origin, mctx);
574 isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
575 isc_mem_detach(&mctx);
578 static void
579 detach(dns_db_t **dbp) {
580 dns_sdb_t *sdb = (dns_sdb_t *)(*dbp);
581 isc_boolean_t need_destroy = ISC_FALSE;
583 REQUIRE(VALID_SDB(sdb));
584 LOCK(&sdb->lock);
585 REQUIRE(sdb->references > 0);
586 sdb->references--;
587 if (sdb->references == 0)
588 need_destroy = ISC_TRUE;
589 UNLOCK(&sdb->lock);
591 if (need_destroy)
592 destroy(sdb);
594 *dbp = NULL;
597 static isc_result_t
598 beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
599 UNUSED(db);
600 UNUSED(addp);
601 UNUSED(dbloadp);
602 return (ISC_R_NOTIMPLEMENTED);
605 static isc_result_t
606 endload(dns_db_t *db, dns_dbload_t **dbloadp) {
607 UNUSED(db);
608 UNUSED(dbloadp);
609 return (ISC_R_NOTIMPLEMENTED);
612 static isc_result_t
613 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
614 dns_masterformat_t masterformat) {
615 UNUSED(db);
616 UNUSED(version);
617 UNUSED(filename);
618 UNUSED(masterformat);
619 return (ISC_R_NOTIMPLEMENTED);
622 static void
623 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
624 REQUIRE(versionp != NULL && *versionp == NULL);
626 UNUSED(db);
628 *versionp = (void *) &dummy;
629 return;
632 static isc_result_t
633 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
634 UNUSED(db);
635 UNUSED(versionp);
637 return (ISC_R_NOTIMPLEMENTED);
640 static void
641 attachversion(dns_db_t *db, dns_dbversion_t *source,
642 dns_dbversion_t **targetp)
644 REQUIRE(source != NULL && source == (void *) &dummy);
645 REQUIRE(targetp != NULL && *targetp == NULL);
647 UNUSED(db);
648 *targetp = source;
649 return;
652 static void
653 closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
654 REQUIRE(versionp != NULL && *versionp == (void *) &dummy);
655 REQUIRE(commit == ISC_FALSE);
657 UNUSED(db);
658 UNUSED(commit);
660 *versionp = NULL;
663 static isc_result_t
664 createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) {
665 dns_sdbnode_t *node;
666 isc_result_t result;
668 node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t));
669 if (node == NULL)
670 return (ISC_R_NOMEMORY);
672 node->sdb = NULL;
673 attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb);
674 ISC_LIST_INIT(node->lists);
675 ISC_LIST_INIT(node->buffers);
676 ISC_LINK_INIT(node, link);
677 node->name = NULL;
678 result = isc_mutex_init(&node->lock);
679 if (result != ISC_R_SUCCESS) {
680 isc_mem_put(sdb->common.mctx, node, sizeof(dns_sdbnode_t));
681 return (result);
683 dns_rdatacallbacks_init(&node->callbacks);
684 node->references = 1;
685 node->magic = SDBLOOKUP_MAGIC;
687 *nodep = node;
688 return (ISC_R_SUCCESS);
691 static void
692 destroynode(dns_sdbnode_t *node) {
693 dns_rdatalist_t *list;
694 dns_rdata_t *rdata;
695 isc_buffer_t *b;
696 dns_sdb_t *sdb;
697 isc_mem_t *mctx;
699 sdb = node->sdb;
700 mctx = sdb->common.mctx;
702 while (!ISC_LIST_EMPTY(node->lists)) {
703 list = ISC_LIST_HEAD(node->lists);
704 while (!ISC_LIST_EMPTY(list->rdata)) {
705 rdata = ISC_LIST_HEAD(list->rdata);
706 ISC_LIST_UNLINK(list->rdata, rdata, link);
707 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
709 ISC_LIST_UNLINK(node->lists, list, link);
710 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
713 while (!ISC_LIST_EMPTY(node->buffers)) {
714 b = ISC_LIST_HEAD(node->buffers);
715 ISC_LIST_UNLINK(node->buffers, b, link);
716 isc_buffer_free(&b);
719 if (node->name != NULL) {
720 dns_name_free(node->name, mctx);
721 isc_mem_put(mctx, node->name, sizeof(dns_name_t));
723 DESTROYLOCK(&node->lock);
724 node->magic = 0;
725 isc_mem_put(mctx, node, sizeof(dns_sdbnode_t));
726 detach((dns_db_t **) (void *)&sdb);
729 static isc_result_t
730 findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
731 dns_dbnode_t **nodep)
733 dns_sdb_t *sdb = (dns_sdb_t *)db;
734 dns_sdbnode_t *node = NULL;
735 isc_result_t result;
736 isc_buffer_t b;
737 char namestr[DNS_NAME_MAXTEXT + 1];
738 isc_boolean_t isorigin;
739 dns_sdbimplementation_t *imp;
741 REQUIRE(VALID_SDB(sdb));
742 REQUIRE(create == ISC_FALSE);
743 REQUIRE(nodep != NULL && *nodep == NULL);
745 UNUSED(name);
746 UNUSED(create);
748 imp = sdb->implementation;
750 isc_buffer_init(&b, namestr, sizeof(namestr));
751 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
752 dns_name_t relname;
753 unsigned int labels;
755 labels = dns_name_countlabels(name) -
756 dns_name_countlabels(&db->origin);
757 dns_name_init(&relname, NULL);
758 dns_name_getlabelsequence(name, 0, labels, &relname);
759 result = dns_name_totext(&relname, ISC_TRUE, &b);
760 if (result != ISC_R_SUCCESS)
761 return (result);
762 } else {
763 result = dns_name_totext(name, ISC_TRUE, &b);
764 if (result != ISC_R_SUCCESS)
765 return (result);
767 isc_buffer_putuint8(&b, 0);
769 result = createnode(sdb, &node);
770 if (result != ISC_R_SUCCESS)
771 return (result);
773 isorigin = dns_name_equal(name, &sdb->common.origin);
775 MAYBE_LOCK(sdb);
776 result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata, node);
777 MAYBE_UNLOCK(sdb);
778 if (result != ISC_R_SUCCESS &&
779 !(result == ISC_R_NOTFOUND &&
780 isorigin && imp->methods->authority != NULL))
782 destroynode(node);
783 return (result);
786 if (isorigin && imp->methods->authority != NULL) {
787 MAYBE_LOCK(sdb);
788 result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
789 MAYBE_UNLOCK(sdb);
790 if (result != ISC_R_SUCCESS) {
791 destroynode(node);
792 return (result);
796 *nodep = node;
797 return (ISC_R_SUCCESS);
800 static isc_result_t
801 find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
802 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
803 dns_dbnode_t **nodep, dns_name_t *foundname,
804 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
806 dns_sdb_t *sdb = (dns_sdb_t *)db;
807 dns_dbnode_t *node = NULL;
808 dns_fixedname_t fname;
809 dns_rdataset_t xrdataset;
810 dns_name_t *xname;
811 unsigned int nlabels, olabels;
812 isc_result_t result;
813 unsigned int i;
815 REQUIRE(VALID_SDB(sdb));
816 REQUIRE(nodep == NULL || *nodep == NULL);
817 REQUIRE(version == NULL || version == (void *) &dummy);
819 UNUSED(options);
820 UNUSED(sdb);
822 if (!dns_name_issubdomain(name, &db->origin))
823 return (DNS_R_NXDOMAIN);
825 olabels = dns_name_countlabels(&db->origin);
826 nlabels = dns_name_countlabels(name);
828 dns_fixedname_init(&fname);
829 xname = dns_fixedname_name(&fname);
831 if (rdataset == NULL) {
832 dns_rdataset_init(&xrdataset);
833 rdataset = &xrdataset;
836 result = DNS_R_NXDOMAIN;
838 for (i = olabels; i <= nlabels; i++) {
840 * Unless this is an explicit lookup at the origin, don't
841 * look at the origin.
843 if (i == olabels && i != nlabels)
844 continue;
847 * Look up the next label.
849 dns_name_getlabelsequence(name, nlabels - i, i, xname);
850 result = findnode(db, xname, ISC_FALSE, &node);
851 if (result != ISC_R_SUCCESS) {
852 result = DNS_R_NXDOMAIN;
853 continue;
857 * Look for a DNAME at the current label, unless this is
858 * the qname.
860 if (i < nlabels) {
861 result = findrdataset(db, node, version,
862 dns_rdatatype_dname,
863 0, now, rdataset, sigrdataset);
864 if (result == ISC_R_SUCCESS) {
865 result = DNS_R_DNAME;
866 break;
871 * Look for an NS at the current label, unless this is the
872 * origin or glue is ok.
874 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
875 result = findrdataset(db, node, version,
876 dns_rdatatype_ns,
877 0, now, rdataset, sigrdataset);
878 if (result == ISC_R_SUCCESS) {
879 if (i == nlabels && type == dns_rdatatype_any)
881 result = DNS_R_ZONECUT;
882 dns_rdataset_disassociate(rdataset);
883 if (sigrdataset != NULL &&
884 dns_rdataset_isassociated
885 (sigrdataset)) {
886 dns_rdataset_disassociate
887 (sigrdataset);
889 } else
890 result = DNS_R_DELEGATION;
891 break;
896 * If the current name is not the qname, add another label
897 * and try again.
899 if (i < nlabels) {
900 destroynode(node);
901 node = NULL;
902 continue;
906 * If we're looking for ANY, we're done.
908 if (type == dns_rdatatype_any) {
909 result = ISC_R_SUCCESS;
910 break;
914 * Look for the qtype.
916 result = findrdataset(db, node, version, type,
917 0, now, rdataset, sigrdataset);
918 if (result == ISC_R_SUCCESS)
919 break;
922 * Look for a CNAME
924 if (type != dns_rdatatype_cname) {
925 result = findrdataset(db, node, version,
926 dns_rdatatype_cname,
927 0, now, rdataset, sigrdataset);
928 if (result == ISC_R_SUCCESS) {
929 result = DNS_R_CNAME;
930 break;
934 result = DNS_R_NXRRSET;
935 break;
938 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
939 dns_rdataset_disassociate(rdataset);
941 if (foundname != NULL) {
942 isc_result_t xresult;
944 xresult = dns_name_copy(xname, foundname, NULL);
945 if (xresult != ISC_R_SUCCESS) {
946 if (node != NULL)
947 destroynode(node);
948 if (dns_rdataset_isassociated(rdataset))
949 dns_rdataset_disassociate(rdataset);
950 return (DNS_R_BADDB);
954 if (nodep != NULL)
955 *nodep = node;
956 else if (node != NULL)
957 detachnode(db, &node);
959 return (result);
962 static isc_result_t
963 findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
964 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
965 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
967 UNUSED(db);
968 UNUSED(name);
969 UNUSED(options);
970 UNUSED(now);
971 UNUSED(nodep);
972 UNUSED(foundname);
973 UNUSED(rdataset);
974 UNUSED(sigrdataset);
976 return (ISC_R_NOTIMPLEMENTED);
979 static void
980 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
981 dns_sdb_t *sdb = (dns_sdb_t *)db;
982 dns_sdbnode_t *node = (dns_sdbnode_t *)source;
984 REQUIRE(VALID_SDB(sdb));
986 UNUSED(sdb);
988 LOCK(&node->lock);
989 INSIST(node->references > 0);
990 node->references++;
991 INSIST(node->references != 0); /* Catch overflow. */
992 UNLOCK(&node->lock);
994 *targetp = source;
997 static void
998 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
999 dns_sdb_t *sdb = (dns_sdb_t *)db;
1000 dns_sdbnode_t *node;
1001 isc_boolean_t need_destroy = ISC_FALSE;
1003 REQUIRE(VALID_SDB(sdb));
1004 REQUIRE(targetp != NULL && *targetp != NULL);
1006 UNUSED(sdb);
1008 node = (dns_sdbnode_t *)(*targetp);
1010 LOCK(&node->lock);
1011 INSIST(node->references > 0);
1012 node->references--;
1013 if (node->references == 0)
1014 need_destroy = ISC_TRUE;
1015 UNLOCK(&node->lock);
1017 if (need_destroy)
1018 destroynode(node);
1020 *targetp = NULL;
1023 static isc_result_t
1024 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
1025 UNUSED(db);
1026 UNUSED(node);
1027 UNUSED(now);
1028 INSIST(0);
1029 return (ISC_R_UNEXPECTED);
1032 static void
1033 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
1034 UNUSED(db);
1035 UNUSED(node);
1036 UNUSED(out);
1037 return;
1040 static isc_result_t
1041 createiterator(dns_db_t *db, isc_boolean_t relative_names,
1042 dns_dbiterator_t **iteratorp)
1044 dns_sdb_t *sdb = (dns_sdb_t *)db;
1045 sdb_dbiterator_t *sdbiter;
1046 dns_sdbimplementation_t *imp = sdb->implementation;
1047 isc_result_t result;
1049 REQUIRE(VALID_SDB(sdb));
1051 if (imp->methods->allnodes == NULL)
1052 return (ISC_R_NOTIMPLEMENTED);
1054 sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t));
1055 if (sdbiter == NULL)
1056 return (ISC_R_NOMEMORY);
1058 sdbiter->common.methods = &dbiterator_methods;
1059 sdbiter->common.db = NULL;
1060 dns_db_attach(db, &sdbiter->common.db);
1061 sdbiter->common.relative_names = relative_names;
1062 sdbiter->common.magic = DNS_DBITERATOR_MAGIC;
1063 ISC_LIST_INIT(sdbiter->nodelist);
1064 sdbiter->current = NULL;
1065 sdbiter->origin = NULL;
1067 MAYBE_LOCK(sdb);
1068 result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter);
1069 MAYBE_UNLOCK(sdb);
1070 if (result != ISC_R_SUCCESS) {
1071 dbiterator_destroy((dns_dbiterator_t **) (void *)&sdbiter);
1072 return (result);
1075 if (sdbiter->origin != NULL) {
1076 ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link);
1077 ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link);
1080 *iteratorp = (dns_dbiterator_t *)sdbiter;
1082 return (ISC_R_SUCCESS);
1085 static isc_result_t
1086 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1087 dns_rdatatype_t type, dns_rdatatype_t covers,
1088 isc_stdtime_t now, dns_rdataset_t *rdataset,
1089 dns_rdataset_t *sigrdataset)
1091 dns_rdatalist_t *list;
1092 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
1094 REQUIRE(VALID_SDBNODE(node));
1096 UNUSED(db);
1097 UNUSED(version);
1098 UNUSED(covers);
1099 UNUSED(now);
1100 UNUSED(sigrdataset);
1102 if (type == dns_rdatatype_rrsig)
1103 return (ISC_R_NOTIMPLEMENTED);
1105 list = ISC_LIST_HEAD(sdbnode->lists);
1106 while (list != NULL) {
1107 if (list->type == type)
1108 break;
1109 list = ISC_LIST_NEXT(list, link);
1111 if (list == NULL)
1112 return (ISC_R_NOTFOUND);
1114 list_tordataset(list, db, node, rdataset);
1116 return (ISC_R_SUCCESS);
1119 static isc_result_t
1120 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1121 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
1123 sdb_rdatasetiter_t *iterator;
1125 REQUIRE(version == NULL || version == &dummy);
1127 UNUSED(version);
1128 UNUSED(now);
1130 iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t));
1131 if (iterator == NULL)
1132 return (ISC_R_NOMEMORY);
1134 iterator->common.magic = DNS_RDATASETITER_MAGIC;
1135 iterator->common.methods = &rdatasetiter_methods;
1136 iterator->common.db = db;
1137 iterator->common.node = NULL;
1138 attachnode(db, node, &iterator->common.node);
1139 iterator->common.version = version;
1140 iterator->common.now = now;
1142 *iteratorp = (dns_rdatasetiter_t *)iterator;
1144 return (ISC_R_SUCCESS);
1147 static isc_result_t
1148 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1149 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
1150 dns_rdataset_t *addedrdataset)
1152 UNUSED(db);
1153 UNUSED(node);
1154 UNUSED(version);
1155 UNUSED(now);
1156 UNUSED(rdataset);
1157 UNUSED(options);
1158 UNUSED(addedrdataset);
1160 return (ISC_R_NOTIMPLEMENTED);
1163 static isc_result_t
1164 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1165 dns_rdataset_t *rdataset, unsigned int options,
1166 dns_rdataset_t *newrdataset)
1168 UNUSED(db);
1169 UNUSED(node);
1170 UNUSED(version);
1171 UNUSED(rdataset);
1172 UNUSED(options);
1173 UNUSED(newrdataset);
1175 return (ISC_R_NOTIMPLEMENTED);
1178 static isc_result_t
1179 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1180 dns_rdatatype_t type, dns_rdatatype_t covers)
1182 UNUSED(db);
1183 UNUSED(node);
1184 UNUSED(version);
1185 UNUSED(type);
1186 UNUSED(covers);
1188 return (ISC_R_NOTIMPLEMENTED);
1191 static isc_boolean_t
1192 issecure(dns_db_t *db) {
1193 UNUSED(db);
1195 return (ISC_FALSE);
1198 static unsigned int
1199 nodecount(dns_db_t *db) {
1200 UNUSED(db);
1202 return (0);
1205 static isc_boolean_t
1206 ispersistent(dns_db_t *db) {
1207 UNUSED(db);
1208 return (ISC_TRUE);
1211 static void
1212 overmem(dns_db_t *db, isc_boolean_t overmem) {
1213 UNUSED(db);
1214 UNUSED(overmem);
1217 static void
1218 settask(dns_db_t *db, isc_task_t *task) {
1219 UNUSED(db);
1220 UNUSED(task);
1224 static dns_dbmethods_t sdb_methods = {
1225 attach,
1226 detach,
1227 beginload,
1228 endload,
1229 dump,
1230 currentversion,
1231 newversion,
1232 attachversion,
1233 closeversion,
1234 findnode,
1235 find,
1236 findzonecut,
1237 attachnode,
1238 detachnode,
1239 expirenode,
1240 printnode,
1241 createiterator,
1242 findrdataset,
1243 allrdatasets,
1244 addrdataset,
1245 subtractrdataset,
1246 deleterdataset,
1247 issecure,
1248 nodecount,
1249 ispersistent,
1250 overmem,
1251 settask,
1252 NULL,
1253 NULL,
1254 NULL
1257 static isc_result_t
1258 dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
1259 dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
1260 void *driverarg, dns_db_t **dbp)
1262 dns_sdb_t *sdb;
1263 isc_result_t result;
1264 char zonestr[DNS_NAME_MAXTEXT + 1];
1265 isc_buffer_t b;
1266 dns_sdbimplementation_t *imp;
1268 REQUIRE(driverarg != NULL);
1270 imp = driverarg;
1272 if (type != dns_dbtype_zone)
1273 return (ISC_R_NOTIMPLEMENTED);
1275 sdb = isc_mem_get(mctx, sizeof(dns_sdb_t));
1276 if (sdb == NULL)
1277 return (ISC_R_NOMEMORY);
1278 memset(sdb, 0, sizeof(dns_sdb_t));
1280 dns_name_init(&sdb->common.origin, NULL);
1281 sdb->common.attributes = 0;
1282 sdb->common.methods = &sdb_methods;
1283 sdb->common.rdclass = rdclass;
1284 sdb->common.mctx = NULL;
1285 sdb->implementation = imp;
1287 isc_mem_attach(mctx, &sdb->common.mctx);
1289 result = isc_mutex_init(&sdb->lock);
1290 if (result != ISC_R_SUCCESS)
1291 goto cleanup_mctx;
1293 result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
1294 if (result != ISC_R_SUCCESS)
1295 goto cleanup_lock;
1297 isc_buffer_init(&b, zonestr, sizeof(zonestr));
1298 result = dns_name_totext(origin, ISC_TRUE, &b);
1299 if (result != ISC_R_SUCCESS)
1300 goto cleanup_origin;
1301 isc_buffer_putuint8(&b, 0);
1303 sdb->zone = isc_mem_strdup(mctx, zonestr);
1304 if (sdb->zone == NULL) {
1305 result = ISC_R_NOMEMORY;
1306 goto cleanup_origin;
1309 sdb->dbdata = NULL;
1310 if (imp->methods->create != NULL) {
1311 MAYBE_LOCK(sdb);
1312 result = imp->methods->create(sdb->zone, argc, argv,
1313 imp->driverdata, &sdb->dbdata);
1314 MAYBE_UNLOCK(sdb);
1315 if (result != ISC_R_SUCCESS)
1316 goto cleanup_zonestr;
1319 sdb->references = 1;
1321 sdb->common.magic = DNS_DB_MAGIC;
1322 sdb->common.impmagic = SDB_MAGIC;
1324 *dbp = (dns_db_t *)sdb;
1326 return (ISC_R_SUCCESS);
1328 cleanup_zonestr:
1329 isc_mem_free(mctx, sdb->zone);
1330 cleanup_origin:
1331 dns_name_free(&sdb->common.origin, mctx);
1332 cleanup_lock:
1333 isc_mutex_destroy(&sdb->lock);
1334 cleanup_mctx:
1335 isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
1336 isc_mem_detach(&mctx);
1338 return (result);
1343 * Rdataset Methods
1346 static void
1347 disassociate(dns_rdataset_t *rdataset) {
1348 dns_dbnode_t *node = rdataset->private5;
1349 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
1350 dns_db_t *db = (dns_db_t *) sdbnode->sdb;
1352 detachnode(db, &node);
1353 isc__rdatalist_disassociate(rdataset);
1356 static void
1357 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1358 dns_dbnode_t *node = source->private5;
1359 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
1360 dns_db_t *db = (dns_db_t *) sdbnode->sdb;
1361 dns_dbnode_t *tempdb = NULL;
1363 isc__rdatalist_clone(source, target);
1364 attachnode(db, node, &tempdb);
1365 source->private5 = tempdb;
1368 static dns_rdatasetmethods_t methods = {
1369 disassociate,
1370 isc__rdatalist_first,
1371 isc__rdatalist_next,
1372 isc__rdatalist_current,
1373 rdataset_clone,
1374 isc__rdatalist_count,
1375 isc__rdatalist_addnoqname,
1376 isc__rdatalist_getnoqname,
1377 NULL,
1378 NULL,
1379 NULL,
1380 NULL,
1381 NULL
1384 static void
1385 list_tordataset(dns_rdatalist_t *rdatalist,
1386 dns_db_t *db, dns_dbnode_t *node,
1387 dns_rdataset_t *rdataset)
1390 * The sdb rdataset is an rdatalist with some additions.
1391 * - private1 & private2 are used by the rdatalist.
1392 * - private3 & private 4 are unused.
1393 * - private5 is the node.
1396 /* This should never fail. */
1397 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1398 ISC_R_SUCCESS);
1400 rdataset->methods = &methods;
1401 dns_db_attachnode(db, node, &rdataset->private5);
1405 * Database Iterator Methods
1407 static void
1408 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1409 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp);
1410 dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db;
1412 while (!ISC_LIST_EMPTY(sdbiter->nodelist)) {
1413 dns_sdbnode_t *node;
1414 node = ISC_LIST_HEAD(sdbiter->nodelist);
1415 ISC_LIST_UNLINK(sdbiter->nodelist, node, link);
1416 destroynode(node);
1419 dns_db_detach(&sdbiter->common.db);
1420 isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t));
1422 *iteratorp = NULL;
1425 static isc_result_t
1426 dbiterator_first(dns_dbiterator_t *iterator) {
1427 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1429 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1430 if (sdbiter->current == NULL)
1431 return (ISC_R_NOMORE);
1432 else
1433 return (ISC_R_SUCCESS);
1436 static isc_result_t
1437 dbiterator_last(dns_dbiterator_t *iterator) {
1438 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1440 sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist);
1441 if (sdbiter->current == NULL)
1442 return (ISC_R_NOMORE);
1443 else
1444 return (ISC_R_SUCCESS);
1447 static isc_result_t
1448 dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
1449 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1451 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1452 while (sdbiter->current != NULL) {
1453 if (dns_name_equal(sdbiter->current->name, name))
1454 return (ISC_R_SUCCESS);
1455 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
1457 return (ISC_R_NOTFOUND);
1460 static isc_result_t
1461 dbiterator_prev(dns_dbiterator_t *iterator) {
1462 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1464 sdbiter->current = ISC_LIST_PREV(sdbiter->current, link);
1465 if (sdbiter->current == NULL)
1466 return (ISC_R_NOMORE);
1467 else
1468 return (ISC_R_SUCCESS);
1471 static isc_result_t
1472 dbiterator_next(dns_dbiterator_t *iterator) {
1473 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1475 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
1476 if (sdbiter->current == NULL)
1477 return (ISC_R_NOMORE);
1478 else
1479 return (ISC_R_SUCCESS);
1482 static isc_result_t
1483 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1484 dns_name_t *name)
1486 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1488 attachnode(iterator->db, sdbiter->current, nodep);
1489 if (name != NULL)
1490 return (dns_name_copy(sdbiter->current->name, name, NULL));
1491 return (ISC_R_SUCCESS);
1494 static isc_result_t
1495 dbiterator_pause(dns_dbiterator_t *iterator) {
1496 UNUSED(iterator);
1497 return (ISC_R_SUCCESS);
1500 static isc_result_t
1501 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1502 UNUSED(iterator);
1503 return (dns_name_copy(dns_rootname, name, NULL));
1507 * Rdataset Iterator Methods
1510 static void
1511 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
1512 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp);
1513 detachnode(sdbiterator->common.db, &sdbiterator->common.node);
1514 isc_mem_put(sdbiterator->common.db->mctx, sdbiterator,
1515 sizeof(sdb_rdatasetiter_t));
1516 *iteratorp = NULL;
1519 static isc_result_t
1520 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
1521 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1522 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node;
1524 if (ISC_LIST_EMPTY(sdbnode->lists))
1525 return (ISC_R_NOMORE);
1526 sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists);
1527 return (ISC_R_SUCCESS);
1530 static isc_result_t
1531 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
1532 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1534 sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link);
1535 if (sdbiterator->current == NULL)
1536 return (ISC_R_NOMORE);
1537 else
1538 return (ISC_R_SUCCESS);
1541 static void
1542 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
1543 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1545 list_tordataset(sdbiterator->current, iterator->db, iterator->node,
1546 rdataset);