26 RCSIDH(xlat_h,
"$Id: 273818188c22ecae2a0c0f8a7f706edfda6c1383 $")
53 #include <freeradius-devel/server/request.h>
57 #include <freeradius-devel/server/cf_util.h>
58 #include <freeradius-devel/server/signal.h>
59 #include <freeradius-devel/server/tmpl.h>
61 #include <freeradius-devel/util/heap.h>
62 #include <freeradius-devel/util/pair.h>
63 #include <freeradius-devel/util/sbuff.h>
64 #include <freeradius-devel/util/time.h>
65 #include <freeradius-devel/util/value.h>
67 #include <freeradius-devel/unlang/call_env.h>
68 #include <freeradius-devel/unlang/xlat_ctx.h>
166 #define XLAT_ARG_PARSER_TERMINATOR { .required = false, .concat = false, .single = false, .variadic = false, \
167 .type = FR_TYPE_NULL, .func = NULL, .uctx = NULL }
281 #define XLAT_ARGS_NEXT(_list, _prev, _curr) *(_curr) = likely(*(_prev) != NULL) ? fr_value_box_list_next(_list, *(_prev)) : NULL
283 #define XLAT_ARGS_1(_list, _a) \
284 *(_a) = fr_value_box_list_head(_list)
286 #define XLAT_ARGS_2(_list, _a, _b) \
288 *(_a) = fr_value_box_list_head(_list); \
289 XLAT_ARGS_NEXT(_list, _a, _b); \
292 #define XLAT_ARGS_3(_list, _a, _b, _c) \
294 *(_a) = fr_value_box_list_head(_list); \
295 XLAT_ARGS_NEXT(_list, _a, _b); \
296 XLAT_ARGS_NEXT(_list, _b, _c); \
299 #define XLAT_ARGS_4(_list, _a, _b, _c, _d) \
301 *(_a) = fr_value_box_list_head(_list); \
302 XLAT_ARGS_NEXT(_list, _a, _b); \
303 XLAT_ARGS_NEXT(_list, _b, _c); \
304 XLAT_ARGS_NEXT(_list, _c, _d); \
307 #define XLAT_ARGS_5(_list, _a, _b, _c, _d, _e) \
309 *(_a) = fr_value_box_list_head(_list); \
310 XLAT_ARGS_NEXT(_list, _a, _b); \
311 XLAT_ARGS_NEXT(_list, _b, _c); \
312 XLAT_ARGS_NEXT(_list, _c, _d); \
313 XLAT_ARGS_NEXT(_list, _d, _e); \
316 #define XLAT_ARGS_6(_list, _a, _b, _c, _d, _e, _f) \
318 *(_a) = fr_value_box_list_head(_list); \
319 XLAT_ARGS_NEXT(_list, _a, _b); \
320 XLAT_ARGS_NEXT(_list, _b, _c); \
321 XLAT_ARGS_NEXT(_list, _c, _d); \
322 XLAT_ARGS_NEXT(_list, _d, _e); \
323 XLAT_ARGS_NEXT(_list, _e, _f); \
326 #define XLAT_ARGS_7(_list, _a, _b, _c, _d, _e, _f, _g) \
328 *(_a) = fr_value_box_list_head(_list); \
329 XLAT_ARGS_NEXT(_list, _a, _b); \
330 XLAT_ARGS_NEXT(_list, _b, _c); \
331 XLAT_ARGS_NEXT(_list, _c, _d); \
332 XLAT_ARGS_NEXT(_list, _d, _e); \
333 XLAT_ARGS_NEXT(_list, _e, _f); \
334 XLAT_ARGS_NEXT(_list, _f, _g); \
337 #define XLAT_ARGS_8(_list, _a, _b, _c, _d, _e, _f, _g, _h) \
339 *(_a) = fr_value_box_list_head(_list); \
340 XLAT_ARGS_NEXT(_list, _a, _b); \
341 XLAT_ARGS_NEXT(_list, _b, _c); \
342 XLAT_ARGS_NEXT(_list, _c, _d); \
343 XLAT_ARGS_NEXT(_list, _d, _e); \
344 XLAT_ARGS_NEXT(_list, _e, _f); \
345 XLAT_ARGS_NEXT(_list, _f, _g); \
346 XLAT_ARGS_NEXT(_list, _g, _h); \
357 #define _XLAT_ARGS_X(XLAT_ARGS_N, _list, ...) XLAT_ARGS_N(_list, __VA_ARGS__)
365 #define XLAT_ARGS(_list, ...) _XLAT_ARGS_X(JOIN(XLAT_ARGS_, VA_NARG(__VA_ARGS__)), _list, __VA_ARGS__)
368 void const *escape_ctx)
389 fr_sbuff_parse_rules_t
const *p_rules,
tmpl_rules_t const *t_rules);
392 fr_sbuff_parse_rules_t
const *p_rules,
tmpl_rules_t const *t_rules);
396 fr_sbuff_parse_rules_t
const *p_rules,
tmpl_rules_t const *t_rules,
bool comma,
bool allow_attr);
399 fr_sbuff_parse_rules_t
const *p_rules,
tmpl_rules_t const *t_rules,
443 #define xlat_copy(_ctx, _out, _in) _xlat_copy(NDEBUG_LOCATION_EXP _ctx, _out, _in)
444 #ifdef WITH_VERIFY_PTR
448 # define XLAT_VERIFY(_node) xlat_exp_verify(_node)
449 # define XLAT_HEAD_VERIFY(_head) xlat_exp_head_verify(_head)
451 # define XLAT_VERIFY(_node)
452 # define XLAT_HEAD_VERIFY(_head)
490 CC_HINT(warn_unused_result);
494 CC_HINT(warn_unused_result);
498 CC_HINT(warn_unused_result);
static int const char * fmt
#define NDEBUG_LOCATION_ARGS
Pass caller information to the function.
Structure containing both a talloc pool, a list of parsed call_env_pairs.
fr_dcursor_eval_t void const * uctx
unsigned int fr_heap_index_t
Stores all information relating to an event list.
Temporary structure to hold arguments for module calls.
#define SBUFF_OUT_TALLOC_FUNC_NO_LEN_DEF(_func,...)
Similar to tmpl_rules_t, but used to specify parameters that may change during subsequent resolution ...
Optional arguments passed to vp_tmpl functions.
fr_aka_sim_id_type_t type
Stores an attribute, a value and various bits of other data.
An element in a lexicographically sorted array of name to num mappings.
static fr_event_list_t * el
bool xlat_needs_resolving(xlat_exp_head_t const *head)
Check to see if the expansion needs resolving.
fr_heap_index_t idx
Entry in heap of xlat instances.
tmpl_res_rules_t const * tr_rules
tmpl resolution rules.
fr_type_t type
Type to cast argument to.
tmpl_t * xlat_to_tmpl_attr(TALLOC_CTX *ctx, xlat_exp_head_t *xlat)
Try to convert an xlat to a tmpl for efficiency.
int(* xlat_thread_detach_t)(xlat_thread_inst_ctx_t const *xctx)
xlat thread detach callback
xlat_exp_t * node
Node this data relates to.
int unlang_xlat_eval(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, xlat_exp_head_t const *head)
Evaluate a "pure" (or not impure) xlat.
void * data
Thread specific instance data.
bool xlat_is_literal(xlat_exp_head_t const *head)
Check to see if the expansion consists entirely of value-box elements.
xlat_exp_t const * node
Node this data relates to.
int(* xlat_detach_t)(xlat_inst_ctx_t const *xctx)
xlat detach callback
int xlat_from_tmpl_attr(TALLOC_CTX *ctx, xlat_exp_head_t **head, tmpl_t **vpt_p)
Convert attr tmpl to an xlat for &attr[*].
void(* fr_unlang_xlat_fd_event_t)(xlat_ctx_t const *xctx, request_t *request, int fd)
A callback when the FD is ready for reading.
xlat_thread_inst_t * xlat_thread_instance_find(xlat_exp_t const *node)
Retrieve xlat/thread specific instance data.
fr_heap_index_t idx
Entry in heap of xlat thread instances.
int xlat_instance_register_func(xlat_exp_t *node)
Callback for creating "permanent" instance data for a xlat_exp_t.
uint64_t active_callers
total number of times we've been called
static fr_slen_t e_rules bool xlat_is_truthy(xlat_exp_head_t const *head, bool *out)
Allow callers to see if an xlat is truthy.
fr_slen_t xlat_print(fr_sbuff_t *in, xlat_exp_head_t const *node, fr_sbuff_escape_rules_t const *e_rules)
Reconstitute an xlat expression from its constituent nodes.
void * uctx
Argument to pass to escape callback.
void xlat_debug_head(xlat_exp_head_t const *head)
void xlat_thread_detach(void)
Destroy any thread specific xlat instances.
bool required
Argument must be present, and non-empty.
fr_table_num_sorted_t const xlat_action_table[]
bool xlat_impure_func(xlat_exp_head_t const *head)
xlat_escape_func_t func
Function to handle tainted values.
fr_event_list_t * el
Event list associated with this thread.
ssize_t(* xlat_escape_legacy_t)(request_t *request, char *out, size_t outlen, char const *in, void *arg)
ssize_t xlat_eval_compiled(char *out, size_t outlen, request_t *request, xlat_exp_head_t const *head, xlat_escape_legacy_t escape, void const *escape_ctx))
bool allow_unresolved
If false, all resolution steps must be completed.
fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, xlat_t const *xlat, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool comma, bool allow_attr)
Tokenize an xlat expansion into a series of XLAT_TYPE_CHILD arguments.
ssize_t xlat_eval(char *out, size_t outlen, request_t *request, char const *fmt, xlat_escape_legacy_t escape, void const *escape_ctx))
xlat_action_t xlat_transparent(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
bool xlat
it's an xlat wrapper
xlat_arg_parser_variadic_t
@ XLAT_ARG_VARIADIC_EMPTY_KEEP
Empty argument groups are left alone, and either passed through as empty groups or null boxes.
@ XLAT_ARG_VARIADIC_EMPTY_SQUASH
Empty argument groups are removed.
@ XLAT_ARG_VARIADIC_DISABLED
xlat_arg_parser_variadic_t variadic
All additional boxes should be processed using this definition.
int xlat_instantiate(void)
Call instantiation functions for all registered, "permanent" xlats.
int xlat_flatten_compiled_argv(TALLOC_CTX *ctx, xlat_exp_head_t ***argv, xlat_exp_head_t *head)
Turn xlat_tokenize_argv() into an argv[] array, and nuke the input list.
bool concat
Concat boxes together.
bool single
Argument must only contain a single box.
size_t xlat_action_table_len
int xlat_protocols_register(void)
Register xlats for any loaded dictionaries.
void xlat_debug_attr_list(request_t *request, fr_pair_list_t const *list)
bool always_escape
Pass all arguments to escape function not just tainted ones.
void(* xlat_func_signal_t)(xlat_ctx_t const *xctx, request_t *request, fr_signal_t action)
A callback when the request gets a fr_signal_t.
static fr_slen_t xlat_aprint(TALLOC_CTX *ctx, char **out, xlat_exp_head_t const *head, fr_sbuff_escape_rules_t const *e_rules) 1(xlat_print
ssize_t xlat_aeval_compiled(TALLOC_CTX *ctx, char **out, request_t *request, xlat_exp_head_t const *head, xlat_escape_legacy_t escape, void const *escape_ctx))
fr_value_box_safe_for_t safe_for
Escaped value to set for boxes processed by this escape function.
bool xlat_to_string(TALLOC_CTX *ctx, char **str, xlat_exp_head_t **head)
Convert an xlat node to an unescaped literal string and free the original node.
int xlat_global_init(void)
bool can_purify
if the xlat has a pure function with pure arguments.
@ XLAT_INPUT_ARGS
Ingests a number of arguments.
@ XLAT_INPUT_UNPROCESSED
No input argument processing.
int xlat_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Create thread specific instance tree and create thread instances.
int xlat_purify_op(TALLOC_CTX *ctx, xlat_exp_t **out, xlat_exp_t *lhs, fr_token_t op, xlat_exp_t *rhs)
int xlat_purify(xlat_exp_head_t *head, unlang_interpret_t *intp)
Purify an xlat.
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
void xlat_debug(xlat_exp_t const *node)
int _xlat_copy(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_exp_head_t *out, xlat_exp_head_t const *in)
fr_slen_t xlat_validate_function_args(xlat_exp_t *node)
void * data
xlat node specific instance data.
void xlat_debug_attr_vp(request_t *request, fr_pair_t *vp, tmpl_t const *vpt)
int unlang_xlat_eval_type(TALLOC_CTX *ctx, fr_value_box_t *out, fr_type_t type, fr_dict_attr_t const *enumv, request_t *request, xlat_exp_head_t const *head)
Evaluate a "pure" (or not impure) xlat.
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t callback, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
void xlat_instances_free(void)
Walk over all registered instance data and free them explicitly.
int unlang_xlat_push(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, request_t *request, xlat_exp_head_t const *head, bool top_frame)
Push a pre-compiled xlat onto the stack for evaluation.
bool pure
has no external side effects, true for BOX, LITERAL, and some functions
fr_slen_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, fr_value_box_safe_for_t literals_safe_for)
Tokenize an xlat expansion.
int xlat_aeval_compiled_argv(TALLOC_CTX *ctx, char ***argv, request_t *request, xlat_exp_head_t const *head, xlat_escape_legacy_t escape, void const *escape_ctx)
Synchronous compile xlat_tokenize_argv() into argv[] array.
bool needs_resolving
Needs pass2 resolution.
int(* xlat_thread_instantiate_t)(xlat_thread_inst_ctx_t const *xctx)
Allocate new thread instance data for an xlat instance.
void(* fr_unlang_xlat_timeout_t)(xlat_ctx_t const *xctx, request_t *request, fr_time_t fired)
A callback when the the timeout occurs.
int xlat_resolve(xlat_exp_head_t *head, xlat_res_rules_t const *xr_rules)
Walk over an xlat tree recursively, resolving any unresolved functions or references.
int unlang_xlat_timeout_add(request_t *request, fr_unlang_xlat_timeout_t callback, void const *rctx, fr_time_t when)
Add a timeout for an xlat handler.
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_PUSH_CHILD
A deeper level of nesting needs to be evaluated.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
call_env_t const * call_env
Per call environment.
bool constant
xlat is just tmpl_attr_tail_data, or XLAT_BOX
int(* xlat_escape_func_t)(request_t *request, fr_value_box_t *vb, void *uctx)
A function used to escape an argument passed to an xlat.
fr_slen_t xlat_tokenize_condition(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
fr_slen_t xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
bool impure_func
xlat contains an impure function
int xlat_instance_unregister_func(xlat_exp_t *node)
Remove a node from the list of xlat instance data.
ssize_t xlat_aeval(TALLOC_CTX *ctx, char **out, request_t *request, char const *fmt, xlat_escape_legacy_t escape, void const *escape_ctx))
void xlat_global_free(void)
int(* xlat_instantiate_t)(xlat_inst_ctx_t const *xctx)
Allocate new instance data for an xlat instance.
module_ctx_t const * mctx
A synthesised module calling ctx containing module global and thread instance data.
Definition for a single argument consumend by an xlat function.
Flags that control resolution and evaluation.
Instance data for an xlat expansion node.
Thread specific instance data for xlat expansion node.
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
static size_t char ** out
An xlat instantiation ctx.
An xlat thread instantiation ctx.