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