29 RCSID(
"$Id: 1559ecfc620ccfa03ede71b420dbc26701a7f13d $")
31 #include <freeradius-devel/server/cf_file.h>
32 #include <freeradius-devel/server/cf_util.h>
34 #include <freeradius-devel/server/global_lib.h>
35 #include <freeradius-devel/server/modpriv.h>
36 #include <freeradius-devel/server/module.h>
37 #include <freeradius-devel/server/module_rlm.h>
38 #include <freeradius-devel/server/pair.h>
39 #include <freeradius-devel/server/section.h>
40 #include <freeradius-devel/server/tmpl.h>
41 #include <freeradius-devel/server/virtual_servers.h>
43 #include <freeradius-devel/util/atexit.h>
44 #include <freeradius-devel/util/debug.h>
45 #include <freeradius-devel/util/dlist.h>
46 #include <freeradius-devel/util/rb.h>
47 #include <freeradius-devel/util/sbuff.h>
48 #include <freeradius-devel/util/strerror.h>
49 #include <freeradius-devel/util/talloc.h>
50 #include <freeradius-devel/util/token.h>
51 #include <freeradius-devel/util/value.h>
53 #include <freeradius-devel/unlang/compile.h>
55 #include <freeradius-devel/unlang/xlat_func.h>
56 #include <freeradius-devel/unlang/xlat_redundant.h>
121 char const *trigger_prefix,
124 char trigger_prefix_buff[128];
127 if (!trigger_prefix) {
129 trigger_prefix = trigger_prefix_buff;
132 handle =
exfile_init(ctx, max_entries, max_idle, locking);
133 if (!handle)
return NULL;
176 char const *inst_name;
178 #define FIND_SIBLING_CF_KEY "find_sibling"
199 cf_log_err(cp,
"Module reference loop found");
213 cf_log_err(cp,
"Unknown module instance \"%s\"", inst_name);
246 cf_log_err(cp,
"Referenced module is a rlm_%s instance, must be a rlm_%s instance",
267 "instance name. Pass a NULL `name` arg if this is required");
272 if ((
size_t)
snprintf(inst_name,
sizeof(inst_name),
"%s.%s", mctx->
mi->
name,
name) >=
sizeof(inst_name)) {
273 ERROR(
"%s: Instance name too long", __FUNCTION__);
280 if (
unlikely(x == NULL))
return NULL;
312 char const *log_prefix,
313 char const *trigger_prefix,
317 char log_prefix_buff[128];
318 char trigger_prefix_buff[128];
321 char const *cs_name1, *cs_name2;
325 #define parent_name(_x) cf_section_name(cf_item_to_section(cf_parent(_x)))
329 if (!cs_name2) cs_name2 = cs_name1;
331 if (!trigger_prefix) {
332 snprintf(trigger_prefix_buff,
sizeof(trigger_prefix_buff),
"modules.%s.pool", cs_name1);
333 trigger_prefix = trigger_prefix_buff;
337 snprintf(log_prefix_buff,
sizeof(log_prefix_buff),
"rlm_%s (%s)", cs_name1, cs_name2);
338 log_prefix = log_prefix_buff;
354 DEBUG4(
"%s: Using local pool section", log_prefix);
363 DEBUG4(
"%s: Adding pool section to config item \"%s\" to store pool references", log_prefix,
374 DEBUG4(
"%s: \"%s.pool\" section not found, using \"%s.pool\"", log_prefix,
388 DEBUG4(
"%s: No pool reference found for config item \"%s.pool\"", log_prefix,
parent_name(cs));
390 if (!pool)
return NULL;
395 ERROR(
"%s: Starting initial connections failed", log_prefix);
399 DEBUG4(
"%s: Adding pool reference %p to config item \"%s.pool\"", log_prefix, pool,
parent_name(cs));
405 DEBUG4(
"%s: Found pool reference %p in config item \"%s.pool\"", log_prefix, pool,
parent_name(cs));
413 DEBUG4(
"%s: Copying pool reference %p from config item \"%s.pool\" to config item \"%s.pool\"",
439 RDEBUG2(
"&control.%s already set. Not setting to %s",
vp->
da->name, enumv->
name);
496 #ifdef __clang_analyzer__
526 if (!mmb_p || !mmb_p[0].section)
goto next;
533 for (; mmb_p->
section; mmb_p++) {
538 name1, name2 ?
"." :
"", name2 ? name2 :
"");
599 mmc = mmc_out ? mmc_out : &mmc_tmp;
600 if (mmc_out) memset(mmc_out, 0,
sizeof(*mmc_out));
620 fr_sbuff_marker(&end, &our_name);
635 fr_sbuff_marker(&s_end, &our_name);
637 fr_sbuff_set_to_start(&our_name);
664 fr_sbuff_set_to_start(&our_name);
687 p = strrchr(elem1->start,
'.');
697 fr_sbuff_set_to_start(&our_name);
702 fr_sbuff_marker(&meth_start, &our_name);
711 fr_sbuff_marker(&meth_start, &our_name);
726 fr_sbuff_set_to_start(elem1);
733 if (slen == 0)
goto by_section;
747 .
name1 = elem1->start,
756 method.
name2 ?
"." :
"",
781 for (; *alt_p; alt_p++) {
793 fr_strerror_printf(
"Module \"%s\" has no method for section %s %s { ... }, i.e. %s%s%s",
798 section->
name2 ?
"." :
"",
818 if (!
inst)
return NULL;
854 if ((strcmp(
name,
"group") == 0) ||
855 (strcmp(
name,
"redundant") == 0) ||
856 (strcmp(
name,
"redundant-load-balance") == 0) ||
857 (strcmp(
name,
"load-balance") == 0)) {
860 cf_log_err(cs,
"Keyword module must have a second name");
869 cf_log_err(cs,
"Module names cannot be unlang keywords '%s'",
name);
878 ERROR(
"Duplicate module \"%s\" in file %s[%d] and file %s[%d]",
908 cf_log_perr(sub_ci,
"Failed resolving module reference '%s' in %s block",
933 if (!
inst)
return -1;
937 inst->all_same = all_same;
1006 bool in_order =
true;
1017 "First section identifier can't be NULL"))
return -1;
1019 "Section identifiers can't both be null"))
return -1;
1067 if (!last_binding ||
1109 static inline CC_HINT(always_inline)
1119 if (
unlikely(mi == NULL))
return NULL;
1132 char const *inst_name;
1142 cf_log_err(mod_conf,
"Module names cannot be unlang keywords '%s'",
name);
1163 if (strcmp(
name,
"template") == 0) {
1188 cf_log_perr(mod_conf,
"Failed parsing module config");
1230 WARN(
"Cannot find a \"modules\" section in the configuration file!");
1266 DEBUG2(
"#### Bootstrapping static modules ####");
1281 PERROR(
"Failed registering radmin commands for modules");
1290 DEBUG2(
"#### Bootstrapping dynamic modules ####");
1314 cf_log_err(policy_cs,
"Policy name '%s' cannot be an unlang keyword", name1);
1319 cf_log_err(policy_cs,
"Policies cannot have two names");
1324 if (!problemcs)
continue;
1326 cf_log_err(problemcs,
"Duplicate policy '%s' is forbidden.",
#define fr_atexit_global(_func, _uctx)
Add a free function to the global free list.
#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.
void const * uctx
User data accessible by the cf_parse_t func.
Defines a CONF_PAIR to C data type mapping.
Internal data that is associated with a configuration section.
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of 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.
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
CONF_SECTION * cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, char const *name1, char const *name2)
Return the next matching section.
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
char const * cf_section_name(CONF_SECTION const *cs)
Return name2 if set, else name1.
#define cf_item_add(_parent, _child)
#define cf_log_err(_cf, _fmt,...)
#define cf_section_foreach(_parent, _iter)
#define cf_data_add(_cf, _data, _name, _free)
#define cf_data_find(_cf, _type, _name)
#define cf_data_remove_by_data(_cf, _cd)
Remove an item from a parent.
#define cf_item_remove(_parent, _child)
#define cf_log_perr(_cf, _fmt,...)
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
#define cf_item_prev(_ci, _curr)
#define cf_log_debug(_cf, _fmt,...)
#define cf_item_next(_ci, _curr)
fr_command_register_hook_t fr_command_register_hook
bool unlang_compile_is_keyword(const char *name)
Check if name is an unlang keyword.
bool unlang_compile_actions(unlang_mod_actions_t *actions, CONF_SECTION *action_cs, bool module_retry)
fr_dcursor_eval_t void const * uctx
#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.
fr_value_box_t const * value
Enum value (what name maps to).
char const * name
Enum name.
Value of an enumerated attribute.
@ DL_MODULE_TYPE_MODULE
Standard loadable module.
unsigned int refs
Number of references to this module.
static void fr_dlist_sort(fr_dlist_head_t *list, fr_cmp_t cmp)
Sort a dlist using merge sort.
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
static unsigned int fr_dlist_num_elements(fr_dlist_head_t const *head)
Return the number of elements in the dlist.
static void * fr_dlist_tail(fr_dlist_head_t const *list_head)
Return the TAIL item of a list or NULL if the list is empty.
static void * fr_dlist_head(fr_dlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
#define fr_dlist_talloc_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
Head of a doubly linked list.
void exfile_enable_triggers(exfile_t *ef, CONF_SECTION *conf, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Enable triggers for an exfiles handle.
exfile_t * exfile_init(TALLOC_CTX *ctx, uint32_t max_entries, fr_time_delta_t max_idle, bool locking)
Initialize a way for multiple threads to log to one or more files.
int global_lib_instantiate(void)
Walk the tree of libraries and instantiate any which are pending.
Stores all information relating to an event list.
static char const * mod_name(fr_listen_t *li)
size_t fr_sbuff_out_bstrncpy_until(fr_sbuff_t *out, fr_sbuff_t *in, size_t len, fr_sbuff_term_t const *tt, fr_sbuff_unescape_rules_t const *u_rules)
fr_cmd_table_t module_cmd_list_table[]
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for instantiation calls.
static module_list_t * rlm_modules_dynamic
Runtime instantiated list.
static int _modules_rlm_free_atexit(UNUSED void *uctx)
void modules_rlm_thread_detach(void)
Frees thread-specific data for all registered backend modules.
int modules_rlm_bootstrap(CONF_SECTION *root)
Bootstrap modules and virtual modules.
static int module_rlm_bootstrap_virtual(CONF_SECTION *cs)
Create a virtual module.
static int8_t binding_name_cmp(void const *one, void const *two)
Compare the section names of two module_method_binding_t structures.
static module_method_binding_t const * module_binding_find(module_method_group_t const *mmg, section_name_t const *section)
Iterate over an array of named module methods, looking for matches.
module_instance_t * module_rlm_static_by_name(module_instance_t const *parent, char const *asked_name)
fr_slen_t module_rlm_by_name_and_method(TALLOC_CTX *ctx, module_method_call_t *mmc_out, virtual_server_t const *vs, section_name_t const *section, fr_sbuff_t *name, tmpl_rules_t const *t_rules)
Find an existing module instance and verify it implements the specified method.
char const * name
module name
fr_rb_node_t name_node
Entry in the name tree.
module_instance_t * module_rlm_dynamic_by_name(module_instance_t const *parent, char const *asked_name)
int module_rlm_sibling_section_find(CONF_SECTION **out, CONF_SECTION *module, char const *name)
Resolve polymorphic item's from a module's CONF_SECTION to a subsection in another module.
static int8_t module_rlm_virtual_name_cmp(void const *one, void const *two)
Compare virtual modules by name.
void module_rlm_list_debug(void)
Print information on all loaded modules.
static module_instance_t * module_rlm_instance_alloc(module_list_t *ml, module_instance_t const *parent, dl_module_type_t type, char const *mod_name, char const *inst_name, module_instance_state_t init_state)
Allocate a rlm module instance.
static int module_method_validate(module_instance_t *mi)
exfile_t * module_rlm_exfile_init(TALLOC_CTX *ctx, CONF_SECTION *module, uint32_t max_entries, fr_time_delta_t max_idle, bool locking, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Initialise a module specific exfile handle.
static fr_rb_tree_t * module_rlm_virtual_name_tree
Lookup virtual module by name.
int module_rlm_submodule_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic conf_parser_t func for loading drivers.
bool module_rlm_section_type_set(request_t *request, fr_dict_attr_t const *type_da, fr_dict_enum_value_t const *enumv)
Set the next section type if it's not already set.
CONF_SECTION * module_rlm_virtual_by_name(char const *asked_name)
static int module_conf_parse(module_list_t *ml, CONF_SECTION *mod_conf)
fr_pool_t * module_rlm_connection_pool_init(CONF_SECTION *module, void *opaque, fr_pool_connection_create_t c, fr_pool_connection_alive_t a, char const *log_prefix, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Initialise a module specific connection pool.
static void module_rlm_methods_to_strerror(module_method_group_t const *mmg)
Dump the available bindings for the module into the strerror stack.
int modules_rlm_free(void)
Cleanup all global structures.
#define FIND_SIBLING_CF_KEY
int modules_rlm_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Allocates thread-specific data for all registered backend modules.
static module_list_t * rlm_modules_static
Global module list for all backend modules.
int modules_rlm_instantiate(void)
Performs the instantiation phase for all backend modules.
int modules_rlm_init(void)
Initialise the module list structure.
static int module_method_group_validate(module_method_group_t *group)
CONF_SECTION * cs
CONF_SECTION where it is defined.
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
module_method_group_t method_group
named methods
module_instance_t * mi
The module instance that registered the xlat.
fr_dlist_head_t xlats
xlats registered to this module instance.
module_instance_t * mi
The process modules also push module calls onto the stack for execution.
xlat_t const * xlat
The xlat function.
tmpl_t * key
Dynamic key, only set for dynamic modules.
section_name_t asked
The actual <name1>.
module_method_binding_t mmb
Method we're calling.
static module_rlm_t * module_rlm_from_module(module_t *module)
module_rlm_t const * rlm
Cached module_rlm_t.
The output of module_rlm_by_name_and_method.
An xlat function registered to a module.
int fr_pool_start(fr_pool_t *pool)
void fr_pool_ref(fr_pool_t *pool)
Increment pool reference by one.
void fr_pool_enable_triggers(fr_pool_t *pool, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Enable triggers for a connection pool.
fr_pool_t * fr_pool_init(TALLOC_CTX *ctx, CONF_SECTION const *cs, void *opaque, fr_pool_connection_create_t c, fr_pool_connection_alive_t a, char const *log_prefix)
Create a new connection pool.
void *(* fr_pool_connection_create_t)(TALLOC_CTX *ctx, void *opaque, fr_time_delta_t timeout)
Create a new connection handle.
int(* fr_pool_connection_alive_t)(void *opaque, void *connection)
Check a connection handle is still viable.
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.
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
bool fr_rb_insert(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.
size_t fr_sbuff_adv_until(fr_sbuff_t *sbuff, size_t len, fr_sbuff_term_t const *tt, char escape_chr)
Wind position until we hit a character in the terminal set.
size_t fr_sbuff_out_bstrncpy(fr_sbuff_t *out, fr_sbuff_t *in, size_t len)
Copy as many bytes as possible from a sbuff to a sbuff.
#define fr_sbuff_set(_dst, _src)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define fr_sbuff_error(_sbuff_or_marker)
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_used(_sbuff_or_marker)
#define fr_sbuff_ahead(_sbuff_or_marker)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
Set of terminal elements.
int8_t section_name_cmp(void const *one, void const *two)
Compare two sections.
static int section_name2_match(section_name_t const *a, section_name_t const *b)
static int section_name_match(section_name_t const *a, section_name_t const *b)
static char const * section_name_str(char const *name)
Return a printable string for the section name.
static void section_name_dup(TALLOC_CTX *ctx, section_name_t *dst, section_name_t const *src)
char const * name2
Second section name. Usually a packet type like 'access-request', 'access-accept',...
char const * name1
First section name. Usually a verb like 'recv', 'send', etc...
char const * name
Instance name e.g. user_database.
@ MODULE_TYPE_RETRY
can handle retries
module_flags_t flags
Flags that control how a module starts up and how a module is called.
module_method_group_t * next
Next group in the list.
CONF_SECTION * conf
Module's instance configuration.
module_instance_state_t state
What's been done with this module so far.
unlang_mod_actions_t actions
default actions and retries.
dl_module_t * module
Dynamic loader handle.
bool validated
Set to true by module_method_group_validate.
#define MODULE_INSTANCE_LEN_MAX
The maximum size of a module instance.
fr_dlist_head_t same_name1
List of bindings with the same name1.
module_instance_state_t
What state the module instance is currently in.
@ MODULE_INSTANCE_INSTANTIATED
Module instance has been bootstrapped and instantiated.
void * uctx
Extra data passed to module_instance_alloc.
module_method_binding_t * bindings
named methods
section_name_t const * section
Identifier for a section.
module_t * exported
Public module structure.
Named methods exported by a module.
A group of methods exported by a module or added as an overlay.
Struct exported by a rlm_* module.
#define pair_update_control(_attr, _da)
Return or allocate a fr_pair_t in the control list.
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
Optional arguments passed to vp_tmpl functions.
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
void module_list_debug(module_list_t const *ml)
Print the contents of a module list.
module_list_type_t const module_list_type_thread_local
Callbacks for a thread local list.
module_instance_t * module_instance_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.
void module_list_mask_set(module_list_t *ml, module_instance_state_t mask)
Set a new bootstrap/instantiate state for a list.
fr_slen_t module_instance_name_from_conf(char const **name, CONF_SECTION *conf)
Avoid boilerplate when setting the module instance name.
void modules_thread_detach(module_list_t *ml)
Remove thread-specific data for a given module list.
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.
int modules_instantiate(module_list_t const *ml)
Completes instantiation of modules.
void module_instance_uctx_set(module_instance_t *mi, void *uctx)
Set the uctx pointer for a module instance.
module_list_type_t const module_list_type_global
Callbacks for a global module list.
int modules_bootstrap(module_list_t const *ml)
Bootstrap any modules which have not been bootstrapped already.
int module_instantiate(module_instance_t *instance)
Manually complete module setup by calling its instantiate function.
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.
int module_instance_conf_parse(module_instance_t *mi, CONF_SECTION *conf)
Covert a CONF_SECTION into parsed module instance data.
module_instance_t * module_instance_alloc(module_list_t *ml, module_instance_t const *parent, dl_module_type_t type, char const *mod_name, char const *inst_name, module_instance_state_t init_state)
Allocate a new module and add it to a module list for later bootstrap/instantiation.
module_list_t * module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type, char const *name, bool write_protect)
Allocate a new module list.
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
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
A time delta, a difference in time measured in nanoseconds.
static fr_event_list_t * el
xlat_action_t(* xlat_func_t)(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
xlat callback function
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
#define fr_strerror_const_push(_msg)
#define fr_strerror_const(_msg)
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
#define fr_box_strvalue_len(_val, _len)
static size_t char ** out
section_name_t const ** virtual_server_section_methods(virtual_server_t const *vs, section_name_t const *section)
Find the component for a section.
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
void xlat_mctx_set(xlat_t *x, module_inst_ctx_t const *mctx)
Associate a module calling ctx with the xlat.
int xlat_register_redundant(CONF_SECTION *cs)
Registers a redundant xlat.