]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
move the dns_sdb API
authorEvan Hunt <each@isc.org>
Thu, 9 Feb 2023 06:22:40 +0000 (22:22 -0800)
committerEvan Hunt <each@isc.org>
Tue, 21 Feb 2023 18:13:10 +0000 (10:13 -0800)
move all dns_sdb code into bin/named/builtin.c, which is the
only place from which it's called.

(note this is temporary: later we'll refactor builtin so that it's a
standalone dns_db implementation on its own instead of using SDB
as a wrapper.)

bin/named/builtin.c
bin/named/include/named/builtin.h
lib/dns/Makefile.am
lib/dns/include/dns/sdb.h [deleted file]
lib/dns/include/dns/types.h
lib/dns/sdb.c [deleted file]

index 989f077a5a21c5b00f3c059805d8b53356085c63..0216ba5fe59fbc0f1ceb456c0c1cfbc89f9da3ab 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
+#include <isc/lex.h>
 #include <isc/mem.h>
 #include <isc/result.h>
 #include <isc/util.h>
 
-#include <dns/sdb.h>
+#include <dns/callbacks.h>
+#include <dns/dbiterator.h>
+#include <dns/rdatalist.h>
+#include <dns/rdatasetiter.h>
+#include <dns/types.h>
 
 #include <named/builtin.h>
 #include <named/globals.h>
 typedef struct builtin builtin_t;
 
 static isc_result_t
-do_authors_lookup(dns_sdblookup_t *lookup);
+do_authors_lookup(sdblookup_t *lookup);
 static isc_result_t
-do_dns64_lookup(dns_sdblookup_t *lookup);
+do_dns64_lookup(sdblookup_t *lookup);
 static isc_result_t
-do_empty_lookup(dns_sdblookup_t *lookup);
+do_empty_lookup(sdblookup_t *lookup);
 static isc_result_t
-do_hostname_lookup(dns_sdblookup_t *lookup);
+do_hostname_lookup(sdblookup_t *lookup);
 static isc_result_t
-do_id_lookup(dns_sdblookup_t *lookup);
+do_id_lookup(sdblookup_t *lookup);
 static isc_result_t
-do_ipv4only_lookup(dns_sdblookup_t *lookup);
+do_ipv4only_lookup(sdblookup_t *lookup);
 static isc_result_t
-do_ipv4reverse_lookup(dns_sdblookup_t *lookup);
+do_ipv4reverse_lookup(sdblookup_t *lookup);
 static isc_result_t
-do_version_lookup(dns_sdblookup_t *lookup);
+do_version_lookup(sdblookup_t *lookup);
 
 /*
  * We can't use function pointers as the db_data directly
@@ -56,7 +61,7 @@ do_version_lookup(dns_sdblookup_t *lookup);
  */
 
 struct builtin {
-       isc_result_t (*do_lookup)(dns_sdblookup_t *lookup);
+       isc_result_t (*do_lookup)(sdblookup_t *lookup);
        char *server;
        char *contact;
 };
@@ -70,8 +75,8 @@ static builtin_t ipv4only_builtin = { do_ipv4only_lookup, NULL, NULL };
 static builtin_t ipv4reverse_builtin = { do_ipv4reverse_lookup, NULL, NULL };
 static builtin_t version_builtin = { do_version_lookup, NULL, NULL };
 
