"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.17.5/lib/dns/dyndb.c" (4 Sep 2020, 7936 Bytes) of package /linux/misc/dns/bind9/9.17.5/bind-9.17.5.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 "dyndb.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 <ltdl.h>
   13 #include <string.h>
   14 
   15 #include <isc/buffer.h>
   16 #include <isc/mem.h>
   17 #include <isc/mutex.h>
   18 #include <isc/once.h>
   19 #include <isc/region.h>
   20 #include <isc/result.h>
   21 #include <isc/task.h>
   22 #include <isc/types.h>
   23 #include <isc/util.h>
   24 
   25 #include <dns/dyndb.h>
   26 #include <dns/log.h>
   27 #include <dns/types.h>
   28 #include <dns/view.h>
   29 #include <dns/zone.h>
   30 
   31 #define CHECK(op)                            \
   32     do {                                 \
   33         result = (op);               \
   34         if (result != ISC_R_SUCCESS) \
   35             goto cleanup;        \
   36     } while (0)
   37 
   38 typedef struct dyndb_implementation dyndb_implementation_t;
   39 struct dyndb_implementation {
   40     isc_mem_t *mctx;
   41     void *handle;
   42     dns_dyndb_register_t *register_func;
   43     dns_dyndb_destroy_t *destroy_func;
   44     char *name;
   45     void *inst;
   46     LINK(dyndb_implementation_t) link;
   47 };
   48 
   49 /*
   50  * List of dyndb implementations. Locked by dyndb_lock.
   51  *
   52  * These are stored here so they can be cleaned up on shutdown.
   53  * (The order in which they are stored is not important.)
   54  */
   55 static LIST(dyndb_implementation_t) dyndb_implementations;
   56 
   57 /* Locks dyndb_implementations. */
   58 static isc_mutex_t dyndb_lock;
   59 static isc_once_t once = ISC_ONCE_INIT;
   60 
   61 static void
   62 dyndb_initialize(void) {
   63     isc_mutex_init(&dyndb_lock);
   64     INIT_LIST(dyndb_implementations);
   65 }
   66 
   67 static dyndb_implementation_t *
   68 impfind(const char *name) {
   69     dyndb_implementation_t *imp;
   70 
   71     for (imp = ISC_LIST_HEAD(dyndb_implementations); imp != NULL;
   72          imp = ISC_LIST_NEXT(imp, link))
   73     {
   74         if (strcasecmp(name, imp->name) == 0) {
   75             return (imp);
   76         }
   77     }
   78     return (NULL);
   79 }
   80 
   81 static isc_result_t
   82 load_symbol(lt_dlhandle handle, const char *filename, const char *symbol_name,
   83         void **symbolp) {
   84     void *symbol;
   85 
   86     REQUIRE(handle != NULL);
   87     REQUIRE(symbolp != NULL && *symbolp == NULL);
   88 
   89     symbol = lt_dlsym(handle, symbol_name);
   90     if (symbol == NULL) {
   91         const char *errmsg = lt_dlerror();
   92         if (errmsg == NULL) {
   93             errmsg = "returned function pointer is NULL";
   94         }
   95         isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
   96                   DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR,
   97                   "failed to lookup symbol %s in "
   98                   "dyndb module '%s': %s",
   99                   symbol_name, filename, errmsg);
  100         return (ISC_R_FAILURE);
  101     }
  102     (void)lt_dlerror();
  103 
  104     *symbolp = symbol;
  105 
  106     return (ISC_R_SUCCESS);
  107 }
  108 
  109 static isc_result_t
  110 load_library(isc_mem_t *mctx, const char *filename, const char *instname,
  111          dyndb_implementation_t **impp) {
  112     isc_result_t result;
  113     lt_dlhandle handle = NULL;
  114     dyndb_implementation_t *imp = NULL;
  115     dns_dyndb_register_t *register_func = NULL;
  116     dns_dyndb_destroy_t *destroy_func = NULL;
  117     dns_dyndb_version_t *version_func = NULL;
  118     int version;
  119 
  120     REQUIRE(impp != NULL && *impp == NULL);
  121 
  122     isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DYNDB,
  123               ISC_LOG_INFO, "loading DynDB instance '%s' driver '%s'",
  124               instname, filename);
  125 
  126     if (lt_dlinit() != 0) {
  127         CHECK(ISC_R_FAILURE);
  128     }
  129 
  130     handle = lt_dlopen(filename);
  131     if (handle == NULL) {
  132         CHECK(ISC_R_FAILURE);
  133     }
  134 
  135     /* Clear dlerror */
  136     (void)lt_dlerror();
  137 
  138     CHECK(load_symbol(handle, filename, "dyndb_version",
  139               (void **)&version_func));
  140 
  141     version = version_func(NULL);
  142     if (version < (DNS_DYNDB_VERSION - DNS_DYNDB_AGE) ||
  143         version > DNS_DYNDB_VERSION)
  144     {
  145         isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
  146                   DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR,
  147                   "driver API version mismatch: %d/%d", version,
  148                   DNS_DYNDB_VERSION);
  149         CHECK(ISC_R_FAILURE);
  150     }
  151 
  152     CHECK(load_symbol(handle, filename, "dyndb_init",
  153               (void **)&register_func));
  154     CHECK(load_symbol(handle, filename, "dyndb_destroy",
  155               (void **)&destroy_func));
  156 
  157     imp = isc_mem_get(mctx, sizeof(dyndb_implementation_t));
  158 
  159     imp->mctx = NULL;
  160     isc_mem_attach(mctx, &imp->mctx);
  161     imp->handle = handle;
  162     imp->register_func = register_func;
  163     imp->destroy_func = destroy_func;
  164     imp->name = isc_mem_strdup(mctx, instname);
  165 
  166     imp->inst = NULL;
  167     INIT_LINK(imp, link);
  168 
  169     *impp = imp;
  170     imp = NULL;
  171 
  172 cleanup:
  173     if (result != ISC_R_SUCCESS) {
  174         isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
  175                   DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR,
  176                   "failed to dynamically load instance '%s' "
  177                   "driver '%s': %s (%s)",
  178                   instname, filename, lt_dlerror(),
  179                   isc_result_totext(result));
  180     }
  181     if (imp != NULL) {
  182         isc_mem_putanddetach(&imp->mctx, imp,
  183                      sizeof(dyndb_implementation_t));
  184     }
  185     if (result != ISC_R_SUCCESS && handle != NULL) {
  186         (void)lt_dlclose(handle);
  187     }
  188 
  189     return (result);
  190 }
  191 
  192 static void
  193 unload_library(dyndb_implementation_t **impp) {
  194     dyndb_implementation_t *imp;
  195 
  196     REQUIRE(impp != NULL && *impp != NULL);
  197 
  198     imp = *impp;
  199     *impp = NULL;
  200 
  201     isc_mem_free(imp->mctx, imp->name);
  202     isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t));
  203 }
  204 
  205 isc_result_t
  206 dns_dyndb_load(const char *libname, const char *name, const char *parameters,
  207            const char *file, unsigned long line, isc_mem_t *mctx,
  208            const dns_dyndbctx_t *dctx) {
  209     isc_result_t result;
  210     dyndb_implementation_t *implementation = NULL;
  211 
  212     REQUIRE(DNS_DYNDBCTX_VALID(dctx));
  213     REQUIRE(name != NULL);
  214 
  215     RUNTIME_CHECK(isc_once_do(&once, dyndb_initialize) == ISC_R_SUCCESS);
  216 
  217     LOCK(&dyndb_lock);
  218 
  219     /* duplicate instance names are not allowed */
  220     if (impfind(name) != NULL) {
  221         CHECK(ISC_R_EXISTS);
  222     }
  223 
  224     CHECK(load_library(mctx, libname, name, &implementation));
  225     CHECK(implementation->register_func(mctx, name, parameters, file, line,
  226                         dctx, &implementation->inst));
  227 
  228     APPEND(dyndb_implementations, implementation, link);
  229     result = ISC_R_SUCCESS;
  230 
  231 cleanup:
  232     if (result != ISC_R_SUCCESS) {
  233         if (implementation != NULL) {
  234             unload_library(&implementation);
  235         }
  236     }
  237 
  238     UNLOCK(&dyndb_lock);
  239     return (result);
  240 }
  241 
  242 void
  243 dns_dyndb_cleanup(bool exiting) {
  244     dyndb_implementation_t *elem;
  245     dyndb_implementation_t *prev;
  246 
  247     RUNTIME_CHECK(isc_once_do(&once, dyndb_initialize) == ISC_R_SUCCESS);
  248 
  249     LOCK(&dyndb_lock);
  250     elem = TAIL(dyndb_implementations);
  251     while (elem != NULL) {
  252         prev = PREV(elem, link);
  253         UNLINK(dyndb_implementations, elem, link);
  254         isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
  255                   DNS_LOGMODULE_DYNDB, ISC_LOG_INFO,
  256                   "unloading DynDB instance '%s'", elem->name);
  257         elem->destroy_func(&elem->inst);
  258         ENSURE(elem->inst == NULL);
  259         unload_library(&elem);
  260         elem = prev;
  261     }
  262     UNLOCK(&dyndb_lock);
  263 
  264     if (exiting) {
  265         isc_mutex_destroy(&dyndb_lock);
  266     }
  267 }
  268 
  269 isc_result_t
  270 dns_dyndb_createctx(isc_mem_t *mctx, const void *hashinit, isc_log_t *lctx,
  271             dns_view_t *view, dns_zonemgr_t *zmgr, isc_task_t *task,
  272             isc_timermgr_t *tmgr, dns_dyndbctx_t **dctxp) {
  273     dns_dyndbctx_t *dctx;
  274 
  275     REQUIRE(dctxp != NULL && *dctxp == NULL);
  276 
  277     dctx = isc_mem_get(mctx, sizeof(*dctx));
  278 
  279     memset(dctx, 0, sizeof(*dctx));
  280     if (view != NULL) {
  281         dns_view_attach(view, &dctx->view);
  282     }
  283     if (zmgr != NULL) {
  284         dns_zonemgr_attach(zmgr, &dctx->zmgr);
  285     }
  286     if (task != NULL) {
  287         isc_task_attach(task, &dctx->task);
  288     }
  289     dctx->timermgr = tmgr;
  290     dctx->hashinit = hashinit;
  291     dctx->lctx = lctx;
  292     dctx->refvar = &isc_bind9;
  293 
  294     isc_mem_attach(mctx, &dctx->mctx);
  295     dctx->magic = DNS_DYNDBCTX_MAGIC;
  296 
  297     *dctxp = dctx;
  298 
  299     return (ISC_R_SUCCESS);
  300 }
  301 
  302 void
  303 dns_dyndb_destroyctx(dns_dyndbctx_t **dctxp) {
  304     dns_dyndbctx_t *dctx;
  305 
  306     REQUIRE(dctxp != NULL && DNS_DYNDBCTX_VALID(*dctxp));
  307 
  308     dctx = *dctxp;
  309     *dctxp = NULL;
  310 
  311     dctx->magic = 0;
  312 
  313     if (dctx->view != NULL) {
  314         dns_view_detach(&dctx->view);
  315     }
  316     if (dctx->zmgr != NULL) {
  317         dns_zonemgr_detach(&dctx->zmgr);
  318     }
  319     if (dctx->task != NULL) {
  320         isc_task_detach(&dctx->task);
  321     }
  322     dctx->timermgr = NULL;
  323     dctx->lctx = NULL;
  324 
  325     isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(*dctx));
  326 }