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