29 RCSID(
"$Id: dc6e1b1564c23e459d78892db29760fa35067731 $")
31 #include <freeradius-devel/server/base.h>
32 #include <freeradius-devel/server/cf_file.h>
33 #include <freeradius-devel/server/modpriv.h>
34 #include <freeradius-devel/server/module_rlm.h>
35 #include <freeradius-devel/server/radmin.h>
36 #include <freeradius-devel/server/request_data.h>
37 #include <freeradius-devel/server/module.h>
38 #include <freeradius-devel/util/strerror.h>
39 #include <freeradius-devel/unlang/xlat_func.h>
84 .help =
"Show the status of a particular module.",
89 .parent =
"show module",
93 .help =
"Show configuration for a module",
99 .parent =
"set module",
102 .syntax =
"(alive|disallow|fail|reject|handled|invalid|notfound|noop|ok|updated)",
104 .help =
"Change module status to fixed value.",
115 .help =
"Show information about modules.",
122 .parent =
"show module",
125 .help =
"Show the list of modules loaded in the server.",
132 .help =
"Change module settings.",
153 fr_cmd_info_t *info,
int max_expansions,
char const **expansions)
158 if (info->
argc <= 0)
return 0;
166 if (
count >= max_expansions) {
183 fprintf(fp,
"\t%s\n", mi->
name);
194 fprintf(fp,
"alive\n");
208 if (strcmp(info->
argv[0],
"alive") == 0) {
215 fprintf(fp_err,
"Unknown status '%s'\n", info->
argv[0]);
240 if (ret != 0)
return 0;
255 int a_depth = 0, b_depth = 0;
263 for (dl_inst = a->
dl_inst; dl_inst; dl_inst = dl_inst->
parent) a_depth++;
264 for (dl_inst = b->
dl_inst; dl_inst; dl_inst = dl_inst->
parent) b_depth++;
266 ret =
CMP(a_depth, b_depth);
267 if (ret != 0)
return ret;
273 #ifdef STATIC_ANALYZER
279 if (ret != 0)
return ret;
341 cf_log_err(submodule_cs,
"Failed loading submodule");
346 cf_log_err(submodule_cs,
"Failed parsing submodule config");
369 char const *inst_name;
379 inst_name = asked_name;
380 if (inst_name[0] ==
'-') inst_name++;
384 .dl_inst = &(dl_module_inst_t){ .parent = parent ? parent->dl_inst : NULL },
387 if (!
inst)
return NULL;
444 .dl_inst = &(dl_module_inst_t){ .data = UNCONST(void *, data) },
446 if (!mi)
return NULL;
466 "mismatch between global module heap (%u entries) and thread local (%zu entries)",
470 fr_assert_msg(ti->
mi == mi,
"thread/module mismatch thread %s (%p), module %s (%p)",
489 if (!mi)
return NULL;
494 "mismatch between global module heap (%u entries) and thread local (%zu entries)",
498 fr_assert_msg(ti->
mi == mi,
"thread/module mismatch thread %s (%p), module %s (%p)",
541 DEBUG4(
"Worker cleaning up %s thread instance data (%p/%p)",
566 size_t i, len = talloc_array_length(til);
567 unsigned int found = 0;
569 for (i = 0; i < len; i++)
if (til[i]) found++;
573 "Thread local array has %u non-null elements remaining on exit. This is a leak",
600 TALLOC_CTX *our_ctx = ctx;
623 talloc_set_name(ti->
data,
"%s_%s_thread_t",
639 DEBUG4(
"Alloced %s thread instance data (%p/%p)", ti->
mi->
module->name, ti, ti->
data);
642 PERROR(
"Thread instantiation failed for module \"%s\"", mi->
name);
714 PERROR(
"Failed registering radmin commands for module %s", mi->
name);
764 DEBUG2(
"#### Instantiating %s modules ####", ml->
name);
835 DEBUG2(
"#### Bootstrapping %s modules ####", ml->
name);
868 if (!
parent->dl_inst->parent)
break;
910 ret = pthread_mutex_trylock(&mi->
mutex);
912 pthread_mutex_unlock(&mi->
mutex);
914 pthread_mutex_destroy(&mi->
mutex);
933 talloc_free_children(mi);
980 char *qual_inst_name = NULL;
993 ERROR(
"Module name too long");
1007 ERROR(
"Duplicate %s_%s instance \"%s\", previous instance defined at %s[%d]",
1015 ERROR(
"Duplicate %s_%s instance \"%s\"",
1028 mi->
name = qual_inst_name;
1037 ERROR(
"Missing public structure for \"%s\"", qual_inst_name);
1150 "Global module heap has %u elements remaining on exit. This is a leak",
#define fr_atexit_thread_local(_name, _free, _uctx)
#define fr_atexit_global_once(_init, _free, _uctx)
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#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_write(FILE *fp, CONF_SECTION *cs, int depth)
int cf_section_parse_pass2(void *base, CONF_SECTION *cs)
Fixup xlat expansions and attributes.
void const * uctx
User data accessible by the cf_parse_t func.
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
A section grouping multiple CONF_PAIR.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
#define cf_log_err(_cf, _fmt,...)
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
#define cf_log_debug(_cf, _fmt,...)
fr_command_register_hook_t fr_command_register_hook
bool fr_command_strncmp(const char *word, const char *name)
int argc
current argument count
char const * parent
e.g. "show module"
char const ** argv
text version of commands
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
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.
fr_table_num_sorted_t const dl_module_type_prefix[]
Name prefixes matching the types of loadable module.
dl_module_inst_t const * dl_module_parent_instance(dl_module_inst_t const *child)
Lookup a module's parent.
dl_module_loader_t * dl_module_loader_init(char const *lib_dir)
Initialise structures needed by the dynamic linker.
int dl_module_conf_parse(dl_module_inst_t *dl_inst, CONF_SECTION *conf)
Wrapper struct around dl_loader_t.
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.
void *_CONST data
Module instance's parsed configuration.
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.
dl_module_inst_t const *_CONST parent
Parent module's instance (if any).
int global_lib_init(void)
Initialise the global list of external libraries.
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
int fr_heap_extract(fr_heap_t **hp, void *data)
Remove a node from the heap.
#define fr_heap_alloc(_ctx, _cmp, _type, _field, _init)
Creates a heap that can be used with non-talloced elements.
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
static unsigned int fr_heap_num_elements(fr_heap_t *h)
Return the number of elements in the heap.
#define fr_heap_foreach(_heap, _type, _data)
Iterate over the contents of a heap.
Stores all information relating to an event list.
static char const * mod_name(fr_listen_t *li)
#define MODULE_INST_CTX(_dl_inst)
Wrapper to create a module_inst_ctx_t as a compound literal.
#define MODULE_THREAD_INST_CTX(_dl_inst, _thread, _el)
Wrapper to create a module_thread_inst_ctx_t as a compound literal.
Temporary structure to hold arguments for thread_instantiation calls.
void fr_rb_iter_delete_inorder(fr_rb_iter_inorder_t *iter)
Remove the current node from the 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_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
static bool fr_rb_node_inline_in_tree(fr_rb_node_t const *node)
Check to see if an item is in a tree by examining its inline fr_rb_node_t.
Iterator structure for in-order traversal of an rbtree.
fr_table_num_sorted_t const rcode_table[]
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_NOT_SET
Error resolving rcode (should not be returned by modules).
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_IN_STRCPY_RETURN(...)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
module_instance_t const * mi
As opposed to the thread local inst.
char const * name
Instance name e.g. user_database.
@ MODULE_TYPE_THREAD_UNSAFE
Module is not threadsafe.
fr_rb_node_t name_node
Entry in the name tree.
bool force
Force the module to return a specific code.
module_instance_state_t state
What's been done with this module so far.
module_thread_instantiate_t thread_instantiate
module_instantiate_t instantiate
fr_rb_tree_t * name_tree
Modules indexed by name.
dl_module_inst_t * dl_inst
Structure containing the module's instance data, configuration, and dl handle.
void * data
Thread specific instance data.
rlm_rcode_t code
Code module will return when 'force' has has been set to true.
fr_rb_tree_t * data_tree
Modules indexed by data.
fr_heap_index_t inst_idx
Entry in the bootstrap/instantiation heap.
@ MODULE_INSTANCE_INSTANTIATED
@ MODULE_INSTANCE_BOOTSTRAPPED
uint32_t number
Unique module number.
char const * thread_inst_type
module_instantiate_t bootstrap
fr_rb_node_t data_node
Entry in the data tree.
module_thread_detach_t thread_detach
module_t const * module
Public module structure.
uint32_t last_number
Last identifier assigned to a module instance.
module_list_t * ml
Module list this instance belongs to.
char const * name
Friendly list identifier.
fr_event_list_t * el
Event list associated with this thread.
pthread_mutex_t mutex
Used prevent multiple threads entering a thread unsafe module simultaneously.
Struct exported by a rlm_* module.
Per thread per instance data.
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
static int _module_list_free(module_list_t *ml)
Free all modules loaded by the server.
static int module_thread_instantiate(TALLOC_CTX *ctx, module_thread_instance_t **out, module_list_t const *ml, module_instance_t *mi, fr_event_list_t *el)
Allocate thread-local instance data for a module.
static int _module_instance_free(module_instance_t *mi)
Free module's instance data, and any xlats or paircmps.
module_instance_t * module_by_name(module_list_t const *ml, module_instance_t const *parent, char const *asked_name)
Find an existing module instance by its name and parent.
static fr_slen_t module_instance_name(TALLOC_CTX *ctx, char **out, module_list_t const *ml, module_instance_t const *parent, char const *inst_name)
Generate a module name from the module's name and its parents.
static int _module_thread_inst_list_free(void *tilp)
Free the thread local heap on exit.
module_thread_instance_t * module_thread(module_instance_t *mi)
Retrieve module/thread specific instance for a module.
static int cmd_show_module_status(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info)
static _Thread_local bool module_list_in_sync
Toggle used to determine if it's safe to use index based lookups.
static int8_t module_instance_data_cmp(void const *one, void const *two)
Compare module's by their private instance data.
static int8_t module_instance_name_cmp(void const *one, void const *two)
Compare module instances by parent and name.
int modules_thread_instantiate(TALLOC_CTX *ctx, module_list_t const *ml, fr_event_list_t *el)
Creates per-thread instance data for modules which need it.
static int cmd_show_module_list(FILE *fp, UNUSED FILE *fp_err, UNUSED void *uctx, UNUSED fr_cmd_info_t const *info)
static int module_name_tab_expand(UNUSED TALLOC_CTX *talloc_ctx, UNUSED void *uctx, fr_cmd_info_t *info, int max_expansions, char const **expansions)
int modules_instantiate(module_list_t const *ml)
Completes instantiation of modules.
static int8_t _module_instance_global_cmp(void const *one, void const *two)
Sort module instance data first by list then by number.
module_instance_t * module_alloc(module_list_t *ml, module_instance_t const *parent, dl_module_type_t type, char const *mod_name, char const *inst_name)
Allocate a new module and add it to a module list for later bootstrap/instantiation.
module_instance_t * module_by_data(module_list_t const *ml, void const *data)
Find an existing module instance by its private instance data.
static int cmd_set_module_status(UNUSED FILE *fp, FILE *fp_err, void *ctx, fr_cmd_info_t const *info)
int module_conf_parse(module_instance_t *mi, CONF_SECTION *mod_conf)
Parse the configuration associated with a module.
module_thread_instance_t * module_thread_by_data(module_list_t const *ml, void const *data)
Retrieve module/thread specific instance data for a module.
static int cmd_show_module_config(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info)
void modules_thread_detach(module_list_t const *ml)
Remove thread-specific data for a given module list.
void module_free(module_instance_t *mi)
Explicitly free a module if a fatal error occurs during bootstrap.
static fr_heap_t * module_global_inst_list
Heap of all lists/modules used to get a common index with module_thread_inst_list.
static _Thread_local module_thread_instance_t ** module_thread_inst_list
An array of thread-local module lists.
static int _module_thread_inst_free(module_thread_instance_t *ti)
static dl_module_loader_t * dl_modules
dl module tracking
fr_cmd_table_t module_cmd_list_table[]
static int _module_global_list_init(void *uctx)
module_instance_t * module_root(module_instance_t const *child)
Find the module's shallowest parent.
int modules_bootstrap(module_list_t const *ml)
Bootstrap any modules which have not been bootstrapped already.
fr_cmd_table_t module_cmd_table[]
int module_instantiate(module_instance_t *instance)
Manually complete module setup by calling its instantiate function.
static int _module_global_list_free(UNUSED void *uctx)
int module_submodule_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic callback for conf_parser_t to load a submodule.
module_instance_t * module_parent(module_instance_t const *child)
Find the module's parent (if any)
module_list_t * module_list_alloc(TALLOC_CTX *ctx, char const *name)
Allocate a new module list.
int module_bootstrap(module_instance_t *mi)
Manually complete module bootstrap by calling its instantiate function.
if(!subtype_vp) goto fail
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
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
#define talloc_get_type_abort_const
static fr_event_list_t * el
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
static size_t char ** out
void xlat_func_unregister(char const *name)
Unregister an xlat function.
void xlat_func_unregister_module(dl_module_inst_t const *inst)