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