1 /* $NetBSD: dlz_dlopen_driver.c,v 1.6 2014/12/10 04:37:52 christos Exp $ */
2
3 /*
4 * Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /* Id */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <dlfcn.h>
27
28 #include <dns/log.h>
29 #include <dns/result.h>
30 #include <dns/dlz_dlopen.h>
31
32 #include <isc/mem.h>
33 #include <isc/print.h>
34 #include <isc/result.h>
35 #include <isc/util.h>
36
37 #include <named/globals.h>
38
39 #include <dlz/dlz_dlopen_driver.h>
40
41 #ifdef ISC_DLZ_DLOPEN
42 static dns_sdlzimplementation_t *dlz_dlopen = NULL;
43
44
45 typedef struct dlopen_data {
46 isc_mem_t *mctx;
47 char *dl_path;
48 char *dlzname;
49 void *dl_handle;
50 void *dbdata;
51 unsigned int flags;
52 isc_mutex_t lock;
53 int version;
54 isc_boolean_t in_configure;
55
56 dlz_dlopen_version_t *dlz_version;
57 dlz_dlopen_create_t *dlz_create;
58 dlz_dlopen_findzonedb_t *dlz_findzonedb;
59 dlz_dlopen_lookup_t *dlz_lookup;
60 dlz_dlopen_authority_t *dlz_authority;
61 dlz_dlopen_allnodes_t *dlz_allnodes;
62 dlz_dlopen_allowzonexfr_t *dlz_allowzonexfr;
63 dlz_dlopen_newversion_t *dlz_newversion;
64 dlz_dlopen_closeversion_t *dlz_closeversion;
65 dlz_dlopen_configure_t *dlz_configure;
66 dlz_dlopen_ssumatch_t *dlz_ssumatch;
67 dlz_dlopen_addrdataset_t *dlz_addrdataset;
68 dlz_dlopen_subrdataset_t *dlz_subrdataset;
69 dlz_dlopen_delrdataset_t *dlz_delrdataset;
70 dlz_dlopen_destroy_t *dlz_destroy;
71 } dlopen_data_t;
72
73 /* Modules can choose whether they are lock-safe or not. */
74 #define MAYBE_LOCK(cd) \
75 do { \
76 if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \
77 cd->in_configure == ISC_FALSE) \
78 LOCK(&cd->lock); \
79 } while (/*CONSTCOND*/0)
80
81 #define MAYBE_UNLOCK(cd) \
82 do { \
83 if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \
84 cd->in_configure == ISC_FALSE) \
85 UNLOCK(&cd->lock); \
86 } while (0)
87
88 /*
89 * Log a message at the given level.
90 */
dlopen_log(int level,const char * fmt,...)91 static void dlopen_log(int level, const char *fmt, ...)
92 {
93 va_list ap;
94 va_start(ap, fmt);
95 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
96 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level),
97 fmt, ap);
98 va_end(ap);
99 }
100
101 /*
102 * SDLZ methods
103 */
104
105 static isc_result_t
dlopen_dlz_allnodes(const char * zone,void * driverarg,void * dbdata,dns_sdlzallnodes_t * allnodes)106 dlopen_dlz_allnodes(const char *zone, void *driverarg, void *dbdata,
107 dns_sdlzallnodes_t *allnodes)
108 {
109 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
110 isc_result_t result;
111
112
113 UNUSED(driverarg);
114
115 if (cd->dlz_allnodes == NULL) {
116 return (ISC_R_NOPERM);
117 }
118
119 MAYBE_LOCK(cd);
120 result = cd->dlz_allnodes(zone, cd->dbdata, allnodes);
121 MAYBE_UNLOCK(cd);
122 return (result);
123 }
124
125
126 static isc_result_t
dlopen_dlz_allowzonexfr(void * driverarg,void * dbdata,const char * name,const char * client)127 dlopen_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name,
128 const char *client)
129 {
130 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
131 isc_result_t result;
132
133 UNUSED(driverarg);
134
135
136 if (cd->dlz_allowzonexfr == NULL) {
137 return (ISC_R_NOPERM);
138 }
139
140 MAYBE_LOCK(cd);
141 result = cd->dlz_allowzonexfr(cd->dbdata, name, client);
142 MAYBE_UNLOCK(cd);
143 return (result);
144 }
145
146 static isc_result_t
dlopen_dlz_authority(const char * zone,void * driverarg,void * dbdata,dns_sdlzlookup_t * lookup)147 dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata,
148 dns_sdlzlookup_t *lookup)
149 {
150 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
151 isc_result_t result;
152
153 UNUSED(driverarg);
154
155 if (cd->dlz_authority == NULL) {
156 return (ISC_R_NOTIMPLEMENTED);
157 }
158
159 MAYBE_LOCK(cd);
160 result = cd->dlz_authority(zone, cd->dbdata, lookup);
161 MAYBE_UNLOCK(cd);
162 return (result);
163 }
164
165 static isc_result_t
dlopen_dlz_findzonedb(void * driverarg,void * dbdata,const char * name,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo)166 dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name,
167 dns_clientinfomethods_t *methods,
168 dns_clientinfo_t *clientinfo)
169 {
170 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
171 isc_result_t result;
172
173 UNUSED(driverarg);
174
175 MAYBE_LOCK(cd);
176 result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo);
177 MAYBE_UNLOCK(cd);
178 return (result);
179 }
180
181
182 static isc_result_t
dlopen_dlz_lookup(const char * zone,const char * name,void * driverarg,void * dbdata,dns_sdlzlookup_t * lookup,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo)183 dlopen_dlz_lookup(const char *zone, const char *name, void *driverarg,
184 void *dbdata, dns_sdlzlookup_t *lookup,
185 dns_clientinfomethods_t *methods,
186 dns_clientinfo_t *clientinfo)
187 {
188 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
189 isc_result_t result;
190
191 UNUSED(driverarg);
192
193 MAYBE_LOCK(cd);
194 result = cd->dlz_lookup(zone, name, cd->dbdata, lookup,
195 methods, clientinfo);
196 MAYBE_UNLOCK(cd);
197 return (result);
198 }
199
200 /*
201 * Load a symbol from the library
202 */
203 static void *
dl_load_symbol(dlopen_data_t * cd,const char * symbol,isc_boolean_t mandatory)204 dl_load_symbol(dlopen_data_t *cd, const char *symbol, isc_boolean_t mandatory) {
205 void *ptr = dlsym(cd->dl_handle, symbol);
206 if (ptr == NULL && mandatory) {
207 dlopen_log(ISC_LOG_ERROR,
208 "dlz_dlopen: library '%s' is missing "
209 "required symbol '%s'", cd->dl_path, symbol);
210 }
211 return (ptr);
212 }
213
214 /*
215 * Called at startup for each dlopen zone in named.conf
216 */
217 static isc_result_t
dlopen_dlz_create(const char * dlzname,unsigned int argc,char * argv[],void * driverarg,void ** dbdata)218 dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
219 void *driverarg, void **dbdata)
220 {
221 dlopen_data_t *cd;
222 isc_mem_t *mctx = NULL;
223 isc_result_t result = ISC_R_FAILURE;
224 int dlopen_flags = 0;
225
226 UNUSED(driverarg);
227
228 if (argc < 2) {
229 dlopen_log(ISC_LOG_ERROR,
230 "dlz_dlopen driver for '%s' needs a path to "
231 "the shared library", dlzname);
232 return (ISC_R_FAILURE);
233 }
234
235 result = isc_mem_create(0, 0, &mctx);
236 if (result != ISC_R_SUCCESS)
237 return (result);
238
239 cd = isc_mem_get(mctx, sizeof(*cd));
240 if (cd == NULL) {
241 isc_mem_destroy(&mctx);
242 return (ISC_R_NOMEMORY);
243 }
244 memset(cd, 0, sizeof(*cd));
245
246 cd->mctx = mctx;
247
248 cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]);
249 if (cd->dl_path == NULL) {
250 result = ISC_R_NOMEMORY;
251 goto failed;
252 }
253
254 cd->dlzname = isc_mem_strdup(cd->mctx, dlzname);
255 if (cd->dlzname == NULL) {
256 result = ISC_R_NOMEMORY;
257 goto failed;
258 }
259
260 /* Initialize the lock */
261 result = isc_mutex_init(&cd->lock);
262 if (result != ISC_R_SUCCESS)
263 goto failed;
264
265 /* Open the library */
266 dlopen_flags = RTLD_NOW|RTLD_GLOBAL;
267
268 #ifdef RTLD_DEEPBIND
269 /*
270 * If RTLD_DEEPBIND is available then use it. This can avoid
271 * issues with a module using a different version of a system
272 * library than one that bind9 uses. For example, bind9 may link
273 * to MIT kerberos, but the module may use Heimdal. If we don't
274 * use RTLD_DEEPBIND then we could end up with Heimdal functions
275 * calling MIT functions, which leads to bizarre results (usually
276 * a segfault).
277 */
278 dlopen_flags |= RTLD_DEEPBIND;
279 #endif
280
281 cd->dl_handle = dlopen(cd->dl_path, dlopen_flags);
282 if (cd->dl_handle == NULL) {
283 dlopen_log(ISC_LOG_ERROR,
284 "dlz_dlopen failed to open library '%s' - %s",
285 cd->dl_path, dlerror());
286 result = ISC_R_FAILURE;
287 goto failed;
288 }
289
290 /* Find the symbols */
291 cd->dlz_version = (dlz_dlopen_version_t *)
292 dl_load_symbol(cd, "dlz_version", ISC_TRUE);
293 cd->dlz_create = (dlz_dlopen_create_t *)
294 dl_load_symbol(cd, "dlz_create", ISC_TRUE);
295 cd->dlz_lookup = (dlz_dlopen_lookup_t *)
296 dl_load_symbol(cd, "dlz_lookup", ISC_TRUE);
297 cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *)
298 dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE);
299
300 if (cd->dlz_create == NULL ||
301 cd->dlz_version == NULL ||
302 cd->dlz_lookup == NULL ||
303 cd->dlz_findzonedb == NULL)
304 {
305 /* We're missing a required symbol */
306 result = ISC_R_FAILURE;
307 goto failed;
308 }
309
310 cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *)
311 dl_load_symbol(cd, "dlz_allowzonexfr", ISC_FALSE);
312 cd->dlz_allnodes = (dlz_dlopen_allnodes_t *)
313 dl_load_symbol(cd, "dlz_allnodes",
314 ISC_TF(cd->dlz_allowzonexfr != NULL));
315 cd->dlz_authority = (dlz_dlopen_authority_t *)
316 dl_load_symbol(cd, "dlz_authority", ISC_FALSE);
317 cd->dlz_newversion = (dlz_dlopen_newversion_t *)
318 dl_load_symbol(cd, "dlz_newversion", ISC_FALSE);
319 cd->dlz_closeversion = (dlz_dlopen_closeversion_t *)
320 dl_load_symbol(cd, "dlz_closeversion",
321 ISC_TF(cd->dlz_newversion != NULL));
322 cd->dlz_configure = (dlz_dlopen_configure_t *)
323 dl_load_symbol(cd, "dlz_configure", ISC_FALSE);
324 cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *)
325 dl_load_symbol(cd, "dlz_ssumatch", ISC_FALSE);
326 cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *)
327 dl_load_symbol(cd, "dlz_addrdataset", ISC_FALSE);
328 cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *)
329 dl_load_symbol(cd, "dlz_subrdataset", ISC_FALSE);
330 cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *)
331 dl_load_symbol(cd, "dlz_delrdataset", ISC_FALSE);
332 cd->dlz_destroy = (dlz_dlopen_destroy_t *)
333 dl_load_symbol(cd, "dlz_destroy", ISC_FALSE);
334
335 /* Check the version of the API is the same */
336 cd->version = cd->dlz_version(&cd->flags);
337 if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) ||
338 cd->version > DLZ_DLOPEN_VERSION)
339 {
340 dlopen_log(ISC_LOG_ERROR,
341 "dlz_dlopen: %s: incorrect driver API version %d, "
342 "requires %d",
343 cd->dl_path, cd->version, DLZ_DLOPEN_VERSION);
344 result = ISC_R_FAILURE;
345 goto failed;
346 }
347
348 /*
349 * Call the library's create function. Note that this is an
350 * extended version of dlz create, with the addition of
351 * named function pointers for helper functions that the
352 * driver will need. This avoids the need for the backend to
353 * link the BIND9 libraries
354 */
355 MAYBE_LOCK(cd);
356 result = cd->dlz_create(dlzname, argc-1, argv+1,
357 &cd->dbdata,
358 "log", dlopen_log,
359 "putrr", dns_sdlz_putrr,
360 "putnamedrr", dns_sdlz_putnamedrr,
361 "writeable_zone", dns_dlz_writeablezone,
362 NULL);
363 MAYBE_UNLOCK(cd);
364 if (result != ISC_R_SUCCESS)
365 goto failed;
366
367 *dbdata = cd;
368
369 return (ISC_R_SUCCESS);
370
371 failed:
372 dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname);
373 if (cd->dl_path != NULL)
374 isc_mem_free(mctx, cd->dl_path);
375 if (cd->dlzname != NULL)
376 isc_mem_free(mctx, cd->dlzname);
377 if (dlopen_flags != 0)
378 (void) isc_mutex_destroy(&cd->lock);
379 #ifdef HAVE_DLCLOSE
380 if (cd->dl_handle)
381 dlclose(cd->dl_handle);
382 #endif
383 isc_mem_put(mctx, cd, sizeof(*cd));
384 isc_mem_destroy(&mctx);
385 return (result);
386 }
387
388 /*
389 * Called when bind is shutting down
390 */
391 static void
dlopen_dlz_destroy(void * driverarg,void * dbdata)392 dlopen_dlz_destroy(void *driverarg, void *dbdata) {
393 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
394 isc_mem_t *mctx;
395
396 UNUSED(driverarg);
397
398 if (cd->dlz_destroy) {
399 MAYBE_LOCK(cd);
400 cd->dlz_destroy(cd->dbdata);
401 MAYBE_UNLOCK(cd);
402 }
403
404 if (cd->dl_path)
405 isc_mem_free(cd->mctx, cd->dl_path);
406 if (cd->dlzname)
407 isc_mem_free(cd->mctx, cd->dlzname);
408
409 #ifdef HAVE_DLCLOSE
410 if (cd->dl_handle)
411 dlclose(cd->dl_handle);
412 #endif
413
414 (void) isc_mutex_destroy(&cd->lock);
415
416 mctx = cd->mctx;
417 isc_mem_put(mctx, cd, sizeof(*cd));
418 isc_mem_destroy(&mctx);
419 }
420
421 /*
422 * Called to start a transaction
423 */
424 static isc_result_t
dlopen_dlz_newversion(const char * zone,void * driverarg,void * dbdata,void ** versionp)425 dlopen_dlz_newversion(const char *zone, void *driverarg, void *dbdata,
426 void **versionp)
427 {
428 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
429 isc_result_t result;
430
431 UNUSED(driverarg);
432
433 if (cd->dlz_newversion == NULL)
434 return (ISC_R_NOTIMPLEMENTED);
435
436 MAYBE_LOCK(cd);
437 result = cd->dlz_newversion(zone, cd->dbdata, versionp);
438 MAYBE_UNLOCK(cd);
439 return (result);
440 }
441
442 /*
443 * Called to end a transaction
444 */
445 static void
dlopen_dlz_closeversion(const char * zone,isc_boolean_t commit,void * driverarg,void * dbdata,void ** versionp)446 dlopen_dlz_closeversion(const char *zone, isc_boolean_t commit,
447 void *driverarg, void *dbdata, void **versionp)
448 {
449 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
450
451 UNUSED(driverarg);
452
453 if (cd->dlz_newversion == NULL) {
454 *versionp = NULL;
455 return;
456 }
457
458 MAYBE_LOCK(cd);
459 cd->dlz_closeversion(zone, commit, cd->dbdata, versionp);
460 MAYBE_UNLOCK(cd);
461 }
462
463 /*
464 * Called on startup to configure any writeable zones
465 */
466 static isc_result_t
dlopen_dlz_configure(dns_view_t * view,dns_dlzdb_t * dlzdb,void * driverarg,void * dbdata)467 dlopen_dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb,
468 void *driverarg, void *dbdata)
469 {
470 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
471 isc_result_t result;
472
473 UNUSED(driverarg);
474
475 if (cd->dlz_configure == NULL)
476 return (ISC_R_SUCCESS);
477
478 MAYBE_LOCK(cd);
479 cd->in_configure = ISC_TRUE;
480 result = cd->dlz_configure(view, dlzdb, cd->dbdata);
481 cd->in_configure = ISC_FALSE;
482 MAYBE_UNLOCK(cd);
483
484 return (result);
485 }
486
487
488 /*
489 * Check for authority to change a name
490 */
491 static isc_boolean_t
dlopen_dlz_ssumatch(const char * signer,const char * name,const char * tcpaddr,const char * type,const char * key,isc_uint32_t keydatalen,unsigned char * keydata,void * driverarg,void * dbdata)492 dlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
493 const char *type, const char *key, isc_uint32_t keydatalen,
494 unsigned char *keydata, void *driverarg, void *dbdata)
495 {
496 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
497 isc_boolean_t ret;
498
499 UNUSED(driverarg);
500
501 if (cd->dlz_ssumatch == NULL)
502 return (ISC_FALSE);
503
504 MAYBE_LOCK(cd);
505 ret = cd->dlz_ssumatch(signer, name, tcpaddr, type, key, keydatalen,
506 keydata, cd->dbdata);
507 MAYBE_UNLOCK(cd);
508
509 return (ret);
510 }
511
512
513 /*
514 * Add an rdataset
515 */
516 static isc_result_t
dlopen_dlz_addrdataset(const char * name,const char * rdatastr,void * driverarg,void * dbdata,void * version)517 dlopen_dlz_addrdataset(const char *name, const char *rdatastr,
518 void *driverarg, void *dbdata, void *version)
519 {
520 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
521 isc_result_t result;
522
523 UNUSED(driverarg);
524
525 if (cd->dlz_addrdataset == NULL)
526 return (ISC_R_NOTIMPLEMENTED);
527
528 MAYBE_LOCK(cd);
529 result = cd->dlz_addrdataset(name, rdatastr, cd->dbdata, version);
530 MAYBE_UNLOCK(cd);
531
532 return (result);
533 }
534
535 /*
536 * Subtract an rdataset
537 */
538 static isc_result_t
dlopen_dlz_subrdataset(const char * name,const char * rdatastr,void * driverarg,void * dbdata,void * version)539 dlopen_dlz_subrdataset(const char *name, const char *rdatastr,
540 void *driverarg, void *dbdata, void *version)
541 {
542 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
543 isc_result_t result;
544
545 UNUSED(driverarg);
546
547 if (cd->dlz_subrdataset == NULL)
548 return (ISC_R_NOTIMPLEMENTED);
549
550 MAYBE_LOCK(cd);
551 result = cd->dlz_subrdataset(name, rdatastr, cd->dbdata, version);
552 MAYBE_UNLOCK(cd);
553
554 return (result);
555 }
556
557 /*
558 delete a rdataset
559 */
560 static isc_result_t
dlopen_dlz_delrdataset(const char * name,const char * type,void * driverarg,void * dbdata,void * version)561 dlopen_dlz_delrdataset(const char *name, const char *type,
562 void *driverarg, void *dbdata, void *version)
563 {
564 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
565 isc_result_t result;
566
567 UNUSED(driverarg);
568
569 if (cd->dlz_delrdataset == NULL)
570 return (ISC_R_NOTIMPLEMENTED);
571
572 MAYBE_LOCK(cd);
573 result = cd->dlz_delrdataset(name, type, cd->dbdata, version);
574 MAYBE_UNLOCK(cd);
575
576 return (result);
577 }
578
579
580 static dns_sdlzmethods_t dlz_dlopen_methods = {
581 dlopen_dlz_create,
582 dlopen_dlz_destroy,
583 dlopen_dlz_findzonedb,
584 dlopen_dlz_lookup,
585 dlopen_dlz_authority,
586 dlopen_dlz_allnodes,
587 dlopen_dlz_allowzonexfr,
588 dlopen_dlz_newversion,
589 dlopen_dlz_closeversion,
590 dlopen_dlz_configure,
591 dlopen_dlz_ssumatch,
592 dlopen_dlz_addrdataset,
593 dlopen_dlz_subrdataset,
594 dlopen_dlz_delrdataset
595 };
596 #endif
597
598 /*
599 * Register driver with BIND
600 */
601 isc_result_t
dlz_dlopen_init(isc_mem_t * mctx)602 dlz_dlopen_init(isc_mem_t *mctx) {
603 #ifndef ISC_DLZ_DLOPEN
604 UNUSED(mctx);
605 return (ISC_R_NOTIMPLEMENTED);
606 #else
607 isc_result_t result;
608
609 dlopen_log(2, "Registering DLZ_dlopen driver");
610
611 result = dns_sdlzregister("dlopen", &dlz_dlopen_methods, NULL,
612 DNS_SDLZFLAG_RELATIVEOWNER |
613 DNS_SDLZFLAG_RELATIVERDATA |
614 DNS_SDLZFLAG_THREADSAFE,
615 mctx, &dlz_dlopen);
616
617 if (result != ISC_R_SUCCESS) {
618 UNEXPECTED_ERROR(__FILE__, __LINE__,
619 "dns_sdlzregister() failed: %s",
620 isc_result_totext(result));
621 result = ISC_R_UNEXPECTED;
622 }
623
624 return (result);
625 #endif
626 }
627
628
629 /*
630 * Unregister the driver
631 */
632 void
dlz_dlopen_clear(void)633 dlz_dlopen_clear(void) {
634 #ifdef ISC_DLZ_DLOPEN
635 dlopen_log(2, "Unregistering DLZ_dlopen driver");
636 if (dlz_dlopen != NULL)
637 dns_sdlzunregister(&dlz_dlopen);
638 #endif
639 }
640