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