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