1*bcda20f6Schristos /* $NetBSD: dlz.c,v 1.9 2025/01/26 16:25:22 christos Exp $ */ 2d68c78b8Schristos 3d68c78b8Schristos /* 48596601aSchristos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 58596601aSchristos * 68596601aSchristos * SPDX-License-Identifier: MPL-2.0 AND ISC 7d68c78b8Schristos * 8d68c78b8Schristos * This Source Code Form is subject to the terms of the Mozilla Public 9d68c78b8Schristos * License, v. 2.0. If a copy of the MPL was not distributed with this 10fce770bdSchristos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11d68c78b8Schristos * 12d68c78b8Schristos * See the COPYRIGHT file distributed with this work for additional 13d68c78b8Schristos * information regarding copyright ownership. 14d68c78b8Schristos */ 15d68c78b8Schristos 16d68c78b8Schristos /* 17d68c78b8Schristos * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl. 18d68c78b8Schristos * 19d68c78b8Schristos * Permission to use, copy, modify, and distribute this software for any 20d68c78b8Schristos * purpose with or without fee is hereby granted, provided that the 21d68c78b8Schristos * above copyright notice and this permission notice appear in all 22d68c78b8Schristos * copies. 23d68c78b8Schristos * 24d68c78b8Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET 25d68c78b8Schristos * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 26d68c78b8Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 27d68c78b8Schristos * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 28d68c78b8Schristos * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 29d68c78b8Schristos * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 30d68c78b8Schristos * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE 31d68c78b8Schristos * USE OR PERFORMANCE OF THIS SOFTWARE. 32d68c78b8Schristos * 33d68c78b8Schristos * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was 34d68c78b8Schristos * conceived and contributed by Rob Butler. 35d68c78b8Schristos * 36d68c78b8Schristos * Permission to use, copy, modify, and distribute this software for any 37d68c78b8Schristos * purpose with or without fee is hereby granted, provided that the 38d68c78b8Schristos * above copyright notice and this permission notice appear in all 39d68c78b8Schristos * copies. 40d68c78b8Schristos * 41d68c78b8Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER 42d68c78b8Schristos * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 43d68c78b8Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 44d68c78b8Schristos * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 45d68c78b8Schristos * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 46d68c78b8Schristos * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 47d68c78b8Schristos * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE 48d68c78b8Schristos * USE OR PERFORMANCE OF THIS SOFTWARE. 49d68c78b8Schristos */ 50d68c78b8Schristos 51d68c78b8Schristos /*! \file */ 52d68c78b8Schristos 53d68c78b8Schristos /*** 54d68c78b8Schristos *** Imports 55d68c78b8Schristos ***/ 56d68c78b8Schristos 57d4a20c3eSchristos #include <stdbool.h> 58d4a20c3eSchristos 59d68c78b8Schristos #include <isc/buffer.h> 60d68c78b8Schristos #include <isc/commandline.h> 61d68c78b8Schristos #include <isc/magic.h> 62d68c78b8Schristos #include <isc/mem.h> 63*bcda20f6Schristos #include <isc/netmgr.h> 64d68c78b8Schristos #include <isc/once.h> 65*bcda20f6Schristos #include <isc/random.h> 66d68c78b8Schristos #include <isc/rwlock.h> 67d68c78b8Schristos #include <isc/string.h> 68d68c78b8Schristos #include <isc/util.h> 69d68c78b8Schristos 705606745fSchristos #include <dns/db.h> 715606745fSchristos #include <dns/dlz.h> 725606745fSchristos #include <dns/fixedname.h> 735606745fSchristos #include <dns/log.h> 745606745fSchristos #include <dns/master.h> 755606745fSchristos #include <dns/ssu.h> 765606745fSchristos #include <dns/zone.h> 775606745fSchristos 78d68c78b8Schristos /*** 79d68c78b8Schristos *** Supported DLZ DB Implementations Registry 80d68c78b8Schristos ***/ 81d68c78b8Schristos 82d68c78b8Schristos static ISC_LIST(dns_dlzimplementation_t) dlz_implementations; 83d68c78b8Schristos static isc_rwlock_t dlz_implock; 84d68c78b8Schristos static isc_once_t once = ISC_ONCE_INIT; 85d68c78b8Schristos 86d68c78b8Schristos static void 87d68c78b8Schristos dlz_initialize(void) { 88*bcda20f6Schristos isc_rwlock_init(&dlz_implock); 89d68c78b8Schristos ISC_LIST_INIT(dlz_implementations); 90d68c78b8Schristos } 91d68c78b8Schristos 92d68c78b8Schristos /*% 93d68c78b8Schristos * Searches the dlz_implementations list for a driver matching name. 94d68c78b8Schristos */ 958596601aSchristos static dns_dlzimplementation_t * 96d68c78b8Schristos dlz_impfind(const char *name) { 97d68c78b8Schristos dns_dlzimplementation_t *imp; 98d68c78b8Schristos 995606745fSchristos for (imp = ISC_LIST_HEAD(dlz_implementations); imp != NULL; 100d68c78b8Schristos imp = ISC_LIST_NEXT(imp, link)) 1015606745fSchristos { 1025606745fSchristos if (strcasecmp(name, imp->name) == 0) { 103*bcda20f6Schristos return imp; 1045606745fSchristos } 1055606745fSchristos } 106*bcda20f6Schristos return NULL; 107d68c78b8Schristos } 108d68c78b8Schristos 109d68c78b8Schristos /*** 110d68c78b8Schristos *** Basic DLZ Methods 111d68c78b8Schristos ***/ 112d68c78b8Schristos 113d68c78b8Schristos isc_result_t 114d68c78b8Schristos dns_dlzallowzonexfr(dns_view_t *view, const dns_name_t *name, 1155606745fSchristos const isc_sockaddr_t *clientaddr, dns_db_t **dbp) { 116d68c78b8Schristos isc_result_t result = ISC_R_NOTFOUND; 117d68c78b8Schristos dns_dlzallowzonexfr_t allowzonexfr; 118d68c78b8Schristos dns_dlzdb_t *dlzdb; 119d68c78b8Schristos 120d68c78b8Schristos /* 121d68c78b8Schristos * Performs checks to make sure data is as we expect it to be. 122d68c78b8Schristos */ 123d68c78b8Schristos REQUIRE(name != NULL); 124d68c78b8Schristos REQUIRE(dbp != NULL && *dbp == NULL); 125d68c78b8Schristos 126d68c78b8Schristos /* 127d68c78b8Schristos * Find a driver in which the zone exists and transfer is supported 128d68c78b8Schristos */ 1295606745fSchristos for (dlzdb = ISC_LIST_HEAD(view->dlz_searched); dlzdb != NULL; 130d68c78b8Schristos dlzdb = ISC_LIST_NEXT(dlzdb, link)) 131d68c78b8Schristos { 132d68c78b8Schristos REQUIRE(DNS_DLZ_VALID(dlzdb)); 133d68c78b8Schristos 134d68c78b8Schristos allowzonexfr = dlzdb->implementation->methods->allowzonexfr; 135d68c78b8Schristos result = (*allowzonexfr)(dlzdb->implementation->driverarg, 136d68c78b8Schristos dlzdb->dbdata, dlzdb->mctx, 137d68c78b8Schristos view->rdclass, name, clientaddr, dbp); 138d68c78b8Schristos 139d68c78b8Schristos /* 1405606745fSchristos * In these cases, we found the right database. Non-success 1415606745fSchristos * result codes indicate the zone might not transfer. 142d68c78b8Schristos */ 1435606745fSchristos switch (result) { 1445606745fSchristos case ISC_R_SUCCESS: 1455606745fSchristos case ISC_R_NOPERM: 1465606745fSchristos case ISC_R_DEFAULT: 147*bcda20f6Schristos return result; 1485606745fSchristos default: 1495606745fSchristos break; 1505606745fSchristos } 151d68c78b8Schristos } 152d68c78b8Schristos 1535606745fSchristos if (result == ISC_R_NOTIMPLEMENTED) { 154d68c78b8Schristos result = ISC_R_NOTFOUND; 1555606745fSchristos } 156d68c78b8Schristos 157*bcda20f6Schristos return result; 158d68c78b8Schristos } 159d68c78b8Schristos 160d68c78b8Schristos isc_result_t 161d68c78b8Schristos dns_dlzcreate(isc_mem_t *mctx, const char *dlzname, const char *drivername, 1625606745fSchristos unsigned int argc, char *argv[], dns_dlzdb_t **dbp) { 163d68c78b8Schristos dns_dlzimplementation_t *impinfo; 164d68c78b8Schristos isc_result_t result; 165d68c78b8Schristos dns_dlzdb_t *db = NULL; 166d68c78b8Schristos 167d68c78b8Schristos /* 168d68c78b8Schristos * initialize the dlz_implementations list, this is guaranteed 169d68c78b8Schristos * to only really happen once. 170d68c78b8Schristos */ 171*bcda20f6Schristos isc_once_do(&once, dlz_initialize); 172d68c78b8Schristos 173d68c78b8Schristos /* 174d68c78b8Schristos * Performs checks to make sure data is as we expect it to be. 175d68c78b8Schristos */ 176d68c78b8Schristos REQUIRE(dbp != NULL && *dbp == NULL); 177d68c78b8Schristos REQUIRE(dlzname != NULL); 178d68c78b8Schristos REQUIRE(drivername != NULL); 179d68c78b8Schristos REQUIRE(mctx != NULL); 180d68c78b8Schristos 181d68c78b8Schristos /* write log message */ 1825606745fSchristos isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, 1835606745fSchristos ISC_LOG_INFO, "Loading '%s' using driver %s", dlzname, 1845606745fSchristos drivername); 185d68c78b8Schristos 186d68c78b8Schristos /* lock the dlz_implementations list so we can search it. */ 187d68c78b8Schristos RWLOCK(&dlz_implock, isc_rwlocktype_read); 188d68c78b8Schristos 189d68c78b8Schristos /* search for the driver implementation */ 190d68c78b8Schristos impinfo = dlz_impfind(drivername); 191d68c78b8Schristos if (impinfo == NULL) { 192d68c78b8Schristos RWUNLOCK(&dlz_implock, isc_rwlocktype_read); 193d68c78b8Schristos 194d68c78b8Schristos isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 195d68c78b8Schristos DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, 196d68c78b8Schristos "unsupported DLZ database driver '%s'." 197d68c78b8Schristos " %s not loaded.", 198d68c78b8Schristos drivername, dlzname); 199d68c78b8Schristos 200*bcda20f6Schristos return ISC_R_NOTFOUND; 201d68c78b8Schristos } 202d68c78b8Schristos 203d68c78b8Schristos /* Allocate memory to hold the DLZ database driver */ 204*bcda20f6Schristos db = isc_mem_get(mctx, sizeof(*db)); 205*bcda20f6Schristos *db = (dns_dlzdb_t){ 206*bcda20f6Schristos .implementation = impinfo, 207*bcda20f6Schristos }; 208d68c78b8Schristos 209d68c78b8Schristos ISC_LINK_INIT(db, link); 2105606745fSchristos if (dlzname != NULL) { 211d68c78b8Schristos db->dlzname = isc_mem_strdup(mctx, dlzname); 2125606745fSchristos } 213d68c78b8Schristos 214d68c78b8Schristos /* Create a new database using implementation 'drivername'. */ 215d68c78b8Schristos result = ((impinfo->methods->create)(mctx, dlzname, argc, argv, 2165606745fSchristos impinfo->driverarg, &db->dbdata)); 217d68c78b8Schristos 218d68c78b8Schristos RWUNLOCK(&dlz_implock, isc_rwlocktype_read); 219*bcda20f6Schristos /* mark the DLZ driver as valid */ 220*bcda20f6Schristos if (result != ISC_R_SUCCESS) { 221*bcda20f6Schristos goto failure; 222d68c78b8Schristos } 223d68c78b8Schristos 224*bcda20f6Schristos db->magic = DNS_DLZ_MAGIC; 225*bcda20f6Schristos isc_mem_attach(mctx, &db->mctx); 226*bcda20f6Schristos isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, 227*bcda20f6Schristos ISC_LOG_DEBUG(2), "DLZ driver loaded successfully."); 228*bcda20f6Schristos *dbp = db; 229*bcda20f6Schristos return ISC_R_SUCCESS; 230*bcda20f6Schristos failure: 231*bcda20f6Schristos isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, 232*bcda20f6Schristos ISC_LOG_ERROR, "DLZ driver failed to load."); 233*bcda20f6Schristos 234d68c78b8Schristos /* impinfo->methods->create failed. */ 2358596601aSchristos isc_mem_free(mctx, db->dlzname); 236*bcda20f6Schristos isc_mem_put(mctx, db, sizeof(*db)); 237*bcda20f6Schristos return result; 238d68c78b8Schristos } 239d68c78b8Schristos 240d68c78b8Schristos void 241d68c78b8Schristos dns_dlzdestroy(dns_dlzdb_t **dbp) { 242d68c78b8Schristos dns_dlzdestroy_t destroy; 243d68c78b8Schristos dns_dlzdb_t *db; 244d68c78b8Schristos 245d68c78b8Schristos /* Write debugging message to log */ 2465606745fSchristos isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, 2475606745fSchristos ISC_LOG_DEBUG(2), "Unloading DLZ driver."); 248d68c78b8Schristos 249d68c78b8Schristos /* 250d68c78b8Schristos * Perform checks to make sure data is as we expect it to be. 251d68c78b8Schristos */ 252d68c78b8Schristos REQUIRE(dbp != NULL && DNS_DLZ_VALID(*dbp)); 253d68c78b8Schristos 254d68c78b8Schristos db = *dbp; 255d68c78b8Schristos *dbp = NULL; 256d68c78b8Schristos 2575606745fSchristos if (db->ssutable != NULL) { 258d68c78b8Schristos dns_ssutable_detach(&db->ssutable); 2595606745fSchristos } 260d68c78b8Schristos 261d68c78b8Schristos /* call the drivers destroy method */ 2625606745fSchristos if (db->dlzname != NULL) { 263d68c78b8Schristos isc_mem_free(db->mctx, db->dlzname); 2645606745fSchristos } 265d68c78b8Schristos destroy = db->implementation->methods->destroy; 266d68c78b8Schristos (*destroy)(db->implementation->driverarg, db->dbdata); 267d68c78b8Schristos /* return memory and detach */ 268*bcda20f6Schristos isc_mem_putanddetach(&db->mctx, db, sizeof(*db)); 269d68c78b8Schristos } 270d68c78b8Schristos 271d68c78b8Schristos /*% 272d68c78b8Schristos * Registers a DLZ driver. This basically just adds the dlz 273d68c78b8Schristos * driver to the list of available drivers in the dlz_implementations list. 274d68c78b8Schristos */ 275d68c78b8Schristos isc_result_t 276d68c78b8Schristos dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods, 277d68c78b8Schristos void *driverarg, isc_mem_t *mctx, 2785606745fSchristos dns_dlzimplementation_t **dlzimp) { 279d68c78b8Schristos dns_dlzimplementation_t *dlz_imp; 280d68c78b8Schristos 281d68c78b8Schristos /* Write debugging message to log */ 2825606745fSchristos isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, 2835606745fSchristos ISC_LOG_DEBUG(2), "Registering DLZ driver '%s'", 2845606745fSchristos drivername); 285d68c78b8Schristos 286d68c78b8Schristos /* 287d68c78b8Schristos * Performs checks to make sure data is as we expect it to be. 288d68c78b8Schristos */ 289d68c78b8Schristos REQUIRE(drivername != NULL); 290d68c78b8Schristos REQUIRE(methods != NULL); 291d68c78b8Schristos REQUIRE(methods->create != NULL); 292d68c78b8Schristos REQUIRE(methods->destroy != NULL); 293d68c78b8Schristos REQUIRE(methods->findzone != NULL); 294d68c78b8Schristos REQUIRE(mctx != NULL); 295d68c78b8Schristos REQUIRE(dlzimp != NULL && *dlzimp == NULL); 296d68c78b8Schristos 297d68c78b8Schristos /* 298d68c78b8Schristos * initialize the dlz_implementations list, this is guaranteed 299d68c78b8Schristos * to only really happen once. 300d68c78b8Schristos */ 301*bcda20f6Schristos isc_once_do(&once, dlz_initialize); 302d68c78b8Schristos 303d68c78b8Schristos /* lock the dlz_implementations list so we can modify it. */ 304d68c78b8Schristos RWLOCK(&dlz_implock, isc_rwlocktype_write); 305d68c78b8Schristos 306d68c78b8Schristos /* 307d68c78b8Schristos * check that another already registered driver isn't using 308d68c78b8Schristos * the same name 309d68c78b8Schristos */ 310d68c78b8Schristos dlz_imp = dlz_impfind(drivername); 311d68c78b8Schristos if (dlz_imp != NULL) { 312d68c78b8Schristos isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 313d68c78b8Schristos DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 3145606745fSchristos "DLZ Driver '%s' already registered", drivername); 315d68c78b8Schristos RWUNLOCK(&dlz_implock, isc_rwlocktype_write); 316*bcda20f6Schristos return ISC_R_EXISTS; 317d68c78b8Schristos } 318d68c78b8Schristos 319d68c78b8Schristos /* 320d68c78b8Schristos * Allocate memory for a dlz_implementation object. Error if 321d68c78b8Schristos * we cannot. 322d68c78b8Schristos */ 323*bcda20f6Schristos dlz_imp = isc_mem_get(mctx, sizeof(*dlz_imp)); 324*bcda20f6Schristos *dlz_imp = (dns_dlzimplementation_t){ 325*bcda20f6Schristos .name = drivername, 326*bcda20f6Schristos .methods = methods, 327*bcda20f6Schristos .driverarg = driverarg, 328*bcda20f6Schristos }; 329d68c78b8Schristos 330d68c78b8Schristos /* attach the new dlz_implementation object to a memory context */ 331d68c78b8Schristos isc_mem_attach(mctx, &dlz_imp->mctx); 332d68c78b8Schristos 333d68c78b8Schristos /* 334d68c78b8Schristos * prepare the dlz_implementation object to be put in a list, 335d68c78b8Schristos * and append it to the list 336d68c78b8Schristos */ 337d68c78b8Schristos ISC_LINK_INIT(dlz_imp, link); 338d68c78b8Schristos ISC_LIST_APPEND(dlz_implementations, dlz_imp, link); 339d68c78b8Schristos 340d68c78b8Schristos /* Unlock the dlz_implementations list. */ 341d68c78b8Schristos RWUNLOCK(&dlz_implock, isc_rwlocktype_write); 342d68c78b8Schristos 343d68c78b8Schristos /* Pass back the dlz_implementation that we created. */ 344d68c78b8Schristos *dlzimp = dlz_imp; 345d68c78b8Schristos 346*bcda20f6Schristos return ISC_R_SUCCESS; 347d68c78b8Schristos } 348d68c78b8Schristos 349d68c78b8Schristos /*% 350d68c78b8Schristos * Tokenize the string "s" into whitespace-separated words, 351d68c78b8Schristos * return the number of words in '*argcp' and an array 352d68c78b8Schristos * of pointers to the words in '*argvp'. The caller 353d68c78b8Schristos * must free the array using isc_mem_put(). The string 354d68c78b8Schristos * is modified in-place. 355d68c78b8Schristos */ 356d68c78b8Schristos isc_result_t 3575606745fSchristos dns_dlzstrtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) { 358*bcda20f6Schristos return isc_commandline_strtoargv(mctx, s, argcp, argvp, 0); 359d68c78b8Schristos } 360d68c78b8Schristos 361d68c78b8Schristos /*% 362d68c78b8Schristos * Unregisters a DLZ driver. This basically just removes the dlz 363d68c78b8Schristos * driver from the list of available drivers in the dlz_implementations list. 364d68c78b8Schristos */ 365d68c78b8Schristos void 366d68c78b8Schristos dns_dlzunregister(dns_dlzimplementation_t **dlzimp) { 367d68c78b8Schristos dns_dlzimplementation_t *dlz_imp; 368d68c78b8Schristos 369d68c78b8Schristos /* Write debugging message to log */ 3705606745fSchristos isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, 3715606745fSchristos ISC_LOG_DEBUG(2), "Unregistering DLZ driver."); 372d68c78b8Schristos 373d68c78b8Schristos /* 374d68c78b8Schristos * Performs checks to make sure data is as we expect it to be. 375d68c78b8Schristos */ 376d68c78b8Schristos REQUIRE(dlzimp != NULL && *dlzimp != NULL); 377d68c78b8Schristos 378d68c78b8Schristos /* 379d68c78b8Schristos * initialize the dlz_implementations list, this is guaranteed 380d68c78b8Schristos * to only really happen once. 381d68c78b8Schristos */ 382*bcda20f6Schristos isc_once_do(&once, dlz_initialize); 383d68c78b8Schristos 384d68c78b8Schristos dlz_imp = *dlzimp; 385d68c78b8Schristos 386d68c78b8Schristos /* lock the dlz_implementations list so we can modify it. */ 387d68c78b8Schristos RWLOCK(&dlz_implock, isc_rwlocktype_write); 388d68c78b8Schristos 389d68c78b8Schristos /* remove the dlz_implementation object from the list */ 390d68c78b8Schristos ISC_LIST_UNLINK(dlz_implementations, dlz_imp, link); 391d68c78b8Schristos 392d68c78b8Schristos /* 393d68c78b8Schristos * Return the memory back to the available memory pool and 394d68c78b8Schristos * remove it from the memory context. 395d68c78b8Schristos */ 3965606745fSchristos isc_mem_putanddetach(&dlz_imp->mctx, dlz_imp, sizeof(*dlz_imp)); 397d68c78b8Schristos 398d68c78b8Schristos /* Unlock the dlz_implementations list. */ 399d68c78b8Schristos RWUNLOCK(&dlz_implock, isc_rwlocktype_write); 400d68c78b8Schristos } 401d68c78b8Schristos 402d68c78b8Schristos /* 403d68c78b8Schristos * Create a writeable DLZ zone. This can be called by DLZ drivers 404d68c78b8Schristos * during configure() to create a zone that can be updated. The zone 405bb5aa156Schristos * type is set to dns_zone_dlz, which is equivalent to a primary zone 406d68c78b8Schristos * 407d68c78b8Schristos * This function uses a callback setup in dns_dlzconfigure() to call 408d68c78b8Schristos * into the server zone code to setup the remaining pieces of server 409d68c78b8Schristos * specific functionality on the zone 410d68c78b8Schristos */ 411d68c78b8Schristos isc_result_t 412d68c78b8Schristos dns_dlz_writeablezone(dns_view_t *view, dns_dlzdb_t *dlzdb, 4135606745fSchristos const char *zone_name) { 414d68c78b8Schristos dns_zone_t *zone = NULL; 415d68c78b8Schristos dns_zone_t *dupzone = NULL; 416d68c78b8Schristos isc_result_t result; 417d68c78b8Schristos isc_buffer_t buffer; 418d68c78b8Schristos dns_fixedname_t fixorigin; 419d68c78b8Schristos dns_name_t *origin; 420d68c78b8Schristos 421d68c78b8Schristos REQUIRE(DNS_DLZ_VALID(dlzdb)); 422d68c78b8Schristos 423d68c78b8Schristos REQUIRE(dlzdb->configure_callback != NULL); 424d68c78b8Schristos 425d68c78b8Schristos isc_buffer_constinit(&buffer, zone_name, strlen(zone_name)); 426d68c78b8Schristos isc_buffer_add(&buffer, strlen(zone_name)); 427d68c78b8Schristos dns_fixedname_init(&fixorigin); 4285606745fSchristos result = dns_name_fromtext(dns_fixedname_name(&fixorigin), &buffer, 4295606745fSchristos dns_rootname, 0, NULL); 4305606745fSchristos if (result != ISC_R_SUCCESS) { 431d68c78b8Schristos goto cleanup; 4325606745fSchristos } 433d68c78b8Schristos origin = dns_fixedname_name(&fixorigin); 434d68c78b8Schristos 435d68c78b8Schristos if (!dlzdb->search) { 436d68c78b8Schristos isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 437d68c78b8Schristos DNS_LOGMODULE_DLZ, ISC_LOG_WARNING, 438d68c78b8Schristos "DLZ %s has 'search no;', but attempted to " 439d68c78b8Schristos "register writeable zone %s.", 440d68c78b8Schristos dlzdb->dlzname, zone_name); 441d68c78b8Schristos result = ISC_R_SUCCESS; 442d68c78b8Schristos goto cleanup; 443d68c78b8Schristos } 444d68c78b8Schristos 445d68c78b8Schristos /* See if the zone already exists */ 446*bcda20f6Schristos result = dns_view_findzone(view, origin, DNS_ZTFIND_EXACT, &dupzone); 447d68c78b8Schristos if (result == ISC_R_SUCCESS) { 448d68c78b8Schristos dns_zone_detach(&dupzone); 449d68c78b8Schristos result = ISC_R_EXISTS; 450d68c78b8Schristos goto cleanup; 451d68c78b8Schristos } 452d68c78b8Schristos INSIST(dupzone == NULL); 453d68c78b8Schristos 454d68c78b8Schristos /* Create it */ 455*bcda20f6Schristos dns_zone_create(&zone, view->mctx, 0); 456d68c78b8Schristos result = dns_zone_setorigin(zone, origin); 4575606745fSchristos if (result != ISC_R_SUCCESS) { 458d68c78b8Schristos goto cleanup; 4595606745fSchristos } 460d68c78b8Schristos dns_zone_setview(zone, view); 461d68c78b8Schristos 462d4a20c3eSchristos dns_zone_setadded(zone, true); 463d68c78b8Schristos 464d68c78b8Schristos if (dlzdb->ssutable == NULL) { 465bb5aa156Schristos dns_ssutable_createdlz(dlzdb->mctx, &dlzdb->ssutable, dlzdb); 4665606745fSchristos } 467d68c78b8Schristos dns_zone_setssutable(zone, dlzdb->ssutable); 468d68c78b8Schristos 469d68c78b8Schristos result = dlzdb->configure_callback(view, dlzdb, zone); 4705606745fSchristos if (result != ISC_R_SUCCESS) { 471d68c78b8Schristos goto cleanup; 4725606745fSchristos } 473d68c78b8Schristos 474d68c78b8Schristos result = dns_view_addzone(view, zone); 475d68c78b8Schristos 476d68c78b8Schristos cleanup: 4775606745fSchristos if (zone != NULL) { 478d68c78b8Schristos dns_zone_detach(&zone); 4795606745fSchristos } 480d68c78b8Schristos 481*bcda20f6Schristos return result; 482d68c78b8Schristos } 483d68c78b8Schristos 484d68c78b8Schristos /*% 485d68c78b8Schristos * Configure a DLZ driver. This is optional, and if supplied gives 486d68c78b8Schristos * the backend an opportunity to configure parameters related to DLZ. 487d68c78b8Schristos */ 488d68c78b8Schristos isc_result_t 489d68c78b8Schristos dns_dlzconfigure(dns_view_t *view, dns_dlzdb_t *dlzdb, 4905606745fSchristos dlzconfigure_callback_t callback) { 491d68c78b8Schristos dns_dlzimplementation_t *impl; 492d68c78b8Schristos isc_result_t result; 493d68c78b8Schristos 494d68c78b8Schristos REQUIRE(DNS_DLZ_VALID(dlzdb)); 495d68c78b8Schristos REQUIRE(dlzdb->implementation != NULL); 496d68c78b8Schristos 497d68c78b8Schristos impl = dlzdb->implementation; 498d68c78b8Schristos 4995606745fSchristos if (impl->methods->configure == NULL) { 500*bcda20f6Schristos return ISC_R_SUCCESS; 5015606745fSchristos } 502d68c78b8Schristos 503d68c78b8Schristos dlzdb->configure_callback = callback; 504d68c78b8Schristos 5055606745fSchristos result = impl->methods->configure(impl->driverarg, dlzdb->dbdata, view, 5065606745fSchristos dlzdb); 507*bcda20f6Schristos return result; 508d68c78b8Schristos } 509d68c78b8Schristos 510d4a20c3eSchristos bool 511d68c78b8Schristos dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase, const dns_name_t *signer, 512d68c78b8Schristos const dns_name_t *name, const isc_netaddr_t *tcpaddr, 5135606745fSchristos dns_rdatatype_t type, const dst_key_t *key) { 514d68c78b8Schristos dns_dlzimplementation_t *impl; 515d4a20c3eSchristos bool r; 516d68c78b8Schristos 517d68c78b8Schristos REQUIRE(dlzdatabase != NULL); 518d68c78b8Schristos REQUIRE(dlzdatabase->implementation != NULL); 519d68c78b8Schristos REQUIRE(dlzdatabase->implementation->methods != NULL); 520d68c78b8Schristos impl = dlzdatabase->implementation; 521d68c78b8Schristos 522d68c78b8Schristos if (impl->methods->ssumatch == NULL) { 523d68c78b8Schristos isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 524d68c78b8Schristos DNS_LOGMODULE_DLZ, ISC_LOG_INFO, 525d68c78b8Schristos "No ssumatch method for DLZ database"); 526*bcda20f6Schristos return false; 527d68c78b8Schristos } 528d68c78b8Schristos 529d68c78b8Schristos r = impl->methods->ssumatch(signer, name, tcpaddr, type, key, 530d68c78b8Schristos impl->driverarg, dlzdatabase->dbdata); 531*bcda20f6Schristos return r; 532d68c78b8Schristos } 533