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