"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/bin/named/win32/dlz_dlopen_driver.c" (4 Sep 2020, 14261 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dlz_dlopen_driver.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 #include <inttypes.h>
   13 #include <stdbool.h>
   14 #include <stdio.h>
   15 #include <stdlib.h>
   16 #include <string.h>
   17 #include <windows.h>
   18 
   19 #include <isc/mem.h>
   20 #include <isc/print.h>
   21 #include <isc/result.h>
   22 #include <isc/util.h>
   23 
   24 #include <dns/dlz_dlopen.h>
   25 #include <dns/log.h>
   26 #include <dns/result.h>
   27 
   28 #include <dlz/dlz_dlopen_driver.h>
   29 #include <named/globals.h>
   30 
   31 #ifdef ISC_DLZ_DLOPEN
   32 static dns_sdlzimplementation_t *dlz_dlopen = NULL;
   33 
   34 typedef struct dlopen_data {
   35     isc_mem_t *mctx;
   36     char *dl_path;
   37     char *dlzname;
   38     HMODULE dl_handle;
   39     void *dbdata;
   40     unsigned int flags;
   41     isc_mutex_t lock;
   42     int version;
   43     bool in_configure;
   44 
   45     dlz_dlopen_version_t *dlz_version;
   46     dlz_dlopen_create_t *dlz_create;
   47     dlz_dlopen_findzonedb_t *dlz_findzonedb;
   48     dlz_dlopen_lookup_t *dlz_lookup;
   49     dlz_dlopen_authority_t *dlz_authority;
   50     dlz_dlopen_allnodes_t *dlz_allnodes;
   51     dlz_dlopen_allowzonexfr_t *dlz_allowzonexfr;
   52     dlz_dlopen_newversion_t *dlz_newversion;
   53     dlz_dlopen_closeversion_t *dlz_closeversion;
   54     dlz_dlopen_configure_t *dlz_configure;
   55     dlz_dlopen_ssumatch_t *dlz_ssumatch;
   56     dlz_dlopen_addrdataset_t *dlz_addrdataset;
   57     dlz_dlopen_subrdataset_t *dlz_subrdataset;
   58     dlz_dlopen_delrdataset_t *dlz_delrdataset;
   59     dlz_dlopen_destroy_t *dlz_destroy;
   60 } dlopen_data_t;
   61 
   62 /* Modules can choose whether they are lock-safe or not. */
   63 #define MAYBE_LOCK(cd)                                            \
   64     do {                                                      \
   65         if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \
   66             !cd->in_configure)                            \
   67             LOCK(&cd->lock);                          \
   68     } while (0)
   69 
   70 #define MAYBE_UNLOCK(cd)                                          \
   71     do {                                                      \
   72         if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \
   73             !cd->in_configure)                            \
   74             UNLOCK(&cd->lock);                        \
   75     } while (0)
   76 
   77 /*
   78  * Log a message at the given level.
   79  */
   80 static void
   81 dlopen_log(int level, const char *fmt, ...) {
   82     va_list ap;
   83     va_start(ap, fmt);
   84     isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ,
   85                ISC_LOG_DEBUG(level), fmt, ap);
   86     va_end(ap);
   87 }
   88 
   89 /*
   90  * SDLZ methods
   91  */
   92 
   93 static isc_result_t
   94 dlopen_dlz_allnodes(const char *zone, void *driverarg, void *dbdata,
   95             dns_sdlzallnodes_t *allnodes) {
   96     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
   97     isc_result_t result;
   98 
   99     UNUSED(driverarg);
  100 
  101     if (cd->dlz_allnodes == NULL) {
  102         return (ISC_R_NOPERM);
  103     }
  104 
  105     MAYBE_LOCK(cd);
  106     result = cd->dlz_allnodes(zone, cd->dbdata, allnodes);
  107     MAYBE_UNLOCK(cd);
  108     return (result);
  109 }
  110 
  111 static isc_result_t
  112 dlopen_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name,
  113             const char *client) {
  114     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
  115     isc_result_t result;
  116 
  117     UNUSED(driverarg);
  118 
  119     if (cd->dlz_allowzonexfr == NULL) {
  120         return (ISC_R_NOPERM);
  121     }
  122 
  123     MAYBE_LOCK(cd);
  124     result = cd->dlz_allowzonexfr(cd->dbdata, name, client);
  125     MAYBE_UNLOCK(cd);
  126     return (result);
  127 }
  128 
  129 static isc_result_t
  130 dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata,
  131              dns_sdlzlookup_t *lookup) {
  132     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
  133     isc_result_t result;
  134 
  135     UNUSED(driverarg);
  136 
  137     if (cd->dlz_authority == NULL) {
  138         return (ISC_R_NOTIMPLEMENTED);
  139     }
  140 
  141     MAYBE_LOCK(cd);
  142     result = cd->dlz_authority(zone, cd->dbdata, lookup);
  143     MAYBE_UNLOCK(cd);
  144     return (result);
  145 }
  146 
  147 static isc_result_t
  148 dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name,
  149               dns_clientinfomethods_t *methods,
  150               dns_clientinfo_t *clientinfo) {
  151     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
  152     isc_result_t result;
  153 
  154     UNUSED(driverarg);
  155 
  156     MAYBE_LOCK(cd);
  157     result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo);
  158     MAYBE_UNLOCK(cd);
  159     return (result);
  160 }
  161 
  162 static isc_result_t
  163 dlopen_dlz_lookup(const char *zone, const char *name, void *driverarg,
  164           void *dbdata, dns_sdlzlookup_t *lookup,
  165           dns_clientinfomethods_t *methods,
  166           dns_clientinfo_t *clientinfo) {
  167     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
  168     isc_result_t result;
  169 
  170     UNUSED(driverarg);
  171 
  172     MAYBE_LOCK(cd);
  173     result = cd->dlz_lookup(zone, name, cd->dbdata, lookup, methods,
  174                 clientinfo);
  175     MAYBE_UNLOCK(cd);
  176     return (result);
  177 }
  178 
  179 /*
  180  * Load a symbol from the library
  181  */
  182 static void *
  183 dl_load_symbol(dlopen_data_t *cd, const char *symbol, bool mandatory) {
  184     void *ptr = GetProcAddress(cd->dl_handle, symbol);
  185     if (ptr == NULL && mandatory) {
  186         dlopen_log(ISC_LOG_ERROR,
  187                "dlz_dlopen: library '%s' is missing "
  188                "required symbol '%s'",
  189                cd->dl_path, symbol);
  190     }
  191     return (ptr);
  192 }
  193 
  194 /*
  195  * Called at startup for each dlopen zone in named.conf
  196  */
  197 static isc_result_t
  198 dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
  199           void *driverarg, void **dbdata) {
  200     dlopen_data_t *cd;
  201     isc_mem_t *mctx = NULL;
  202     isc_result_t result = ISC_R_FAILURE;
  203     bool triedload = false;
  204 
  205     UNUSED(driverarg);
  206 
  207     if (argc < 2) {
  208         dlopen_log(ISC_LOG_ERROR,
  209                "dlz_dlopen driver for '%s' needs a path to "
  210                "the shared library",
  211                dlzname);
  212         return (ISC_R_FAILURE);
  213     }
  214 
  215     isc_mem_create(&mctx);
  216 
  217     cd = isc_mem_get(mctx, sizeof(*cd));
  218     memset(cd, 0, sizeof(*cd));
  219 
  220     cd->mctx = mctx;
  221 
  222     cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]);
  223 
  224     cd->dlzname = isc_mem_strdup(cd->mctx, dlzname);
  225 
  226     triedload = true;
  227 
  228     /* Initialize the lock */
  229     isc_mutex_init(&cd->lock);
  230 
  231     /* Open the library */
  232     cd->dl_handle = LoadLibraryA(cd->dl_path);
  233     if (cd->dl_handle == NULL) {
  234         unsigned int error = GetLastError();
  235 
  236         dlopen_log(ISC_LOG_ERROR,
  237                "dlz_dlopen failed to open library '%s' - %u",
  238                cd->dl_path, error);
  239         result = ISC_R_FAILURE;
  240         goto cleanup_lock;
  241     }
  242 
  243     /* Find the symbols */
  244     cd->dlz_version =
  245         (dlz_dlopen_version_t *)dl_load_symbol(cd, "dlz_version", true);
  246     cd->dlz_create = (dlz_dlopen_create_t *)dl_load_symbol(cd, "dlz_create",
  247                                    true);
  248     cd->dlz_lookup = (dlz_dlopen_lookup_t *)dl_load_symbol(cd, "dlz_lookup",
  249                                    true);
  250     cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *)dl_load_symbol(
  251         cd, "dlz_findzonedb", true);
  252 
  253     if (cd->dlz_create == NULL || cd->dlz_version == NULL ||
  254         cd->dlz_lookup == NULL || cd->dlz_findzonedb == NULL)
  255     {
  256         /* We're missing a required symbol */
  257         result = ISC_R_FAILURE;
  258         goto cleanup_lock;
  259     }
  260 
  261     cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *)dl_load_symbol(
  262         cd, "dlz_allowzonexfr", false);
  263     cd->dlz_allnodes = (dlz_dlopen_allnodes_t *)dl_load_symbol(
  264         cd, "dlz_allnodes", (cd->dlz_allowzonexfr != NULL));
  265     cd->dlz_authority = (dlz_dlopen_authority_t *)dl_load_symbol(
  266         cd, "dlz_authority", false);
  267     cd->dlz_newversion = (dlz_dlopen_newversion_t *)dl_load_symbol(
  268         cd, "dlz_newversion", false);
  269     cd->dlz_closeversion = (dlz_dlopen_closeversion_t *)dl_load_symbol(
  270         cd, "dlz_closeversion", (cd->dlz_newversion != NULL));
  271     cd->dlz_configure = (dlz_dlopen_configure_t *)dl_load_symbol(
  272         cd, "dlz_configure", false);
  273     cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *)dl_load_symbol(
  274         cd, "dlz_ssumatch", false);
  275     cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *)dl_load_symbol(
  276         cd, "dlz_addrdataset", false);
  277     cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *)dl_load_symbol(
  278         cd, "dlz_subrdataset", false);
  279     cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *)dl_load_symbol(
  280         cd, "dlz_delrdataset", false);
  281 
  282     /* Check the version of the API is the same */
  283     cd->version = cd->dlz_version(&cd->flags);
  284     if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) ||
  285         cd->version > DLZ_DLOPEN_VERSION)
  286     {
  287         dlopen_log(ISC_LOG_ERROR,
  288                "dlz_dlopen: %s: incorrect driver API version %d, "
  289                "requires %d",
  290                cd->dl_path, cd->version, DLZ_DLOPEN_VERSION);
  291         result = ISC_R_FAILURE;
  292         goto cleanup_lock;
  293     }
  294 
  295     /*
  296      * Call the library's create function. Note that this is an
  297      * extended version of dlz create, with the addition of
  298      * named function pointers for helper functions that the
  299      * driver will need. This avoids the need for the backend to
  300      * link the BIND9 libraries
  301      */
  302     MAYBE_LOCK(cd);
  303     result = cd->dlz_create(dlzname, argc - 1, argv + 1, &cd->dbdata, "log",
  304                 dlopen_log, "putrr", dns_sdlz_putrr,
  305                 "putnamedrr", dns_sdlz_putnamedrr,
  306                 "writeable_zone", dns_dlz_writeablezone, NULL);
  307     MAYBE_UNLOCK(cd);
  308     if (result != ISC_R_SUCCESS) {
  309         goto cleanup_lock;
  310     }
  311 
  312     *dbdata = cd;
  313 
  314     return (ISC_R_SUCCESS);
  315 
  316 cleanup_lock:
  317     isc_mutex_destroy(&cd->lock);
  318 failed:
  319     dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname);
  320     if (cd->dl_path) {
  321         isc_mem_free(mctx, cd->dl_path);
  322     }
  323     if (cd->dlzname) {
  324         isc_mem_free(mctx, cd->dlzname);
  325     }
  326     if (triedload) {
  327         isc_mutex_destroy(&cd->lock);
  328     }
  329     if (cd->dl_handle) {
  330         FreeLibrary(cd->dl_handle);
  331     }
  332     isc_mem_put(mctx, cd, sizeof(*cd));
  333     isc_mem_destroy(&mctx);
  334     return (result);
  335 }
  336 
  337 /*
  338  * Called when bind is shutting down
  339  */
  340 static void
  341 dlopen_dlz_destroy(void *driverarg, void *dbdata) {
  342     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
  343     isc_mem_t *mctx;
  344 
  345     UNUSED(driverarg);
  346 
  347     if (cd->dlz_destroy) {
  348         MAYBE_LOCK(cd);
  349         cd->dlz_destroy(cd->dbdata);
  350         MAYBE_UNLOCK(cd);
  351     }
  352 
  353     if (cd->dl_path) {
  354         isc_mem_free(cd->mctx, cd->dl_path);
  355     }
  356     if (cd->dlzname) {
  357         isc_mem_free(cd->mctx, cd->dlzname);
  358     }
  359 
  360     if (cd->dl_handle) {
  361         FreeLibrary(cd->dl_handle);
  362     }
  363 
  364     isc_mutex_destroy(&cd->lock);
  365 
  366     mctx = cd->mctx;
  367     isc_mem_put(mctx, cd, sizeof(*cd));
  368     isc_mem_destroy(&mctx);
  369 }
  370 
  371 /*
  372  * Called to start a transaction
  373  */
  374 static isc_result_t
  375 dlopen_dlz_newversion(const char *zone, void *driverarg, void *dbdata,
  376               void **versionp) {
  377     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
  378     isc_result_t result;
  379 
  380     UNUSED(driverarg);
  381 
  382     if (cd->dlz_newversion == NULL) {
  383         return (ISC_R_NOTIMPLEMENTED);
  384     }
  385 
  386     MAYBE_LOCK(cd);
  387     result = cd->dlz_newversion(zone, cd->dbdata, versionp);
  388     MAYBE_UNLOCK(cd);
  389     return (result);
  390 }
  391 
  392 /*
  393  * Called to end a transaction
  394  */
  395 static void
  396 dlopen_dlz_closeversion(const char *zone, bool commit, void *driverarg,
  397             void *dbdata, void **versionp) {
  398     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
  399 
  400     UNUSED(driverarg);
  401 
  402     if (cd->dlz_newversion == NULL) {
  403         *versionp = NULL;
  404         return;
  405     }
  406 
  407     MAYBE_LOCK(cd);
  408     cd->dlz_closeversion(zone, commit, cd->dbdata, versionp);
  409     MAYBE_UNLOCK(cd);
  410 }
  411 
  412 /*
  413  * Called on startup to configure any writeable zones
  414  */
  415 static isc_result_t
  416 dlopen_dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *driverarg,
  417              void *dbdata) {
  418     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
  419     isc_result_t result;
  420 
  421     UNUSED(driverarg);
  422 
  423     if (cd->dlz_configure == NULL) {
  424         return (ISC_R_SUCCESS);
  425     }
  426 
  427     MAYBE_LOCK(cd);
  428     cd->in_configure = true;
  429     result = cd->dlz_configure(view, dlzdb, cd->dbdata);
  430     cd->in_configure = false;
  431     MAYBE_UNLOCK(cd);
  432 
  433     return (result);
  434 }
  435 
  436 /*
  437  * Check for authority to change a name
  438  */
  439 static bool
  440 dlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
  441             const char *type, const char *key, uint32_t keydatalen,
  442             unsigned char *keydata, void *driverarg, void *dbdata) {
  443     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
  444     bool ret;
  445 
  446     UNUSED(driverarg);
  447 
  448     if (cd->dlz_ssumatch == NULL) {
  449         return (false);
  450     }
  451 
  452     MAYBE_LOCK(cd);
  453     ret = cd->dlz_ssumatch(signer, name, tcpaddr, type, key, keydatalen,
  454                    keydata, cd->dbdata);
  455     MAYBE_UNLOCK(cd);
  456 
  457     return (ret);
  458 }
  459 
  460 /*
  461  * Add an rdataset
  462  */
  463 static isc_result_t
  464 dlopen_dlz_addrdataset(const char *name, const char *rdatastr, void *driverarg,
  465                void *dbdata, void *version) {
  466     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
  467     isc_result_t result;
  468 
  469     UNUSED(driverarg);
  470 
  471     if (cd->dlz_addrdataset == NULL) {
  472         return (ISC_R_NOTIMPLEMENTED);
  473     }
  474 
  475     MAYBE_LOCK(cd);
  476     result = cd->dlz_addrdataset(name, rdatastr, cd->dbdata, version);
  477     MAYBE_UNLOCK(cd);
  478 
  479     return (result);
  480 }
  481 
  482 /*
  483  * Subtract an rdataset
  484  */
  485 static isc_result_t
  486 dlopen_dlz_subrdataset(const char *name, const char *rdatastr, void *driverarg,
  487                void *dbdata, void *version) {
  488     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
  489     isc_result_t result;
  490 
  491     UNUSED(driverarg);
  492 
  493     if (cd->dlz_subrdataset == NULL) {
  494         return (ISC_R_NOTIMPLEMENTED);
  495     }
  496 
  497     MAYBE_LOCK(cd);
  498     result = cd->dlz_subrdataset(name, rdatastr, cd->dbdata, version);
  499     MAYBE_UNLOCK(cd);
  500 
  501     return (result);
  502 }
  503 
  504 /*
  505  * delete a rdataset
  506  */
  507 static isc_result_t
  508 dlopen_dlz_delrdataset(const char *name, const char *type, void *driverarg,
  509                void *dbdata, void *version) {
  510     dlopen_data_t *cd = (dlopen_data_t *)dbdata;
  511     isc_result_t result;
  512 
  513     UNUSED(driverarg);
  514 
  515     if (cd->dlz_delrdataset == NULL) {
  516         return (ISC_R_NOTIMPLEMENTED);
  517     }
  518 
  519     MAYBE_LOCK(cd);
  520     result = cd->dlz_delrdataset(name, type, cd->dbdata, version);
  521     MAYBE_UNLOCK(cd);
  522 
  523     return (result);
  524 }
  525 
  526 static dns_sdlzmethods_t dlz_dlopen_methods = {
  527     dlopen_dlz_create,   dlopen_dlz_destroy,    dlopen_dlz_findzonedb,
  528     dlopen_dlz_lookup,   dlopen_dlz_authority,  dlopen_dlz_allnodes,
  529     dlopen_dlz_allowzonexfr, dlopen_dlz_newversion, dlopen_dlz_closeversion,
  530     dlopen_dlz_configure,    dlopen_dlz_ssumatch,   dlopen_dlz_addrdataset,
  531     dlopen_dlz_subrdataset,  dlopen_dlz_delrdataset
  532 };
  533 #endif /* ifdef ISC_DLZ_DLOPEN */
  534 
  535 /*
  536  * Register driver with BIND
  537  */
  538 isc_result_t
  539 dlz_dlopen_init(isc_mem_t *mctx) {
  540 #ifndef ISC_DLZ_DLOPEN
  541     UNUSED(mctx);
  542     return (ISC_R_NOTIMPLEMENTED);
  543 #else  /* ifndef ISC_DLZ_DLOPEN */
  544     isc_result_t result;
  545 
  546     dlopen_log(2, "Registering DLZ_dlopen driver");
  547 
  548     result = dns_sdlzregister("dlopen", &dlz_dlopen_methods, NULL,
  549                   DNS_SDLZFLAG_RELATIVEOWNER |
  550                       DNS_SDLZFLAG_RELATIVERDATA |
  551                       DNS_SDLZFLAG_THREADSAFE,
  552                   mctx, &dlz_dlopen);
  553 
  554     if (result != ISC_R_SUCCESS) {
  555         UNEXPECTED_ERROR(__FILE__, __LINE__,
  556                  "dns_sdlzregister() failed: %s",
  557                  isc_result_totext(result));
  558         result = ISC_R_UNEXPECTED;
  559     }
  560 
  561     return (result);
  562 #endif /* ifndef ISC_DLZ_DLOPEN */
  563 }
  564 
  565 /*
  566  * Unregister the driver
  567  */
  568 void
  569 dlz_dlopen_clear(void) {
  570 #ifdef ISC_DLZ_DLOPEN
  571     dlopen_log(2, "Unregistering DLZ_dlopen driver");
  572     if (dlz_dlopen != NULL) {
  573         dns_sdlzunregister(&dlz_dlopen);
  574     }
  575 #endif /* ifdef ISC_DLZ_DLOPEN */
  576 }