-static dns_sdbimplementation_t *builtin_impl;
-static dns_sdbimplementation_t *dns64_impl;
+static sdbimplementation_t *builtin_impl;
+static sdbimplementation_t *dns64_impl;
 
 /*
  * Pre computed HEX * 16 or 1 table.
@@ -130,7 +135,7 @@ dns64_rdata(unsigned char *v, size_t start, unsigned char *rdata) {
 
 static isc_result_t
 dns64_cname(const dns_name_t *zone, const dns_name_t *name,
-           dns_sdblookup_t *lookup) {
+           sdblookup_t *lookup) {
        size_t zlen, nlen, j, len;
        unsigned char v[16], n;
        unsigned int i;
@@ -303,17 +308,17 @@ dns64_cname(const dns_name_t *zone, const dns_name_t *name,
        if ((v[0] == 170 || v[0] == 171) && v[1] == 0 && v[2] == 0 &&
            v[3] == 192)
        {
-               return (dns_sdb_putrdata(lookup, dns_rdatatype_ptr, 3600,
-                                        ipv4only, sizeof(ipv4only)));
+               return (sdb_putrdata(lookup, dns_rdatatype_ptr, 3600, ipv4only,
+                                    sizeof(ipv4only)));
        }
 
-       return (dns_sdb_putrdata(lookup, dns_rdatatype_cname, 600, rdata,
-                                (unsigned int)len));
+       return (sdb_putrdata(lookup, dns_rdatatype_cname, 600, rdata,
+                            (unsigned int)len));
 }
 
 static isc_result_t
 builtin_lookup(const dns_name_t *zone, const dns_name_t *name, void *dbdata,
-              dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
+              sdblookup_t *lookup, dns_clientinfomethods_t *methods,
               dns_clientinfo_t *clientinfo) {
        builtin_t *b = (builtin_t *)dbdata;
 
@@ -330,7 +335,7 @@ builtin_lookup(const dns_name_t *zone, const dns_name_t *name, void *dbdata,
 
 static isc_result_t
 dns64_lookup(const dns_name_t *zone, const dns_name_t *name, void *dbdata,
-            dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
+            sdblookup_t *lookup, dns_clientinfomethods_t *methods,
             dns_clientinfo_t *clientinfo) {
        builtin_t *b = (builtin_t *)dbdata;
 
@@ -345,7 +350,7 @@ dns64_lookup(const dns_name_t *zone, const dns_name_t *name, void *dbdata,
 }
 
 static isc_result_t
-put_txt(dns_sdblookup_t *lookup, const char *text) {
+put_txt(sdblookup_t *lookup, const char *text) {
        unsigned char buf[256];
        unsigned int len = strlen(text);
        if (len > 255) {
@@ -353,11 +358,11 @@ put_txt(dns_sdblookup_t *lookup, const char *text) {
        }
        buf[0] = len;
        memmove(&buf[1], text, len);
-       return (dns_sdb_putrdata(lookup, dns_rdatatype_txt, 0, buf, len + 1));
+       return (sdb_putrdata(lookup, dns_rdatatype_txt, 0, buf, len + 1));
 }
 
 static isc_result_t
-do_version_lookup(dns_sdblookup_t *lookup) {
+do_version_lookup(sdblookup_t *lookup) {
        if (named_g_server->version_set) {
                if (named_g_server->version == NULL) {
                        return (ISC_R_SUCCESS);
@@ -370,7 +375,7 @@ do_version_lookup(dns_sdblookup_t *lookup) {
 }
 
 static isc_result_t
-do_hostname_lookup(dns_sdblookup_t *lookup) {
+do_hostname_lookup(sdblookup_t *lookup) {
        if (named_g_server->hostname_set) {
                if (named_g_server->hostname == NULL) {
                        return (ISC_R_SUCCESS);
@@ -387,7 +392,7 @@ do_hostname_lookup(dns_sdblookup_t *lookup) {
 }
 
 static isc_result_t
-do_authors_lookup(dns_sdblookup_t *lookup) {
+do_authors_lookup(sdblookup_t *lookup) {
        isc_result_t result;
        const char **p;
        static const char *authors[] = {
@@ -417,7 +422,7 @@ do_authors_lookup(dns_sdblookup_t *lookup) {
 }
 
 static isc_result_t
-do_id_lookup(dns_sdblookup_t *lookup) {
+do_id_lookup(sdblookup_t *lookup) {
        if (named_g_server->sctx->usehostname) {
                char buf[256];
                if (gethostname(buf, sizeof(buf)) != 0) {
@@ -432,25 +437,25 @@ do_id_lookup(dns_sdblookup_t *lookup) {
 }
 
 static isc_result_t
-do_dns64_lookup(dns_sdblookup_t *lookup) {
+do_dns64_lookup(sdblookup_t *lookup) {
        UNUSED(lookup);
        return (ISC_R_SUCCESS);
 }
 
 static isc_result_t
-do_empty_lookup(dns_sdblookup_t *lookup) {
+do_empty_lookup(sdblookup_t *lookup) {
        UNUSED(lookup);
        return (ISC_R_SUCCESS);
 }
 
 static isc_result_t
-do_ipv4only_lookup(dns_sdblookup_t *lookup) {
+do_ipv4only_lookup(sdblookup_t *lookup) {
        isc_result_t result;
        unsigned char data[2][4] = { { 192, 0, 0, 170 }, { 192, 0, 0, 171 } };
 
        for (int i = 0; i < 2; i++) {
-               result = dns_sdb_putrdata(lookup, dns_rdatatype_a, 3600,
-                                         data[i], 4);
+               result = sdb_putrdata(lookup, dns_rdatatype_a, 3600, data[i],
+                                     4);
                if (result != ISC_R_SUCCESS) {
                        return (result);
                }
@@ -459,16 +464,16 @@ do_ipv4only_lookup(dns_sdblookup_t *lookup) {
 }
 
 static isc_result_t
-do_ipv4reverse_lookup(dns_sdblookup_t *lookup) {
+do_ipv4reverse_lookup(sdblookup_t *lookup) {
        isc_result_t result;
 
-       result = dns_sdb_putrdata(lookup, dns_rdatatype_ptr, 3600, ipv4only,
-                                 sizeof(ipv4only));
+       result = sdb_putrdata(lookup, dns_rdatatype_ptr, 3600, ipv4only,
+                             sizeof(ipv4only));
        return (result);
 }
 
 static isc_result_t
-builtin_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
+builtin_authority(const char *zone, void *dbdata, sdblookup_t *lookup) {
        isc_result_t result;
        const char *contact = "hostmaster";
        const char *server = "@";
@@ -489,12 +494,12 @@ builtin_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
                }
        }
 
-       result = dns_sdb_putsoa(lookup, server, contact, 0);
+       result = sdb_putsoa(lookup, server, contact, 0);
        if (result != ISC_R_SUCCESS) {
                return (ISC_R_FAILURE);
        }
 
-       result = dns_sdb_putrr(lookup, "ns", 0, server);
+       result = sdb_putrr(lookup, "ns", 0, server);
        if (result != ISC_R_SUCCESS) {
                return (ISC_R_FAILURE);
        }
@@ -616,14 +621,14 @@ builtin_destroy(const char *zone, void *driverdata, void **dbdata) {
        isc_mem_put(named_g_mctx, b, sizeof(*b));
 }
 
-static dns_sdbmethods_t builtin_methods = {
+static sdbmethods_t builtin_methods = {
        .lookup = builtin_lookup,
        .authority = builtin_authority,
        .create = builtin_create,
        .destroy = builtin_destroy,
 };
 
-static dns_sdbmethods_t dns64_methods = {
+static sdbmethods_t dns64_methods = {
        .lookup = dns64_lookup,
        .authority = builtin_authority,
        .create = builtin_create,
@@ -632,17 +637,1013 @@ static dns_sdbmethods_t dns64_methods = {
 
 isc_result_t
 named_builtin_init(void) {
-       RUNTIME_CHECK(dns_sdb_register("_builtin", &builtin_methods, NULL, 0,
-                                      named_g_mctx,
-                                      &builtin_impl) == ISC_R_SUCCESS);
-       RUNTIME_CHECK(dns_sdb_register("_dns64", &dns64_methods, NULL,
-                                      DNS_SDBFLAG_DNS64, named_g_mctx,
-                                      &dns64_impl) == ISC_R_SUCCESS);
+       RUNTIME_CHECK(sdb_register("_builtin", &builtin_methods, NULL, 0,
+                                  named_g_mctx,
+                                  &builtin_impl) == ISC_R_SUCCESS);
+       RUNTIME_CHECK(sdb_register("_dns64", &dns64_methods, NULL,
+                                  DNS_SDBFLAG_DNS64, named_g_mctx,
+                                  &dns64_impl) == ISC_R_SUCCESS);
        return (ISC_R_SUCCESS);
 }
 
 void
 named_builtin_deinit(void) {
-       dns_sdb_unregister(&builtin_impl);
-       dns_sdb_unregister(&dns64_impl);
+       sdb_unregister(&builtin_impl);
+       sdb_unregister(&dns64_impl);
+}
+
+/*
+ * Simple database implementation:
+ * XXX this is only in builtin.c temporarily; everything from
+ * here down will be moved to its own file later.
+ */
+struct sdbimplementation {
+       const sdbmethods_t *methods;
+       void *driverdata;
+       unsigned int flags;
+       isc_mem_t *mctx;
+       isc_mutex_t driverlock;
+       dns_dbimplementation_t *dbimp;
+};
+
+struct sdb {
+       /* Unlocked */
+       dns_db_t common;
+       char *zone;
+       sdbimplementation_t *implementation;
+       void *dbdata;
+};
+
+struct sdblookup {
+       /* Unlocked */
+       unsigned int magic;
+       sdb_t *sdb;
+       ISC_LIST(dns_rdatalist_t) lists;
+       ISC_LIST(isc_buffer_t) buffers;
+       dns_name_t *name;
+       ISC_LINK(sdblookup_t) link;
+       dns_rdatacallbacks_t callbacks;
+
+       /* Atomic */
+       isc_refcount_t references;
+};
+
+typedef struct sdblookup sdbnode_t;
+
+typedef struct sdb_rdatasetiter {
+       dns_rdatasetiter_t common;
+       dns_rdatalist_t *current;
+} sdb_rdatasetiter_t;
+
+#define SDB_MAGIC ISC_MAGIC('S', 'D', 'B', '-')
+
+/*%
+ * Note that "impmagic" is not the first four bytes of the struct, so
+ * ISC_MAGIC_VALID cannot be used.
+ */
+#define VALID_SDB(sdb) ((sdb) != NULL && (sdb)->common.impmagic == SDB_MAGIC)
+
+#define SDBLOOKUP_MAGIC              ISC_MAGIC('S', 'D', 'B', 'L')
+#define VALID_SDBLOOKUP(sdbl) ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)
+#define VALID_SDBNODE(sdbn)   VALID_SDBLOOKUP(sdbn)
+
+/* These values are taken from RFC1537 */
+#define SDB_DEFAULT_REFRESH 28800U  /* 8 hours */
+#define SDB_DEFAULT_RETRY   7200U   /* 2 hours */
+#define SDB_DEFAULT_EXPIRE  604800U /* 7 days */
+#define SDB_DEFAULT_MINIMUM 86400U  /* 1 day */
+
+/* This is a reasonable value */
+#define SDB_DEFAULT_TTL (60 * 60 * 24)
+
+static int dummy;
+
+static isc_result_t
+create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
+       dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
+       void *driverarg, dns_db_t **dbp);
+
+static isc_result_t
+findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+            dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
+            dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
+
+static isc_result_t
+createnode(sdb_t *sdb, sdbnode_t **nodep);
+
+static void
+destroynode(sdbnode_t *node);
+
+static void
+detachnode(dns_db_t *db, dns_dbnode_t **targetp);
+
+static void
+list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
+               dns_rdataset_t *rdataset);
+
+static void
+rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
+static isc_result_t
+rdatasetiter_first(dns_rdatasetiter_t *iterator);
+static isc_result_t
+rdatasetiter_next(dns_rdatasetiter_t *iterator);
+static void
+rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset);
+
+static dns_rdatasetitermethods_t rdatasetiter_methods = {
+       rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next,
+       rdatasetiter_current
+};
+
+/*
+ * Functions used by implementors of simple databases
+ */
+isc_result_t
+sdb_register(const char *drivername, const sdbmethods_t *methods,
+            void *driverdata, unsigned int flags, isc_mem_t *mctx,
+            sdbimplementation_t **sdbimp) {
+       sdbimplementation_t *imp = NULL;
+       isc_result_t result;
+
+       REQUIRE(drivername != NULL);
+       REQUIRE(methods != NULL);
+       REQUIRE(methods->lookup != NULL);
+       REQUIRE(mctx != NULL);
+       REQUIRE(sdbimp != NULL && *sdbimp == NULL);
+       REQUIRE((flags & ~DNS_SDBFLAG_DNS64) == 0);
+
+       imp = isc_mem_get(mctx, sizeof(sdbimplementation_t));
+       imp->methods = methods;
+       imp->driverdata = driverdata;
+       imp->flags = flags;
+       imp->mctx = NULL;
+       isc_mem_attach(mctx, &imp->mctx);
+       isc_mutex_init(&imp->driverlock);
+
+       imp->dbimp = NULL;
+       result = dns_db_register(drivername, create, imp, mctx, &imp->dbimp);
+       if (result != ISC_R_SUCCESS) {
+               goto cleanup_mutex;
+       }
+       *sdbimp = imp;
+
+       return (ISC_R_SUCCESS);
+
+cleanup_mutex:
+       isc_mutex_destroy(&imp->driverlock);
+       isc_mem_put(mctx, imp, sizeof(sdbimplementation_t));
+       return (result);
+}
+
+void
+sdb_unregister(sdbimplementation_t **sdbimp) {
+       sdbimplementation_t *imp = NULL;
+
+       REQUIRE(sdbimp != NULL && *sdbimp != NULL);
+
+       imp = *sdbimp;
+       *sdbimp = NULL;
+       dns_db_unregister(&imp->dbimp);
+       isc_mutex_destroy(&imp->driverlock);
+
+       isc_mem_putanddetach(&imp->mctx, imp, sizeof(sdbimplementation_t));
+}
+
+static unsigned int
+initial_size(unsigned int len) {
+       unsigned int size;
+
+       for (size = 1024; size < (64 * 1024); size *= 2) {
+               if (len < size) {
+                       return (size);
+               }
+       }
+       return (65535);
+}
+
+isc_result_t
+sdb_putrdata(sdblookup_t *lookup, dns_rdatatype_t typeval, dns_ttl_t ttl,
+            const unsigned char *rdatap, unsigned int rdlen) {
+       dns_rdatalist_t *rdatalist = NULL;
+       dns_rdata_t *rdata = NULL;
+       isc_buffer_t *rdatabuf = NULL;
+       isc_mem_t *mctx = NULL;
+       isc_region_t region;
+
+       mctx = lookup->sdb->common.mctx;
+
+       rdatalist = ISC_LIST_HEAD(lookup->lists);
+       while (rdatalist != NULL) {
+               if (rdatalist->type == typeval) {
+                       break;
+               }
+               rdatalist = ISC_LIST_NEXT(rdatalist, link);
+       }
+
+       if (rdatalist == NULL) {
+               rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
+               dns_rdatalist_init(rdatalist);
+               rdatalist->rdclass = lookup->sdb->common.rdclass;
+               rdatalist->type = typeval;
+               rdatalist->ttl = ttl;
+               ISC_LIST_APPEND(lookup->lists, rdatalist, link);
+       } else if (rdatalist->ttl != ttl) {
+               return (DNS_R_BADTTL);
+       }
+
+       rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
+
+       isc_buffer_allocate(mctx, &rdatabuf, rdlen);
+       DE_CONST(rdatap, region.base);
+       region.length = rdlen;
+       isc_buffer_copyregion(rdatabuf, &region);
+       isc_buffer_usedregion(rdatabuf, &region);
+       dns_rdata_init(rdata);
+       dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type,
+                            &region);
+       ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+       ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
+
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+sdb_putrr(sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
+         const char *data) {
+       unsigned int datalen;
+       dns_rdatatype_t typeval;
+       isc_textregion_t r;
+       isc_lex_t *lex = NULL;
+       isc_result_t result;
+       unsigned char *p = NULL;
+       unsigned int size = 0; /* Init to suppress compiler warning */
+       isc_mem_t *mctx = NULL;
+       const dns_name_t *origin = NULL;
+       isc_buffer_t b;
+       isc_buffer_t rb;
+
+       REQUIRE(VALID_SDBLOOKUP(lookup));
+       REQUIRE(type != NULL);
+       REQUIRE(data != NULL);
+
+       mctx = lookup->sdb->common.mctx;
+
+       DE_CONST(type, r.base);
+       r.length = strlen(type);
+       result = dns_rdatatype_fromtext(&typeval, &r);
+       if (result != ISC_R_SUCCESS) {
+               return (result);
+       }
+
+       origin = &lookup->sdb->common.origin;
+
+       isc_lex_create(mctx, 64, &lex);
+
+       datalen = strlen(data);
+       size = initial_size(datalen);
+       do {
+               isc_buffer_constinit(&b, data, datalen);
+               isc_buffer_add(&b, datalen);
+               result = isc_lex_openbuffer(lex, &b);
+               if (result != ISC_R_SUCCESS) {
+                       goto failure;
+               }
+
+               if (size >= 65535) {
+                       size = 65535;
+               }
+               p = isc_mem_get(mctx, size);
+               isc_buffer_init(&rb, p, size);
+               result = dns_rdata_fromtext(NULL, lookup->sdb->common.rdclass,
+                                           typeval, lex, origin, 0, mctx, &rb,
+                                           &lookup->callbacks);
+               if (result != ISC_R_NOSPACE) {
+                       break;
+               }
+
+               /*
+                * Is the RR too big?
+                */
+               if (size >= 65535) {
+                       break;
+               }
+               isc_mem_put(mctx, p, size);
+               p = NULL;
+               size *= 2;
+       } while (result == ISC_R_NOSPACE);
+
+       if (result != ISC_R_SUCCESS) {
+               goto failure;
+       }
+
+       result = sdb_putrdata(lookup, typeval, ttl, isc_buffer_base(&rb),
+                             isc_buffer_usedlength(&rb));
+failure:
+       if (p != NULL) {
+               isc_mem_put(mctx, p, size);
+       }
+       if (lex != NULL) {
+               isc_lex_destroy(&lex);
+       }
+
+       return (result);
+}
+
+isc_result_t
+sdb_putsoa(sdblookup_t *lookup, const char *mname, const char *rname,
+          uint32_t serial) {
+       char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
+       int n;
+
+       REQUIRE(mname != NULL);
+       REQUIRE(rname != NULL);
+
+       n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u", mname, rname,
+                    serial, SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY,
+                    SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM);
+       if (n >= (int)sizeof(str) || n < 0) {
+               return (ISC_R_NOSPACE);
+       }
+       return (sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));
+}
+
+/*
+ * DB routines
+ */
+
+static void
+destroy(dns_db_t *db) {
+       sdb_t *sdb = (sdb_t *)db;
+       sdbimplementation_t *imp = sdb->implementation;
+
+       isc_refcount_destroy(&sdb->common.references);
+
+       if (imp != NULL && imp->methods->destroy != NULL) {
+               LOCK(&sdb->implementation->driverlock);
+               imp->methods->destroy(sdb->zone, imp->driverdata, &sdb->dbdata);
+               UNLOCK(&sdb->implementation->driverlock);
+       }
+
+       isc_mem_free(sdb->common.mctx, sdb->zone);
+
+       sdb->common.magic = 0;
+       sdb->common.impmagic = 0;
+
+       dns_name_free(&sdb->common.origin, sdb->common.mctx);
+
+       isc_mem_putanddetach(&sdb->common.mctx, sdb, sizeof(sdb_t));
+}
+
+static void
+currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
+       REQUIRE(versionp != NULL && *versionp == NULL);
+
+       UNUSED(db);
+
+       *versionp = (void *)&dummy;
+       return;
+}
+
+static void
+attachversion(dns_db_t *db, dns_dbversion_t *source,
+             dns_dbversion_t **targetp) {
+       REQUIRE(source != NULL && source == (void *)&dummy);
+       REQUIRE(targetp != NULL && *targetp == NULL);
+
+       UNUSED(db);
+       *targetp = source;
+       return;
+}
+
+static void
+closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
+       REQUIRE(versionp != NULL && *versionp == (void *)&dummy);
+       REQUIRE(!commit);
+
+       UNUSED(db);
+       UNUSED(commit);
+
+       *versionp = NULL;
+}
+
+static isc_result_t
+createnode(sdb_t *sdb, sdbnode_t **nodep) {
+       sdbnode_t *node = NULL;
+
+       node = isc_mem_get(sdb->common.mctx, sizeof(sdbnode_t));
+
+       node->sdb = NULL;
+       dns_db_attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb);
+       ISC_LIST_INIT(node->lists);
+       ISC_LIST_INIT(node->buffers);
+       ISC_LINK_INIT(node, link);
+       node->name = NULL;
+       dns_rdatacallbacks_init(&node->callbacks);
+
+       isc_refcount_init(&node->references, 1);
+
+       node->magic = SDBLOOKUP_MAGIC;
+
+       *nodep = node;
+       return (ISC_R_SUCCESS);
+}
+
+static void
+destroynode(sdbnode_t *node) {
+       dns_rdatalist_t *list = NULL;
+       dns_rdata_t *rdata = NULL;
+       isc_buffer_t *b = NULL;
+       sdb_t *sdb = NULL;
+       isc_mem_t *mctx = NULL;
+
+       sdb = node->sdb;
+       mctx = sdb->common.mctx;
+
+       while (!ISC_LIST_EMPTY(node->lists)) {
+               list = ISC_LIST_HEAD(node->lists);
+               while (!ISC_LIST_EMPTY(list->rdata)) {
+                       rdata = ISC_LIST_HEAD(list->rdata);
+                       ISC_LIST_UNLINK(list->rdata, rdata, link);
+                       isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
+               }
+               ISC_LIST_UNLINK(node->lists, list, link);
+               isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
+       }
+
+       while (!ISC_LIST_EMPTY(node->buffers)) {
+               b = ISC_LIST_HEAD(node->buffers);
+               ISC_LIST_UNLINK(node->buffers, b, link);
+               isc_buffer_free(&b);
+       }
+
+       if (node->name != NULL) {
+               dns_name_free(node->name, mctx);
+               isc_mem_put(mctx, node->name, sizeof(dns_name_t));
+       }
+
+       node->magic = 0;
+       isc_mem_put(mctx, node, sizeof(sdbnode_t));
+       dns_db_detach((dns_db_t **)(void *)&sdb);
+}
+
+static isc_result_t
+getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
+       sdb_t *sdb = (sdb_t *)db;
+       sdbnode_t *node = NULL;
+       isc_result_t result;
+       sdbimplementation_t *imp = NULL;
+       dns_name_t relname;
+       dns_name_t *name = NULL;
+
+       REQUIRE(VALID_SDB(sdb));
+       REQUIRE(nodep != NULL && *nodep == NULL);
+
+       imp = sdb->implementation;
+       dns_name_init(&relname, NULL);
+       name = &relname;
+
+       result = createnode(sdb, &node);
+       if (result != ISC_R_SUCCESS) {
+               return (result);
+       }
+
+       LOCK(&sdb->implementation->driverlock);
+       result = imp->methods->lookup(&sdb->common.origin, name, sdb->dbdata,
+                                     node, NULL, NULL);
+       UNLOCK(&sdb->implementation->driverlock);
+       if (result != ISC_R_SUCCESS &&
+           !(result == ISC_R_NOTFOUND && imp->methods->authority != NULL))
+       {
+               destroynode(node);
+               return (result);
+       }
+
+       if (imp->methods->authority != NULL) {
+               LOCK(&sdb->implementation->driverlock);
+               result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
+               UNLOCK(&sdb->implementation->driverlock);
+               if (result != ISC_R_SUCCESS) {
+                       destroynode(node);
+                       return (result);
+               }
+       }
+
+       *nodep = node;
+       return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
+           dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
+           dns_dbnode_t **nodep) {
+       sdb_t *sdb = (sdb_t *)db;
+       sdbnode_t *node = NULL;
+       isc_result_t result;
+       bool isorigin;
+       sdbimplementation_t *imp = NULL;
+       dns_name_t relname;
+       unsigned int labels;
+
+       REQUIRE(VALID_SDB(sdb));
+       REQUIRE(nodep != NULL && *nodep == NULL);
+
+       UNUSED(name);
+       UNUSED(create);
+
+       imp = sdb->implementation;
+
+       isorigin = dns_name_equal(name, &sdb->common.origin);
+
+       labels = dns_name_countlabels(name) - dns_name_countlabels(&db->origin);
+       dns_name_init(&relname, NULL);
+       dns_name_getlabelsequence(name, 0, labels, &relname);
+       name = &relname;
+
+       result = createnode(sdb, &node);
+       if (result != ISC_R_SUCCESS) {
+               return (result);
+       }
+
+       LOCK(&sdb->implementation->driverlock);
+       result = imp->methods->lookup(&sdb->common.origin, name, sdb->dbdata,
+                                     node, methods, clientinfo);
+       UNLOCK(&sdb->implementation->driverlock);
+       if (result != ISC_R_SUCCESS && !(result == ISC_R_NOTFOUND && isorigin &&
+                                        imp->methods->authority != NULL))
+       {
+               destroynode(node);
+               return (result);
+       }
+
+       if (isorigin && imp->methods->authority != NULL) {
+               LOCK(&sdb->implementation->driverlock);
+               result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
+               UNLOCK(&sdb->implementation->driverlock);
+               if (result != ISC_R_SUCCESS) {
+                       destroynode(node);
+                       return (result);
+               }
+       }
+
+       *nodep = node;
+       return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
+       dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
+       dns_dbnode_t **nodep, dns_name_t *foundname,
+       dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
+       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
+       sdb_t *sdb = (sdb_t *)db;
+       dns_dbnode_t *node = NULL;
+       dns_fixedname_t fname;
+       dns_rdataset_t xrdataset;
+       dns_name_t *xname = NULL;
+       unsigned int nlabels, olabels;
+       isc_result_t result;
+       unsigned int i;
+       unsigned int flags;
+
+       REQUIRE(VALID_SDB(sdb));
+       REQUIRE(nodep == NULL || *nodep == NULL);
+       REQUIRE(version == NULL || version == (void *)&dummy);
+
+       UNUSED(options);
+
+       if (!dns_name_issubdomain(name, &db->origin)) {
+               return (DNS_R_NXDOMAIN);
+       }
+
+       olabels = dns_name_countlabels(&db->origin);
+       nlabels = dns_name_countlabels(name);
+
+       xname = dns_fixedname_initname(&fname);
+
+       if (rdataset == NULL) {
+               dns_rdataset_init(&xrdataset);
+               rdataset = &xrdataset;
+       }
+
+       result = DNS_R_NXDOMAIN;
+       flags = sdb->implementation->flags;
+       i = (flags & DNS_SDBFLAG_DNS64) != 0 ? nlabels : olabels;
+       for (; i <= nlabels; i++) {
+               /*
+                * Look up the next label.
+                */
+               dns_name_getlabelsequence(name, nlabels - i, i, xname);
+               result = findnodeext(db, xname, false, methods, clientinfo,
+                                    &node);
+               if (result == ISC_R_NOTFOUND) {
+                       /*
+                        * No data at zone apex?
+                        */
+                       if (i == olabels) {
+                               return (DNS_R_BADDB);
+                       }
+                       result = DNS_R_NXDOMAIN;
+                       continue;
+               }
+               if (result != ISC_R_SUCCESS) {
+                       return (result);
+               }
+
+               /*
+                * DNS64 zone's don't have DNAME or NS records.
+                */
+               if ((flags & DNS_SDBFLAG_DNS64) != 0) {
+                       goto skip;
+               }
+
+               /*
+                * DNS64 zone's don't have DNAME or NS records.
+                */
+               if ((flags & DNS_SDBFLAG_DNS64) != 0) {
+                       goto skip;
+               }
+
+               /*
+                * Look for a DNAME at the current label, unless this is
+                * the qname.
+                */
+               if (i < nlabels) {
+                       result = findrdataset(db, node, version,
+                                             dns_rdatatype_dname, 0, now,
+                                             rdataset, sigrdataset);
+                       if (result == ISC_R_SUCCESS) {
+                               result = DNS_R_DNAME;
+                               break;
+                       }
+               }
+
+               /*
+                * Look for an NS at the current label, unless this is the
+                * origin or glue is ok.
+                */
+               if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
+                       result = findrdataset(db, node, version,
+                                             dns_rdatatype_ns, 0, now,
+                                             rdataset, sigrdataset);
+                       if (result == ISC_R_SUCCESS) {
+                               if (i == nlabels && type == dns_rdatatype_any) {
+                                       result = DNS_R_ZONECUT;
+                                       dns_rdataset_disassociate(rdataset);
+                                       if (sigrdataset != NULL &&
+                                           dns_rdataset_isassociated(
+                                                   sigrdataset))
+                                       {
+                                               dns_rdataset_disassociate(
+                                                       sigrdataset);
+                                       }
+                               } else {
+                                       result = DNS_R_DELEGATION;
+                               }
+                               break;
+                       }
+               }
+
+               /*
+                * If the current name is not the qname, add another label
+                * and try again.
+                */
+               if (i < nlabels) {
+                       destroynode(node);
+                       node = NULL;
+                       continue;
+               }
+
+       skip:
+               /*
+                * If we're looking for ANY, we're done.
+                */
+               if (type == dns_rdatatype_any) {
+                       result = ISC_R_SUCCESS;
+                       break;
+               }
+
+               /*
+                * Look for the qtype.
+                */
+               result = findrdataset(db, node, version, type, 0, now, rdataset,
+                                     sigrdataset);
+               if (result == ISC_R_SUCCESS) {
+                       break;
+               }
+
+               /*
+                * Look for a CNAME
+                */
+               if (type != dns_rdatatype_cname) {
+                       result = findrdataset(db, node, version,
+                                             dns_rdatatype_cname, 0, now,
+                                             rdataset, sigrdataset);
+                       if (result == ISC_R_SUCCESS) {
+                               result = DNS_R_CNAME;
+                               break;
+                       }
+               }
+
+               result = DNS_R_NXRRSET;
+               break;
+       }
+
+       if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) {
+               dns_rdataset_disassociate(rdataset);
+       }
+
+       if (foundname != NULL) {
+               dns_name_copy(xname, foundname);
+       }
+
+       if (nodep != NULL) {
+               *nodep = node;
+       } else if (node != NULL) {
+               detachnode(db, &node);
+       }
+
+       return (result);
+}
+
+static void
+attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
+       sdb_t *sdb = (sdb_t *)db;
+       sdbnode_t *node = (sdbnode_t *)source;
+
+       REQUIRE(VALID_SDB(sdb));
+
+       UNUSED(sdb);
+
+       isc_refcount_increment(&node->references);
+
+       *targetp = source;
+}
+
+static void
+detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
+       sdb_t *sdb = (sdb_t *)db;
+       sdbnode_t *node = NULL;
+
+       REQUIRE(VALID_SDB(sdb));
+       REQUIRE(targetp != NULL && *targetp != NULL);
+
+       UNUSED(sdb);
+
+       node = (sdbnode_t *)(*targetp);
+
+       *targetp = NULL;
+
+       if (isc_refcount_decrement(&node->references) == 1) {
+               destroynode(node);
+       }
+}
+
+static isc_result_t
+findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+            dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
+            dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
+       REQUIRE(VALID_SDBNODE(node));
+
+       dns_rdatalist_t *list = NULL;
+       sdbnode_t *sdbnode = (sdbnode_t *)node;
+
+       UNUSED(db);
+       UNUSED(version);
+       UNUSED(covers);
+       UNUSED(now);
+       UNUSED(sigrdataset);
+
+       if (type == dns_rdatatype_rrsig) {
+               return (ISC_R_NOTIMPLEMENTED);
+       }
+
+       list = ISC_LIST_HEAD(sdbnode->lists);
+       while (list != NULL) {
+               if (list->type == type) {
+                       break;
+               }
+               list = ISC_LIST_NEXT(list, link);
+       }
+       if (list == NULL) {
+               return (ISC_R_NOTFOUND);
+       }
+
+       list_tordataset(list, db, node, rdataset);
+
+       return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+            unsigned int options, isc_stdtime_t now,
+            dns_rdatasetiter_t **iteratorp) {
+       sdb_rdatasetiter_t *iterator = NULL;
+
+       REQUIRE(version == NULL || version == &dummy);
+
+       UNUSED(version);
+       UNUSED(now);
+
+       iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t));
+
+       iterator->common.magic = DNS_RDATASETITER_MAGIC;
+       iterator->common.methods = &rdatasetiter_methods;
+       iterator->common.db = db;
+       iterator->common.node = NULL;
+       attachnode(db, node, &iterator->common.node);
+       iterator->common.version = version;
+       iterator->common.options = options;
+       iterator->common.now = now;
+
+       *iteratorp = (dns_rdatasetiter_t *)iterator;
+
+       return (ISC_R_SUCCESS);
+}
+
+static dns_dbmethods_t sdb_methods = {
+       .destroy = destroy,
+       .currentversion = currentversion,
+       .attachversion = attachversion,
+       .closeversion = closeversion,
+       .attachnode = attachnode,
+       .detachnode = detachnode,
+       .findrdataset = findrdataset,
+       .allrdatasets = allrdatasets,
+       .getoriginnode = getoriginnode,
+       .findnodeext = findnodeext,
+       .findext = findext,
+};
+
+static isc_result_t
+create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
+       dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
+       void *driverarg, dns_db_t **dbp) {
+       sdb_t *sdb = NULL;
+       isc_result_t result;
+       char zonestr[DNS_NAME_MAXTEXT + 1];
+       isc_buffer_t b;
+       sdbimplementation_t *imp = NULL;
+
+       REQUIRE(driverarg != NULL);
+
+       imp = driverarg;
+
+       if (type != dns_dbtype_zone) {
+               return (ISC_R_NOTIMPLEMENTED);
+       }
+
+       sdb = isc_mem_get(mctx, sizeof(*sdb));
+       *sdb = (sdb_t){
+               .common = { .methods = &sdb_methods, .rdclass = rdclass },
+               .implementation = imp,
+       };
+
+       dns_name_init(&sdb->common.origin, NULL);
+
+       isc_mem_attach(mctx, &sdb->common.mctx);
+
+       result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
+       if (result != ISC_R_SUCCESS) {
+               goto cleanup_lock;
+       }
+
+       isc_buffer_init(&b, zonestr, sizeof(zonestr));
+       result = dns_name_totext(origin, true, &b);
+       if (result != ISC_R_SUCCESS) {
+               goto cleanup_origin;
+       }
+       isc_buffer_putuint8(&b, 0);
+
+       sdb->zone = isc_mem_strdup(mctx, zonestr);
+
+       if (imp->methods->create != NULL) {
+               LOCK(&sdb->implementation->driverlock);
+               result = imp->methods->create(sdb->zone, argc, argv,
+                                             imp->driverdata, &sdb->dbdata);
+               UNLOCK(&sdb->implementation->driverlock);
+               if (result != ISC_R_SUCCESS) {
+                       goto cleanup_zonestr;
+               }
+       }
+
+       isc_refcount_init(&sdb->common.references, 1);
+
+       sdb->common.magic = DNS_DB_MAGIC;
+       sdb->common.impmagic = SDB_MAGIC;
+
+       *dbp = (dns_db_t *)sdb;
+
+       return (ISC_R_SUCCESS);
+
+cleanup_zonestr:
+       isc_mem_free(mctx, sdb->zone);
+cleanup_origin:
+       dns_name_free(&sdb->common.origin, mctx);
+cleanup_lock:
+       isc_mem_putanddetach(&mctx, sdb, sizeof(sdb_t));
+
+       return (result);
+}
+
+/*
+ * Rdataset Methods
+ */
+
+static void
+disassociate(dns_rdataset_t *rdataset) {
+       dns_dbnode_t *node = rdataset->private5;
+       sdbnode_t *sdbnode = (sdbnode_t *)node;
+       dns_db_t *db = (dns_db_t *)sdbnode->sdb;
+
+       detachnode(db, &node);
+       dns_rdatalist_disassociate(rdataset);
+}
+
+static void
+rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
+       dns_dbnode_t *node = source->private5;
+       sdbnode_t *sdbnode = (sdbnode_t *)node;
+       dns_db_t *db = (dns_db_t *)sdbnode->sdb;
+       dns_dbnode_t *tempdb = NULL;
+
+       dns_rdatalist_clone(source, target);
+       attachnode(db, node, &tempdb);
+       source->private5 = tempdb;
+}
+
+static dns_rdatasetmethods_t sdb_rdataset_methods = {
+       disassociate,
+       dns_rdatalist_first,
+       dns_rdatalist_next,
+       dns_rdatalist_current,
+       rdataset_clone,
+       dns_rdatalist_count,
+       dns_rdatalist_addnoqname,
+       dns_rdatalist_getnoqname,
+       NULL, /* addclosest */
+       NULL, /* getclosest */
+       NULL, /* settrust */
+       NULL, /* expire */
+       NULL, /* clearprefetch */
+       NULL, /* setownercase */
+       NULL, /* getownercase */
+       NULL  /* addglue */
+};
+
+static void
+list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
+               dns_rdataset_t *rdataset) {
+       /*
+        * The sdb rdataset is an rdatalist, with private5
+        * attached to the database node.
+        */
+       dns_rdatalist_tordataset(rdatalist, rdataset);
+
+       rdataset->methods = &sdb_rdataset_methods;
+       dns_db_attachnode(db, node, &rdataset->private5);
+}
+
+/*
+ * Rdataset Iterator Methods
+ */
+
+static void
+rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
+       sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp);
+       detachnode(sdbiterator->common.db, &sdbiterator->common.node);
+       isc_mem_put(sdbiterator->common.db->mctx, sdbiterator,
+                   sizeof(sdb_rdatasetiter_t));
+       *iteratorp = NULL;
+}
+
+static isc_result_t
+rdatasetiter_first(dns_rdatasetiter_t *iterator) {
+       sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
+       sdbnode_t *sdbnode = (sdbnode_t *)iterator->node;
+
+       if (ISC_LIST_EMPTY(sdbnode->lists)) {
+               return (ISC_R_NOMORE);
+       }
+       sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists);
+       return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+rdatasetiter_next(dns_rdatasetiter_t *iterator) {
+       sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
+
+       sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link);
+       if (sdbiterator->current == NULL) {
+               return (ISC_R_NOMORE);
+       } else {
+               return (ISC_R_SUCCESS);
+       }
+}
+
+static void
+rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
+       sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
+
+       list_tordataset(sdbiterator->current, iterator->db, iterator->node,
+                       rdataset);
 }
