"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.17.5/lib/dns/sdlz.c" (4 Sep 2020, 53717 Bytes) of package /linux/misc/dns/bind9/9.17.5/bind-9.17.5.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sdlz.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 9.17.3_vs_9.17.4.

    1 /*
    2  * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*
   13  * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
   14  *
   15  * Permission to use, copy, modify, and distribute this software for any
   16  * purpose with or without fee is hereby granted, provided that the
   17  * above copyright notice and this permission notice appear in all
   18  * copies.
   19  *
   20  * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
   21  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
   23  * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
   24  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
   25  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
   26  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
   27  * USE OR PERFORMANCE OF THIS SOFTWARE.
   28  *
   29  * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
   30  * conceived and contributed by Rob Butler.
   31  *
   32  * Permission to use, copy, modify, and distribute this software for any
   33  * purpose with or without fee is hereby granted, provided that the
   34  * above copyright notice and this permission notice appear in all
   35  * copies.
   36  *
   37  * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
   38  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
   39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
   40  * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
   41  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
   42  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
   43  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
   44  * USE OR PERFORMANCE OF THIS SOFTWARE.
   45  */
   46 
   47 /*! \file */
   48 
   49 #include <inttypes.h>
   50 #include <stdbool.h>
   51 #include <string.h>
   52 
   53 #include <isc/buffer.h>
   54 #include <isc/lex.h>
   55 #include <isc/log.h>
   56 #include <isc/magic.h>
   57 #include <isc/mem.h>
   58 #include <isc/once.h>
   59 #include <isc/print.h>
   60 #include <isc/region.h>
   61 #include <isc/rwlock.h>
   62 #include <isc/string.h>
   63 #include <isc/util.h>
   64 
   65 #include <dns/callbacks.h>
   66 #include <dns/db.h>
   67 #include <dns/dbiterator.h>
   68 #include <dns/dlz.h>
   69 #include <dns/fixedname.h>
   70 #include <dns/log.h>
   71 #include <dns/master.h>
   72 #include <dns/rdata.h>
   73 #include <dns/rdatalist.h>
   74 #include <dns/rdataset.h>
   75 #include <dns/rdatasetiter.h>
   76 #include <dns/rdatatype.h>
   77 #include <dns/result.h>
   78 #include <dns/sdlz.h>
   79 #include <dns/types.h>
   80 
   81 #include "rdatalist_p.h"
   82 
   83 /*
   84  * Private Types
   85  */
   86 
   87 struct dns_sdlzimplementation {
   88     const dns_sdlzmethods_t *methods;
   89     isc_mem_t *mctx;
   90     void *driverarg;
   91     unsigned int flags;
   92     isc_mutex_t driverlock;
   93     dns_dlzimplementation_t *dlz_imp;
   94 };
   95 
   96 struct dns_sdlz_db {
   97     /* Unlocked */
   98     dns_db_t common;
   99     void *dbdata;
  100     dns_sdlzimplementation_t *dlzimp;
  101 
  102     /* Atomic */
  103     isc_refcount_t references;
  104 
  105     /* Locked */
  106     dns_dbversion_t *future_version;
  107     int dummy_version;
  108 };
  109 
  110 struct dns_sdlzlookup {
  111     /* Unlocked */
  112     unsigned int magic;
  113     dns_sdlz_db_t *sdlz;
  114     ISC_LIST(dns_rdatalist_t) lists;
  115     ISC_LIST(isc_buffer_t) buffers;
  116     dns_name_t *name;
  117     ISC_LINK(dns_sdlzlookup_t) link;
  118     dns_rdatacallbacks_t callbacks;
  119 
  120     /* Atomic */
  121     isc_refcount_t references;
  122 };
  123 
  124 typedef struct dns_sdlzlookup dns_sdlznode_t;
  125 
  126 struct dns_sdlzallnodes {
  127     dns_dbiterator_t common;
  128     ISC_LIST(dns_sdlznode_t) nodelist;
  129     dns_sdlznode_t *current;
  130     dns_sdlznode_t *origin;
  131 };
  132 
  133 typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
  134 
  135 typedef struct sdlz_rdatasetiter {
  136     dns_rdatasetiter_t common;
  137     dns_rdatalist_t *current;
  138 } sdlz_rdatasetiter_t;
  139 
  140 #define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S')
  141 
  142 /*
  143  * Note that "impmagic" is not the first four bytes of the struct, so
  144  * ISC_MAGIC_VALID cannot be used.
  145  */
  146 
  147 #define VALID_SDLZDB(sdlzdb) \
  148     ((sdlzdb) != NULL && (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
  149 
  150 #define SDLZLOOKUP_MAGIC    ISC_MAGIC('D', 'L', 'Z', 'L')
  151 #define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
  152 #define VALID_SDLZNODE(sdlzn)   VALID_SDLZLOOKUP(sdlzn)
  153 
  154 /* These values are taken from RFC 1537 */
  155 #define SDLZ_DEFAULT_REFRESH 28800U  /* 8 hours */
  156 #define SDLZ_DEFAULT_RETRY   7200U   /* 2 hours */
  157 #define SDLZ_DEFAULT_EXPIRE  604800U /* 7 days */
  158 #define SDLZ_DEFAULT_MINIMUM 86400U  /* 1 day */
  159 
  160 /* This is a reasonable value */
  161 #define SDLZ_DEFAULT_TTL (60 * 60 * 24)
  162 
  163 #ifdef __COVERITY__
  164 #define MAYBE_LOCK(imp)   LOCK(&imp->driverlock)
  165 #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
  166 #else /* ifdef __COVERITY__ */
  167 #define MAYBE_LOCK(imp)                                     \
  168     do {                                                \
  169         unsigned int flags = imp->flags;            \
  170         if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
  171             LOCK(&imp->driverlock);             \
  172     } while (0)
  173 
  174 #define MAYBE_UNLOCK(imp)                                   \
  175     do {                                                \
  176         unsigned int flags = imp->flags;            \
  177         if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
  178             UNLOCK(&imp->driverlock);           \
  179     } while (0)
  180 #endif /* ifdef __COVERITY__ */
  181 
  182 /*
  183  * Forward references.
  184  */
  185 static isc_result_t
  186 getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
  187         unsigned int options, dns_clientinfomethods_t *methods,
  188         dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep);
  189 
  190 static void
  191 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
  192         dns_rdataset_t *rdataset);
  193 
  194 static void
  195 detachnode(dns_db_t *db, dns_dbnode_t **targetp);
  196 
  197 static void
  198 dbiterator_destroy(dns_dbiterator_t **iteratorp);
  199 static isc_result_t
  200 dbiterator_first(dns_dbiterator_t *iterator);
  201 static isc_result_t
  202 dbiterator_last(dns_dbiterator_t *iterator);
  203 static isc_result_t
  204 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name);
  205 static isc_result_t
  206 dbiterator_prev(dns_dbiterator_t *iterator);
  207 static isc_result_t
  208 dbiterator_next(dns_dbiterator_t *iterator);
  209 static isc_result_t
  210 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
  211            dns_name_t *name);
  212 static isc_result_t
  213 dbiterator_pause(dns_dbiterator_t *iterator);
  214 static isc_result_t
  215 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
  216 
  217 static dns_dbiteratormethods_t dbiterator_methods = {
  218     dbiterator_destroy, dbiterator_first, dbiterator_last,
  219     dbiterator_seek,    dbiterator_prev,  dbiterator_next,
  220     dbiterator_current, dbiterator_pause, dbiterator_origin
  221 };
  222 
  223 /*
  224  * Utility functions
  225  */
  226 
  227 /*
  228  * Log a message at the given level
  229  */
  230 static void
  231 sdlz_log(int level, const char *fmt, ...) {
  232     va_list ap;
  233     va_start(ap, fmt);
  234     isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ,
  235                ISC_LOG_DEBUG(level), fmt, ap);
  236     va_end(ap);
  237 }
  238 
  239 /*% Converts the input string to lowercase, in place. */
  240 static void
  241 dns_sdlz_tolower(char *str) {
  242     unsigned int len = strlen(str);
  243     unsigned int i;
  244 
  245     for (i = 0; i < len; i++) {
  246         if (str[i] >= 'A' && str[i] <= 'Z') {
  247             str[i] += 32;
  248         }
  249     }
  250 }
  251 
  252 static inline unsigned int
  253 initial_size(const char *data) {
  254     unsigned int len = (strlen(data) / 64) + 1;
  255     return (len * 64 + 64);
  256 }
  257 
  258 /*
  259  * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
  260  * driver interface.  See the SDB driver interface documentation for more info.
  261  */
  262 
  263 static void
  264 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
  265     sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)(*iteratorp);
  266 
  267     detachnode(sdlziterator->common.db, &sdlziterator->common.node);
  268     isc_mem_put(sdlziterator->common.db->mctx, sdlziterator,
  269             sizeof(sdlz_rdatasetiter_t));
  270     *iteratorp = NULL;
  271 }
  272 
  273 static isc_result_t
  274 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
  275     sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
  276     dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node;
  277 
  278     if (ISC_LIST_EMPTY(sdlznode->lists)) {
  279         return (ISC_R_NOMORE);
  280     }
  281     sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
  282     return (ISC_R_SUCCESS);
  283 }
  284 
  285 static isc_result_t
  286 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
  287     sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
  288 
  289     sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
  290     if (sdlziterator->current == NULL) {
  291         return (ISC_R_NOMORE);
  292     } else {
  293         return (ISC_R_SUCCESS);
  294     }
  295 }
  296 
  297 static void
  298 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
  299     sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
  300 
  301     list_tordataset(sdlziterator->current, iterator->db, iterator->node,
  302             rdataset);
  303 }
  304 
  305 static dns_rdatasetitermethods_t rdatasetiter_methods = {
  306     rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next,
  307     rdatasetiter_current
  308 };
  309 
  310 /*
  311  * DB routines. These methods were "borrowed" from the SDB driver interface.
  312  * See the SDB driver interface documentation for more info.
  313  */
  314 
  315 static void
  316 attach(dns_db_t *source, dns_db_t **targetp) {
  317     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)source;
  318 
  319     REQUIRE(VALID_SDLZDB(sdlz));
  320 
  321     isc_refcount_increment(&sdlz->references);
  322 
  323     *targetp = source;
  324 }
  325 
  326 static void
  327 destroy(dns_sdlz_db_t *sdlz) {
  328     sdlz->common.magic = 0;
  329     sdlz->common.impmagic = 0;
  330 
  331     dns_name_free(&sdlz->common.origin, sdlz->common.mctx);
  332 
  333     isc_refcount_destroy(&sdlz->references);
  334     isc_mem_putanddetach(&sdlz->common.mctx, sdlz, sizeof(dns_sdlz_db_t));
  335 }
  336 
  337 static void
  338 detach(dns_db_t **dbp) {
  339     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
  340 
  341     REQUIRE(VALID_SDLZDB(sdlz));
  342 
  343     *dbp = NULL;
  344 
  345     if (isc_refcount_decrement(&sdlz->references) == 1) {
  346         destroy(sdlz);
  347     }
  348 }
  349 
  350 static isc_result_t
  351 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
  352     UNUSED(db);
  353     UNUSED(callbacks);
  354     return (ISC_R_NOTIMPLEMENTED);
  355 }
  356 
  357 static isc_result_t
  358 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
  359     UNUSED(db);
  360     UNUSED(callbacks);
  361     return (ISC_R_NOTIMPLEMENTED);
  362 }
  363 
  364 static isc_result_t
  365 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
  366      dns_masterformat_t masterformat) {
  367     UNUSED(db);
  368     UNUSED(version);
  369     UNUSED(filename);
  370     UNUSED(masterformat);
  371     return (ISC_R_NOTIMPLEMENTED);
  372 }
  373 
  374 static void
  375 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
  376     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  377     REQUIRE(VALID_SDLZDB(sdlz));
  378     REQUIRE(versionp != NULL && *versionp == NULL);
  379 
  380     *versionp = (void *)&sdlz->dummy_version;
  381     return;
  382 }
  383 
  384 static isc_result_t
  385 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
  386     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  387     char origin[DNS_NAME_MAXTEXT + 1];
  388     isc_result_t result;
  389 
  390     REQUIRE(VALID_SDLZDB(sdlz));
  391 
  392     if (sdlz->dlzimp->methods->newversion == NULL) {
  393         return (ISC_R_NOTIMPLEMENTED);
  394     }
  395 
  396     dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
  397 
  398     result = sdlz->dlzimp->methods->newversion(
  399         origin, sdlz->dlzimp->driverarg, sdlz->dbdata, versionp);
  400     if (result != ISC_R_SUCCESS) {
  401         sdlz_log(ISC_LOG_ERROR,
  402              "sdlz newversion on origin %s failed : %s", origin,
  403              isc_result_totext(result));
  404         return (result);
  405     }
  406 
  407     sdlz->future_version = *versionp;
  408     return (ISC_R_SUCCESS);
  409 }
  410 
  411 static void
  412 attachversion(dns_db_t *db, dns_dbversion_t *source,
  413           dns_dbversion_t **targetp) {
  414     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  415 
  416     REQUIRE(VALID_SDLZDB(sdlz));
  417     REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version);
  418 
  419     *targetp = source;
  420 }
  421 
  422 static void
  423 closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
  424     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  425     char origin[DNS_NAME_MAXTEXT + 1];
  426 
  427     REQUIRE(VALID_SDLZDB(sdlz));
  428     REQUIRE(versionp != NULL);
  429 
  430     if (*versionp == (void *)&sdlz->dummy_version) {
  431         *versionp = NULL;
  432         return;
  433     }
  434 
  435     REQUIRE(*versionp == sdlz->future_version);
  436     REQUIRE(sdlz->dlzimp->methods->closeversion != NULL);
  437 
  438     dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
  439 
  440     sdlz->dlzimp->methods->closeversion(origin, commit,
  441                         sdlz->dlzimp->driverarg,
  442                         sdlz->dbdata, versionp);
  443     if (*versionp != NULL) {
  444         sdlz_log(ISC_LOG_ERROR, "sdlz closeversion on origin %s failed",
  445              origin);
  446     }
  447 
  448     sdlz->future_version = NULL;
  449 }
  450 
  451 static isc_result_t
  452 createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
  453     dns_sdlznode_t *node;
  454 
  455     node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
  456 
  457     node->sdlz = NULL;
  458     attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz);
  459     ISC_LIST_INIT(node->lists);
  460     ISC_LIST_INIT(node->buffers);
  461     ISC_LINK_INIT(node, link);
  462     node->name = NULL;
  463     dns_rdatacallbacks_init(&node->callbacks);
  464 
  465     isc_refcount_init(&node->references, 1);
  466     node->magic = SDLZLOOKUP_MAGIC;
  467 
  468     *nodep = node;
  469     return (ISC_R_SUCCESS);
  470 }
  471 
  472 static void
  473 destroynode(dns_sdlznode_t *node) {
  474     dns_rdatalist_t *list;
  475     dns_rdata_t *rdata;
  476     isc_buffer_t *b;
  477     dns_sdlz_db_t *sdlz;
  478     dns_db_t *db;
  479     isc_mem_t *mctx;
  480 
  481     isc_refcount_destroy(&node->references);
  482 
  483     sdlz = node->sdlz;
  484     mctx = sdlz->common.mctx;
  485 
  486     while (!ISC_LIST_EMPTY(node->lists)) {
  487         list = ISC_LIST_HEAD(node->lists);
  488         while (!ISC_LIST_EMPTY(list->rdata)) {
  489             rdata = ISC_LIST_HEAD(list->rdata);
  490             ISC_LIST_UNLINK(list->rdata, rdata, link);
  491             isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
  492         }
  493         ISC_LIST_UNLINK(node->lists, list, link);
  494         isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
  495     }
  496 
  497     while (!ISC_LIST_EMPTY(node->buffers)) {
  498         b = ISC_LIST_HEAD(node->buffers);
  499         ISC_LIST_UNLINK(node->buffers, b, link);
  500         isc_buffer_free(&b);
  501     }
  502 
  503     if (node->name != NULL) {
  504         dns_name_free(node->name, mctx);
  505         isc_mem_put(mctx, node->name, sizeof(dns_name_t));
  506     }
  507 
  508     node->magic = 0;
  509     isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
  510     db = &sdlz->common;
  511     detach(&db);
  512 }
  513 
  514 static isc_result_t
  515 getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
  516         unsigned int options, dns_clientinfomethods_t *methods,
  517         dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) {
  518     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  519     dns_sdlznode_t *node = NULL;
  520     isc_result_t result;
  521     isc_buffer_t b;
  522     char namestr[DNS_NAME_MAXTEXT + 1];
  523     isc_buffer_t b2;
  524     char zonestr[DNS_NAME_MAXTEXT + 1];
  525     bool isorigin;
  526     dns_sdlzauthorityfunc_t authority;
  527 
  528     REQUIRE(VALID_SDLZDB(sdlz));
  529     REQUIRE(nodep != NULL && *nodep == NULL);
  530 
  531     if (sdlz->dlzimp->methods->newversion == NULL) {
  532         REQUIRE(!create);
  533     }
  534 
  535     isc_buffer_init(&b, namestr, sizeof(namestr));
  536     if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
  537         dns_name_t relname;
  538         unsigned int labels;
  539 
  540         labels = dns_name_countlabels(name) -
  541              dns_name_countlabels(&sdlz->common.origin);
  542         dns_name_init(&relname, NULL);
  543         dns_name_getlabelsequence(name, 0, labels, &relname);
  544         result = dns_name_totext(&relname, true, &b);
  545         if (result != ISC_R_SUCCESS) {
  546             return (result);
  547         }
  548     } else {
  549         result = dns_name_totext(name, true, &b);
  550         if (result != ISC_R_SUCCESS) {
  551             return (result);
  552         }
  553     }
  554     isc_buffer_putuint8(&b, 0);
  555 
  556     isc_buffer_init(&b2, zonestr, sizeof(zonestr));
  557     result = dns_name_totext(&sdlz->common.origin, true, &b2);
  558     if (result != ISC_R_SUCCESS) {
  559         return (result);
  560     }
  561     isc_buffer_putuint8(&b2, 0);
  562 
  563     result = createnode(sdlz, &node);
  564     if (result != ISC_R_SUCCESS) {
  565         return (result);
  566     }
  567 
  568     isorigin = dns_name_equal(name, &sdlz->common.origin);
  569 
  570     /* make sure strings are always lowercase */
  571     dns_sdlz_tolower(zonestr);
  572     dns_sdlz_tolower(namestr);
  573 
  574     MAYBE_LOCK(sdlz->dlzimp);
  575 
  576     /* try to lookup the host (namestr) */
  577     result = sdlz->dlzimp->methods->lookup(
  578         zonestr, namestr, sdlz->dlzimp->driverarg, sdlz->dbdata, node,
  579         methods, clientinfo);
  580 
  581     /*
  582      * If the name was not found and DNS_DBFIND_NOWILD is not
  583      * set, then we try to find a wildcard entry.
  584      *
  585      * If DNS_DBFIND_NOZONECUT is set and there are multiple
  586      * levels between the host and the zone origin, we also look
  587      * for wildcards at each level.
  588      */
  589     if (result == ISC_R_NOTFOUND && !create &&
  590         (options & DNS_DBFIND_NOWILD) == 0) {
  591         unsigned int i, dlabels, nlabels;
  592 
  593         nlabels = dns_name_countlabels(name);
  594         dlabels = nlabels - dns_name_countlabels(&sdlz->common.origin);
  595         for (i = 0; i < dlabels; i++) {
  596             char wildstr[DNS_NAME_MAXTEXT + 1];
  597             dns_fixedname_t fixed;
  598             const dns_name_t *wild;
  599 
  600             dns_fixedname_init(&fixed);
  601             if (i == dlabels - 1) {
  602                 wild = dns_wildcardname;
  603             } else {
  604                 dns_name_t *fname;
  605                 fname = dns_fixedname_name(&fixed);
  606                 dns_name_getlabelsequence(
  607                     name, i + 1, dlabels - i - 1, fname);
  608                 result = dns_name_concatenate(
  609                     dns_wildcardname, fname, fname, NULL);
  610                 if (result != ISC_R_SUCCESS) {
  611                     MAYBE_UNLOCK(sdlz->dlzimp);
  612                     return (result);
  613                 }
  614                 wild = fname;
  615             }
  616 
  617             isc_buffer_init(&b, wildstr, sizeof(wildstr));
  618             result = dns_name_totext(wild, true, &b);
  619             if (result != ISC_R_SUCCESS) {
  620                 MAYBE_UNLOCK(sdlz->dlzimp);
  621                 return (result);
  622             }
  623             isc_buffer_putuint8(&b, 0);
  624 
  625             result = sdlz->dlzimp->methods->lookup(
  626                 zonestr, wildstr, sdlz->dlzimp->driverarg,
  627                 sdlz->dbdata, node, methods, clientinfo);
  628             if (result == ISC_R_SUCCESS) {
  629                 break;
  630             }
  631         }
  632     }
  633 
  634     MAYBE_UNLOCK(sdlz->dlzimp);
  635 
  636     if (result == ISC_R_NOTFOUND && (isorigin || create)) {
  637         result = ISC_R_SUCCESS;
  638     }
  639 
  640     if (result != ISC_R_SUCCESS) {
  641         isc_refcount_decrementz(&node->references);
  642         destroynode(node);
  643         return (result);
  644     }
  645 
  646     if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
  647         MAYBE_LOCK(sdlz->dlzimp);
  648         authority = sdlz->dlzimp->methods->authority;
  649         result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
  650                       sdlz->dbdata, node);
  651         MAYBE_UNLOCK(sdlz->dlzimp);
  652         if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
  653             isc_refcount_decrementz(&node->references);
  654             destroynode(node);
  655             return (result);
  656         }
  657     }
  658 
  659     if (node->name == NULL) {
  660         node->name = isc_mem_get(sdlz->common.mctx, sizeof(dns_name_t));
  661         dns_name_init(node->name, NULL);
  662         dns_name_dup(name, sdlz->common.mctx, node->name);
  663     }
  664 
  665     *nodep = node;
  666     return (ISC_R_SUCCESS);
  667 }
  668 
  669 static isc_result_t
  670 findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
  671         dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
  672         dns_dbnode_t **nodep) {
  673     return (getnodedata(db, name, create, 0, methods, clientinfo, nodep));
  674 }
  675 
  676 static isc_result_t
  677 findnode(dns_db_t *db, const dns_name_t *name, bool create,
  678      dns_dbnode_t **nodep) {
  679     return (getnodedata(db, name, create, 0, NULL, NULL, nodep));
  680 }
  681 
  682 static isc_result_t
  683 findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
  684         isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
  685         dns_name_t *dcname, dns_rdataset_t *rdataset,
  686         dns_rdataset_t *sigrdataset) {
  687     UNUSED(db);
  688     UNUSED(name);
  689     UNUSED(options);
  690     UNUSED(now);
  691     UNUSED(nodep);
  692     UNUSED(foundname);
  693     UNUSED(dcname);
  694     UNUSED(rdataset);
  695     UNUSED(sigrdataset);
  696 
  697     return (ISC_R_NOTIMPLEMENTED);
  698 }
  699 
  700 static void
  701 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
  702     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  703     dns_sdlznode_t *node = (dns_sdlznode_t *)source;
  704 
  705     REQUIRE(VALID_SDLZDB(sdlz));
  706 
  707     UNUSED(sdlz);
  708 
  709     isc_refcount_increment(&node->references);
  710 
  711     *targetp = source;
  712 }
  713 
  714 static void
  715 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
  716     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  717     dns_sdlznode_t *node;
  718 
  719     REQUIRE(VALID_SDLZDB(sdlz));
  720     REQUIRE(targetp != NULL && *targetp != NULL);
  721 
  722     UNUSED(sdlz);
  723 
  724     node = (dns_sdlznode_t *)(*targetp);
  725     *targetp = NULL;
  726 
  727     if (isc_refcount_decrement(&node->references) == 1) {
  728         destroynode(node);
  729     }
  730 }
  731 
  732 static isc_result_t
  733 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
  734     UNUSED(db);
  735     UNUSED(node);
  736     UNUSED(now);
  737     INSIST(0);
  738     ISC_UNREACHABLE();
  739 }
  740 
  741 static void
  742 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
  743     UNUSED(db);
  744     UNUSED(node);
  745     UNUSED(out);
  746     return;
  747 }
  748 
  749 static isc_result_t
  750 createiterator(dns_db_t *db, unsigned int options,
  751            dns_dbiterator_t **iteratorp) {
  752     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  753     sdlz_dbiterator_t *sdlziter;
  754     isc_result_t result;
  755     isc_buffer_t b;
  756     char zonestr[DNS_NAME_MAXTEXT + 1];
  757 
  758     REQUIRE(VALID_SDLZDB(sdlz));
  759 
  760     if (sdlz->dlzimp->methods->allnodes == NULL) {
  761         return (ISC_R_NOTIMPLEMENTED);
  762     }
  763 
  764     if ((options & DNS_DB_NSEC3ONLY) != 0 ||
  765         (options & DNS_DB_NONSEC3) != 0) {
  766         return (ISC_R_NOTIMPLEMENTED);
  767     }
  768 
  769     isc_buffer_init(&b, zonestr, sizeof(zonestr));
  770     result = dns_name_totext(&sdlz->common.origin, true, &b);
  771     if (result != ISC_R_SUCCESS) {
  772         return (result);
  773     }
  774     isc_buffer_putuint8(&b, 0);
  775 
  776     sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
  777 
  778     sdlziter->common.methods = &dbiterator_methods;
  779     sdlziter->common.db = NULL;
  780     dns_db_attach(db, &sdlziter->common.db);
  781     sdlziter->common.relative_names = ((options & DNS_DB_RELATIVENAMES) !=
  782                        0);
  783     sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
  784     ISC_LIST_INIT(sdlziter->nodelist);
  785     sdlziter->current = NULL;
  786     sdlziter->origin = NULL;
  787 
  788     /* make sure strings are always lowercase */
  789     dns_sdlz_tolower(zonestr);
  790 
  791     MAYBE_LOCK(sdlz->dlzimp);
  792     result = sdlz->dlzimp->methods->allnodes(
  793         zonestr, sdlz->dlzimp->driverarg, sdlz->dbdata, sdlziter);
  794     MAYBE_UNLOCK(sdlz->dlzimp);
  795     if (result != ISC_R_SUCCESS) {
  796         dns_dbiterator_t *iter = &sdlziter->common;
  797         dbiterator_destroy(&iter);
  798         return (result);
  799     }
  800 
  801     if (sdlziter->origin != NULL) {
  802         ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
  803         ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
  804     }
  805 
  806     *iteratorp = (dns_dbiterator_t *)sdlziter;
  807 
  808     return (ISC_R_SUCCESS);
  809 }
  810 
  811 static isc_result_t
  812 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  813          dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
  814          dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
  815     REQUIRE(VALID_SDLZNODE(node));
  816     dns_rdatalist_t *list;
  817     dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
  818 
  819     UNUSED(db);
  820     UNUSED(version);
  821     UNUSED(covers);
  822     UNUSED(now);
  823     UNUSED(sigrdataset);
  824 
  825     if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig) {
  826         return (ISC_R_NOTIMPLEMENTED);
  827     }
  828 
  829     list = ISC_LIST_HEAD(sdlznode->lists);
  830     while (list != NULL) {
  831         if (list->type == type) {
  832             break;
  833         }
  834         list = ISC_LIST_NEXT(list, link);
  835     }
  836     if (list == NULL) {
  837         return (ISC_R_NOTFOUND);
  838     }
  839 
  840     list_tordataset(list, db, node, rdataset);
  841 
  842     return (ISC_R_SUCCESS);
  843 }
  844 
  845 static isc_result_t
  846 findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
  847     dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
  848     dns_dbnode_t **nodep, dns_name_t *foundname,
  849     dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
  850     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
  851     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  852     dns_dbnode_t *node = NULL;
  853     dns_fixedname_t fname;
  854     dns_rdataset_t xrdataset;
  855     dns_name_t *xname;
  856     unsigned int nlabels, olabels;
  857     isc_result_t result;
  858     unsigned int i;
  859 
  860     REQUIRE(VALID_SDLZDB(sdlz));
  861     REQUIRE(nodep == NULL || *nodep == NULL);
  862     REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version ||
  863         version == sdlz->future_version);
  864 
  865     UNUSED(sdlz);
  866 
  867     if (!dns_name_issubdomain(name, &db->origin)) {
  868         return (DNS_R_NXDOMAIN);
  869     }
  870 
  871     olabels = dns_name_countlabels(&db->origin);
  872     nlabels = dns_name_countlabels(name);
  873 
  874     xname = dns_fixedname_initname(&fname);
  875 
  876     if (rdataset == NULL) {
  877         dns_rdataset_init(&xrdataset);
  878         rdataset = &xrdataset;
  879     }
  880 
  881     result = DNS_R_NXDOMAIN;
  882 
  883     /*
  884      * If we're not walking down searching for zone
  885      * cuts, we can cut straight to the chase
  886      */
  887     if ((options & DNS_DBFIND_NOZONECUT) != 0) {
  888         i = nlabels;
  889         goto search;
  890     }
  891 
  892     for (i = olabels; i <= nlabels; i++) {
  893     search:
  894         /*
  895          * Look up the next label.
  896          */
  897         dns_name_getlabelsequence(name, nlabels - i, i, xname);
  898         result = getnodedata(db, xname, false, options, methods,
  899                      clientinfo, &node);
  900         if (result == ISC_R_NOTFOUND) {
  901             result = DNS_R_NXDOMAIN;
  902             continue;
  903         } else if (result != ISC_R_SUCCESS) {
  904             break;
  905         }
  906 
  907         /*
  908          * Look for a DNAME at the current label, unless this is
  909          * the qname.
  910          */
  911         if (i < nlabels) {
  912             result = findrdataset(db, node, version,
  913                           dns_rdatatype_dname, 0, now,
  914                           rdataset, sigrdataset);
  915             if (result == ISC_R_SUCCESS) {
  916                 result = DNS_R_DNAME;
  917                 break;
  918             }
  919         }
  920 
  921         /*
  922          * Look for an NS at the current label, unless this is the
  923          * origin, glue is ok, or there are known to be no zone cuts.
  924          */
  925         if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0 &&
  926             (options & DNS_DBFIND_NOZONECUT) == 0)
  927         {
  928             result = findrdataset(db, node, version,
  929                           dns_rdatatype_ns, 0, now,
  930                           rdataset, sigrdataset);
  931 
  932             if (result == ISC_R_SUCCESS && i == nlabels &&
  933                 type == dns_rdatatype_any) {
  934                 result = DNS_R_ZONECUT;
  935                 dns_rdataset_disassociate(rdataset);
  936                 if (sigrdataset != NULL &&
  937                     dns_rdataset_isassociated(sigrdataset)) {
  938                     dns_rdataset_disassociate(sigrdataset);
  939                 }
  940                 break;
  941             } else if (result == ISC_R_SUCCESS) {
  942                 result = DNS_R_DELEGATION;
  943                 break;
  944             }
  945         }
  946 
  947         /*
  948          * If the current name is not the qname, add another label
  949          * and try again.
  950          */
  951         if (i < nlabels) {
  952             detachnode(db, &node);
  953             node = NULL;
  954             continue;
  955         }
  956 
  957         /*
  958          * If we're looking for ANY, we're done.
  959          */
  960         if (type == dns_rdatatype_any) {
  961             result = ISC_R_SUCCESS;
  962             break;
  963         }
  964 
  965         /*
  966          * Look for the qtype.
  967          */
  968         result = findrdataset(db, node, version, type, 0, now, rdataset,
  969                       sigrdataset);
  970         if (result == ISC_R_SUCCESS) {
  971             break;
  972         }
  973 
  974         /*
  975          * Look for a CNAME
  976          */
  977         if (type != dns_rdatatype_cname) {
  978             result = findrdataset(db, node, version,
  979                           dns_rdatatype_cname, 0, now,
  980                           rdataset, sigrdataset);
  981             if (result == ISC_R_SUCCESS) {
  982                 result = DNS_R_CNAME;
  983                 break;
  984             }
  985         }
  986 
  987         result = DNS_R_NXRRSET;
  988         break;
  989     }
  990 
  991     if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) {
  992         dns_rdataset_disassociate(rdataset);
  993     }
  994 
  995     if (foundname != NULL) {
  996         dns_name_copynf(xname, foundname);
  997     }
  998 
  999     if (nodep != NULL) {
 1000         *nodep = node;
 1001     } else if (node != NULL) {
 1002         detachnode(db, &node);
 1003     }
 1004 
 1005     return (result);
 1006 }
 1007 
 1008 static isc_result_t
 1009 find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
 1010      dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
 1011      dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset,
 1012      dns_rdataset_t *sigrdataset) {
 1013     return (findext(db, name, version, type, options, now, nodep, foundname,
 1014             NULL, NULL, rdataset, sigrdataset));
 1015 }
 1016 
 1017 static isc_result_t
 1018 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
 1019          isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) {
 1020     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
 1021     sdlz_rdatasetiter_t *iterator;
 1022 
 1023     REQUIRE(VALID_SDLZDB(sdlz));
 1024 
 1025     REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version ||
 1026         version == sdlz->future_version);
 1027 
 1028     UNUSED(version);
 1029     UNUSED(now);
 1030 
 1031     iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
 1032 
 1033     iterator->common.magic = DNS_RDATASETITER_MAGIC;
 1034     iterator->common.methods = &rdatasetiter_methods;
 1035     iterator->common.db = db;
 1036     iterator->common.node = NULL;
 1037     attachnode(db, node, &iterator->common.node);
 1038     iterator->common.version = version;
 1039     iterator->common.now = now;
 1040 
 1041     *iteratorp = (dns_rdatasetiter_t *)iterator;
 1042 
 1043     return (ISC_R_SUCCESS);
 1044 }
 1045 
 1046 static isc_result_t
 1047 modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
 1048         dns_rdataset_t *rdataset, unsigned int options,
 1049         dns_sdlzmodrdataset_t mod_function) {
 1050     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
 1051     dns_master_style_t *style = NULL;
 1052     isc_result_t result;
 1053     isc_buffer_t *buffer = NULL;
 1054     isc_mem_t *mctx;
 1055     dns_sdlznode_t *sdlznode;
 1056     char *rdatastr = NULL;
 1057     char name[DNS_NAME_MAXTEXT + 1];
 1058 
 1059     REQUIRE(VALID_SDLZDB(sdlz));
 1060 
 1061     if (mod_function == NULL) {
 1062         return (ISC_R_NOTIMPLEMENTED);
 1063     }
 1064 
 1065     sdlznode = (dns_sdlznode_t *)node;
 1066 
 1067     UNUSED(options);
 1068 
 1069     dns_name_format(sdlznode->name, name, sizeof(name));
 1070 
 1071     mctx = sdlz->common.mctx;
 1072 
 1073     isc_buffer_allocate(mctx, &buffer, 1024);
 1074 
 1075     result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, 0xffffffff,
 1076                     mctx);
 1077     if (result != ISC_R_SUCCESS) {
 1078         goto cleanup;
 1079     }
 1080 
 1081     result = dns_master_rdatasettotext(sdlznode->name, rdataset, style,
 1082                        NULL, buffer);
 1083     if (result != ISC_R_SUCCESS) {
 1084         goto cleanup;
 1085     }
 1086 
 1087     if (isc_buffer_usedlength(buffer) < 1) {
 1088         result = ISC_R_BADADDRESSFORM;
 1089         goto cleanup;
 1090     }
 1091 
 1092     rdatastr = isc_buffer_base(buffer);
 1093     if (rdatastr == NULL) {
 1094         result = ISC_R_NOMEMORY;
 1095         goto cleanup;
 1096     }
 1097     rdatastr[isc_buffer_usedlength(buffer) - 1] = 0;
 1098 
 1099     MAYBE_LOCK(sdlz->dlzimp);
 1100     result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg,
 1101                   sdlz->dbdata, version);
 1102     MAYBE_UNLOCK(sdlz->dlzimp);
 1103 
 1104 cleanup:
 1105     isc_buffer_free(&buffer);
 1106     if (style != NULL) {
 1107         dns_master_styledestroy(&style, mctx);
 1108     }
 1109 
 1110     return (result);
 1111 }
 1112 
 1113 static isc_result_t
 1114 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
 1115         isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
 1116         dns_rdataset_t *addedrdataset) {
 1117     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
 1118     isc_result_t result;
 1119 
 1120     UNUSED(now);
 1121     UNUSED(addedrdataset);
 1122     REQUIRE(VALID_SDLZDB(sdlz));
 1123 
 1124     if (sdlz->dlzimp->methods->addrdataset == NULL) {
 1125         return (ISC_R_NOTIMPLEMENTED);
 1126     }
 1127 
 1128     result = modrdataset(db, node, version, rdataset, options,
 1129                  sdlz->dlzimp->methods->addrdataset);
 1130     return (result);
 1131 }
 1132 
 1133 static isc_result_t
 1134 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
 1135          dns_rdataset_t *rdataset, unsigned int options,
 1136          dns_rdataset_t *newrdataset) {
 1137     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
 1138     isc_result_t result;
 1139 
 1140     UNUSED(newrdataset);
 1141     REQUIRE(VALID_SDLZDB(sdlz));
 1142 
 1143     if (sdlz->dlzimp->methods->subtractrdataset == NULL) {
 1144         return (ISC_R_NOTIMPLEMENTED);
 1145     }
 1146 
 1147     result = modrdataset(db, node, version, rdataset, options,
 1148                  sdlz->dlzimp->methods->subtractrdataset);
 1149     return (result);
 1150 }
 1151 
 1152 static isc_result_t
 1153 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
 1154            dns_rdatatype_t type, dns_rdatatype_t covers) {
 1155     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
 1156     char name[DNS_NAME_MAXTEXT + 1];
 1157     char b_type[DNS_RDATATYPE_FORMATSIZE];
 1158     dns_sdlznode_t *sdlznode;
 1159     isc_result_t result;
 1160 
 1161     UNUSED(covers);
 1162 
 1163     REQUIRE(VALID_SDLZDB(sdlz));
 1164 
 1165     if (sdlz->dlzimp->methods->delrdataset == NULL) {
 1166         return (ISC_R_NOTIMPLEMENTED);
 1167     }
 1168 
 1169     sdlznode = (dns_sdlznode_t *)node;
 1170     dns_name_format(sdlznode->name, name, sizeof(name));
 1171     dns_rdatatype_format(type, b_type, sizeof(b_type));
 1172 
 1173     MAYBE_LOCK(sdlz->dlzimp);
 1174     result = sdlz->dlzimp->methods->delrdataset(
 1175         name, b_type, sdlz->dlzimp->driverarg, sdlz->dbdata, version);
 1176     MAYBE_UNLOCK(sdlz->dlzimp);
 1177 
 1178     return (result);
 1179 }
 1180 
 1181 static bool
 1182 issecure(dns_db_t *db) {
 1183     UNUSED(db);
 1184 
 1185     return (false);
 1186 }
 1187 
 1188 static unsigned int
 1189 nodecount(dns_db_t *db) {
 1190     UNUSED(db);
 1191 
 1192     return (0);
 1193 }
 1194 
 1195 static bool
 1196 ispersistent(dns_db_t *db) {
 1197     UNUSED(db);
 1198     return (true);
 1199 }
 1200 
 1201 static void
 1202 overmem(dns_db_t *db, bool over) {
 1203     UNUSED(db);
 1204     UNUSED(over);
 1205 }
 1206 
 1207 static void
 1208 settask(dns_db_t *db, isc_task_t *task) {
 1209     UNUSED(db);
 1210     UNUSED(task);
 1211 }
 1212 
 1213 /*
 1214  * getoriginnode() is used by the update code to find the
 1215  * dns_rdatatype_dnskey record for a zone
 1216  */
 1217 static isc_result_t
 1218 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
 1219     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
 1220     isc_result_t result;
 1221 
 1222     REQUIRE(VALID_SDLZDB(sdlz));
 1223     if (sdlz->dlzimp->methods->newversion == NULL) {
 1224         return (ISC_R_NOTIMPLEMENTED);
 1225     }
 1226 
 1227     result = getnodedata(db, &sdlz->common.origin, false, 0, NULL, NULL,
 1228                  nodep);
 1229     if (result != ISC_R_SUCCESS) {
 1230         sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s",
 1231              isc_result_totext(result));
 1232     }
 1233     return (result);
 1234 }
 1235 
 1236 static dns_dbmethods_t sdlzdb_methods = {
 1237     attach,
 1238     detach,
 1239     beginload,
 1240     endload,
 1241     NULL, /* serialize */
 1242     dump,
 1243     currentversion,
 1244     newversion,
 1245     attachversion,
 1246     closeversion,
 1247     findnode,
 1248     find,
 1249     findzonecut,
 1250     attachnode,
 1251     detachnode,
 1252     expirenode,
 1253     printnode,
 1254     createiterator,
 1255     findrdataset,
 1256     allrdatasets,
 1257     addrdataset,
 1258     subtractrdataset,
 1259     deleterdataset,
 1260     issecure,
 1261     nodecount,
 1262     ispersistent,
 1263     overmem,
 1264     settask,
 1265     getoriginnode,
 1266     NULL, /* transfernode */
 1267     NULL, /* getnsec3parameters */
 1268     NULL, /* findnsec3node */
 1269     NULL, /* setsigningtime */
 1270     NULL, /* getsigningtime */
 1271     NULL, /* resigned */
 1272     NULL, /* isdnssec */
 1273     NULL, /* getrrsetstats */
 1274     NULL, /* rpz_attach */
 1275     NULL, /* rpz_ready */
 1276     findnodeext,
 1277     findext,
 1278     NULL, /* setcachestats */
 1279     NULL, /* hashsize */
 1280     NULL, /* nodefullname */
 1281     NULL, /* getsize */
 1282     NULL, /* setservestalettl */
 1283     NULL, /* getservestalettl */
 1284     NULL, /* setgluecachestats */
 1285     NULL  /* adjusthashsize */
 1286 };
 1287 
 1288 /*
 1289  * Database Iterator Methods.  These methods were "borrowed" from the SDB
 1290  * driver interface.  See the SDB driver interface documentation for more info.
 1291  */
 1292 
 1293 static void
 1294 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
 1295     sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
 1296     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
 1297 
 1298     while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
 1299         dns_sdlznode_t *node;
 1300         node = ISC_LIST_HEAD(sdlziter->nodelist);
 1301         ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
 1302         isc_refcount_decrementz(&node->references);
 1303         destroynode(node);
 1304     }
 1305 
 1306     dns_db_detach(&sdlziter->common.db);
 1307     isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
 1308 
 1309     *iteratorp = NULL;
 1310 }
 1311 
 1312 static isc_result_t
 1313 dbiterator_first(dns_dbiterator_t *iterator) {
 1314     sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
 1315 
 1316     sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
 1317     if (sdlziter->current == NULL) {
 1318         return (ISC_R_NOMORE);
 1319     } else {
 1320         return (ISC_R_SUCCESS);
 1321     }
 1322 }
 1323 
 1324 static isc_result_t
 1325 dbiterator_last(dns_dbiterator_t *iterator) {
 1326     sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
 1327 
 1328     sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
 1329     if (sdlziter->current == NULL) {
 1330         return (ISC_R_NOMORE);
 1331     } else {
 1332         return (ISC_R_SUCCESS);
 1333     }
 1334 }
 1335 
 1336 static isc_result_t
 1337 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) {
 1338     sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
 1339 
 1340     sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
 1341     while (sdlziter->current != NULL) {
 1342         if (dns_name_equal(sdlziter->current->name, name)) {
 1343             return (ISC_R_SUCCESS);
 1344         }
 1345         sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
 1346     }
 1347     return (ISC_R_NOTFOUND);
 1348 }
 1349 
 1350 static isc_result_t
 1351 dbiterator_prev(dns_dbiterator_t *iterator) {
 1352     sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
 1353 
 1354     sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
 1355     if (sdlziter->current == NULL) {
 1356         return (ISC_R_NOMORE);
 1357     } else {
 1358         return (ISC_R_SUCCESS);
 1359     }
 1360 }
 1361 
 1362 static isc_result_t
 1363 dbiterator_next(dns_dbiterator_t *iterator) {
 1364     sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
 1365 
 1366     sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
 1367     if (sdlziter->current == NULL) {
 1368         return (ISC_R_NOMORE);
 1369     } else {
 1370         return (ISC_R_SUCCESS);
 1371     }
 1372 }
 1373 
 1374 static isc_result_t
 1375 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
 1376            dns_name_t *name) {
 1377     sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
 1378 
 1379     attachnode(iterator->db, sdlziter->current, nodep);
 1380     if (name != NULL) {
 1381         dns_name_copynf(sdlziter->current->name, name);
 1382         return (ISC_R_SUCCESS);
 1383     }
 1384     return (ISC_R_SUCCESS);
 1385 }
 1386 
 1387 static isc_result_t
 1388 dbiterator_pause(dns_dbiterator_t *iterator) {
 1389     UNUSED(iterator);
 1390     return (ISC_R_SUCCESS);
 1391 }
 1392 
 1393 static isc_result_t
 1394 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
 1395     UNUSED(iterator);
 1396     dns_name_copynf(dns_rootname, name);
 1397     return (ISC_R_SUCCESS);
 1398 }
 1399 
 1400 /*
 1401  * Rdataset Methods. These methods were "borrowed" from the SDB driver
 1402  * interface.  See the SDB driver interface documentation for more info.
 1403  */
 1404 
 1405 static void
 1406 disassociate(dns_rdataset_t *rdataset) {
 1407     dns_dbnode_t *node = rdataset->private5;
 1408     dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
 1409     dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
 1410 
 1411     detachnode(db, &node);
 1412     isc__rdatalist_disassociate(rdataset);
 1413 }
 1414 
 1415 static void
 1416 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
 1417     dns_dbnode_t *node = source->private5;
 1418     dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
 1419     dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
 1420     dns_dbnode_t *tempdb = NULL;
 1421 
 1422     isc__rdatalist_clone(source, target);
 1423     attachnode(db, node, &tempdb);
 1424     source->private5 = tempdb;
 1425 }
 1426 
 1427 static dns_rdatasetmethods_t rdataset_methods = {
 1428     disassociate,
 1429     isc__rdatalist_first,
 1430     isc__rdatalist_next,
 1431     isc__rdatalist_current,
 1432     rdataset_clone,
 1433     isc__rdatalist_count,
 1434     isc__rdatalist_addnoqname,
 1435     isc__rdatalist_getnoqname,
 1436     NULL, /* addclosest */
 1437     NULL, /* getclosest */
 1438     NULL, /* settrust */
 1439     NULL, /* expire */
 1440     NULL, /* clearprefetch */
 1441     NULL, /* setownercase */
 1442     NULL, /* getownercase */
 1443     NULL  /* addglue */
 1444 };
 1445 
 1446 static void
 1447 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
 1448         dns_rdataset_t *rdataset) {
 1449     /*
 1450      * The sdlz rdataset is an rdatalist with some additions.
 1451      *  - private1 & private2 are used by the rdatalist.
 1452      *  - private3 & private 4 are unused.
 1453      *  - private5 is the node.
 1454      */
 1455 
 1456     /* This should never fail. */
 1457     RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
 1458               ISC_R_SUCCESS);
 1459 
 1460     rdataset->methods = &rdataset_methods;
 1461     dns_db_attachnode(db, node, &rdataset->private5);
 1462 }
 1463 
 1464 /*
 1465  * SDLZ core methods. This is the core of the new DLZ functionality.
 1466  */
 1467 
 1468 /*%
 1469  * Build a 'bind' database driver structure to be returned by
 1470  * either the find zone or the allow zone transfer method.
 1471  * This method is only available in this source file, it is
 1472  * not made available anywhere else.
 1473  */
 1474 
 1475 static isc_result_t
 1476 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
 1477           const dns_name_t *name, dns_rdataclass_t rdclass,
 1478           dns_db_t **dbp) {
 1479     isc_result_t result;
 1480     dns_sdlz_db_t *sdlzdb;
 1481     dns_sdlzimplementation_t *imp;
 1482 
 1483     /* check that things are as we expect */
 1484     REQUIRE(dbp != NULL && *dbp == NULL);
 1485     REQUIRE(name != NULL);
 1486 
 1487     imp = (dns_sdlzimplementation_t *)driverarg;
 1488 
 1489     /* allocate and zero memory for driver structure */
 1490     sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
 1491     memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
 1492 
 1493     /* initialize and set origin */
 1494     dns_name_init(&sdlzdb->common.origin, NULL);
 1495     result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
 1496     if (result != ISC_R_SUCCESS) {
 1497         goto mem_cleanup;
 1498     }
 1499 
 1500     /* set the rest of the database structure attributes */
 1501     sdlzdb->dlzimp = imp;
 1502     sdlzdb->common.methods = &sdlzdb_methods;
 1503     sdlzdb->common.attributes = 0;
 1504     sdlzdb->common.rdclass = rdclass;
 1505     sdlzdb->common.mctx = NULL;
 1506     sdlzdb->dbdata = dbdata;
 1507     isc_refcount_init(&sdlzdb->references, 1);
 1508 
 1509     /* attach to the memory context */
 1510     isc_mem_attach(mctx, &sdlzdb->common.mctx);
 1511 
 1512     /* mark structure as valid */
 1513     sdlzdb->common.magic = DNS_DB_MAGIC;
 1514     sdlzdb->common.impmagic = SDLZDB_MAGIC;
 1515     *dbp = (dns_db_t *)sdlzdb;
 1516 
 1517     return (result);
 1518 mem_cleanup:
 1519     isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
 1520     return (result);
 1521 }
 1522 
 1523 static isc_result_t
 1524 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
 1525              dns_rdataclass_t rdclass, const dns_name_t *name,
 1526              const isc_sockaddr_t *clientaddr, dns_db_t **dbp) {
 1527     isc_buffer_t b;
 1528     isc_buffer_t b2;
 1529     char namestr[DNS_NAME_MAXTEXT + 1];
 1530     char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255."
 1531                    "255") +
 1532                1];
 1533     isc_netaddr_t netaddr;
 1534     isc_result_t result;
 1535     dns_sdlzimplementation_t *imp;
 1536 
 1537     /*
 1538      * Perform checks to make sure data is as we expect it to be.
 1539      */
 1540     REQUIRE(driverarg != NULL);
 1541     REQUIRE(name != NULL);
 1542     REQUIRE(clientaddr != NULL);
 1543     REQUIRE(dbp != NULL && *dbp == NULL);
 1544 
 1545     imp = (dns_sdlzimplementation_t *)driverarg;
 1546 
 1547     /* Convert DNS name to ascii text */
 1548     isc_buffer_init(&b, namestr, sizeof(namestr));
 1549     result = dns_name_totext(name, true, &b);
 1550     if (result != ISC_R_SUCCESS) {
 1551         return (result);
 1552     }
 1553     isc_buffer_putuint8(&b, 0);
 1554 
 1555     /* convert client address to ascii text */
 1556     isc_buffer_init(&b2, clientstr, sizeof(clientstr));
 1557     isc_netaddr_fromsockaddr(&netaddr, clientaddr);
 1558     result = isc_netaddr_totext(&netaddr, &b2);
 1559     if (result != ISC_R_SUCCESS) {
 1560         return (result);
 1561     }
 1562     isc_buffer_putuint8(&b2, 0);
 1563 
 1564     /* make sure strings are always lowercase */
 1565     dns_sdlz_tolower(namestr);
 1566     dns_sdlz_tolower(clientstr);
 1567 
 1568     /* Call SDLZ driver's find zone method */
 1569     if (imp->methods->allowzonexfr != NULL) {
 1570         isc_result_t rresult = ISC_R_SUCCESS;
 1571 
 1572         MAYBE_LOCK(imp);
 1573         result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
 1574                             namestr, clientstr);
 1575         MAYBE_UNLOCK(imp);
 1576         /*
 1577          * if zone is supported and transfers are (or might be)
 1578          * allowed, build a 'bind' database driver
 1579          */
 1580         if (result == ISC_R_SUCCESS || result == ISC_R_DEFAULT) {
 1581             rresult = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
 1582                             name, rdclass, dbp);
 1583         }
 1584         if (rresult != ISC_R_SUCCESS) {
 1585             result = rresult;
 1586         }
 1587         return (result);
 1588     }
 1589 
 1590     return (ISC_R_NOTIMPLEMENTED);
 1591 }
 1592 
 1593 static isc_result_t
 1594 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
 1595            char *argv[], void *driverarg, void **dbdata) {
 1596     dns_sdlzimplementation_t *imp;
 1597     isc_result_t result = ISC_R_NOTFOUND;
 1598 
 1599     /* Write debugging message to log */
 1600     sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
 1601 
 1602     /*
 1603      * Performs checks to make sure data is as we expect it to be.
 1604      */
 1605     REQUIRE(driverarg != NULL);
 1606     REQUIRE(dlzname != NULL);
 1607     REQUIRE(dbdata != NULL);
 1608     UNUSED(mctx);
 1609 
 1610     imp = driverarg;
 1611 
 1612     /* If the create method exists, call it. */
 1613     if (imp->methods->create != NULL) {
 1614         MAYBE_LOCK(imp);
 1615         result = imp->methods->create(dlzname, argc, argv,
 1616                           imp->driverarg, dbdata);
 1617         MAYBE_UNLOCK(imp);
 1618     }
 1619 
 1620     /* Write debugging message to log */
 1621     if (result == ISC_R_SUCCESS) {
 1622         sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
 1623     } else {
 1624         sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
 1625     }
 1626 
 1627     return (result);
 1628 }
 1629 
 1630 static void
 1631 dns_sdlzdestroy(void *driverdata, void **dbdata) {
 1632     dns_sdlzimplementation_t *imp;
 1633 
 1634     /* Write debugging message to log */
 1635     sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
 1636 
 1637     imp = driverdata;
 1638 
 1639     /* If the destroy method exists, call it. */
 1640     if (imp->methods->destroy != NULL) {
 1641         MAYBE_LOCK(imp);
 1642         imp->methods->destroy(imp->driverarg, dbdata);
 1643         MAYBE_UNLOCK(imp);
 1644     }
 1645 }
 1646 
 1647 static isc_result_t
 1648 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
 1649          dns_rdataclass_t rdclass, const dns_name_t *name,
 1650          dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
 1651          dns_db_t **dbp) {
 1652     isc_buffer_t b;
 1653     char namestr[DNS_NAME_MAXTEXT + 1];
 1654     isc_result_t result;
 1655     dns_sdlzimplementation_t *imp;
 1656 
 1657     /*
 1658      * Perform checks to make sure data is as we expect it to be.
 1659      */
 1660     REQUIRE(driverarg != NULL);
 1661     REQUIRE(name != NULL);
 1662     REQUIRE(dbp != NULL && *dbp == NULL);
 1663 
 1664     imp = (dns_sdlzimplementation_t *)driverarg;
 1665 
 1666     /* Convert DNS name to ascii text */
 1667     isc_buffer_init(&b, namestr, sizeof(namestr));
 1668     result = dns_name_totext(name, true, &b);
 1669     if (result != ISC_R_SUCCESS) {
 1670         return (result);
 1671     }
 1672     isc_buffer_putuint8(&b, 0);
 1673 
 1674     /* make sure strings are always lowercase */
 1675     dns_sdlz_tolower(namestr);
 1676 
 1677     /* Call SDLZ driver's find zone method */
 1678     MAYBE_LOCK(imp);
 1679     result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
 1680                     methods, clientinfo);
 1681     MAYBE_UNLOCK(imp);
 1682 
 1683     /*
 1684      * if zone is supported build a 'bind' database driver
 1685      * structure to return
 1686      */
 1687     if (result == ISC_R_SUCCESS) {
 1688         result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
 1689                        rdclass, dbp);
 1690     }
 1691 
 1692     return (result);
 1693 }
 1694 
 1695 static isc_result_t
 1696 dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view,
 1697           dns_dlzdb_t *dlzdb) {
 1698     isc_result_t result;
 1699     dns_sdlzimplementation_t *imp;
 1700 
 1701     REQUIRE(driverarg != NULL);
 1702 
 1703     imp = (dns_sdlzimplementation_t *)driverarg;
 1704 
 1705     /* Call SDLZ driver's configure method */
 1706     if (imp->methods->configure != NULL) {
 1707         MAYBE_LOCK(imp);
 1708         result = imp->methods->configure(view, dlzdb, imp->driverarg,
 1709                          dbdata);
 1710         MAYBE_UNLOCK(imp);
 1711     } else {
 1712         result = ISC_R_SUCCESS;
 1713     }
 1714 
 1715     return (result);
 1716 }
 1717 
 1718 static bool
 1719 dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name,
 1720          const isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
 1721          const dst_key_t *key, void *driverarg, void *dbdata) {
 1722     dns_sdlzimplementation_t *imp;
 1723     char b_signer[DNS_NAME_FORMATSIZE];
 1724     char b_name[DNS_NAME_FORMATSIZE];
 1725     char b_addr[ISC_NETADDR_FORMATSIZE];
 1726     char b_type[DNS_RDATATYPE_FORMATSIZE];
 1727     char b_key[DST_KEY_FORMATSIZE];
 1728     isc_buffer_t *tkey_token = NULL;
 1729     isc_region_t token_region = { NULL, 0 };
 1730     uint32_t token_len = 0;
 1731     bool ret;
 1732 
 1733     REQUIRE(driverarg != NULL);
 1734 
 1735     imp = (dns_sdlzimplementation_t *)driverarg;
 1736     if (imp->methods->ssumatch == NULL) {
 1737         return (false);
 1738     }
 1739 
 1740     /*
 1741      * Format the request elements. sdlz operates on strings, not
 1742      * structures
 1743      */
 1744     if (signer != NULL) {
 1745         dns_name_format(signer, b_signer, sizeof(b_signer));
 1746     } else {
 1747         b_signer[0] = 0;
 1748     }
 1749 
 1750     dns_name_format(name, b_name, sizeof(b_name));
 1751 
 1752     if (tcpaddr != NULL) {
 1753         isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
 1754     } else {
 1755         b_addr[0] = 0;
 1756     }
 1757 
 1758     dns_rdatatype_format(type, b_type, sizeof(b_type));
 1759 
 1760     if (key != NULL) {
 1761         dst_key_format(key, b_key, sizeof(b_key));
 1762         tkey_token = dst_key_tkeytoken(key);
 1763     } else {
 1764         b_key[0] = 0;
 1765     }
 1766 
 1767     if (tkey_token != NULL) {
 1768         isc_buffer_region(tkey_token, &token_region);
 1769         token_len = token_region.length;
 1770     }
 1771 
 1772     MAYBE_LOCK(imp);
 1773     ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
 1774                      token_len,
 1775                      token_len != 0 ? token_region.base : NULL,
 1776                      imp->driverarg, dbdata);
 1777     MAYBE_UNLOCK(imp);
 1778     return (ret);
 1779 }
 1780 
 1781 static dns_dlzmethods_t sdlzmethods = { dns_sdlzcreate,    dns_sdlzdestroy,
 1782                     dns_sdlzfindzone,  dns_sdlzallowzonexfr,
 1783                     dns_sdlzconfigure, dns_sdlzssumatch };
 1784 
 1785 /*
 1786  * Public functions.
 1787  */
 1788 
 1789 isc_result_t
 1790 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
 1791            const char *data) {
 1792     dns_rdatalist_t *rdatalist;
 1793     dns_rdata_t *rdata;
 1794     dns_rdatatype_t typeval;
 1795     isc_consttextregion_t r;
 1796     isc_buffer_t b;
 1797     isc_buffer_t *rdatabuf = NULL;
 1798     isc_lex_t *lex;
 1799     isc_result_t result;
 1800     unsigned int size;
 1801     isc_mem_t *mctx;
 1802     const dns_name_t *origin;
 1803 
 1804     REQUIRE(VALID_SDLZLOOKUP(lookup));
 1805     REQUIRE(type != NULL);
 1806     REQUIRE(data != NULL);
 1807 
 1808     mctx = lookup->sdlz->common.mctx;
 1809 
 1810     r.base = type;
 1811     r.length = strlen(type);
 1812     result = dns_rdatatype_fromtext(&typeval, (void *)&r);
 1813     if (result != ISC_R_SUCCESS) {
 1814         return (result);
 1815     }
 1816 
 1817     rdatalist = ISC_LIST_HEAD(lookup->lists);
 1818     while (rdatalist != NULL) {
 1819         if (rdatalist->type == typeval) {
 1820             break;
 1821         }
 1822         rdatalist = ISC_LIST_NEXT(rdatalist, link);
 1823     }
 1824 
 1825     if (rdatalist == NULL) {
 1826         rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
 1827         dns_rdatalist_init(rdatalist);
 1828         rdatalist->rdclass = lookup->sdlz->common.rdclass;
 1829         rdatalist->type = typeval;
 1830         rdatalist->ttl = ttl;
 1831         ISC_LIST_APPEND(lookup->lists, rdatalist, link);
 1832     } else if (rdatalist->ttl > ttl) {
 1833         /*
 1834          * BIND9 doesn't enforce all RRs in an RRset
 1835          * having the same TTL, as per RFC 2136,
 1836          * section 7.12. If a DLZ backend has
 1837          * different TTLs, then the best
 1838          * we can do is return the lowest.
 1839          */
 1840         rdatalist->ttl = ttl;
 1841     }
 1842 
 1843     rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
 1844     dns_rdata_init(rdata);
 1845 
 1846     if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
 1847         origin = &lookup->sdlz->common.origin;
 1848     } else {
 1849         origin = dns_rootname;
 1850     }
 1851 
 1852     lex = NULL;
 1853     result = isc_lex_create(mctx, 64, &lex);
 1854     if (result != ISC_R_SUCCESS) {
 1855         goto failure;
 1856     }
 1857 
 1858     size = initial_size(data);
 1859     do {
 1860         isc_buffer_constinit(&b, data, strlen(data));
 1861         isc_buffer_add(&b, strlen(data));
 1862 
 1863         result = isc_lex_openbuffer(lex, &b);
 1864         if (result != ISC_R_SUCCESS) {
 1865             goto failure;
 1866         }
 1867 
 1868         rdatabuf = NULL;
 1869         isc_buffer_allocate(mctx, &rdatabuf, size);
 1870 
 1871         result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
 1872                         rdatalist->type, lex, origin, false,
 1873                         mctx, rdatabuf, &lookup->callbacks);
 1874         if (result != ISC_R_SUCCESS) {
 1875             isc_buffer_free(&rdatabuf);
 1876             result = DNS_R_SERVFAIL;
 1877         }
 1878         if (size >= 65535) {
 1879             break;
 1880         }
 1881         size *= 2;
 1882         if (size >= 65535) {
 1883             size = 65535;
 1884         }
 1885     } while (result == ISC_R_NOSPACE);
 1886 
 1887     if (result != ISC_R_SUCCESS) {
 1888         goto failure;
 1889     }
 1890 
 1891     ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
 1892     ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
 1893 
 1894     if (lex != NULL) {
 1895         isc_lex_destroy(&lex);
 1896     }
 1897 
 1898     return (ISC_R_SUCCESS);
 1899 
 1900 failure:
 1901     if (rdatabuf != NULL) {
 1902         isc_buffer_free(&rdatabuf);
 1903     }
 1904     if (lex != NULL) {
 1905         isc_lex_destroy(&lex);
 1906     }
 1907     isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
 1908 
 1909     return (result);
 1910 }
 1911 
 1912 isc_result_t
 1913 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
 1914             const char *type, dns_ttl_t ttl, const char *data) {
 1915     dns_name_t *newname;
 1916     const dns_name_t *origin;
 1917     dns_fixedname_t fnewname;
 1918     dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
 1919     dns_sdlznode_t *sdlznode;
 1920     isc_mem_t *mctx = sdlz->common.mctx;
 1921     isc_buffer_t b;
 1922     isc_result_t result;
 1923 
 1924     newname = dns_fixedname_initname(&fnewname);
 1925 
 1926     if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
 1927         origin = &sdlz->common.origin;
 1928     } else {
 1929         origin = dns_rootname;
 1930     }
 1931     isc_buffer_constinit(&b, name, strlen(name));
 1932     isc_buffer_add(&b, strlen(name));
 1933 
 1934     result = dns_name_fromtext(newname, &b, origin, 0, NULL);
 1935     if (result != ISC_R_SUCCESS) {
 1936         return (result);
 1937     }
 1938 
 1939     if (allnodes->common.relative_names) {
 1940         /* All names are relative to the root */
 1941         unsigned int nlabels = dns_name_countlabels(newname);
 1942         dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
 1943     }
 1944 
 1945     sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
 1946     if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
 1947         sdlznode = NULL;
 1948         result = createnode(sdlz, &sdlznode);
 1949         if (result != ISC_R_SUCCESS) {
 1950             return (result);
 1951         }
 1952         sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
 1953         dns_name_init(sdlznode->name, NULL);
 1954         dns_name_dup(newname, mctx, sdlznode->name);
 1955         ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
 1956         if (allnodes->origin == NULL &&
 1957             dns_name_equal(newname, &sdlz->common.origin)) {
 1958             allnodes->origin = sdlznode;
 1959         }
 1960     }
 1961     return (dns_sdlz_putrr(sdlznode, type, ttl, data));
 1962 }
 1963 
 1964 isc_result_t
 1965 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
 1966         uint32_t serial) {
 1967     char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
 1968     int n;
 1969 
 1970     REQUIRE(mname != NULL);
 1971     REQUIRE(rname != NULL);
 1972 
 1973     n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", mname, rname,
 1974              serial, SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
 1975              SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
 1976     if (n >= (int)sizeof(str) || n < 0) {
 1977         return (ISC_R_NOSPACE);
 1978     }
 1979     return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
 1980 }
 1981 
 1982 isc_result_t
 1983 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
 1984          void *driverarg, unsigned int flags, isc_mem_t *mctx,
 1985          dns_sdlzimplementation_t **sdlzimp) {
 1986     dns_sdlzimplementation_t *imp;
 1987     isc_result_t result;
 1988 
 1989     /*
 1990      * Performs checks to make sure data is as we expect it to be.
 1991      */
 1992     REQUIRE(drivername != NULL);
 1993     REQUIRE(methods != NULL);
 1994     REQUIRE(methods->findzone != NULL);
 1995     REQUIRE(methods->lookup != NULL);
 1996     REQUIRE(mctx != NULL);
 1997     REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
 1998     REQUIRE((flags &
 1999          ~(DNS_SDLZFLAG_RELATIVEOWNER | DNS_SDLZFLAG_RELATIVERDATA |
 2000            DNS_SDLZFLAG_THREADSAFE)) == 0);
 2001 
 2002     /* Write debugging message to log */
 2003     sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
 2004 
 2005     /*
 2006      * Allocate memory for a sdlz_implementation object.  Error if
 2007      * we cannot.
 2008      */
 2009     imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
 2010 
 2011     /* Make sure memory region is set to all 0's */
 2012     memset(imp, 0, sizeof(dns_sdlzimplementation_t));
 2013 
 2014     /* Store the data passed into this method */
 2015     imp->methods = methods;
 2016     imp->driverarg = driverarg;
 2017     imp->flags = flags;
 2018     imp->mctx = NULL;
 2019 
 2020     /* attach the new sdlz_implementation object to a memory context */
 2021     isc_mem_attach(mctx, &imp->mctx);
 2022 
 2023     /*
 2024      * initialize the driver lock, error if we cannot
 2025      * (used if a driver does not support multiple threads)
 2026      */
 2027     isc_mutex_init(&imp->driverlock);
 2028 
 2029     imp->dlz_imp = NULL;
 2030 
 2031     /*
 2032      * register the DLZ driver.  Pass in our "extra" sdlz information as
 2033      * a driverarg.  (that's why we stored the passed in driver arg in our
 2034      * sdlz_implementation structure)  Also, store the dlz_implementation
 2035      * structure in our sdlz_implementation.
 2036      */
 2037     result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
 2038                  &imp->dlz_imp);
 2039 
 2040     /* if registration fails, cleanup and get outta here. */
 2041     if (result != ISC_R_SUCCESS) {
 2042         goto cleanup_mutex;
 2043     }
 2044 
 2045     *sdlzimp = imp;
 2046 
 2047     return (ISC_R_SUCCESS);
 2048 
 2049 cleanup_mutex:
 2050     /* destroy the driver lock, we don't need it anymore */
 2051     isc_mutex_destroy(&imp->driverlock);
 2052 
 2053     /*
 2054      * return the memory back to the available memory pool and
 2055      * remove it from the memory context.
 2056      */
 2057     isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
 2058     return (result);
 2059 }
 2060 
 2061 void
 2062 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
 2063     dns_sdlzimplementation_t *imp;
 2064 
 2065     /* Write debugging message to log */
 2066     sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
 2067 
 2068     /*
 2069      * Performs checks to make sure data is as we expect it to be.
 2070      */
 2071     REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
 2072 
 2073     imp = *sdlzimp;
 2074     *sdlzimp = NULL;
 2075 
 2076     /* Unregister the DLZ driver implementation */
 2077     dns_dlzunregister(&imp->dlz_imp);
 2078 
 2079     /* destroy the driver lock, we don't need it anymore */
 2080     isc_mutex_destroy(&imp->driverlock);
 2081 
 2082     /*
 2083      * return the memory back to the available memory pool and
 2084      * remove it from the memory context.
 2085      */
 2086     isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
 2087 }
 2088 
 2089 isc_result_t
 2090 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
 2091            const dns_name_t *name, dns_db_t **dbp) {
 2092     isc_result_t result;
 2093 
 2094     result = dns_sdlzcreateDBP(dlzdatabase->mctx,
 2095                    dlzdatabase->implementation->driverarg,
 2096                    dlzdatabase->dbdata, name, rdclass, dbp);
 2097     return (result);
 2098 }