Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / bin / named / win32 / dlz_dlopen_driver.c
blobe1606a689e5ec14354fb5cdc08f0aa4af52d27fe
1 /* $NetBSD: dlz_dlopen_driver.c,v 1.4 2015/07/08 17:28:55 christos Exp $ */
3 /*
4 * Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
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.
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.
19 /* Id: dlz_dlopen_driver.c,v 1.5 2011/10/14 00:52:32 marka Exp */
21 #include <config.h>
23 #include <windows.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
29 #include <dns/log.h>
30 #include <dns/result.h>
31 #include <dns/dlz_dlopen.h>
33 #include <isc/mem.h>
34 #include <isc/print.h>
35 #include <isc/result.h>
36 #include <isc/util.h>
38 #include <named/globals.h>
40 #include <dlz/dlz_dlopen_driver.h>
42 #ifdef ISC_DLZ_DLOPEN
43 static dns_sdlzimplementation_t *dlz_dlopen = NULL;
46 typedef struct dlopen_data {
47 isc_mem_t *mctx;
48 char *dl_path;
49 char *dlzname;
50 HMODULE dl_handle;
51 void *dbdata;
52 unsigned int flags;
53 isc_mutex_t lock;
54 int version;
55 isc_boolean_t in_configure;
57 dlz_dlopen_version_t *dlz_version;
58 dlz_dlopen_create_t *dlz_create;
59 dlz_dlopen_findzonedb_t *dlz_findzonedb;
60 dlz_dlopen_lookup_t *dlz_lookup;
61 dlz_dlopen_authority_t *dlz_authority;
62 dlz_dlopen_allnodes_t *dlz_allnodes;
63 dlz_dlopen_allowzonexfr_t *dlz_allowzonexfr;
64 dlz_dlopen_newversion_t *dlz_newversion;
65 dlz_dlopen_closeversion_t *dlz_closeversion;
66 dlz_dlopen_configure_t *dlz_configure;
67 dlz_dlopen_ssumatch_t *dlz_ssumatch;
68 dlz_dlopen_addrdataset_t *dlz_addrdataset;
69 dlz_dlopen_subrdataset_t *dlz_subrdataset;
70 dlz_dlopen_delrdataset_t *dlz_delrdataset;
71 dlz_dlopen_destroy_t *dlz_destroy;
72 } dlopen_data_t;
74 /* Modules can choose whether they are lock-safe or not. */
75 #define MAYBE_LOCK(cd) \
76 do { \
77 if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \
78 cd->in_configure == ISC_FALSE) \
79 LOCK(&cd->lock); \
80 } while (/*CONSTCOND*/0)
82 #define MAYBE_UNLOCK(cd) \
83 do { \
84 if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \
85 cd->in_configure == ISC_FALSE) \
86 UNLOCK(&cd->lock); \
87 } while (/*CONSTCOND*/0)
90 * Log a message at the given level.
92 static void dlopen_log(int level, const char *fmt, ...)
94 va_list ap;
95 va_start(ap, fmt);
96 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
97 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level),
98 fmt, ap);
99 va_end(ap);
103 * SDLZ methods
106 static isc_result_t
107 dlopen_dlz_allnodes(const char *zone, void *driverarg, void *dbdata,
108 dns_sdlzallnodes_t *allnodes)
110 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
111 isc_result_t result;
114 UNUSED(driverarg);
116 if (cd->dlz_allnodes == NULL) {
117 return (ISC_R_NOPERM);
120 MAYBE_LOCK(cd);
121 result = cd->dlz_allnodes(zone, cd->dbdata, allnodes);
122 MAYBE_UNLOCK(cd);
123 return (result);
127 static isc_result_t
128 dlopen_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name,
129 const char *client)
131 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
132 isc_result_t result;
134 UNUSED(driverarg);
137 if (cd->dlz_allowzonexfr == NULL) {
138 return (ISC_R_NOPERM);
141 MAYBE_LOCK(cd);
142 result = cd->dlz_allowzonexfr(cd->dbdata, name, client);
143 MAYBE_UNLOCK(cd);
144 return (result);
147 static isc_result_t
148 dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata,
149 dns_sdlzlookup_t *lookup)
151 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
152 isc_result_t result;
154 UNUSED(driverarg);
156 if (cd->dlz_authority == NULL) {
157 return (ISC_R_NOTIMPLEMENTED);
160 MAYBE_LOCK(cd);
161 result = cd->dlz_authority(zone, cd->dbdata, lookup);
162 MAYBE_UNLOCK(cd);
163 return (result);
166 static isc_result_t
167 dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name,
168 dns_clientinfomethods_t *methods,
169 dns_clientinfo_t *clientinfo)
171 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
172 isc_result_t result;
174 UNUSED(driverarg);
176 MAYBE_LOCK(cd);
177 result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo);
178 MAYBE_UNLOCK(cd);
179 return (result);
183 static isc_result_t
184 dlopen_dlz_lookup(const char *zone, const char *name, void *driverarg,
185 void *dbdata, dns_sdlzlookup_t *lookup,
186 dns_clientinfomethods_t *methods,
187 dns_clientinfo_t *clientinfo)
189 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
190 isc_result_t result;
192 UNUSED(driverarg);
194 MAYBE_LOCK(cd);
195 result = cd->dlz_lookup(zone, name, cd->dbdata, lookup,
196 methods, clientinfo);
197 MAYBE_UNLOCK(cd);
198 return (result);
202 * Load a symbol from the library
204 static void *
205 dl_load_symbol(dlopen_data_t *cd, const char *symbol, isc_boolean_t mandatory) {
206 void *ptr = GetProcAddress(cd->dl_handle, symbol);
207 if (ptr == NULL && mandatory) {
208 dlopen_log(ISC_LOG_ERROR,
209 "dlz_dlopen: library '%s' is missing "
210 "required symbol '%s'", cd->dl_path, symbol);
212 return (ptr);
216 * Called at startup for each dlopen zone in named.conf
218 static isc_result_t
219 dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
220 void *driverarg, void **dbdata)
222 dlopen_data_t *cd;
223 isc_mem_t *mctx = NULL;
224 isc_result_t result = ISC_R_FAILURE;
225 isc_boolean_t triedload = ISC_FALSE;
227 UNUSED(driverarg);
229 if (argc < 2) {
230 dlopen_log(ISC_LOG_ERROR,
231 "dlz_dlopen driver for '%s' needs a path to "
232 "the shared library", dlzname);
233 return (ISC_R_FAILURE);
236 isc_mem_create(0, 0, &mctx);
238 cd = isc_mem_get(mctx, sizeof(*cd));
239 if (cd == NULL) {
240 isc_mem_destroy(&mctx);
241 return (ISC_R_NOMEMORY);
243 memset(cd, 0, sizeof(*cd));
245 cd->mctx = mctx;
247 cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]);
248 if (cd->dl_path == NULL) {
249 result = ISC_R_NOMEMORY;
250 goto failed;
253 cd->dlzname = isc_mem_strdup(cd->mctx, dlzname);
254 if (cd->dlzname == NULL) {
255 result = ISC_R_NOMEMORY;
256 goto failed;
259 triedload = ISC_TRUE;
261 /* Initialize the lock */
262 result = isc_mutex_init(&cd->lock);
263 if (result != ISC_R_SUCCESS)
264 goto failed;
266 /* Open the library */
267 cd->dl_handle = LoadLibraryA(cd->dl_path);
268 if (cd->dl_handle == NULL) {
269 unsigned int error = GetLastError();
271 dlopen_log(ISC_LOG_ERROR,
272 "dlz_dlopen failed to open library '%s' - %u",
273 cd->dl_path, error);
274 result = ISC_R_FAILURE;
275 goto cleanup_lock;
278 /* Find the symbols */
279 cd->dlz_version = (dlz_dlopen_version_t *)
280 dl_load_symbol(cd, "dlz_version", ISC_TRUE);
281 cd->dlz_create = (dlz_dlopen_create_t *)
282 dl_load_symbol(cd, "dlz_create", ISC_TRUE);
283 cd->dlz_lookup = (dlz_dlopen_lookup_t *)
284 dl_load_symbol(cd, "dlz_lookup", ISC_TRUE);
285 cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *)
286 dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE);
288 if (cd->dlz_create == NULL ||
289 cd->dlz_version == NULL ||
290 cd->dlz_lookup == NULL ||
291 cd->dlz_findzonedb == NULL)
293 /* We're missing a required symbol */
294 result = ISC_R_FAILURE;
295 goto cleanup_lock;
298 cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *)
299 dl_load_symbol(cd, "dlz_allowzonexfr", ISC_FALSE);
300 cd->dlz_allnodes = (dlz_dlopen_allnodes_t *)
301 dl_load_symbol(cd, "dlz_allnodes",
302 ISC_TF(cd->dlz_allowzonexfr != NULL));
303 cd->dlz_authority = (dlz_dlopen_authority_t *)
304 dl_load_symbol(cd, "dlz_authority", ISC_FALSE);
305 cd->dlz_newversion = (dlz_dlopen_newversion_t *)
306 dl_load_symbol(cd, "dlz_newversion", ISC_FALSE);
307 cd->dlz_closeversion = (dlz_dlopen_closeversion_t *)
308 dl_load_symbol(cd, "dlz_closeversion",
309 ISC_TF(cd->dlz_newversion != NULL));
310 cd->dlz_configure = (dlz_dlopen_configure_t *)
311 dl_load_symbol(cd, "dlz_configure", ISC_FALSE);
312 cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *)
313 dl_load_symbol(cd, "dlz_ssumatch", ISC_FALSE);
314 cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *)
315 dl_load_symbol(cd, "dlz_addrdataset", ISC_FALSE);
316 cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *)
317 dl_load_symbol(cd, "dlz_subrdataset", ISC_FALSE);
318 cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *)
319 dl_load_symbol(cd, "dlz_delrdataset", ISC_FALSE);
321 /* Check the version of the API is the same */
322 cd->version = cd->dlz_version(&cd->flags);
323 if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) ||
324 cd->version > DLZ_DLOPEN_VERSION)
326 dlopen_log(ISC_LOG_ERROR,
327 "dlz_dlopen: %s: incorrect driver API version %d, "
328 "requires %d",
329 cd->dl_path, cd->version, DLZ_DLOPEN_VERSION);
330 result = ISC_R_FAILURE;
331 goto cleanup_lock;
335 * Call the library's create function. Note that this is an
336 * extended version of dlz create, with the addition of
337 * named function pointers for helper functions that the
338 * driver will need. This avoids the need for the backend to
339 * link the BIND9 libraries
341 MAYBE_LOCK(cd);
342 result = cd->dlz_create(dlzname, argc-1, argv+1,
343 &cd->dbdata,
344 "log", dlopen_log,
345 "putrr", dns_sdlz_putrr,
346 "putnamedrr", dns_sdlz_putnamedrr,
347 "writeable_zone", dns_dlz_writeablezone,
348 NULL);
349 MAYBE_UNLOCK(cd);
350 if (result != ISC_R_SUCCESS)
351 goto cleanup_lock;
353 *dbdata = cd;
355 return (ISC_R_SUCCESS);
357 cleanup_lock:
358 DESTROYLOCK(&cd->lock);
359 failed:
360 dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname);
361 if (cd->dl_path)
362 isc_mem_free(mctx, cd->dl_path);
363 if (cd->dlzname)
364 isc_mem_free(mctx, cd->dlzname);
365 if (triedload)
366 (void) isc_mutex_destroy(&cd->lock);
367 if (cd->dl_handle)
368 FreeLibrary(cd->dl_handle);
369 isc_mem_put(mctx, cd, sizeof(*cd));
370 isc_mem_destroy(&mctx);
371 return (result);
376 * Called when bind is shutting down
378 static void
379 dlopen_dlz_destroy(void *driverarg, void *dbdata) {
380 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
381 isc_mem_t *mctx;
383 UNUSED(driverarg);
385 if (cd->dlz_destroy) {
386 MAYBE_LOCK(cd);
387 cd->dlz_destroy(cd->dbdata);
388 MAYBE_UNLOCK(cd);
391 if (cd->dl_path)
392 isc_mem_free(cd->mctx, cd->dl_path);
393 if (cd->dlzname)
394 isc_mem_free(cd->mctx, cd->dlzname);
396 if (cd->dl_handle)
397 FreeLibrary(cd->dl_handle);
399 DESTROYLOCK(&cd->lock);
401 mctx = cd->mctx;
402 isc_mem_put(mctx, cd, sizeof(*cd));
403 isc_mem_destroy(&mctx);
407 * Called to start a transaction
409 static isc_result_t
410 dlopen_dlz_newversion(const char *zone, void *driverarg, void *dbdata,
411 void **versionp)
413 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
414 isc_result_t result;
416 UNUSED(driverarg);
418 if (cd->dlz_newversion == NULL)
419 return (ISC_R_NOTIMPLEMENTED);
421 MAYBE_LOCK(cd);
422 result = cd->dlz_newversion(zone, cd->dbdata, versionp);
423 MAYBE_UNLOCK(cd);
424 return (result);
428 * Called to end a transaction
430 static void
431 dlopen_dlz_closeversion(const char *zone, isc_boolean_t commit,
432 void *driverarg, void *dbdata, void **versionp)
434 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
436 UNUSED(driverarg);
438 if (cd->dlz_newversion == NULL) {
439 *versionp = NULL;
440 return;
443 MAYBE_LOCK(cd);
444 cd->dlz_closeversion(zone, commit, cd->dbdata, versionp);
445 MAYBE_UNLOCK(cd);
449 * Called on startup to configure any writeable zones
451 static isc_result_t
452 dlopen_dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb,
453 void *driverarg, void *dbdata)
455 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
456 isc_result_t result;
458 UNUSED(driverarg);
460 if (cd->dlz_configure == NULL)
461 return (ISC_R_SUCCESS);
463 MAYBE_LOCK(cd);
464 cd->in_configure = ISC_TRUE;
465 result = cd->dlz_configure(view, dlzdb, cd->dbdata);
466 cd->in_configure = ISC_FALSE;
467 MAYBE_UNLOCK(cd);
469 return (result);
474 * Check for authority to change a name
476 static isc_boolean_t
477 dlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
478 const char *type, const char *key, isc_uint32_t keydatalen,
479 unsigned char *keydata, void *driverarg, void *dbdata)
481 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
482 isc_boolean_t ret;
484 UNUSED(driverarg);
486 if (cd->dlz_ssumatch == NULL)
487 return (ISC_FALSE);
489 MAYBE_LOCK(cd);
490 ret = cd->dlz_ssumatch(signer, name, tcpaddr, type, key, keydatalen,
491 keydata, cd->dbdata);
492 MAYBE_UNLOCK(cd);
494 return (ret);
499 * Add an rdataset
501 static isc_result_t
502 dlopen_dlz_addrdataset(const char *name, const char *rdatastr,
503 void *driverarg, void *dbdata, void *version)
505 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
506 isc_result_t result;
508 UNUSED(driverarg);
510 if (cd->dlz_addrdataset == NULL)
511 return (ISC_R_NOTIMPLEMENTED);
513 MAYBE_LOCK(cd);
514 result = cd->dlz_addrdataset(name, rdatastr, cd->dbdata, version);
515 MAYBE_UNLOCK(cd);
517 return (result);
521 * Subtract an rdataset
523 static isc_result_t
524 dlopen_dlz_subrdataset(const char *name, const char *rdatastr,
525 void *driverarg, void *dbdata, void *version)
527 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
528 isc_result_t result;
530 UNUSED(driverarg);
532 if (cd->dlz_subrdataset == NULL)
533 return (ISC_R_NOTIMPLEMENTED);
535 MAYBE_LOCK(cd);
536 result = cd->dlz_subrdataset(name, rdatastr, cd->dbdata, version);
537 MAYBE_UNLOCK(cd);
539 return (result);
543 delete a rdataset
545 static isc_result_t
546 dlopen_dlz_delrdataset(const char *name, const char *type,
547 void *driverarg, void *dbdata, void *version)
549 dlopen_data_t *cd = (dlopen_data_t *) dbdata;
550 isc_result_t result;
552 UNUSED(driverarg);
554 if (cd->dlz_delrdataset == NULL)
555 return (ISC_R_NOTIMPLEMENTED);
557 MAYBE_LOCK(cd);
558 result = cd->dlz_delrdataset(name, type, cd->dbdata, version);
559 MAYBE_UNLOCK(cd);
561 return (result);
565 static dns_sdlzmethods_t dlz_dlopen_methods = {
566 dlopen_dlz_create,
567 dlopen_dlz_destroy,
568 dlopen_dlz_findzonedb,
569 dlopen_dlz_lookup,
570 dlopen_dlz_authority,
571 dlopen_dlz_allnodes,
572 dlopen_dlz_allowzonexfr,
573 dlopen_dlz_newversion,
574 dlopen_dlz_closeversion,
575 dlopen_dlz_configure,
576 dlopen_dlz_ssumatch,
577 dlopen_dlz_addrdataset,
578 dlopen_dlz_subrdataset,
579 dlopen_dlz_delrdataset
581 #endif
584 * Register driver with BIND
586 isc_result_t
587 dlz_dlopen_init(isc_mem_t *mctx) {
588 #ifndef ISC_DLZ_DLOPEN
589 UNUSED(mctx);
590 return (ISC_R_NOTIMPLEMENTED);
591 #else
592 isc_result_t result;
594 dlopen_log(2, "Registering DLZ_dlopen driver");
596 result = dns_sdlzregister("dlopen", &dlz_dlopen_methods, NULL,
597 DNS_SDLZFLAG_RELATIVEOWNER |
598 DNS_SDLZFLAG_RELATIVERDATA |
599 DNS_SDLZFLAG_THREADSAFE,
600 mctx, &dlz_dlopen);
602 if (result != ISC_R_SUCCESS) {
603 UNEXPECTED_ERROR(__FILE__, __LINE__,
604 "dns_sdlzregister() failed: %s",
605 isc_result_totext(result));
606 result = ISC_R_UNEXPECTED;
609 return (result);
610 #endif
615 * Unregister the driver
617 void
618 dlz_dlopen_clear(void) {
619 #ifdef ISC_DLZ_DLOPEN
620 dlopen_log(2, "Unregistering DLZ_dlopen driver");
621 if (dlz_dlopen != NULL)
622 dns_sdlzunregister(&dlz_dlopen);
623 #endif