Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Plugin base
0003  *
0004  * @file expluginbase.c
0005  */
0006 /* -----------------------------------------------------------------------------
0007  * Enduro/X Middleware Platform for Distributed Transaction Processing
0008  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0009  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0010  * This software is released under one of the following licenses:
0011  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0012  * See LICENSE file for full text.
0013  * -----------------------------------------------------------------------------
0014  * AGPL license:
0015  *
0016  * This program is free software; you can redistribute it and/or modify it under
0017  * the terms of the GNU Affero General Public License, version 3 as published
0018  * by the Free Software Foundation;
0019  *
0020  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0021  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0022  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0023  * for more details.
0024  *
0025  * You should have received a copy of the GNU Affero General Public License along 
0026  * with this program; if not, write to the Free Software Foundation, Inc.,
0027  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0028  *
0029  * -----------------------------------------------------------------------------
0030  * A commercial use license is available from Mavimax, Ltd
0031  * contact@mavimax.com
0032  * -----------------------------------------------------------------------------
0033  */
0034 #include <ndrx_config.h>
0035 #include <string.h>
0036 #include <stdio.h>
0037 #include <stdlib.h>
0038 #include <dlfcn.h>
0039 
0040 #include <ndrstandard.h>
0041 #include <expluginbase.h>
0042 #include <excrypto.h>
0043 #include <inttypes.h>
0044 
0045 #include "ndebug.h"
0046 #include "userlog.h"
0047 /*---------------------------Externs------------------------------------*/
0048 /*---------------------------Macros-------------------------------------*/
0049 /** Offset definition for the function */
0050 #define OFSZ(e)   EXOFFSET(ndrx_pluginbase_t,p_ndrx_##e), EXOFFSET(ndrx_pluginbase_t,ndrx_##e##_provider)
0051 /*---------------------------Enums--------------------------------------*/
0052 /*---------------------------Typedefs-----------------------------------*/
0053 
0054 /**
0055  * Plugin loader mapping
0056  */
0057 struct plugin_loader_map
0058 {
0059     char *symb;
0060     int func_off;
0061     int provider_off;
0062     long flags;
0063 };
0064 typedef struct plugin_loader_map plugin_loader_map_t;
0065 
0066 /*---------------------------Globals------------------------------------*/
0067 
0068 /**
0069  * Plugin directory:
0070  * How about sync here? Threads must be sure that plugins are loaded
0071  * maybe we need some read/write locks?
0072  * Or normally expect that tpinit() must took a place and only then plugins
0073  * are valid!
0074  * Some of them might be pre-initialized like standard crypto key
0075  */
0076 expublic ndrx_pluginbase_t ndrx_G_plugins = {
0077 
0078     /* Is plugins loaded? */
0079     .plugins_loaded = EXFALSE
0080     
0081     /* Standard encryption encryption key function: */
0082     ,.p_ndrx_crypto_getkey = ndrx_crypto_getkey_std
0083     ,.ndrx_crypto_getkey_provider = "built in"
0084     
0085     /* UBF log print hooking */
0086     ,.p_ndrx_tplogprintubf_hook = NULL
0087     ,.ndrx_tplogprintubf_hook_provider = "none"
0088     };
0089 
0090 /*---------------------------Statics------------------------------------*/
0091 
0092 /**
0093  * Mapping driver
0094  */
0095 exprivate plugin_loader_map_t M_map_driver[] =
0096 {  
0097      {NDRX_PLUGIN_CRYPTO_GETKEY_SYMB,      OFSZ(crypto_getkey),        NDRX_PLUGIN_FUNC_ENCKEY}
0098     ,{NDRX_PLUGIN_TPLOGPRINTUBF_HOOK_SYMB, OFSZ(tplogprintubf_hook),   NDRX_PLUGIN_FUNC_TPLOGPRINTUBF_HOOK}
0099     ,{NULL}
0100 };
0101 
0102 /*---------------------------Prototypes---------------------------------*/
0103 
0104 /**
0105  * Load single plugin
0106  * @param name shared library name
0107  * @return EXSUCCEED/EXFAIL
0108  */
0109 expublic int ndrx_plugins_loadone(char *fname)
0110 {
0111     int ret = EXSUCCEED;
0112     void *handle;
0113     ndrx_plugin_init_t init;
0114     ndrx_plugin_crypto_getkey_t crypto;
0115     long flags;
0116     char provider[NDRX_PLUGIN_PROVIDERSTR_BUFSZ];
0117     
0118     plugin_loader_map_t *p = M_map_driver;
0119     
0120     
0121     handle = dlopen(fname, RTLD_LOCAL | RTLD_LAZY);
0122     
0123     if (NULL==handle)
0124     {
0125         NDRX_LOG_EARLY(log_error, "Failed to load [%s]: %s", fname, dlerror());
0126         EXFAIL_OUT(ret);
0127     }
0128     
0129     /* init the plugin */
0130     init = (ndrx_plugin_init_t)dlsym(handle, NDRX_PLUGIN_INIT_SYMB);
0131     
0132     if (NULL==init)
0133     {
0134         NDRX_LOG_EARLY(log_error, "Invalid plugin [%s] - symbol [%s] not found: %s",
0135                     fname, NDRX_PLUGIN_INIT_SYMB, dlerror());   
0136         userlog("Invalid plugin [%s] - symbol [%s] not found: %s",
0137                     fname, NDRX_PLUGIN_INIT_SYMB, dlerror());
0138         EXFAIL_OUT(ret);
0139     }
0140     
0141     NDRX_LOG_EARLY(log_debug, "About to call init: %p", init);
0142     
0143     flags = init(provider, sizeof(provider));
0144     
0145     if (EXFAIL==flags)
0146     {
0147         NDRX_LOG_EARLY(log_error, "Invalid plugin [%s] init failed!", fname);
0148         userlog("Invalid plugin [%s] init failed!", fname);
0149         EXFAIL_OUT(ret);
0150     }
0151     
0152     /* now check which functionality plugin supports... */
0153     
0154     NDRX_LOG_EARLY(log_info, "[%s] flags %lx", fname, flags);
0155     
0156     while (NULL!=p->symb)
0157     {
0158         if (flags & p->flags)
0159         {
0160             void *fptr = dlsym(handle, p->symb);
0161             void **func_ptr = (void *)(((char *)&ndrx_G_plugins) + p->func_off);
0162             char *prov_ptr = ((char *)&ndrx_G_plugins) + p->provider_off;
0163             
0164             if (NULL==fptr)
0165             {
0166                 NDRX_LOG_EARLY(log_error, "Invalid plugin [%s] - symbol [%s] not "
0167                         "found (flags " PRIx64 "): %s",
0168                         fname, p->flags, flags, dlerror());
0169                 userlog("Invalid plugin [%s] - symbol [%s] not "
0170                         "found (flags " PRIx64 "): %s",
0171                         fname, p->flags, flags, dlerror());
0172                 EXFAIL_OUT(ret);
0173             }
0174 
0175             NDRX_LOG_EARLY(log_info, "Plugin [%s] provides [%s] function",
0176                     provider, p->symb);
0177 
0178             *func_ptr = fptr;
0179             NDRX_STRCPY_SAFE_DST(prov_ptr, provider, NDRX_PLUGIN_PROVIDERSTR_BUFSZ);
0180             
0181         }
0182         
0183         p++;
0184     }
0185     
0186 out:
0187     if (EXSUCCEED!=ret && NULL!=handle)
0188     {
0189         dlclose(handle);
0190     }
0191     return ret;
0192 }
0193 
0194 /**
0195  * Load the plugins from the NDRX_PLUGINS - semicolon separated list of
0196  * dynamic link libraries. Once we load the lib, we call `long ndrx_init()'
0197  * This shall in case of success it must return the flags of which functionality
0198  * the library provides. Thus then we search for globals in the library and
0199  * send our pointer to it.
0200  * 
0201  * In case of failure the init shall return -1. We will print the warning to the
0202  * ULOG and skip the plugin.
0203  * 
0204  * @return 
0205  */
0206 expublic int ndrx_plugins_load(void)
0207 {
0208     int ret = EXSUCCEED;
0209     char *plugins_env = getenv(CONF_NDRX_PLUGINS);
0210     char *plugins = NULL;
0211     char *p;
0212     char *fname;
0213     char *save_ptr;
0214     
0215     if (NULL==plugins_env)
0216     {
0217         NDRX_LOG_EARLY(log_info, "No plugins defined by %s env variable", 
0218                 CONF_NDRX_PLUGINS);
0219         /* nothing to do... */
0220         goto out;
0221     }
0222     
0223     /* Get the env and iterate it over... */
0224     
0225     plugins = NDRX_STRDUP(plugins_env);
0226     
0227     NDRX_LOG_EARLY(log_debug, "%s: loading plugins.... [%s]", __func__, plugins);
0228     
0229     p = strtok_r (plugins, ";", &save_ptr);
0230     
0231     while (NULL!=p)
0232     {
0233         /* trim down ltrim/rtrim the name */
0234         
0235         fname = ndrx_str_lstrip_ptr(p, " \t");
0236         ndrx_str_rstrip(fname, " \t");
0237         
0238         NDRX_LOG_EARLY(log_info, "About to load: [%s]", fname);
0239         
0240         /* Resolve symbols... */
0241         if (EXSUCCEED!=ndrx_plugins_loadone(fname))
0242         {
0243             userlog("Failed to load [%s] plugin...", fname);
0244         }
0245         
0246         p = strtok_r (NULL, ";", &save_ptr);
0247     }
0248     
0249 out:
0250     if (NULL!=plugins)
0251     {
0252         NDRX_FREE(plugins);
0253     }
0254     return ret;
0255 }
0256 
0257 /* vim: set ts=4 sw=4 et smartindent: */