Home | History | Annotate | Line # | Download | only in dns
sdlz.c revision 1.10.2.1
      1 /*	$NetBSD: sdlz.c,v 1.10.2.1 2023/08/11 13:43:35 martin Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0 AND ISC
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 /*
     17  * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting (at) nlnet.nl.
     18  *
     19  * Permission to use, copy, modify, and distribute this software for any
     20  * purpose with or without fee is hereby granted, provided that the
     21  * above copyright notice and this permission notice appear in all
     22  * copies.
     23  *
     24  * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
     25  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
     27  * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
     28  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
     29  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
     30  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
     31  * USE OR PERFORMANCE OF THIS SOFTWARE.
     32  *
     33  * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
     34  * conceived and contributed by Rob Butler.
     35  *
     36  * Permission to use, copy, modify, and distribute this software for any
     37  * purpose with or without fee is hereby granted, provided that the
     38  * above copyright notice and this permission notice appear in all
     39  * copies.
     40  *
     41  * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
     42  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
     43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
     44  * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
     45  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
     46  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
     47  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
     48  * USE OR PERFORMANCE OF THIS SOFTWARE.
     49  */
     50 
     51 /*! \file */
     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/magic.h>
     61 #include <isc/mem.h>
     62 #include <isc/once.h>
     63 #include <isc/print.h>
     64 #include <isc/region.h>
     65 #include <isc/rwlock.h>
     66 #include <isc/string.h>
     67 #include <isc/util.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/master.h>
     76 #include <dns/rdata.h>
     77 #include <dns/rdatalist.h>
     78 #include <dns/rdataset.h>
     79 #include <dns/rdatasetiter.h>
     80 #include <dns/rdatatype.h>
     81 #include <dns/result.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 
    106 	/* Atomic */
    107 	isc_refcount_t references;
    108 
    109 	/* Locked */
    110 	dns_dbversion_t *future_version;
    111 	int dummy_version;
    112 };
    113 
    114 struct dns_sdlzlookup {
    115 	/* Unlocked */
    116 	unsigned int magic;
    117 	dns_sdlz_db_t *sdlz;
    118 	ISC_LIST(dns_rdatalist_t) lists;
    119 	ISC_LIST(isc_buffer_t) buffers;
    120 	dns_name_t *name;
    121 	ISC_LINK(dns_sdlzlookup_t) link;
    122 	dns_rdatacallbacks_t callbacks;
    123 
    124 	/* Atomic */
    125 	isc_refcount_t references;
    126 };
    127 
    128 typedef struct dns_sdlzlookup dns_sdlznode_t;
    129 
    130 struct dns_sdlzallnodes {
    131 	dns_dbiterator_t common;
    132 	ISC_LIST(dns_sdlznode_t) nodelist;
    133 	dns_sdlznode_t *current;
    134 	dns_sdlznode_t *origin;
    135 };
    136 
    137 typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
    138 
    139 typedef struct sdlz_rdatasetiter {
    140 	dns_rdatasetiter_t common;
    141 	dns_rdatalist_t *current;
    142 } sdlz_rdatasetiter_t;
    143 
    144 #define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S')
    145 
    146 /*
    147  * Note that "impmagic" is not the first four bytes of the struct, so
    148  * ISC_MAGIC_VALID cannot be used.
    149  */
    150 
    151 #define VALID_SDLZDB(sdlzdb) \
    152 	((sdlzdb) != NULL && (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
    153 
    154 #define SDLZLOOKUP_MAGIC	ISC_MAGIC('D', 'L', 'Z', 'L')
    155 #define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
    156 #define VALID_SDLZNODE(sdlzn)	VALID_SDLZLOOKUP(sdlzn)
    157 
    158 /* These values are taken from RFC 1537 */
    159 #define SDLZ_DEFAULT_REFRESH 28800U  /* 8 hours */
    160 #define SDLZ_DEFAULT_RETRY   7200U   /* 2 hours */
    161 #define SDLZ_DEFAULT_EXPIRE  604800U /* 7 days */
    162 #define SDLZ_DEFAULT_MINIMUM 86400U  /* 1 day */
    163 
    164 /* This is a reasonable value */
    165 #define SDLZ_DEFAULT_TTL (60 * 60 * 24)
    166 
    167 #ifdef __COVERITY__
    168 #define MAYBE_LOCK(imp)	  LOCK(&imp->driverlock)
    169 #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
    170 #else /* ifdef __COVERITY__ */
    171 #define MAYBE_LOCK(imp)                                     \
    172 	do {                                                \
    173 		unsigned int flags = imp->flags;            \
    174 		if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
    175 			LOCK(&imp->driverlock);             \
    176 	} while (0)
    177 
    178 #define MAYBE_UNLOCK(imp)                                   \
    179 	do {                                                \
    180 		unsigned int flags = imp->flags;            \
    181 		if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
    182 			UNLOCK(&imp->driverlock);           \
    183 	} while (0)
    184 #endif /* ifdef __COVERITY__ */
    185 
    186 /*
    187  * Forward references.
    188  */
    189 static isc_result_t
    190 getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
    191 	    unsigned int options, dns_clientinfomethods_t *methods,
    192 	    dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep);
    193 
    194 static void
    195 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
    196 		dns_rdataset_t *rdataset);
    197 
    198 static void
    199 detachnode(dns_db_t *db, dns_dbnode_t **targetp);
    200 
    201 static void
    202 dbiterator_destroy(dns_dbiterator_t **iteratorp);
    203 static isc_result_t
    204 dbiterator_first(dns_dbiterator_t *iterator);
    205 static isc_result_t
    206 dbiterator_last(dns_dbiterator_t *iterator);
    207 static isc_result_t
    208 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name);
    209 static isc_result_t
    210 dbiterator_prev(dns_dbiterator_t *iterator);
    211 static isc_result_t
    212 dbiterator_next(dns_dbiterator_t *iterator);
    213 static isc_result_t
    214 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
    215 		   dns_name_t *name);
    216 static isc_result_t
    217 dbiterator_pause(dns_dbiterator_t *iterator);
    218 static isc_result_t
    219 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
    220 
    221 static dns_dbiteratormethods_t dbiterator_methods = {
    222 	dbiterator_destroy, dbiterator_first, dbiterator_last,
    223 	dbiterator_seek,    dbiterator_prev,  dbiterator_next,
    224 	dbiterator_current, dbiterator_pause, dbiterator_origin
    225 };
    226 
    227 /*
    228  * Utility functions
    229  */
    230 
    231 /*
    232  * Log a message at the given level
    233  */
    234 static void
    235 sdlz_log(int level, const char *fmt, ...) {
    236 	va_list ap;
    237 	va_start(ap, fmt);
    238 	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ,
    239 		       ISC_LOG_DEBUG(level), 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 
    256 static unsigned int
    257 initial_size(const char *data) {
    258 	unsigned int len = (strlen(data) / 64) + 1;
    259 	return (len * 64 + 64);
    260 }
    261 
    262 /*
    263  * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
    264  * driver interface.  See the SDB driver interface documentation for more info.
    265  */
    266 
    267 static void
    268 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
    269 	sdlz_rdatasetiter_t *sdlziterator = (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 	}
    285 	sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
    286 	return (ISC_R_SUCCESS);
    287 }
    288 
    289 static isc_result_t
    290 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
    291 	sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
    292 
    293 	sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
    294 	if (sdlziterator->current == NULL) {
    295 		return (ISC_R_NOMORE);
    296 	} else {
    297 		return (ISC_R_SUCCESS);
    298 	}
    299 }
    300 
    301 static void
    302 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
    303 	sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
    304 
    305 	list_tordataset(sdlziterator->current, iterator->db, iterator->node,
    306 			rdataset);
    307 }
    308 
    309 static dns_rdatasetitermethods_t rdatasetiter_methods = {
    310 	rdatasetiter_destroy, rdatasetiter_first, 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 	isc_refcount_increment(&sdlz->references);
    326 
    327 	*targetp = source;
    328 }
    329 
    330 static void
    331 destroy(dns_sdlz_db_t *sdlz) {
    332 	sdlz->common.magic = 0;
    333 	sdlz->common.impmagic = 0;
    334 
    335 	dns_name_free(&sdlz->common.origin, sdlz->common.mctx);
    336 
    337 	isc_refcount_destroy(&sdlz->references);
    338 	isc_mem_putanddetach(&sdlz->common.mctx, sdlz, sizeof(dns_sdlz_db_t));
    339 }
    340 
    341 static void
    342 detach(dns_db_t **dbp) {
    343 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
    344 
    345 	REQUIRE(VALID_SDLZDB(sdlz));
    346 
    347 	*dbp = NULL;
    348 
    349 	if (isc_refcount_decrement(&sdlz->references) == 1) {
    350 		destroy(sdlz);
    351 	}
    352 }
    353 
    354 static isc_result_t
    355 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
    356 	UNUSED(db);
    357 	UNUSED(callbacks);
    358 	return (ISC_R_NOTIMPLEMENTED);
    359 }
    360 
    361 static isc_result_t
    362 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
    363 	UNUSED(db);
    364 	UNUSED(callbacks);
    365 	return (ISC_R_NOTIMPLEMENTED);
    366 }
    367 
    368 static isc_result_t
    369 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
    370      dns_masterformat_t masterformat) {
    371 	UNUSED(db);
    372 	UNUSED(version);
    373 	UNUSED(filename);
    374 	UNUSED(masterformat);
    375 	return (ISC_R_NOTIMPLEMENTED);
    376 }
    377 
    378 static void
    379 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
    380 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    381 	REQUIRE(VALID_SDLZDB(sdlz));
    382 	REQUIRE(versionp != NULL && *versionp == NULL);
    383 
    384 	*versionp = (void *)&sdlz->dummy_version;
    385 	return;
    386 }
    387 
    388 static isc_result_t
    389 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
    390 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    391 	char origin[DNS_NAME_MAXTEXT + 1];
    392 	isc_result_t result;
    393 
    394 	REQUIRE(VALID_SDLZDB(sdlz));
    395 
    396 	if (sdlz->dlzimp->methods->newversion == NULL) {
    397 		return (ISC_R_NOTIMPLEMENTED);
    398 	}
    399 
    400 	dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
    401 
    402 	result = sdlz->dlzimp->methods->newversion(
    403 		origin, sdlz->dlzimp->driverarg, sdlz->dbdata, versionp);
    404 	if (result != ISC_R_SUCCESS) {
    405 		sdlz_log(ISC_LOG_ERROR,
    406 			 "sdlz newversion on origin %s failed : %s", origin,
    407 			 isc_result_totext(result));
    408 		return (result);
    409 	}
    410 
    411 	sdlz->future_version = *versionp;
    412 	return (ISC_R_SUCCESS);
    413 }
    414 
    415 static void
    416 attachversion(dns_db_t *db, dns_dbversion_t *source,
    417 	      dns_dbversion_t **targetp) {
    418 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    419 
    420 	REQUIRE(VALID_SDLZDB(sdlz));
    421 	REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version);
    422 
    423 	*targetp = source;
    424 }
    425 
    426 static void
    427 closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
    428 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    429 	char origin[DNS_NAME_MAXTEXT + 1];
    430 
    431 	REQUIRE(VALID_SDLZDB(sdlz));
    432 	REQUIRE(versionp != NULL);
    433 
    434 	if (*versionp == (void *)&sdlz->dummy_version) {
    435 		*versionp = NULL;
    436 		return;
    437 	}
    438 
    439 	REQUIRE(*versionp == sdlz->future_version);
    440 	REQUIRE(sdlz->dlzimp->methods->closeversion != NULL);
    441 
    442 	dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
    443 
    444 	sdlz->dlzimp->methods->closeversion(origin, commit,
    445 					    sdlz->dlzimp->driverarg,
    446 					    sdlz->dbdata, versionp);
    447 	if (*versionp != NULL) {
    448 		sdlz_log(ISC_LOG_ERROR, "sdlz closeversion on origin %s failed",
    449 			 origin);
    450 	}
    451 
    452 	sdlz->future_version = NULL;
    453 }
    454 
    455 static isc_result_t
    456 createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
    457 	dns_sdlznode_t *node;
    458 	void *sdlzv, *tdlzv;
    459 
    460 	node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
    461 
    462 	node->sdlz = NULL;
    463 	sdlzv = sdlz;
    464 	tdlzv = &node->sdlz;
    465 	attach(sdlzv, tdlzv);
    466 	ISC_LIST_INIT(node->lists);
    467 	ISC_LIST_INIT(node->buffers);
    468 	ISC_LINK_INIT(node, link);
    469 	node->name = NULL;
    470 	dns_rdatacallbacks_init(&node->callbacks);
    471 
    472 	isc_refcount_init(&node->references, 1);
    473 	node->magic = SDLZLOOKUP_MAGIC;
    474 
    475 	*nodep = node;
    476 	return (ISC_R_SUCCESS);
    477 }
    478 
    479 static void
    480 destroynode(dns_sdlznode_t *node) {
    481 	dns_rdatalist_t *list;
    482 	dns_rdata_t *rdata;
    483 	isc_buffer_t *b;
    484 	dns_sdlz_db_t *sdlz;
    485 	dns_db_t *db;
    486 	isc_mem_t *mctx;
    487 
    488 	isc_refcount_destroy(&node->references);
    489 
    490 	sdlz = node->sdlz;
    491 	mctx = sdlz->common.mctx;
    492 
    493 	while (!ISC_LIST_EMPTY(node->lists)) {
    494 		list = ISC_LIST_HEAD(node->lists);
    495 		while (!ISC_LIST_EMPTY(list->rdata)) {
    496 			rdata = ISC_LIST_HEAD(list->rdata);
    497 			ISC_LIST_UNLINK(list->rdata, rdata, link);
    498 			isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
    499 		}
    500 		ISC_LIST_UNLINK(node->lists, list, link);
    501 		isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
    502 	}
    503 
    504 	while (!ISC_LIST_EMPTY(node->buffers)) {
    505 		b = ISC_LIST_HEAD(node->buffers);
    506 		ISC_LIST_UNLINK(node->buffers, b, link);
    507 		isc_buffer_free(&b);
    508 	}
    509 
    510 	if (node->name != NULL) {
    511 		dns_name_free(node->name, mctx);
    512 		isc_mem_put(mctx, node->name, sizeof(dns_name_t));
    513 	}
    514 
    515 	node->magic = 0;
    516 	isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
    517 	db = &sdlz->common;
    518 	detach(&db);
    519 }
    520 
    521 static isc_result_t
    522 getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
    523 	    unsigned int options, dns_clientinfomethods_t *methods,
    524 	    dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) {
    525 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    526 	dns_sdlznode_t *node = NULL;
    527 	isc_result_t result;
    528 	isc_buffer_t b;
    529 	char namestr[DNS_NAME_MAXTEXT + 1];
    530 	isc_buffer_t b2;
    531 	char zonestr[DNS_NAME_MAXTEXT + 1];
    532 	bool isorigin;
    533 	dns_sdlzauthorityfunc_t authority;
    534 
    535 	REQUIRE(VALID_SDLZDB(sdlz));
    536 	REQUIRE(nodep != NULL && *nodep == NULL);
    537 
    538 	if (sdlz->dlzimp->methods->newversion == NULL) {
    539 		REQUIRE(!create);
    540 	}
    541 
    542 	isc_buffer_init(&b, namestr, sizeof(namestr));
    543 	if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
    544 		dns_name_t relname;
    545 		unsigned int labels;
    546 
    547 		labels = dns_name_countlabels(name) -
    548 			 dns_name_countlabels(&sdlz->common.origin);
    549 		dns_name_init(&relname, NULL);
    550 		dns_name_getlabelsequence(name, 0, labels, &relname);
    551 		result = dns_name_totext(&relname, true, &b);
    552 		if (result != ISC_R_SUCCESS) {
    553 			return (result);
    554 		}
    555 	} else {
    556 		result = dns_name_totext(name, true, &b);
    557 		if (result != ISC_R_SUCCESS) {
    558 			return (result);
    559 		}
    560 	}
    561 	isc_buffer_putuint8(&b, 0);
    562 
    563 	isc_buffer_init(&b2, zonestr, sizeof(zonestr));
    564 	result = dns_name_totext(&sdlz->common.origin, true, &b2);
    565 	if (result != ISC_R_SUCCESS) {
    566 		return (result);
    567 	}
    568 	isc_buffer_putuint8(&b2, 0);
    569 
    570 	result = createnode(sdlz, &node);
    571 	if (result != ISC_R_SUCCESS) {
    572 		return (result);
    573 	}
    574 
    575 	isorigin = dns_name_equal(name, &sdlz->common.origin);
    576 
    577 	/* make sure strings are always lowercase */
    578 	dns_sdlz_tolower(zonestr);
    579 	dns_sdlz_tolower(namestr);
    580 
    581 	MAYBE_LOCK(sdlz->dlzimp);
    582 
    583 	/* try to lookup the host (namestr) */
    584 	result = sdlz->dlzimp->methods->lookup(
    585 		zonestr, namestr, sdlz->dlzimp->driverarg, sdlz->dbdata, node,
    586 		methods, clientinfo);
    587 
    588 	/*
    589 	 * If the name was not found and DNS_DBFIND_NOWILD is not
    590 	 * set, then we try to find a wildcard entry.
    591 	 *
    592 	 * If DNS_DBFIND_NOZONECUT is set and there are multiple
    593 	 * levels between the host and the zone origin, we also look
    594 	 * for wildcards at each level.
    595 	 */
    596 	if (result == ISC_R_NOTFOUND && !create &&
    597 	    (options & DNS_DBFIND_NOWILD) == 0)
    598 	{
    599 		unsigned int i, dlabels, nlabels;
    600 
    601 		nlabels = dns_name_countlabels(name);
    602 		dlabels = nlabels - dns_name_countlabels(&sdlz->common.origin);
    603 		for (i = 0; i < dlabels; i++) {
    604 			char wildstr[DNS_NAME_MAXTEXT + 1];
    605 			dns_fixedname_t fixed;
    606 			const dns_name_t *wild;
    607 
    608 			dns_fixedname_init(&fixed);
    609 			if (i == dlabels - 1) {
    610 				wild = dns_wildcardname;
    611 			} else {
    612 				dns_name_t *fname;
    613 				fname = dns_fixedname_name(&fixed);
    614 				dns_name_getlabelsequence(
    615 					name, i + 1, dlabels - i - 1, fname);
    616 				result = dns_name_concatenate(
    617 					dns_wildcardname, fname, fname, NULL);
    618 				if (result != ISC_R_SUCCESS) {
    619 					MAYBE_UNLOCK(sdlz->dlzimp);
    620 					return (result);
    621 				}
    622 				wild = fname;
    623 			}
    624 
    625 			isc_buffer_init(&b, wildstr, sizeof(wildstr));
    626 			result = dns_name_totext(wild, true, &b);
    627 			if (result != ISC_R_SUCCESS) {
    628 				MAYBE_UNLOCK(sdlz->dlzimp);
    629 				return (result);
    630 			}
    631 			isc_buffer_putuint8(&b, 0);
    632 
    633 			result = sdlz->dlzimp->methods->lookup(
    634 				zonestr, wildstr, sdlz->dlzimp->driverarg,
    635 				sdlz->dbdata, node, methods, clientinfo);
    636 			if (result == ISC_R_SUCCESS) {
    637 				break;
    638 			}
    639 		}
    640 	}
    641 
    642 	MAYBE_UNLOCK(sdlz->dlzimp);
    643 
    644 	if (result == ISC_R_NOTFOUND && (isorigin || create)) {
    645 		result = ISC_R_SUCCESS;
    646 	}
    647 
    648 	if (result != ISC_R_SUCCESS) {
    649 		isc_refcount_decrementz(&node->references);
    650 		destroynode(node);
    651 		return (result);
    652 	}
    653 
    654 	if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
    655 		MAYBE_LOCK(sdlz->dlzimp);
    656 		authority = sdlz->dlzimp->methods->authority;
    657 		result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
    658 				      sdlz->dbdata, node);
    659 		MAYBE_UNLOCK(sdlz->dlzimp);
    660 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
    661 			isc_refcount_decrementz(&node->references);
    662 			destroynode(node);
    663 			return (result);
    664 		}
    665 	}
    666 
    667 	if (node->name == NULL) {
    668 		node->name = isc_mem_get(sdlz->common.mctx, sizeof(dns_name_t));
    669 		dns_name_init(node->name, NULL);
    670 		dns_name_dup(name, sdlz->common.mctx, node->name);
    671 	}
    672 
    673 	*nodep = node;
    674 	return (ISC_R_SUCCESS);
    675 }
    676 
    677 static isc_result_t
    678 findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
    679 	    dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
    680 	    dns_dbnode_t **nodep) {
    681 	return (getnodedata(db, name, create, 0, methods, clientinfo, nodep));
    682 }
    683 
    684 static isc_result_t
    685 findnode(dns_db_t *db, const dns_name_t *name, bool create,
    686 	 dns_dbnode_t **nodep) {
    687 	return (getnodedata(db, name, create, 0, NULL, NULL, nodep));
    688 }
    689 
    690 static isc_result_t
    691 findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
    692 	    isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
    693 	    dns_name_t *dcname, dns_rdataset_t *rdataset,
    694 	    dns_rdataset_t *sigrdataset) {
    695 	UNUSED(db);
    696 	UNUSED(name);
    697 	UNUSED(options);
    698 	UNUSED(now);
    699 	UNUSED(nodep);
    700 	UNUSED(foundname);
    701 	UNUSED(dcname);
    702 	UNUSED(rdataset);
    703 	UNUSED(sigrdataset);
    704 
    705 	return (ISC_R_NOTIMPLEMENTED);
    706 }
    707 
    708 static void
    709 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
    710 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    711 	dns_sdlznode_t *node = (dns_sdlznode_t *)source;
    712 
    713 	REQUIRE(VALID_SDLZDB(sdlz));
    714 
    715 	UNUSED(sdlz);
    716 
    717 	isc_refcount_increment(&node->references);
    718 
    719 	*targetp = source;
    720 }
    721 
    722 static void
    723 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
    724 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    725 	dns_sdlznode_t *node;
    726 
    727 	REQUIRE(VALID_SDLZDB(sdlz));
    728 	REQUIRE(targetp != NULL && *targetp != NULL);
    729 
    730 	UNUSED(sdlz);
    731 
    732 	node = (dns_sdlznode_t *)(*targetp);
    733 	*targetp = NULL;
    734 
    735 	if (isc_refcount_decrement(&node->references) == 1) {
    736 		destroynode(node);
    737 	}
    738 }
    739 
    740 static isc_result_t
    741 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
    742 	UNUSED(db);
    743 	UNUSED(node);
    744 	UNUSED(now);
    745 	UNREACHABLE();
    746 }
    747 
    748 static void
    749 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
    750 	UNUSED(db);
    751 	UNUSED(node);
    752 	UNUSED(out);
    753 	return;
    754 }
    755 
    756 static isc_result_t
    757 createiterator(dns_db_t *db, unsigned int options,
    758 	       dns_dbiterator_t **iteratorp) {
    759 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    760 	sdlz_dbiterator_t *sdlziter;
    761 	isc_result_t result;
    762 	isc_buffer_t b;
    763 	char zonestr[DNS_NAME_MAXTEXT + 1];
    764 
    765 	REQUIRE(VALID_SDLZDB(sdlz));
    766 
    767 	if (sdlz->dlzimp->methods->allnodes == NULL) {
    768 		return (ISC_R_NOTIMPLEMENTED);
    769 	}
    770 
    771 	if ((options & DNS_DB_NSEC3ONLY) != 0 ||
    772 	    (options & DNS_DB_NONSEC3) != 0)
    773 	{
    774 		return (ISC_R_NOTIMPLEMENTED);
    775 	}
    776 
    777 	isc_buffer_init(&b, zonestr, sizeof(zonestr));
    778 	result = dns_name_totext(&sdlz->common.origin, true, &b);
    779 	if (result != ISC_R_SUCCESS) {
    780 		return (result);
    781 	}
    782 	isc_buffer_putuint8(&b, 0);
    783 
    784 	sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
    785 
    786 	sdlziter->common.methods = &dbiterator_methods;
    787 	sdlziter->common.db = NULL;
    788 	dns_db_attach(db, &sdlziter->common.db);
    789 	sdlziter->common.relative_names = ((options & DNS_DB_RELATIVENAMES) !=
    790 					   0);
    791 	sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
    792 	ISC_LIST_INIT(sdlziter->nodelist);
    793 	sdlziter->current = NULL;
    794 	sdlziter->origin = NULL;
    795 
    796 	/* make sure strings are always lowercase */
    797 	dns_sdlz_tolower(zonestr);
    798 
    799 	MAYBE_LOCK(sdlz->dlzimp);
    800 	result = sdlz->dlzimp->methods->allnodes(
    801 		zonestr, sdlz->dlzimp->driverarg, sdlz->dbdata, sdlziter);
    802 	MAYBE_UNLOCK(sdlz->dlzimp);
    803 	if (result != ISC_R_SUCCESS) {
    804 		dns_dbiterator_t *iter = &sdlziter->common;
    805 		dbiterator_destroy(&iter);
    806 		return (result);
    807 	}
    808 
    809 	if (sdlziter->origin != NULL) {
    810 		ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
    811 		ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
    812 	}
    813 
    814 	*iteratorp = (dns_dbiterator_t *)sdlziter;
    815 
    816 	return (ISC_R_SUCCESS);
    817 }
    818 
    819 static isc_result_t
    820 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
    821 	     dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
    822 	     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
    823 	REQUIRE(VALID_SDLZNODE(node));
    824 	dns_rdatalist_t *list;
    825 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
    826 
    827 	UNUSED(db);
    828 	UNUSED(version);
    829 	UNUSED(covers);
    830 	UNUSED(now);
    831 	UNUSED(sigrdataset);
    832 
    833 	if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig) {
    834 		return (ISC_R_NOTIMPLEMENTED);
    835 	}
    836 
    837 	list = ISC_LIST_HEAD(sdlznode->lists);
    838 	while (list != NULL) {
    839 		if (list->type == type) {
    840 			break;
    841 		}
    842 		list = ISC_LIST_NEXT(list, link);
    843 	}
    844 	if (list == NULL) {
    845 		return (ISC_R_NOTFOUND);
    846 	}
    847 
    848 	list_tordataset(list, db, node, rdataset);
    849 
    850 	return (ISC_R_SUCCESS);
    851 }
    852 
    853 static isc_result_t
    854 findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
    855 	dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
    856 	dns_dbnode_t **nodep, dns_name_t *foundname,
    857 	dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
    858 	dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
    859 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
    860 	dns_dbnode_t *node = NULL;
    861 	dns_fixedname_t fname;
    862 	dns_rdataset_t xrdataset;
    863 	dns_name_t *xname;
    864 	unsigned int nlabels, olabels;
    865 	isc_result_t result;
    866 	unsigned int i;
    867 
    868 	REQUIRE(VALID_SDLZDB(sdlz));
    869 	REQUIRE(nodep == NULL || *nodep == NULL);
    870 	REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version ||
    871 		version == sdlz->future_version);
    872 
    873 	UNUSED(sdlz);
    874 
    875 	if (!dns_name_issubdomain(name, &db->origin)) {
    876 		return (DNS_R_NXDOMAIN);
    877 	}
    878 
    879 	olabels = dns_name_countlabels(&db->origin);
    880 	nlabels = dns_name_countlabels(name);
    881 
    882 	xname = dns_fixedname_initname(&fname);
    883 
    884 	if (rdataset == NULL) {
    885 		dns_rdataset_init(&xrdataset);
    886 		rdataset = &xrdataset;
    887 	}
    888 
    889 	result = DNS_R_NXDOMAIN;
    890 
    891 	/*
    892 	 * If we're not walking down searching for zone
    893 	 * cuts, we can cut straight to the chase
    894 	 */
    895 	if ((options & DNS_DBFIND_NOZONECUT) != 0) {
    896 		i = nlabels;
    897 		goto search;
    898 	}
    899 
    900 	for (i = olabels; i <= nlabels; i++) {
    901 	search:
    902 		/*
    903 		 * Look up the next label.
    904 		 */
    905 		dns_name_getlabelsequence(name, nlabels - i, i, xname);
    906 		result = getnodedata(db, xname, false, options, methods,
    907 				     clientinfo, &node);
    908 		if (result == ISC_R_NOTFOUND) {
    909 			result = DNS_R_NXDOMAIN;
    910 			continue;
    911 		} else if (result != ISC_R_SUCCESS) {
    912 			break;
    913 		}
    914 
    915 		/*
    916 		 * Look for a DNAME at the current label, unless this is
    917 		 * the qname.
    918 		 */
    919 		if (i < nlabels) {
    920 			result = findrdataset(db, node, version,
    921 					      dns_rdatatype_dname, 0, now,
    922 					      rdataset, sigrdataset);
    923 			if (result == ISC_R_SUCCESS) {
    924 				result = DNS_R_DNAME;
    925 				break;
    926 			}
    927 		}
    928 
    929 		/*
    930 		 * Look for an NS at the current label, unless this is the
    931 		 * origin, glue is ok, or there are known to be no zone cuts.
    932 		 */
    933 		if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0 &&
    934 		    (options & DNS_DBFIND_NOZONECUT) == 0)
    935 		{
    936 			result = findrdataset(db, node, version,
    937 					      dns_rdatatype_ns, 0, now,
    938 					      rdataset, sigrdataset);
    939 
    940 			if (result == ISC_R_SUCCESS && i == nlabels &&
    941 			    type == dns_rdatatype_any)
    942 			{
    943 				result = DNS_R_ZONECUT;
    944 				dns_rdataset_disassociate(rdataset);
    945 				if (sigrdataset != NULL &&
    946 				    dns_rdataset_isassociated(sigrdataset))
    947 				{
    948 					dns_rdataset_disassociate(sigrdataset);
    949 				}
    950 				break;
    951 			} else if (result == ISC_R_SUCCESS) {
    952 				result = DNS_R_DELEGATION;
    953 				break;
    954 			}
    955 		}
    956 
    957 		/*
    958 		 * If the current name is not the qname, add another label
    959 		 * and try again.
    960 		 */
    961 		if (i < nlabels) {
    962 			detachnode(db, &node);
    963 			node = NULL;
    964 			continue;
    965 		}
    966 
    967 		/*
    968 		 * If we're looking for ANY, we're done.
    969 		 */
    970 		if (type == dns_rdatatype_any) {
    971 			result = ISC_R_SUCCESS;
    972 			break;
    973 		}
    974 
    975 		/*
    976 		 * Look for the qtype.
    977 		 */
    978 		result = findrdataset(db, node, version, type, 0, now, rdataset,
    979 				      sigrdataset);
    980 		if (result == ISC_R_SUCCESS) {
    981 			break;
    982 		}
    983 
    984 		/*
    985 		 * Look for a CNAME
    986 		 */
    987 		if (type != dns_rdatatype_cname) {
    988 			result = findrdataset(db, node, version,
    989 					      dns_rdatatype_cname, 0, now,
    990 					      rdataset, sigrdataset);
    991 			if (result == ISC_R_SUCCESS) {
    992 				result = DNS_R_CNAME;
    993 				break;
    994 			}
    995 		}
    996 
    997 		result = DNS_R_NXRRSET;
    998 		break;
    999 	}
   1000 
   1001 	if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) {
   1002 		dns_rdataset_disassociate(rdataset);
   1003 	}
   1004 
   1005 	if (foundname != NULL) {
   1006 		dns_name_copynf(xname, foundname);
   1007 	}
   1008 
   1009 	if (nodep != NULL) {
   1010 		*nodep = node;
   1011 	} else if (node != NULL) {
   1012 		detachnode(db, &node);
   1013 	}
   1014 
   1015 	return (result);
   1016 }
   1017 
   1018 static isc_result_t
   1019 find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
   1020      dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
   1021      dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset,
   1022      dns_rdataset_t *sigrdataset) {
   1023 	return (findext(db, name, version, type, options, now, nodep, foundname,
   1024 			NULL, NULL, rdataset, sigrdataset));
   1025 }
   1026 
   1027 static isc_result_t
   1028 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   1029 	     unsigned int options, isc_stdtime_t now,
   1030 	     dns_rdatasetiter_t **iteratorp) {
   1031 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1032 	sdlz_rdatasetiter_t *iterator;
   1033 
   1034 	REQUIRE(VALID_SDLZDB(sdlz));
   1035 
   1036 	REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version ||
   1037 		version == sdlz->future_version);
   1038 
   1039 	UNUSED(version);
   1040 	UNUSED(now);
   1041 
   1042 	iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
   1043 
   1044 	iterator->common.magic = DNS_RDATASETITER_MAGIC;
   1045 	iterator->common.methods = &rdatasetiter_methods;
   1046 	iterator->common.db = db;
   1047 	iterator->common.node = NULL;
   1048 	attachnode(db, node, &iterator->common.node);
   1049 	iterator->common.version = version;
   1050 	iterator->common.options = options;
   1051 	iterator->common.now = now;
   1052 
   1053 	*iteratorp = (dns_rdatasetiter_t *)iterator;
   1054 
   1055 	return (ISC_R_SUCCESS);
   1056 }
   1057 
   1058 static isc_result_t
   1059 modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   1060 	    dns_rdataset_t *rdataset, unsigned int options,
   1061 	    dns_sdlzmodrdataset_t mod_function) {
   1062 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1063 	dns_master_style_t *style = NULL;
   1064 	isc_result_t result;
   1065 	isc_buffer_t *buffer = NULL;
   1066 	isc_mem_t *mctx;
   1067 	dns_sdlznode_t *sdlznode;
   1068 	char *rdatastr = NULL;
   1069 	char name[DNS_NAME_MAXTEXT + 1];
   1070 
   1071 	REQUIRE(VALID_SDLZDB(sdlz));
   1072 
   1073 	if (mod_function == NULL) {
   1074 		return (ISC_R_NOTIMPLEMENTED);
   1075 	}
   1076 
   1077 	sdlznode = (dns_sdlznode_t *)node;
   1078 
   1079 	UNUSED(options);
   1080 
   1081 	dns_name_format(sdlznode->name, name, sizeof(name));
   1082 
   1083 	mctx = sdlz->common.mctx;
   1084 
   1085 	isc_buffer_allocate(mctx, &buffer, 1024);
   1086 
   1087 	result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, 0xffffffff,
   1088 					mctx);
   1089 	if (result != ISC_R_SUCCESS) {
   1090 		goto cleanup;
   1091 	}
   1092 
   1093 	result = dns_master_rdatasettotext(sdlznode->name, rdataset, style,
   1094 					   NULL, buffer);
   1095 	if (result != ISC_R_SUCCESS) {
   1096 		goto cleanup;
   1097 	}
   1098 
   1099 	if (isc_buffer_usedlength(buffer) < 1) {
   1100 		result = ISC_R_BADADDRESSFORM;
   1101 		goto cleanup;
   1102 	}
   1103 
   1104 	rdatastr = isc_buffer_base(buffer);
   1105 	if (rdatastr == NULL) {
   1106 		result = ISC_R_NOMEMORY;
   1107 		goto cleanup;
   1108 	}
   1109 	rdatastr[isc_buffer_usedlength(buffer) - 1] = 0;
   1110 
   1111 	MAYBE_LOCK(sdlz->dlzimp);
   1112 	result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg,
   1113 			      sdlz->dbdata, version);
   1114 	MAYBE_UNLOCK(sdlz->dlzimp);
   1115 
   1116 cleanup:
   1117 	isc_buffer_free(&buffer);
   1118 	if (style != NULL) {
   1119 		dns_master_styledestroy(&style, mctx);
   1120 	}
   1121 
   1122 	return (result);
   1123 }
   1124 
   1125 static isc_result_t
   1126 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   1127 	    isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
   1128 	    dns_rdataset_t *addedrdataset) {
   1129 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1130 	isc_result_t result;
   1131 
   1132 	UNUSED(now);
   1133 	UNUSED(addedrdataset);
   1134 	REQUIRE(VALID_SDLZDB(sdlz));
   1135 
   1136 	if (sdlz->dlzimp->methods->addrdataset == NULL) {
   1137 		return (ISC_R_NOTIMPLEMENTED);
   1138 	}
   1139 
   1140 	result = modrdataset(db, node, version, rdataset, options,
   1141 			     sdlz->dlzimp->methods->addrdataset);
   1142 	return (result);
   1143 }
   1144 
   1145 static isc_result_t
   1146 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   1147 		 dns_rdataset_t *rdataset, unsigned int options,
   1148 		 dns_rdataset_t *newrdataset) {
   1149 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1150 	isc_result_t result;
   1151 
   1152 	UNUSED(newrdataset);
   1153 	REQUIRE(VALID_SDLZDB(sdlz));
   1154 
   1155 	if (sdlz->dlzimp->methods->subtractrdataset == NULL) {
   1156 		return (ISC_R_NOTIMPLEMENTED);
   1157 	}
   1158 
   1159 	result = modrdataset(db, node, version, rdataset, options,
   1160 			     sdlz->dlzimp->methods->subtractrdataset);
   1161 	return (result);
   1162 }
   1163 
   1164 static isc_result_t
   1165 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   1166 	       dns_rdatatype_t type, dns_rdatatype_t covers) {
   1167 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1168 	char name[DNS_NAME_MAXTEXT + 1];
   1169 	char b_type[DNS_RDATATYPE_FORMATSIZE];
   1170 	dns_sdlznode_t *sdlznode;
   1171 	isc_result_t result;
   1172 
   1173 	UNUSED(covers);
   1174 
   1175 	REQUIRE(VALID_SDLZDB(sdlz));
   1176 
   1177 	if (sdlz->dlzimp->methods->delrdataset == NULL) {
   1178 		return (ISC_R_NOTIMPLEMENTED);
   1179 	}
   1180 
   1181 	sdlznode = (dns_sdlznode_t *)node;
   1182 	dns_name_format(sdlznode->name, name, sizeof(name));
   1183 	dns_rdatatype_format(type, b_type, sizeof(b_type));
   1184 
   1185 	MAYBE_LOCK(sdlz->dlzimp);
   1186 	result = sdlz->dlzimp->methods->delrdataset(
   1187 		name, b_type, sdlz->dlzimp->driverarg, sdlz->dbdata, version);
   1188 	MAYBE_UNLOCK(sdlz->dlzimp);
   1189 
   1190 	return (result);
   1191 }
   1192 
   1193 static bool
   1194 issecure(dns_db_t *db) {
   1195 	UNUSED(db);
   1196 
   1197 	return (false);
   1198 }
   1199 
   1200 static unsigned int
   1201 nodecount(dns_db_t *db) {
   1202 	UNUSED(db);
   1203 
   1204 	return (0);
   1205 }
   1206 
   1207 static bool
   1208 ispersistent(dns_db_t *db) {
   1209 	UNUSED(db);
   1210 	return (true);
   1211 }
   1212 
   1213 static void
   1214 overmem(dns_db_t *db, bool over) {
   1215 	UNUSED(db);
   1216 	UNUSED(over);
   1217 }
   1218 
   1219 static void
   1220 settask(dns_db_t *db, isc_task_t *task) {
   1221 	UNUSED(db);
   1222 	UNUSED(task);
   1223 }
   1224 
   1225 /*
   1226  * getoriginnode() is used by the update code to find the
   1227  * dns_rdatatype_dnskey record for a zone
   1228  */
   1229 static isc_result_t
   1230 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
   1231 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1232 	isc_result_t result;
   1233 
   1234 	REQUIRE(VALID_SDLZDB(sdlz));
   1235 	if (sdlz->dlzimp->methods->newversion == NULL) {
   1236 		return (ISC_R_NOTIMPLEMENTED);
   1237 	}
   1238 
   1239 	result = getnodedata(db, &sdlz->common.origin, false, 0, NULL, NULL,
   1240 			     nodep);
   1241 	if (result != ISC_R_SUCCESS) {
   1242 		sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s",
   1243 			 isc_result_totext(result));
   1244 	}
   1245 	return (result);
   1246 }
   1247 
   1248 static dns_dbmethods_t sdlzdb_methods = {
   1249 	attach,
   1250 	detach,
   1251 	beginload,
   1252 	endload,
   1253 	NULL, /* serialize */
   1254 	dump,
   1255 	currentversion,
   1256 	newversion,
   1257 	attachversion,
   1258 	closeversion,
   1259 	findnode,
   1260 	find,
   1261 	findzonecut,
   1262 	attachnode,
   1263 	detachnode,
   1264 	expirenode,
   1265 	printnode,
   1266 	createiterator,
   1267 	findrdataset,
   1268 	allrdatasets,
   1269 	addrdataset,
   1270 	subtractrdataset,
   1271 	deleterdataset,
   1272 	issecure,
   1273 	nodecount,
   1274 	ispersistent,
   1275 	overmem,
   1276 	settask,
   1277 	getoriginnode,
   1278 	NULL, /* transfernode */
   1279 	NULL, /* getnsec3parameters */
   1280 	NULL, /* findnsec3node */
   1281 	NULL, /* setsigningtime */
   1282 	NULL, /* getsigningtime */
   1283 	NULL, /* resigned */
   1284 	NULL, /* isdnssec */
   1285 	NULL, /* getrrsetstats */
   1286 	NULL, /* rpz_attach */
   1287 	NULL, /* rpz_ready */
   1288 	findnodeext,
   1289 	findext,
   1290 	NULL, /* setcachestats */
   1291 	NULL, /* hashsize */
   1292 	NULL, /* nodefullname */
   1293 	NULL, /* getsize */
   1294 	NULL, /* setservestalettl */
   1295 	NULL, /* getservestalettl */
   1296 	NULL, /* setservestalerefresh */
   1297 	NULL, /* getservestalerefresh */
   1298 	NULL, /* setgluecachestats */
   1299 	NULL  /* adjusthashsize */
   1300 };
   1301 
   1302 /*
   1303  * Database Iterator Methods.  These methods were "borrowed" from the SDB
   1304  * driver interface.  See the SDB driver interface documentation for more info.
   1305  */
   1306 
   1307 static void
   1308 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
   1309 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
   1310 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
   1311 
   1312 	while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
   1313 		dns_sdlznode_t *node;
   1314 		node = ISC_LIST_HEAD(sdlziter->nodelist);
   1315 		ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
   1316 		isc_refcount_decrementz(&node->references);
   1317 		destroynode(node);
   1318 	}
   1319 
   1320 	dns_db_detach(&sdlziter->common.db);
   1321 	isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
   1322 
   1323 	*iteratorp = NULL;
   1324 }
   1325 
   1326 static isc_result_t
   1327 dbiterator_first(dns_dbiterator_t *iterator) {
   1328 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1329 
   1330 	sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
   1331 	if (sdlziter->current == NULL) {
   1332 		return (ISC_R_NOMORE);
   1333 	} else {
   1334 		return (ISC_R_SUCCESS);
   1335 	}
   1336 }
   1337 
   1338 static isc_result_t
   1339 dbiterator_last(dns_dbiterator_t *iterator) {
   1340 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1341 
   1342 	sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
   1343 	if (sdlziter->current == NULL) {
   1344 		return (ISC_R_NOMORE);
   1345 	} else {
   1346 		return (ISC_R_SUCCESS);
   1347 	}
   1348 }
   1349 
   1350 static isc_result_t
   1351 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) {
   1352 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1353 
   1354 	sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
   1355 	while (sdlziter->current != NULL) {
   1356 		if (dns_name_equal(sdlziter->current->name, name)) {
   1357 			return (ISC_R_SUCCESS);
   1358 		}
   1359 		sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
   1360 	}
   1361 	return (ISC_R_NOTFOUND);
   1362 }
   1363 
   1364 static isc_result_t
   1365 dbiterator_prev(dns_dbiterator_t *iterator) {
   1366 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1367 
   1368 	sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
   1369 	if (sdlziter->current == NULL) {
   1370 		return (ISC_R_NOMORE);
   1371 	} else {
   1372 		return (ISC_R_SUCCESS);
   1373 	}
   1374 }
   1375 
   1376 static isc_result_t
   1377 dbiterator_next(dns_dbiterator_t *iterator) {
   1378 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1379 
   1380 	sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
   1381 	if (sdlziter->current == NULL) {
   1382 		return (ISC_R_NOMORE);
   1383 	} else {
   1384 		return (ISC_R_SUCCESS);
   1385 	}
   1386 }
   1387 
   1388 static isc_result_t
   1389 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
   1390 		   dns_name_t *name) {
   1391 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1392 
   1393 	attachnode(iterator->db, sdlziter->current, nodep);
   1394 	if (name != NULL) {
   1395 		dns_name_copynf(sdlziter->current->name, name);
   1396 		return (ISC_R_SUCCESS);
   1397 	}
   1398 	return (ISC_R_SUCCESS);
   1399 }
   1400 
   1401 static isc_result_t
   1402 dbiterator_pause(dns_dbiterator_t *iterator) {
   1403 	UNUSED(iterator);
   1404 	return (ISC_R_SUCCESS);
   1405 }
   1406 
   1407 static isc_result_t
   1408 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
   1409 	UNUSED(iterator);
   1410 	dns_name_copynf(dns_rootname, name);
   1411 	return (ISC_R_SUCCESS);
   1412 }
   1413 
   1414 /*
   1415  * Rdataset Methods. These methods were "borrowed" from the SDB driver
   1416  * interface.  See the SDB driver interface documentation for more info.
   1417  */
   1418 
   1419 static void
   1420 disassociate(dns_rdataset_t *rdataset) {
   1421 	dns_dbnode_t *node = rdataset->private5;
   1422 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
   1423 	dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
   1424 
   1425 	detachnode(db, &node);
   1426 	isc__rdatalist_disassociate(rdataset);
   1427 }
   1428 
   1429 static void
   1430 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
   1431 	dns_dbnode_t *node = source->private5;
   1432 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
   1433 	dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
   1434 	dns_dbnode_t *tempdb = NULL;
   1435 
   1436 	isc__rdatalist_clone(source, target);
   1437 	attachnode(db, node, &tempdb);
   1438 	source->private5 = tempdb;
   1439 }
   1440 
   1441 static dns_rdatasetmethods_t rdataset_methods = {
   1442 	disassociate,
   1443 	isc__rdatalist_first,
   1444 	isc__rdatalist_next,
   1445 	isc__rdatalist_current,
   1446 	rdataset_clone,
   1447 	isc__rdatalist_count,
   1448 	isc__rdatalist_addnoqname,
   1449 	isc__rdatalist_getnoqname,
   1450 	NULL, /* addclosest */
   1451 	NULL, /* getclosest */
   1452 	NULL, /* settrust */
   1453 	NULL, /* expire */
   1454 	NULL, /* clearprefetch */
   1455 	NULL, /* setownercase */
   1456 	NULL, /* getownercase */
   1457 	NULL  /* addglue */
   1458 };
   1459 
   1460 static void
   1461 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
   1462 		dns_rdataset_t *rdataset) {
   1463 	/*
   1464 	 * The sdlz rdataset is an rdatalist with some additions.
   1465 	 *	- private1 & private2 are used by the rdatalist.
   1466 	 *	- private3 & private 4 are unused.
   1467 	 *	- private5 is the node.
   1468 	 */
   1469 
   1470 	/* This should never fail. */
   1471 	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
   1472 		      ISC_R_SUCCESS);
   1473 
   1474 	rdataset->methods = &rdataset_methods;
   1475 	dns_db_attachnode(db, node, &rdataset->private5);
   1476 }
   1477 
   1478 /*
   1479  * SDLZ core methods. This is the core of the new DLZ functionality.
   1480  */
   1481 
   1482 /*%
   1483  * Build a 'bind' database driver structure to be returned by
   1484  * either the find zone or the allow zone transfer method.
   1485  * This method is only available in this source file, it is
   1486  * not made available anywhere else.
   1487  */
   1488 
   1489 static isc_result_t
   1490 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
   1491 		  const dns_name_t *name, dns_rdataclass_t rdclass,
   1492 		  dns_db_t **dbp) {
   1493 	isc_result_t result;
   1494 	dns_sdlz_db_t *sdlzdb;
   1495 	dns_sdlzimplementation_t *imp;
   1496 
   1497 	/* check that things are as we expect */
   1498 	REQUIRE(dbp != NULL && *dbp == NULL);
   1499 	REQUIRE(name != NULL);
   1500 
   1501 	imp = (dns_sdlzimplementation_t *)driverarg;
   1502 
   1503 	/* allocate and zero memory for driver structure */
   1504 	sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
   1505 	memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
   1506 
   1507 	/* initialize and set origin */
   1508 	dns_name_init(&sdlzdb->common.origin, NULL);
   1509 	result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
   1510 	if (result != ISC_R_SUCCESS) {
   1511 		goto mem_cleanup;
   1512 	}
   1513 
   1514 	/* set the rest of the database structure attributes */
   1515 	sdlzdb->dlzimp = imp;
   1516 	sdlzdb->common.methods = &sdlzdb_methods;
   1517 	sdlzdb->common.attributes = 0;
   1518 	sdlzdb->common.rdclass = rdclass;
   1519 	sdlzdb->common.mctx = NULL;
   1520 	sdlzdb->dbdata = dbdata;
   1521 	isc_refcount_init(&sdlzdb->references, 1);
   1522 
   1523 	/* attach to the memory context */
   1524 	isc_mem_attach(mctx, &sdlzdb->common.mctx);
   1525 
   1526 	/* mark structure as valid */
   1527 	sdlzdb->common.magic = DNS_DB_MAGIC;
   1528 	sdlzdb->common.impmagic = SDLZDB_MAGIC;
   1529 	*dbp = (dns_db_t *)sdlzdb;
   1530 
   1531 	return (result);
   1532 mem_cleanup:
   1533 	isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
   1534 	return (result);
   1535 }
   1536 
   1537 static isc_result_t
   1538 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
   1539 		     dns_rdataclass_t rdclass, const dns_name_t *name,
   1540 		     const isc_sockaddr_t *clientaddr, dns_db_t **dbp) {
   1541 	isc_buffer_t b;
   1542 	isc_buffer_t b2;
   1543 	char namestr[DNS_NAME_MAXTEXT + 1];
   1544 	char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255."
   1545 			       "255") +
   1546 		       1];
   1547 	isc_netaddr_t netaddr;
   1548 	isc_result_t result;
   1549 	dns_sdlzimplementation_t *imp;
   1550 
   1551 	/*
   1552 	 * Perform checks to make sure data is as we expect it to be.
   1553 	 */
   1554 	REQUIRE(driverarg != NULL);
   1555 	REQUIRE(name != NULL);
   1556 	REQUIRE(clientaddr != NULL);
   1557 	REQUIRE(dbp != NULL && *dbp == NULL);
   1558 
   1559 	imp = (dns_sdlzimplementation_t *)driverarg;
   1560 
   1561 	/* Convert DNS name to ascii text */
   1562 	isc_buffer_init(&b, namestr, sizeof(namestr));
   1563 	result = dns_name_totext(name, true, &b);
   1564 	if (result != ISC_R_SUCCESS) {
   1565 		return (result);
   1566 	}
   1567 	isc_buffer_putuint8(&b, 0);
   1568 
   1569 	/* convert client address to ascii text */
   1570 	isc_buffer_init(&b2, clientstr, sizeof(clientstr));
   1571 	isc_netaddr_fromsockaddr(&netaddr, clientaddr);
   1572 	result = isc_netaddr_totext(&netaddr, &b2);
   1573 	if (result != ISC_R_SUCCESS) {
   1574 		return (result);
   1575 	}
   1576 	isc_buffer_putuint8(&b2, 0);
   1577 
   1578 	/* make sure strings are always lowercase */
   1579 	dns_sdlz_tolower(namestr);
   1580 	dns_sdlz_tolower(clientstr);
   1581 
   1582 	/* Call SDLZ driver's find zone method */
   1583 	if (imp->methods->allowzonexfr != NULL) {
   1584 		isc_result_t rresult = ISC_R_SUCCESS;
   1585 
   1586 		MAYBE_LOCK(imp);
   1587 		result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
   1588 						    namestr, clientstr);
   1589 		MAYBE_UNLOCK(imp);
   1590 		/*
   1591 		 * if zone is supported and transfers are (or might be)
   1592 		 * allowed, build a 'bind' database driver
   1593 		 */
   1594 		if (result == ISC_R_SUCCESS || result == ISC_R_DEFAULT) {
   1595 			rresult = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
   1596 						    name, rdclass, dbp);
   1597 		}
   1598 		if (rresult != ISC_R_SUCCESS) {
   1599 			result = rresult;
   1600 		}
   1601 		return (result);
   1602 	}
   1603 
   1604 	return (ISC_R_NOTIMPLEMENTED);
   1605 }
   1606 
   1607 static isc_result_t
   1608 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
   1609 	       char *argv[], void *driverarg, void **dbdata) {
   1610 	dns_sdlzimplementation_t *imp;
   1611 	isc_result_t result = ISC_R_NOTFOUND;
   1612 
   1613 	/* Write debugging message to log */
   1614 	sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
   1615 
   1616 	/*
   1617 	 * Performs checks to make sure data is as we expect it to be.
   1618 	 */
   1619 	REQUIRE(driverarg != NULL);
   1620 	REQUIRE(dlzname != NULL);
   1621 	REQUIRE(dbdata != NULL);
   1622 	UNUSED(mctx);
   1623 
   1624 	imp = driverarg;
   1625 
   1626 	/* If the create method exists, call it. */
   1627 	if (imp->methods->create != NULL) {
   1628 		MAYBE_LOCK(imp);
   1629 		result = imp->methods->create(dlzname, argc, argv,
   1630 					      imp->driverarg, dbdata);
   1631 		MAYBE_UNLOCK(imp);
   1632 	}
   1633 
   1634 	/* Write debugging message to log */
   1635 	if (result == ISC_R_SUCCESS) {
   1636 		sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
   1637 	} else {
   1638 		sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
   1639 	}
   1640 
   1641 	return (result);
   1642 }
   1643 
   1644 static void
   1645 dns_sdlzdestroy(void *driverdata, void **dbdata) {
   1646 	dns_sdlzimplementation_t *imp;
   1647 
   1648 	/* Write debugging message to log */
   1649 	sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
   1650 
   1651 	imp = driverdata;
   1652 
   1653 	/* If the destroy method exists, call it. */
   1654 	if (imp->methods->destroy != NULL) {
   1655 		MAYBE_LOCK(imp);
   1656 		imp->methods->destroy(imp->driverarg, dbdata);
   1657 		MAYBE_UNLOCK(imp);
   1658 	}
   1659 }
   1660 
   1661 static isc_result_t
   1662 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
   1663 		 dns_rdataclass_t rdclass, const dns_name_t *name,
   1664 		 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
   1665 		 dns_db_t **dbp) {
   1666 	isc_buffer_t b;
   1667 	char namestr[DNS_NAME_MAXTEXT + 1];
   1668 	isc_result_t result;
   1669 	dns_sdlzimplementation_t *imp;
   1670 
   1671 	/*
   1672 	 * Perform checks to make sure data is as we expect it to be.
   1673 	 */
   1674 	REQUIRE(driverarg != NULL);
   1675 	REQUIRE(name != NULL);
   1676 	REQUIRE(dbp != NULL && *dbp == NULL);
   1677 
   1678 	imp = (dns_sdlzimplementation_t *)driverarg;
   1679 
   1680 	/* Convert DNS name to ascii text */
   1681 	isc_buffer_init(&b, namestr, sizeof(namestr));
   1682 	result = dns_name_totext(name, true, &b);
   1683 	if (result != ISC_R_SUCCESS) {
   1684 		return (result);
   1685 	}
   1686 	isc_buffer_putuint8(&b, 0);
   1687 
   1688 	/* make sure strings are always lowercase */
   1689 	dns_sdlz_tolower(namestr);
   1690 
   1691 	/* Call SDLZ driver's find zone method */
   1692 	MAYBE_LOCK(imp);
   1693 	result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
   1694 					methods, clientinfo);
   1695 	MAYBE_UNLOCK(imp);
   1696 
   1697 	/*
   1698 	 * if zone is supported build a 'bind' database driver
   1699 	 * structure to return
   1700 	 */
   1701 	if (result == ISC_R_SUCCESS) {
   1702 		result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
   1703 					   rdclass, dbp);
   1704 	}
   1705 
   1706 	return (result);
   1707 }
   1708 
   1709 static isc_result_t
   1710 dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view,
   1711 		  dns_dlzdb_t *dlzdb) {
   1712 	isc_result_t result;
   1713 	dns_sdlzimplementation_t *imp;
   1714 
   1715 	REQUIRE(driverarg != NULL);
   1716 
   1717 	imp = (dns_sdlzimplementation_t *)driverarg;
   1718 
   1719 	/* Call SDLZ driver's configure method */
   1720 	if (imp->methods->configure != NULL) {
   1721 		MAYBE_LOCK(imp);
   1722 		result = imp->methods->configure(view, dlzdb, imp->driverarg,
   1723 						 dbdata);
   1724 		MAYBE_UNLOCK(imp);
   1725 	} else {
   1726 		result = ISC_R_SUCCESS;
   1727 	}
   1728 
   1729 	return (result);
   1730 }
   1731 
   1732 static bool
   1733 dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name,
   1734 		 const isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
   1735 		 const dst_key_t *key, void *driverarg, void *dbdata) {
   1736 	dns_sdlzimplementation_t *imp;
   1737 	char b_signer[DNS_NAME_FORMATSIZE];
   1738 	char b_name[DNS_NAME_FORMATSIZE];
   1739 	char b_addr[ISC_NETADDR_FORMATSIZE];
   1740 	char b_type[DNS_RDATATYPE_FORMATSIZE];
   1741 	char b_key[DST_KEY_FORMATSIZE];
   1742 	isc_buffer_t *tkey_token = NULL;
   1743 	isc_region_t token_region = { NULL, 0 };
   1744 	uint32_t token_len = 0;
   1745 	bool ret;
   1746 
   1747 	REQUIRE(driverarg != NULL);
   1748 
   1749 	imp = (dns_sdlzimplementation_t *)driverarg;
   1750 	if (imp->methods->ssumatch == NULL) {
   1751 		return (false);
   1752 	}
   1753 
   1754 	/*
   1755 	 * Format the request elements. sdlz operates on strings, not
   1756 	 * structures
   1757 	 */
   1758 	if (signer != NULL) {
   1759 		dns_name_format(signer, b_signer, sizeof(b_signer));
   1760 	} else {
   1761 		b_signer[0] = 0;
   1762 	}
   1763 
   1764 	dns_name_format(name, b_name, sizeof(b_name));
   1765 
   1766 	if (tcpaddr != NULL) {
   1767 		isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
   1768 	} else {
   1769 		b_addr[0] = 0;
   1770 	}
   1771 
   1772 	dns_rdatatype_format(type, b_type, sizeof(b_type));
   1773 
   1774 	if (key != NULL) {
   1775 		dst_key_format(key, b_key, sizeof(b_key));
   1776 		tkey_token = dst_key_tkeytoken(key);
   1777 	} else {
   1778 		b_key[0] = 0;
   1779 	}
   1780 
   1781 	if (tkey_token != NULL) {
   1782 		isc_buffer_region(tkey_token, &token_region);
   1783 		token_len = token_region.length;
   1784 	}
   1785 
   1786 	MAYBE_LOCK(imp);
   1787 	ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
   1788 				     token_len,
   1789 				     token_len != 0 ? token_region.base : NULL,
   1790 				     imp->driverarg, dbdata);
   1791 	MAYBE_UNLOCK(imp);
   1792 	return (ret);
   1793 }
   1794 
   1795 static dns_dlzmethods_t sdlzmethods = { dns_sdlzcreate,	   dns_sdlzdestroy,
   1796 					dns_sdlzfindzone,  dns_sdlzallowzonexfr,
   1797 					dns_sdlzconfigure, dns_sdlzssumatch };
   1798 
   1799 /*
   1800  * Public functions.
   1801  */
   1802 
   1803 isc_result_t
   1804 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
   1805 	       const char *data) {
   1806 	dns_rdatalist_t *rdatalist;
   1807 	dns_rdata_t *rdata;
   1808 	dns_rdatatype_t typeval;
   1809 	isc_consttextregion_t r;
   1810 	isc_buffer_t b;
   1811 	isc_buffer_t *rdatabuf = NULL;
   1812 	isc_lex_t *lex;
   1813 	isc_result_t result;
   1814 	unsigned int size;
   1815 	isc_mem_t *mctx;
   1816 	const dns_name_t *origin;
   1817 
   1818 	REQUIRE(VALID_SDLZLOOKUP(lookup));
   1819 	REQUIRE(type != NULL);
   1820 	REQUIRE(data != NULL);
   1821 
   1822 	mctx = lookup->sdlz->common.mctx;
   1823 
   1824 	r.base = type;
   1825 	r.length = strlen(type);
   1826 	result = dns_rdatatype_fromtext(&typeval, (void *)&r);
   1827 	if (result != ISC_R_SUCCESS) {
   1828 		return (result);
   1829 	}
   1830 
   1831 	rdatalist = ISC_LIST_HEAD(lookup->lists);
   1832 	while (rdatalist != NULL) {
   1833 		if (rdatalist->type == typeval) {
   1834 			break;
   1835 		}
   1836 		rdatalist = ISC_LIST_NEXT(rdatalist, link);
   1837 	}
   1838 
   1839 	if (rdatalist == NULL) {
   1840 		rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
   1841 		dns_rdatalist_init(rdatalist);
   1842 		rdatalist->rdclass = lookup->sdlz->common.rdclass;
   1843 		rdatalist->type = typeval;
   1844 		rdatalist->ttl = ttl;
   1845 		ISC_LIST_APPEND(lookup->lists, rdatalist, link);
   1846 	} else if (rdatalist->ttl > ttl) {
   1847 		/*
   1848 		 * BIND9 doesn't enforce all RRs in an RRset
   1849 		 * having the same TTL, as per RFC 2136,
   1850 		 * section 7.12. If a DLZ backend has
   1851 		 * different TTLs, then the best
   1852 		 * we can do is return the lowest.
   1853 		 */
   1854 		rdatalist->ttl = ttl;
   1855 	}
   1856 
   1857 	rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
   1858 	dns_rdata_init(rdata);
   1859 
   1860 	if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
   1861 		origin = &lookup->sdlz->common.origin;
   1862 	} else {
   1863 		origin = dns_rootname;
   1864 	}
   1865 
   1866 	lex = NULL;
   1867 	result = isc_lex_create(mctx, 64, &lex);
   1868 	if (result != ISC_R_SUCCESS) {
   1869 		goto failure;
   1870 	}
   1871 
   1872 	size = initial_size(data);
   1873 	do {
   1874 		isc_buffer_constinit(&b, data, strlen(data));
   1875 		isc_buffer_add(&b, strlen(data));
   1876 
   1877 		result = isc_lex_openbuffer(lex, &b);
   1878 		if (result != ISC_R_SUCCESS) {
   1879 			goto failure;
   1880 		}
   1881 
   1882 		rdatabuf = NULL;
   1883 		isc_buffer_allocate(mctx, &rdatabuf, size);
   1884 
   1885 		result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
   1886 					    rdatalist->type, lex, origin, false,
   1887 					    mctx, rdatabuf, &lookup->callbacks);
   1888 		if (result != ISC_R_SUCCESS) {
   1889 			isc_buffer_free(&rdatabuf);
   1890 		}
   1891 		if (size >= 65535) {
   1892 			break;
   1893 		}
   1894 		size *= 2;
   1895 		if (size >= 65535) {
   1896 			size = 65535;
   1897 		}
   1898 	} while (result == ISC_R_NOSPACE);
   1899 
   1900 	if (result != ISC_R_SUCCESS) {
   1901 		result = DNS_R_SERVFAIL;
   1902 		goto failure;
   1903 	}
   1904 
   1905 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
   1906 	ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
   1907 
   1908 	if (lex != NULL) {
   1909 		isc_lex_destroy(&lex);
   1910 	}
   1911 
   1912 	return (ISC_R_SUCCESS);
   1913 
   1914 failure:
   1915 	if (rdatabuf != NULL) {
   1916 		isc_buffer_free(&rdatabuf);
   1917 	}
   1918 	if (lex != NULL) {
   1919 		isc_lex_destroy(&lex);
   1920 	}
   1921 	isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
   1922 
   1923 	return (result);
   1924 }
   1925 
   1926 isc_result_t
   1927 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
   1928 		    const char *type, dns_ttl_t ttl, const char *data) {
   1929 	dns_name_t *newname;
   1930 	const dns_name_t *origin;
   1931 	dns_fixedname_t fnewname;
   1932 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
   1933 	dns_sdlznode_t *sdlznode;
   1934 	isc_mem_t *mctx = sdlz->common.mctx;
   1935 	isc_buffer_t b;
   1936 	isc_result_t result;
   1937 
   1938 	newname = dns_fixedname_initname(&fnewname);
   1939 
   1940 	if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
   1941 		origin = &sdlz->common.origin;
   1942 	} else {
   1943 		origin = dns_rootname;
   1944 	}
   1945 	isc_buffer_constinit(&b, name, strlen(name));
   1946 	isc_buffer_add(&b, strlen(name));
   1947 
   1948 	result = dns_name_fromtext(newname, &b, origin, 0, NULL);
   1949 	if (result != ISC_R_SUCCESS) {
   1950 		return (result);
   1951 	}
   1952 
   1953 	if (allnodes->common.relative_names) {
   1954 		/* All names are relative to the root */
   1955 		unsigned int nlabels = dns_name_countlabels(newname);
   1956 		dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
   1957 	}
   1958 
   1959 	sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
   1960 	if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
   1961 		sdlznode = NULL;
   1962 		result = createnode(sdlz, &sdlznode);
   1963 		if (result != ISC_R_SUCCESS) {
   1964 			return (result);
   1965 		}
   1966 		sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
   1967 		dns_name_init(sdlznode->name, NULL);
   1968 		dns_name_dup(newname, mctx, sdlznode->name);
   1969 		ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
   1970 		if (allnodes->origin == NULL &&
   1971 		    dns_name_equal(newname, &sdlz->common.origin))
   1972 		{
   1973 			allnodes->origin = sdlznode;
   1974 		}
   1975 	}
   1976 	return (dns_sdlz_putrr(sdlznode, type, ttl, data));
   1977 }
   1978 
   1979 isc_result_t
   1980 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
   1981 		uint32_t serial) {
   1982 	char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
   1983 	int n;
   1984 
   1985 	REQUIRE(mname != NULL);
   1986 	REQUIRE(rname != NULL);
   1987 
   1988 	n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", mname, rname,
   1989 		     serial, SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
   1990 		     SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
   1991 	if (n >= (int)sizeof(str) || n < 0) {
   1992 		return (ISC_R_NOSPACE);
   1993 	}
   1994 	return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
   1995 }
   1996 
   1997 isc_result_t
   1998 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
   1999 		 void *driverarg, unsigned int flags, isc_mem_t *mctx,
   2000 		 dns_sdlzimplementation_t **sdlzimp) {
   2001 	dns_sdlzimplementation_t *imp;
   2002 	isc_result_t result;
   2003 
   2004 	/*
   2005 	 * Performs checks to make sure data is as we expect it to be.
   2006 	 */
   2007 	REQUIRE(drivername != NULL);
   2008 	REQUIRE(methods != NULL);
   2009 	REQUIRE(methods->findzone != NULL);
   2010 	REQUIRE(methods->lookup != NULL);
   2011 	REQUIRE(mctx != NULL);
   2012 	REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
   2013 	REQUIRE((flags &
   2014 		 ~(DNS_SDLZFLAG_RELATIVEOWNER | DNS_SDLZFLAG_RELATIVERDATA |
   2015 		   DNS_SDLZFLAG_THREADSAFE)) == 0);
   2016 
   2017 	/* Write debugging message to log */
   2018 	sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
   2019 
   2020 	/*
   2021 	 * Allocate memory for a sdlz_implementation object.  Error if
   2022 	 * we cannot.
   2023 	 */
   2024 	imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
   2025 
   2026 	/* Make sure memory region is set to all 0's */
   2027 	memset(imp, 0, sizeof(dns_sdlzimplementation_t));
   2028 
   2029 	/* Store the data passed into this method */
   2030 	imp->methods = methods;
   2031 	imp->driverarg = driverarg;
   2032 	imp->flags = flags;
   2033 	imp->mctx = NULL;
   2034 
   2035 	/* attach the new sdlz_implementation object to a memory context */
   2036 	isc_mem_attach(mctx, &imp->mctx);
   2037 
   2038 	/*
   2039 	 * initialize the driver lock, error if we cannot
   2040 	 * (used if a driver does not support multiple threads)
   2041 	 */
   2042 	isc_mutex_init(&imp->driverlock);
   2043 
   2044 	imp->dlz_imp = NULL;
   2045 
   2046 	/*
   2047 	 * register the DLZ driver.  Pass in our "extra" sdlz information as
   2048 	 * a driverarg.  (that's why we stored the passed in driver arg in our
   2049 	 * sdlz_implementation structure)  Also, store the dlz_implementation
   2050 	 * structure in our sdlz_implementation.
   2051 	 */
   2052 	result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
   2053 				 &imp->dlz_imp);
   2054 
   2055 	/* if registration fails, cleanup and get outta here. */
   2056 	if (result != ISC_R_SUCCESS) {
   2057 		goto cleanup_mutex;
   2058 	}
   2059 
   2060 	*sdlzimp = imp;
   2061 
   2062 	return (ISC_R_SUCCESS);
   2063 
   2064 cleanup_mutex:
   2065 	/* destroy the driver lock, we don't need it anymore */
   2066 	isc_mutex_destroy(&imp->driverlock);
   2067 
   2068 	/*
   2069 	 * return the memory back to the available memory pool and
   2070 	 * remove it from the memory context.
   2071 	 */
   2072 	isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
   2073 	return (result);
   2074 }
   2075 
   2076 void
   2077 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
   2078 	dns_sdlzimplementation_t *imp;
   2079 
   2080 	/* Write debugging message to log */
   2081 	sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
   2082 
   2083 	/*
   2084 	 * Performs checks to make sure data is as we expect it to be.
   2085 	 */
   2086 	REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
   2087 
   2088 	imp = *sdlzimp;
   2089 	*sdlzimp = NULL;
   2090 
   2091 	/* Unregister the DLZ driver implementation */
   2092 	dns_dlzunregister(&imp->dlz_imp);
   2093 
   2094 	/* destroy the driver lock, we don't need it anymore */
   2095 	isc_mutex_destroy(&imp->driverlock);
   2096 
   2097 	/*
   2098 	 * return the memory back to the available memory pool and
   2099 	 * remove it from the memory context.
   2100 	 */
   2101 	isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
   2102 }
   2103 
   2104 isc_result_t
   2105 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
   2106 	       const dns_name_t *name, dns_db_t **dbp) {
   2107 	isc_result_t result;
   2108 
   2109 	result = dns_sdlzcreateDBP(dlzdatabase->mctx,
   2110 				   dlzdatabase->implementation->driverarg,
   2111 				   dlzdatabase->dbdata, name, rdclass, dbp);
   2112 	return (result);
   2113 }
   2114