Home | History | Annotate | Line # | Download | only in dns
sdlz.c revision 1.1.1.3
      1 /*	$NetBSD: sdlz.c,v 1.1.1.3 2019/04/27 23:47:29 christos Exp $	*/
      2 
      3 /*
      4  * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * This Source Code Form is subject to the terms of the Mozilla Public
      7  * License, v. 2.0. If a copy of the MPL was not distributed with this
      8  * file, You can obtain one at 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 
     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/rwlock.h>
     61 #include <isc/string.h>
     62 #include <isc/util.h>
     63 #include <isc/magic.h>
     64 #include <isc/mem.h>
     65 #include <isc/once.h>
     66 #include <isc/print.h>
     67 #include <isc/region.h>
     68 
     69 #include <dns/callbacks.h>
     70 #include <dns/db.h>
     71 #include <dns/dbiterator.h>
     72 #include <dns/dlz.h>
     73 #include <dns/fixedname.h>
     74 #include <dns/log.h>
     75 #include <dns/rdata.h>
     76 #include <dns/rdatalist.h>
     77 #include <dns/rdataset.h>
     78 #include <dns/rdatasetiter.h>
     79 #include <dns/rdatatype.h>
     80 #include <dns/result.h>
     81 #include <dns/master.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 	isc_mutex_t			refcnt_lock;
    106 	/* Locked */
    107 	unsigned int			references;
    108 	dns_dbversion_t			*future_version;
    109 	int				dummy_version;
    110 };
    111 
    112 struct dns_sdlzlookup {
    113 	/* Unlocked */
    114 	unsigned int			magic;
    115 	dns_sdlz_db_t			*sdlz;
    116 	ISC_LIST(dns_rdatalist_t)	lists;
    117 	ISC_LIST(isc_buffer_t)		buffers;
    118 	dns_name_t			*name;
    119 	ISC_LINK(dns_sdlzlookup_t)	link;
    120 	isc_mutex_t			lock;
    121 	dns_rdatacallbacks_t		callbacks;
    122 	/* Locked */
    123 	unsigned int			references;
    124 };
    125 
    126 typedef struct dns_sdlzlookup dns_sdlznode_t;
    127 
    128 struct dns_sdlzallnodes {
    129 	dns_dbiterator_t		common;
    130 	ISC_LIST(dns_sdlznode_t)	nodelist;
    131 	dns_sdlznode_t			*current;
    132 	dns_sdlznode_t			*origin;
    133 };
    134 
    135 typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
    136 
    137 typedef struct sdlz_rdatasetiter {
    138 	dns_rdatasetiter_t		common;
    139 	dns_rdatalist_t			*current;
    140 } sdlz_rdatasetiter_t;
    141 
    142 
    143 #define SDLZDB_MAGIC		ISC_MAGIC('D', 'L', 'Z', 'S')
    144 
    145 /*
    146  * Note that "impmagic" is not the first four bytes of the struct, so
    147  * ISC_MAGIC_VALID cannot be used.
    148  */
    149 
    150 #define VALID_SDLZDB(sdlzdb)	((sdlzdb) != NULL && \
    151 				 (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
    152 
    153 #define SDLZLOOKUP_MAGIC	ISC_MAGIC('D','L','Z','L')
    154 #define VALID_SDLZLOOKUP(sdlzl)	ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
    155 #define VALID_SDLZNODE(sdlzn)	VALID_SDLZLOOKUP(sdlzn)
    156 
    157 /* These values are taken from RFC 1537 */
    158 #define SDLZ_DEFAULT_REFRESH	28800U		/* 8 hours */
    159 #define SDLZ_DEFAULT_RETRY	7200U		/* 2 hours */
    160 #define SDLZ_DEFAULT_EXPIRE	604800U		/* 7 days */
    161 #define SDLZ_DEFAULT_MINIMUM	86400U		/* 1 day */
    162 
    163 /* This is a reasonable value */
    164 #define SDLZ_DEFAULT_TTL	(60 * 60 * 24)
    165 
    166 #ifdef __COVERITY__
    167 #define MAYBE_LOCK(imp) LOCK(&imp->driverlock)
    168 #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
    169 #else
    170 #define MAYBE_LOCK(imp) \
    171 	do { \
    172 		unsigned int flags = imp->flags; \
    173 		if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
    174 			LOCK(&imp->driverlock); \
    175 	} while (0)
    176 
    177 #define MAYBE_UNLOCK(imp) \
    178 	do { \
    179 		unsigned int flags = imp->flags; \
    180 		if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
    181 			UNLOCK(&imp->driverlock); \
    182 	} while (0)
    183 #endif
    184 
    185 /*
    186  * Forward references.
    187  */
    188 static isc_result_t getnodedata(dns_db_t *db, const dns_name_t *name,
    189 				bool create, unsigned int options,
    190 				dns_clientinfomethods_t *methods,
    191 				dns_clientinfo_t *clientinfo,
    192 				dns_dbnode_t **nodep);
    193 
    194 static void list_tordataset(dns_rdatalist_t *rdatalist,
    195 			    dns_db_t *db, dns_dbnode_t *node,
    196 			    dns_rdataset_t *rdataset);
    197 
    198 static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
    199 
    200 static void		dbiterator_destroy(dns_dbiterator_t **iteratorp);
    201 static isc_result_t	dbiterator_first(dns_dbiterator_t *iterator);
    202 static isc_result_t	dbiterator_last(dns_dbiterator_t *iterator);
    203 static isc_result_t	dbiterator_seek(dns_dbiterator_t *iterator,
    204 					const dns_name_t *name);
    205 static isc_result_t	dbiterator_prev(dns_dbiterator_t *iterator);
    206 static isc_result_t	dbiterator_next(dns_dbiterator_t *iterator);
    207 static isc_result_t	dbiterator_current(dns_dbiterator_t *iterator,
    208 					   dns_dbnode_t **nodep,
    209 					   dns_name_t *name);
    210 static isc_result_t	dbiterator_pause(dns_dbiterator_t *iterator);
    211 static isc_result_t	dbiterator_origin(dns_dbiterator_t *iterator,
    212 					  dns_name_t *name);
    213 
    214 static dns_dbiteratormethods_t dbiterator_methods = {
    215 	dbiterator_destroy,
    216 	dbiterator_first,
    217 	dbiterator_last,
    218 	dbiterator_seek,
    219 	dbiterator_prev,
    220 	dbiterator_next,
    221 	dbiterator_current,
    222 	dbiterator_pause,
    223 	dbiterator_origin
    224 };
    225 
    226 /*
    227  * Utility functions
    228  */
    229 
    230 /*
    231  * Log a message at the given level
    232  */
    233 static void
    234 sdlz_log(int level, const char *fmt, ...) {
    235 	va_list ap;
    236 	va_start(ap, fmt);
    237 	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
    238 		       DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level),
    239 		       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 static inline unsigned int
    256 initial_size(const char *data) {
    257 	unsigned int len = (strlen(data) / 64) + 1;
    258 	return (len * 64 + 64);
    259 }
    260 
    261 /*
    262  * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
    263  * driver interface.  See the SDB driver interface documentation for more info.
    264  */
    265 
    266 static void
    267 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
    268 	sdlz_rdatasetiter_t *sdlziterator =
    269 		(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 	sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
    285 	return (ISC_R_SUCCESS);
    286 }
    287 
    288 static isc_result_t
    289 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
    290 	sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
    291 
    292 	sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
    293 	if (sdlziterator->current == NULL)
    294 		return (ISC_R_NOMORE);
    295 	else
    296 		return (ISC_R_SUCCESS);
    297 }
    298 
    299 static void
    300 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
    301 	sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
    302 
    303 	list_tordataset(sdlziterator->current, iterator->db, iterator->node,
    304 			rdataset);
    305 }
    306 
    307 static dns_rdatasetitermethods_t rdatasetiter_methods = {
    308 	rdatasetiter_destroy,
    309 	rdatasetiter_first,
    310 	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 	LOCK(&sdlz->refcnt_lock);
    326 	REQUIRE(sdlz->references > 0);
    327 	sdlz->references++;
    328 	UNLOCK(&sdlz->refcnt_lock);
    329 
    330 	*targetp = source;
    331 }
    332 
    333 static void
    334 destroy(dns_sdlz_db_t *sdlz) {
    335 	isc_mem_t *mctx;
    336 	mctx = sdlz->common.mctx;
    337 
    338 	sdlz->common.magic = 0;
    339 	sdlz->common.impmagic = 0;
    340 
    341 	isc_mutex_destroy(&sdlz->refcnt_lock);
    342 
    343 	dns_name_free(&sdlz->common.origin, mctx);
    344 
    345 	isc_mem_put(mctx, sdlz, sizeof(dns_sdlz_db_t));
    346 	isc_mem_detach(&mctx);
    347 }
    348 
    349 static void
    350 detach(dns_db_t **dbp) {
    351 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
    352 	bool need_destroy = false;
    353 
    354 	REQUIRE(VALID_SDLZDB(sdlz));
    355 	LOCK(&sdlz->refcnt_lock);
    356 	REQUIRE(sdlz->references > 0);
    357 	sdlz->references--;
    358 	if (sdlz->references == 0)
    359 		need_destroy = true;
    360 	UNLOCK(&sdlz->refcnt_lock);
    361 
    362 	if (need_destroy)
    363 		destroy(sdlz);
    364 
    365 	*dbp = NULL;
    366 }
    367 
    368 static isc_result_t
    369 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
    370 	UNUSED(db);
    371 	UNUSED(callbacks);
    372 	return (ISC_R_NOTIMPLEMENTED);
    373 }
    374 
    375 static isc_result_t
    376 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
    377 	UNUSED(db);
    378 	UNUSED(callbacks);
    379 	return (ISC_R_NOTIMPLEMENTED);
    380 }
    381 
    382 static isc_result_t
    383 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
    384      dns_masterformat_t masterformat)
    385 {
    386 	UNUSED(db);
    387 	UNUSED(version);
    388 	UNUSED(filename);
    389 	UNUSED(masterformat);
    390 	return (ISC_R_NOTIMPLEMENTED);
    391 }
    392 
    393 static void
    394 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
    395 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    396 	REQUIRE(VALID_SDLZDB(sdlz));
    397 	REQUIRE(versionp != NULL && *versionp == NULL);
    398 
    399 	*versionp = (void *) &sdlz->dummy_version;
    400 	return;
    401 }
    402 
    403 static isc_result_t
    404 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
    405 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    406 	char origin[DNS_NAME_MAXTEXT + 1];
    407 	isc_result_t result;
    408 
    409 	REQUIRE(VALID_SDLZDB(sdlz));
    410 
    411 	if (sdlz->dlzimp->methods->newversion == NULL)
    412 		return (ISC_R_NOTIMPLEMENTED);
    413 
    414 	dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
    415 
    416 	result = sdlz->dlzimp->methods->newversion(origin,
    417 						   sdlz->dlzimp->driverarg,
    418 						   sdlz->dbdata, versionp);
    419 	if (result != ISC_R_SUCCESS) {
    420 		sdlz_log(ISC_LOG_ERROR,
    421 			 "sdlz newversion on origin %s failed : %s",
    422 			 origin, isc_result_totext(result));
    423 		return (result);
    424 	}
    425 
    426 	sdlz->future_version = *versionp;
    427 	return (ISC_R_SUCCESS);
    428 }
    429 
    430 static void
    431 attachversion(dns_db_t *db, dns_dbversion_t *source, dns_dbversion_t **targetp)
    432 {
    433 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    434 
    435 	REQUIRE(VALID_SDLZDB(sdlz));
    436 	REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version);
    437 
    438 	*targetp = source;
    439 }
    440 
    441 static void
    442 closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
    443 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    444 	char origin[DNS_NAME_MAXTEXT + 1];
    445 
    446 	REQUIRE(VALID_SDLZDB(sdlz));
    447 	REQUIRE(versionp != NULL);
    448 
    449 	if (*versionp == (void *)&sdlz->dummy_version) {
    450 		*versionp = NULL;
    451 		return;
    452 	}
    453 
    454 	REQUIRE(*versionp == sdlz->future_version);
    455 	REQUIRE(sdlz->dlzimp->methods->closeversion != NULL);
    456 
    457 	dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
    458 
    459 	sdlz->dlzimp->methods->closeversion(origin, commit,
    460 					    sdlz->dlzimp->driverarg,
    461 					    sdlz->dbdata, versionp);
    462 	if (*versionp != NULL)
    463 		sdlz_log(ISC_LOG_ERROR,
    464 			"sdlz closeversion on origin %s failed", origin);
    465 
    466 	sdlz->future_version = NULL;
    467 }
    468 
    469 static isc_result_t
    470 createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
    471 	dns_sdlznode_t *node;
    472 
    473 	node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
    474 	if (node == NULL)
    475 		return (ISC_R_NOMEMORY);
    476 
    477 	node->sdlz = NULL;
    478 	attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz);
    479 	ISC_LIST_INIT(node->lists);
    480 	ISC_LIST_INIT(node->buffers);
    481 	ISC_LINK_INIT(node, link);
    482 	node->name = NULL;
    483 	isc_mutex_init(&node->lock);
    484 	dns_rdatacallbacks_init(&node->callbacks);
    485 	node->references = 1;
    486 	node->magic = SDLZLOOKUP_MAGIC;
    487 
    488 	*nodep = node;
    489 	return (ISC_R_SUCCESS);
    490 }
    491 
    492 static void
    493 destroynode(dns_sdlznode_t *node) {
    494 	dns_rdatalist_t *list;
    495 	dns_rdata_t *rdata;
    496 	isc_buffer_t *b;
    497 	dns_sdlz_db_t *sdlz;
    498 	dns_db_t *db;
    499 	isc_mem_t *mctx;
    500 
    501 	sdlz = node->sdlz;
    502 	mctx = sdlz->common.mctx;
    503 
    504 	while (!ISC_LIST_EMPTY(node->lists)) {
    505 		list = ISC_LIST_HEAD(node->lists);
    506 		while (!ISC_LIST_EMPTY(list->rdata)) {
    507 			rdata = ISC_LIST_HEAD(list->rdata);
    508 			ISC_LIST_UNLINK(list->rdata, rdata, link);
    509 			isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
    510 		}
    511 		ISC_LIST_UNLINK(node->lists, list, link);
    512 		isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
    513 	}
    514 
    515 	while (!ISC_LIST_EMPTY(node->buffers)) {
    516 		b = ISC_LIST_HEAD(node->buffers);
    517 		ISC_LIST_UNLINK(node->buffers, b, link);
    518 		isc_buffer_free(&b);
    519 	}
    520 
    521 	if (node->name != NULL) {
    522 		dns_name_free(node->name, mctx);
    523 		isc_mem_put(mctx, node->name, sizeof(dns_name_t));
    524 	}
    525 	isc_mutex_destroy(&node->lock);
    526 	node->magic = 0;
    527 	isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
    528 	db = &sdlz->common;
    529 	detach(&db);
    530 }
    531 
    532 static isc_result_t
    533 getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
    534 	    unsigned int options, dns_clientinfomethods_t *methods,
    535 	    dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep)
    536 {
    537 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    538 	dns_sdlznode_t *node = NULL;
    539 	isc_result_t result;
    540 	isc_buffer_t b;
    541 	char namestr[DNS_NAME_MAXTEXT + 1];
    542 	isc_buffer_t b2;
    543 	char zonestr[DNS_NAME_MAXTEXT + 1];
    544 	bool isorigin;
    545 	dns_sdlzauthorityfunc_t authority;
    546 
    547 	REQUIRE(VALID_SDLZDB(sdlz));
    548 	REQUIRE(nodep != NULL && *nodep == NULL);
    549 
    550 	if (sdlz->dlzimp->methods->newversion == NULL) {
    551 		REQUIRE(create == false);
    552 	}
    553 
    554 	isc_buffer_init(&b, namestr, sizeof(namestr));
    555 	if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
    556 		dns_name_t relname;
    557 		unsigned int labels;
    558 
    559 		labels = dns_name_countlabels(name) -
    560 			 dns_name_countlabels(&sdlz->common.origin);
    561 		dns_name_init(&relname, NULL);
    562 		dns_name_getlabelsequence(name, 0, labels, &relname);
    563 		result = dns_name_totext(&relname, true, &b);
    564 		if (result != ISC_R_SUCCESS)
    565 			return (result);
    566 	} else {
    567 		result = dns_name_totext(name, true, &b);
    568 		if (result != ISC_R_SUCCESS)
    569 			return (result);
    570 	}
    571 	isc_buffer_putuint8(&b, 0);
    572 
    573 	isc_buffer_init(&b2, zonestr, sizeof(zonestr));
    574 	result = dns_name_totext(&sdlz->common.origin, true, &b2);
    575 	if (result != ISC_R_SUCCESS)
    576 		return (result);
    577 	isc_buffer_putuint8(&b2, 0);
    578 
    579 	result = createnode(sdlz, &node);
    580 	if (result != ISC_R_SUCCESS)
    581 		return (result);
    582 
    583 	isorigin = dns_name_equal(name, &sdlz->common.origin);
    584 
    585 	/* make sure strings are always lowercase */
    586 	dns_sdlz_tolower(zonestr);
    587 	dns_sdlz_tolower(namestr);
    588 
    589 	MAYBE_LOCK(sdlz->dlzimp);
    590 
    591 	/* try to lookup the host (namestr) */
    592 	result = sdlz->dlzimp->methods->lookup(zonestr, namestr,
    593 					       sdlz->dlzimp->driverarg,
    594 					       sdlz->dbdata, node,
    595 					       methods, clientinfo);
    596 
    597 	/*
    598 	 * If the name was not found and DNS_DBFIND_NOWILD is not
    599 	 * set, then we try to find a wildcard entry.
    600 	 *
    601 	 * If DNS_DBFIND_NOZONECUT is set and there are multiple
    602 	 * levels between the host and the zone origin, we also look
    603 	 * for wildcards at each level.
    604 	 */
    605 	if (result == ISC_R_NOTFOUND && !create &&
    606 	    (options & DNS_DBFIND_NOWILD) == 0)
    607 	{
    608 		unsigned int i, dlabels, nlabels;
    609 
    610 		nlabels = dns_name_countlabels(name);
    611 		dlabels = nlabels - dns_name_countlabels(&sdlz->common.origin);
    612 		for (i = 0; i < dlabels; i++) {
    613 			char wildstr[DNS_NAME_MAXTEXT + 1];
    614 			dns_fixedname_t fixed;
    615 			const dns_name_t *wild;
    616 
    617 			dns_fixedname_init(&fixed);
    618 			if (i == dlabels - 1) {
    619 				wild = dns_wildcardname;
    620 			} else {
    621 				dns_name_t *fname;
    622 				fname = dns_fixedname_name(&fixed);
    623 				dns_name_getlabelsequence(name, i + 1,
    624 							  dlabels - i - 1,
    625 							  fname);
    626 				result = dns_name_concatenate(dns_wildcardname,
    627 							      fname, fname,
    628 							      NULL);
    629 				if (result != ISC_R_SUCCESS) {
    630 					MAYBE_UNLOCK(sdlz->dlzimp);
    631 					return (result);
    632 				}
    633 				wild = fname;
    634 			}
    635 
    636 			isc_buffer_init(&b, wildstr, sizeof(wildstr));
    637 			result = dns_name_totext(wild, true, &b);
    638 			if (result != ISC_R_SUCCESS) {
    639 				MAYBE_UNLOCK(sdlz->dlzimp);
    640 				return (result);
    641 			}
    642 			isc_buffer_putuint8(&b, 0);
    643 
    644 			result = sdlz->dlzimp->methods->lookup(zonestr, wildstr,
    645 						       sdlz->dlzimp->driverarg,
    646 						       sdlz->dbdata, node,
    647 						       methods, clientinfo);
    648 			if (result == ISC_R_SUCCESS)
    649 				break;
    650 		}
    651 	}
    652 
    653 	MAYBE_UNLOCK(sdlz->dlzimp);
    654 
    655 	if (result == ISC_R_NOTFOUND && (isorigin || create))
    656 		result = ISC_R_SUCCESS;
    657 
    658 	if (result != ISC_R_SUCCESS) {
    659 		destroynode(node);
    660 		return (result);
    661 	}
    662 
    663 	if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
    664 		MAYBE_LOCK(sdlz->dlzimp);
    665 		authority = sdlz->dlzimp->methods->authority;
    666 		result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
    667 				      sdlz->dbdata, node);
    668 		MAYBE_UNLOCK(sdlz->dlzimp);
    669 		if (result != ISC_R_SUCCESS &&
    670 		    result != ISC_R_NOTIMPLEMENTED)
    671 		{
    672 			destroynode(node);
    673 			return (result);
    674 		}
    675 	}
    676 
    677 	if (node->name == NULL) {
    678 		node->name = isc_mem_get(sdlz->common.mctx,
    679 					 sizeof(dns_name_t));
    680 		if (node->name == NULL) {
    681 			destroynode(node);
    682 			return (ISC_R_NOMEMORY);
    683 		}
    684 		dns_name_init(node->name, NULL);
    685 		result = dns_name_dup(name, sdlz->common.mctx, node->name);
    686 		if (result != ISC_R_SUCCESS) {
    687 			isc_mem_put(sdlz->common.mctx, node->name,
    688 				    sizeof(dns_name_t));
    689 			destroynode(node);
    690 			return (result);
    691 		}
    692 	}
    693 
    694 	*nodep = node;
    695 	return (ISC_R_SUCCESS);
    696 }
    697 
    698 static isc_result_t
    699 findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
    700 	    dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
    701 	    dns_dbnode_t **nodep)
    702 {
    703 	return (getnodedata(db, name, create, 0, methods, clientinfo, nodep));
    704 }
    705 
    706 static isc_result_t
    707 findnode(dns_db_t *db, const dns_name_t *name, bool create,
    708 	 dns_dbnode_t **nodep)
    709 {
    710 	return (getnodedata(db, name, create, 0, NULL, NULL, nodep));
    711 }
    712 
    713 static isc_result_t
    714 findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
    715 	    isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
    716 	    dns_name_t *dcname, dns_rdataset_t *rdataset,
    717 	    dns_rdataset_t *sigrdataset)
    718 {
    719 	UNUSED(db);
    720 	UNUSED(name);
    721 	UNUSED(options);
    722 	UNUSED(now);
    723 	UNUSED(nodep);
    724 	UNUSED(foundname);
    725 	UNUSED(dcname);
    726 	UNUSED(rdataset);
    727 	UNUSED(sigrdataset);
    728 
    729 	return (ISC_R_NOTIMPLEMENTED);
    730 }
    731 
    732 static void
    733 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
    734 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    735 	dns_sdlznode_t *node = (dns_sdlznode_t *)source;
    736 
    737 	REQUIRE(VALID_SDLZDB(sdlz));
    738 
    739 	UNUSED(sdlz);
    740 
    741 	LOCK(&node->lock);
    742 	INSIST(node->references > 0);
    743 	node->references++;
    744 	INSIST(node->references != 0);		/* Catch overflow. */
    745 	UNLOCK(&node->lock);
    746 
    747 	*targetp = source;
    748 }
    749 
    750 static void
    751 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
    752 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    753 	dns_sdlznode_t *node;
    754 	bool need_destroy = false;
    755 
    756 	REQUIRE(VALID_SDLZDB(sdlz));
    757 	REQUIRE(targetp != NULL && *targetp != NULL);
    758 
    759 	UNUSED(sdlz);
    760 
    761 	node = (dns_sdlznode_t *)(*targetp);
    762 
    763 	LOCK(&node->lock);
    764 	INSIST(node->references > 0);
    765 	node->references--;
    766 	if (node->references == 0)
    767 		need_destroy = true;
    768 	UNLOCK(&node->lock);
    769 
    770 	if (need_destroy)
    771 		destroynode(node);
    772 
    773 	*targetp = NULL;
    774 }
    775 
    776 static isc_result_t
    777 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
    778 	UNUSED(db);
    779 	UNUSED(node);
    780 	UNUSED(now);
    781 	INSIST(0);
    782 	ISC_UNREACHABLE();
    783 }
    784 
    785 static void
    786 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
    787 	UNUSED(db);
    788 	UNUSED(node);
    789 	UNUSED(out);
    790 	return;
    791 }
    792 
    793 static isc_result_t
    794 createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
    795 {
    796 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    797 	sdlz_dbiterator_t *sdlziter;
    798 	isc_result_t result;
    799 	isc_buffer_t b;
    800 	char zonestr[DNS_NAME_MAXTEXT + 1];
    801 
    802 	REQUIRE(VALID_SDLZDB(sdlz));
    803 
    804 	if (sdlz->dlzimp->methods->allnodes == NULL)
    805 		return (ISC_R_NOTIMPLEMENTED);
    806 
    807 	if ((options & DNS_DB_NSEC3ONLY) != 0 ||
    808 	    (options & DNS_DB_NONSEC3) != 0)
    809 		 return (ISC_R_NOTIMPLEMENTED);
    810 
    811 	isc_buffer_init(&b, zonestr, sizeof(zonestr));
    812 	result = dns_name_totext(&sdlz->common.origin, true, &b);
    813 	if (result != ISC_R_SUCCESS)
    814 		return (result);
    815 	isc_buffer_putuint8(&b, 0);
    816 
    817 	sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
    818 	if (sdlziter == NULL)
    819 		return (ISC_R_NOMEMORY);
    820 
    821 	sdlziter->common.methods = &dbiterator_methods;
    822 	sdlziter->common.db = NULL;
    823 	dns_db_attach(db, &sdlziter->common.db);
    824 	sdlziter->common.relative_names =
    825 		((options & DNS_DB_RELATIVENAMES) != 0);
    826 	sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
    827 	ISC_LIST_INIT(sdlziter->nodelist);
    828 	sdlziter->current = NULL;
    829 	sdlziter->origin = NULL;
    830 
    831 	/* make sure strings are always lowercase */
    832 	dns_sdlz_tolower(zonestr);
    833 
    834 	MAYBE_LOCK(sdlz->dlzimp);
    835 	result = sdlz->dlzimp->methods->allnodes(zonestr,
    836 						 sdlz->dlzimp->driverarg,
    837 						 sdlz->dbdata, sdlziter);
    838 	MAYBE_UNLOCK(sdlz->dlzimp);
    839 	if (result != ISC_R_SUCCESS) {
    840 		dns_dbiterator_t *iter = &sdlziter->common;
    841 		dbiterator_destroy(&iter);
    842 		return (result);
    843 	}
    844 
    845 	if (sdlziter->origin != NULL) {
    846 		ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
    847 		ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
    848 	}
    849 
    850 	*iteratorp = (dns_dbiterator_t *)sdlziter;
    851 
    852 	return (ISC_R_SUCCESS);
    853 }
    854 
    855 static isc_result_t
    856 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
    857 	     dns_rdatatype_t type, dns_rdatatype_t covers,
    858 	     isc_stdtime_t now, dns_rdataset_t *rdataset,
    859 	     dns_rdataset_t *sigrdataset)
    860 {
    861 	dns_rdatalist_t *list;
    862 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
    863 
    864 	REQUIRE(VALID_SDLZNODE(node));
    865 
    866 	UNUSED(db);
    867 	UNUSED(version);
    868 	UNUSED(covers);
    869 	UNUSED(now);
    870 	UNUSED(sigrdataset);
    871 
    872 	if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig)
    873 		return (ISC_R_NOTIMPLEMENTED);
    874 
    875 	list = ISC_LIST_HEAD(sdlznode->lists);
    876 	while (list != NULL) {
    877 		if (list->type == type)
    878 			break;
    879 		list = ISC_LIST_NEXT(list, link);
    880 	}
    881 	if (list == NULL)
    882 		return (ISC_R_NOTFOUND);
    883 
    884 	list_tordataset(list, db, node, rdataset);
    885 
    886 	return (ISC_R_SUCCESS);
    887 }
    888 
    889 static isc_result_t
    890 findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
    891 	dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
    892 	dns_dbnode_t **nodep, dns_name_t *foundname,
    893 	dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
    894 	dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
    895 {
    896 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    897 	dns_dbnode_t *node = NULL;
    898 	dns_fixedname_t fname;
    899 	dns_rdataset_t xrdataset;
    900 	dns_name_t *xname;
    901 	unsigned int nlabels, olabels;
    902 	isc_result_t result;
    903 	unsigned int i;
    904 
    905 	REQUIRE(VALID_SDLZDB(sdlz));
    906 	REQUIRE(nodep == NULL || *nodep == NULL);
    907 	REQUIRE(version == NULL ||
    908 		version == (void*)&sdlz->dummy_version ||
    909 		version == sdlz->future_version);
    910 
    911 	UNUSED(sdlz);
    912 
    913 	if (!dns_name_issubdomain(name, &db->origin))
    914 		return (DNS_R_NXDOMAIN);
    915 
    916 	olabels = dns_name_countlabels(&db->origin);
    917 	nlabels = dns_name_countlabels(name);
    918 
    919 	xname = dns_fixedname_initname(&fname);
    920 
    921 	if (rdataset == NULL) {
    922 		dns_rdataset_init(&xrdataset);
    923 		rdataset = &xrdataset;
    924 	}
    925 
    926 	result = DNS_R_NXDOMAIN;
    927 
    928 	/*
    929 	 * If we're not walking down searching for zone
    930 	 * cuts, we can cut straight to the chase
    931 	 */
    932 	if ((options & DNS_DBFIND_NOZONECUT) != 0) {
    933 		i = nlabels;
    934 		goto search;
    935 	}
    936 
    937 	for (i = olabels; i <= nlabels; i++) {
    938  search:
    939 		/*
    940 		 * Look up the next label.
    941 		 */
    942 		dns_name_getlabelsequence(name, nlabels - i, i, xname);
    943 		result = getnodedata(db, xname, false, options,
    944 				     methods, clientinfo, &node);
    945 		if (result == ISC_R_NOTFOUND) {
    946 			result = DNS_R_NXDOMAIN;
    947 			continue;
    948 		} else if (result != ISC_R_SUCCESS)
    949 			break;
    950 
    951 		/*
    952 		 * Look for a DNAME at the current label, unless this is
    953 		 * the qname.
    954 		 */
    955 		if (i < nlabels) {
    956 			result = findrdataset(db, node, version,
    957 					      dns_rdatatype_dname, 0, now,
    958 					      rdataset, sigrdataset);
    959 			if (result == ISC_R_SUCCESS) {
    960 				result = DNS_R_DNAME;
    961 				break;
    962 			}
    963 		}
    964 
    965 		/*
    966 		 * Look for an NS at the current label, unless this is the
    967 		 * origin, glue is ok, or there are known to be no zone cuts.
    968 		 */
    969 		if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0 &&
    970 		    (options & DNS_DBFIND_NOZONECUT) == 0)
    971 		{
    972 			result = findrdataset(db, node, version,
    973 					      dns_rdatatype_ns, 0, now,
    974 					      rdataset, sigrdataset);
    975 
    976 			if (result == ISC_R_SUCCESS &&
    977 			    i == nlabels && type == dns_rdatatype_any)
    978 			{
    979 				result = DNS_R_ZONECUT;
    980 				dns_rdataset_disassociate(rdataset);
    981 				if (sigrdataset != NULL &&
    982 				    dns_rdataset_isassociated(sigrdataset))
    983 					dns_rdataset_disassociate(sigrdataset);
    984 				break;
    985 			} else if (result == ISC_R_SUCCESS) {
    986 				result = DNS_R_DELEGATION;
    987 				break;
    988 			}
    989 		}
    990 
    991 		/*
    992 		 * If the current name is not the qname, add another label
    993 		 * and try again.
    994 		 */
    995 		if (i < nlabels) {
    996 			destroynode(node);
    997 			node = NULL;
    998 			continue;
    999 		}
   1000 
   1001 		/*
   1002 		 * If we're looking for ANY, we're done.
   1003 		 */
   1004 		if (type == dns_rdatatype_any) {
   1005 			result = ISC_R_SUCCESS;
   1006 			break;
   1007 		}
   1008 
   1009 		/*
   1010 		 * Look for the qtype.
   1011 		 */
   1012 		result = findrdataset(db, node, version, type, 0, now,
   1013 				      rdataset, sigrdataset);
   1014 		if (result == ISC_R_SUCCESS)
   1015 			break;
   1016 
   1017 		/*
   1018 		 * Look for a CNAME
   1019 		 */
   1020 		if (type != dns_rdatatype_cname) {
   1021 			result = findrdataset(db, node, version,
   1022 					      dns_rdatatype_cname, 0, now,
   1023 					      rdataset, sigrdataset);
   1024 			if (result == ISC_R_SUCCESS) {
   1025 				result = DNS_R_CNAME;
   1026 				break;
   1027 			}
   1028 		}
   1029 
   1030 		result = DNS_R_NXRRSET;
   1031 		break;
   1032 	}
   1033 
   1034 	if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
   1035 		dns_rdataset_disassociate(rdataset);
   1036 
   1037 	if (foundname != NULL) {
   1038 		isc_result_t xresult;
   1039 
   1040 		xresult = dns_name_copy(xname, foundname, NULL);
   1041 		if (xresult != ISC_R_SUCCESS) {
   1042 			if (node != NULL)
   1043 				destroynode(node);
   1044 			if (dns_rdataset_isassociated(rdataset))
   1045 				dns_rdataset_disassociate(rdataset);
   1046 			return (DNS_R_BADDB);
   1047 		}
   1048 	}
   1049 
   1050 	if (nodep != NULL)
   1051 		*nodep = node;
   1052 	else if (node != NULL)
   1053 		detachnode(db, &node);
   1054 
   1055 	return (result);
   1056 }
   1057 
   1058 static isc_result_t
   1059 find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
   1060      dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
   1061      dns_dbnode_t **nodep, dns_name_t *foundname,
   1062      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
   1063 {
   1064 	return (findext(db, name, version, type, options, now, nodep,
   1065 			foundname, NULL, NULL, rdataset, sigrdataset));
   1066 }
   1067 
   1068 static isc_result_t
   1069 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   1070 	     isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
   1071 {
   1072 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) db;
   1073 	sdlz_rdatasetiter_t *iterator;
   1074 
   1075 	REQUIRE(VALID_SDLZDB(sdlz));
   1076 
   1077 	REQUIRE(version == NULL ||
   1078 		version == (void*)&sdlz->dummy_version ||
   1079 		version == sdlz->future_version);
   1080 
   1081 	UNUSED(version);
   1082 	UNUSED(now);
   1083 
   1084 	iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
   1085 	if (iterator == NULL)
   1086 		return (ISC_R_NOMEMORY);
   1087 
   1088 	iterator->common.magic = DNS_RDATASETITER_MAGIC;
   1089 	iterator->common.methods = &rdatasetiter_methods;
   1090 	iterator->common.db = db;
   1091 	iterator->common.node = NULL;
   1092 	attachnode(db, node, &iterator->common.node);
   1093 	iterator->common.version = version;
   1094 	iterator->common.now = now;
   1095 
   1096 	*iteratorp = (dns_rdatasetiter_t *)iterator;
   1097 
   1098 	return (ISC_R_SUCCESS);
   1099 }
   1100 
   1101 static isc_result_t
   1102 modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   1103 	    dns_rdataset_t *rdataset, unsigned int options,
   1104 	    dns_sdlzmodrdataset_t mod_function)
   1105 {
   1106 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1107 	dns_master_style_t *style = NULL;
   1108 	isc_result_t result;
   1109 	isc_buffer_t *buffer = NULL;
   1110 	isc_mem_t *mctx;
   1111 	dns_sdlznode_t *sdlznode;
   1112 	char *rdatastr = NULL;
   1113 	char name[DNS_NAME_MAXTEXT + 1];
   1114 
   1115 	REQUIRE(VALID_SDLZDB(sdlz));
   1116 
   1117 	if (mod_function == NULL)
   1118 		return (ISC_R_NOTIMPLEMENTED);
   1119 
   1120 	sdlznode = (dns_sdlznode_t *)node;
   1121 
   1122 	UNUSED(options);
   1123 
   1124 	dns_name_format(sdlznode->name, name, sizeof(name));
   1125 
   1126 	mctx = sdlz->common.mctx;
   1127 
   1128 	result = isc_buffer_allocate(mctx, &buffer, 1024);
   1129 	if (result != ISC_R_SUCCESS)
   1130 		return (result);
   1131 
   1132 	result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1,
   1133 					0xffffffff, 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 bool
   1239 issecure(dns_db_t *db) {
   1240 	UNUSED(db);
   1241 
   1242 	return (false);
   1243 }
   1244 
   1245 static unsigned int
   1246 nodecount(dns_db_t *db) {
   1247 	UNUSED(db);
   1248 
   1249 	return (0);
   1250 }
   1251 
   1252 static bool
   1253 ispersistent(dns_db_t *db) {
   1254 	UNUSED(db);
   1255 	return (true);
   1256 }
   1257 
   1258 static void
   1259 overmem(dns_db_t *db, bool 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, 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 	isc_mutex_init(&sdlzdb->refcnt_lock);
   1552 
   1553 	/* set the rest of the database structure attributes */
   1554 	sdlzdb->dlzimp = imp;
   1555 	sdlzdb->common.methods = &sdlzdb_methods;
   1556 	sdlzdb->common.attributes = 0;
   1557 	sdlzdb->common.rdclass = rdclass;
   1558 	sdlzdb->common.mctx = NULL;
   1559 	sdlzdb->dbdata = dbdata;
   1560 	sdlzdb->references = 1;
   1561 
   1562 	/* attach to the memory context */
   1563 	isc_mem_attach(mctx, &sdlzdb->common.mctx);
   1564 
   1565 	/* mark structure as valid */
   1566 	sdlzdb->common.magic = DNS_DB_MAGIC;
   1567 	sdlzdb->common.impmagic = SDLZDB_MAGIC;
   1568 	*dbp = (dns_db_t *) sdlzdb;
   1569 
   1570 	return (result);
   1571  mem_cleanup:
   1572 	isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
   1573 	return (result);
   1574 }
   1575 
   1576 static isc_result_t
   1577 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
   1578 		     dns_rdataclass_t rdclass, const dns_name_t *name,
   1579 		     const isc_sockaddr_t *clientaddr, dns_db_t **dbp)
   1580 {
   1581 	isc_buffer_t b;
   1582 	isc_buffer_t b2;
   1583 	char namestr[DNS_NAME_MAXTEXT + 1];
   1584 	char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
   1585 		       + 1];
   1586 	isc_netaddr_t netaddr;
   1587 	isc_result_t result;
   1588 	dns_sdlzimplementation_t *imp;
   1589 
   1590 	/*
   1591 	 * Perform checks to make sure data is as we expect it to be.
   1592 	 */
   1593 	REQUIRE(driverarg != NULL);
   1594 	REQUIRE(name != NULL);
   1595 	REQUIRE(clientaddr != NULL);
   1596 	REQUIRE(dbp != NULL && *dbp == NULL);
   1597 
   1598 	imp = (dns_sdlzimplementation_t *) driverarg;
   1599 
   1600 	/* Convert DNS name to ascii text */
   1601 	isc_buffer_init(&b, namestr, sizeof(namestr));
   1602 	result = dns_name_totext(name, true, &b);
   1603 	if (result != ISC_R_SUCCESS)
   1604 		return (result);
   1605 	isc_buffer_putuint8(&b, 0);
   1606 
   1607 	/* convert client address to ascii text */
   1608 	isc_buffer_init(&b2, clientstr, sizeof(clientstr));
   1609 	isc_netaddr_fromsockaddr(&netaddr, clientaddr);
   1610 	result = isc_netaddr_totext(&netaddr, &b2);
   1611 	if (result != ISC_R_SUCCESS)
   1612 		return (result);
   1613 	isc_buffer_putuint8(&b2, 0);
   1614 
   1615 	/* make sure strings are always lowercase */
   1616 	dns_sdlz_tolower(namestr);
   1617 	dns_sdlz_tolower(clientstr);
   1618 
   1619 	/* Call SDLZ driver's find zone method */
   1620 	if (imp->methods->allowzonexfr != NULL) {
   1621 		MAYBE_LOCK(imp);
   1622 		result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
   1623 						    namestr, clientstr);
   1624 		MAYBE_UNLOCK(imp);
   1625 		/*
   1626 		 * if zone is supported and transfers allowed build a 'bind'
   1627 		 * database driver
   1628 		 */
   1629 		if (result == ISC_R_SUCCESS)
   1630 			result = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
   1631 						   name, rdclass, dbp);
   1632 		return (result);
   1633 	}
   1634 
   1635 	return (ISC_R_NOTIMPLEMENTED);
   1636 }
   1637 
   1638 static isc_result_t
   1639 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
   1640 	       char *argv[], void *driverarg, void **dbdata)
   1641 {
   1642 	dns_sdlzimplementation_t *imp;
   1643 	isc_result_t result = ISC_R_NOTFOUND;
   1644 
   1645 	/* Write debugging message to log */
   1646 	sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
   1647 
   1648 	/*
   1649 	 * Performs checks to make sure data is as we expect it to be.
   1650 	 */
   1651 	REQUIRE(driverarg != NULL);
   1652 	REQUIRE(dlzname != NULL);
   1653 	REQUIRE(dbdata != NULL);
   1654 	UNUSED(mctx);
   1655 
   1656 	imp = driverarg;
   1657 
   1658 	/* If the create method exists, call it. */
   1659 	if (imp->methods->create != NULL) {
   1660 		MAYBE_LOCK(imp);
   1661 		result = imp->methods->create(dlzname, argc, argv,
   1662 					      imp->driverarg, dbdata);
   1663 		MAYBE_UNLOCK(imp);
   1664 	}
   1665 
   1666 	/* Write debugging message to log */
   1667 	if (result == ISC_R_SUCCESS) {
   1668 		sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
   1669 	} else {
   1670 		sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
   1671 	}
   1672 
   1673 	return (result);
   1674 }
   1675 
   1676 static void
   1677 dns_sdlzdestroy(void *driverdata, void **dbdata) {
   1678 	dns_sdlzimplementation_t *imp;
   1679 
   1680 	/* Write debugging message to log */
   1681 	sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
   1682 
   1683 	imp = driverdata;
   1684 
   1685 	/* If the destroy method exists, call it. */
   1686 	if (imp->methods->destroy != NULL) {
   1687 		MAYBE_LOCK(imp);
   1688 		imp->methods->destroy(imp->driverarg, dbdata);
   1689 		MAYBE_UNLOCK(imp);
   1690 	}
   1691 }
   1692 
   1693 static isc_result_t
   1694 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
   1695 		 dns_rdataclass_t rdclass, const dns_name_t *name,
   1696 		 dns_clientinfomethods_t *methods,
   1697 		 dns_clientinfo_t *clientinfo,
   1698 		 dns_db_t **dbp)
   1699 {
   1700 	isc_buffer_t b;
   1701 	char namestr[DNS_NAME_MAXTEXT + 1];
   1702 	isc_result_t result;
   1703 	dns_sdlzimplementation_t *imp;
   1704 
   1705 	/*
   1706 	 * Perform checks to make sure data is as we expect it to be.
   1707 	 */
   1708 	REQUIRE(driverarg != NULL);
   1709 	REQUIRE(name != NULL);
   1710 	REQUIRE(dbp != NULL && *dbp == NULL);
   1711 
   1712 	imp = (dns_sdlzimplementation_t *) driverarg;
   1713 
   1714 	/* Convert DNS name to ascii text */
   1715 	isc_buffer_init(&b, namestr, sizeof(namestr));
   1716 	result = dns_name_totext(name, true, &b);
   1717 	if (result != ISC_R_SUCCESS)
   1718 		return (result);
   1719 	isc_buffer_putuint8(&b, 0);
   1720 
   1721 	/* make sure strings are always lowercase */
   1722 	dns_sdlz_tolower(namestr);
   1723 
   1724 	/* Call SDLZ driver's find zone method */
   1725 	MAYBE_LOCK(imp);
   1726 	result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
   1727 					methods, clientinfo);
   1728 	MAYBE_UNLOCK(imp);
   1729 
   1730 	/*
   1731 	 * if zone is supported build a 'bind' database driver
   1732 	 * structure to return
   1733 	 */
   1734 	if (result == ISC_R_SUCCESS)
   1735 		result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
   1736 					   rdclass, dbp);
   1737 
   1738 	return (result);
   1739 }
   1740 
   1741 
   1742 static isc_result_t
   1743 dns_sdlzconfigure(void *driverarg, void *dbdata,
   1744 		  dns_view_t *view, dns_dlzdb_t *dlzdb)
   1745 {
   1746 	isc_result_t result;
   1747 	dns_sdlzimplementation_t *imp;
   1748 
   1749 	REQUIRE(driverarg != NULL);
   1750 
   1751 	imp = (dns_sdlzimplementation_t *) driverarg;
   1752 
   1753 	/* Call SDLZ driver's configure method */
   1754 	if (imp->methods->configure != NULL) {
   1755 		MAYBE_LOCK(imp);
   1756 		result = imp->methods->configure(view, dlzdb,
   1757 						 imp->driverarg, dbdata);
   1758 		MAYBE_UNLOCK(imp);
   1759 	} else {
   1760 		result = ISC_R_SUCCESS;
   1761 	}
   1762 
   1763 	return (result);
   1764 }
   1765 
   1766 static bool
   1767 dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name,
   1768 		 const isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
   1769 		 const dst_key_t *key, void *driverarg, void *dbdata)
   1770 {
   1771 	dns_sdlzimplementation_t *imp;
   1772 	char b_signer[DNS_NAME_FORMATSIZE];
   1773 	char b_name[DNS_NAME_FORMATSIZE];
   1774 	char b_addr[ISC_NETADDR_FORMATSIZE];
   1775 	char b_type[DNS_RDATATYPE_FORMATSIZE];
   1776 	char b_key[DST_KEY_FORMATSIZE];
   1777 	isc_buffer_t *tkey_token = NULL;
   1778 	isc_region_t token_region = { NULL, 0 };
   1779 	uint32_t token_len = 0;
   1780 	bool ret;
   1781 
   1782 	REQUIRE(driverarg != NULL);
   1783 
   1784 	imp = (dns_sdlzimplementation_t *) driverarg;
   1785 	if (imp->methods->ssumatch == NULL)
   1786 		return (false);
   1787 
   1788 	/*
   1789 	 * Format the request elements. sdlz operates on strings, not
   1790 	 * structures
   1791 	 */
   1792 	if (signer != NULL)
   1793 		dns_name_format(signer, b_signer, sizeof(b_signer));
   1794 	else
   1795 		b_signer[0] = 0;
   1796 
   1797 	dns_name_format(name, b_name, sizeof(b_name));
   1798 
   1799 	if (tcpaddr != NULL)
   1800 		isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
   1801 	else
   1802 		b_addr[0] = 0;
   1803 
   1804 	dns_rdatatype_format(type, b_type, sizeof(b_type));
   1805 
   1806 	if (key != NULL) {
   1807 		dst_key_format(key, b_key, sizeof(b_key));
   1808 		tkey_token = dst_key_tkeytoken(key);
   1809 	} else
   1810 		b_key[0] = 0;
   1811 
   1812 	if (tkey_token != NULL) {
   1813 		isc_buffer_region(tkey_token, &token_region);
   1814 		token_len = token_region.length;
   1815 	}
   1816 
   1817 	MAYBE_LOCK(imp);
   1818 	ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
   1819 				     token_len,
   1820 				     token_len != 0 ? token_region.base : NULL,
   1821 				     imp->driverarg, dbdata);
   1822 	MAYBE_UNLOCK(imp);
   1823 	return (ret);
   1824 }
   1825 
   1826 static dns_dlzmethods_t sdlzmethods = {
   1827 	dns_sdlzcreate,
   1828 	dns_sdlzdestroy,
   1829 	dns_sdlzfindzone,
   1830 	dns_sdlzallowzonexfr,
   1831 	dns_sdlzconfigure,
   1832 	dns_sdlzssumatch
   1833 };
   1834 
   1835 /*
   1836  * Public functions.
   1837  */
   1838 
   1839 isc_result_t
   1840 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
   1841 	       const char *data)
   1842 {
   1843 	dns_rdatalist_t *rdatalist;
   1844 	dns_rdata_t *rdata;
   1845 	dns_rdatatype_t typeval;
   1846 	isc_consttextregion_t r;
   1847 	isc_buffer_t b;
   1848 	isc_buffer_t *rdatabuf = NULL;
   1849 	isc_lex_t *lex;
   1850 	isc_result_t result;
   1851 	unsigned int size;
   1852 	isc_mem_t *mctx;
   1853 	const dns_name_t *origin;
   1854 
   1855 	REQUIRE(VALID_SDLZLOOKUP(lookup));
   1856 	REQUIRE(type != NULL);
   1857 	REQUIRE(data != NULL);
   1858 
   1859 	mctx = lookup->sdlz->common.mctx;
   1860 
   1861 	r.base = type;
   1862 	r.length = strlen(type);
   1863 	result = dns_rdatatype_fromtext(&typeval, (void *) &r);
   1864 	if (result != ISC_R_SUCCESS)
   1865 		return (result);
   1866 
   1867 	rdatalist = ISC_LIST_HEAD(lookup->lists);
   1868 	while (rdatalist != NULL) {
   1869 		if (rdatalist->type == typeval)
   1870 			break;
   1871 		rdatalist = ISC_LIST_NEXT(rdatalist, link);
   1872 	}
   1873 
   1874 	if (rdatalist == NULL) {
   1875 		rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
   1876 		if (rdatalist == NULL)
   1877 			return (ISC_R_NOMEMORY);
   1878 		dns_rdatalist_init(rdatalist);
   1879 		rdatalist->rdclass = lookup->sdlz->common.rdclass;
   1880 		rdatalist->type = typeval;
   1881 		rdatalist->ttl = ttl;
   1882 		ISC_LIST_APPEND(lookup->lists, rdatalist, link);
   1883 	} else
   1884 		if (rdatalist->ttl > ttl) {
   1885 			/*
   1886 			 * BIND9 doesn't enforce all RRs in an RRset
   1887 			 * having the same TTL, as per RFC 2136,
   1888 			 * section 7.12. If a DLZ backend has
   1889 			 * different TTLs, then the best
   1890 			 * we can do is return the lowest.
   1891 			*/
   1892 			rdatalist->ttl = ttl;
   1893 		}
   1894 
   1895 	rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
   1896 	if (rdata == NULL)
   1897 		return (ISC_R_NOMEMORY);
   1898 	dns_rdata_init(rdata);
   1899 
   1900 	if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
   1901 		origin = &lookup->sdlz->common.origin;
   1902 	else
   1903 		origin = dns_rootname;
   1904 
   1905 	lex = NULL;
   1906 	result = isc_lex_create(mctx, 64, &lex);
   1907 	if (result != ISC_R_SUCCESS)
   1908 		goto failure;
   1909 
   1910 	size = initial_size(data);
   1911 	do {
   1912 		isc_buffer_constinit(&b, data, strlen(data));
   1913 		isc_buffer_add(&b, strlen(data));
   1914 
   1915 		result = isc_lex_openbuffer(lex, &b);
   1916 		if (result != ISC_R_SUCCESS)
   1917 			goto failure;
   1918 
   1919 		rdatabuf = NULL;
   1920 		result = isc_buffer_allocate(mctx, &rdatabuf, size);
   1921 		if (result != ISC_R_SUCCESS)
   1922 			goto failure;
   1923 
   1924 		result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
   1925 					    rdatalist->type, lex,
   1926 					    origin, false,
   1927 					    mctx, rdatabuf,
   1928 					    &lookup->callbacks);
   1929 		if (result != ISC_R_SUCCESS) {
   1930 			isc_buffer_free(&rdatabuf);
   1931 			result = DNS_R_SERVFAIL;
   1932 		}
   1933 		if (size >= 65535)
   1934 			break;
   1935 		size *= 2;
   1936 		if (size >= 65535)
   1937 			size = 65535;
   1938 	} while (result == ISC_R_NOSPACE);
   1939 
   1940 	if (result != ISC_R_SUCCESS)
   1941 		goto failure;
   1942 
   1943 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
   1944 	ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
   1945 
   1946 	if (lex != NULL)
   1947 		isc_lex_destroy(&lex);
   1948 
   1949 	return (ISC_R_SUCCESS);
   1950 
   1951  failure:
   1952 	if (rdatabuf != NULL)
   1953 		isc_buffer_free(&rdatabuf);
   1954 	if (lex != NULL)
   1955 		isc_lex_destroy(&lex);
   1956 	isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
   1957 
   1958 	return (result);
   1959 }
   1960 
   1961 isc_result_t
   1962 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
   1963 		    const char *type, dns_ttl_t ttl, const char *data)
   1964 {
   1965 	dns_name_t *newname;
   1966 	const dns_name_t *origin;
   1967 	dns_fixedname_t fnewname;
   1968 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
   1969 	dns_sdlznode_t *sdlznode;
   1970 	isc_mem_t *mctx = sdlz->common.mctx;
   1971 	isc_buffer_t b;
   1972 	isc_result_t result;
   1973 
   1974 	newname = dns_fixedname_initname(&fnewname);
   1975 
   1976 	if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
   1977 		origin = &sdlz->common.origin;
   1978 	else
   1979 		origin = dns_rootname;
   1980 	isc_buffer_constinit(&b, name, strlen(name));
   1981 	isc_buffer_add(&b, strlen(name));
   1982 
   1983 	result = dns_name_fromtext(newname, &b, origin, 0, NULL);
   1984 	if (result != ISC_R_SUCCESS)
   1985 		return (result);
   1986 
   1987 	if (allnodes->common.relative_names) {
   1988 		/* All names are relative to the root */
   1989 		unsigned int nlabels = dns_name_countlabels(newname);
   1990 		dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
   1991 	}
   1992 
   1993 	sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
   1994 	if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
   1995 		sdlznode = NULL;
   1996 		result = createnode(sdlz, &sdlznode);
   1997 		if (result != ISC_R_SUCCESS)
   1998 			return (result);
   1999 		sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
   2000 		if (sdlznode->name == NULL) {
   2001 			destroynode(sdlznode);
   2002 			return (ISC_R_NOMEMORY);
   2003 		}
   2004 		dns_name_init(sdlznode->name, NULL);
   2005 		result = dns_name_dup(newname, mctx, sdlznode->name);
   2006 		if (result != ISC_R_SUCCESS) {
   2007 			isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
   2008 			destroynode(sdlznode);
   2009 			return (result);
   2010 		}
   2011 		ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
   2012 		if (allnodes->origin == NULL &&
   2013 		    dns_name_equal(newname, &sdlz->common.origin))
   2014 			allnodes->origin = sdlznode;
   2015 	}
   2016 	return (dns_sdlz_putrr(sdlznode, type, ttl, data));
   2017 
   2018 }
   2019 
   2020 isc_result_t
   2021 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
   2022 		uint32_t serial)
   2023 {
   2024 	char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
   2025 	int n;
   2026 
   2027 	REQUIRE(mname != NULL);
   2028 	REQUIRE(rname != NULL);
   2029 
   2030 	n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
   2031 		     mname, rname, serial,
   2032 		     SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
   2033 		     SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
   2034 	if (n >= (int)sizeof(str) || n < 0)
   2035 		return (ISC_R_NOSPACE);
   2036 	return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
   2037 }
   2038 
   2039 isc_result_t
   2040 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
   2041 		 void *driverarg, unsigned int flags, isc_mem_t *mctx,
   2042 		 dns_sdlzimplementation_t **sdlzimp)
   2043 {
   2044 
   2045 	dns_sdlzimplementation_t *imp;
   2046 	isc_result_t result;
   2047 
   2048 	/*
   2049 	 * Performs checks to make sure data is as we expect it to be.
   2050 	 */
   2051 	REQUIRE(drivername != NULL);
   2052 	REQUIRE(methods != NULL);
   2053 	REQUIRE(methods->findzone != NULL);
   2054 	REQUIRE(methods->lookup != NULL);
   2055 	REQUIRE(mctx != NULL);
   2056 	REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
   2057 	REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER |
   2058 			   DNS_SDLZFLAG_RELATIVERDATA |
   2059 			   DNS_SDLZFLAG_THREADSAFE)) == 0);
   2060 
   2061 	/* Write debugging message to log */
   2062 	sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
   2063 
   2064 	/*
   2065 	 * Allocate memory for a sdlz_implementation object.  Error if
   2066 	 * we cannot.
   2067 	 */
   2068 	imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
   2069 	if (imp == NULL)
   2070 		return (ISC_R_NOMEMORY);
   2071 
   2072 	/* Make sure memory region is set to all 0's */
   2073 	memset(imp, 0, sizeof(dns_sdlzimplementation_t));
   2074 
   2075 	/* Store the data passed into this method */
   2076 	imp->methods = methods;
   2077 	imp->driverarg = driverarg;
   2078 	imp->flags = flags;
   2079 	imp->mctx = NULL;
   2080 
   2081 	/* attach the new sdlz_implementation object to a memory context */
   2082 	isc_mem_attach(mctx, &imp->mctx);
   2083 
   2084 	/*
   2085 	 * initialize the driver lock, error if we cannot
   2086 	 * (used if a driver does not support multiple threads)
   2087 	 */
   2088 	isc_mutex_init(&imp->driverlock);
   2089 
   2090 	imp->dlz_imp = NULL;
   2091 
   2092 	/*
   2093 	 * register the DLZ driver.  Pass in our "extra" sdlz information as
   2094 	 * a driverarg.  (that's why we stored the passed in driver arg in our
   2095 	 * sdlz_implementation structure)  Also, store the dlz_implementation
   2096 	 * structure in our sdlz_implementation.
   2097 	 */
   2098 	result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
   2099 				 &imp->dlz_imp);
   2100 
   2101 	/* if registration fails, cleanup and get outta here. */
   2102 	if (result != ISC_R_SUCCESS)
   2103 		goto cleanup_mutex;
   2104 
   2105 	*sdlzimp = imp;
   2106 
   2107 	return (ISC_R_SUCCESS);
   2108 
   2109  cleanup_mutex:
   2110 	/* destroy the driver lock, we don't need it anymore */
   2111 	isc_mutex_destroy(&imp->driverlock);
   2112 
   2113 	/*
   2114 	 * return the memory back to the available memory pool and
   2115 	 * remove it from the memory context.
   2116 	 */
   2117 	isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
   2118 	isc_mem_detach(&mctx);
   2119 	return (result);
   2120 }
   2121 
   2122 void
   2123 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
   2124 	dns_sdlzimplementation_t *imp;
   2125 	isc_mem_t *mctx;
   2126 
   2127 	/* Write debugging message to log */
   2128 	sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
   2129 
   2130 	/*
   2131 	 * Performs checks to make sure data is as we expect it to be.
   2132 	 */
   2133 	REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
   2134 
   2135 	imp = *sdlzimp;
   2136 
   2137 	/* Unregister the DLZ driver implementation */
   2138 	dns_dlzunregister(&imp->dlz_imp);
   2139 
   2140 	/* destroy the driver lock, we don't need it anymore */
   2141 	isc_mutex_destroy(&imp->driverlock);
   2142 
   2143 	mctx = imp->mctx;
   2144 
   2145 	/*
   2146 	 * return the memory back to the available memory pool and
   2147 	 * remove it from the memory context.
   2148 	 */
   2149 	isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
   2150 	isc_mem_detach(&mctx);
   2151 
   2152 	*sdlzimp = NULL;
   2153 }
   2154 
   2155 
   2156 isc_result_t
   2157 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
   2158 	       const dns_name_t *name, dns_db_t **dbp)
   2159 {
   2160 	isc_result_t result;
   2161 
   2162 	result = dns_sdlzcreateDBP(dlzdatabase->mctx,
   2163 				   dlzdatabase->implementation->driverarg,
   2164 				   dlzdatabase->dbdata, name, rdclass, dbp);
   2165 	return (result);
   2166 }
   2167