26 RCSID(
"$Id: 11671f5e962fdb53289587721defa3607be2b2a9 $")
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>
40 #define DL_INIT_CHECK fr_assert(dl_module_loader)
92 ret = strcmp(a->
dl->
name, b->dl->name);
120 PERROR(
"Initialisation failed for module \"%s\" - onload() returned %i",
165 dladdr(module, &dl_info);
170 ERROR(
"Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname);
172 ERROR(
"Application and rlm_%s magic number (prefix) mismatch."
173 " application: %x module: %x", module->name,
181 ERROR(
"Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname);
183 ERROR(
"Application and rlm_%s magic number (version) mismatch."
184 " application: %lx module: %lx", module->name,
192 ERROR(
"Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname);
194 ERROR(
"Application and rlm_%s magic number (commit) mismatch."
195 " application: %lx module: %lx", module->name,
240 if (!
inst)
return NULL;
259 if (!dl_inst)
return NULL;
261 if (!dl_inst->
parent)
return NULL;
286 ERROR(
"Failed resolving data %p, to dl_module_inst_t, refusing to free",
data);
320 if (!module->
common->inst_type) {
321 talloc_set_name(
data,
"%s_t", module->
dl->
name ? module->
dl->
name :
"config");
323 talloc_set_name_const(
data, module->
common->inst_type);
386 char *module_name = NULL;
395 parent->type,
"<INVALID>"),
403 if (!module_name)
return NULL;
405 for (p = module_name, q = p + talloc_array_length(p) - 1; p < q; p++) *p = tolower((
uint8_t) *p);
411 &(
dl_module_t){ .dl = &(dl_t){ .name = module_name }});
429 PERROR(
"Failed to link to module \"%s\"", module_name);
430 ERROR(
"Make sure it (and all its dependent libraries!) are in the search path"
431 " of your system's ld");
439 DEBUG3(
"%s loaded, checking if it's valid", module_name);
441 common = dlsym(
dl->
handle, module_name);
443 ERROR(
"Could not find \"%s\" symbol in module: %s", module_name, dlerror());
453 DEBUG3(
"%s validated. Handle address %p, symbol address %p", module_name,
dl, common);
456 PERROR(
"Failed calling initializers for module \"%s\"", module_name);
460 DEBUG2(
"Loaded module %s", module_name);
467 ERROR(
"Failed caching module \"%s\"", module_name);
497 talloc_free_children(dl_inst);
528 if (!sym_name)
return NULL;
589 if (name2)
return name2;
606 cf_log_err(dl_inst->
conf,
"Failed evaluating configuration for module \"%s\"",
624 WARN(
"Refusing to cleanup dl loader, the following module instances are still in use:");
642 PWARN(
"dl loader not freed");
648 WARN(
"This may appear as a leak in talloc memory reports");
674 if (ret < 0)
PERROR(
"Failed autoloading enum value for \"%s\"", module->
name);
686 if (ret < 0)
PERROR(
"Failed autoloading attribute for \"%s\"", module->
name);
698 if (ret < 0)
PERROR(
"Failed autoloading dictionary for \"%s\"", module->
name);
721 ERROR(
"Failed initialising uctx for dl_loader");
727 PERROR(
"Failed initialising dl_loader");
737 ERROR(
"Failed initialising dl->inst_data_tree");
744 ERROR(
"Failed initialising dl->module_tree");
750 ERROR(
"Failed registering load() callback");
756 ERROR(
"Failed registering unload() callback");
782 DEBUG4(
"Module linker search path(s)");
789 env = getenv(
"LD_LIBRARY_PATH");
791 DEBUG4(
"LD_LIBRARY_PATH : %s", env);
793 env = getenv(
"DYLD_LIBRARY_PATH");
795 DEBUG4(
"DYLB_LIBRARY_PATH : %s", env);
797 env = getenv(
"DYLD_FALLBACK_LIBRARY_PATH");
799 DEBUG4(
"DYLD_FALLBACK_LIBRARY_PATH : %s", env);
803 DEBUG4(
"Current directory : %s", env);
806 env = getenv(
"LD_LIBRARY_PATH");
808 DEBUG4(
"LD_LIBRARY_PATH : %s", env);
810 DEBUG4(
"Defaults : /lib:/usr/lib");
static int const char char buffer[256]
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#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.
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
#define cf_section_rules_push(_cs, _rule)
A section grouping multiple CONF_PAIR.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
#define cf_log_err(_cf, _fmt,...)
#define cf_data_add(_cf, _data, _name, _free)
#define cf_data_find(_cf, _type, _name)
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)
dl_module_inst_t * inst
Instance wrapper struct.
int dl_module_instance(TALLOC_CTX *ctx, dl_module_inst_t **out, dl_module_inst_t const *parent, dl_module_type_t type, char const *mod_name, char const *inst_name)
Load a module and parse its CONF_SECTION in one operation.
char const * dl_module_inst_name_from_conf(CONF_SECTION *conf)
Avoid boilerplate when setting the module instance name.
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.
char const * dl_module_instance_name_by_data(void const *data)
Lookup instance name via instance data.
static int8_t dl_module_cmp(void const *one, void const *two)
static _Thread_local dl_module_inst_cache_t dl_inst_cache
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.
static int _dl_module_instance_free(dl_module_inst_t *dl_inst)
Free a module instance, removing it from the instance tree.
static void dl_module_instance_data_alloc(dl_module_inst_t *dl_inst, dl_module_t const *module)
Allocate module instance data, and parse the module's configuration.
dl_module_inst_t const * dl_module_parent_instance(dl_module_inst_t const *child)
Lookup a module's parent.
void * dl_module_parent_data_by_child_data(void const *data)
A convenience function for returning a parent's private data.
dl_module_inst_t const * dl_module_instance_by_data(void const *data)
Lookup a dl_module_inst_t via instance data.
static int _dl_module_instance_data_free(void *data)
fr_rb_tree_t * module_tree
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.
fr_rb_tree_t * inst_data_tree
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.
dl_module_t const * dl_module(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.
void * dl_module_instance_symbol(dl_module_inst_t const *dl_inst, char const *sym_name)
Retrieve a public symbol from a module using dlsym.
static int dl_dict_attr_autoload(dl_t const *module, void *symbol, void *user_ctx)
Wrapper to log errors.
static int8_t dl_module_inst_data_cmp(void const *one, void const *two)
static void dl_module_detach_parent(dl_module_inst_t *dl_inst)
Detach the shallowest parent first.
static int dl_dict_enum_autoload(dl_t const *module, void *symbol, void *user_ctx)
Wrapper to log errors.
void * data
Module's data.
size_t dl_module_type_prefix_len
static dl_module_loader_t * dl_module_loader
dl_module_inst_t const * dl_module_instance_by_cs(CONF_SECTION const *cs)
Lookup a dl_module_inst_t via a config section.
int dl_module_conf_parse(dl_module_inst_t *dl_inst, CONF_SECTION *conf)
Make data to instance name resolution more efficient.
Wrapper struct around dl_loader_t.
dl_t *_CONST dl
Dynamic loader handle.
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.
dl_module_t const *_CONST module
Module.
#define DL_PRIORITY_BOOTSTRAP
Callback priority for bootstrap callback.
bool _CONST detached
Whether the detach function has been called.
#define DL_PRIORITY_DICT_ATTR
Callback priority for attribute resolution.
#define DL_PRIORITY_DICT
Callback priorities.
char const *_CONST name
Instance name.
void *_CONST data
Module instance's parsed configuration.
#define DL_PRIORITY_LIB
Callback priority for library config.
CONF_SECTION *_CONST conf
Module's instance configuration.
dl_module_common_t const *_CONST common
Symbol exported by the module, containing its public functions, name and behaviour control flags.
#define DL_PRIORITY_DICT_ENUM
Callback priority for enum resolution.
dl_module_inst_t const *_CONST parent
Parent module's instance (if any).
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.
static char const * mod_name(fr_listen_t *li)
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
Return how many nodes there are in a tree.
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
Remove node and free data (if a free function was specified)
void * fr_rb_iter_init_inorder(fr_rb_iter_inorder_t *iter, fr_rb_tree_t *tree)
Initialise an in-order iterator.
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
#define fr_rb_talloc_alloc(_ctx, _type, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
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)
eap_aka_sim_process_conf_t * inst
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_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
int talloc_decrease_ref_count(void const *ptr)
Decrease the reference count on a ptr.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
#define MAGIC_VERSION(_x)
#define RADIUSD_MAGIC_NUMBER
static size_t char ** out