29RCSID(
"$Id: 105bca7b2b76db4d3beae0056d375af227e07112 $")
31#include <freeradius-devel/util/debug.h>
32#include <freeradius-devel/util/event.h>
33#include <freeradius-devel/util/sbuff.h>
34#include <freeradius-devel/util/value.h>
35#include <freeradius-devel/server/regex.h>
36#include <freeradius-devel/unlang/xlat_priv.h>
41# define XLAT_DEBUG(_fmt, ...) DEBUG3("%s[%i] "_fmt, __FILE__, __LINE__, ##__VA_ARGS__)
42# define XLAT_HEXDUMP(_data, _len, _fmt, ...) HEXDUMP3(_data, _len, "%s[%i] "_fmt, __FILE__, __LINE__, ##__VA_ARGS__)
44# define XLAT_DEBUG(...)
45# define XLAT_HEXDUMP(...)
130 fr_sbuff_marker(&m_s,
in);
135 fr_strerror_printf(
"Invalid regex reference. Must be in range 0-%d", REQUEST_MAX_REGEX);
136 fr_sbuff_marker_release(&m_s);
140 if (num > REQUEST_MAX_REGEX) {
148 fr_sbuff_marker_release(&m_s);
152 fr_sbuff_marker_release(&m_s);
157 node->regex_index = num;
159 fr_sbuff_marker_release(&m_s);
170 [
'.'] =
true, [
'-'] =
true, [
'_'] =
true,
189 if (!node)
return -1;
216 node->data.vb_strvalue, node->data.vb_length,
219 if (slen <= 0)
return slen;
238 for (arg_p = node->call.func->args, i = 0; arg_p->
type !=
FR_TYPE_NULL; arg_p++) {
245 (
unsigned int)(arg_p - node->call.func->args) + 1);
285 fr_sbuff_marker(&m_s,
in);
299 if (strchr(
"cCdDeGHIlmMnSstTY", c) != NULL) {
308 if (!
n)
goto one_letter;
335 fr_sbuff_marker_release(&m_s);
337#ifdef STATIC_ANALYZER
338 if (!node->
fmt)
return -1;
373 fr_sbuff_marker_release(&m_s);
379 node->call.func = func;
386 (void) fr_sbuff_next(
in);
393 my_t_rules = *t_rules;
395 t_rules = &my_t_rules;
420 switch (node->call.input_type) {
444 if (!func)
return -1;
451 node->call.func = func;
480 memset(&our_t_rules, 0,
sizeof(our_t_rules));
481 our_t_rules = *t_rules;
483 memset(&our_t_rules, 0,
sizeof(our_t_rules));
497 fr_sbuff_marker(&m_s,
in);
509 fr_sbuff_marker_release(&m_s);
560 fr_sbuff_marker_release(&m_s);
566 [
'-'] =
true, [
'/'] =
true, [
'_'] =
true,
567 [
'.'] =
true, [
'*'] =
true, [
'#'] =
true,
568 [
'['] =
true, [
']'] =
true,
583 fr_sbuff_parse_rules_t attr_p_rules = {
591 fr_sbuff_marker(&s_m,
in);
601 ret = xlat_tokenize_regex(
head,
in);
602 if (ret <= 0)
return ret;
615 if (!len)
goto empty_disallowed;
621 fr_sbuff_marker_release(&s_m);
645 my_rules.
enumv = NULL;
672 (void) fr_sbuff_next(
in);
688 fr_sbuff_marker(&s_m,
in);
699 fr_sbuff_marker_release(&s_m);
705 XLAT_DEBUG(
"EXPANSION HINT TOKEN '%c'", hint);
732 fr_sbuff_marker_release(&s_m);
782 fr_sbuff_parse_rules_t
const *p_rules,
tmpl_rules_t const *t_rules,
795 escapes = p_rules ? p_rules->escapes : NULL;
796 tokens = p_rules && p_rules->terminals ?
811 fr_sbuff_marker(&m_s,
in);
812 slen = fr_sbuff_out_aunescape_until(node, &str,
in, SIZE_MAX, tokens,
escapes);
822 fr_sbuff_marker_release(&m_s);
849 fr_sbuff_marker_release(&m_s);
868 fr_sbuff_marker_release(&m_s);
900 fr_sbuff_marker_release(&m_s);
919#define INFO_INDENT(_fmt, ...) INFO("%*s"_fmt, depth * 2, " ", ## __VA_ARGS__)
929 switch (node->
type) {
959 list = tmpl_request(node->vpt);
960 while ((rr = tmpl_request_list_next(list, rr))) {
1014 INFO_INDENT(
"regex-var -- %d", node->regex_index);
1019 DEBUG(
"XLAT-INVALID");
1039 head->flags.needs_resolving ?
"need_resolving," :
"",
1040 head->flags.pure ?
"pure" :
"",
1041 head->flags.can_purify ?
"can_purify" :
"");
1067 if (!node)
return 0;
1069 switch (node->
type) {
1137 fr_assert(talloc_parent(node->vpt) == node);
1161 if (node->call.func->print) {
1162 slen = node->call.func->print(
out, node, node->call.inst->data, e_rules);
1163 if (slen < 0)
return slen;
1183 switch (node->
type) {
1186 if (slen < 0)
return slen;
1215 if (slen < 0)
return slen;
1276 fr_sbuff_parse_rules_t
const *p_rules,
tmpl_rules_t const *t_rules,
bool comma,
bool allow_attr)
1282 fr_sbuff_parse_rules_t
const *our_p_rules;
1283 fr_sbuff_parse_rules_t tmp_p_rules;
1287 if (xlat && xlat->
args) {
1288 arg_start = arg = xlat->
args;
1292 arg_start = arg = &default_arg[0];
1296 if (p_rules && p_rules->terminals) {
1297 tmp_p_rules = (fr_sbuff_parse_rules_t){
1302 our_p_rules = &tmp_p_rules;
1313 fr_sbuff_marker(&m, &our_in);
1336 node->
quote = quote;
1364 our_p_rules, t_rules, arg->
safe_for) < 0) {
1396 slen = fr_sbuff_out_aunescape_until(child, &str, &our_in, SIZE_MAX,
1399 if (slen < 0)
goto error;
1447 fr_assert(p_rules && p_rules->terminals);
1460 if ((p_rules && p_rules->terminals) &&
fr_sbuff_is_terminal(&our_in, p_rules->terminals))
break;
1476 (
size_t) (arg - arg_start), argc - 1);
1510 fr_sbuff_parse_rules_t
const *p_rules,
tmpl_rules_t const *t_rules,
1565 return head->flags.needs_resolving;
1585 if (!*
head)
return false;
1595 len += talloc_array_length(node->
fmt) - 1;
1598 fr_sbuff_init_talloc(ctx, &
out, &tctx, len, SIZE_MAX);
1623 if (!
head->flags.needs_resolving)
return 0;
1625 if (!xr_rules) xr_rules = &xr_default;
1627 our_flags =
head->flags;
1629 our_flags.
pure =
true;
1640 switch (node->
type) {
1642 if (
xlat_resolve(node->group, xr_rules) < 0)
return -1;
1654 if (!node->call.func) {
1673 switch (node->call.func->input_type) {
1680 "be called using %(func:args) syntax");
1705 if (node->call.func->resolve) {
1706 void *
inst = node->call.inst ? node->call.inst->data : NULL;
1708 if (node->call.func->resolve(node,
inst, xr_rules) < 0)
return -1;
1710 if (
xlat_resolve(node->call.args, xr_rules) < 0)
return -1;
1782 head->flags = our_flags;
1810 if (!
vpt)
return NULL;
1856 node->vpt = talloc_move(node, vpt_p);
1862 node->vpt = talloc_move(node, vpt_p);
1863 node->call.func = func;
1870 node->vpt = talloc_move(node, vpt_p);
1882 return head->flags.impure_func;
static int const char * fmt
#define L(_str)
Helper for initialising arrays of string literals.
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
#define FR_DLIST_HEAD(_name)
Expands to the type name used for the head wrapper structure.
static const bool escapes[UINT8_MAX+1]
@ TMPL_ATTR_REF_PREFIX_NO
Attribute refs have no '&' prefix.
@ TMPL_ATTR_REF_PREFIX_YES
Attribute refs must have '&' prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_SBUFF_PARSE_OK
No error.
static uint8_t depth(fr_minmax_heap_index_t i)
static void print_args(fr_log_t const *log, char const *file, int line, size_t arg_cnt, uint8_t const *argv, uint8_t const *start, uint8_t const *end)
fr_dict_attr_t const * request_attr_request
size_t fr_sbuff_adv_past_allowed(fr_sbuff_t *sbuff, size_t len, bool const allowed[static UINT8_MAX+1], fr_sbuff_term_t const *tt)
Wind position past characters in the allowed set.
bool const sbuff_char_class_uint[UINT8_MAX+1]
bool fr_sbuff_is_terminal(fr_sbuff_t *in, fr_sbuff_term_t const *tt)
Efficient terminal string search.
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.
ssize_t fr_sbuff_in_bstrcpy_buffer(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
fr_sbuff_term_t * fr_sbuff_terminals_amerge(TALLOC_CTX *ctx, fr_sbuff_term_t const *a, fr_sbuff_term_t const *b)
Merge two sets of terminal strings.
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
bool const sbuff_char_alpha_num[UINT8_MAX+1]
#define fr_sbuff_out_by_longest_prefix(_match_len, _out, _table, _sbuff, _def)
#define fr_sbuff_adv_past_str_literal(_sbuff, _needle)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define fr_sbuff_set(_dst, _src)
#define fr_sbuff_is_alnum(_sbuff_or_marker)
#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt)
#define fr_sbuff_current(_sbuff_or_marker)
#define fr_sbuff_char(_sbuff_or_marker, _eob)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
char const * name
Name for rule set to aid we debugging.
#define FR_SBUFF_IN_STRCPY_LITERAL_RETURN(_sbuff, _str)
#define fr_sbuff_extend(_sbuff_or_marker)
#define fr_sbuff_buff(_sbuff_or_marker)
#define fr_sbuff_used_total(_sbuff_or_marker)
#define SBUFF_CHAR_CLASS_ALPHA_NUM
#define FR_SBUFF_RETURN(_func, _sbuff,...)
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define FR_SBUFF_ERROR_RETURN(_sbuff_or_marker)
#define FR_SBUFF_SET_RETURN(_dst, _src)
#define FR_SBUFF_IN_SPRINTF_RETURN(...)
#define SBUFF_CHAR_UNPRINTABLES_EXTENDED
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_out(_err, _out, _in)
#define fr_sbuff_remaining(_sbuff_or_marker)
#define SBUFF_CHAR_UNPRINTABLES_LOW
#define fr_sbuff_behind(_sbuff_or_marker)
#define FR_SBUFF_TERM(_str)
Initialise a terminal structure with a single string.
#define FR_SBUFF_IN_STRCPY_RETURN(...)
#define FR_SBUFF_IN_BSTRCPY_BUFFER_RETURN(...)
Set of terminal elements.
Talloc sbuff extension structure.
Set of parsing rules for *unescape_until functions.
static int16_t tmpl_attr_tail_num(tmpl_t const *vpt)
Return the last attribute reference's attribute number.
#define tmpl_contains_xlat(vpt)
#define TMPL_VERIFY(_vpt)
#define tmpl_is_attr_unresolved(vpt)
void tmpl_set_xlat(tmpl_t *vpt, xlat_exp_head_t *xlat)
Change the default dictionary in the tmpl's resolution rules.
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules))
Attempt to resolve functions and attributes in xlats and attribute references.
#define tmpl_value(_tmpl)
tmpl_t * tmpl_alloc(TALLOC_CTX *ctx, tmpl_type_t type, fr_token_t quote, char const *name, ssize_t len)
Create a new heap allocated tmpl_t.
#define tmpl_contains_regex(vpt)
#define tmpl_is_attr(vpt)
fr_dict_attr_t const * enumv
Enumeration attribute used to resolve enum values.
static fr_dict_attr_t const * tmpl_list(tmpl_t const *vpt)
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
@ TMPL_TYPE_XLAT
Pre-parsed xlat expansion.
tmpl_xlat_rules_t xlat
Rules/data for parsing xlats.
static char const * tmpl_attr_tail_unresolved(tmpl_t const *vpt)
Return the last attribute reference unresolved da.
bool at_runtime
Produce an ephemeral/runtime tmpl.
static fr_slen_t rql fr_slen_t tmpl_attr_print(fr_sbuff_t *out, tmpl_t const *vpt, tmpl_attr_prefix_t ar_prefix))
Print an attribute or list tmpl_t to a string.
ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, fr_sbuff_t *name, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
#define tmpl_is_data(vpt)
void tmpl_set_name_shallow(tmpl_t *vpt, fr_token_t quote, char const *name, ssize_t len)
Set the name on a pre-initialised tmpl.
fr_dict_t const * dict_def
Alternative default dictionary to use if vpt->rules->dict_def is NULL.
static size_t tmpl_attr_num_elements(tmpl_t const *vpt)
The number of attribute references contained within a tmpl.
#define tmpl_value_type(_tmpl)
@ TMPL_ATTR_ERROR_MISSING_TERMINATOR
Unexpected text found after attribute reference.
fr_type_t cast
Whether there was an explicit cast.
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
int tmpl_attr_copy(tmpl_t *dst, tmpl_t const *src)
Copy a list of attribute and request references from one tmpl to another.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
static char const * tmpl_list_name(fr_dict_attr_t const *list, char const *def)
Return the name of a tmpl list or def if list not provided.
fr_event_list_t * runtime_el
The eventlist to use for runtime instantiation of xlats.
#define tmpl_needs_resolving(vpt)
Optional arguments passed to vp_tmpl functions.
eap_aka_sim_process_conf_t * inst
uint8_t allow_unresolved
Allow attributes that look valid but were not found in the dictionaries.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
tmpl_attr_prefix_t prefix
Whether the attribute reference requires a prefix.
Define manipulation functions for the attribute reference list.
tmpl_request_ref_t _CONST request
An element in a lexicographically sorted array of name to num mappings.
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
static int talloc_const_free(void const *ptr)
Free const'd memory.
const char fr_token_quote[T_TOKEN_LAST]
Convert tokens back to a quoting character.
tmpl_res_rules_t const * tr_rules
tmpl resolution rules.
fr_type_t type
Type to cast argument to.
#define XLAT_HEAD_VERIFY(_head)
int xlat_instance_register_func(xlat_exp_t *node)
Callback for creating "permanent" instance data for a xlat_exp_t.
bool required
Argument must be present, and non-empty.
bool allow_unresolved
If false, all resolution steps must be completed.
bool xlat
it's an xlat wrapper
@ XLAT_ARG_VARIADIC_EMPTY_SQUASH
Empty argument groups are removed.
xlat_arg_parser_variadic_t variadic
All additional boxes should be processed using this definition.
fr_value_box_safe_for_t safe_for
Escaped value to set for boxes processed by this escape function.
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.
bool pure
has no external side effects, true for BOX, LITERAL, and some functions
bool needs_resolving
Needs pass2 resolution.
#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.
bool constant
xlat is just tmpl_attr_tail_data, or XLAT_BOX
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
Definition for a single argument consumend by an xlat function.
Flags that control resolution and evaluation.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
#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(_msg)
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules, bool tainted)
ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules)
Print one boxed value to a string.
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.
fr_sbuff_parse_rules_t const value_parse_rules_single_quoted
fr_sbuff_escape_rules_t * fr_value_escape_by_quote[T_TOKEN_LAST]
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.
ssize_t fr_value_box_print_quoted(fr_sbuff_t *out, fr_value_box_t const *data, fr_token_t quote)
Print one boxed value to a string with quotes (where needed)
fr_sbuff_parse_rules_t const value_parse_rules_bareword_quoted
fr_sbuff_parse_rules_t const value_parse_rules_double_quoted
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
#define fr_value_box_mark_safe_for(_box, _safe_for)
#define fr_box_strvalue_buffer(_val)
#define fr_box_strvalue_len(_val, _len)
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
static size_t char ** out
void xlat_exp_set_name(xlat_exp_t *node, char const *fmt, size_t len)
Set the format string for an xlat node.
void xlat_exp_set_name_buffer_shallow(xlat_exp_t *node, char const *fmt)
Set the format string for an xlat node from a pre-existing buffer.
xlat_t * xlat_func_find(char const *in, ssize_t inlen)
#define xlat_exp_head_alloc(_ctx)
xlat_flags_t flags
Flags that control resolution and evaluation.
#define xlat_exp_alloc_null(_ctx)
static xlat_exp_t * xlat_exp_next(xlat_exp_head_t const *head, xlat_exp_t const *node)
xlat_flags_t flags
Flags that control resolution and evaluation.
fr_token_t quote
Type of quoting around XLAT_GROUP types.
@ 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.
static void xlat_flags_merge(xlat_flags_t *parent, xlat_flags_t const *child)
Merge flags from child to parent.
#define xlat_exp_set_type(_node, _type)
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.
#define xlat_exp_alloc(_ctx, _type, _in, _inlen)
xlat_flags_t flags
various flags
#define xlat_exp_foreach(_list_head, _iter)
Iterate over the contents of a list, only one level.
static int xlat_exp_insert_tail(xlat_exp_head_t *head, xlat_exp_t *node)
static xlat_exp_t * xlat_exp_head(xlat_exp_head_t const *head)
bool xlat_needs_resolving(xlat_exp_head_t const *head)
Check to see if the expansion needs resolving.
#define INFO_INDENT(_fmt,...)
fr_slen_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **out, 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.
bool xlat_is_literal(xlat_exp_head_t const *head)
Check to see if the expansion consists entirely of value-box elements.
bool const xlat_func_chars[UINT8_MAX+1]
int xlat_tokenize_expansion(xlat_exp_head_t *head, fr_sbuff_t *in, tmpl_rules_t const *t_rules)
static int xlat_resolve_virtual_attribute(xlat_exp_t *node, tmpl_t *vpt)
static fr_table_num_sorted_t const xlat_quote_table[]
void xlat_debug_head(xlat_exp_head_t const *head)
static void _xlat_debug_head(xlat_exp_head_t const *head, int depth)
bool xlat_impure_func(xlat_exp_head_t const *head)
static size_t xlat_quote_table_len
tmpl_t * xlat_to_tmpl_attr(TALLOC_CTX *ctx, xlat_exp_head_t *head)
Try to convert an xlat to a tmpl for efficiency.
static fr_slen_t xlat_validate_function_arg(xlat_arg_parser_t const *arg_p, xlat_exp_t *arg)
ssize_t xlat_print(fr_sbuff_t *out, xlat_exp_head_t const *head, fr_sbuff_escape_rules_t const *e_rules)
Reconstitute an xlat expression from its constituent nodes.
#define XLAT_HEXDUMP(...)
static fr_sbuff_parse_rules_t const xlat_function_arg_rules
Parse rules for literal values inside of an expansion.
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.
static void _xlat_debug_node(xlat_exp_t const *node, int depth)
int xlat_from_tmpl_attr(TALLOC_CTX *ctx, xlat_exp_head_t **out, tmpl_t **vpt_p)
Convert attr tmpl to an xlat for &attr[*].
static fr_sbuff_unescape_rules_t const xlat_unescape
These rules apply to literal values and function arguments inside of an expansion.
void xlat_debug(xlat_exp_t const *node)
ssize_t xlat_print_node(fr_sbuff_t *out, xlat_exp_head_t const *head, xlat_exp_t const *node, fr_sbuff_escape_rules_t const *e_rules, char c)
static int xlat_tokenize_input(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 safe_for)
Parse an xlat string i.e.
static bool const tmpl_attr_allowed_chars[UINT8_MAX+1]
static fr_sbuff_escape_rules_t const xlat_escape
These rules apply to literal values and function arguments inside of an expansion.
fr_slen_t xlat_validate_function_args(xlat_exp_t *node)
fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, 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.
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.
static int xlat_tokenize_attribute(xlat_exp_head_t *head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, tmpl_attr_prefix_t attr_prefix)
Parse an attribute ref or a virtual attribute.
static int xlat_tokenize_function_args(xlat_exp_head_t *head, fr_sbuff_t *in, tmpl_rules_t const *t_rules)
Parse an xlat function and its child argument.