index fbfc5997f1be8d3448a91ea7fc79b51ef3577e3a..f4b54e05da455aff22fdca04463bfbde2379b019 100644 (file)
 
 /*! \file */
 
+#include <inttypes.h>
+
+#include <isc/lang.h>
 #include <isc/types.h>
 
+#include <dns/clientinfo.h>
+#include <dns/types.h>
+
+/*
+ * Simple database implementation. Originally sdb.
+ * XXX: this will be moved to its own file later.
+ */
+
+/* Opaque types: */
+
+/* A simple database.  */
+typedef struct sdb              sdb_t;
+typedef struct sdbimplementation sdbimplementation_t;
+
+/* A simple database lookup in progress. */
+typedef struct sdblookup sdblookup_t;
+
+/* A simple database traversal in progress. */
+typedef struct sdballnodes sdballnodes_t;
+
+/* Callback function types */
+typedef isc_result_t (*sdblookupfunc_t)(const dns_name_t *zone,
+                                       const dns_name_t *name, void *dbdata,
+                                       sdblookup_t             *lookup,
+                                       dns_clientinfomethods_t *methods,
+                                       dns_clientinfo_t        *clientinfo);
+
+typedef isc_result_t (*sdbauthorityfunc_t)(const char *zone, void *dbdata,
+                                          sdblookup_t *);
+
+typedef isc_result_t (*sdballnodesfunc_t)(const char *zone, void *dbdata,
+                                         sdballnodes_t *allnodes);
+
+typedef isc_result_t (*sdbcreatefunc_t)(const char *zone, int argc, char **argv,
+                                       void *driverdata, void **dbdata);
+
+typedef void (*sdbdestroyfunc_t)(const char *zone, void *driverdata,
+                                void **dbdata);
+
+typedef struct sdbmethods {
+       sdblookupfunc_t    lookup;
+       sdbauthorityfunc_t authority;
+       sdbcreatefunc_t    create;
+       sdbdestroyfunc_t   destroy;
+} sdbmethods_t;
+
+/***
+ *** Functions
+ ***/
+
+#define DNS_SDBFLAG_DNS64 0x00000001U
+
+isc_result_t
+sdb_register(const char *drivername, const sdbmethods_t *methods,
+            void *driverdata, unsigned int flags, isc_mem_t *mctx,
+            sdbimplementation_t **sdbimp);
+/*%<
+ * Register a simple database driver for the database type 'drivername',
+ * implemented by the functions in '*methods'.
+ *
+ * sdbimp must point to a NULL sdbimplementation_t pointer.  That is,
+ * sdbimp != NULL && *sdbimp == NULL.  It will be assigned a value that
+ * will later be used to identify the driver when deregistering it.
+ *
+ * The name server will perform lookups in the database by calling the
+ * function 'lookup', passing it a printable zone name 'zone', a printable
+ * domain name 'name', and a copy of the argument 'dbdata' that
+ * was potentially returned by the create function.  The 'sdblookup_t'
+ * argument to 'lookup' and 'authority' is an opaque pointer to be passed to
+ * ns_sdb_putrr().
+ *
+ * The lookup function returns the lookup results to the name server
+ * by calling ns_sdb_putrr() once for each record found.  On success,
+ * the return value of the lookup function should be ISC_R_SUCCESS.
+ * If the domain name 'name' does not exist, the lookup function should
+ * ISC_R_NOTFOUND.  Any other return value is treated as an error.
+ *
+ * Lookups at the zone apex will cause the server to also call the
+ * function 'authority' (if non-NULL), which must provide an SOA record
+ * and NS records for the zone by calling ns_sdb_putrr() once for each of
+ * these records.  The 'authority' function may be NULL if invoking
+ * the 'lookup' function on the zone apex will return SOA and NS records.
+ *
+ * The allnodes function, if non-NULL, fills in an opaque structure to be
+ * used by a database iterator.  This allows the zone to be transferred.
+ * This may use a considerable amount of memory for large zones, and the
+ * zone transfer may not be fully RFC1035 compliant if the zone is
+ * frequently changed.
+ *
+ * The create function will be called for each zone configured
+ * into the name server using this database type.  It can be used
+ * to create a "database object" containing zone specific data,
+ * which can make use of the database arguments specified in the
+ * name server configuration.
+ *
+ * The destroy function will be called to free the database object
+ * when its zone is destroyed.
+ *
+ * The create and destroy functions may be NULL.
+ *
+ * The lookup and authority functions are called with relative names
+ * rather than absolute names. The string "@" represents the zone apex.
+ *
+ * Rdata strings may include relative names.  Be aware that absolute names
+ * must contain a trailing dot.
+ */
+
+void
+sdb_unregister(sdbimplementation_t **sdbimp);
+/*%<
+ * Removes the simple database driver from the list of registered database
+ * types.  There must be no active databases of this type when this function
+ * is called.
+ */
+
+/*% See sdb_putradata() */
+isc_result_t
+sdb_putrr(sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
+         const char *data);
+
+/*
+ * Add a single resource record to the lookup structure to be
+ * returned in the query response.  sdb_putrr() takes the
+ * resource record in master file text format as a null-terminated
+ * string, and sdb_putrdata() takes the raw RDATA in
+ * uncompressed wire format.
+ */
+isc_result_t
+sdb_putrdata(sdblookup_t *lookup, dns_rdatatype_t type, dns_ttl_t ttl,
+            const unsigned char *rdata, unsigned int rdlen);
+
+/*
+ * May be called from the 'authority' callback to simplify construction of
+ * an SOA record for 'zone'.  It will provide a SOA listing 'mname' as as
+ * the primary server and 'rname' as the responsible person mailbox.  It is
+ * the responsibility of the driver to increment the serial number between
+ * responses if necessary.  All other SOA fields will have reasonable
+ * default values.
+ */
+isc_result_t
+sdb_putsoa(sdblookup_t *lookup, const char *mname, const char *rname,
+          uint32_t serial);
+
+/* Initialization functions for builtin zone databases */
 isc_result_t
 named_builtin_init(void);
 
