27RCSID(
"$Id: 79470e0b5af62a697cc375e1e2d98b9b2ae639cc $")
29#include <freeradius-devel/server/base.h>
30#include <freeradius-devel/unlang/xlat_priv.h>
131 if (!da_p)
return NULL;
149 switch (node->
type) {
174 bool first_done =
false;
186 if (node->call.args) {
188 if (first_done && (node->call.func->args)) {
228 RDEBUG2(
"| %%%s(%pM)", node->call.func->name,
args);
235 RERROR(
"Failed printing expansion");
288 if (!fr_value_box_list_head(&vb->vb_group)) {
289 fr_value_box_entry_t entry;
313 rcode = arg->
func(request, vb, arg->
uctx);
314 if (rcode != 0)
return rcode;
363 quoted = concat =
true;
374 if (fr_value_box_list_empty(list)) {
389 fr_value_box_list_insert_tail(list, vb);
395 REDEBUG(
"Function \"%s\" is missing required argument %u",
name, arg_num);
412 for (vb = fr_value_box_list_head(list);
414 vb = fr_value_box_list_next(list, vb)) {
416 RPEDEBUG(
"Function \"%s\" failed escaping argument %u",
name, arg_num);
422 vb = fr_value_box_list_head(list);
433 fr_assert(fr_value_box_list_num_elements(list) == 1);
450 if (fr_value_box_list_num_elements(list) > 1) {
451 RPEDEBUG(
"Function \"%s\" was provided an incorrect number of values at argument %u, "
452 "expected %s got %u",
455 fr_value_box_list_num_elements(list));
477 if (vb->type == arg->
type)
continue;
479 arg->
type, NULL) < 0)
goto cast_error;
480 }
while ((vb = fr_value_box_list_next(list, vb)));
502static inline CC_HINT(always_inline)
520 vb = fr_value_box_list_head(list);
533 REDEBUG(
"Function \"%s\" is missing required argument %u",
534 func->
name, (
unsigned int)((arg_p - func->
args) + 1));
555 vb_next = fr_value_box_list_next(list, vb);
559 (
unsigned int)((arg_p - func->
args) + 1));
565 if (fr_value_box_list_empty(&vb->vb_group)) {
571 fr_value_box_list_talloc_free_head(list);
604 fr_value_box_list_talloc_free_head(list);
634 fr_value_box_list_replace(list, vb,
head);
661static inline CC_HINT(
nonnull(1,2,3))
664 unsigned int count = 0;
674 REDEBUG(
"%s return type registered as %s, but %s expansion produced data",
684 if (pos->type != func->return_type) {
685 REDEBUG(
"%s returned invalid result type at index %u. Expected type %s, got type %s",
693 }
while ((pos = fr_value_box_list_next(returned, pos)));
709static inline CC_HINT(always_inline)
733 value->datum.uint32 = request->packet->id;
738 value->datum.uint64 = request->number;
743 value->datum.uint64 = request->seq_start;
779 value->datum.uint8 = ts.tm_mday;
795 value->datum.uint8 = ts.tm_sec;
802 value->datum.uint8 = ts.tm_min;
809 value->datum.uint8 = ts.tm_hour;
818 value->datum.uint64 = (uint64_t ) now;
825 value->datum.uint8 = ts.tm_mon + 1;
839 strftime(
buffer,
sizeof(
buffer),
"%Y-%m-%d %H:%M:%S", &ts);
862 if (!
gmtime_r(&now, &ts))
goto error;
864 if (!(len = strftime(
buffer,
sizeof(
buffer) - 1,
"%Y-%m-%dT%H:%M:%S", &ts))) {
865 REDEBUG(
"Failed converting packet timestamp to gmtime: Buffer full");
883 value->datum.int16 = ts.tm_year + 1900;
887 fr_assert_fail(
"%%%c is not a valid one letter expansion", letter);
891 fr_value_box_list_insert_tail(
out,
value);
912 fr_value_box_list_move((fr_value_box_list_t *)
out->dlist, &rctx->
list);
932 signal(
XLAT_CTX(exp->call.inst, t->
data, t->
mctx, NULL, rctx), request, action);
964 fr_value_box_list_t *result,
xlat_func_t resume,
void *rctx)
978 xa = resume(ctx,
out,
XLAT_CTX(NULL, NULL, NULL, NULL, rctx), request, result);
982 xa = resume(ctx,
out,
XLAT_CTX(node->call.inst->data, t->
data, t->
mctx, NULL, rctx), request, result);
985 RDEBUG2(
"| %%%s(...)", node->call.func->name);
997 if (node->call.func) {
1038 void *env_data, fr_value_box_list_t *result)
1044 switch (node->
type) {
1049 fr_value_box_list_t result_copy;
1054 XLAT_DEBUG(
"** [%i] %s(func-async) - %%%s(%pM)",
1065 fr_value_box_list_init(&result_copy);
1074 fr_value_box_list_talloc_free(&result_copy);
1079 xa = node->call.func->func(ctx,
out,
1089 fr_value_box_list_talloc_free(&result_copy);
1113 (fr_value_box_list_t *)
out->dlist,
1148 if (!fr_value_box_list_head(result)) {
1158 arg = fr_value_box_list_head(result);
1166 while ((arg = fr_value_box_list_pop_head(result)) != NULL) {
1167 talloc_steal(ctx, arg);
1175 if (!fr_value_box_list_empty(result)) {
1177 fr_value_box_list_move(&arg->vb_group, result);
1190 fr_value_box_list_talloc_free(result);
1198 fr_value_box_list_move((fr_value_box_list_t *)
out->dlist, result);
1245 fr_value_box_list_t result;
1248 fr_value_box_list_init(&result);
1261 fr_assert(fr_value_box_list_num_elements(&result) == 0);
1263 switch (node->
type) {
1292 fr_value_box_list_talloc_free(&result);
1297 fr_value_box_list_move((fr_value_box_list_t *)
out->dlist, &result);
1313 fr_value_box_list_insert_tail(&result,
value);
1320 fr_value_box_list_move((fr_value_box_list_t *)
out->dlist, &result);
1324 if (node->
fmt[0] ==
'&') {
1333 if (
tmpl_eval_pair(ctx, &result, request, node->vpt) < 0)
goto fail;
1342 fr_value_box_list_init(&rctx->
list);
1350 false, &rctx->
status)) < 0)
goto fail;
1369 fr_value_box_list_move((fr_value_box_list_t *)
out->dlist, &result);
1381 *child = node->call.args;
1401 if (regex_request_to_sub(
value,
value, request, node->regex_index) < 0) {
1420 *child = node->group;
1450 vb = fr_value_box_list_head(list);
1457 size_t len, real_len;
1469 if (
xlat_sync_stringify(vb, request, node->group, &vb->vb_group, escape, escape_ctx) < 0)
return -1;
1481 fr_value_box_list_insert_before(list, vb, box);
1482 fr_value_box_list_remove(list, vb);
1493 if (!escape)
goto next;
1504 len = vb->vb_length * 3;
1505 MEM(escaped = talloc_array(vb,
char, len));
1506 real_len = escape(request, escaped, len, vb->vb_strvalue,
UNCONST(
void *, escape_ctx));
1512 vb = fr_value_box_list_next(list, vb);
1515 }
while (node && vb);
1523 fr_value_box_list_t result;
1525 TALLOC_CTX *pool = talloc_new(NULL);
1533 fr_value_box_list_init(&result);
1565 if (!fr_value_box_list_empty(&result)) {
1574 if (!str)
goto fail;
1582 return talloc_array_length(str) - 1;
1622 if ((
size_t)slen >= outlen) {
1631 (*out)[slen] =
'\0';
1650static CC_HINT(
nonnull (2, 4, 5))
1667 .dict_def = request->local_dict,
1679 *
out = talloc_zero_array(ctx,
char, 1);
1705 return _xlat_eval(request, &
out, outlen, request,
fmt, escape, escape_ctx);
1745 if (
head->flags.needs_resolving) {
1763 my_argv[i++] = talloc_steal(my_argv, node->group);
1766 fr_value_box_list_talloc_free((fr_value_box_list_t *)&
head->dlist);
1789 switch (node->type){
1798 if (ret < 0)
return ret;
1802 ret = walker(node, uctx);
1803 if (ret < 0)
return ret;
1810 if (ret < 0)
return ret;
1814 ret = walker(node, uctx);
1815 if (ret < 0)
return ret;
1821 ret = walker(node, uctx);
1822 if (ret < 0)
return ret;
1823 if (ret > 0)
continue;
1830 if (ret < 0)
return ret;
1834 if (!
type || (
type & node->type)) {
1835 ret = walker(node, uctx);
1836 if (ret < 0)
return ret;
1857 PERROR(
"%s", __FUNCTION__);
1862 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.
static unsigned int fr_dlist_num_elements(fr_dlist_head_t const *head)
Return the number of elements in the dlist.
#define EXEC_TIMEOUT
Default wait time for exec calls (in seconds).
rlm_rcode_t unlang_interpret(request_t *request, bool running)
Run the interpreter for a current request.
unlang_interpret_t * unlang_interpret_get(request_t *request)
Get the interpreter set for a request.
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.
#define UNLANG_REQUEST_RUNNING
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)
#define tmpl_needs_resolving(vpt)
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.
void * uctx
Argument to pass to escape callback.
bool required
Argument must be present, and non-empty.
bool xlat_impure_func(xlat_exp_head_t const *head)
xlat_escape_func_t func
Function to handle tainted values.
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)
Tokenize an xlat expansion.
@ 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 will_escape
the function will do escaping and concatenation.
bool single
Argument must only contain a single box.
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.
fr_value_box_safe_for_t safe_for
Escaped value to set for boxes processed by this escape function.
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
@ 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.
uint8_t 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.
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
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.
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.
void fr_value_box_strdup_shallow_replace(fr_value_box_t *vb, char const *src, ssize_t len)
Free the existing buffer (if talloced) associated with the valuebox, and replace it with a new one.
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_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 fr_value_box_is_safe_for(_box, _safe_for)
#define FR_VALUE_BOX_SAFE_FOR_NONE
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
#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.
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
#define fr_value_box_list_foreach(_list_head, _iter)
static size_t char ** out
#define FR_VALUE_BOX_SAFE_FOR_ANY
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
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 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, xlat_exp_t const *node, unsigned int arg_num)
Process an individual xlat argument value box group.
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.
int xlat_flatten_to_argv(TALLOC_CTX *ctx, xlat_exp_head_t ***argv, xlat_exp_head_t *head)
Turn am xlat list into an argv[] array, and nuke the input list.
static fr_dict_attr_autoload_t xlat_eval_dict_attr[]
static xlat_action_t xlat_process_args(TALLOC_CTX *ctx, fr_value_box_list_t *list, request_t *request, xlat_exp_t const *node)
Process list of boxed values provided as input to an xlat.
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)
static int xlat_arg_stringify(request_t *request, xlat_arg_parser_t const *arg, xlat_exp_t const *node, fr_value_box_t *vb)
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)
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 int xlat_sync_stringify(TALLOC_CTX *ctx, request_t *request, xlat_exp_head_t const *head, fr_value_box_list_t *list, 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 fr_dict_attr_t const * attr_cast_time_res_hour
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)
xlat_func_t func
async xlat function (async unsafe).
int(* xlat_walker_t)(xlat_exp_t *exp, void *uctx)
Walker callback for xlat_walk()
fr_token_t quote
Type of quoting around XLAT_GROUP types.
@ XLAT_ONE_LETTER
Special "one-letter" expansion.
@ XLAT_TMPL
xlat 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.
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)