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