index 3edbf210a512a0dfd0298b74acabcc34a2185224..41ba474af5e1ad70076b2839fc1d6b0bf9dcb6cd 100644 (file)
@@ -116,7 +116,6 @@ libdns_la_HEADERS =                 \
        include/dns/rpz.h               \
        include/dns/rriterator.h        \
        include/dns/rrl.h               \
-       include/dns/sdb.h               \
        include/dns/sdlz.h              \
        include/dns/secalg.h            \
        include/dns/secproto.h          \
@@ -219,7 +218,6 @@ libdns_la_SOURCES =                 \
        rpz.c                           \
        rrl.c                           \
        rriterator.c                    \
-       sdb.c                           \
        sdlz.c                          \
        soa.c                           \
        ssu.c                           \
diff --git a/lib/dns/include/dns/sdb.h b/lib/dns/include/dns/sdb.h
deleted file mode 100644 (file)
index 1f4d5b1..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
- *
- * SPDX-License-Identifier: MPL-2.0
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, you can obtain one at https://mozilla.org/MPL/2.0/.
- *
- * See the COPYRIGHT file distributed with this work for additional
- * information regarding copyright ownership.
- */
-
-#pragma once
-
-/*****
-***** Module Info
-*****/
-
-/*! \file dns/sdb.h
- * \brief
- * Simple database API.
- */
-
-/***
- *** Imports
- ***/
-
-#include <inttypes.h>
-
-#include <isc/lang.h>
-
-#include <dns/clientinfo.h>
-#include <dns/types.h>
-
-/***
- *** Types
- ***/
-
-/*%
- * A simple database.  This is an opaque type.
- */
-typedef struct dns_sdb dns_sdb_t;
-
-/*%
- * A simple database lookup in progress.  This is an opaque type.
- */
-typedef struct dns_sdblookup dns_sdblookup_t;
-
-typedef isc_result_t (*dns_sdblookupfunc_t)(const dns_name_t       *zone,
-                                           const dns_name_t        *name,
-                                           void                    *dbdata,
-                                           dns_sdblookup_t         *lookup,
-                                           dns_clientinfomethods_t *methods,
-                                           dns_clientinfo_t *clientinfo);
-
-typedef isc_result_t (*dns_sdbauthorityfunc_t)(const char *zone, void *dbdata,
-                                              dns_sdblookup_t *);
-
-typedef isc_result_t (*dns_sdbcreatefunc_t)(const char *zone, int argc,
-                                           char **argv, void *driverdata,
-                                           void **dbdata);
-
-typedef void (*dns_sdbdestroyfunc_t)(const char *zone, void *driverdata,
-                                    void **dbdata);
-
-typedef struct dns_sdbmethods {
-       dns_sdblookupfunc_t    lookup;
-       dns_sdbauthorityfunc_t authority;
-       dns_sdbcreatefunc_t    create;
-       dns_sdbdestroyfunc_t   destroy;
-} dns_sdbmethods_t;
-
-/***
- *** Functions
- ***/
-
-ISC_LANG_BEGINDECLS
-
-#define DNS_SDBFLAG_DNS64 0x00000008U
-
-isc_result_t
-dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
-                void *driverdata, unsigned int flags, isc_mem_t *mctx,
-                dns_sdbimplementation_t **sdbimp);
-/*%<
- * Register a simple database driver for the database type 'drivername',
- * implemented by the functions in '*methods'.
- *
- * sdbimp must point to a NULL dns_sdbimplementation_t pointer.  That is,
- * sdbimp != NULL && *sdbimp == NULL.  It will be assigned a value that
- * will later be used to identify the driver when deregistering it.
- *
- * The name server will perform lookups in the database by calling the
- * function 'lookup', passing it a printable zone name 'zone', a printable
- * domain name 'name', and a copy of the argument 'dbdata' that
- * was potentially returned by the create function.  The 'dns_sdblookup_t'
- * argument to 'lookup' and 'authority' is an opaque pointer to be passed to
- * ns_sdb_putrr().
- *
- * The lookup function returns the lookup results to the name server
- * by calling ns_sdb_putrr() once for each record found.  On success,
- * the return value of the lookup function should be ISC_R_SUCCESS.
- * If the domain name 'name' does not exist, the lookup function should
- * ISC_R_NOTFOUND.  Any other return value is treated as an error.
- *
- * Lookups at the zone apex will cause the server to also call the
- * function 'authority' (if non-NULL), which must provide an SOA record
- * and NS records for the zone by calling ns_sdb_putrr() once for each of
- * these records.  The 'authority' function may be NULL if invoking
- * the 'lookup' function on the zone apex will return SOA and NS records.
- *
- * The create function will be called for each zone configured
- * into the name server using this database type.  It can be used
- * to create a "database object" containing zone specific data,
- * which can make use of the database arguments specified in the
- * name server configuration.
- *
- * The destroy function will be called to free the database object
- * when its zone is destroyed.
- *
- * The create and destroy functions may be NULL.
- *
- * The lookup and authority functions are called with relative names
- * rather than absolute names. The string "@" represents the zone apex.
- *
- * Rdata strings may include relative names.  Be aware that absolute names
- * must contain a trailing dot.
- */
-
-void
-dns_sdb_unregister(dns_sdbimplementation_t **sdbimp);
-/*%<
- * Removes the simple database driver from the list of registered database
- * types.  There must be no active databases of this type when this function
- * is called.
- */
-
-/*% See dns_sdb_putradata() */
-isc_result_t
-dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
-             const char *data);
-isc_result_t
-dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t type, dns_ttl_t ttl,
-                const unsigned char *rdata, unsigned int rdlen);
-/*%<
- * Add a single resource record to the lookup structure to be
- * returned in the query response.  dns_sdb_putrr() takes the
- * resource record in master file text format as a null-terminated
- * string, and dns_sdb_putrdata() takes the raw RDATA in
- * uncompressed wire format.
- */
-
-isc_result_t
-dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
-              uint32_t serial);
-/*%<
- * This function may optionally be called from the 'authority' callback
- * to simplify construction of the SOA record for 'zone'.  It will
- * provide a SOA listing 'mname' as as the primary server and 'rname' as
- * the responsible person mailbox.  It is the responsibility of the
- * driver to increment the serial number between responses if necessary.
- * All other SOA fields will have reasonable default values.
- */
-
-ISC_LANG_ENDDECLS
index 7f0e3b2d3931db05a7544c29fef0f2e41f8c3276..363683bff124aa99e77e02697f54fcd63becf651 100644 (file)
@@ -126,31 +126,30 @@ typedef uint16_t            dns_rdataclass_t;
 typedef struct dns_rdatalist     dns_rdatalist_t;
 typedef struct dns_rdataset      dns_rdataset_t;
 typedef ISC_LIST(dns_rdataset_t) dns_rdatasetlist_t;
