27RCSID(
"$Id: b413695a785a1a1b2b1aba1854533d75a3df29c3 $")
29#include <freeradius-devel/server/base.h>
30#include <freeradius-devel/unlang/xlat.h>
31#include <freeradius-devel/unlang/xlat_priv.h>
32#include <freeradius-devel/util/debug.h>
33#include <freeradius-devel/util/types.h>
34#include <freeradius-devel/util/sbuff.h>
35#include <freeradius-devel/util/value.h>
37#include <freeradius-devel/unlang/unlang_priv.h>
139 if (!da_p)
return NULL;
157 switch (node->
type) {
185 bool first_done =
false;
198 if ((first_done) && (node->call.func->input_type ==
XLAT_INPUT_ARGS)) {
237 RDEBUG2(
"| %%%s(%pM)", node->call.func->name,
args);
244 RERROR(
"Failed printing expansion");
298#define ESCAPE(_arg, _vb, _arg_num) \
300 if ((_arg)->func && (!(_vb)->safe_for || !fr_value_box_is_safe_for((_vb), (_arg)->safe_for) || (_arg)->always_escape)) { \
301 if ((_arg)->func(request, _vb, (_arg)->uctx) < 0) { \
302 RPEDEBUG("Function \"%s\" failed escaping argument %u", name, _arg_num); \
303 return XLAT_ACTION_FAIL; \
305 fr_value_box_mark_safe_for((_vb), (_arg)->safe_for); \
309 if (fr_value_box_list_empty(list)) {
311 REDEBUG(
"Function \"%s\" is missing required argument %u",
name, arg_num);
317 vb = fr_value_box_list_head(list);
325 do ESCAPE(arg, vb, arg_num);
while ((vb = fr_value_box_list_next(list, vb)));
327 vb = fr_value_box_list_head(list);
337 fr_assert(fr_value_box_list_num_elements(list) <= 1);
347 if (fr_value_box_list_num_elements(list) > 1) {
348 RPEDEBUG(
"Function \"%s\" was provided an incorrect number of values at argument %u, "
349 "expected %s got %u",
352 fr_value_box_list_num_elements(list));
361 arg->
type, NULL) < 0) {
377 if (vb->type == arg->
type)
continue;
379 arg->
type, NULL) < 0)
goto cast_error;
380 }
while ((vb = fr_value_box_list_next(list, vb)));
385 }
else if (arg->
func) {
386 do ESCAPE(arg, vb, arg_num);
while ((vb = fr_value_box_list_next(list, vb)));
408static inline CC_HINT(always_inline)
424 switch (func->input_type) {
432 vb = fr_value_box_list_head(list);
443 REDEBUG(
"Function \"%s\" is missing required argument %u",
444 func->name, (
unsigned int)((arg_p - func->args) + 1));
465 next = fr_value_box_list_next(list, vb);
467 (
unsigned int)((arg_p - func->args) + 1));
473 if (fr_value_box_list_empty(&vb->vb_group)) {
479 fr_value_box_list_talloc_free_head(list);
512 fr_value_box_list_talloc_free_head(list);
542 fr_value_box_list_replace(list, vb,
head);
570static inline CC_HINT(
nonnull(1,2,3))
573 unsigned int count = 0;
583 REDEBUG(
"%s return type registered as %s, but %s expansion produced data",
593 if (pos->type != func->return_type) {
594 REDEBUG(
"%s returned invalid result type at index %u. Expected type %s, got type %s",
602 }
while ((pos = fr_value_box_list_next(returned, pos)));
618static inline CC_HINT(always_inline)
642 value->datum.uint32 = request->packet->id;
647 value->datum.uint64 = request->number;
652 value->datum.uint64 = request->seq_start;
688 value->datum.uint8 = ts.tm_mday;
704 value->datum.uint8 = ts.tm_sec;
711 value->datum.uint8 = ts.tm_min;
718 value->datum.uint8 = ts.tm_hour;
727 value->datum.uint64 = (uint64_t ) now;
734 value->datum.uint8 = ts.tm_mon + 1;
748 strftime(
buffer,
sizeof(
buffer),
"%Y-%m-%d %H:%M:%S", &ts);
771 if (!
gmtime_r(&now, &ts))
goto error;
773 if (!(len = strftime(
buffer,
sizeof(
buffer) - 1,
"%Y-%m-%dT%H:%M:%S", &ts))) {
774 REDEBUG(
"Failed converting packet timestamp to gmtime: Buffer full");
792 value->datum.int16 = ts.tm_year + 1900;
796 fr_assert_fail(
"%%%c is not a valid one letter expansion", letter);
800 fr_value_box_list_insert_tail(
out,
value);
821 fr_value_box_list_move((fr_value_box_list_t *)
out->dlist, &rctx->
list);
841 signal(
XLAT_CTX(exp->call.inst, t->
data, t->
mctx, NULL, rctx), request, action);
873 fr_value_box_list_t *result,
xlat_func_t resume,
void *rctx)
887 xa = resume(ctx,
out,
XLAT_CTX(NULL, NULL, NULL, NULL, rctx), request, result);
891 xa = resume(ctx,
out,
XLAT_CTX(node->call.inst->data, t->
data, t->
mctx, NULL, rctx), request, result);
894 RDEBUG2(
"| %%%s(...)", node->call.func->name);
906 if (node->call.func) {
947 void *env_data, fr_value_box_list_t *result)
953 switch (node->
type) {
958 fr_value_box_list_t result_copy;
963 XLAT_DEBUG(
"** [%i] %s(func-async) - %%%s(%pM)",
974 fr_value_box_list_init(&result_copy);
983 fr_value_box_list_talloc_free(&result_copy);
988 xa = node->call.func->func(ctx,
out,
998 fr_value_box_list_talloc_free(&result_copy);
1026 (fr_value_box_list_t *)
out->dlist,
1051 if (!fr_value_box_list_empty(result)) {
1053 fr_value_box_list_move(&arg->vb_group, result);
1069 fr_value_box_list_talloc_free(result);
1077 fr_value_box_list_move((fr_value_box_list_t *)
out->dlist, result);
1124 fr_value_box_list_t result;
1127 fr_value_box_list_init(&result);
1140 fr_assert(fr_value_box_list_num_elements(&result) == 0);
1142 switch (node->
type) {
1171 fr_value_box_list_talloc_free(&result);
1176 fr_value_box_list_move((fr_value_box_list_t *)
out->dlist, &result);
1187 fr_value_box_list_insert_tail(&result,
value);
1194 fr_value_box_list_move((fr_value_box_list_t *)
out->dlist, &result);
1198 if (node->
fmt[0] ==
'&') {
1207 if (
tmpl_eval_pair(ctx, &result, request, node->vpt) < 0)
goto fail;
1216 fr_value_box_list_init(&rctx->
list);
1224 false, &rctx->
status)) < 0)
goto fail;
1243 fr_value_box_list_move((fr_value_box_list_t *)
out->dlist, &result);
1252 xa = node->call.func->func(ctx,
out,
1253 XLAT_CTX(node->call.func->uctx, NULL, NULL, NULL, NULL),
1270 *child = node->call.args;
1293 if (regex_request_to_sub(ctx, &str, request, node->regex_index) < 0) {
1314 *child = node->group;
1340 fr_value_box_list_t result;
1342 TALLOC_CTX *pool = talloc_new(NULL);
1350 fr_value_box_list_init(&result);
1372 if (!
success)
goto eval_failed;
1374 if (!fr_value_box_list_empty(&result)) {
1381 while ((vb = fr_value_box_list_next(&result, vb))) {
1382 fr_value_box_entry_t entry;
1383 size_t len, real_len;
1386 if (!vb->tainted)
continue;
1389 RPEDEBUG(
"Failed casting result to string");
1395 len = vb->vb_length * 3;
1396 MEM(escaped = talloc_array(pool,
char, len));
1397 real_len = escape(request, escaped, len, vb->vb_strvalue,
UNCONST(
void *, escape_ctx));
1420 return talloc_array_length(str) - 1;
1460 if ((
size_t)slen >= outlen) {
1469 (*out)[slen] =
'\0';
1488static CC_HINT(
nonnull (2, 4, 5))
1505 .dict_def = request->dict,
1517 *
out = talloc_zero_array(ctx,
char, 1);
1543 return _xlat_eval(request, &
out, outlen, request,
fmt, escape, escape_ctx);
1600 MEM(my_argv = talloc_zero_array(ctx,
char *,
count + 1));
1609 slen =
_xlat_eval_compiled(my_argv, &my_argv[i], 0, request, node->group, escape, escape_ctx);
1610 if (slen < 0)
return -i;
1641 my_argv[i++] = talloc_steal(my_argv, node->group);
1644 fr_value_box_list_talloc_free((fr_value_box_list_t *)&
head->dlist);
1667 switch (node->type){
1676 if (ret < 0)
return ret;
1680 ret = walker(node, uctx);
1681 if (ret < 0)
return ret;
1688 if (ret < 0)
return ret;
1692 ret = walker(node, uctx);
1693 if (ret < 0)
return ret;
1699 ret = walker(node, uctx);
1700 if (ret < 0)
return ret;
1701 if (ret > 0)
continue;
1708 if (ret < 0)
return ret;
1712 if (!
type || (
type & node->type)) {
1713 ret = walker(node, uctx);
1714 if (ret < 0)
return ret;
1735 PERROR(
"%s", __FUNCTION__);
1740 PERROR(
"%s", __FUNCTION__);
static int const char char buffer[256]
static int const char * fmt
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define L(_str)
Helper for initialising arrays of string literals.
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
static void * fr_dcursor_tail(fr_dcursor_t *cursor)
Wind cursor to the tail item in the list.
static int fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
Insert directly after the current item.
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
#define fr_dict_autofree(_to_free)
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
#define fr_dict_autoload(_to_load)
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
#define EXEC_TIMEOUT
Default wait time for exec calls (in seconds).
int unlang_interpret_stack_depth(request_t *request)
Return the depth of the request's stack.
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
rlm_rcode_t unlang_interpret_synchronous(fr_event_list_t *el, request_t *request)
Execute an unlang section synchronously.
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
#define RPEDEBUG(fmt,...)
#define RINDENT()
Indent R* messages by one level.
size_t(* xlat_escape_legacy_t)(request_t *request, char *out, size_t outlen, char const *in, void *arg)
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_GROUP
A grouping of other attributes.
struct tm * gmtime_r(time_t const *l_clock, struct tm *result)
struct tm * localtime_r(time_t const *l_clock, struct tm *result)
#define RDEBUG_ENABLED2()
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_REJECT
Immediately reject the request.
fr_dict_attr_t const * request_attr_request
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
ssize_t fr_sbuff_in_sprintf(fr_sbuff_t *sbuff, char const *fmt,...)
Print using a fmt string to an sbuff.
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define fr_sbuff_set(_dst, _src)
#define FR_SBUFF_IN(_start, _len_or_end)
#define FR_SBUFF_IN_SPRINTF_RETURN(...)
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
#define tmpl_is_xlat(vpt)
#define tmpl_value(_tmpl)
#define tmpl_is_attr(vpt)
#define tmpl_is_exec(vpt)
int tmpl_eval_cast_in_place(fr_value_box_list_t *out, request_t *request, tmpl_t const *vpt)
Casts a value or list of values according to the tmpl.
int tmpl_eval_pair(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *vpt)
Gets the value of a real or virtual attribute.
#define tmpl_is_data(vpt)
#define tmpl_value_type(_tmpl)
Optional arguments passed to vp_tmpl functions.
fr_signal_t
Signals that can be generated/processed by request signal handlers.
static char buff[sizeof("18446744073709551615")+3]
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
fr_aka_sim_id_type_t type
#define fr_time()
Allow us to arbitrarily manipulate time.
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.
An element in a lexicographically sorted array of name to num mappings.
An element in an arbitrarily ordered array of name to ptr mappings.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
static int64_t fr_time_to_sec(fr_time_t when)
Convert an fr_time_t (internal time) to number of sec since the unix epoch (wallclock time)
static int64_t fr_time_to_msec(fr_time_t when)
Convert an fr_time_t (internal time) to number of msec since the unix epoch (wallclock time)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
static int64_t fr_time_to_usec(fr_time_t when)
Convert an fr_time_t (internal time) to number of usec since the unix epoch (wallclock time)
int unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *tmpl, unlang_tmpl_args_t *args)
Push a tmpl onto the stack for evaluation.
#define TMPL_ARGS_EXEC(_env, _timeout, _stdout_on_error, _status_out)
Create a temporary argument structure for evaluating an exec type tmpl.
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.
void * data
Thread specific instance data.
xlat_thread_inst_t * xlat_thread_instance_find(xlat_exp_t const *node)
Retrieve xlat/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.
bool required
Argument must be present, and non-empty.
xlat_escape_func_t func
Function to handle tainted values.
@ 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.
bool concat
Concat boxes together.
bool single
Argument must only contain a single box.
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.
@ XLAT_INPUT_ARGS
Ingests a number of arguments.
@ XLAT_INPUT_UNPROCESSED
No input argument processing.
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
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.
@ 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.
bool constant
xlat is just tmpl_attr_tail_data, or XLAT_BOX
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.
Thread specific instance data for xlat expansion node.
char const * fr_strerror(void)
Get the last library error.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
#define fr_type_is_void(_x)
#define fr_type_is_null(_x)
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
char * fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim, fr_sbuff_escape_rules_t const *e_rules)
Concatenate the string representations of a list of value boxes together.
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.
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
int fr_value_box_list_acopy(TALLOC_CTX *ctx, fr_value_box_list_t *out, fr_value_box_list_t const *in)
Do a full copy of a list of value boxes.
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
int fr_value_box_bstrdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a talloced buffer containing a nul terminated string to a box, but don't copy it.
int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx, fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type, fr_value_box_list_action_t proc_action, bool flatten, size_t max_size)
Concatenate a list of value boxes.
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
#define fr_value_box_mark_safe_for(_box, _safe_for)
#define fr_box_strvalue_buffer(_val)
#define VALUE_BOX_VERIFY(_x)
#define VALUE_BOX_LIST_VERIFY(_x)
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
static size_t char ** out
void * rctx
Resume context.
#define XLAT_CTX(_inst, _thread, _mctx, _env_data, _rctx)
Wrapper to create a xlat_ctx_t as a compound literal.
ssize_t xlat_eval_compiled(char *out, size_t outlen, request_t *request, xlat_exp_head_t const *xlat, xlat_escape_legacy_t escape, void const *escape_ctx)
static size_t xlat_time_precision_table_len
static fr_dict_attr_t const * attr_cast_time_res_week
static fr_table_ptr_ordered_t const xlat_time_precision_table[]
static fr_slen_t xlat_fmt_print(fr_sbuff_t *out, xlat_exp_t const *node)
Reconstruct the original expansion string from an xlat tree.
static void xlat_debug_log_expansion(request_t *request, xlat_exp_t const *node, fr_value_box_list_t const *args, UNUSED int line)
Output what we're currently expanding.
xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_exp_head_t const **child, request_t *request, xlat_exp_head_t const *head, xlat_exp_t const **in, void *env_data, fr_value_box_list_t *result)
Process the result of a previous nested expansion.
void xlat_signal(xlat_func_signal_t signal, xlat_exp_t const *exp, request_t *request, void *rctx, fr_signal_t action)
Signal an xlat function.
fr_dict_attr_t const * xlat_time_res_attr(char const *res)
static void xlat_debug_log_result(request_t *request, xlat_exp_t const *node, fr_value_box_t const *result)
Output the result of an expansion.
fr_table_num_sorted_t const xlat_action_table[]
xlat_action_t xlat_frame_eval_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_exp_head_t const **child, request_t *request, xlat_exp_head_t const *head, xlat_exp_t const **in, fr_value_box_list_t *result, xlat_func_t resume, void *rctx)
Call an xlat's resumption method.
static fr_dict_attr_t const * attr_cast_time_res_year
static fr_dict_t const * dict_freeradius
static fr_dict_attr_t const * attr_cast_time_res_nsec
static xlat_action_t xlat_eval_one_letter(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, char letter)
One letter expansions.
static fr_dict_attr_t const * attr_cast_time_res_month
static fr_dict_attr_t const * attr_cast_time_res_usec
fr_dict_attr_t const * attr_expr_bool_enum
static fr_dict_attr_t const * attr_cast_time_res_csec
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.
static xlat_action_t xlat_process_args(TALLOC_CTX *ctx, fr_value_box_list_t *list, request_t *request, xlat_t const *func)
Process list of boxed values provided as input to an xlat.
size_t xlat_action_table_len
static ssize_t _xlat_eval(TALLOC_CTX *ctx, char **out, size_t outlen, request_t *request, char const *fmt, xlat_escape_legacy_t escape, void const *escape_ctx)
Replace whatever in a string.
static fr_dict_autoload_t xlat_eval_dict[]
static fr_dict_attr_t const * attr_cast_time_res_msec
fr_dict_attr_t const * attr_cast_base
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_frame_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_exp_head_t const **child, request_t *request, xlat_exp_head_t const *head, xlat_exp_t const **in)
Converts xlat nodes to value boxes.
static fr_dict_attr_autoload_t xlat_eval_dict_attr[]
static bool xlat_process_return(request_t *request, xlat_t const *func, fr_value_box_list_t const *returned, fr_value_box_t *pos)
Validate that the return values from an xlat function match what it registered.
void xlat_eval_free(void)
int xlat_eval_walk(xlat_exp_head_t *head, xlat_walker_t walker, xlat_type_t type, void *uctx)
Walk over all xlat nodes (depth first) in a xlat expansion, calling a callback.
static fr_dict_attr_t const * attr_cast_time_res_sec
static xlat_action_t xlat_null_resume(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
ssize_t xlat_aeval(TALLOC_CTX *ctx, char **out, request_t *request, char const *fmt, xlat_escape_legacy_t escape, void const *escape_ctx)
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.
static fr_dict_attr_t const * attr_cast_time_res_day
static ssize_t _xlat_eval_compiled(TALLOC_CTX *ctx, char **out, size_t outlen, request_t *request, xlat_exp_head_t const *head, xlat_escape_legacy_t escape, void const *escape_ctx)
Replace whatever in a string.
ssize_t xlat_aeval_compiled(TALLOC_CTX *ctx, char **out, request_t *request, xlat_exp_head_t const *xlat, xlat_escape_legacy_t escape, void const *escape_ctx)
static void xlat_debug_log_list_result(request_t *request, xlat_exp_t const *node, fr_value_box_list_t const *result)
Output the list result of an expansion.
static fr_dict_attr_t const * attr_cast_time_res_min
static ssize_t xlat_eval_sync(TALLOC_CTX *ctx, char **out, request_t *request, xlat_exp_head_t const *const head, xlat_escape_legacy_t escape, void const *escape_ctx)
static xlat_action_t xlat_exec_resume(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
static xlat_action_t xlat_process_arg_list(TALLOC_CTX *ctx, fr_value_box_list_t *list, request_t *request, char const *name, xlat_arg_parser_t const *arg, unsigned int arg_num)
Process an individual xlat argument value box group.
static fr_dict_attr_t const * attr_cast_time_res_hour
#define ESCAPE(_arg, _vb, _arg_num)
static int instance_count
char const * name
Name of xlat function.
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.
static xlat_exp_t * xlat_exp_next(xlat_exp_head_t const *head, xlat_exp_t const *node)
int(* xlat_walker_t)(xlat_exp_t *exp, void *uctx)
Walker callback for xlat_walk()
@ XLAT_ONE_LETTER
Special "one-letter" expansion.
@ XLAT_TMPL
xlat attribute
@ XLAT_VIRTUAL_UNRESOLVED
virtual attribute needs resolution during pass2.
@ XLAT_VIRTUAL
virtual attribute
@ XLAT_GROUP
encapsulated string of xlats
@ XLAT_FUNC_UNRESOLVED
func needs resolution during pass2.
@ XLAT_INVALID
Bad expansion.
xlat_arg_parser_t const * args
Definition of args consumed.
xlat_input_type_t input_type
Type of input used.
char const *_CONST fmt
The original format string (a talloced buffer).
xlat_type_t _CONST type
type of this expansion.
fr_value_box_safe_for_t return_safe_for
Escaped value to set in output boxes.
#define xlat_exp_foreach(_list_head, _iter)
Iterate over the contents of a list, only one level.
static xlat_exp_t * xlat_exp_head(xlat_exp_head_t const *head)