26 RCSID(
"$Id: efc200b7a8b88541760d2370d0ec7d3a3b790ca1 $")
28 #include <freeradius-devel/unlang/interpret.h>
29 #include <freeradius-devel/unlang/xlat_redundant.h>
30 #include <freeradius-devel/unlang/xlat_func.h>
31 #include <freeradius-devel/unlang/xlat_priv.h>
32 #include <freeradius-devel/util/rand.h>
201 node->call.func = func;
226 unsigned int num = 0;
242 switch (xctx->
ex->call.input_type) {
248 PERROR(
"Expansion function \"%s\" takes defined arguments and should "
249 "be called using %%(func:args) syntax",
250 xctx->
ex->call.func->name);
258 PERROR(
"Expansion function \"%s\" should be called using %%{func:arg} syntax",
259 xctx->
ex->call.func->name);
279 cf_log_err(xr->
cs,
"Expansion functions \"%s\" and \"%s\" use different argument styles "
280 "cannot be used in the same redundant section", first->
func->
name, xrf->func->name);
296 switch (xrf->func->input_type) {
302 PERROR(
"Invalid arguments for redundant expansion function \"%s\"",
310 PERROR(
"Invalid arguments for redundant expansion function \"%s\"",
325 PERROR(
"Failed bootstrapping function \"%s\"",
370 static size_t xlat_redundant_type_table_len =
NUM_ELEMENTS(xlat_redundant_type_table);
372 char const *name1, *name2;
376 bool can_be_pure =
false;
389 cf_log_err(cs,
"Invalid redundant section verb \"%s\"", name1);
407 cf_log_err(cs,
"An expansion is already registered for this name");
427 char const *mod_func_name;
442 mod_func =
xlat_func_find(mod_func_name, talloc_array_length(mod_func_name) - 1);
467 xrf->
func = mod_func;
489 ERROR(
"Registering xlat for %s section failed",
#define L(_str)
Helper for initialising arrays of string literals.
Common header for all CONF_* types.
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.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
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_item_next(_ci, _prev)
#define fr_dlist_foreach(_list_head, _type, _iter)
Iterate over the contents of a list.
static void fr_dlist_talloc_free(fr_dlist_head_t *head)
Free all items in a doubly linked list (with talloc)
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_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.
Entry in a doubly linked list.
static xlat_action_t xlat_redundant(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
xlat "redundant", "load-balance" and "redundant-load-balance" processing
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
uint32_t fr_rand(void)
Return a 32-bit random number.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
#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.
An element in a lexicographically sorted array of name to num mappings.
#define talloc_get_type_abort_const
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t resume, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
int unlang_xlat_push(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, request_t *request, xlat_exp_head_t const *xlat, bool top_frame)
Push a pre-compiled xlat onto the stack for evaluation.
fr_type_t type
Type to cast argument to.
int xlat_validate_function_args(xlat_exp_t *node)
#define xlat_copy(_ctx, _out, _in)
bool can_purify
if the xlat has a pure function with pure arguments.
@ XLAT_INPUT_MONO
Ingests a single argument.
@ XLAT_INPUT_ARGS
Ingests a number of arguments.
@ XLAT_INPUT_UNPROCESSED
No input argument processing.
int xlat_validate_function_mono(xlat_exp_t *node)
bool pure
has no external side effects, true for BOX, LITERAL, and some functions
#define XLAT_ARG_PARSER_TERMINATOR
int xlat_finalize(xlat_exp_head_t *head, fr_event_list_t *runtime_el)
Bootstrap static xlats, or instantiate ephemeral ones.
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_YIELD
An xlat function pushed a resume frame onto the stack.
@ XLAT_ACTION_PUSH_UNLANG
An xlat function pushed an unlang frame onto the unlang stack.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumend by an xlat function.
static size_t char ** out
void * rctx
Resume context.
void * inst
xlat instance data to populate.
void const * inst
xlat instance data.
xlat_exp_t * ex
Tokenized expression to use in expansion.
void * uctx
Passed to the registration function.
An xlat instantiation ctx.
void xlat_func_flags_set(xlat_t *x, xlat_func_flags_t flags)
Specify flags that alter the xlat's behaviour.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
xlat_t * xlat_func_find(char const *in, ssize_t inlen)
#define xlat_func_instantiate_set(_xlat, _instantiate, _inst_struct, _detach, _uctx)
Set a callback for global instantiation of xlat functions.
char const * name
Name of xlat function.
#define xlat_exp_head_alloc(_ctx)
xlat_flags_t flags
Flags that control resolution and evaluation.
fr_type_t return_type
Function is guaranteed to return one or more boxes of this type.
xlat_arg_parser_t const * args
Definition of args consumed.
static void xlat_flags_merge(xlat_flags_t *parent, xlat_flags_t const *child)
Merge flags from child to parent.
xlat_input_type_t input_type
Type of input used.
#define xlat_exp_alloc(_ctx, _type, _in, _inlen)
xlat_flags_t flags
various flags
static int xlat_exp_insert_tail(xlat_exp_head_t *head, xlat_exp_t *node)
static xlat_action_t xlat_load_balance_resume(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
Pass back the result from a single redundant child call.
xlat_redundant_t * xr
Information about the redundant xlat.
static xlat_arg_parser_t const xlat_redundant_args[]
bool last_success
Did the last call succeed?
fr_dlist_head_t funcs
List of redundant xlat functions.
fr_dlist_t entry
Entry in the redundant function list.
xlat_exp_head_t ** first
First function called.
static xlat_exp_t * xlat_exp_func_alloc(TALLOC_CTX *ctx, xlat_t *func, xlat_exp_head_t const *args)
Allocate an xlat node to call an xlat function.
xlat_redundant_type_t type
Type of redundant xlat expression.
xlat_exp_head_t ** current
Last function called, used for redundant xlats.
xlat_exp_head_t ** ex
Array of xlat expressions created by tokenizing the arguments to the redundant xlat,...
static int xlat_redundant_instantiate(xlat_inst_ctx_t const *xctx)
Allocate additional nodes for evaluation.
int xlat_register_redundant(CONF_SECTION *cs)
Registers a redundant xlat.
xlat_t * func
Resolved xlat function.
CONF_SECTION * cs
That this redundant xlat list was created from.
@ XLAT_REDUNDANT_INVALID
Not a valid redundant type.
@ XLAT_REDUNDANT
Use the first xlat function first, then go through in sequence, using the next function after each fa...
@ XLAT_LOAD_BALANCE
Pick a random xlat, and if that fails then the call as a whole fails.
@ XLAT_REDUNDANT_LOAD_BALANCE
Pick a random xlat to start, then fail between the other xlats in the redundant group.
static xlat_action_t xlat_redundant_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
Pass back the result from a single redundant child call.