"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/dns/sdlz.c" (7 Sep 2020, 55070 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


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