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