dlz.c revision ca103999e64da0b16bb8b30589408f1556264dce
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd/*
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * Portions Copyright (C) 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC")
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * Portions Copyright (C) 1999-2001 Internet Software Consortium.
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar *
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * Permission to use, copy, modify, and/or distribute this software for any
a3d2b657dd7ca66251b562b6a82c2335135b9172nd * purpose with or without fee is hereby granted, provided that the above
031b91a62d25106ae69d4693475c79618dd5e884fielding * copyright notice and this permission notice appear in all copies.
031b91a62d25106ae69d4693475c79618dd5e884fielding *
031b91a62d25106ae69d4693475c79618dd5e884fielding * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
031b91a62d25106ae69d4693475c79618dd5e884fielding * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
031b91a62d25106ae69d4693475c79618dd5e884fielding * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
031b91a62d25106ae69d4693475c79618dd5e884fielding * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
a3d2b657dd7ca66251b562b6a82c2335135b9172nd * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
a3d2b657dd7ca66251b562b6a82c2335135b9172nd * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
a3d2b657dd7ca66251b562b6a82c2335135b9172nd * PERFORMANCE OF THIS SOFTWARE.
a3d2b657dd7ca66251b562b6a82c2335135b9172nd */
a3d2b657dd7ca66251b562b6a82c2335135b9172nd
a3d2b657dd7ca66251b562b6a82c2335135b9172nd/*
a3d2b657dd7ca66251b562b6a82c2335135b9172nd * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
a3d2b657dd7ca66251b562b6a82c2335135b9172nd *
a3d2b657dd7ca66251b562b6a82c2335135b9172nd * Permission to use, copy, modify, and distribute this software for any
a3d2b657dd7ca66251b562b6a82c2335135b9172nd * purpose with or without fee is hereby granted, provided that the
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * above copyright notice and this permission notice appear in all
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * copies.
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd *
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * USE OR PERFORMANCE OF THIS SOFTWARE.
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd *
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * conceived and contributed by Rob Butler.
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd *
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * Permission to use, copy, modify, and distribute this software for any
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * purpose with or without fee is hereby granted, provided that the
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd * above copyright notice and this permission notice appear in all
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * copies.
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd *
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * USE OR PERFORMANCE OF THIS SOFTWARE.
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd/* $Id: dlz.c,v 1.10 2010/12/20 23:47:20 tbox Exp $ */
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd/*! \file */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd/***
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd *** Imports
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd ***/
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <config.h>
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <dns/fixedname.h>
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <dns/log.h>
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd#include <dns/master.h>
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <dns/dlz.h>
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <dns/ssu.h>
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <dns/zone.h>
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <isc/buffer.h>
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <isc/magic.h>
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <isc/mem.h>
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <isc/once.h>
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <isc/rwlock.h>
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <isc/string.h>
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#include <isc/util.h>
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd/***
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd *** Supported DLZ DB Implementations Registry
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd ***/
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic ISC_LIST(dns_dlzimplementation_t) dlz_implementations;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic isc_rwlock_t dlz_implock;
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fndstatic isc_once_t once = ISC_ONCE_INIT;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic void
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nddlz_initialize(void) {
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd RUNTIME_CHECK(isc_rwlock_init(&dlz_implock, 0, 0) == ISC_R_SUCCESS);
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd ISC_LIST_INIT(dlz_implementations);
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd}
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd/*%
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd * Searches the dlz_implementations list for a driver matching name.
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd */
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fndstatic inline dns_dlzimplementation_t *
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnddlz_impfind(const char *name) {
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd dns_dlzimplementation_t *imp;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd for (imp = ISC_LIST_HEAD(dlz_implementations);
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd imp != NULL;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd imp = ISC_LIST_NEXT(imp, link))
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd if (strcasecmp(name, imp->name) == 0)
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd return (imp);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd return (NULL);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd}
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd/***
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd *** Basic DLZ Methods
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd ***/
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndisc_result_t
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nddns_dlzallowzonexfr(dns_view_t *view, dns_name_t *name,
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd isc_sockaddr_t *clientaddr, dns_db_t **dbp)
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd{
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd isc_result_t result;
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd dns_dlzallowzonexfr_t allowzonexfr;
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd dns_dlzdb_t *dlzdatabase;
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd /*
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd * Performs checks to make sure data is as we expect it to be.
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd */
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd REQUIRE(name != NULL);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd REQUIRE(dbp != NULL && *dbp == NULL);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd /* ask driver if the zone is supported */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd dlzdatabase = view->dlzdatabase;
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd allowzonexfr = dlzdatabase->implementation->methods->allowzonexfr;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd result = (*allowzonexfr)(dlzdatabase->implementation->driverarg,
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd dlzdatabase->dbdata, dlzdatabase->mctx,
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd view->rdclass, name, clientaddr, dbp);
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd if (result == ISC_R_NOTIMPLEMENTED)
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd return (ISC_R_NOTFOUND);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd return (result);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd}
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fndisc_result_t
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnddns_dlzcreate(isc_mem_t *mctx, const char *dlzname, const char *drivername,
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd unsigned int argc, char *argv[], dns_dlzdb_t **dbp)
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd{
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd dns_dlzimplementation_t *impinfo;
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd isc_result_t result;
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd /*
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd * initialize the dlz_implementations list, this is guaranteed
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd * to only really happen once.
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd */
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd /*
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd * Performs checks to make sure data is as we expect it to be.
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd */
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd REQUIRE(dbp != NULL && *dbp == NULL);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd REQUIRE(dlzname != NULL);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd REQUIRE(drivername != NULL);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd REQUIRE(mctx != NULL);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd /* write log message */
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd "Loading '%s' using driver %s", dlzname, drivername);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd /* lock the dlz_implementations list so we can search it. */
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd RWLOCK(&dlz_implock, isc_rwlocktype_read);
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd /* search for the driver implementation */
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd impinfo = dlz_impfind(drivername);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd if (impinfo == NULL) {
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd "unsupported DLZ database driver '%s'."
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd " %s not loaded.",
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd drivername, dlzname);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd return (ISC_R_NOTFOUND);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd }
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd /* Allocate memory to hold the DLZ database driver */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd (*dbp) = isc_mem_get(mctx, sizeof(dns_dlzdb_t));
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd if ((*dbp) == NULL) {
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd return (ISC_R_NOMEMORY);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd }
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd /* Make sure memory region is set to all 0's */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd memset((*dbp), 0, sizeof(dns_dlzdb_t));
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd (*dbp)->implementation = impinfo;
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd /* Create a new database using implementation 'drivername'. */
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd result = ((impinfo->methods->create)(mctx, dlzname, argc, argv,
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd impinfo->driverarg,
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd &(*dbp)->dbdata));
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd /* mark the DLZ driver as valid */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd if (result == ISC_R_SUCCESS) {
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd (*dbp)->magic = DNS_DLZ_MAGIC;
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd isc_mem_attach(mctx, &(*dbp)->mctx);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd "DLZ driver loaded successfully.");
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd return (ISC_R_SUCCESS);
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd } else {
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd "DLZ driver failed to load.");
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd }
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd /* impinfo->methods->create failed. */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd isc_mem_put(mctx, (*dbp), sizeof(dns_dlzdb_t));
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd return (result);
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd}
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndvoid
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnddns_dlzdestroy(dns_dlzdb_t **dbp) {
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd isc_mem_t *mctx;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd dns_dlzdestroy_t destroy;
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd /* Write debugging message to log */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd "Unloading DLZ driver.");
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd /*
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * Perform checks to make sure data is as we expect it to be.
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd */
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd REQUIRE(dbp != NULL && DNS_DLZ_VALID(*dbp));
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd#ifdef BIND9
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd if ((*dbp)->ssutable != NULL) {
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd dns_ssutable_detach(&(*dbp)->ssutable);
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd }
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd#endif
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd /* call the drivers destroy method */
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd if ((*dbp) != NULL) {
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd mctx = (*dbp)->mctx;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd destroy = (*dbp)->implementation->methods->destroy;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd (*destroy)((*dbp)->implementation->driverarg,(*dbp)->dbdata);
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd /* return memory */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd isc_mem_put(mctx, (*dbp), sizeof(dns_dlzdb_t));
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd isc_mem_detach(&mctx);
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd }
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd *dbp = NULL;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd}
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fndisc_result_t
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnddns_dlzfindzone(dns_view_t *view, dns_name_t *name, unsigned int minlabels,
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fnd dns_db_t **dbp)
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd{
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd dns_fixedname_t fname;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd dns_name_t *zonename;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd unsigned int namelabels;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd unsigned int i;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd isc_result_t result;
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd dns_dlzfindzone_t findzone;
dns_dlzdb_t *dlzdatabase;
/*
* Performs checks to make sure data is as we expect it to be.
*/
REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
REQUIRE(name != NULL);
REQUIRE(dbp != NULL && *dbp == NULL);
/* setup a "fixed" dns name */
dns_fixedname_init(&fname);
zonename = dns_fixedname_name(&fname);
/* count the number of labels in the name */
namelabels = dns_name_countlabels(name);
/*
* loop through starting with the longest domain name and
* trying shorter names portions of the name until we find a
* match, have an error, or are below the 'minlabels'
* threshold. minlabels is 0, if the standard database didn't
* have a zone name match. Otherwise minlabels is the number
* of labels in that name. We need to beat that for a
* "better" match for the DLZ database to be authoritative
* instead of the standard database.
*/
for (i = namelabels; i > minlabels && i > 1; i--) {
if (i == namelabels) {
result = dns_name_copy(name, zonename, NULL);
if (result != ISC_R_SUCCESS)
return (result);
} else
dns_name_split(name, i, NULL, zonename);
/* ask SDLZ driver if the zone is supported */
dlzdatabase = view->dlzdatabase;
findzone = dlzdatabase->implementation->methods->findzone;
result = (*findzone)(dlzdatabase->implementation->driverarg,
dlzdatabase->dbdata, dlzdatabase->mctx,
view->rdclass, zonename, dbp);
if (result != ISC_R_NOTFOUND)
return (result);
}
return (ISC_R_NOTFOUND);
}
/*%
* Registers a DLZ driver. This basically just adds the dlz
* driver to the list of available drivers in the dlz_implementations list.
*/
isc_result_t
dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods,
void *driverarg, isc_mem_t *mctx,
dns_dlzimplementation_t **dlzimp)
{
dns_dlzimplementation_t *dlz_imp;
/* Write debugging message to log */
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
"Registering DLZ driver '%s'", drivername);
/*
* Performs checks to make sure data is as we expect it to be.
*/
REQUIRE(drivername != NULL);
REQUIRE(methods != NULL);
REQUIRE(methods->create != NULL);
REQUIRE(methods->destroy != NULL);
REQUIRE(methods->findzone != NULL);
REQUIRE(mctx != NULL);
REQUIRE(dlzimp != NULL && *dlzimp == NULL);
/*
* initialize the dlz_implementations list, this is guaranteed
* to only really happen once.
*/
RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
/* lock the dlz_implementations list so we can modify it. */
RWLOCK(&dlz_implock, isc_rwlocktype_write);
/*
* check that another already registered driver isn't using
* the same name
*/
dlz_imp = dlz_impfind(drivername);
if (dlz_imp != NULL) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
"DLZ Driver '%s' already registered",
drivername);
RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
return (ISC_R_EXISTS);
}
/*
* Allocate memory for a dlz_implementation object. Error if
* we cannot.
*/
dlz_imp = isc_mem_get(mctx, sizeof(dns_dlzimplementation_t));
if (dlz_imp == NULL) {
RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
return (ISC_R_NOMEMORY);
}
/* Make sure memory region is set to all 0's */
memset(dlz_imp, 0, sizeof(dns_dlzimplementation_t));
/* Store the data passed into this method */
dlz_imp->name = drivername;
dlz_imp->methods = methods;
dlz_imp->mctx = NULL;
dlz_imp->driverarg = driverarg;
/* attach the new dlz_implementation object to a memory context */
isc_mem_attach(mctx, &dlz_imp->mctx);
/*
* prepare the dlz_implementation object to be put in a list,
* and append it to the list
*/
ISC_LINK_INIT(dlz_imp, link);
ISC_LIST_APPEND(dlz_implementations, dlz_imp, link);
/* Unlock the dlz_implementations list. */
RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
/* Pass back the dlz_implementation that we created. */
*dlzimp = dlz_imp;
return (ISC_R_SUCCESS);
}
/*%
* Helper function for dns_dlzstrtoargv().
* Pardon the gratuitous recursion.
*/
static isc_result_t
dns_dlzstrtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp,
char ***argvp, unsigned int n)
{
isc_result_t result;
restart:
/* Discard leading whitespace. */
while (*s == ' ' || *s == '\t')
s++;
if (*s == '\0') {
/* We have reached the end of the string. */
*argcp = n;
*argvp = isc_mem_get(mctx, n * sizeof(char *));
if (*argvp == NULL)
return (ISC_R_NOMEMORY);
} else {
char *p = s;
while (*p != ' ' && *p != '\t' && *p != '\0' && *p != '{') {
if (*p == '\n') {
*p = ' ';
goto restart;
}
p++;
}
/* do "grouping", items between { and } are one arg */
if (*p == '{') {
char *t = p;
/*
* shift all characters to left by 1 to get rid of '{'
*/
while (*t != '\0') {
t++;
*(t-1) = *t;
}
while (*p != '\0' && *p != '}') {
p++;
}
/* get rid of '}' character */
if (*p == '}') {
*p = '\0';
p++;
}
/* normal case, no "grouping" */
} else if (*p != '\0')
*p++ = '\0';
result = dns_dlzstrtoargvsub(mctx, p, argcp, argvp, n + 1);
if (result != ISC_R_SUCCESS)
return (result);
(*argvp)[n] = s;
}
return (ISC_R_SUCCESS);
}
/*%
* Tokenize the string "s" into whitespace-separated words,
* return the number of words in '*argcp' and an array
* of pointers to the words in '*argvp'. The caller
* must free the array using isc_mem_put(). The string
* is modified in-place.
*/
isc_result_t
dns_dlzstrtoargv(isc_mem_t *mctx, char *s,
unsigned int *argcp, char ***argvp)
{
return(dns_dlzstrtoargvsub(mctx, s, argcp, argvp, 0));
}
/*%
* Unregisters a DLZ driver. This basically just removes the dlz
* driver from the list of available drivers in the dlz_implementations list.
*/
void
dns_dlzunregister(dns_dlzimplementation_t **dlzimp) {
dns_dlzimplementation_t *dlz_imp;
isc_mem_t *mctx;
/* Write debugging message to log */
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
"Unregistering DLZ driver.");
/*
* Performs checks to make sure data is as we expect it to be.
*/
REQUIRE(dlzimp != NULL && *dlzimp != NULL);
/*
* initialize the dlz_implementations list, this is guaranteed
* to only really happen once.
*/
RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
dlz_imp = *dlzimp;
/* lock the dlz_implementations list so we can modify it. */
RWLOCK(&dlz_implock, isc_rwlocktype_write);
/* remove the dlz_implementation object from the list */
ISC_LIST_UNLINK(dlz_implementations, dlz_imp, link);
mctx = dlz_imp->mctx;
/*
* Return the memory back to the available memory pool and
* remove it from the memory context.
*/
isc_mem_put(mctx, dlz_imp, sizeof(dns_dlzimplementation_t));
isc_mem_detach(&mctx);
/* Unlock the dlz_implementations list. */
RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
}
#ifdef BIND9
/*
* Create a writeable DLZ zone. This can be called by DLZ drivers
* during configure() to create a zone that can be updated. The zone
* type is set to dns_zone_dlz, which is equivalent to a master zone
*
* This function uses a callback setup in dns_dlzconfigure() to call
* into the server zone code to setup the remaining pieces of server
* specific functionality on the zone
*/
isc_result_t
dns_dlz_writeablezone(dns_view_t *view, const char *zone_name) {
dns_zone_t *zone = NULL;
dns_zone_t *dupzone = NULL;
isc_result_t result;
isc_buffer_t buffer;
dns_fixedname_t fixorigin;
dns_name_t *origin;
dns_rdataclass_t zclass;
dns_dlzdb_t *dlzdatabase;
REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
dlzdatabase = view->dlzdatabase;
REQUIRE(dlzdatabase->configure_callback != NULL);
isc_buffer_init(&buffer, zone_name, strlen(zone_name));
isc_buffer_add(&buffer, strlen(zone_name));
dns_fixedname_init(&fixorigin);
result = dns_name_fromtext(dns_fixedname_name(&fixorigin),
&buffer, dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS)
goto cleanup;
origin = dns_fixedname_name(&fixorigin);
zclass = view->rdclass;
/* See if the zone already exists */
result = dns_view_findzone(view, origin, &dupzone);
if (result == ISC_R_SUCCESS) {
dns_zone_detach(&dupzone);
result = ISC_R_EXISTS;
goto cleanup;
}
INSIST(dupzone == NULL);
/* Create it */
result = dns_zone_create(&zone, view->mctx);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_zone_setorigin(zone, origin);
if (result != ISC_R_SUCCESS)
goto cleanup;
dns_zone_setview(zone, view);
dns_zone_setadded(zone, ISC_TRUE);
if (dlzdatabase->ssutable == NULL) {
result = dns_ssutable_createdlz(dlzdatabase->mctx,
&dlzdatabase->ssutable,
view->dlzdatabase);
if (result != ISC_R_SUCCESS)
goto cleanup;
}
dns_zone_setssutable(zone, dlzdatabase->ssutable);
result = dlzdatabase->configure_callback(view, zone);
if (result != ISC_R_SUCCESS)
goto cleanup;
/*
* Add the zone to its view in the new view list.
*/
result = dns_view_addzone(view, zone);
result = ISC_R_SUCCESS;
cleanup:
if (zone != NULL)
dns_zone_detach(&zone);
return (result);
}
#endif
/*%
* Configure a DLZ driver. This is optional, and if supplied gives
* the backend an opportunity to configure parameters related to DLZ.
*/
isc_result_t
dns_dlzconfigure(dns_view_t *view, isc_result_t (*callback)(dns_view_t *,
dns_zone_t *))
{
dns_dlzimplementation_t *impl;
dns_dlzdb_t *dlzdatabase;
isc_result_t result;
REQUIRE(view != NULL);
REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
REQUIRE(view->dlzdatabase->implementation != NULL);
dlzdatabase = view->dlzdatabase;
impl = dlzdatabase->implementation;
if (impl->methods->configure == NULL)
return (ISC_R_SUCCESS);
dlzdatabase->configure_callback = callback;
result = impl->methods->configure(impl->driverarg,
dlzdatabase->dbdata, view);
return (result);
}
isc_boolean_t
dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase,
dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr,
dns_rdatatype_t type, const dst_key_t *key)
{
dns_dlzimplementation_t *impl;
isc_boolean_t r;
REQUIRE(dlzdatabase != NULL);
REQUIRE(dlzdatabase->implementation != NULL);
REQUIRE(dlzdatabase->implementation->methods != NULL);
impl = dlzdatabase->implementation;
if (impl->methods->ssumatch == NULL) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
"No ssumatch method for DLZ database");
return (ISC_FALSE);
}
r = impl->methods->ssumatch(signer, name, tcpaddr, type, key,
impl->driverarg, dlzdatabase->dbdata);
return (r);
}