-typedef struct dns_rdatasetiter             dns_rdatasetiter_t;
-typedef uint16_t                    dns_rdatatype_t;
-typedef struct dns_remote           dns_remote_t;
-typedef struct dns_request          dns_request_t;
-typedef struct dns_requestmgr       dns_requestmgr_t;
-typedef struct dns_resolver         dns_resolver_t;
-typedef struct dns_sdbimplementation dns_sdbimplementation_t;
-typedef uint8_t                             dns_secalg_t;
-typedef uint8_t                             dns_secproto_t;
-typedef struct dns_signature        dns_signature_t;
-typedef struct dns_sortlist_arg             dns_sortlist_arg_t;
-typedef struct dns_ssurule          dns_ssurule_t;
-typedef struct dns_ssutable         dns_ssutable_t;
-typedef struct dns_stats            dns_stats_t;
-typedef uint32_t                    dns_rdatastatstype_t;
-typedef struct dns_tkeyctx          dns_tkeyctx_t;
-typedef struct dns_transport        dns_transport_t;
-typedef struct dns_transport_list    dns_transport_list_t;
-typedef uint16_t                    dns_trust_t;
-typedef struct dns_tsig_keyring             dns_tsig_keyring_t;
-typedef struct dns_tsigkey          dns_tsigkey_t;
-typedef uint32_t                    dns_ttl_t;
-typedef struct dns_update_state             dns_update_state_t;
-typedef struct dns_validator        dns_validator_t;
-typedef struct dns_view                     dns_view_t;
+typedef struct dns_rdatasetiter          dns_rdatasetiter_t;
+typedef uint16_t                 dns_rdatatype_t;
+typedef struct dns_remote        dns_remote_t;
+typedef struct dns_request       dns_request_t;
+typedef struct dns_requestmgr    dns_requestmgr_t;
+typedef struct dns_resolver      dns_resolver_t;
+typedef uint8_t                          dns_secalg_t;
+typedef uint8_t                          dns_secproto_t;
+typedef struct dns_signature     dns_signature_t;
+typedef struct dns_sortlist_arg          dns_sortlist_arg_t;
+typedef struct dns_ssurule       dns_ssurule_t;
+typedef struct dns_ssutable      dns_ssutable_t;
+typedef struct dns_stats         dns_stats_t;
+typedef uint32_t                 dns_rdatastatstype_t;
+typedef struct dns_tkeyctx       dns_tkeyctx_t;
+typedef struct dns_transport     dns_transport_t;
+typedef struct dns_transport_list dns_transport_list_t;
+typedef uint16_t                 dns_trust_t;
+typedef struct dns_tsig_keyring          dns_tsig_keyring_t;
+typedef struct dns_tsigkey       dns_tsigkey_t;
+typedef uint32_t                 dns_ttl_t;
+typedef struct dns_update_state          dns_update_state_t;
+typedef struct dns_validator     dns_validator_t;
+typedef struct dns_view                  dns_view_t;
 typedef ISC_LIST(dns_view_t) dns_viewlist_t;
 typedef struct dns_zone dns_zone_t;
 typedef ISC_LIST(dns_zone_t) dns_zonelist_t;
diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c
deleted file mode 100644 (file)
index d67c27a..0000000
+++ /dev/null
@@ -1,1036 +0,0 @@
-/*
- * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
- *
- * SPDX-License-Identifier: MPL-2.0
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, you can obtain one at https://mozilla.org/MPL/2.0/.
- *
- * See the COPYRIGHT file distributed with this work for additional
- * information regarding copyright ownership.
- */
-
-/*! \file */
-
-#include <inttypes.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <isc/buffer.h>
-#include <isc/lex.h>
-#include <isc/log.h>
-#include <isc/magic.h>
-#include <isc/mem.h>
-#include <isc/once.h>
-#include <isc/refcount.h>
-#include <isc/region.h>
-#include <isc/result.h>
-#include <isc/util.h>
-
-#include <dns/callbacks.h>
-#include <dns/db.h>
-#include <dns/dbiterator.h>
-#include <dns/fixedname.h>
-#include <dns/log.h>
-#include <dns/rdata.h>
-#include <dns/rdatalist.h>
-#include <dns/rdataset.h>
-#include <dns/rdatasetiter.h>
-#include <dns/rdatatype.h>
-#include <dns/sdb.h>
-#include <dns/types.h>
-
-struct dns_sdbimplementation {
-       const dns_sdbmethods_t *methods;
-       void *driverdata;
-       unsigned int flags;
-       isc_mem_t *mctx;
-       isc_mutex_t driverlock;
-       dns_dbimplementation_t *dbimp;
-};
-
-struct dns_sdb {
-       /* Unlocked */
-       dns_db_t common;
-       char *zone;
-       dns_sdbimplementation_t *implementation;
-       void *dbdata;
-};
-
-struct dns_sdblookup {
-       /* Unlocked */
-       unsigned int magic;
-       dns_sdb_t *sdb;
-       ISC_LIST(dns_rdatalist_t) lists;
-       ISC_LIST(isc_buffer_t) buffers;
-       dns_name_t *name;
-       ISC_LINK(dns_sdblookup_t) link;
-       dns_rdatacallbacks_t callbacks;
-
-       /* Atomic */
-       isc_refcount_t references;
-};
-
-typedef struct dns_sdblookup dns_sdbnode_t;
-
-typedef struct sdb_rdatasetiter {
-       dns_rdatasetiter_t common;
-       dns_rdatalist_t *current;
-} sdb_rdatasetiter_t;
-
-#define SDB_MAGIC ISC_MAGIC('S', 'D', 'B', '-')
-
-/*%
- * Note that "impmagic" is not the first four bytes of the struct, so
- * ISC_MAGIC_VALID cannot be used.
- */
-#define VALID_SDB(sdb) ((sdb) != NULL && (sdb)->common.impmagic == SDB_MAGIC)
-
-#define SDBLOOKUP_MAGIC              ISC_MAGIC('S', 'D', 'B', 'L')
-#define VALID_SDBLOOKUP(sdbl) ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)
-#define VALID_SDBNODE(sdbn)   VALID_SDBLOOKUP(sdbn)
-
-/* These values are taken from RFC1537 */
-#define SDB_DEFAULT_REFRESH 28800U  /* 8 hours */
-#define SDB_DEFAULT_RETRY   7200U   /* 2 hours */
-#define SDB_DEFAULT_EXPIRE  604800U /* 7 days */
-#define SDB_DEFAULT_MINIMUM 86400U  /* 1 day */
-
-/* This is a reasonable value */
-#define SDB_DEFAULT_TTL (60 * 60 * 24)
-
-static int dummy;
-
-static isc_result_t
-create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
-       dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
-       void *driverarg, dns_db_t **dbp);
-
-static isc_result_t
-findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
-            dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
-            dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
-
-static isc_result_t
-createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep);
-
-static void
-destroynode(dns_sdbnode_t *node);
-
-static void
-detachnode(dns_db_t *db, dns_dbnode_t **targetp);
-
-static void
-list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
-               dns_rdataset_t *rdataset);
-
-static void
-rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
-static isc_result_t
-rdatasetiter_first(dns_rdatasetiter_t *iterator);
-static isc_result_t
-rdatasetiter_next(dns_rdatasetiter_t *iterator);
-static void
-rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset);
-
-static dns_rdatasetitermethods_t rdatasetiter_methods = {
-       rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next,
-       rdatasetiter_current
-};
-
-/*
- * Functions used by implementors of simple databases
- */
-isc_result_t
-dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
-                void *driverdata, unsigned int flags, isc_mem_t *mctx,
-                dns_sdbimplementation_t **sdbimp) {
-       dns_sdbimplementation_t *imp = NULL;
-       isc_result_t result;
-
-       REQUIRE(drivername != NULL);
-       REQUIRE(methods != NULL);
-       REQUIRE(methods->lookup != NULL);
-       REQUIRE(mctx != NULL);
-       REQUIRE(sdbimp != NULL && *sdbimp == NULL);
-       REQUIRE((flags & ~DNS_SDBFLAG_DNS64) == 0);
-
-       imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t));
-       imp->methods = methods;
-       imp->driverdata = driverdata;
-       imp->flags = flags;
-       imp->mctx = NULL;
-       isc_mem_attach(mctx, &imp->mctx);
-       isc_mutex_init(&imp->driverlock);
-
-       imp->dbimp = NULL;
-       result = dns_db_register(drivername, create, imp, mctx, &imp->dbimp);
-       if (result != ISC_R_SUCCESS) {
-               goto cleanup_mutex;
-       }
-       *sdbimp = imp;
-
-       return (ISC_R_SUCCESS);
-
-cleanup_mutex:
-       isc_mutex_destroy(&imp->driverlock);
-       isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
-       return (result);
-}
-
-void
-dns_sdb_unregister(dns_sdbimplementation_t **sdbimp) {
-       dns_sdbimplementation_t *imp = NULL;
-
-       REQUIRE(sdbimp != NULL && *sdbimp != NULL);
-
-       imp = *sdbimp;
-       *sdbimp = NULL;
-       dns_db_unregister(&imp->dbimp);
-       isc_mutex_destroy(&imp->driverlock);
-
-       isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdbimplementation_t));
-}
-
-static unsigned int
-initial_size(unsigned int len) {
-       unsigned int size;
-
-       for (size = 1024; size < (64 * 1024); size *= 2) {
-               if (len < size) {
-                       return (size);
-               }
-       }
-       return (65535);
-}
-
-isc_result_t
-dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval,
-                dns_ttl_t ttl, const unsigned char *rdatap,
-                unsigned int rdlen) {
-       dns_rdatalist_t *rdatalist = NULL;
-       dns_rdata_t *rdata = NULL;
-       isc_buffer_t *rdatabuf = NULL;
-       isc_mem_t *mctx = NULL;
-       isc_region_t region;
-
-       mctx = lookup->sdb->common.mctx;
-
-       rdatalist = ISC_LIST_HEAD(lookup->lists);
-       while (rdatalist != NULL) {
-               if (rdatalist->type == typeval) {
-                       break;
-               }
-               rdatalist = ISC_LIST_NEXT(rdatalist, link);
-       }
-
-       if (rdatalist == NULL) {
-               rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
-               dns_rdatalist_init(rdatalist);
-               rdatalist->rdclass = lookup->sdb->common.rdclass;
-               rdatalist->type = typeval;
-               rdatalist->ttl = ttl;
-               ISC_LIST_APPEND(lookup->lists, rdatalist, link);
-       } else if (rdatalist->ttl != ttl) {
-               return (DNS_R_BADTTL);
-       }
-
-       rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
-
-       isc_buffer_allocate(mctx, &rdatabuf, rdlen);
-       DE_CONST(rdatap, region.base);
-       region.length = rdlen;
-       isc_buffer_copyregion(rdatabuf, &region);
-       isc_buffer_usedregion(rdatabuf, &region);
-       dns_rdata_init(rdata);
-       dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type,
-                            &region);
-       ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
-       ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
-
-       return (ISC_R_SUCCESS);
-}
-
-isc_result_t
-dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
-             const char *data) {
-       unsigned int datalen;
-       dns_rdatatype_t typeval;
-       isc_textregion_t r;
-       isc_lex_t *lex = NULL;
-       isc_result_t result;
-       unsigned char *p = NULL;
-       unsigned int size = 0; /* Init to suppress compiler warning */
-       isc_mem_t *mctx = NULL;
-       const dns_name_t *origin = NULL;
-       isc_buffer_t b;
-       isc_buffer_t rb;
-
-       REQUIRE(VALID_SDBLOOKUP(lookup));
-       REQUIRE(type != NULL);
-       REQUIRE(data != NULL);
-
-       mctx = lookup->sdb->common.mctx;
-
-       DE_CONST(type, r.base);
-       r.length = strlen(type);
-       result = dns_rdatatype_fromtext(&typeval, &r);
-       if (result != ISC_R_SUCCESS) {
-               return (result);
-       }
-
-       origin = &lookup->sdb->common.origin;
-
-       isc_lex_create(mctx, 64, &lex);
-
-       datalen = strlen(data);
-       size = initial_size(datalen);
-       do {
-               isc_buffer_constinit(&b, data, datalen);
-               isc_buffer_add(&b, datalen);
-               result = isc_lex_openbuffer(lex, &b);
-               if (result != ISC_R_SUCCESS) {
-                       goto failure;
-               }
-
-               if (size >= 65535) {
-                       size = 65535;
-               }
-               p = isc_mem_get(mctx, size);
-               isc_buffer_init(&rb, p, size);
-               result = dns_rdata_fromtext(NULL, lookup->sdb->common.rdclass,
-                                           typeval, lex, origin, 0, mctx, &rb,
-                                           &lookup->callbacks);
-               if (result != ISC_R_NOSPACE) {
-                       break;
-               }
-
-               /*
-                * Is the RR too big?
-                */
-               if (size >= 65535) {
-                       break;
-               }
-               isc_mem_put(mctx, p, size);
-               p = NULL;
-               size *= 2;
-       } while (result == ISC_R_NOSPACE);
-
-       if (result != ISC_R_SUCCESS) {
-               goto failure;
-       }
-
-       result = dns_sdb_putrdata(lookup, typeval, ttl, isc_buffer_base(&rb),
-                                 isc_buffer_usedlength(&rb));
-failure:
-       if (p != NULL) {
-               isc_mem_put(mctx, p, size);
-       }
-       if (lex != NULL) {
-               isc_lex_destroy(&lex);
-       }
-
-       return (result);
-}
-
-isc_result_t
-dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
-              uint32_t serial) {
-       char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
-       int n;
-
-       REQUIRE(mname != NULL);
-       REQUIRE(rname != NULL);
-
-       n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u", mname, rname,
-                    serial, SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY,
-                    SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM);
-       if (n >= (int)sizeof(str) || n < 0) {
-               return (ISC_R_NOSPACE);
-       }
-       return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));
-}
-
-/*
- * DB routines
- */
-
-static void
-destroy(dns_db_t *db) {
-       dns_sdb_t *sdb = (dns_sdb_t *)db;
-       dns_sdbimplementation_t *imp = sdb->implementation;
-
-       isc_refcount_destroy(&sdb->common.references);
-
-       if (imp != NULL && imp->methods->destroy != NULL) {
-               LOCK(&sdb->implementation->driverlock);
-               imp->methods->destroy(sdb->zone, imp->driverdata, &sdb->dbdata);
-               UNLOCK(&sdb->implementation->driverlock);
-       }
-
-       isc_mem_free(sdb->common.mctx, sdb->zone);
-
-       sdb->common.magic = 0;
-       sdb->common.impmagic = 0;
-
-       dns_name_free(&sdb->common.origin, sdb->common.mctx);
-
-       isc_mem_putanddetach(&sdb->common.mctx, sdb, sizeof(dns_sdb_t));
-}
-
-static void
-currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
-       REQUIRE(versionp != NULL && *versionp == NULL);
-
-       UNUSED(db);
-
-       *versionp = (void *)&dummy;
-       return;
-}
-
-static void
-attachversion(dns_db_t *db, dns_dbversion_t *source,
-             dns_dbversion_t **targetp) {
-       REQUIRE(source != NULL && source == (void *)&dummy);
-       REQUIRE(targetp != NULL && *targetp == NULL);
-
-       UNUSED(db);
-       *targetp = source;
-       return;
-}
-
-static void
-closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
-       REQUIRE(versionp != NULL && *versionp == (void *)&dummy);
-       REQUIRE(!commit);
-
-       UNUSED(db);
-       UNUSED(commit);
-
-       *versionp = NULL;
-}
-
-static isc_result_t
-createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) {
-       dns_sdbnode_t *node = NULL;
-
-       node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t));
-
-       node->sdb = NULL;
-       dns_db_attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb);
-       ISC_LIST_INIT(node->lists);
-       ISC_LIST_INIT(node->buffers);
-       ISC_LINK_INIT(node, link);
-       node->name = NULL;
-       dns_rdatacallbacks_init(&node->callbacks);
-
-       isc_refcount_init(&node->references, 1);
-
-       node->magic = SDBLOOKUP_MAGIC;
-
-       *nodep = node;
-       return (ISC_R_SUCCESS);
-}
-
-static void
-destroynode(dns_sdbnode_t *node) {
-       dns_rdatalist_t *list = NULL;
-       dns_rdata_t *rdata = NULL;
-       isc_buffer_t *b = NULL;
-       dns_sdb_t *sdb = NULL;
-       isc_mem_t *mctx = NULL;
-
-       sdb = node->sdb;
-       mctx = sdb->common.mctx;
-
-       while (!ISC_LIST_EMPTY(node->lists)) {
-               list = ISC_LIST_HEAD(node->lists);
-               while (!ISC_LIST_EMPTY(list->rdata)) {
-                       rdata = ISC_LIST_HEAD(list->rdata);
-                       ISC_LIST_UNLINK(list->rdata, rdata, link);
-                       isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
-               }
-               ISC_LIST_UNLINK(node->lists, list, link);
-               isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
-       }
-
-       while (!ISC_LIST_EMPTY(node->buffers)) {
-               b = ISC_LIST_HEAD(node->buffers);
-               ISC_LIST_UNLINK(node->buffers, b, link);
-               isc_buffer_free(&b);
-       }
-
-       if (node->name != NULL) {
-               dns_name_free(node->name, mctx);
-               isc_mem_put(mctx, node->name, sizeof(dns_name_t));
-       }
-
-       node->magic = 0;
-       isc_mem_put(mctx, node, sizeof(dns_sdbnode_t));
-       dns_db_detach((dns_db_t **)(void *)&sdb);
-}
-
-static isc_result_t
-getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
-       dns_sdb_t *sdb = (dns_sdb_t *)db;
-       dns_sdbnode_t *node = NULL;
-       isc_result_t result;
-       dns_sdbimplementation_t *imp = NULL;
-       dns_name_t relname;
-       dns_name_t *name = NULL;
-
-       REQUIRE(VALID_SDB(sdb));
-       REQUIRE(nodep != NULL && *nodep == NULL);
-
-       imp = sdb->implementation;
-       dns_name_init(&relname, NULL);
-       name = &relname;
-
-       result = createnode(sdb, &node);
-       if (result != ISC_R_SUCCESS) {
-               return (result);
-       }
-
-       LOCK(&sdb->implementation->driverlock);
-       result = imp->methods->lookup(&sdb->common.origin, name, sdb->dbdata,
-                                     node, NULL, NULL);
-       UNLOCK(&sdb->implementation->driverlock);
-       if (result != ISC_R_SUCCESS &&
-           !(result == ISC_R_NOTFOUND && imp->methods->authority != NULL))
-       {
-               destroynode(node);
-               return (result);
-       }
-
-       if (imp->methods->authority != NULL) {
-               LOCK(&sdb->implementation->driverlock);
-               result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
-               UNLOCK(&sdb->implementation->driverlock);
-               if (result != ISC_R_SUCCESS) {
-                       destroynode(node);
-                       return (result);
-               }
-       }
-
-       *nodep = node;
-       return (ISC_R_SUCCESS);
-}
-
-static isc_result_t
-findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
-           dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
-           dns_dbnode_t **nodep) {
-       dns_sdb_t *sdb = (dns_sdb_t *)db;
-       dns_sdbnode_t *node = NULL;
-       isc_result_t result;
-       bool isorigin;
-       dns_sdbimplementation_t *imp = NULL;
-       dns_name_t relname;
-       unsigned int labels;
-
-       REQUIRE(VALID_SDB(sdb));
-       REQUIRE(nodep != NULL && *nodep == NULL);
-
-       UNUSED(name);
-       UNUSED(create);
-
-       imp = sdb->implementation;
-
-       isorigin = dns_name_equal(name, &sdb->common.origin);
-
-       labels = dns_name_countlabels(name) - dns_name_countlabels(&db->origin);
-       dns_name_init(&relname, NULL);
-       dns_name_getlabelsequence(name, 0, labels, &relname);
-       name = &relname;
-
-       result = createnode(sdb, &node);
-       if (result != ISC_R_SUCCESS) {
-               return (result);
-       }
-
-       LOCK(&sdb->implementation->driverlock);
-       result = imp->methods->lookup(&sdb->common.origin, name, sdb->dbdata,
-                                     node, methods, clientinfo);
-       UNLOCK(&sdb->implementation->driverlock);
-       if (result != ISC_R_SUCCESS && !(result == ISC_R_NOTFOUND && isorigin &&
-                                        imp->methods->authority != NULL))
-       {
-               destroynode(node);
-               return (result);
-       }
-
-       if (isorigin && imp->methods->authority != NULL) {
-               LOCK(&sdb->implementation->driverlock);
-               result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
-               UNLOCK(&sdb->implementation->driverlock);
-               if (result != ISC_R_SUCCESS) {
-                       destroynode(node);
-                       return (result);
-               }
-       }
-
-       *nodep = node;
-       return (ISC_R_SUCCESS);
-}
-
-static isc_result_t
-findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
-       dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
-       dns_dbnode_t **nodep, dns_name_t *foundname,
-       dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
-       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
-       dns_sdb_t *sdb = (dns_sdb_t *)db;
-       dns_dbnode_t *node = NULL;
-       dns_fixedname_t fname;
-       dns_rdataset_t xrdataset;
-       dns_name_t *xname = NULL;
-       unsigned int nlabels, olabels;
-       isc_result_t result;
-       unsigned int i;
-       unsigned int flags;
-
-       REQUIRE(VALID_SDB(sdb));
-       REQUIRE(nodep == NULL || *nodep == NULL);
-       REQUIRE(version == NULL || version == (void *)&dummy);
-
-       UNUSED(options);
-
-       if (!dns_name_issubdomain(name, &db->origin)) {
-               return (DNS_R_NXDOMAIN);
-       }
-
-       olabels = dns_name_countlabels(&db->origin);
-       nlabels = dns_name_countlabels(name);
-
-       xname = dns_fixedname_initname(&fname);
-
-       if (rdataset == NULL) {
-               dns_rdataset_init(&xrdataset);
-               rdataset = &xrdataset;
-       }
-
-       result = DNS_R_NXDOMAIN;
-       flags = sdb->implementation->flags;
-       i = (flags & DNS_SDBFLAG_DNS64) != 0 ? nlabels : olabels;
-       for (; i <= nlabels; i++) {
-               /*
-                * Look up the next label.
-                */
-               dns_name_getlabelsequence(name, nlabels - i, i, xname);
-               result = findnodeext(db, xname, false, methods, clientinfo,
-                                    &node);
-               if (result == ISC_R_NOTFOUND) {
-                       /*
-                        * No data at zone apex?
-                        */
-                       if (i == olabels) {
-                               return (DNS_R_BADDB);
-                       }
-                       result = DNS_R_NXDOMAIN;
-                       continue;
-               }
-               if (result != ISC_R_SUCCESS) {
-                       return (result);
-               }
-
-               /*
-                * DNS64 zone's don't have DNAME or NS records.
-                */
-               if ((flags & DNS_SDBFLAG_DNS64) != 0) {
-                       goto skip;
-               }
-
-               /*
-                * DNS64 zone's don't have DNAME or NS records.
-                */
-               if ((flags & DNS_SDBFLAG_DNS64) != 0) {
-                       goto skip;
-               }
-
-               /*
-                * Look for a DNAME at the current label, unless this is
-                * the qname.
-                */
-               if (i < nlabels) {
-                       result = findrdataset(db, node, version,
-                                             dns_rdatatype_dname, 0, now,
-                                             rdataset, sigrdataset);
-                       if (result == ISC_R_SUCCESS) {
-                               result = DNS_R_DNAME;
-                               break;
-                       }
-               }
-
-               /*
-                * Look for an NS at the current label, unless this is the
-                * origin or glue is ok.
-                */
-               if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
-                       result = findrdataset(db, node, version,
-                                             dns_rdatatype_ns, 0, now,
-                                             rdataset, sigrdataset);
-                       if (result == ISC_R_SUCCESS) {
-                               if (i == nlabels && type == dns_rdatatype_any) {
-                                       result = DNS_R_ZONECUT;
-                                       dns_rdataset_disassociate(rdataset);
-                                       if (sigrdataset != NULL &&
-                                           dns_rdataset_isassociated(
-                                                   sigrdataset))
-                                       {
-                                               dns_rdataset_disassociate(
-                                                       sigrdataset);
-                                       }
-                               } else {
-                                       result = DNS_R_DELEGATION;
-                               }
-                               break;
-                       }
-               }
-
-               /*
-                * If the current name is not the qname, add another label
-                * and try again.
-                */
-               if (i < nlabels) {
-                       destroynode(node);
-                       node = NULL;
-                       continue;
-               }
-
-       skip:
-               /*
-                * If we're looking for ANY, we're done.
-                */
-               if (type == dns_rdatatype_any) {
-                       result = ISC_R_SUCCESS;
-                       break;
-               }
-
-               /*
-                * Look for the qtype.
-                */
-               result = findrdataset(db, node, version, type, 0, now, rdataset,
-                                     sigrdataset);
-               if (result == ISC_R_SUCCESS) {
-                       break;
-               }
-
-               /*
-                * Look for a CNAME
-                */
-               if (type != dns_rdatatype_cname) {
-                       result = findrdataset(db, node, version,
-                                             dns_rdatatype_cname, 0, now,
-                                             rdataset, sigrdataset);
-                       if (result == ISC_R_SUCCESS) {
-                               result = DNS_R_CNAME;
-                               break;
-                       }
-               }
-
-               result = DNS_R_NXRRSET;
-               break;
-       }
-
-       if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) {
-               dns_rdataset_disassociate(rdataset);
-       }
-
-       if (foundname != NULL) {
-               dns_name_copy(xname, foundname);
-       }
-
-       if (nodep != NULL) {
-               *nodep = node;
-       } else if (node != NULL) {
-               detachnode(db, &node);
-       }
-
-       return (result);
-}
-
-static void
-attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
-       dns_sdb_t *sdb = (dns_sdb_t *)db;
-       dns_sdbnode_t *node = (dns_sdbnode_t *)source;
-
-       REQUIRE(VALID_SDB(sdb));
-
-       UNUSED(sdb);
-
-       isc_refcount_increment(&node->references);
-
-       *targetp = source;
-}
-
-static void
-detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
-       dns_sdb_t *sdb = (dns_sdb_t *)db;
-       dns_sdbnode_t *node = NULL;
-
-       REQUIRE(VALID_SDB(sdb));
-       REQUIRE(targetp != NULL && *targetp != NULL);
-
-       UNUSED(sdb);
-
-       node = (dns_sdbnode_t *)(*targetp);
-
-       *targetp = NULL;
-
-       if (isc_refcount_decrement(&node->references) == 1) {
-               destroynode(node);
-       }
-}
-
-static isc_result_t
-findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
-            dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
-            dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
-       REQUIRE(VALID_SDBNODE(node));
-
-       dns_rdatalist_t *list = NULL;
-       dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
-
-       UNUSED(db);
-       UNUSED(version);
-       UNUSED(covers);
-       UNUSED(now);
-       UNUSED(sigrdataset);
-
-       if (type == dns_rdatatype_rrsig) {
-               return (ISC_R_NOTIMPLEMENTED);
-       }
-
-       list = ISC_LIST_HEAD(sdbnode->lists);
-       while (list != NULL) {
-               if (list->type == type) {
-                       break;
-               }
-               list = ISC_LIST_NEXT(list, link);
-       }
-       if (list == NULL) {
-               return (ISC_R_NOTFOUND);
-       }
-
-       list_tordataset(list, db, node, rdataset);
-
-       return (ISC_R_SUCCESS);
-}
-
-static isc_result_t
-allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
-            unsigned int options, isc_stdtime_t now,
-            dns_rdatasetiter_t **iteratorp) {
-       sdb_rdatasetiter_t *iterator = NULL;
-
-       REQUIRE(version == NULL || version == &dummy);
-
-       UNUSED(version);
-       UNUSED(now);
-
-       iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t));
-
-       iterator->common.magic = DNS_RDATASETITER_MAGIC;
-       iterator->common.methods = &rdatasetiter_methods;
-       iterator->common.db = db;
-       iterator->common.node = NULL;
-       attachnode(db, node, &iterator->common.node);
-       iterator->common.version = version;
-       iterator->common.options = options;
-       iterator->common.now = now;
-
-       *iteratorp = (dns_rdatasetiter_t *)iterator;
-
-       return (ISC_R_SUCCESS);
-}
-
-static bool
-ispersistent(dns_db_t *db) {
-       UNUSED(db);
-       return (true);
-}
-
-static dns_dbmethods_t sdb_methods = {
-       .destroy = destroy,
-       .currentversion = currentversion,
-       .attachversion = attachversion,
-       .closeversion = closeversion,
-       .attachnode = attachnode,
-       .detachnode = detachnode,
-       .findrdataset = findrdataset,
-       .allrdatasets = allrdatasets,
-       .ispersistent = ispersistent,
-       .getoriginnode = getoriginnode,
-       .findnodeext = findnodeext,
-       .findext = findext,
-};
-
-static isc_result_t
-create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
-       dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
-       void *driverarg, dns_db_t **dbp) {
-       dns_sdb_t *sdb = NULL;
-       isc_result_t result;
-       char zonestr[DNS_NAME_MAXTEXT + 1];
-       isc_buffer_t b;
-       dns_sdbimplementation_t *imp = NULL;
-
-       REQUIRE(driverarg != NULL);
-
-       imp = driverarg;
-
-       if (type != dns_dbtype_zone) {
-               return (ISC_R_NOTIMPLEMENTED);
-       }
-
-       sdb = isc_mem_get(mctx, sizeof(*sdb));
-       *sdb = (dns_sdb_t){
-               .common = { .methods = &sdb_methods, .rdclass = rdclass },
-               .implementation = imp,
-       };
-
-       dns_name_init(&sdb->common.origin, NULL);
-
-       isc_mem_attach(mctx, &sdb->common.mctx);
-
-       result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
-       if (result != ISC_R_SUCCESS) {
-               goto cleanup_lock;
-       }
-
-       isc_buffer_init(&b, zonestr, sizeof(zonestr));
-       result = dns_name_totext(origin, true, &b);
-       if (result != ISC_R_SUCCESS) {
-               goto cleanup_origin;
-       }
-       isc_buffer_putuint8(&b, 0);
-
-       sdb->zone = isc_mem_strdup(mctx, zonestr);
-
-       if (imp->methods->create != NULL) {
-               LOCK(&sdb->implementation->driverlock);
-               result = imp->methods->create(sdb->zone, argc, argv,
-                                             imp->driverdata, &sdb->dbdata);
-               UNLOCK(&sdb->implementation->driverlock);
-               if (result != ISC_R_SUCCESS) {
-                       goto cleanup_zonestr;
-               }
-       }
-
-       isc_refcount_init(&sdb->common.references, 1);
-
-       sdb->common.magic = DNS_DB_MAGIC;
-       sdb->common.impmagic = SDB_MAGIC;
-
-       *dbp = (dns_db_t *)sdb;
-
-       return (ISC_R_SUCCESS);
-
-cleanup_zonestr:
-       isc_mem_free(mctx, sdb->zone);
-cleanup_origin:
-       dns_name_free(&sdb->common.origin, mctx);
-cleanup_lock:
-       isc_mem_putanddetach(&mctx, sdb, sizeof(dns_sdb_t));
-
-       return (result);
-}
-
-/*
- * Rdataset Methods
- */
-
-static void
-disassociate(dns_rdataset_t *rdataset) {
-       dns_dbnode_t *node = rdataset->private5;
-       dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
-       dns_db_t *db = (dns_db_t *)sdbnode->sdb;
-
-       detachnode(db, &node);
-       dns_rdatalist_disassociate(rdataset);
-}
-
-static void
-rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
-       dns_dbnode_t *node = source->private5;
-       dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
-       dns_db_t *db = (dns_db_t *)sdbnode->sdb;
-       dns_dbnode_t *tempdb = NULL;
-
-       dns_rdatalist_clone(source, target);
-       attachnode(db, node, &tempdb);
-       source->private5 = tempdb;
-}
-
-static dns_rdatasetmethods_t sdb_rdataset_methods = {
-       .disassociate = disassociate,
-       .first = dns_rdatalist_first,
-       .next = dns_rdatalist_next,
-       .current = dns_rdatalist_current,
-       .clone = rdataset_clone,
-       .count = dns_rdatalist_count,
-       .addnoqname = dns_rdatalist_addnoqname,
-       .getnoqname = dns_rdatalist_getnoqname,
-};
-
-static void
-list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
-               dns_rdataset_t *rdataset) {
-       /*
-        * The sdb rdataset is an rdatalist with some additions.
-        *      - private1 & private2 are used by the rdatalist.
-        *      - private3 & private 4 are unused.
-        *      - private5 is the node.
-        */
-
-       dns_rdatalist_tordataset(rdatalist, rdataset);
-
-       rdataset->methods = &sdb_rdataset_methods;
-       dns_db_attachnode(db, node, &rdataset->private5);
-}
-
-/*
- * Rdataset Iterator Methods
- */
-
-static void
-rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
-       sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp);
-       detachnode(sdbiterator->common.db, &sdbiterator->common.node);
-       isc_mem_put(sdbiterator->common.db->mctx, sdbiterator,
-                   sizeof(sdb_rdatasetiter_t));
-       *iteratorp = NULL;
-}
-
-static isc_result_t
-rdatasetiter_first(dns_rdatasetiter_t *iterator) {
-       sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
-       dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node;
-
-       if (ISC_LIST_EMPTY(sdbnode->lists)) {
-               return (ISC_R_NOMORE);
-       }
-       sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists);
-       return (ISC_R_SUCCESS);
-}
-
-static isc_result_t
-rdatasetiter_next(dns_rdatasetiter_t *iterator) {
-       sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
-
-       sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link);
-       if (sdbiterator->current == NULL) {
-               return (ISC_R_NOMORE);
-       } else {
-               return (ISC_R_SUCCESS);
-       }
-}
-
-static void
-rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
-       sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
-
-       list_tordataset(sdbiterator->current, iterator->db, iterator->node,
-                       rdataset);
-}