Home | History | Annotate | Line # | Download | only in dns
sdlz.c revision 1.12
      1 /*	$NetBSD: sdlz.c,v 1.12 2024/02/21 22:52:08 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/result.h>
     66 #include <isc/rwlock.h>
     67 #include <isc/string.h>
     68 #include <isc/util.h>
     69 
     70 #include <dns/callbacks.h>
     71 #include <dns/db.h>
     72 #include <dns/dbiterator.h>
     73 #include <dns/dlz.h>
     74 #include <dns/fixedname.h>
     75 #include <dns/log.h>
     76 #include <dns/master.h>
     77 #include <dns/rdata.h>
     78 #include <dns/rdatalist.h>
     79 #include <dns/rdataset.h>
     80 #include <dns/rdatasetiter.h>
     81 #include <dns/rdatatype.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_copy(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, dns_dbtree_t tree) {
   1199 	UNUSED(db);
   1200 	UNUSED(tree);
   1201 
   1202 	return (0);
   1203 }
   1204 
   1205 static bool
   1206 ispersistent(dns_db_t *db) {
   1207 	UNUSED(db);
   1208 	return (true);
   1209 }
   1210 
   1211 static void
   1212 overmem(dns_db_t *db, bool over) {
   1213 	UNUSED(db);
   1214 	UNUSED(over);
   1215 }
   1216 
   1217 static void
   1218 settask(dns_db_t *db, isc_task_t *task) {
   1219 	UNUSED(db);
   1220 	UNUSED(task);
   1221 }
   1222 
   1223 /*
   1224  * getoriginnode() is used by the update code to find the
   1225  * dns_rdatatype_dnskey record for a zone
   1226  */
   1227 static isc_result_t
   1228 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
   1229 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
   1230 	isc_result_t result;
   1231 
   1232 	REQUIRE(VALID_SDLZDB(sdlz));
   1233 	if (sdlz->dlzimp->methods->newversion == NULL) {
   1234 		return (ISC_R_NOTIMPLEMENTED);
   1235 	}
   1236 
   1237 	result = getnodedata(db, &sdlz->common.origin, false, 0, NULL, NULL,
   1238 			     nodep);
   1239 	if (result != ISC_R_SUCCESS) {
   1240 		sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s",
   1241 			 isc_result_totext(result));
   1242 	}
   1243 	return (result);
   1244 }
   1245 
   1246 static dns_dbmethods_t sdlzdb_methods = {
   1247 	attach,		detach,		beginload,
   1248 	endload,	dump,		currentversion,
   1249 	newversion,	attachversion,	closeversion,
   1250 	findnode,	find,		findzonecut,
   1251 	attachnode,	detachnode,	expirenode,
   1252 	printnode,	createiterator, findrdataset,
   1253 	allrdatasets,	addrdataset,	subtractrdataset,
   1254 	deleterdataset, issecure,	nodecount,
   1255 	ispersistent,	overmem,	settask,
   1256 	getoriginnode,	NULL,		      /* transfernode */
   1257 	NULL,				      /* getnsec3parameters */
   1258 	NULL,				      /* findnsec3node */
   1259 	NULL,				      /* setsigningtime */
   1260 	NULL,				      /* getsigningtime */
   1261 	NULL,				      /* resigned */
   1262 	NULL,				      /* isdnssec */
   1263 	NULL,				      /* getrrsetstats */
   1264 	NULL,				      /* rpz_attach */
   1265 	NULL,				      /* rpz_ready */
   1266 	findnodeext,	findext,	NULL, /* setcachestats */
   1267 	NULL,				      /* hashsize */
   1268 	NULL,				      /* nodefullname */
   1269 	NULL,				      /* getsize */
   1270 	NULL,				      /* setservestalettl */
   1271 	NULL,				      /* getservestalettl */
   1272 	NULL,				      /* setservestalerefresh */
   1273 	NULL,				      /* getservestalerefresh */
   1274 	NULL,				      /* setgluecachestats */
   1275 };
   1276 
   1277 /*
   1278  * Database Iterator Methods.  These methods were "borrowed" from the SDB
   1279  * driver interface.  See the SDB driver interface documentation for more info.
   1280  */
   1281 
   1282 static void
   1283 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
   1284 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
   1285 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
   1286 
   1287 	while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
   1288 		dns_sdlznode_t *node;
   1289 		node = ISC_LIST_HEAD(sdlziter->nodelist);
   1290 		ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
   1291 		isc_refcount_decrementz(&node->references);
   1292 		destroynode(node);
   1293 	}
   1294 
   1295 	dns_db_detach(&sdlziter->common.db);
   1296 	isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
   1297 
   1298 	*iteratorp = NULL;
   1299 }
   1300 
   1301 static isc_result_t
   1302 dbiterator_first(dns_dbiterator_t *iterator) {
   1303 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1304 
   1305 	sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
   1306 	if (sdlziter->current == NULL) {
   1307 		return (ISC_R_NOMORE);
   1308 	} else {
   1309 		return (ISC_R_SUCCESS);
   1310 	}
   1311 }
   1312 
   1313 static isc_result_t
   1314 dbiterator_last(dns_dbiterator_t *iterator) {
   1315 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1316 
   1317 	sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
   1318 	if (sdlziter->current == NULL) {
   1319 		return (ISC_R_NOMORE);
   1320 	} else {
   1321 		return (ISC_R_SUCCESS);
   1322 	}
   1323 }
   1324 
   1325 static isc_result_t
   1326 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) {
   1327 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1328 
   1329 	sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
   1330 	while (sdlziter->current != NULL) {
   1331 		if (dns_name_equal(sdlziter->current->name, name)) {
   1332 			return (ISC_R_SUCCESS);
   1333 		}
   1334 		sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
   1335 	}
   1336 	return (ISC_R_NOTFOUND);
   1337 }
   1338 
   1339 static isc_result_t
   1340 dbiterator_prev(dns_dbiterator_t *iterator) {
   1341 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1342 
   1343 	sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
   1344 	if (sdlziter->current == NULL) {
   1345 		return (ISC_R_NOMORE);
   1346 	} else {
   1347 		return (ISC_R_SUCCESS);
   1348 	}
   1349 }
   1350 
   1351 static isc_result_t
   1352 dbiterator_next(dns_dbiterator_t *iterator) {
   1353 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1354 
   1355 	sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
   1356 	if (sdlziter->current == NULL) {
   1357 		return (ISC_R_NOMORE);
   1358 	} else {
   1359 		return (ISC_R_SUCCESS);
   1360 	}
   1361 }
   1362 
   1363 static isc_result_t
   1364 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
   1365 		   dns_name_t *name) {
   1366 	sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
   1367 
   1368 	attachnode(iterator->db, sdlziter->current, nodep);
   1369 	if (name != NULL) {
   1370 		dns_name_copy(sdlziter->current->name, name);
   1371 		return (ISC_R_SUCCESS);
   1372 	}
   1373 	return (ISC_R_SUCCESS);
   1374 }
   1375 
   1376 static isc_result_t
   1377 dbiterator_pause(dns_dbiterator_t *iterator) {
   1378 	UNUSED(iterator);
   1379 	return (ISC_R_SUCCESS);
   1380 }
   1381 
   1382 static isc_result_t
   1383 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
   1384 	UNUSED(iterator);
   1385 	dns_name_copy(dns_rootname, name);
   1386 	return (ISC_R_SUCCESS);
   1387 }
   1388 
   1389 /*
   1390  * Rdataset Methods. These methods were "borrowed" from the SDB driver
   1391  * interface.  See the SDB driver interface documentation for more info.
   1392  */
   1393 
   1394 static void
   1395 disassociate(dns_rdataset_t *rdataset) {
   1396 	dns_dbnode_t *node = rdataset->private5;
   1397 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
   1398 	dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
   1399 
   1400 	detachnode(db, &node);
   1401 	isc__rdatalist_disassociate(rdataset);
   1402 }
   1403 
   1404 static void
   1405 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
   1406 	dns_dbnode_t *node = source->private5;
   1407 	dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
   1408 	dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
   1409 	dns_dbnode_t *tempdb = NULL;
   1410 
   1411 	isc__rdatalist_clone(source, target);
   1412 	attachnode(db, node, &tempdb);
   1413 	source->private5 = tempdb;
   1414 }
   1415 
   1416 static dns_rdatasetmethods_t rdataset_methods = {
   1417 	disassociate,
   1418 	isc__rdatalist_first,
   1419 	isc__rdatalist_next,
   1420 	isc__rdatalist_current,
   1421 	rdataset_clone,
   1422 	isc__rdatalist_count,
   1423 	isc__rdatalist_addnoqname,
   1424 	isc__rdatalist_getnoqname,
   1425 	NULL, /* addclosest */
   1426 	NULL, /* getclosest */
   1427 	NULL, /* settrust */
   1428 	NULL, /* expire */
   1429 	NULL, /* clearprefetch */
   1430 	NULL, /* setownercase */
   1431 	NULL, /* getownercase */
   1432 	NULL  /* addglue */
   1433 };
   1434 
   1435 static void
   1436 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
   1437 		dns_rdataset_t *rdataset) {
   1438 	/*
   1439 	 * The sdlz rdataset is an rdatalist with some additions.
   1440 	 *	- private1 & private2 are used by the rdatalist.
   1441 	 *	- private3 & private 4 are unused.
   1442 	 *	- private5 is the node.
   1443 	 */
   1444 
   1445 	/* This should never fail. */
   1446 	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
   1447 		      ISC_R_SUCCESS);
   1448 
   1449 	rdataset->methods = &rdataset_methods;
   1450 	dns_db_attachnode(db, node, &rdataset->private5);
   1451 }
   1452 
   1453 /*
   1454  * SDLZ core methods. This is the core of the new DLZ functionality.
   1455  */
   1456 
   1457 /*%
   1458  * Build a 'bind' database driver structure to be returned by
   1459  * either the find zone or the allow zone transfer method.
   1460  * This method is only available in this source file, it is
   1461  * not made available anywhere else.
   1462  */
   1463 
   1464 static isc_result_t
   1465 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
   1466 		  const dns_name_t *name, dns_rdataclass_t rdclass,
   1467 		  dns_db_t **dbp) {
   1468 	isc_result_t result;
   1469 	dns_sdlz_db_t *sdlzdb;
   1470 	dns_sdlzimplementation_t *imp;
   1471 
   1472 	/* check that things are as we expect */
   1473 	REQUIRE(dbp != NULL && *dbp == NULL);
   1474 	REQUIRE(name != NULL);
   1475 
   1476 	imp = (dns_sdlzimplementation_t *)driverarg;
   1477 
   1478 	/* allocate and zero memory for driver structure */
   1479 	sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
   1480 	memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
   1481 
   1482 	/* initialize and set origin */
   1483 	dns_name_init(&sdlzdb->common.origin, NULL);
   1484 	result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
   1485 	if (result != ISC_R_SUCCESS) {
   1486 		goto mem_cleanup;
   1487 	}
   1488 
   1489 	/* set the rest of the database structure attributes */
   1490 	sdlzdb->dlzimp = imp;
   1491 	sdlzdb->common.methods = &sdlzdb_methods;
   1492 	sdlzdb->common.attributes = 0;
   1493 	sdlzdb->common.rdclass = rdclass;
   1494 	sdlzdb->common.mctx = NULL;
   1495 	sdlzdb->dbdata = dbdata;
   1496 	isc_refcount_init(&sdlzdb->references, 1);
   1497 
   1498 	/* attach to the memory context */
   1499 	isc_mem_attach(mctx, &sdlzdb->common.mctx);
   1500 
   1501 	/* mark structure as valid */
   1502 	sdlzdb->common.magic = DNS_DB_MAGIC;
   1503 	sdlzdb->common.impmagic = SDLZDB_MAGIC;
   1504 	*dbp = (dns_db_t *)sdlzdb;
   1505 
   1506 	return (result);
   1507 mem_cleanup:
   1508 	isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
   1509 	return (result);
   1510 }
   1511 
   1512 static isc_result_t
   1513 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
   1514 		     dns_rdataclass_t rdclass, const dns_name_t *name,
   1515 		     const isc_sockaddr_t *clientaddr, dns_db_t **dbp) {
   1516 	isc_buffer_t b;
   1517 	isc_buffer_t b2;
   1518 	char namestr[DNS_NAME_MAXTEXT + 1];
   1519 	char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255."
   1520 			       "255") +
   1521 		       1];
   1522 	isc_netaddr_t netaddr;
   1523 	isc_result_t result;
   1524 	dns_sdlzimplementation_t *imp;
   1525 
   1526 	/*
   1527 	 * Perform checks to make sure data is as we expect it to be.
   1528 	 */
   1529 	REQUIRE(driverarg != NULL);
   1530 	REQUIRE(name != NULL);
   1531 	REQUIRE(clientaddr != NULL);
   1532 	REQUIRE(dbp != NULL && *dbp == NULL);
   1533 
   1534 	imp = (dns_sdlzimplementation_t *)driverarg;
   1535 
   1536 	/* Convert DNS name to ascii text */
   1537 	isc_buffer_init(&b, namestr, sizeof(namestr));
   1538 	result = dns_name_totext(name, true, &b);
   1539 	if (result != ISC_R_SUCCESS) {
   1540 		return (result);
   1541 	}
   1542 	isc_buffer_putuint8(&b, 0);
   1543 
   1544 	/* convert client address to ascii text */
   1545 	isc_buffer_init(&b2, clientstr, sizeof(clientstr));
   1546 	isc_netaddr_fromsockaddr(&netaddr, clientaddr);
   1547 	result = isc_netaddr_totext(&netaddr, &b2);
   1548 	if (result != ISC_R_SUCCESS) {
   1549 		return (result);
   1550 	}
   1551 	isc_buffer_putuint8(&b2, 0);
   1552 
   1553 	/* make sure strings are always lowercase */
   1554 	dns_sdlz_tolower(namestr);
   1555 	dns_sdlz_tolower(clientstr);
   1556 
   1557 	/* Call SDLZ driver's find zone method */
   1558 	if (imp->methods->allowzonexfr != NULL) {
   1559 		isc_result_t rresult = ISC_R_SUCCESS;
   1560 
   1561 		MAYBE_LOCK(imp);
   1562 		result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
   1563 						    namestr, clientstr);
   1564 		MAYBE_UNLOCK(imp);
   1565 		/*
   1566 		 * if zone is supported and transfers are (or might be)
   1567 		 * allowed, build a 'bind' database driver
   1568 		 */
   1569 		if (result == ISC_R_SUCCESS || result == ISC_R_DEFAULT) {
   1570 			rresult = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
   1571 						    name, rdclass, dbp);
   1572 		}
   1573 		if (rresult != ISC_R_SUCCESS) {
   1574 			result = rresult;
   1575 		}
   1576 		return (result);
   1577 	}
   1578 
   1579 	return (ISC_R_NOTIMPLEMENTED);
   1580 }
   1581 
   1582 static isc_result_t
   1583 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
   1584 	       char *argv[], void *driverarg, void **dbdata) {
   1585 	dns_sdlzimplementation_t *imp;
   1586 	isc_result_t result = ISC_R_NOTFOUND;
   1587 
   1588 	/* Write debugging message to log */
   1589 	sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
   1590 
   1591 	/*
   1592 	 * Performs checks to make sure data is as we expect it to be.
   1593 	 */
   1594 	REQUIRE(driverarg != NULL);
   1595 	REQUIRE(dlzname != NULL);
   1596 	REQUIRE(dbdata != NULL);
   1597 	UNUSED(mctx);
   1598 
   1599 	imp = driverarg;
   1600 
   1601 	/* If the create method exists, call it. */
   1602 	if (imp->methods->create != NULL) {
   1603 		MAYBE_LOCK(imp);
   1604 		result = imp->methods->create(dlzname, argc, argv,
   1605 					      imp->driverarg, dbdata);
   1606 		MAYBE_UNLOCK(imp);
   1607 	}
   1608 
   1609 	/* Write debugging message to log */
   1610 	if (result == ISC_R_SUCCESS) {
   1611 		sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
   1612 	} else {
   1613 		sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
   1614 	}
   1615 
   1616 	return (result);
   1617 }
   1618 
   1619 static void
   1620 dns_sdlzdestroy(void *driverdata, void **dbdata) {
   1621 	dns_sdlzimplementation_t *imp;
   1622 
   1623 	/* Write debugging message to log */
   1624 	sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
   1625 
   1626 	imp = driverdata;
   1627 
   1628 	/* If the destroy method exists, call it. */
   1629 	if (imp->methods->destroy != NULL) {
   1630 		MAYBE_LOCK(imp);
   1631 		imp->methods->destroy(imp->driverarg, dbdata);
   1632 		MAYBE_UNLOCK(imp);
   1633 	}
   1634 }
   1635 
   1636 static isc_result_t
   1637 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
   1638 		 dns_rdataclass_t rdclass, const dns_name_t *name,
   1639 		 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
   1640 		 dns_db_t **dbp) {
   1641 	isc_buffer_t b;
   1642 	char namestr[DNS_NAME_MAXTEXT + 1];
   1643 	isc_result_t result;
   1644 	dns_sdlzimplementation_t *imp;
   1645 
   1646 	/*
   1647 	 * Perform checks to make sure data is as we expect it to be.
   1648 	 */
   1649 	REQUIRE(driverarg != NULL);
   1650 	REQUIRE(name != NULL);
   1651 	REQUIRE(dbp != NULL && *dbp == NULL);
   1652 
   1653 	imp = (dns_sdlzimplementation_t *)driverarg;
   1654 
   1655 	/* Convert DNS name to ascii text */
   1656 	isc_buffer_init(&b, namestr, sizeof(namestr));
   1657 	result = dns_name_totext(name, true, &b);
   1658 	if (result != ISC_R_SUCCESS) {
   1659 		return (result);
   1660 	}
   1661 	isc_buffer_putuint8(&b, 0);
   1662 
   1663 	/* make sure strings are always lowercase */
   1664 	dns_sdlz_tolower(namestr);
   1665 
   1666 	/* Call SDLZ driver's find zone method */
   1667 	MAYBE_LOCK(imp);
   1668 	result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
   1669 					methods, clientinfo);
   1670 	MAYBE_UNLOCK(imp);
   1671 
   1672 	/*
   1673 	 * if zone is supported build a 'bind' database driver
   1674 	 * structure to return
   1675 	 */
   1676 	if (result == ISC_R_SUCCESS) {
   1677 		result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
   1678 					   rdclass, dbp);
   1679 	}
   1680 
   1681 	return (result);
   1682 }
   1683 
   1684 static isc_result_t
   1685 dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view,
   1686 		  dns_dlzdb_t *dlzdb) {
   1687 	isc_result_t result;
   1688 	dns_sdlzimplementation_t *imp;
   1689 
   1690 	REQUIRE(driverarg != NULL);
   1691 
   1692 	imp = (dns_sdlzimplementation_t *)driverarg;
   1693 
   1694 	/* Call SDLZ driver's configure method */
   1695 	if (imp->methods->configure != NULL) {
   1696 		MAYBE_LOCK(imp);
   1697 		result = imp->methods->configure(view, dlzdb, imp->driverarg,
   1698 						 dbdata);
   1699 		MAYBE_UNLOCK(imp);
   1700 	} else {
   1701 		result = ISC_R_SUCCESS;
   1702 	}
   1703 
   1704 	return (result);
   1705 }
   1706 
   1707 static bool
   1708 dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name,
   1709 		 const isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
   1710 		 const dst_key_t *key, void *driverarg, void *dbdata) {
   1711 	dns_sdlzimplementation_t *imp;
   1712 	char b_signer[DNS_NAME_FORMATSIZE];
   1713 	char b_name[DNS_NAME_FORMATSIZE];
   1714 	char b_addr[ISC_NETADDR_FORMATSIZE];
   1715 	char b_type[DNS_RDATATYPE_FORMATSIZE];
   1716 	char b_key[DST_KEY_FORMATSIZE];
   1717 	isc_buffer_t *tkey_token = NULL;
   1718 	isc_region_t token_region = { NULL, 0 };
   1719 	uint32_t token_len = 0;
   1720 	bool ret;
   1721 
   1722 	REQUIRE(driverarg != NULL);
   1723 
   1724 	imp = (dns_sdlzimplementation_t *)driverarg;
   1725 	if (imp->methods->ssumatch == NULL) {
   1726 		return (false);
   1727 	}
   1728 
   1729 	/*
   1730 	 * Format the request elements. sdlz operates on strings, not
   1731 	 * structures
   1732 	 */
   1733 	if (signer != NULL) {
   1734 		dns_name_format(signer, b_signer, sizeof(b_signer));
   1735 	} else {
   1736 		b_signer[0] = 0;
   1737 	}
   1738 
   1739 	dns_name_format(name, b_name, sizeof(b_name));
   1740 
   1741 	if (tcpaddr != NULL) {
   1742 		isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
   1743 	} else {
   1744 		b_addr[0] = 0;
   1745 	}
   1746 
   1747 	dns_rdatatype_format(type, b_type, sizeof(b_type));
   1748 
   1749 	if (key != NULL) {
   1750 		dst_key_format(key, b_key, sizeof(b_key));
   1751 		tkey_token = dst_key_tkeytoken(key);
   1752 	} else {
   1753 		b_key[0] = 0;
   1754 	}
   1755 
   1756 	if (tkey_token != NULL) {
   1757 		isc_buffer_region(tkey_token, &token_region);
   1758 		token_len = token_region.length;
   1759 	}
   1760 
   1761 	MAYBE_LOCK(imp);
   1762 	ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
   1763 				     token_len,
   1764 				     token_len != 0 ? token_region.base : NULL,
   1765 				     imp->driverarg, dbdata);
   1766 	MAYBE_UNLOCK(imp);
   1767 	return (ret);
   1768 }
   1769 
   1770 static dns_dlzmethods_t sdlzmethods = { dns_sdlzcreate,	   dns_sdlzdestroy,
   1771 					dns_sdlzfindzone,  dns_sdlzallowzonexfr,
   1772 					dns_sdlzconfigure, dns_sdlzssumatch };
   1773 
   1774 /*
   1775  * Public functions.
   1776  */
   1777 
   1778 isc_result_t
   1779 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
   1780 	       const char *data) {
   1781 	dns_rdatalist_t *rdatalist;
   1782 	dns_rdata_t *rdata;
   1783 	dns_rdatatype_t typeval;
   1784 	isc_consttextregion_t r;
   1785 	isc_buffer_t b;
   1786 	isc_buffer_t *rdatabuf = NULL;
   1787 	isc_lex_t *lex;
   1788 	isc_result_t result;
   1789 	unsigned int size;
   1790 	isc_mem_t *mctx;
   1791 	const dns_name_t *origin;
   1792 
   1793 	REQUIRE(VALID_SDLZLOOKUP(lookup));
   1794 	REQUIRE(type != NULL);
   1795 	REQUIRE(data != NULL);
   1796 
   1797 	mctx = lookup->sdlz->common.mctx;
   1798 
   1799 	r.base = type;
   1800 	r.length = strlen(type);
   1801 	result = dns_rdatatype_fromtext(&typeval, (void *)&r);
   1802 	if (result != ISC_R_SUCCESS) {
   1803 		return (result);
   1804 	}
   1805 
   1806 	rdatalist = ISC_LIST_HEAD(lookup->lists);
   1807 	while (rdatalist != NULL) {
   1808 		if (rdatalist->type == typeval) {
   1809 			break;
   1810 		}
   1811 		rdatalist = ISC_LIST_NEXT(rdatalist, link);
   1812 	}
   1813 
   1814 	if (rdatalist == NULL) {
   1815 		rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
   1816 		dns_rdatalist_init(rdatalist);
   1817 		rdatalist->rdclass = lookup->sdlz->common.rdclass;
   1818 		rdatalist->type = typeval;
   1819 		rdatalist->ttl = ttl;
   1820 		ISC_LIST_APPEND(lookup->lists, rdatalist, link);
   1821 	} else if (rdatalist->ttl > ttl) {
   1822 		/*
   1823 		 * BIND9 doesn't enforce all RRs in an RRset
   1824 		 * having the same TTL, as per RFC 2136,
   1825 		 * section 7.12. If a DLZ backend has
   1826 		 * different TTLs, then the best
   1827 		 * we can do is return the lowest.
   1828 		 */
   1829 		rdatalist->ttl = ttl;
   1830 	}
   1831 
   1832 	rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
   1833 	dns_rdata_init(rdata);
   1834 
   1835 	if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
   1836 		origin = &lookup->sdlz->common.origin;
   1837 	} else {
   1838 		origin = dns_rootname;
   1839 	}
   1840 
   1841 	lex = NULL;
   1842 	result = isc_lex_create(mctx, 64, &lex);
   1843 	if (result != ISC_R_SUCCESS) {
   1844 		goto failure;
   1845 	}
   1846 
   1847 	size = initial_size(data);
   1848 	do {
   1849 		isc_buffer_constinit(&b, data, strlen(data));
   1850 		isc_buffer_add(&b, strlen(data));
   1851 
   1852 		result = isc_lex_openbuffer(lex, &b);
   1853 		if (result != ISC_R_SUCCESS) {
   1854 			goto failure;
   1855 		}
   1856 
   1857 		rdatabuf = NULL;
   1858 		isc_buffer_allocate(mctx, &rdatabuf, size);
   1859 
   1860 		result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
   1861 					    rdatalist->type, lex, origin, false,
   1862 					    mctx, rdatabuf, &lookup->callbacks);
   1863 		if (result != ISC_R_SUCCESS) {
   1864 			isc_buffer_free(&rdatabuf);
   1865 		}
   1866 		if (size >= 65535) {
   1867 			break;
   1868 		}
   1869 		size *= 2;
   1870 		if (size >= 65535) {
   1871 			size = 65535;
   1872 		}
   1873 	} while (result == ISC_R_NOSPACE);
   1874 
   1875 	if (result != ISC_R_SUCCESS) {
   1876 		result = DNS_R_SERVFAIL;
   1877 		goto failure;
   1878 	}
   1879 
   1880 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
   1881 	ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
   1882 
   1883 	if (lex != NULL) {
   1884 		isc_lex_destroy(&lex);
   1885 	}
   1886 
   1887 	return (ISC_R_SUCCESS);
   1888 
   1889 failure:
   1890 	if (rdatabuf != NULL) {
   1891 		isc_buffer_free(&rdatabuf);
   1892 	}
   1893 	if (lex != NULL) {
   1894 		isc_lex_destroy(&lex);
   1895 	}
   1896 	isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
   1897 
   1898 	return (result);
   1899 }
   1900 
   1901 isc_result_t
   1902 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
   1903 		    const char *type, dns_ttl_t ttl, const char *data) {
   1904 	dns_name_t *newname;
   1905 	const dns_name_t *origin;
   1906 	dns_fixedname_t fnewname;
   1907 	dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
   1908 	dns_sdlznode_t *sdlznode;
   1909 	isc_mem_t *mctx = sdlz->common.mctx;
   1910 	isc_buffer_t b;
   1911 	isc_result_t result;
   1912 
   1913 	newname = dns_fixedname_initname(&fnewname);
   1914 
   1915 	if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
   1916 		origin = &sdlz->common.origin;
   1917 	} else {
   1918 		origin = dns_rootname;
   1919 	}
   1920 	isc_buffer_constinit(&b, name, strlen(name));
   1921 	isc_buffer_add(&b, strlen(name));
   1922 
   1923 	result = dns_name_fromtext(newname, &b, origin, 0, NULL);
   1924 	if (result != ISC_R_SUCCESS) {
   1925 		return (result);
   1926 	}
   1927 
   1928 	if (allnodes->common.relative_names) {
   1929 		/* All names are relative to the root */
   1930 		unsigned int nlabels = dns_name_countlabels(newname);
   1931 		dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
   1932 	}
   1933 
   1934 	sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
   1935 	if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
   1936 		sdlznode = NULL;
   1937 		result = createnode(sdlz, &sdlznode);
   1938 		if (result != ISC_R_SUCCESS) {
   1939 			return (result);
   1940 		}
   1941 		sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
   1942 		dns_name_init(sdlznode->name, NULL);
   1943 		dns_name_dup(newname, mctx, sdlznode->name);
   1944 		ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
   1945 		if (allnodes->origin == NULL &&
   1946 		    dns_name_equal(newname, &sdlz->common.origin))
   1947 		{
   1948 			allnodes->origin = sdlznode;
   1949 		}
   1950 	}
   1951 	return (dns_sdlz_putrr(sdlznode, type, ttl, data));
   1952 }
   1953 
   1954 isc_result_t
   1955 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
   1956 		uint32_t serial) {
   1957 	char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
   1958 	int n;
   1959 
   1960 	REQUIRE(mname != NULL);
   1961 	REQUIRE(rname != NULL);
   1962 
   1963 	n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", mname, rname,
   1964 		     serial, SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
   1965 		     SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
   1966 	if (n >= (int)sizeof(str) || n < 0) {
   1967 		return (ISC_R_NOSPACE);
   1968 	}
   1969 	return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
   1970 }
   1971 
   1972 isc_result_t
   1973 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
   1974 		 void *driverarg, unsigned int flags, isc_mem_t *mctx,
   1975 		 dns_sdlzimplementation_t **sdlzimp) {
   1976 	dns_sdlzimplementation_t *imp;
   1977 	isc_result_t result;
   1978 
   1979 	/*
   1980 	 * Performs checks to make sure data is as we expect it to be.
   1981 	 */
   1982 	REQUIRE(drivername != NULL);
   1983 	REQUIRE(methods != NULL);
   1984 	REQUIRE(methods->findzone != NULL);
   1985 	REQUIRE(methods->lookup != NULL);
   1986 	REQUIRE(mctx != NULL);
   1987 	REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
   1988 	REQUIRE((flags &
   1989 		 ~(DNS_SDLZFLAG_RELATIVEOWNER | DNS_SDLZFLAG_RELATIVERDATA |
   1990 		   DNS_SDLZFLAG_THREADSAFE)) == 0);
   1991 
   1992 	/* Write debugging message to log */
   1993 	sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
   1994 
   1995 	/*
   1996 	 * Allocate memory for a sdlz_implementation object.  Error if
   1997 	 * we cannot.
   1998 	 */
   1999 	imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
   2000 
   2001 	/* Make sure memory region is set to all 0's */
   2002 	memset(imp, 0, sizeof(dns_sdlzimplementation_t));
   2003 
   2004 	/* Store the data passed into this method */
   2005 	imp->methods = methods;
   2006 	imp->driverarg = driverarg;
   2007 	imp->flags = flags;
   2008 	imp->mctx = NULL;
   2009 
   2010 	/* attach the new sdlz_implementation object to a memory context */
   2011 	isc_mem_attach(mctx, &imp->mctx);
   2012 
   2013 	/*
   2014 	 * initialize the driver lock, error if we cannot
   2015 	 * (used if a driver does not support multiple threads)
   2016 	 */
   2017 	isc_mutex_init(&imp->driverlock);
   2018 
   2019 	imp->dlz_imp = NULL;
   2020 
   2021 	/*
   2022 	 * register the DLZ driver.  Pass in our "extra" sdlz information as
   2023 	 * a driverarg.  (that's why we stored the passed in driver arg in our
   2024 	 * sdlz_implementation structure)  Also, store the dlz_implementation
   2025 	 * structure in our sdlz_implementation.
   2026 	 */
   2027 	result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
   2028 				 &imp->dlz_imp);
   2029 
   2030 	/* if registration fails, cleanup and get outta here. */
   2031 	if (result != ISC_R_SUCCESS) {
   2032 		goto cleanup_mutex;
   2033 	}
   2034 
   2035 	*sdlzimp = imp;
   2036 
   2037 	return (ISC_R_SUCCESS);
   2038 
   2039 cleanup_mutex:
   2040 	/* destroy the driver lock, we don't need it anymore */
   2041 	isc_mutex_destroy(&imp->driverlock);
   2042 
   2043 	/*
   2044 	 * return the memory back to the available memory pool and
   2045 	 * remove it from the memory context.
   2046 	 */
   2047 	isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
   2048 	return (result);
   2049 }
   2050 
   2051 void
   2052 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
   2053 	dns_sdlzimplementation_t *imp;
   2054 
   2055 	/* Write debugging message to log */
   2056 	sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
   2057 
   2058 	/*
   2059 	 * Performs checks to make sure data is as we expect it to be.
   2060 	 */
   2061 	REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
   2062 
   2063 	imp = *sdlzimp;
   2064 	*sdlzimp = NULL;
   2065 
   2066 	/* Unregister the DLZ driver implementation */
   2067 	dns_dlzunregister(&imp->dlz_imp);
   2068 
   2069 	/* destroy the driver lock, we don't need it anymore */
   2070 	isc_mutex_destroy(&imp->driverlock);
   2071 
   2072 	/*
   2073 	 * return the memory back to the available memory pool and
   2074 	 * remove it from the memory context.
   2075 	 */
   2076 	isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
   2077 }
   2078 
   2079 isc_result_t
   2080 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
   2081 	       const dns_name_t *name, dns_db_t **dbp) {
   2082 	isc_result_t result;
   2083 
   2084 	result = dns_sdlzcreateDBP(dlzdatabase->mctx,
   2085 				   dlzdatabase->implementation->driverarg,
   2086 				   dlzdatabase->dbdata, name, rdclass, dbp);
   2087 	return (result);
   2088 }
   2089