dyndb.c revision 1.2.2.2 1 1.2.2.2 pgoyette /* $NetBSD: dyndb.c,v 1.2.2.2 2018/09/06 06:55:00 pgoyette Exp $ */
2 1.2.2.2 pgoyette
3 1.2.2.2 pgoyette /*
4 1.2.2.2 pgoyette * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 1.2.2.2 pgoyette *
6 1.2.2.2 pgoyette * This Source Code Form is subject to the terms of the Mozilla Public
7 1.2.2.2 pgoyette * License, v. 2.0. If a copy of the MPL was not distributed with this
8 1.2.2.2 pgoyette * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 1.2.2.2 pgoyette *
10 1.2.2.2 pgoyette * See the COPYRIGHT file distributed with this work for additional
11 1.2.2.2 pgoyette * information regarding copyright ownership.
12 1.2.2.2 pgoyette */
13 1.2.2.2 pgoyette
14 1.2.2.2 pgoyette
15 1.2.2.2 pgoyette #include <config.h>
16 1.2.2.2 pgoyette
17 1.2.2.2 pgoyette #if HAVE_DLFCN_H
18 1.2.2.2 pgoyette #include <dlfcn.h>
19 1.2.2.2 pgoyette #elif _WIN32
20 1.2.2.2 pgoyette #include <windows.h>
21 1.2.2.2 pgoyette #endif
22 1.2.2.2 pgoyette
23 1.2.2.2 pgoyette #include <isc/buffer.h>
24 1.2.2.2 pgoyette #include <isc/mem.h>
25 1.2.2.2 pgoyette #include <isc/mutex.h>
26 1.2.2.2 pgoyette #include <isc/once.h>
27 1.2.2.2 pgoyette #include <isc/result.h>
28 1.2.2.2 pgoyette #include <isc/region.h>
29 1.2.2.2 pgoyette #include <isc/task.h>
30 1.2.2.2 pgoyette #include <isc/types.h>
31 1.2.2.2 pgoyette #include <isc/util.h>
32 1.2.2.2 pgoyette
33 1.2.2.2 pgoyette #include <dns/dyndb.h>
34 1.2.2.2 pgoyette #include <dns/log.h>
35 1.2.2.2 pgoyette #include <dns/types.h>
36 1.2.2.2 pgoyette #include <dns/view.h>
37 1.2.2.2 pgoyette #include <dns/zone.h>
38 1.2.2.2 pgoyette
39 1.2.2.2 pgoyette #include <string.h>
40 1.2.2.2 pgoyette
41 1.2.2.2 pgoyette #define CHECK(op) \
42 1.2.2.2 pgoyette do { result = (op); \
43 1.2.2.2 pgoyette if (result != ISC_R_SUCCESS) goto cleanup; \
44 1.2.2.2 pgoyette } while (0)
45 1.2.2.2 pgoyette
46 1.2.2.2 pgoyette
47 1.2.2.2 pgoyette typedef struct dyndb_implementation dyndb_implementation_t;
48 1.2.2.2 pgoyette struct dyndb_implementation {
49 1.2.2.2 pgoyette isc_mem_t *mctx;
50 1.2.2.2 pgoyette void *handle;
51 1.2.2.2 pgoyette dns_dyndb_register_t *register_func;
52 1.2.2.2 pgoyette dns_dyndb_destroy_t *destroy_func;
53 1.2.2.2 pgoyette char *name;
54 1.2.2.2 pgoyette void *inst;
55 1.2.2.2 pgoyette LINK(dyndb_implementation_t) link;
56 1.2.2.2 pgoyette };
57 1.2.2.2 pgoyette
58 1.2.2.2 pgoyette /*
59 1.2.2.2 pgoyette * List of dyndb implementations. Locked by dyndb_lock.
60 1.2.2.2 pgoyette *
61 1.2.2.2 pgoyette * These are stored here so they can be cleaned up on shutdown.
62 1.2.2.2 pgoyette * (The order in which they are stored is not important.)
63 1.2.2.2 pgoyette */
64 1.2.2.2 pgoyette static LIST(dyndb_implementation_t) dyndb_implementations;
65 1.2.2.2 pgoyette
66 1.2.2.2 pgoyette /* Locks dyndb_implementations. */
67 1.2.2.2 pgoyette static isc_mutex_t dyndb_lock;
68 1.2.2.2 pgoyette static isc_once_t once = ISC_ONCE_INIT;
69 1.2.2.2 pgoyette
70 1.2.2.2 pgoyette static void
71 1.2.2.2 pgoyette dyndb_initialize(void) {
72 1.2.2.2 pgoyette RUNTIME_CHECK(isc_mutex_init(&dyndb_lock) == ISC_R_SUCCESS);
73 1.2.2.2 pgoyette INIT_LIST(dyndb_implementations);
74 1.2.2.2 pgoyette }
75 1.2.2.2 pgoyette
76 1.2.2.2 pgoyette static dyndb_implementation_t *
77 1.2.2.2 pgoyette impfind(const char *name) {
78 1.2.2.2 pgoyette dyndb_implementation_t *imp;
79 1.2.2.2 pgoyette
80 1.2.2.2 pgoyette for (imp = ISC_LIST_HEAD(dyndb_implementations);
81 1.2.2.2 pgoyette imp != NULL;
82 1.2.2.2 pgoyette imp = ISC_LIST_NEXT(imp, link))
83 1.2.2.2 pgoyette if (strcasecmp(name, imp->name) == 0)
84 1.2.2.2 pgoyette return (imp);
85 1.2.2.2 pgoyette return (NULL);
86 1.2.2.2 pgoyette }
87 1.2.2.2 pgoyette
88 1.2.2.2 pgoyette #if HAVE_DLFCN_H && HAVE_DLOPEN
89 1.2.2.2 pgoyette static isc_result_t
90 1.2.2.2 pgoyette load_symbol(void *handle, const char *filename,
91 1.2.2.2 pgoyette const char *symbol_name, void **symbolp)
92 1.2.2.2 pgoyette {
93 1.2.2.2 pgoyette const char *errmsg;
94 1.2.2.2 pgoyette void *symbol;
95 1.2.2.2 pgoyette
96 1.2.2.2 pgoyette REQUIRE(handle != NULL);
97 1.2.2.2 pgoyette REQUIRE(symbolp != NULL && *symbolp == NULL);
98 1.2.2.2 pgoyette
99 1.2.2.2 pgoyette symbol = dlsym(handle, symbol_name);
100 1.2.2.2 pgoyette if (symbol == NULL) {
101 1.2.2.2 pgoyette errmsg = dlerror();
102 1.2.2.2 pgoyette if (errmsg == NULL)
103 1.2.2.2 pgoyette errmsg = "returned function pointer is NULL";
104 1.2.2.2 pgoyette isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
105 1.2.2.2 pgoyette DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR,
106 1.2.2.2 pgoyette "failed to lookup symbol %s in "
107 1.2.2.2 pgoyette "dyndb module '%s': %s",
108 1.2.2.2 pgoyette symbol_name, filename, errmsg);
109 1.2.2.2 pgoyette return (ISC_R_FAILURE);
110 1.2.2.2 pgoyette }
111 1.2.2.2 pgoyette dlerror();
112 1.2.2.2 pgoyette
113 1.2.2.2 pgoyette *symbolp = symbol;
114 1.2.2.2 pgoyette
115 1.2.2.2 pgoyette return (ISC_R_SUCCESS);
116 1.2.2.2 pgoyette }
117 1.2.2.2 pgoyette
118 1.2.2.2 pgoyette static isc_result_t
119 1.2.2.2 pgoyette load_library(isc_mem_t *mctx, const char *filename, const char *instname,
120 1.2.2.2 pgoyette dyndb_implementation_t **impp)
121 1.2.2.2 pgoyette {
122 1.2.2.2 pgoyette isc_result_t result;
123 1.2.2.2 pgoyette void *handle = NULL;
124 1.2.2.2 pgoyette dyndb_implementation_t *imp = NULL;
125 1.2.2.2 pgoyette dns_dyndb_register_t *register_func = NULL;
126 1.2.2.2 pgoyette dns_dyndb_destroy_t *destroy_func = NULL;
127 1.2.2.2 pgoyette dns_dyndb_version_t *version_func = NULL;
128 1.2.2.2 pgoyette int version, flags;
129 1.2.2.2 pgoyette
130 1.2.2.2 pgoyette REQUIRE(impp != NULL && *impp == NULL);
131 1.2.2.2 pgoyette
132 1.2.2.2 pgoyette isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
133 1.2.2.2 pgoyette DNS_LOGMODULE_DYNDB, ISC_LOG_INFO,
134 1.2.2.2 pgoyette "loading DynDB instance '%s' driver '%s'",
135 1.2.2.2 pgoyette instname, filename);
136 1.2.2.2 pgoyette
137 1.2.2.2 pgoyette flags = RTLD_NOW|RTLD_LOCAL;
138 1.2.2.2 pgoyette #ifdef RTLD_DEEPBIND
139 1.2.2.2 pgoyette flags |= RTLD_DEEPBIND;
140 1.2.2.2 pgoyette #endif
141 1.2.2.2 pgoyette
142 1.2.2.2 pgoyette handle = dlopen(filename, flags);
143 1.2.2.2 pgoyette if (handle == NULL)
144 1.2.2.2 pgoyette CHECK(ISC_R_FAILURE);
145 1.2.2.2 pgoyette
146 1.2.2.2 pgoyette /* Clear dlerror */
147 1.2.2.2 pgoyette dlerror();
148 1.2.2.2 pgoyette
149 1.2.2.2 pgoyette CHECK(load_symbol(handle, filename, "dyndb_version",
150 1.2.2.2 pgoyette (void **)&version_func));
151 1.2.2.2 pgoyette
152 1.2.2.2 pgoyette version = version_func(NULL);
153 1.2.2.2 pgoyette if (version < (DNS_DYNDB_VERSION - DNS_DYNDB_AGE) ||
154 1.2.2.2 pgoyette version > DNS_DYNDB_VERSION)
155 1.2.2.2 pgoyette {
156 1.2.2.2 pgoyette isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
157 1.2.2.2 pgoyette DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR,
158 1.2.2.2 pgoyette "driver API version mismatch: %d/%d",
159 1.2.2.2 pgoyette version, DNS_DYNDB_VERSION);
160 1.2.2.2 pgoyette CHECK(ISC_R_FAILURE);
161 1.2.2.2 pgoyette }
162 1.2.2.2 pgoyette
163 1.2.2.2 pgoyette CHECK(load_symbol(handle, filename, "dyndb_init",
164 1.2.2.2 pgoyette (void **)®ister_func));
165 1.2.2.2 pgoyette CHECK(load_symbol(handle, filename, "dyndb_destroy",
166 1.2.2.2 pgoyette (void **)&destroy_func));
167 1.2.2.2 pgoyette
168 1.2.2.2 pgoyette imp = isc_mem_get(mctx, sizeof(dyndb_implementation_t));
169 1.2.2.2 pgoyette if (imp == NULL)
170 1.2.2.2 pgoyette CHECK(ISC_R_NOMEMORY);
171 1.2.2.2 pgoyette
172 1.2.2.2 pgoyette imp->mctx = NULL;
173 1.2.2.2 pgoyette isc_mem_attach(mctx, &imp->mctx);
174 1.2.2.2 pgoyette imp->handle = handle;
175 1.2.2.2 pgoyette imp->register_func = register_func;
176 1.2.2.2 pgoyette imp->destroy_func = destroy_func;
177 1.2.2.2 pgoyette imp->name = isc_mem_strdup(mctx, instname);
178 1.2.2.2 pgoyette if (imp->name == NULL)
179 1.2.2.2 pgoyette CHECK(ISC_R_NOMEMORY);
180 1.2.2.2 pgoyette
181 1.2.2.2 pgoyette imp->inst = NULL;
182 1.2.2.2 pgoyette INIT_LINK(imp, link);
183 1.2.2.2 pgoyette
184 1.2.2.2 pgoyette *impp = imp;
185 1.2.2.2 pgoyette imp = NULL;
186 1.2.2.2 pgoyette
187 1.2.2.2 pgoyette cleanup:
188 1.2.2.2 pgoyette if (result != ISC_R_SUCCESS)
189 1.2.2.2 pgoyette isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
190 1.2.2.2 pgoyette DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR,
191 1.2.2.2 pgoyette "failed to dynamically load instance '%s' "
192 1.2.2.2 pgoyette "driver '%s': %s (%s)", instname, filename,
193 1.2.2.2 pgoyette dlerror(), isc_result_totext(result));
194 1.2.2.2 pgoyette if (imp != NULL)
195 1.2.2.2 pgoyette isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t));
196 1.2.2.2 pgoyette if (result != ISC_R_SUCCESS && handle != NULL)
197 1.2.2.2 pgoyette dlclose(handle);
198 1.2.2.2 pgoyette
199 1.2.2.2 pgoyette return (result);
200 1.2.2.2 pgoyette }
201 1.2.2.2 pgoyette
202 1.2.2.2 pgoyette static void
203 1.2.2.2 pgoyette unload_library(dyndb_implementation_t **impp) {
204 1.2.2.2 pgoyette dyndb_implementation_t *imp;
205 1.2.2.2 pgoyette
206 1.2.2.2 pgoyette REQUIRE(impp != NULL && *impp != NULL);
207 1.2.2.2 pgoyette
208 1.2.2.2 pgoyette imp = *impp;
209 1.2.2.2 pgoyette
210 1.2.2.2 pgoyette isc_mem_free(imp->mctx, imp->name);
211 1.2.2.2 pgoyette isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t));
212 1.2.2.2 pgoyette
213 1.2.2.2 pgoyette *impp = NULL;
214 1.2.2.2 pgoyette }
215 1.2.2.2 pgoyette #elif _WIN32
216 1.2.2.2 pgoyette static isc_result_t
217 1.2.2.2 pgoyette load_symbol(HMODULE handle, const char *filename,
218 1.2.2.2 pgoyette const char *symbol_name, void **symbolp)
219 1.2.2.2 pgoyette {
220 1.2.2.2 pgoyette void *symbol;
221 1.2.2.2 pgoyette
222 1.2.2.2 pgoyette REQUIRE(handle != NULL);
223 1.2.2.2 pgoyette REQUIRE(symbolp != NULL && *symbolp == NULL);
224 1.2.2.2 pgoyette
225 1.2.2.2 pgoyette symbol = GetProcAddress(handle, symbol_name);
226 1.2.2.2 pgoyette if (symbol == NULL) {
227 1.2.2.2 pgoyette int errstatus = GetLastError();
228 1.2.2.2 pgoyette isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
229 1.2.2.2 pgoyette DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR,
230 1.2.2.2 pgoyette "failed to lookup symbol %s in "
231 1.2.2.2 pgoyette "dyndb module '%s': %d",
232 1.2.2.2 pgoyette symbol_name, filename, errstatus);
233 1.2.2.2 pgoyette return (ISC_R_FAILURE);
234 1.2.2.2 pgoyette }
235 1.2.2.2 pgoyette
236 1.2.2.2 pgoyette *symbolp = symbol;
237 1.2.2.2 pgoyette
238 1.2.2.2 pgoyette return (ISC_R_SUCCESS);
239 1.2.2.2 pgoyette }
240 1.2.2.2 pgoyette
241 1.2.2.2 pgoyette static isc_result_t
242 1.2.2.2 pgoyette load_library(isc_mem_t *mctx, const char *filename, const char *instname,
243 1.2.2.2 pgoyette dyndb_implementation_t **impp)
244 1.2.2.2 pgoyette {
245 1.2.2.2 pgoyette isc_result_t result;
246 1.2.2.2 pgoyette HMODULE handle;
247 1.2.2.2 pgoyette dyndb_implementation_t *imp = NULL;
248 1.2.2.2 pgoyette dns_dyndb_register_t *register_func = NULL;
249 1.2.2.2 pgoyette dns_dyndb_destroy_t *destroy_func = NULL;
250 1.2.2.2 pgoyette dns_dyndb_version_t *version_func = NULL;
251 1.2.2.2 pgoyette int version;
252 1.2.2.2 pgoyette
253 1.2.2.2 pgoyette REQUIRE(impp != NULL && *impp == NULL);
254 1.2.2.2 pgoyette
255 1.2.2.2 pgoyette isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
256 1.2.2.2 pgoyette DNS_LOGMODULE_DYNDB, ISC_LOG_INFO,
257 1.2.2.2 pgoyette "loading DynDB instance '%s' driver '%s'",
258 1.2.2.2 pgoyette instname, filename);
259 1.2.2.2 pgoyette
260 1.2.2.2 pgoyette handle = LoadLibraryA(filename);
261 1.2.2.2 pgoyette if (handle == NULL)
262 1.2.2.2 pgoyette CHECK(ISC_R_FAILURE);
263 1.2.2.2 pgoyette
264 1.2.2.2 pgoyette CHECK(load_symbol(handle, filename, "dyndb_version",
265 1.2.2.2 pgoyette (void **)&version_func));
266 1.2.2.2 pgoyette
267 1.2.2.2 pgoyette version = version_func(NULL);
268 1.2.2.2 pgoyette if (version < (DNS_DYNDB_VERSION - DNS_DYNDB_AGE) ||
269 1.2.2.2 pgoyette version > DNS_DYNDB_VERSION)
270 1.2.2.2 pgoyette {
271 1.2.2.2 pgoyette isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
272 1.2.2.2 pgoyette DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR,
273 1.2.2.2 pgoyette "driver API version mismatch: %d/%d",
274 1.2.2.2 pgoyette version, DNS_DYNDB_VERSION);
275 1.2.2.2 pgoyette CHECK(ISC_R_FAILURE);
276 1.2.2.2 pgoyette }
277 1.2.2.2 pgoyette
278 1.2.2.2 pgoyette CHECK(load_symbol(handle, filename, "dyndb_init",
279 1.2.2.2 pgoyette (void **)®ister_func));
280 1.2.2.2 pgoyette CHECK(load_symbol(handle, filename, "dyndb_destroy",
281 1.2.2.2 pgoyette (void **)&destroy_func));
282 1.2.2.2 pgoyette
283 1.2.2.2 pgoyette imp = isc_mem_get(mctx, sizeof(dyndb_implementation_t));
284 1.2.2.2 pgoyette if (imp == NULL)
285 1.2.2.2 pgoyette CHECK(ISC_R_NOMEMORY);
286 1.2.2.2 pgoyette
287 1.2.2.2 pgoyette imp->mctx = NULL;
288 1.2.2.2 pgoyette isc_mem_attach(mctx, &imp->mctx);
289 1.2.2.2 pgoyette imp->handle = handle;
290 1.2.2.2 pgoyette imp->register_func = register_func;
291 1.2.2.2 pgoyette imp->destroy_func = destroy_func;
292 1.2.2.2 pgoyette imp->name = isc_mem_strdup(mctx, instname);
293 1.2.2.2 pgoyette if (imp->name == NULL)
294 1.2.2.2 pgoyette CHECK(ISC_R_NOMEMORY);
295 1.2.2.2 pgoyette
296 1.2.2.2 pgoyette imp->inst = NULL;
297 1.2.2.2 pgoyette INIT_LINK(imp, link);
298 1.2.2.2 pgoyette
299 1.2.2.2 pgoyette *impp = imp;
300 1.2.2.2 pgoyette imp = NULL;
301 1.2.2.2 pgoyette
302 1.2.2.2 pgoyette cleanup:
303 1.2.2.2 pgoyette if (result != ISC_R_SUCCESS)
304 1.2.2.2 pgoyette isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
305 1.2.2.2 pgoyette DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR,
306 1.2.2.2 pgoyette "failed to dynamically load instance '%s' "
307 1.2.2.2 pgoyette "driver '%s': %d (%s)", instname, filename,
308 1.2.2.2 pgoyette GetLastError(), isc_result_totext(result));
309 1.2.2.2 pgoyette if (imp != NULL)
310 1.2.2.2 pgoyette isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t));
311 1.2.2.2 pgoyette if (result != ISC_R_SUCCESS && handle != NULL)
312 1.2.2.2 pgoyette FreeLibrary(handle);
313 1.2.2.2 pgoyette
314 1.2.2.2 pgoyette return (result);
315 1.2.2.2 pgoyette }
316 1.2.2.2 pgoyette
317 1.2.2.2 pgoyette static void
318 1.2.2.2 pgoyette unload_library(dyndb_implementation_t **impp) {
319 1.2.2.2 pgoyette dyndb_implementation_t *imp;
320 1.2.2.2 pgoyette
321 1.2.2.2 pgoyette REQUIRE(impp != NULL && *impp != NULL);
322 1.2.2.2 pgoyette
323 1.2.2.2 pgoyette imp = *impp;
324 1.2.2.2 pgoyette
325 1.2.2.2 pgoyette isc_mem_free(imp->mctx, imp->name);
326 1.2.2.2 pgoyette isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t));
327 1.2.2.2 pgoyette
328 1.2.2.2 pgoyette *impp = NULL;
329 1.2.2.2 pgoyette }
330 1.2.2.2 pgoyette #else /* HAVE_DLFCN_H || _WIN32 */
331 1.2.2.2 pgoyette static isc_result_t
332 1.2.2.2 pgoyette load_library(isc_mem_t *mctx, const char *filename, const char *instname,
333 1.2.2.2 pgoyette dyndb_implementation_t **impp)
334 1.2.2.2 pgoyette {
335 1.2.2.2 pgoyette UNUSED(mctx);
336 1.2.2.2 pgoyette UNUSED(filename);
337 1.2.2.2 pgoyette UNUSED(instname);
338 1.2.2.2 pgoyette UNUSED(impp);
339 1.2.2.2 pgoyette
340 1.2.2.2 pgoyette isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DYNDB,
341 1.2.2.2 pgoyette ISC_LOG_ERROR,
342 1.2.2.2 pgoyette "dynamic database support is not implemented");
343 1.2.2.2 pgoyette
344 1.2.2.2 pgoyette return (ISC_R_NOTIMPLEMENTED);
345 1.2.2.2 pgoyette }
346 1.2.2.2 pgoyette
347 1.2.2.2 pgoyette static void
348 1.2.2.2 pgoyette unload_library(dyndb_implementation_t **impp)
349 1.2.2.2 pgoyette {
350 1.2.2.2 pgoyette UNUSED(impp);
351 1.2.2.2 pgoyette }
352 1.2.2.2 pgoyette #endif /* HAVE_DLFCN_H */
353 1.2.2.2 pgoyette
354 1.2.2.2 pgoyette isc_result_t
355 1.2.2.2 pgoyette dns_dyndb_load(const char *libname, const char *name, const char *parameters,
356 1.2.2.2 pgoyette const char *file, unsigned long line, isc_mem_t *mctx,
357 1.2.2.2 pgoyette const dns_dyndbctx_t *dctx)
358 1.2.2.2 pgoyette {
359 1.2.2.2 pgoyette isc_result_t result;
360 1.2.2.2 pgoyette dyndb_implementation_t *implementation = NULL;
361 1.2.2.2 pgoyette
362 1.2.2.2 pgoyette REQUIRE(DNS_DYNDBCTX_VALID(dctx));
363 1.2.2.2 pgoyette REQUIRE(name != NULL);
364 1.2.2.2 pgoyette
365 1.2.2.2 pgoyette RUNTIME_CHECK(isc_once_do(&once, dyndb_initialize) == ISC_R_SUCCESS);
366 1.2.2.2 pgoyette
367 1.2.2.2 pgoyette LOCK(&dyndb_lock);
368 1.2.2.2 pgoyette
369 1.2.2.2 pgoyette /* duplicate instance names are not allowed */
370 1.2.2.2 pgoyette if (impfind(name) != NULL)
371 1.2.2.2 pgoyette CHECK(ISC_R_EXISTS);
372 1.2.2.2 pgoyette
373 1.2.2.2 pgoyette CHECK(load_library(mctx, libname, name, &implementation));
374 1.2.2.2 pgoyette CHECK(implementation->register_func(mctx, name, parameters, file, line,
375 1.2.2.2 pgoyette dctx, &implementation->inst));
376 1.2.2.2 pgoyette
377 1.2.2.2 pgoyette APPEND(dyndb_implementations, implementation, link);
378 1.2.2.2 pgoyette result = ISC_R_SUCCESS;
379 1.2.2.2 pgoyette
380 1.2.2.2 pgoyette cleanup:
381 1.2.2.2 pgoyette if (result != ISC_R_SUCCESS)
382 1.2.2.2 pgoyette if (implementation != NULL)
383 1.2.2.2 pgoyette unload_library(&implementation);
384 1.2.2.2 pgoyette
385 1.2.2.2 pgoyette UNLOCK(&dyndb_lock);
386 1.2.2.2 pgoyette return (result);
387 1.2.2.2 pgoyette }
388 1.2.2.2 pgoyette
389 1.2.2.2 pgoyette void
390 1.2.2.2 pgoyette dns_dyndb_cleanup(isc_boolean_t exiting) {
391 1.2.2.2 pgoyette dyndb_implementation_t *elem;
392 1.2.2.2 pgoyette dyndb_implementation_t *prev;
393 1.2.2.2 pgoyette
394 1.2.2.2 pgoyette RUNTIME_CHECK(isc_once_do(&once, dyndb_initialize) == ISC_R_SUCCESS);
395 1.2.2.2 pgoyette
396 1.2.2.2 pgoyette LOCK(&dyndb_lock);
397 1.2.2.2 pgoyette elem = TAIL(dyndb_implementations);
398 1.2.2.2 pgoyette while (elem != NULL) {
399 1.2.2.2 pgoyette prev = PREV(elem, link);
400 1.2.2.2 pgoyette UNLINK(dyndb_implementations, elem, link);
401 1.2.2.2 pgoyette isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
402 1.2.2.2 pgoyette DNS_LOGMODULE_DYNDB, ISC_LOG_INFO,
403 1.2.2.2 pgoyette "unloading DynDB instance '%s'", elem->name);
404 1.2.2.2 pgoyette elem->destroy_func(&elem->inst);
405 1.2.2.2 pgoyette ENSURE(elem->inst == NULL);
406 1.2.2.2 pgoyette unload_library(&elem);
407 1.2.2.2 pgoyette elem = prev;
408 1.2.2.2 pgoyette }
409 1.2.2.2 pgoyette UNLOCK(&dyndb_lock);
410 1.2.2.2 pgoyette
411 1.2.2.2 pgoyette if (exiting == ISC_TRUE)
412 1.2.2.2 pgoyette isc_mutex_destroy(&dyndb_lock);
413 1.2.2.2 pgoyette }
414 1.2.2.2 pgoyette
415 1.2.2.2 pgoyette isc_result_t
416 1.2.2.2 pgoyette dns_dyndb_createctx(isc_mem_t *mctx, const void *hashinit, isc_log_t *lctx,
417 1.2.2.2 pgoyette dns_view_t *view, dns_zonemgr_t *zmgr, isc_task_t *task,
418 1.2.2.2 pgoyette isc_timermgr_t *tmgr, dns_dyndbctx_t **dctxp)
419 1.2.2.2 pgoyette {
420 1.2.2.2 pgoyette dns_dyndbctx_t *dctx;
421 1.2.2.2 pgoyette
422 1.2.2.2 pgoyette REQUIRE(dctxp != NULL && *dctxp == NULL);
423 1.2.2.2 pgoyette
424 1.2.2.2 pgoyette dctx = isc_mem_get(mctx, sizeof(*dctx));
425 1.2.2.2 pgoyette if (dctx == NULL)
426 1.2.2.2 pgoyette return (ISC_R_NOMEMORY);
427 1.2.2.2 pgoyette
428 1.2.2.2 pgoyette memset(dctx, 0, sizeof(*dctx));
429 1.2.2.2 pgoyette if (view != NULL)
430 1.2.2.2 pgoyette dns_view_attach(view, &dctx->view);
431 1.2.2.2 pgoyette if (zmgr != NULL)
432 1.2.2.2 pgoyette dns_zonemgr_attach(zmgr, &dctx->zmgr);
433 1.2.2.2 pgoyette if (task != NULL)
434 1.2.2.2 pgoyette isc_task_attach(task, &dctx->task);
435 1.2.2.2 pgoyette dctx->timermgr = tmgr;
436 1.2.2.2 pgoyette dctx->hashinit = hashinit;
437 1.2.2.2 pgoyette dctx->lctx = lctx;
438 1.2.2.2 pgoyette dctx->refvar = &isc_bind9;
439 1.2.2.2 pgoyette
440 1.2.2.2 pgoyette isc_mem_attach(mctx, &dctx->mctx);
441 1.2.2.2 pgoyette dctx->magic = DNS_DYNDBCTX_MAGIC;
442 1.2.2.2 pgoyette
443 1.2.2.2 pgoyette *dctxp = dctx;
444 1.2.2.2 pgoyette
445 1.2.2.2 pgoyette return (ISC_R_SUCCESS);
446 1.2.2.2 pgoyette }
447 1.2.2.2 pgoyette
448 1.2.2.2 pgoyette void
449 1.2.2.2 pgoyette dns_dyndb_destroyctx(dns_dyndbctx_t **dctxp) {
450 1.2.2.2 pgoyette dns_dyndbctx_t *dctx;
451 1.2.2.2 pgoyette
452 1.2.2.2 pgoyette REQUIRE(dctxp != NULL && DNS_DYNDBCTX_VALID(*dctxp));
453 1.2.2.2 pgoyette
454 1.2.2.2 pgoyette dctx = *dctxp;
455 1.2.2.2 pgoyette *dctxp = NULL;
456 1.2.2.2 pgoyette
457 1.2.2.2 pgoyette dctx->magic = 0;
458 1.2.2.2 pgoyette
459 1.2.2.2 pgoyette if (dctx->view != NULL)
460 1.2.2.2 pgoyette dns_view_detach(&dctx->view);
461 1.2.2.2 pgoyette if (dctx->zmgr != NULL)
462 1.2.2.2 pgoyette dns_zonemgr_detach(&dctx->zmgr);
463 1.2.2.2 pgoyette if (dctx->task != NULL)
464 1.2.2.2 pgoyette isc_task_detach(&dctx->task);
465 1.2.2.2 pgoyette dctx->timermgr = NULL;
466 1.2.2.2 pgoyette dctx->lctx = NULL;
467 1.2.2.2 pgoyette
468 1.2.2.2 pgoyette isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(*dctx));
469 1.2.2.2 pgoyette }
470