1/* $NetBSD: driver.c,v 1.8 2024/02/21 22:51:27 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 AND ISC 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16/* 17 * Copyright (C) Red Hat 18 * 19 * Permission to use, copy, modify, and/or distribute this software for any 20 * purpose with or without fee is hereby granted, provided that the above 21 * copyright notice and this permission notice appear in all copies. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH 24 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 25 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 26 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 27 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 28 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 29 * PERFORMANCE OF THIS SOFTWARE. 30 */ 31 32/* 33 * Driver API implementation and main entry point for BIND. 34 * 35 * BIND calls dyndb_version() before loading, dyndb_init() during startup 36 * and dyndb_destroy() during shutdown. 37 * 38 * It is completely up to implementation what to do. 39 * 40 * dyndb <name> <driver> {} sections in named.conf are independent so 41 * driver init() and destroy() functions are called independently for 42 * each section even if they reference the same driver/library. It is 43 * up to driver implementation to detect and catch this situation if 44 * it is undesirable. 45 */ 46 47#include <isc/commandline.h> 48#include <isc/hash.h> 49#include <isc/mem.h> 50#include <isc/util.h> 51 52#include <dns/db.h> 53#include <dns/dyndb.h> 54#include <dns/types.h> 55 56#include "db.h" 57#include "instance.h" 58#include "log.h" 59#include "util.h" 60 61/* aliases for the exported symbols */ 62 63dns_dyndb_destroy_t dyndb_destroy; 64dns_dyndb_register_t dyndb_init; 65dns_dyndb_version_t dyndb_version; 66 67/* 68 * Driver init is called for each dyndb section in named.conf 69 * once during startup and then again on every reload. 70 * 71 * @code 72 * dyndb example-name "sample.so" { param1 param2 }; 73 * @endcode 74 * 75 * @param[in] name User-defined string from dyndb "name" {}; definition 76 * in named.conf. 77 * The example above will have name = "example-name". 78 * @param[in] parameters User-defined parameters from dyndb section as one 79 * string. The example above will have 80 * params = "param1 param2"; 81 * @param[in] file The name of the file from which the parameters 82 * were read. 83 * @param[in] line The line number from which the parameters were read. 84 * @param[out] instp Pointer to instance-specific data 85 * (for one dyndb section). 86 */ 87isc_result_t 88dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters, 89 const char *file, unsigned long line, const dns_dyndbctx_t *dctx, 90 void **instp) { 91 isc_result_t result; 92 unsigned int argc; 93 char **argv = NULL; 94 char *s = NULL; 95 sample_instance_t *sample_inst = NULL; 96 97 REQUIRE(name != NULL); 98 REQUIRE(dctx != NULL); 99 100 s = isc_mem_strdup(mctx, parameters); 101 102 result = isc_commandline_strtoargv(mctx, s, &argc, &argv, 0); 103 if (result != ISC_R_SUCCESS) { 104 log_write(ISC_LOG_ERROR, 105 "dyndb_init: isc_commandline_strtoargv -> %s\n", 106 isc_result_totext(result)); 107 goto cleanup; 108 } 109 110 log_write(ISC_LOG_DEBUG(9), "loading params for dyndb '%s' from %s:%lu", 111 name, file, line); 112 113 /* Finally, create the instance. */ 114 result = new_sample_instance(mctx, name, argc, argv, dctx, 115 &sample_inst); 116 if (result != ISC_R_SUCCESS) { 117 log_write(ISC_LOG_ERROR, 118 "dyndb_init: new_sample_instance -> %s\n", 119 isc_result_totext(result)); 120 goto cleanup; 121 } 122 123 /* 124 * This is an example so we create and load zones 125 * right now. This step can be arbitrarily postponed. 126 */ 127 result = load_sample_instance_zones(sample_inst); 128 if (result != ISC_R_SUCCESS) { 129 log_write(ISC_LOG_ERROR, 130 "dyndb_init: load_sample_instance_zones -> %s\n", 131 isc_result_totext(result)); 132 goto cleanup; 133 } 134 135 *instp = sample_inst; 136 137cleanup: 138 isc_mem_free(mctx, s); 139 if (argv != NULL) { 140 isc_mem_put(mctx, argv, argc * sizeof(*argv)); 141 } 142 143 return (result); 144} 145 146/* 147 * Driver destroy is called for every instance on every reload and then once 148 * during shutdown. 149 * 150 * @param[out] instp Pointer to instance-specific data (for one dyndb section). 151 */ 152void 153dyndb_destroy(void **instp) { 154 destroy_sample_instance((sample_instance_t **)instp); 155} 156 157/* 158 * Driver version is called when loading the driver to ensure there 159 * is no API mismatch between the driver and the caller. 160 */ 161int 162dyndb_version(unsigned int *flags) { 163 UNUSED(flags); 164 165 return (DNS_DYNDB_VERSION); 166} 167