26 RCSID(
"$Id: 742541762963c4cfc46f723070b93ccf301f9c36 $")
27 #define _DL_MODULE_PRIVATE 1
28 #include <freeradius-devel/server/dl_module.h>
30 #include <freeradius-devel/server/log.h>
31 #include <freeradius-devel/server/global_lib.h>
32 #include <freeradius-devel/util/debug.h>
34 #include <freeradius-devel/util/dl.h>
35 #include <freeradius-devel/util/syserror.h>
41 #define DL_INIT_CHECK fr_assert(dl_module_loader)
73 ret = strcmp(a->
dl->
name, b->dl->name);
107 static inline CC_HINT(always_inline)
136 ret = dl_module->
exported->onload();
139 PERROR(
"Initialisation failed for module \"%s\" - onload() returned %i",
142 PERROR(
"Initialisation failed for module \"%s\"", dl_module->
exported->name);
184 dladdr(module, &dl_info);
189 ERROR(
"Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname);
191 ERROR(
"Application and rlm_%s magic number (prefix) mismatch."
192 " application: %x module: %x", module->name,
200 ERROR(
"Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname);
202 ERROR(
"Application and rlm_%s magic number (version) mismatch."
203 " application: %lx module: %lx", module->name,
211 ERROR(
"Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname);
213 ERROR(
"Application and rlm_%s magic number (commit) mismatch."
214 " application: %lx module: %lx", module->name,
240 "dl_module_loader->lock not held when freeing module, "
241 "use dl_module_free() to free modules, not talloc_free");
246 if (--dl_module->
refs > 0)
return -1;
253 DEBUG4(
"%s unloaded. Handle address %p, symbol address %p", dl_module->
dl->
name,
286 pthread_mutex_lock(&dl_module_l->
lock);
288 pthread_mutex_unlock(&dl_module_l->
lock);
319 char *module_name = NULL;
346 &(
dl_module_t){ .dl = &(dl_t){ .name = module_name }});
362 dl_module->name = talloc_strdup(dl_module,
name);
364 dl_module->parent =
parent;
365 dl_module->type =
type;
375 PERROR(
"Failed to link to module \"%s\"", module_name);
376 ERROR(
"Make sure it (and all its dependent libraries!) are in the search path"
377 " of your system's ld");
386 DEBUG3(
"%s loaded, checking if it's valid", module_name);
388 common = dlsym(
dl->
handle, module_name);
390 ERROR(
"Could not find \"%s\" symbol in module: %s", module_name, dlerror());
393 dl_module->exported = common;
400 DEBUG3(
"%s validated. Handle address %p, symbol address %p", module_name,
dl, common);
403 PERROR(
"Failed calling initializers for module \"%s\"", module_name);
407 DEBUG2(
"Loaded module %s", module_name);
413 if (!dl_module->in_tree) {
414 ERROR(
"Failed caching module \"%s\"", module_name);
440 "dl_module_loader->lock held when attempting to free dL_module_loader_t");
447 WARN(
"Refusing to cleanup dl loader, the following modules are still in use:");
465 PWARN(
"dl loader not freed");
471 WARN(
"This may appear as a leak in talloc memory reports");
477 pthread_mutex_unlock(&dl_module_l->
lock);
478 pthread_mutex_destroy(&dl_module_l->
lock);
500 if (ret < 0)
PERROR(
"Failed autoloading enum value for \"%s\"", module->
name);
512 if (ret < 0)
PERROR(
"Failed autoloading attribute for \"%s\"", module->
name);
524 if (ret < 0)
PERROR(
"Failed autoloading dictionary for \"%s\"", module->
name);
547 ERROR(
"Failed initialising uctx for dl_loader");
554 PERROR(
"Failed initialising dl_loader");
564 ERROR(
"Failed initialising dl->module_tree");
570 ERROR(
"Failed registering load() callback");
576 ERROR(
"Failed registering unload() callback");
603 DEBUG4(
"Module linker search path(s)");
610 env = getenv(
"LD_LIBRARY_PATH");
612 DEBUG4(
"LD_LIBRARY_PATH : %s", env);
614 env = getenv(
"DYLD_LIBRARY_PATH");
616 DEBUG4(
"DYLB_LIBRARY_PATH : %s", env);
618 env = getenv(
"DYLD_FALLBACK_LIBRARY_PATH");
620 DEBUG4(
"DYLD_FALLBACK_LIBRARY_PATH : %s", env);
624 DEBUG4(
"Current directory : %s", env);
627 env = getenv(
"LD_LIBRARY_PATH");
629 DEBUG4(
"LD_LIBRARY_PATH : %s", env);
631 DEBUG4(
"Defaults : /lib:/usr/lib");
static int const char char buffer[256]
#define L(_str)
Helper for initialising arrays of string literals.
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
int fr_dl_dict_enum_autoload(dl_t const *module, void *symbol, void *user_ctx)
void fr_dl_dict_autofree(dl_t const *module, void *symbol, void *user_ctx)
int fr_dl_dict_autoload(dl_t const *module, void *symbol, void *user_ctx)
int fr_dl_dict_attr_autoload(dl_t const *module, void *symbol, void *user_ctx)
dl_loader_t * dl_loader_init(TALLOC_CTX *ctx, void *uctx, bool uctx_free, bool defer_symbol_init)
Initialise structures needed by the dynamic linker.
dl_t * dl_by_name(dl_loader_t *dl_loader, char const *name, void *uctx, bool uctx_free)
Search for a dl's shared object in various locations.
int dl_symbol_free_cb_register(dl_loader_t *dl_loader, unsigned int priority, char const *symbol, dl_unload_t func, void *uctx)
Register a callback to execute when a dl with a particular symbol is unloaded.
int dl_search_path_prepend(dl_loader_t *dl_loader, char const *lib_dir)
Append a new search path component to the library search path.
char const * dl_search_path(dl_loader_t *dl_loader)
Return current library path.
int dl_symbol_init_cb_register(dl_loader_t *dl_loader, unsigned int priority, char const *symbol, dl_onload_t func, void *uctx)
Register a callback to execute when a dl with a particular symbol is first loaded.
int dl_search_path_set(dl_loader_t *dl_loader, char const *lib_dir)
Set the current library path.
int dl_free(dl_t const *dl)
"free" a dl handle, possibly actually freeing it, and unloading the library
int dl_symbol_init(dl_loader_t *dl_loader, dl_t const *dl)
Walk over the registered init callbacks, searching for the symbols they depend on.
void * handle
Handle returned by dlopen.
void * uctx
API client's opaque data.
char const * name
Name of the module e.g. sql.
char const * dl_module_search_path(void)
static dl_module_t const * dl_module_root(dl_module_t const *child)
Find the module's shallowest parent, or the child if no parents are found.
dl_loader_t * dl_loader
A list of loaded libraries, and symbol to callback mappings.
static int _dl_module_loader_free(dl_module_loader_t *dl_module_l)
static int _dl_module_free(dl_module_t *dl_module)
Decrement the reference count of the dl, eventually freeing it.
fr_table_num_sorted_t const dl_module_type_prefix[]
Name prefixes matching the types of loadable module.
static void dl_module_unload_func(dl_t const *dl, UNUSED void *symbol, UNUSED void *ctx)
Call the unload() function in a module's exported structure.
static int8_t dl_module_cmp(void const *one, void const *two)
dl_loader_t * dl_loader_from_module_loader(dl_module_loader_t *dl_module_l)
static int dl_dict_autoload(dl_t const *module, void *symbol, void *user_ctx)
Wrapper to log errors.
fr_rb_tree_t * module_tree
Module's dl handles.
dl_module_loader_t * dl_module_loader_init(char const *lib_dir)
Initialise structures needed by the dynamic linker.
static int dl_module_onload_func(dl_t const *dl, UNUSED void *symbol, UNUSED void *ctx)
Call the load() function in a module's exported structure.
static char const * dl_module_root_prefix_str(dl_module_t const *module)
Return the prefix string for the deepest module.
pthread_mutex_t lock
Protects the module tree when multiple threads are loading modules simultaneously.
dl_module_t * dl_module_alloc(dl_module_t const *parent, char const *name, dl_module_type_t type)
Load a module library using dlopen() or return a previously loaded module from the cache.
static int dl_module_magic_verify(dl_module_common_t const *module)
Check if the magic number in the module matches the one in the library.
static int dl_dict_attr_autoload(dl_t const *module, void *symbol, void *user_ctx)
Wrapper to log errors.
static int dl_dict_enum_autoload(dl_t const *module, void *symbol, void *user_ctx)
Wrapper to log errors.
size_t dl_module_type_prefix_len
static dl_module_loader_t * dl_module_loader
int dl_module_free(dl_module_t *dl_module)
Free a dl_module (when there are no more references to it)
Wrapper struct around dl_loader_t.
dl_t *_CONST dl
Dynamic loader handle.
dl_module_common_t * exported
Symbol exported by the module, containing its public functions, name and behaviour control flags.
dl_module_t const *_CONST parent
of this module.
dl_module_type_t _CONST type
of this module.
@ DL_MODULE_TYPE_PROTO
Protocol module.
@ DL_MODULE_TYPE_SUBMODULE
Driver (or method in the case of EAP)
@ DL_MODULE_TYPE_MODULE
Standard loadable module.
@ DL_MODULE_TYPE_PROCESS
protocol processor.
#define DL_PRIORITY_BOOTSTRAP
Callback priority for bootstrap callback.
#define DL_PRIORITY_DICT_ATTR
Callback priority for attribute resolution.
#define DL_PRIORITY_DICT
Callback priorities.
dl_module_loader_t *_CONST loader
Loader that owns this dl.
#define DL_PRIORITY_LIB
Callback priority for library config.
#define DL_PRIORITY_DICT_ENUM
Callback priority for enum resolution.
unsigned int refs
Number of references to this module.
Fields common to all types of loadable modules.
void global_lib_autofree(UNUSED dl_t const *module, void *symbol, UNUSED void *user_ctx)
Callback for freeing of "lib" symbols.
int global_lib_auto_instantiate(UNUSED dl_t const *module, void *symbol, UNUSED void *user_ctx)
Callback for creation of "lib" symbols.
#define DEBUG_ENABLED4
True if global debug level 1-3 messages are enabled.
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
void * fr_rb_iter_init_inorder(fr_rb_iter_inorder_t *iter, fr_rb_tree_t *tree)
Initialise an in-order iterator.
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
#define fr_rb_talloc_alloc(_ctx, _type, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Iterator structure for in-order traversal of an rbtree.
The main red black tree structure.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_aka_sim_id_type_t type
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in a lexicographically sorted array of name to num mappings.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
static void talloc_bstr_tolower(char *str)
Convert a talloced string to lowercase.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
#define fr_strerror_const(_msg)
#define MAGIC_VERSION(_x)
#define RADIUSD_MAGIC_NUMBER