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