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