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