Home | History | Annotate | Line # | Download | only in dns
sdlz.c revision 1.1.1.4
      1 /*	$NetBSD: sdlz.c,v 1.1.1.4 2019/11/24 19:57:57 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(sdlznode));
    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 		dns_name_copynf(xname, foundname);
   1039 	}
   1040 
   1041 	if (nodep != NULL)
   1042 		*nodep = node;
   1043 	else if (node != NULL)
   1044 		detachnode(db, &node);
   1045 
   1046 	return (result);
   1047 }
   1048 
   1049 static isc_result_t
   1050 find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
   1051      dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
   1052      dns_dbnode_t **nodep, dns_name_t *foundname,
   1053      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
   1054 {
   1055 	return (findext(db, name, version, type, options, now, nodep,
   1056 			foundname, NULL, NULL, rdataset, sigrdataset));
   1057 }
   1058 
   1059 static isc_result_t
   1060 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   1061 	     isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
   1062 {
   1063 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) db;
   1064 	sdlz_rdatasetiter_t *iterator;
   1065 
   1066 	REQUIRE(VALID_SDLZDB(sdlz));
   1067 
   1068 	REQUIRE(version == NULL ||
   1069 		version == (void*)&sdlz->dummy_version ||
   1070 		version == sdlz->future_version);
   1071 
   1072 	UNUSED(version);
   1073 	UNUSED(now);
   1074 
   1075 	iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
   1076 	if (iterator == NULL)
   1077 		return (ISC_R_NOMEMORY);
   1078 
   1079 	iterator->common.magic = DNS_RDATASETITER_MAGIC;
   1080 	iterator->common.methods = &rdatasetiter_methods;
   1081 	iterator->common.db = db;
   1082 	iterator->common.node = NULL;
   1083 	attachnode(db, node, &iterator->common.node);
   1084 	iterator->common.version = version;
   1085 	iterator->common.now = now;
   1086 
   1087 	*iteratorp = (dns_rdatasetiter_t *)iterator;
   1088 
   1089 	return (ISC_R_SUCCESS);
   1090 }
   1091 
   1092 static isc_result_t
   1093 modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   1094 	    dns_rdataset_t *rdataset, unsigned int options,
   1095 	    dns_sdlzmodrdataset_t mod_function)
   1096 {
   1097 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1098 	dns_master_style_t *style = NULL;
   1099 	isc_result_t result;
   1100 	isc_buffer_t *buffer = NULL;
   1101 	isc_mem_t *mctx;
   1102 	dns_sdlznode_t *sdlznode;
   1103 	char *rdatastr = NULL;
   1104 	char name[DNS_NAME_MAXTEXT + 1];
   1105 
   1106 	REQUIRE(VALID_SDLZDB(sdlz));
   1107 
   1108 	if (mod_function == NULL)
   1109 		return (ISC_R_NOTIMPLEMENTED);
   1110 
   1111 	sdlznode = (dns_sdlznode_t *)node;
   1112 
   1113 	UNUSED(options);
   1114 
   1115 	dns_name_format(sdlznode->name, name, sizeof(name));
   1116 
   1117 	mctx = sdlz->common.mctx;
   1118 
   1119 	result = isc_buffer_allocate(mctx, &buffer, 1024);
   1120 	if (result != ISC_R_SUCCESS)
   1121 		return (result);
   1122 
   1123 	result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1,
   1124 					0xffffffff, mctx);
   1125 	if (result != ISC_R_SUCCESS)
   1126 		goto cleanup;
   1127 
   1128 	result = dns_master_rdatasettotext(sdlznode->name, rdataset,
   1129 					   style, buffer);
   1130 	if (result != ISC_R_SUCCESS)
   1131 		goto cleanup;
   1132 
   1133 	if (isc_buffer_usedlength(buffer) < 1) {
   1134 		result = ISC_R_BADADDRESSFORM;
   1135 		goto cleanup;
   1136 	}
   1137 
   1138 	rdatastr = isc_buffer_base(buffer);
   1139 	if (rdatastr == NULL) {
   1140 		result = ISC_R_NOMEMORY;
   1141 		goto cleanup;
   1142 	}
   1143 	rdatastr[isc_buffer_usedlength(buffer) - 1] = 0;
   1144 
   1145 	MAYBE_LOCK(sdlz->dlzimp);
   1146 	result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg,
   1147 			      sdlz->dbdata, version);
   1148 	MAYBE_UNLOCK(sdlz->dlzimp);
   1149 
   1150 cleanup:
   1151 	isc_buffer_free(&buffer);
   1152 	if (style != NULL)
   1153 		dns_master_styledestroy(&style, mctx);
   1154 
   1155 	return (result);
   1156 }
   1157 
   1158 static isc_result_t
   1159 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   1160 	    isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
   1161 	    dns_rdataset_t *addedrdataset)
   1162 {
   1163 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1164 	isc_result_t result;
   1165 
   1166 	UNUSED(now);
   1167 	UNUSED(addedrdataset);
   1168 	REQUIRE(VALID_SDLZDB(sdlz));
   1169 
   1170 	if (sdlz->dlzimp->methods->addrdataset == NULL)
   1171 		return (ISC_R_NOTIMPLEMENTED);
   1172 
   1173 	result = modrdataset(db, node, version, rdataset, options,
   1174 			     sdlz->dlzimp->methods->addrdataset);
   1175 	return (result);
   1176 }
   1177 
   1178 
   1179 static isc_result_t
   1180 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   1181 		 dns_rdataset_t *rdataset, unsigned int options,
   1182 		 dns_rdataset_t *newrdataset)
   1183 {
   1184 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1185 	isc_result_t result;
   1186 
   1187 	UNUSED(newrdataset);
   1188 	REQUIRE(VALID_SDLZDB(sdlz));
   1189 
   1190 	if (sdlz->dlzimp->methods->subtractrdataset == NULL) {
   1191 		return (ISC_R_NOTIMPLEMENTED);
   1192 	}
   1193 
   1194 	result = modrdataset(db, node, version, rdataset, options,
   1195 			     sdlz->dlzimp->methods->subtractrdataset);
   1196 	return (result);
   1197 }
   1198 
   1199 static isc_result_t
   1200 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   1201 	       dns_rdatatype_t type, dns_rdatatype_t covers)
   1202 {
   1203 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1204 	char name[DNS_NAME_MAXTEXT + 1];
   1205 	char b_type[DNS_RDATATYPE_FORMATSIZE];
   1206 	dns_sdlznode_t *sdlznode;
   1207 	isc_result_t result;
   1208 
   1209 	UNUSED(covers);
   1210 
   1211 	REQUIRE(VALID_SDLZDB(sdlz));
   1212 
   1213 	if (sdlz->dlzimp->methods->delrdataset == NULL)
   1214 		return (ISC_R_NOTIMPLEMENTED);
   1215 
   1216 	sdlznode = (dns_sdlznode_t *)node;
   1217 	dns_name_format(sdlznode->name, name, sizeof(name));
   1218 	dns_rdatatype_format(type, b_type, sizeof(b_type));
   1219 
   1220 	MAYBE_LOCK(sdlz->dlzimp);
   1221 	result = sdlz->dlzimp->methods->delrdataset(name, b_type,
   1222 						    sdlz->dlzimp->driverarg,
   1223 						    sdlz->dbdata, version);
   1224 	MAYBE_UNLOCK(sdlz->dlzimp);
   1225 
   1226 	return (result);
   1227 }
   1228 
   1229 static bool
   1230 issecure(dns_db_t *db) {
   1231 	UNUSED(db);
   1232 
   1233 	return (false);
   1234 }
   1235 
   1236 static unsigned int
   1237 nodecount(dns_db_t *db) {
   1238 	UNUSED(db);
   1239 
   1240 	return (0);
   1241 }
   1242 
   1243 static bool
   1244 ispersistent(dns_db_t *db) {
   1245 	UNUSED(db);
   1246 	return (true);
   1247 }
   1248 
   1249 static void
   1250 overmem(dns_db_t *db, bool over) {
   1251 	UNUSED(db);
   1252 	UNUSED(over);
   1253 }
   1254 
   1255 static void
   1256 settask(dns_db_t *db, isc_task_t *task) {
   1257 	UNUSED(db);
   1258 	UNUSED(task);
   1259 }
   1260 
   1261 /*
   1262  * getoriginnode() is used by the update code to find the
   1263  * dns_rdatatype_dnskey record for a zone
   1264  */
   1265 static isc_result_t
   1266 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
   1267 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1268 	isc_result_t result;
   1269 
   1270 	REQUIRE(VALID_SDLZDB(sdlz));
   1271 	if (sdlz->dlzimp->methods->newversion == NULL)
   1272 		return (ISC_R_NOTIMPLEMENTED);
   1273 
   1274 	result = getnodedata(db, &sdlz->common.origin, false,
   1275 			     0, NULL, NULL, nodep);
   1276 	if (result != ISC_R_SUCCESS)
   1277 		sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s",
   1278 			 isc_result_totext(result));
   1279 	return (result);
   1280 }
   1281 
   1282 static dns_dbmethods_t sdlzdb_methods = {
   1283 	attach,
   1284 	detach,
   1285 	beginload,
   1286 	endload,
   1287 	NULL,			/* serialize */
   1288 	dump,
   1289 	currentversion,
   1290 	newversion,
   1291 	attachversion,
   1292 	closeversion,
   1293 	findnode,
   1294 	find,
   1295 	findzonecut,
   1296 	attachnode,
   1297 	detachnode,
   1298 	expirenode,
   1299 	printnode,
   1300 	createiterator,
   1301 	findrdataset,
   1302 	allrdatasets,
   1303 	addrdataset,
   1304 	subtractrdataset,
   1305 	deleterdataset,
   1306 	issecure,
   1307 	nodecount,
   1308 	ispersistent,
   1309 	overmem,
   1310 	settask,
   1311 	getoriginnode,
   1312 	NULL,			/* transfernode */
   1313 	NULL,			/* getnsec3parameters */
   1314 	NULL,			/* findnsec3node */
   1315 	NULL,			/* setsigningtime */
   1316 	NULL,			/* getsigningtime */
   1317 	NULL,			/* resigned */
   1318 	NULL,			/* isdnssec */
   1319 	NULL,			/* getrrsetstats */
   1320 	NULL,			/* rpz_attach */
   1321 	NULL,			/* rpz_ready */
   1322 	findnodeext,
   1323 	findext,
   1324 	NULL,			/* setcachestats */
   1325 	NULL,			/* hashsize */
   1326 	NULL,			/* nodefullname */
   1327 	NULL,			/* getsize */
   1328 	NULL,			/* setservestalettl */
   1329 	NULL,			/* getservestalettl */
   1330 	NULL			/* setgluecachestats */
   1331 };
   1332 
   1333 /*
   1334  * Database Iterator Methods.  These methods were "borrowed" from the SDB
   1335  * driver interface.  See the SDB driver interface documentation for more info.
   1336  */
   1337 
   1338 static void
   1339 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
   1340 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
   1341 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
   1342 
   1343 	while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
   1344 		dns_sdlznode_t *node;
   1345 		node = ISC_LIST_HEAD(sdlziter->nodelist);
   1346 		ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
   1347 		destroynode(node);
   1348 	}
   1349 
   1350 	dns_db_detach(&sdlziter->common.db);
   1351 	isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
   1352 
   1353 	*iteratorp = NULL;
   1354 }
   1355 
   1356 static isc_result_t
   1357 dbiterator_first(dns_dbiterator_t *iterator) {
   1358 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1359 
   1360 	sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
   1361 	if (sdlziter->current == NULL)
   1362 		return (ISC_R_NOMORE);
   1363 	else
   1364 		return (ISC_R_SUCCESS);
   1365 }
   1366 
   1367 static isc_result_t
   1368 dbiterator_last(dns_dbiterator_t *iterator) {
   1369 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1370 
   1371 	sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
   1372 	if (sdlziter->current == NULL)
   1373 		return (ISC_R_NOMORE);
   1374 	else
   1375 		return (ISC_R_SUCCESS);
   1376 }
   1377 
   1378 static isc_result_t
   1379 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) {
   1380 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1381 
   1382 	sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
   1383 	while (sdlziter->current != NULL) {
   1384 		if (dns_name_equal(sdlziter->current->name, name))
   1385 			return (ISC_R_SUCCESS);
   1386 		sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
   1387 	}
   1388 	return (ISC_R_NOTFOUND);
   1389 }
   1390 
   1391 static isc_result_t
   1392 dbiterator_prev(dns_dbiterator_t *iterator) {
   1393 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1394 
   1395 	sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
   1396 	if (sdlziter->current == NULL)
   1397 		return (ISC_R_NOMORE);
   1398 	else
   1399 		return (ISC_R_SUCCESS);
   1400 }
   1401 
   1402 static isc_result_t
   1403 dbiterator_next(dns_dbiterator_t *iterator) {
   1404 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1405 
   1406 	sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
   1407 	if (sdlziter->current == NULL)
   1408 		return (ISC_R_NOMORE);
   1409 	else
   1410 		return (ISC_R_SUCCESS);
   1411 }
   1412 
   1413 static isc_result_t
   1414 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
   1415 		   dns_name_t *name)
   1416 {
   1417 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1418 
   1419 	attachnode(iterator->db, sdlziter->current, nodep);
   1420 	if (name != NULL) {
   1421 		dns_name_copynf(sdlziter->current->name, name);
   1422 		return (ISC_R_SUCCESS);
   1423 	}
   1424 	return (ISC_R_SUCCESS);
   1425 }
   1426 
   1427 static isc_result_t
   1428 dbiterator_pause(dns_dbiterator_t *iterator) {
   1429 	UNUSED(iterator);
   1430 	return (ISC_R_SUCCESS);
   1431 }
   1432 
   1433 static isc_result_t
   1434 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
   1435 	UNUSED(iterator);
   1436 	dns_name_copynf(dns_rootname, name);
   1437 	return (ISC_R_SUCCESS);
   1438 }
   1439 
   1440 /*
   1441  * Rdataset Methods. These methods were "borrowed" from the SDB driver
   1442  * interface.  See the SDB driver interface documentation for more info.
   1443  */
   1444 
   1445 static void
   1446 disassociate(dns_rdataset_t *rdataset) {
   1447 	dns_dbnode_t *node = rdataset->private5;
   1448 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
   1449 	dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
   1450 
   1451 	detachnode(db, &node);
   1452 	isc__rdatalist_disassociate(rdataset);
   1453 }
   1454 
   1455 static void
   1456 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
   1457 	dns_dbnode_t *node = source->private5;
   1458 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
   1459 	dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
   1460 	dns_dbnode_t *tempdb = NULL;
   1461 
   1462 	isc__rdatalist_clone(source, target);
   1463 	attachnode(db, node, &tempdb);
   1464 	source->private5 = tempdb;
   1465 }
   1466 
   1467 static dns_rdatasetmethods_t rdataset_methods = {
   1468 	disassociate,
   1469 	isc__rdatalist_first,
   1470 	isc__rdatalist_next,
   1471 	isc__rdatalist_current,
   1472 	rdataset_clone,
   1473 	isc__rdatalist_count,
   1474 	isc__rdatalist_addnoqname,
   1475 	isc__rdatalist_getnoqname,
   1476 	NULL, /* addclosest */
   1477 	NULL, /* getclosest */
   1478 	NULL, /* settrust */
   1479 	NULL, /* expire */
   1480 	NULL, /* clearprefetch */
   1481 	NULL, /* setownercase */
   1482 	NULL, /* getownercase */
   1483 	NULL  /* addglue */
   1484 };
   1485 
   1486 static void
   1487 list_tordataset(dns_rdatalist_t *rdatalist,
   1488 		dns_db_t *db, dns_dbnode_t *node,
   1489 		dns_rdataset_t *rdataset)
   1490 {
   1491 	/*
   1492 	 * The sdlz rdataset is an rdatalist with some additions.
   1493 	 *	- private1 & private2 are used by the rdatalist.
   1494 	 *	- private3 & private 4 are unused.
   1495 	 *	- private5 is the node.
   1496 	 */
   1497 
   1498 	/* This should never fail. */
   1499 	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
   1500 		      ISC_R_SUCCESS);
   1501 
   1502 	rdataset->methods = &rdataset_methods;
   1503 	dns_db_attachnode(db, node, &rdataset->private5);
   1504 }
   1505 
   1506 /*
   1507  * SDLZ core methods. This is the core of the new DLZ functionality.
   1508  */
   1509 
   1510 /*%
   1511  * Build a 'bind' database driver structure to be returned by
   1512  * either the find zone or the allow zone transfer method.
   1513  * This method is only available in this source file, it is
   1514  * not made available anywhere else.
   1515  */
   1516 
   1517 static isc_result_t
   1518 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
   1519 		  const dns_name_t *name, dns_rdataclass_t rdclass,
   1520 		  dns_db_t **dbp)
   1521 {
   1522 	isc_result_t result;
   1523 	dns_sdlz_db_t *sdlzdb;
   1524 	dns_sdlzimplementation_t *imp;
   1525 
   1526 	/* check that things are as we expect */
   1527 	REQUIRE(dbp != NULL && *dbp == NULL);
   1528 	REQUIRE(name != NULL);
   1529 
   1530 	imp = (dns_sdlzimplementation_t *) driverarg;
   1531 
   1532 	/* allocate and zero memory for driver structure */
   1533 	sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
   1534 	if (sdlzdb == NULL)
   1535 		return (ISC_R_NOMEMORY);
   1536 	memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
   1537 
   1538 	/* initialize and set origin */
   1539 	dns_name_init(&sdlzdb->common.origin, NULL);
   1540 	result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
   1541 	if (result != ISC_R_SUCCESS)
   1542 		goto mem_cleanup;
   1543 
   1544 	/* initialize the reference count mutex */
   1545 	isc_mutex_init(&sdlzdb->refcnt_lock);
   1546 
   1547 	/* set the rest of the database structure attributes */
   1548 	sdlzdb->dlzimp = imp;
   1549 	sdlzdb->common.methods = &sdlzdb_methods;
   1550 	sdlzdb->common.attributes = 0;
   1551 	sdlzdb->common.rdclass = rdclass;
   1552 	sdlzdb->common.mctx = NULL;
   1553 	sdlzdb->dbdata = dbdata;
   1554 	sdlzdb->references = 1;
   1555 
   1556 	/* attach to the memory context */
   1557 	isc_mem_attach(mctx, &sdlzdb->common.mctx);
   1558 
   1559 	/* mark structure as valid */
   1560 	sdlzdb->common.magic = DNS_DB_MAGIC;
   1561 	sdlzdb->common.impmagic = SDLZDB_MAGIC;
   1562 	*dbp = (dns_db_t *) sdlzdb;
   1563 
   1564 	return (result);
   1565  mem_cleanup:
   1566 	isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
   1567 	return (result);
   1568 }
   1569 
   1570 static isc_result_t
   1571 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
   1572 		     dns_rdataclass_t rdclass, const dns_name_t *name,
   1573 		     const isc_sockaddr_t *clientaddr, dns_db_t **dbp)
   1574 {
   1575 	isc_buffer_t b;
   1576 	isc_buffer_t b2;
   1577 	char namestr[DNS_NAME_MAXTEXT + 1];
   1578 	char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
   1579 		       + 1];
   1580 	isc_netaddr_t netaddr;
   1581 	isc_result_t result;
   1582 	dns_sdlzimplementation_t *imp;
   1583 
   1584 	/*
   1585 	 * Perform checks to make sure data is as we expect it to be.
   1586 	 */
   1587 	REQUIRE(driverarg != NULL);
   1588 	REQUIRE(name != NULL);
   1589 	REQUIRE(clientaddr != NULL);
   1590 	REQUIRE(dbp != NULL && *dbp == NULL);
   1591 
   1592 	imp = (dns_sdlzimplementation_t *) driverarg;
   1593 
   1594 	/* Convert DNS name to ascii text */
   1595 	isc_buffer_init(&b, namestr, sizeof(namestr));
   1596 	result = dns_name_totext(name, true, &b);
   1597 	if (result != ISC_R_SUCCESS)
   1598 		return (result);
   1599 	isc_buffer_putuint8(&b, 0);
   1600 
   1601 	/* convert client address to ascii text */
   1602 	isc_buffer_init(&b2, clientstr, sizeof(clientstr));
   1603 	isc_netaddr_fromsockaddr(&netaddr, clientaddr);
   1604 	result = isc_netaddr_totext(&netaddr, &b2);
   1605 	if (result != ISC_R_SUCCESS)
   1606 		return (result);
   1607 	isc_buffer_putuint8(&b2, 0);
   1608 
   1609 	/* make sure strings are always lowercase */
   1610 	dns_sdlz_tolower(namestr);
   1611 	dns_sdlz_tolower(clientstr);
   1612 
   1613 	/* Call SDLZ driver's find zone method */
   1614 	if (imp->methods->allowzonexfr != NULL) {
   1615 		MAYBE_LOCK(imp);
   1616 		result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
   1617 						    namestr, clientstr);
   1618 		MAYBE_UNLOCK(imp);
   1619 		/*
   1620 		 * if zone is supported and transfers allowed build a 'bind'
   1621 		 * database driver
   1622 		 */
   1623 		if (result == ISC_R_SUCCESS)
   1624 			result = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
   1625 						   name, rdclass, dbp);
   1626 		return (result);
   1627 	}
   1628 
   1629 	return (ISC_R_NOTIMPLEMENTED);
   1630 }
   1631 
   1632 static isc_result_t
   1633 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
   1634 	       char *argv[], void *driverarg, void **dbdata)
   1635 {
   1636 	dns_sdlzimplementation_t *imp;
   1637 	isc_result_t result = ISC_R_NOTFOUND;
   1638 
   1639 	/* Write debugging message to log */
   1640 	sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
   1641 
   1642 	/*
   1643 	 * Performs checks to make sure data is as we expect it to be.
   1644 	 */
   1645 	REQUIRE(driverarg != NULL);
   1646 	REQUIRE(dlzname != NULL);
   1647 	REQUIRE(dbdata != NULL);
   1648 	UNUSED(mctx);
   1649 
   1650 	imp = driverarg;
   1651 
   1652 	/* If the create method exists, call it. */
   1653 	if (imp->methods->create != NULL) {
   1654 		MAYBE_LOCK(imp);
   1655 		result = imp->methods->create(dlzname, argc, argv,
   1656 					      imp->driverarg, dbdata);
   1657 		MAYBE_UNLOCK(imp);
   1658 	}
   1659 
   1660 	/* Write debugging message to log */
   1661 	if (result == ISC_R_SUCCESS) {
   1662 		sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
   1663 	} else {
   1664 		sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
   1665 	}
   1666 
   1667 	return (result);
   1668 }
   1669 
   1670 static void
   1671 dns_sdlzdestroy(void *driverdata, void **dbdata) {
   1672 	dns_sdlzimplementation_t *imp;
   1673 
   1674 	/* Write debugging message to log */
   1675 	sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
   1676 
   1677 	imp = driverdata;
   1678 
   1679 	/* If the destroy method exists, call it. */
   1680 	if (imp->methods->destroy != NULL) {
   1681 		MAYBE_LOCK(imp);
   1682 		imp->methods->destroy(imp->driverarg, dbdata);
   1683 		MAYBE_UNLOCK(imp);
   1684 	}
   1685 }
   1686 
   1687 static isc_result_t
   1688 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
   1689 		 dns_rdataclass_t rdclass, const dns_name_t *name,
   1690 		 dns_clientinfomethods_t *methods,
   1691 		 dns_clientinfo_t *clientinfo,
   1692 		 dns_db_t **dbp)
   1693 {
   1694 	isc_buffer_t b;
   1695 	char namestr[DNS_NAME_MAXTEXT + 1];
   1696 	isc_result_t result;
   1697 	dns_sdlzimplementation_t *imp;
   1698 
   1699 	/*
   1700 	 * Perform checks to make sure data is as we expect it to be.
   1701 	 */
   1702 	REQUIRE(driverarg != NULL);
   1703 	REQUIRE(name != NULL);
   1704 	REQUIRE(dbp != NULL && *dbp == NULL);
   1705 
   1706 	imp = (dns_sdlzimplementation_t *) driverarg;
   1707 
   1708 	/* Convert DNS name to ascii text */
   1709 	isc_buffer_init(&b, namestr, sizeof(namestr));
   1710 	result = dns_name_totext(name, true, &b);
   1711 	if (result != ISC_R_SUCCESS)
   1712 		return (result);
   1713 	isc_buffer_putuint8(&b, 0);
   1714 
   1715 	/* make sure strings are always lowercase */
   1716 	dns_sdlz_tolower(namestr);
   1717 
   1718 	/* Call SDLZ driver's find zone method */
   1719 	MAYBE_LOCK(imp);
   1720 	result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
   1721 					methods, clientinfo);
   1722 	MAYBE_UNLOCK(imp);
   1723 
   1724 	/*
   1725 	 * if zone is supported build a 'bind' database driver
   1726 	 * structure to return
   1727 	 */
   1728 	if (result == ISC_R_SUCCESS)
   1729 		result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
   1730 					   rdclass, dbp);
   1731 
   1732 	return (result);
   1733 }
   1734 
   1735 
   1736 static isc_result_t
   1737 dns_sdlzconfigure(void *driverarg, void *dbdata,
   1738 		  dns_view_t *view, dns_dlzdb_t *dlzdb)
   1739 {
   1740 	isc_result_t result;
   1741 	dns_sdlzimplementation_t *imp;
   1742 
   1743 	REQUIRE(driverarg != NULL);
   1744 
   1745 	imp = (dns_sdlzimplementation_t *) driverarg;
   1746 
   1747 	/* Call SDLZ driver's configure method */
   1748 	if (imp->methods->configure != NULL) {
   1749 		MAYBE_LOCK(imp);
   1750 		result = imp->methods->configure(view, dlzdb,
   1751 						 imp->driverarg, dbdata);
   1752 		MAYBE_UNLOCK(imp);
   1753 	} else {
   1754 		result = ISC_R_SUCCESS;
   1755 	}
   1756 
   1757 	return (result);
   1758 }
   1759 
   1760 static bool
   1761 dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name,
   1762 		 const isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
   1763 		 const dst_key_t *key, void *driverarg, void *dbdata)
   1764 {
   1765 	dns_sdlzimplementation_t *imp;
   1766 	char b_signer[DNS_NAME_FORMATSIZE];
   1767 	char b_name[DNS_NAME_FORMATSIZE];
   1768 	char b_addr[ISC_NETADDR_FORMATSIZE];
   1769 	char b_type[DNS_RDATATYPE_FORMATSIZE];
   1770 	char b_key[DST_KEY_FORMATSIZE];
   1771 	isc_buffer_t *tkey_token = NULL;
   1772 	isc_region_t token_region = { NULL, 0 };
   1773 	uint32_t token_len = 0;
   1774 	bool ret;
   1775 
   1776 	REQUIRE(driverarg != NULL);
   1777 
   1778 	imp = (dns_sdlzimplementation_t *) driverarg;
   1779 	if (imp->methods->ssumatch == NULL)
   1780 		return (false);
   1781 
   1782 	/*
   1783 	 * Format the request elements. sdlz operates on strings, not
   1784 	 * structures
   1785 	 */
   1786 	if (signer != NULL)
   1787 		dns_name_format(signer, b_signer, sizeof(b_signer));
   1788 	else
   1789 		b_signer[0] = 0;
   1790 
   1791 	dns_name_format(name, b_name, sizeof(b_name));
   1792 
   1793 	if (tcpaddr != NULL)
   1794 		isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
   1795 	else
   1796 		b_addr[0] = 0;
   1797 
   1798 	dns_rdatatype_format(type, b_type, sizeof(b_type));
   1799 
   1800 	if (key != NULL) {
   1801 		dst_key_format(key, b_key, sizeof(b_key));
   1802 		tkey_token = dst_key_tkeytoken(key);
   1803 	} else
   1804 		b_key[0] = 0;
   1805 
   1806 	if (tkey_token != NULL) {
   1807 		isc_buffer_region(tkey_token, &token_region);
   1808 		token_len = token_region.length;
   1809 	}
   1810 
   1811 	MAYBE_LOCK(imp);
   1812 	ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
   1813 				     token_len,
   1814 				     token_len != 0 ? token_region.base : NULL,
   1815 				     imp->driverarg, dbdata);
   1816 	MAYBE_UNLOCK(imp);
   1817 	return (ret);
   1818 }
   1819 
   1820 static dns_dlzmethods_t sdlzmethods = {
   1821 	dns_sdlzcreate,
   1822 	dns_sdlzdestroy,
   1823 	dns_sdlzfindzone,
   1824 	dns_sdlzallowzonexfr,
   1825 	dns_sdlzconfigure,
   1826 	dns_sdlzssumatch
   1827 };
   1828 
   1829 /*
   1830  * Public functions.
   1831  */
   1832 
   1833 isc_result_t
   1834 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
   1835 	       const char *data)
   1836 {
   1837 	dns_rdatalist_t *rdatalist;
   1838 	dns_rdata_t *rdata;
   1839 	dns_rdatatype_t typeval;
   1840 	isc_consttextregion_t r;
   1841 	isc_buffer_t b;
   1842 	isc_buffer_t *rdatabuf = NULL;
   1843 	isc_lex_t *lex;
   1844 	isc_result_t result;
   1845 	unsigned int size;
   1846 	isc_mem_t *mctx;
   1847 	const dns_name_t *origin;
   1848 
   1849 	REQUIRE(VALID_SDLZLOOKUP(lookup));
   1850 	REQUIRE(type != NULL);
   1851 	REQUIRE(data != NULL);
   1852 
   1853 	mctx = lookup->sdlz->common.mctx;
   1854 
   1855 	r.base = type;
   1856 	r.length = strlen(type);
   1857 	result = dns_rdatatype_fromtext(&typeval, (void *) &r);
   1858 	if (result != ISC_R_SUCCESS)
   1859 		return (result);
   1860 
   1861 	rdatalist = ISC_LIST_HEAD(lookup->lists);
   1862 	while (rdatalist != NULL) {
   1863 		if (rdatalist->type == typeval)
   1864 			break;
   1865 		rdatalist = ISC_LIST_NEXT(rdatalist, link);
   1866 	}
   1867 
   1868 	if (rdatalist == NULL) {
   1869 		rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
   1870 		if (rdatalist == NULL)
   1871 			return (ISC_R_NOMEMORY);
   1872 		dns_rdatalist_init(rdatalist);
   1873 		rdatalist->rdclass = lookup->sdlz->common.rdclass;
   1874 		rdatalist->type = typeval;
   1875 		rdatalist->ttl = ttl;
   1876 		ISC_LIST_APPEND(lookup->lists, rdatalist, link);
   1877 	} else
   1878 		if (rdatalist->ttl > ttl) {
   1879 			/*
   1880 			 * BIND9 doesn't enforce all RRs in an RRset
   1881 			 * having the same TTL, as per RFC 2136,
   1882 			 * section 7.12. If a DLZ backend has
   1883 			 * different TTLs, then the best
   1884 			 * we can do is return the lowest.
   1885 			*/
   1886 			rdatalist->ttl = ttl;
   1887 		}
   1888 
   1889 	rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
   1890 	if (rdata == NULL)
   1891 		return (ISC_R_NOMEMORY);
   1892 	dns_rdata_init(rdata);
   1893 
   1894 	if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
   1895 		origin = &lookup->sdlz->common.origin;
   1896 	else
   1897 		origin = dns_rootname;
   1898 
   1899 	lex = NULL;
   1900 	result = isc_lex_create(mctx, 64, &lex);
   1901 	if (result != ISC_R_SUCCESS)
   1902 		goto failure;
   1903 
   1904 	size = initial_size(data);
   1905 	do {
   1906 		isc_buffer_constinit(&b, data, strlen(data));
   1907 		isc_buffer_add(&b, strlen(data));
   1908 
   1909 		result = isc_lex_openbuffer(lex, &b);
   1910 		if (result != ISC_R_SUCCESS)
   1911 			goto failure;
   1912 
   1913 		rdatabuf = NULL;
   1914 		result = isc_buffer_allocate(mctx, &rdatabuf, size);
   1915 		if (result != ISC_R_SUCCESS)
   1916 			goto failure;
   1917 
   1918 		result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
   1919 					    rdatalist->type, lex,
   1920 					    origin, false,
   1921 					    mctx, rdatabuf,
   1922 					    &lookup->callbacks);
   1923 		if (result != ISC_R_SUCCESS) {
   1924 			isc_buffer_free(&rdatabuf);
   1925 			result = DNS_R_SERVFAIL;
   1926 		}
   1927 		if (size >= 65535)
   1928 			break;
   1929 		size *= 2;
   1930 		if (size >= 65535)
   1931 			size = 65535;
   1932 	} while (result == ISC_R_NOSPACE);
   1933 
   1934 	if (result != ISC_R_SUCCESS)
   1935 		goto failure;
   1936 
   1937 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
   1938 	ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
   1939 
   1940 	if (lex != NULL)
   1941 		isc_lex_destroy(&lex);
   1942 
   1943 	return (ISC_R_SUCCESS);
   1944 
   1945  failure:
   1946 	if (rdatabuf != NULL)
   1947 		isc_buffer_free(&rdatabuf);
   1948 	if (lex != NULL)
   1949 		isc_lex_destroy(&lex);
   1950 	isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
   1951 
   1952 	return (result);
   1953 }
   1954 
   1955 isc_result_t
   1956 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
   1957 		    const char *type, dns_ttl_t ttl, const char *data)
   1958 {
   1959 	dns_name_t *newname;
   1960 	const dns_name_t *origin;
   1961 	dns_fixedname_t fnewname;
   1962 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
   1963 	dns_sdlznode_t *sdlznode;
   1964 	isc_mem_t *mctx = sdlz->common.mctx;
   1965 	isc_buffer_t b;
   1966 	isc_result_t result;
   1967 
   1968 	newname = dns_fixedname_initname(&fnewname);
   1969 
   1970 	if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
   1971 		origin = &sdlz->common.origin;
   1972 	else
   1973 		origin = dns_rootname;
   1974 	isc_buffer_constinit(&b, name, strlen(name));
   1975 	isc_buffer_add(&b, strlen(name));
   1976 
   1977 	result = dns_name_fromtext(newname, &b, origin, 0, NULL);
   1978 	if (result != ISC_R_SUCCESS)
   1979 		return (result);
   1980 
   1981 	if (allnodes->common.relative_names) {
   1982 		/* All names are relative to the root */
   1983 		unsigned int nlabels = dns_name_countlabels(newname);
   1984 		dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
   1985 	}
   1986 
   1987 	sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
   1988 	if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
   1989 		sdlznode = NULL;
   1990 		result = createnode(sdlz, &sdlznode);
   1991 		if (result != ISC_R_SUCCESS)
   1992 			return (result);
   1993 		sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
   1994 		if (sdlznode->name == NULL) {
   1995 			destroynode(sdlznode);
   1996 			return (ISC_R_NOMEMORY);
   1997 		}
   1998 		dns_name_init(sdlznode->name, NULL);
   1999 		result = dns_name_dup(newname, mctx, sdlznode->name);
   2000 		if (result != ISC_R_SUCCESS) {
   2001 			isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
   2002 			destroynode(sdlznode);
   2003 			return (result);
   2004 		}
   2005 		ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
   2006 		if (allnodes->origin == NULL &&
   2007 		    dns_name_equal(newname, &sdlz->common.origin))
   2008 			allnodes->origin = sdlznode;
   2009 	}
   2010 	return (dns_sdlz_putrr(sdlznode, type, ttl, data));
   2011 
   2012 }
   2013 
   2014 isc_result_t
   2015 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
   2016 		uint32_t serial)
   2017 {
   2018 	char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
   2019 	int n;
   2020 
   2021 	REQUIRE(mname != NULL);
   2022 	REQUIRE(rname != NULL);
   2023 
   2024 	n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
   2025 		     mname, rname, serial,
   2026 		     SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
   2027 		     SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
   2028 	if (n >= (int)sizeof(str) || n < 0)
   2029 		return (ISC_R_NOSPACE);
   2030 	return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
   2031 }
   2032 
   2033 isc_result_t
   2034 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
   2035 		 void *driverarg, unsigned int flags, isc_mem_t *mctx,
   2036 		 dns_sdlzimplementation_t **sdlzimp)
   2037 {
   2038 
   2039 	dns_sdlzimplementation_t *imp;
   2040 	isc_result_t result;
   2041 
   2042 	/*
   2043 	 * Performs checks to make sure data is as we expect it to be.
   2044 	 */
   2045 	REQUIRE(drivername != NULL);
   2046 	REQUIRE(methods != NULL);
   2047 	REQUIRE(methods->findzone != NULL);
   2048 	REQUIRE(methods->lookup != NULL);
   2049 	REQUIRE(mctx != NULL);
   2050 	REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
   2051 	REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER |
   2052 			   DNS_SDLZFLAG_RELATIVERDATA |
   2053 			   DNS_SDLZFLAG_THREADSAFE)) == 0);
   2054 
   2055 	/* Write debugging message to log */
   2056 	sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
   2057 
   2058 	/*
   2059 	 * Allocate memory for a sdlz_implementation object.  Error if
   2060 	 * we cannot.
   2061 	 */
   2062 	imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
   2063 	if (imp == NULL)
   2064 		return (ISC_R_NOMEMORY);
   2065 
   2066 	/* Make sure memory region is set to all 0's */
   2067 	memset(imp, 0, sizeof(dns_sdlzimplementation_t));
   2068 
   2069 	/* Store the data passed into this method */
   2070 	imp->methods = methods;
   2071 	imp->driverarg = driverarg;
   2072 	imp->flags = flags;
   2073 	imp->mctx = NULL;
   2074 
   2075 	/* attach the new sdlz_implementation object to a memory context */
   2076 	isc_mem_attach(mctx, &imp->mctx);
   2077 
   2078 	/*
   2079 	 * initialize the driver lock, error if we cannot
   2080 	 * (used if a driver does not support multiple threads)
   2081 	 */
   2082 	isc_mutex_init(&imp->driverlock);
   2083 
   2084 	imp->dlz_imp = NULL;
   2085 
   2086 	/*
   2087 	 * register the DLZ driver.  Pass in our "extra" sdlz information as
   2088 	 * a driverarg.  (that's why we stored the passed in driver arg in our
   2089 	 * sdlz_implementation structure)  Also, store the dlz_implementation
   2090 	 * structure in our sdlz_implementation.
   2091 	 */
   2092 	result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
   2093 				 &imp->dlz_imp);
   2094 
   2095 	/* if registration fails, cleanup and get outta here. */
   2096 	if (result != ISC_R_SUCCESS)
   2097 		goto cleanup_mutex;
   2098 
   2099 	*sdlzimp = imp;
   2100 
   2101 	return (ISC_R_SUCCESS);
   2102 
   2103  cleanup_mutex:
   2104 	/* destroy the driver lock, we don't need it anymore */
   2105 	isc_mutex_destroy(&imp->driverlock);
   2106 
   2107 	/*
   2108 	 * return the memory back to the available memory pool and
   2109 	 * remove it from the memory context.
   2110 	 */
   2111 	isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
   2112 	isc_mem_detach(&mctx);
   2113 	return (result);
   2114 }
   2115 
   2116 void
   2117 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
   2118 	dns_sdlzimplementation_t *imp;
   2119 	isc_mem_t *mctx;
   2120 
   2121 	/* Write debugging message to log */
   2122 	sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
   2123 
   2124 	/*
   2125 	 * Performs checks to make sure data is as we expect it to be.
   2126 	 */
   2127 	REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
   2128 
   2129 	imp = *sdlzimp;
   2130 
   2131 	/* Unregister the DLZ driver implementation */
   2132 	dns_dlzunregister(&imp->dlz_imp);
   2133 
   2134 	/* destroy the driver lock, we don't need it anymore */
   2135 	isc_mutex_destroy(&imp->driverlock);
   2136 
   2137 	mctx = imp->mctx;
   2138 
   2139 	/*
   2140 	 * return the memory back to the available memory pool and
   2141 	 * remove it from the memory context.
   2142 	 */
   2143 	isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
   2144 	isc_mem_detach(&mctx);
   2145 
   2146 	*sdlzimp = NULL;
   2147 }
   2148 
   2149 
   2150 isc_result_t
   2151 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
   2152 	       const dns_name_t *name, dns_db_t **dbp)
   2153 {
   2154 	isc_result_t result;
   2155 
   2156 	result = dns_sdlzcreateDBP(dlzdatabase->mctx,
   2157 				   dlzdatabase->implementation->driverarg,
   2158 				   dlzdatabase->dbdata, name, rdclass, dbp);
   2159 	return (result);
   2160 }
   2161