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