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