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