No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / sdb.c
blob14d2ff2896cf178934161950a2f1dbad5cc08e85
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: sdb.c,v 1.71 2009/10/08 23:13:07 marka Exp */
22 /*! \file */
24 #include <config.h>
26 #include <string.h>
28 #include <isc/buffer.h>
29 #include <isc/lex.h>
30 #include <isc/log.h>
31 #include <isc/magic.h>
32 #include <isc/mem.h>
33 #include <isc/once.h>
34 #include <isc/print.h>
35 #include <isc/region.h>
36 #include <isc/util.h>
38 #include <dns/callbacks.h>
39 #include <dns/db.h>
40 #include <dns/dbiterator.h>
41 #include <dns/fixedname.h>
42 #include <dns/log.h>
43 #include <dns/rdata.h>
44 #include <dns/rdatalist.h>
45 #include <dns/rdataset.h>
46 #include <dns/rdatasetiter.h>
47 #include <dns/rdatatype.h>
48 #include <dns/result.h>
49 #include <dns/sdb.h>
50 #include <dns/types.h>
52 #include "rdatalist_p.h"
54 struct dns_sdbimplementation {
55 const dns_sdbmethods_t *methods;
56 void *driverdata;
57 unsigned int flags;
58 isc_mem_t *mctx;
59 isc_mutex_t driverlock;
60 dns_dbimplementation_t *dbimp;
63 struct dns_sdb {
64 /* Unlocked */
65 dns_db_t common;
66 char *zone;
67 dns_sdbimplementation_t *implementation;
68 void *dbdata;
69 isc_mutex_t lock;
70 /* Locked */
71 unsigned int references;
74 struct dns_sdblookup {
75 /* Unlocked */
76 unsigned int magic;
77 dns_sdb_t *sdb;
78 ISC_LIST(dns_rdatalist_t) lists;
79 ISC_LIST(isc_buffer_t) buffers;
80 dns_name_t *name;
81 ISC_LINK(dns_sdblookup_t) link;
82 isc_mutex_t lock;
83 dns_rdatacallbacks_t callbacks;
84 /* Locked */
85 unsigned int references;
88 typedef struct dns_sdblookup dns_sdbnode_t;
90 struct dns_sdballnodes {
91 dns_dbiterator_t common;
92 ISC_LIST(dns_sdbnode_t) nodelist;
93 dns_sdbnode_t *current;
94 dns_sdbnode_t *origin;
97 typedef dns_sdballnodes_t sdb_dbiterator_t;
99 typedef struct sdb_rdatasetiter {
100 dns_rdatasetiter_t common;
101 dns_rdatalist_t *current;
102 } sdb_rdatasetiter_t;
104 #define SDB_MAGIC ISC_MAGIC('S', 'D', 'B', '-')
107 * Note that "impmagic" is not the first four bytes of the struct, so
108 * ISC_MAGIC_VALID cannot be used.
110 #define VALID_SDB(sdb) ((sdb) != NULL && \
111 (sdb)->common.impmagic == SDB_MAGIC)
113 #define SDBLOOKUP_MAGIC ISC_MAGIC('S','D','B','L')
114 #define VALID_SDBLOOKUP(sdbl) ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)
115 #define VALID_SDBNODE(sdbn) VALID_SDBLOOKUP(sdbn)
117 /* These values are taken from RFC1537 */
118 #define SDB_DEFAULT_REFRESH (60 * 60 * 8)
119 #define SDB_DEFAULT_RETRY (60 * 60 * 2)
120 #define SDB_DEFAULT_EXPIRE (60 * 60 * 24 * 7)
121 #define SDB_DEFAULT_MINIMUM (60 * 60 * 24)
123 /* This is a reasonable value */
124 #define SDB_DEFAULT_TTL (60 * 60 * 24)
126 #ifdef __COVERITY__
127 #define MAYBE_LOCK(sdb) LOCK(&sdb->implementation->driverlock)
128 #define MAYBE_UNLOCK(sdb) UNLOCK(&sdb->implementation->driverlock)
129 #else
130 #define MAYBE_LOCK(sdb) \
131 do { \
132 unsigned int flags = sdb->implementation->flags; \
133 if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \
134 LOCK(&sdb->implementation->driverlock); \
135 } while (0)
137 #define MAYBE_UNLOCK(sdb) \
138 do { \
139 unsigned int flags = sdb->implementation->flags; \
140 if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \
141 UNLOCK(&sdb->implementation->driverlock); \
142 } while (0)
143 #endif
145 static int dummy;
147 static isc_result_t dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin,
148 dns_dbtype_t type, dns_rdataclass_t rdclass,
149 unsigned int argc, char *argv[],
150 void *driverarg, dns_db_t **dbp);
152 static isc_result_t findrdataset(dns_db_t *db, dns_dbnode_t *node,
153 dns_dbversion_t *version,
154 dns_rdatatype_t type, dns_rdatatype_t covers,
155 isc_stdtime_t now, dns_rdataset_t *rdataset,
156 dns_rdataset_t *sigrdataset);
158 static isc_result_t createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep);
160 static void destroynode(dns_sdbnode_t *node);
162 static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
165 static void list_tordataset(dns_rdatalist_t *rdatalist,
166 dns_db_t *db, dns_dbnode_t *node,
167 dns_rdataset_t *rdataset);
169 static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
170 static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
171 static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
172 static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
173 dns_name_t *name);
174 static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
175 static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
176 static isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
177 dns_dbnode_t **nodep,
178 dns_name_t *name);
179 static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
180 static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
181 dns_name_t *name);
183 static dns_dbiteratormethods_t dbiterator_methods = {
184 dbiterator_destroy,
185 dbiterator_first,
186 dbiterator_last,
187 dbiterator_seek,
188 dbiterator_prev,
189 dbiterator_next,
190 dbiterator_current,
191 dbiterator_pause,
192 dbiterator_origin
195 static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
196 static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator);
197 static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator);
198 static void rdatasetiter_current(dns_rdatasetiter_t *iterator,
199 dns_rdataset_t *rdataset);
201 static dns_rdatasetitermethods_t rdatasetiter_methods = {
202 rdatasetiter_destroy,
203 rdatasetiter_first,
204 rdatasetiter_next,
205 rdatasetiter_current
209 * Functions used by implementors of simple databases
211 isc_result_t
212 dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
213 void *driverdata, unsigned int flags, isc_mem_t *mctx,
214 dns_sdbimplementation_t **sdbimp)
216 dns_sdbimplementation_t *imp;
217 isc_result_t result;
219 REQUIRE(drivername != NULL);
220 REQUIRE(methods != NULL);
221 REQUIRE(methods->lookup != NULL);
222 REQUIRE(mctx != NULL);
223 REQUIRE(sdbimp != NULL && *sdbimp == NULL);
224 REQUIRE((flags & ~(DNS_SDBFLAG_RELATIVEOWNER |
225 DNS_SDBFLAG_RELATIVERDATA |
226 DNS_SDBFLAG_THREADSAFE)) == 0);
228 imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t));
229 if (imp == NULL)
230 return (ISC_R_NOMEMORY);
231 imp->methods = methods;
232 imp->driverdata = driverdata;
233 imp->flags = flags;
234 imp->mctx = NULL;
235 isc_mem_attach(mctx, &imp->mctx);
236 result = isc_mutex_init(&imp->driverlock);
237 if (result != ISC_R_SUCCESS)
238 goto cleanup_mctx;
240 imp->dbimp = NULL;
241 result = dns_db_register(drivername, dns_sdb_create, imp, mctx,
242 &imp->dbimp);
243 if (result != ISC_R_SUCCESS)
244 goto cleanup_mutex;
245 *sdbimp = imp;
247 return (ISC_R_SUCCESS);
249 cleanup_mutex:
250 DESTROYLOCK(&imp->driverlock);
251 cleanup_mctx:
252 isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
253 return (result);
256 void
257 dns_sdb_unregister(dns_sdbimplementation_t **sdbimp) {
258 dns_sdbimplementation_t *imp;
259 isc_mem_t *mctx;
261 REQUIRE(sdbimp != NULL && *sdbimp != NULL);
263 imp = *sdbimp;
264 dns_db_unregister(&imp->dbimp);
265 DESTROYLOCK(&imp->driverlock);
267 mctx = imp->mctx;
268 isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
269 isc_mem_detach(&mctx);
271 *sdbimp = NULL;
274 static inline unsigned int
275 initial_size(unsigned int len) {
276 unsigned int size;
278 for (size = 1024; size < (64 * 1024); size *= 2)
279 if (len < size)
280 return (size);
281 return (65535);
284 isc_result_t
285 dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval, dns_ttl_t ttl,
286 const unsigned char *rdatap, unsigned int rdlen)
288 dns_rdatalist_t *rdatalist;
289 dns_rdata_t *rdata;
290 isc_buffer_t *rdatabuf = NULL;
291 isc_result_t result;
292 isc_mem_t *mctx;
293 isc_region_t region;
295 mctx = lookup->sdb->common.mctx;
297 rdatalist = ISC_LIST_HEAD(lookup->lists);
298 while (rdatalist != NULL) {
299 if (rdatalist->type == typeval)
300 break;
301 rdatalist = ISC_LIST_NEXT(rdatalist, link);
304 if (rdatalist == NULL) {
305 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
306 if (rdatalist == NULL)
307 return (ISC_R_NOMEMORY);
308 rdatalist->rdclass = lookup->sdb->common.rdclass;
309 rdatalist->type = typeval;
310 rdatalist->covers = 0;
311 rdatalist->ttl = ttl;
312 ISC_LIST_INIT(rdatalist->rdata);
313 ISC_LINK_INIT(rdatalist, link);
314 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
315 } else
316 if (rdatalist->ttl != ttl)
317 return (DNS_R_BADTTL);
319 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
320 if (rdata == NULL)
321 return (ISC_R_NOMEMORY);
323 result = isc_buffer_allocate(mctx, &rdatabuf, rdlen);
324 if (result != ISC_R_SUCCESS)
325 goto failure;
326 DE_CONST(rdatap, region.base);
327 region.length = rdlen;
328 isc_buffer_copyregion(rdatabuf, &region);
329 isc_buffer_usedregion(rdatabuf, &region);
330 dns_rdata_init(rdata);
331 dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type,
332 &region);
333 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
334 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
335 rdata = NULL;
337 failure:
338 if (rdata != NULL)
339 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
340 return (result);
344 isc_result_t
345 dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
346 const char *data)
348 unsigned int datalen;
349 dns_rdatatype_t typeval;
350 isc_textregion_t r;
351 isc_lex_t *lex = NULL;
352 isc_result_t result;
353 unsigned char *p = NULL;
354 unsigned int size = 0; /* Init to suppress compiler warning */
355 isc_mem_t *mctx;
356 dns_sdbimplementation_t *imp;
357 dns_name_t *origin;
358 isc_buffer_t b;
359 isc_buffer_t rb;
361 REQUIRE(VALID_SDBLOOKUP(lookup));
362 REQUIRE(type != NULL);
363 REQUIRE(data != NULL);
365 mctx = lookup->sdb->common.mctx;
367 DE_CONST(type, r.base);
368 r.length = strlen(type);
369 result = dns_rdatatype_fromtext(&typeval, &r);
370 if (result != ISC_R_SUCCESS)
371 return (result);
373 imp = lookup->sdb->implementation;
374 if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
375 origin = &lookup->sdb->common.origin;
376 else
377 origin = dns_rootname;
379 result = isc_lex_create(mctx, 64, &lex);
380 if (result != ISC_R_SUCCESS)
381 goto failure;
383 datalen = strlen(data);
384 size = initial_size(datalen);
385 do {
386 isc_buffer_init(&b, data, datalen);
387 isc_buffer_add(&b, datalen);
388 result = isc_lex_openbuffer(lex, &b);
389 if (result != ISC_R_SUCCESS)
390 goto failure;
392 if (size >= 65535)
393 size = 65535;
394 p = isc_mem_get(mctx, size);
395 if (p == NULL) {
396 result = ISC_R_NOMEMORY;
397 goto failure;
399 isc_buffer_init(&rb, p, size);
400 result = dns_rdata_fromtext(NULL,
401 lookup->sdb->common.rdclass,
402 typeval, lex,
403 origin, 0,
404 mctx, &rb,
405 &lookup->callbacks);
406 if (result != ISC_R_NOSPACE)
407 break;
410 * Is the RR too big?
412 if (size >= 65535)
413 break;
414 isc_mem_put(mctx, p, size);
415 p = NULL;
416 size *= 2;
417 } while (result == ISC_R_NOSPACE);
419 if (result != ISC_R_SUCCESS)
420 goto failure;
422 result = dns_sdb_putrdata(lookup, typeval, ttl,
423 isc_buffer_base(&rb),
424 isc_buffer_usedlength(&rb));
425 failure:
426 if (p != NULL)
427 isc_mem_put(mctx, p, size);
428 if (lex != NULL)
429 isc_lex_destroy(&lex);
431 return (result);
434 static isc_result_t
435 getnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) {
436 dns_name_t *newname, *origin;
437 dns_fixedname_t fnewname;
438 dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db;
439 dns_sdbimplementation_t *imp = sdb->implementation;
440 dns_sdbnode_t *sdbnode;
441 isc_mem_t *mctx = sdb->common.mctx;
442 isc_buffer_t b;
443 isc_result_t result;
445 dns_fixedname_init(&fnewname);
446 newname = dns_fixedname_name(&fnewname);
448 if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
449 origin = &sdb->common.origin;
450 else
451 origin = dns_rootname;
452 isc_buffer_init(&b, name, strlen(name));
453 isc_buffer_add(&b, strlen(name));
455 result = dns_name_fromtext(newname, &b, origin, 0, NULL);
456 if (result != ISC_R_SUCCESS)
457 return (result);
459 if (allnodes->common.relative_names) {
460 /* All names are relative to the root */
461 unsigned int nlabels = dns_name_countlabels(newname);
462 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
465 sdbnode = ISC_LIST_HEAD(allnodes->nodelist);
466 if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) {
467 sdbnode = NULL;
468 result = createnode(sdb, &sdbnode);
469 if (result != ISC_R_SUCCESS)
470 return (result);
471 sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t));
472 if (sdbnode->name == NULL) {
473 destroynode(sdbnode);
474 return (ISC_R_NOMEMORY);
476 dns_name_init(sdbnode->name, NULL);
477 result = dns_name_dup(newname, mctx, sdbnode->name);
478 if (result != ISC_R_SUCCESS) {
479 isc_mem_put(mctx, sdbnode->name, sizeof(dns_name_t));
480 destroynode(sdbnode);
481 return (result);
483 ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link);
484 if (allnodes->origin == NULL &&
485 dns_name_equal(newname, &sdb->common.origin))
486 allnodes->origin = sdbnode;
488 *nodep = sdbnode;
489 return (ISC_R_SUCCESS);
492 isc_result_t
493 dns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name,
494 const char *type, dns_ttl_t ttl, const char *data)
496 isc_result_t result;
497 dns_sdbnode_t *sdbnode = NULL;
498 result = getnode(allnodes, name, &sdbnode);
499 if (result != ISC_R_SUCCESS)
500 return (result);
501 return (dns_sdb_putrr(sdbnode, type, ttl, data));
504 isc_result_t
505 dns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name,
506 dns_rdatatype_t type, dns_ttl_t ttl,
507 const void *rdata, unsigned int rdlen)
509 isc_result_t result;
510 dns_sdbnode_t *sdbnode = NULL;
511 result = getnode(allnodes, name, &sdbnode);
512 if (result != ISC_R_SUCCESS)
513 return (result);
514 return (dns_sdb_putrdata(sdbnode, type, ttl, rdata, rdlen));
517 isc_result_t
518 dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
519 isc_uint32_t serial)
521 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
522 int n;
524 REQUIRE(mname != NULL);
525 REQUIRE(rname != NULL);
527 n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u",
528 mname, rname, serial,
529 SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY,
530 SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM);
531 if (n >= (int)sizeof(str) || n < 0)
532 return (ISC_R_NOSPACE);
533 return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));
537 * DB routines
540 static void
541 attach(dns_db_t *source, dns_db_t **targetp) {
542 dns_sdb_t *sdb = (dns_sdb_t *) source;
544 REQUIRE(VALID_SDB(sdb));
546 LOCK(&sdb->lock);
547 REQUIRE(sdb->references > 0);
548 sdb->references++;
549 UNLOCK(&sdb->lock);
551 *targetp = source;
554 static void
555 destroy(dns_sdb_t *sdb) {
556 isc_mem_t *mctx;
557 dns_sdbimplementation_t *imp = sdb->implementation;
559 mctx = sdb->common.mctx;
561 if (imp->methods->destroy != NULL) {
562 MAYBE_LOCK(sdb);
563 imp->methods->destroy(sdb->zone, imp->driverdata,
564 &sdb->dbdata);
565 MAYBE_UNLOCK(sdb);
568 isc_mem_free(mctx, sdb->zone);
569 DESTROYLOCK(&sdb->lock);
571 sdb->common.magic = 0;
572 sdb->common.impmagic = 0;
574 dns_name_free(&sdb->common.origin, mctx);
576 isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
577 isc_mem_detach(&mctx);
580 static void
581 detach(dns_db_t **dbp) {
582 dns_sdb_t *sdb = (dns_sdb_t *)(*dbp);
583 isc_boolean_t need_destroy = ISC_FALSE;
585 REQUIRE(VALID_SDB(sdb));
586 LOCK(&sdb->lock);
587 REQUIRE(sdb->references > 0);
588 sdb->references--;
589 if (sdb->references == 0)
590 need_destroy = ISC_TRUE;
591 UNLOCK(&sdb->lock);
593 if (need_destroy)
594 destroy(sdb);
596 *dbp = NULL;
599 static isc_result_t
600 beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
601 UNUSED(db);
602 UNUSED(addp);
603 UNUSED(dbloadp);
604 return (ISC_R_NOTIMPLEMENTED);
607 static isc_result_t
608 endload(dns_db_t *db, dns_dbload_t **dbloadp) {
609 UNUSED(db);
610 UNUSED(dbloadp);
611 return (ISC_R_NOTIMPLEMENTED);
614 static isc_result_t
615 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
616 dns_masterformat_t masterformat) {
617 UNUSED(db);
618 UNUSED(version);
619 UNUSED(filename);
620 UNUSED(masterformat);
621 return (ISC_R_NOTIMPLEMENTED);
624 static void
625 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
626 REQUIRE(versionp != NULL && *versionp == NULL);
628 UNUSED(db);
630 *versionp = (void *) &dummy;
631 return;
634 static isc_result_t
635 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
636 UNUSED(db);
637 UNUSED(versionp);
639 return (ISC_R_NOTIMPLEMENTED);
642 static void
643 attachversion(dns_db_t *db, dns_dbversion_t *source,
644 dns_dbversion_t **targetp)
646 REQUIRE(source != NULL && source == (void *) &dummy);
647 REQUIRE(targetp != NULL && *targetp == NULL);
649 UNUSED(db);
650 *targetp = source;
651 return;
654 static void
655 closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
656 REQUIRE(versionp != NULL && *versionp == (void *) &dummy);
657 REQUIRE(commit == ISC_FALSE);
659 UNUSED(db);
660 UNUSED(commit);
662 *versionp = NULL;
665 static isc_result_t
666 createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) {
667 dns_sdbnode_t *node;
668 isc_result_t result;
670 node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t));
671 if (node == NULL)
672 return (ISC_R_NOMEMORY);
674 node->sdb = NULL;
675 attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb);
676 ISC_LIST_INIT(node->lists);
677 ISC_LIST_INIT(node->buffers);
678 ISC_LINK_INIT(node, link);
679 node->name = NULL;
680 result = isc_mutex_init(&node->lock);
681 if (result != ISC_R_SUCCESS) {
682 isc_mem_put(sdb->common.mctx, node, sizeof(dns_sdbnode_t));
683 return (result);
685 dns_rdatacallbacks_init(&node->callbacks);
686 node->references = 1;
687 node->magic = SDBLOOKUP_MAGIC;
689 *nodep = node;
690 return (ISC_R_SUCCESS);
693 static void
694 destroynode(dns_sdbnode_t *node) {
695 dns_rdatalist_t *list;
696 dns_rdata_t *rdata;
697 isc_buffer_t *b;
698 dns_sdb_t *sdb;
699 isc_mem_t *mctx;
701 sdb = node->sdb;
702 mctx = sdb->common.mctx;
704 while (!ISC_LIST_EMPTY(node->lists)) {
705 list = ISC_LIST_HEAD(node->lists);
706 while (!ISC_LIST_EMPTY(list->rdata)) {
707 rdata = ISC_LIST_HEAD(list->rdata);
708 ISC_LIST_UNLINK(list->rdata, rdata, link);
709 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
711 ISC_LIST_UNLINK(node->lists, list, link);
712 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
715 while (!ISC_LIST_EMPTY(node->buffers)) {
716 b = ISC_LIST_HEAD(node->buffers);
717 ISC_LIST_UNLINK(node->buffers, b, link);
718 isc_buffer_free(&b);
721 if (node->name != NULL) {
722 dns_name_free(node->name, mctx);
723 isc_mem_put(mctx, node->name, sizeof(dns_name_t));
725 DESTROYLOCK(&node->lock);
726 node->magic = 0;
727 isc_mem_put(mctx, node, sizeof(dns_sdbnode_t));
728 detach((dns_db_t **) (void *)&sdb);
731 static isc_result_t
732 findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
733 dns_dbnode_t **nodep)
735 dns_sdb_t *sdb = (dns_sdb_t *)db;
736 dns_sdbnode_t *node = NULL;
737 isc_result_t result;
738 isc_buffer_t b;
739 char namestr[DNS_NAME_MAXTEXT + 1];
740 isc_boolean_t isorigin;
741 dns_sdbimplementation_t *imp;
743 REQUIRE(VALID_SDB(sdb));
744 REQUIRE(create == ISC_FALSE);
745 REQUIRE(nodep != NULL && *nodep == NULL);
747 UNUSED(name);
748 UNUSED(create);
750 imp = sdb->implementation;
752 isc_buffer_init(&b, namestr, sizeof(namestr));
753 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
754 dns_name_t relname;
755 unsigned int labels;
757 labels = dns_name_countlabels(name) -
758 dns_name_countlabels(&db->origin);
759 dns_name_init(&relname, NULL);
760 dns_name_getlabelsequence(name, 0, labels, &relname);
761 result = dns_name_totext(&relname, ISC_TRUE, &b);
762 if (result != ISC_R_SUCCESS)
763 return (result);
764 } else {
765 result = dns_name_totext(name, ISC_TRUE, &b);
766 if (result != ISC_R_SUCCESS)
767 return (result);
769 isc_buffer_putuint8(&b, 0);
771 result = createnode(sdb, &node);
772 if (result != ISC_R_SUCCESS)
773 return (result);
775 isorigin = dns_name_equal(name, &sdb->common.origin);
777 MAYBE_LOCK(sdb);
778 result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata, node);
779 MAYBE_UNLOCK(sdb);
780 if (result != ISC_R_SUCCESS &&
781 !(result == ISC_R_NOTFOUND &&
782 isorigin && imp->methods->authority != NULL))
784 destroynode(node);
785 return (result);
788 if (isorigin && imp->methods->authority != NULL) {
789 MAYBE_LOCK(sdb);
790 result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
791 MAYBE_UNLOCK(sdb);
792 if (result != ISC_R_SUCCESS) {
793 destroynode(node);
794 return (result);
798 *nodep = node;
799 return (ISC_R_SUCCESS);
802 static isc_result_t
803 find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
804 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
805 dns_dbnode_t **nodep, dns_name_t *foundname,
806 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
808 dns_sdb_t *sdb = (dns_sdb_t *)db;
809 dns_dbnode_t *node = NULL;
810 dns_fixedname_t fname;
811 dns_rdataset_t xrdataset;
812 dns_name_t *xname;
813 unsigned int nlabels, olabels;
814 isc_result_t result;
815 unsigned int i;
817 REQUIRE(VALID_SDB(sdb));
818 REQUIRE(nodep == NULL || *nodep == NULL);
819 REQUIRE(version == NULL || version == (void *) &dummy);
821 UNUSED(options);
822 UNUSED(sdb);
824 if (!dns_name_issubdomain(name, &db->origin))
825 return (DNS_R_NXDOMAIN);
827 olabels = dns_name_countlabels(&db->origin);
828 nlabels = dns_name_countlabels(name);
830 dns_fixedname_init(&fname);
831 xname = dns_fixedname_name(&fname);
833 if (rdataset == NULL) {
834 dns_rdataset_init(&xrdataset);
835 rdataset = &xrdataset;
838 result = DNS_R_NXDOMAIN;
840 for (i = olabels; i <= nlabels; i++) {
842 * Unless this is an explicit lookup at the origin, don't
843 * look at the origin.
845 if (i == olabels && i != nlabels)
846 continue;
849 * Look up the next label.
851 dns_name_getlabelsequence(name, nlabels - i, i, xname);
852 result = findnode(db, xname, ISC_FALSE, &node);
853 if (result != ISC_R_SUCCESS) {
854 result = DNS_R_NXDOMAIN;
855 continue;
859 * Look for a DNAME at the current label, unless this is
860 * the qname.
862 if (i < nlabels) {
863 result = findrdataset(db, node, version,
864 dns_rdatatype_dname,
865 0, now, rdataset, sigrdataset);
866 if (result == ISC_R_SUCCESS) {
867 result = DNS_R_DNAME;
868 break;
873 * Look for an NS at the current label, unless this is the
874 * origin or glue is ok.
876 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
877 result = findrdataset(db, node, version,
878 dns_rdatatype_ns,
879 0, now, rdataset, sigrdataset);
880 if (result == ISC_R_SUCCESS) {
881 if (i == nlabels && type == dns_rdatatype_any)
883 result = DNS_R_ZONECUT;
884 dns_rdataset_disassociate(rdataset);
885 if (sigrdataset != NULL &&
886 dns_rdataset_isassociated
887 (sigrdataset)) {
888 dns_rdataset_disassociate
889 (sigrdataset);
891 } else
892 result = DNS_R_DELEGATION;
893 break;
898 * If the current name is not the qname, add another label
899 * and try again.
901 if (i < nlabels) {
902 destroynode(node);
903 node = NULL;
904 continue;
908 * If we're looking for ANY, we're done.
910 if (type == dns_rdatatype_any) {
911 result = ISC_R_SUCCESS;
912 break;
916 * Look for the qtype.
918 result = findrdataset(db, node, version, type,
919 0, now, rdataset, sigrdataset);
920 if (result == ISC_R_SUCCESS)
921 break;
924 * Look for a CNAME
926 if (type != dns_rdatatype_cname) {
927 result = findrdataset(db, node, version,
928 dns_rdatatype_cname,
929 0, now, rdataset, sigrdataset);
930 if (result == ISC_R_SUCCESS) {
931 result = DNS_R_CNAME;
932 break;
936 result = DNS_R_NXRRSET;
937 break;
940 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
941 dns_rdataset_disassociate(rdataset);
943 if (foundname != NULL) {
944 isc_result_t xresult;
946 xresult = dns_name_copy(xname, foundname, NULL);
947 if (xresult != ISC_R_SUCCESS) {
948 if (node != NULL)
949 destroynode(node);
950 if (dns_rdataset_isassociated(rdataset))
951 dns_rdataset_disassociate(rdataset);
952 return (DNS_R_BADDB);
956 if (nodep != NULL)
957 *nodep = node;
958 else if (node != NULL)
959 detachnode(db, &node);
961 return (result);
964 static isc_result_t
965 findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
966 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
967 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
969 UNUSED(db);
970 UNUSED(name);
971 UNUSED(options);
972 UNUSED(now);
973 UNUSED(nodep);
974 UNUSED(foundname);
975 UNUSED(rdataset);
976 UNUSED(sigrdataset);
978 return (ISC_R_NOTIMPLEMENTED);
981 static void
982 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
983 dns_sdb_t *sdb = (dns_sdb_t *)db;
984 dns_sdbnode_t *node = (dns_sdbnode_t *)source;
986 REQUIRE(VALID_SDB(sdb));
988 UNUSED(sdb);
990 LOCK(&node->lock);
991 INSIST(node->references > 0);
992 node->references++;
993 INSIST(node->references != 0); /* Catch overflow. */
994 UNLOCK(&node->lock);
996 *targetp = source;
999 static void
1000 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
1001 dns_sdb_t *sdb = (dns_sdb_t *)db;
1002 dns_sdbnode_t *node;
1003 isc_boolean_t need_destroy = ISC_FALSE;
1005 REQUIRE(VALID_SDB(sdb));
1006 REQUIRE(targetp != NULL && *targetp != NULL);
1008 UNUSED(sdb);
1010 node = (dns_sdbnode_t *)(*targetp);
1012 LOCK(&node->lock);
1013 INSIST(node->references > 0);
1014 node->references--;
1015 if (node->references == 0)
1016 need_destroy = ISC_TRUE;
1017 UNLOCK(&node->lock);
1019 if (need_destroy)
1020 destroynode(node);
1022 *targetp = NULL;
1025 static isc_result_t
1026 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
1027 UNUSED(db);
1028 UNUSED(node);
1029 UNUSED(now);
1030 INSIST(0);
1031 return (ISC_R_UNEXPECTED);
1034 static void
1035 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
1036 UNUSED(db);
1037 UNUSED(node);
1038 UNUSED(out);
1039 return;
1042 static isc_result_t
1043 createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
1045 dns_sdb_t *sdb = (dns_sdb_t *)db;
1046 sdb_dbiterator_t *sdbiter;
1047 dns_sdbimplementation_t *imp = sdb->implementation;
1048 isc_result_t result;
1050 REQUIRE(VALID_SDB(sdb));
1052 if (imp->methods->allnodes == NULL)
1053 return (ISC_R_NOTIMPLEMENTED);
1055 if ((options & DNS_DB_NSEC3ONLY) != 0 ||
1056 (options & DNS_DB_NONSEC3) != 0)
1057 return (ISC_R_NOTIMPLEMENTED);
1059 sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t));
1060 if (sdbiter == NULL)
1061 return (ISC_R_NOMEMORY);
1063 sdbiter->common.methods = &dbiterator_methods;
1064 sdbiter->common.db = NULL;
1065 dns_db_attach(db, &sdbiter->common.db);
1066 sdbiter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
1067 sdbiter->common.magic = DNS_DBITERATOR_MAGIC;
1068 ISC_LIST_INIT(sdbiter->nodelist);
1069 sdbiter->current = NULL;
1070 sdbiter->origin = NULL;
1072 MAYBE_LOCK(sdb);
1073 result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter);
1074 MAYBE_UNLOCK(sdb);
1075 if (result != ISC_R_SUCCESS) {
1076 dbiterator_destroy((dns_dbiterator_t **) (void *)&sdbiter);
1077 return (result);
1080 if (sdbiter->origin != NULL) {
1081 ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link);
1082 ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link);
1085 *iteratorp = (dns_dbiterator_t *)sdbiter;
1087 return (ISC_R_SUCCESS);
1090 static isc_result_t
1091 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1092 dns_rdatatype_t type, dns_rdatatype_t covers,
1093 isc_stdtime_t now, dns_rdataset_t *rdataset,
1094 dns_rdataset_t *sigrdataset)
1096 dns_rdatalist_t *list;
1097 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
1099 REQUIRE(VALID_SDBNODE(node));
1101 UNUSED(db);
1102 UNUSED(version);
1103 UNUSED(covers);
1104 UNUSED(now);
1105 UNUSED(sigrdataset);
1107 if (type == dns_rdatatype_rrsig)
1108 return (ISC_R_NOTIMPLEMENTED);
1110 list = ISC_LIST_HEAD(sdbnode->lists);
1111 while (list != NULL) {
1112 if (list->type == type)
1113 break;
1114 list = ISC_LIST_NEXT(list, link);
1116 if (list == NULL)
1117 return (ISC_R_NOTFOUND);
1119 list_tordataset(list, db, node, rdataset);
1121 return (ISC_R_SUCCESS);
1124 static isc_result_t
1125 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1126 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
1128 sdb_rdatasetiter_t *iterator;
1130 REQUIRE(version == NULL || version == &dummy);
1132 UNUSED(version);
1133 UNUSED(now);
1135 iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t));
1136 if (iterator == NULL)
1137 return (ISC_R_NOMEMORY);
1139 iterator->common.magic = DNS_RDATASETITER_MAGIC;
1140 iterator->common.methods = &rdatasetiter_methods;
1141 iterator->common.db = db;
1142 iterator->common.node = NULL;
1143 attachnode(db, node, &iterator->common.node);
1144 iterator->common.version = version;
1145 iterator->common.now = now;
1147 *iteratorp = (dns_rdatasetiter_t *)iterator;
1149 return (ISC_R_SUCCESS);
1152 static isc_result_t
1153 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1154 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
1155 dns_rdataset_t *addedrdataset)
1157 UNUSED(db);
1158 UNUSED(node);
1159 UNUSED(version);
1160 UNUSED(now);
1161 UNUSED(rdataset);
1162 UNUSED(options);
1163 UNUSED(addedrdataset);
1165 return (ISC_R_NOTIMPLEMENTED);
1168 static isc_result_t
1169 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1170 dns_rdataset_t *rdataset, unsigned int options,
1171 dns_rdataset_t *newrdataset)
1173 UNUSED(db);
1174 UNUSED(node);
1175 UNUSED(version);
1176 UNUSED(rdataset);
1177 UNUSED(options);
1178 UNUSED(newrdataset);
1180 return (ISC_R_NOTIMPLEMENTED);
1183 static isc_result_t
1184 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1185 dns_rdatatype_t type, dns_rdatatype_t covers)
1187 UNUSED(db);
1188 UNUSED(node);
1189 UNUSED(version);
1190 UNUSED(type);
1191 UNUSED(covers);
1193 return (ISC_R_NOTIMPLEMENTED);
1196 static isc_boolean_t
1197 issecure(dns_db_t *db) {
1198 UNUSED(db);
1200 return (ISC_FALSE);
1203 static unsigned int
1204 nodecount(dns_db_t *db) {
1205 UNUSED(db);
1207 return (0);
1210 static isc_boolean_t
1211 ispersistent(dns_db_t *db) {
1212 UNUSED(db);
1213 return (ISC_TRUE);
1216 static void
1217 overmem(dns_db_t *db, isc_boolean_t overmem) {
1218 UNUSED(db);
1219 UNUSED(overmem);
1222 static void
1223 settask(dns_db_t *db, isc_task_t *task) {
1224 UNUSED(db);
1225 UNUSED(task);
1229 static dns_dbmethods_t sdb_methods = {
1230 attach,
1231 detach,
1232 beginload,
1233 endload,
1234 dump,
1235 currentversion,
1236 newversion,
1237 attachversion,
1238 closeversion,
1239 findnode,
1240 find,
1241 findzonecut,
1242 attachnode,
1243 detachnode,
1244 expirenode,
1245 printnode,
1246 createiterator,
1247 findrdataset,
1248 allrdatasets,
1249 addrdataset,
1250 subtractrdataset,
1251 deleterdataset,
1252 issecure,
1253 nodecount,
1254 ispersistent,
1255 overmem,
1256 settask,
1257 NULL,
1258 NULL,
1259 NULL,
1260 NULL,
1261 NULL,
1262 NULL,
1263 NULL,
1264 NULL,
1265 NULL,
1268 static isc_result_t
1269 dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
1270 dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
1271 void *driverarg, dns_db_t **dbp)
1273 dns_sdb_t *sdb;
1274 isc_result_t result;
1275 char zonestr[DNS_NAME_MAXTEXT + 1];
1276 isc_buffer_t b;
1277 dns_sdbimplementation_t *imp;
1279 REQUIRE(driverarg != NULL);
1281 imp = driverarg;
1283 if (type != dns_dbtype_zone)
1284 return (ISC_R_NOTIMPLEMENTED);
1286 sdb = isc_mem_get(mctx, sizeof(dns_sdb_t));
1287 if (sdb == NULL)
1288 return (ISC_R_NOMEMORY);
1289 memset(sdb, 0, sizeof(dns_sdb_t));
1291 dns_name_init(&sdb->common.origin, NULL);
1292 sdb->common.attributes = 0;
1293 sdb->common.methods = &sdb_methods;
1294 sdb->common.rdclass = rdclass;
1295 sdb->common.mctx = NULL;
1296 sdb->implementation = imp;
1298 isc_mem_attach(mctx, &sdb->common.mctx);
1300 result = isc_mutex_init(&sdb->lock);
1301 if (result != ISC_R_SUCCESS)
1302 goto cleanup_mctx;
1304 result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
1305 if (result != ISC_R_SUCCESS)
1306 goto cleanup_lock;
1308 isc_buffer_init(&b, zonestr, sizeof(zonestr));
1309 result = dns_name_totext(origin, ISC_TRUE, &b);
1310 if (result != ISC_R_SUCCESS)
1311 goto cleanup_origin;
1312 isc_buffer_putuint8(&b, 0);
1314 sdb->zone = isc_mem_strdup(mctx, zonestr);
1315 if (sdb->zone == NULL) {
1316 result = ISC_R_NOMEMORY;
1317 goto cleanup_origin;
1320 sdb->dbdata = NULL;
1321 if (imp->methods->create != NULL) {
1322 MAYBE_LOCK(sdb);
1323 result = imp->methods->create(sdb->zone, argc, argv,
1324 imp->driverdata, &sdb->dbdata);
1325 MAYBE_UNLOCK(sdb);
1326 if (result != ISC_R_SUCCESS)
1327 goto cleanup_zonestr;
1330 sdb->references = 1;
1332 sdb->common.magic = DNS_DB_MAGIC;
1333 sdb->common.impmagic = SDB_MAGIC;
1335 *dbp = (dns_db_t *)sdb;
1337 return (ISC_R_SUCCESS);
1339 cleanup_zonestr:
1340 isc_mem_free(mctx, sdb->zone);
1341 cleanup_origin:
1342 dns_name_free(&sdb->common.origin, mctx);
1343 cleanup_lock:
1344 isc_mutex_destroy(&sdb->lock);
1345 cleanup_mctx:
1346 isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
1347 isc_mem_detach(&mctx);
1349 return (result);
1354 * Rdataset Methods
1357 static void
1358 disassociate(dns_rdataset_t *rdataset) {
1359 dns_dbnode_t *node = rdataset->private5;
1360 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
1361 dns_db_t *db = (dns_db_t *) sdbnode->sdb;
1363 detachnode(db, &node);
1364 isc__rdatalist_disassociate(rdataset);
1367 static void
1368 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1369 dns_dbnode_t *node = source->private5;
1370 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
1371 dns_db_t *db = (dns_db_t *) sdbnode->sdb;
1372 dns_dbnode_t *tempdb = NULL;
1374 isc__rdatalist_clone(source, target);
1375 attachnode(db, node, &tempdb);
1376 source->private5 = tempdb;
1379 static dns_rdatasetmethods_t methods = {
1380 disassociate,
1381 isc__rdatalist_first,
1382 isc__rdatalist_next,
1383 isc__rdatalist_current,
1384 rdataset_clone,
1385 isc__rdatalist_count,
1386 isc__rdatalist_addnoqname,
1387 isc__rdatalist_getnoqname,
1388 NULL,
1389 NULL,
1390 NULL,
1391 NULL,
1392 NULL
1395 static void
1396 list_tordataset(dns_rdatalist_t *rdatalist,
1397 dns_db_t *db, dns_dbnode_t *node,
1398 dns_rdataset_t *rdataset)
1401 * The sdb rdataset is an rdatalist with some additions.
1402 * - private1 & private2 are used by the rdatalist.
1403 * - private3 & private 4 are unused.
1404 * - private5 is the node.
1407 /* This should never fail. */
1408 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1409 ISC_R_SUCCESS);
1411 rdataset->methods = &methods;
1412 dns_db_attachnode(db, node, &rdataset->private5);
1416 * Database Iterator Methods
1418 static void
1419 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1420 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp);
1421 dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db;
1423 while (!ISC_LIST_EMPTY(sdbiter->nodelist)) {
1424 dns_sdbnode_t *node;
1425 node = ISC_LIST_HEAD(sdbiter->nodelist);
1426 ISC_LIST_UNLINK(sdbiter->nodelist, node, link);
1427 destroynode(node);
1430 dns_db_detach(&sdbiter->common.db);
1431 isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t));
1433 *iteratorp = NULL;
1436 static isc_result_t
1437 dbiterator_first(dns_dbiterator_t *iterator) {
1438 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1440 sdbiter->current = ISC_LIST_HEAD(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_last(dns_dbiterator_t *iterator) {
1449 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1451 sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist);
1452 if (sdbiter->current == NULL)
1453 return (ISC_R_NOMORE);
1454 else
1455 return (ISC_R_SUCCESS);
1458 static isc_result_t
1459 dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
1460 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1462 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1463 while (sdbiter->current != NULL) {
1464 if (dns_name_equal(sdbiter->current->name, name))
1465 return (ISC_R_SUCCESS);
1466 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
1468 return (ISC_R_NOTFOUND);
1471 static isc_result_t
1472 dbiterator_prev(dns_dbiterator_t *iterator) {
1473 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1475 sdbiter->current = ISC_LIST_PREV(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_next(dns_dbiterator_t *iterator) {
1484 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1486 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
1487 if (sdbiter->current == NULL)
1488 return (ISC_R_NOMORE);
1489 else
1490 return (ISC_R_SUCCESS);
1493 static isc_result_t
1494 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1495 dns_name_t *name)
1497 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1499 attachnode(iterator->db, sdbiter->current, nodep);
1500 if (name != NULL)
1501 return (dns_name_copy(sdbiter->current->name, name, NULL));
1502 return (ISC_R_SUCCESS);
1505 static isc_result_t
1506 dbiterator_pause(dns_dbiterator_t *iterator) {
1507 UNUSED(iterator);
1508 return (ISC_R_SUCCESS);
1511 static isc_result_t
1512 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1513 UNUSED(iterator);
1514 return (dns_name_copy(dns_rootname, name, NULL));
1518 * Rdataset Iterator Methods
1521 static void
1522 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
1523 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp);
1524 detachnode(sdbiterator->common.db, &sdbiterator->common.node);
1525 isc_mem_put(sdbiterator->common.db->mctx, sdbiterator,
1526 sizeof(sdb_rdatasetiter_t));
1527 *iteratorp = NULL;
1530 static isc_result_t
1531 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
1532 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1533 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node;
1535 if (ISC_LIST_EMPTY(sdbnode->lists))
1536 return (ISC_R_NOMORE);
1537 sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists);
1538 return (ISC_R_SUCCESS);
1541 static isc_result_t
1542 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
1543 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1545 sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link);
1546 if (sdbiterator->current == NULL)
1547 return (ISC_R_NOMORE);
1548 else
1549 return (ISC_R_SUCCESS);
1552 static void
1553 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
1554 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1556 list_tordataset(sdbiterator->current, iterator->db, iterator->node,
1557 rdataset);