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