27RCSID(
"$Id: 8828851f035f9f14bedcbbad6056a59bb24c4a0d $")
29#define _TMPL_PRIVATE 1
31#include <freeradius-devel/server/tmpl.h>
32#include <freeradius-devel/server/base.h>
33#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
35#include <freeradius-devel/util/debug.h>
36#include <freeradius-devel/util/base16.h>
37#include <freeradius-devel/util/misc.h>
39#include <freeradius-devel/util/sbuff.h>
40#include <freeradius-devel/util/value.h>
45#include <freeradius-devel/unlang/xlat_priv.h>
58#define TMPL_REQUEST_REF_DEF(_name, _ref) \
59static tmpl_request_t _name ## _entry = { \
62 .next = &_name.head.entry, \
63 .prev = &_name.head.entry \
68FR_DLIST_HEAD(tmpl_request_list) _name = { \
70 .offset = offsetof(tmpl_request_t, entry), \
72 .next = &_name ## _entry.entry.entry, \
73 .prev = &_name ## _entry.entry.entry, \
104#define DEFAULT_RULES tmpl_rules_t default_rules = { .attr = { .list_def = request_attr_request }}
106#define CHECK_T_RULES do { \
108 t_rules = &default_rules; \
175#define UNRESOLVED_SET(_flags) (*(_flags) = (*(_flags) | TMPL_FLAG_UNRESOLVED))
176#define RESOLVED_SET(_flags) (*(_flags) = (*(_flags) & ~TMPL_FLAG_UNRESOLVED))
187 fr_sbuff_parse_rules_t
const *p_rules)
193 if (!p_rules || !p_rules->terminals)
return false;
195 fr_sbuff_marker(&m,
in);
198 fr_sbuff_marker_release(&m);
235 if (ar->ar_parent)
FR_FAULT_LOG(
"\t parent : %s (%p)", ar->ar_parent->name, ar->ar_parent);
251 if (ar->ar_parent)
FR_FAULT_LOG(
"\t parent : %s", ar->ar_parent->name);
252 if (ar->ar_unresolved_namespace)
FR_FAULT_LOG(
"\t namespace : %s", ar->ar_unresolved_namespace->name);
271 while ((ar = tmpl_attr_list_next(ar_head, ar))) {
288 FR_FAULT_LOG(
"%s can't print tmpls of type %s", __FUNCTION__,
306 while ((rr = tmpl_request_list_next(&
vpt->data.attribute.rr, rr))) {
372 FR_FAULT_LOG(
"\tlen : %zu", talloc_array_length(
vpt->data.unescaped) - 1);
429static inline CC_HINT(always_inline) CC_HINT(
nonnull(2,3))
439 while ((rr = tmpl_request_list_next(
in, rr))) {
444 tmpl_request_list_insert_tail(
out, n_rr);
452static inline CC_HINT(always_inline) CC_HINT(
nonnull(2,3))
459 tmpl_request_list_talloc_init(rql);
473 while ((rr = tmpl_request_list_next(rql, rr))) {
500 if (!a || !tmpl_request_list_initialised(a) || tmpl_request_list_empty(a)) a = &tmpl_request_def_current;
501 if (!b || !tmpl_request_list_initialised(b) || tmpl_request_list_empty(b)) b = &tmpl_request_def_current;
506 if (a == b)
return 0;
509 a_rr = tmpl_request_list_next(a, a_rr);
510 b_rr = tmpl_request_list_next(b, b_rr);
512 if (!a_rr || !b_rr)
return CMP(tmpl_request_list_num_elements(a), tmpl_request_list_num_elements(b));
534 fr_sbuff_parse_rules_t
const *p_rules,
543 unsigned int depth = 0;
549 at_rules = &t_rules->
attr;
559 if (at_rules->namespace) {
560 *
namespace = at_rules->namespace;
571 if (!tmpl_request_list_initialised(
out)) tmpl_request_list_talloc_init(
out);
573 fr_sbuff_marker(&m, &our_in);
593 if ((
depth == 0) && at_rules->request_def) {
614 tmpl_request_list_talloc_free_to_tail(
out, tail);
622 if (
namespace && t_rules && t_rules->
parent) {
623 t_rules = t_rules->
parent;
631 if (t_rules->
attr.namespace) {
632 *
namespace = t_rules->attr.namespace;
652 tmpl_request_list_insert_tail(
out, rr);
704 tmpl_request_list_talloc_init(rql);
744 tmpl_request_list_talloc_init(&
vpt->data.attribute.rr);
763 char const *old = NULL;
770 vpt->len = talloc_array_length(
vpt->name) - 1;
808 vpt->len = talloc_array_length(
vpt->name) - 1;
819 vpt->rules.attr.dict_def = dict;
829 vpt->rules.escape = *escape;
858 memset(
vpt, 0,
sizeof(*
vpt));
863 vpt->len = talloc_array_length(
vpt->name) - 1;
887 memset(
vpt, 0,
sizeof(*
vpt));
890 if (t_rules)
vpt->rules = *t_rules;
909 memset(
vpt, 0,
sizeof(*
vpt));
912 if (t_rules)
vpt->rules = *t_rules;
955 memset(
vpt, 0,
sizeof(*
vpt));
1044 if (tmpl_attr_list_num_elements(
tmpl_attr(dst)) > 0) tmpl_attr_list_talloc_reverse_free(
tmpl_attr(dst));
1046 while ((src_ar = tmpl_attr_list_next(
tmpl_attr(src), src_ar))) {
1049 switch (src_ar->
type) {
1051 dst_ar->ar_da = src_ar->ar_da;
1062 dst_ar->ar_unresolved =
talloc_bstrdup(dst_ar, src_ar->ar_unresolved);
1068 dst_ar->ar_num = src_ar->ar_num;
1069 dst_ar->ar_filter_type = src_ar->ar_filter_type;
1077 tmpl_request_list_talloc_reverse_free(&dst->data.attribute.rr);
1083 dst->rules = src->rules;
1109 if (da->flags.is_unknown) {
1142 fr_strerror_const(
"New leaf da and old leaf da do not share the same ancestor");
1152 talloc_free_children(ref);
1168 if (da->flags.is_unknown) {
1199 if (tmpl_attr_list_num_elements(
tmpl_attr(
vpt)) == 0)
return;
1228 tmpl_request_list_talloc_reverse_free(&
vpt->data.attribute.rr);
1261 if (da->flags.is_unknown) {
1279 STRINGIFY(
sizeof(attr))
" bytes, got %zu bytes", (
size_t)-slen);
1316 switch (ar->ar_num) {
1352 fr_sbuff_set_to_start(&our_name);
1360 fr_sbuff_next(&our_name);
1365 fr_sbuff_next(&our_name);
1389 if ((ar->ar_num > 1000) || (ar->ar_num < 0)) {
1390 fr_strerror_printf(
"Invalid array index '%hi' (should be between 0-1000)", ar->ar_num);
1419 fr_sbuff_parse_rules_t p_rules;
1456 t_rules.
attr = *at_rules;
1457 t_rules.
attr.namespace = ar->ar_da;
1459 p_rules = (fr_sbuff_parse_rules_t) {
1460 .terminals = &filter_terminals,
1468 if (slen < 0)
goto error;
1482 fr_sbuff_parse_rules_t p_rules;
1485 if (!fr_sbuff_is_str(&our_name,
"%{", 2)) {
1492 t_rules.
attr = *at_rules;
1494 p_rules = (fr_sbuff_parse_rules_t) {
1495 .terminals = &filter_terminals,
1503 if (slen < 0)
goto error;
1506 fr_strerror_const(
"Expression in attribute index cannot depend on functions which call external databases");
1522 if (fr_sbuff_is_str(&our_name,
"n]", 2)) {
1524 fr_sbuff_next(&our_name);
1535 fr_sbuff_parse_rules_t p_rules;
1540 t_rules.
attr = *at_rules;
1547 p_rules = (fr_sbuff_parse_rules_t) {
1548 .terminals = &filter_terminals,
1558 if (slen <= 0)
goto error;
1593static inline CC_HINT(
nonnull(3,4))
1646static inline CC_HINT(
nonnull(3,6))
1669 slen = fr_sbuff_out_abstrncpy_allowed(ar, &unresolved,
1678 tmpl_attr_list_talloc_free_to_tail(
tmpl_attr(
vpt), ar_curr);
1691 .ar_unresolved = unresolved,
1692 .ar_unresolved_namespace =
namespace,
1736 .ar_parent = da->parent,
1782 fr_sbuff_marker(&m_s,
name);
1789 fr_sbuff_marker_release(&m_s);
1817 name, p_rules ? p_rules->terminals : NULL,
1828 our_parent = da->parent;
1830 if (!our_parent->flags.is_root) {
1851 p_rules ? p_rules->terminals : NULL);
1862 ar = tmpl_attr_list_tail(&
vpt->data.attribute.ar);
1869 p_rules ? p_rules->terminals : NULL);
1872 our_parent = internal_root;
1882 if (!da->flags.local && namespace->flags.local)
namespace = our_parent =
fr_dict_root(da->dict);
1888 if (da->parent != our_parent) {
1901 if (our_parent->flags.is_unknown)
break;
1932 our_parent =
namespace =
fr_dict_root(at_rules->dict_def);
1948 namespace = fr_dict_unlocal(namespace);
1962 if (da)
goto alloc_ar;
1982 switch (namespace->type) {
2002 .ar_parent = our_parent,
2021 fr_sbuff_marker_release(&m_s);
2042 .ar_parent = our_parent,
2064 if (da->flags.local && (ar->ar_num > 0)) {
2076 fr_sbuff_marker_release(&m_s);
2077 fr_sbuff_marker(&m_s,
name);
2106 our_parent =
namespace = ref;
2109 our_parent =
namespace =
parent;
2112 our_parent =
namespace =
fr_dict_root(at_rules->dict_def);
2115 our_parent =
namespace = NULL;
2127 namespace = our_parent = da;
2138 "\"struct\", \"tlv\", \"vendor\", \"vsa\" or \"group\", got \"%s\"",
2149 tmpl_attr_list_talloc_free_tail(&
vpt->data.attribute.ar);
2176 fr_sbuff_marker_release(&m_s);
2223 fr_sbuff_parse_rules_t
const *p_rules,
2229 bool is_raw =
false;
2237 at_rules = &t_rules->
attr;
2269 &
vpt->data.attribute.rr,
2281 fr_sbuff_marker(&m_l, &our_name);
2288 namespace,
namespace,
2289 &our_name, p_rules, at_rules, 0);
2290 if (ret < 0)
goto error;
2308 bool is_local = ar->ar_da->flags.local;
2312 if (!ar->ar_da->flags.local ||
2313 (ar->ar_da->flags.local && is_local))
continue;
2387 vpt->rules = *t_rules;
2396 if (t_rules->
attr.request_def) {
2436 fr_sbuff_set_to_start(&our_name);
2466 name_len = strlen(
name);
2468 if (slen <= 0)
return slen;
2472 if (slen != name_len) {
2500 fr_sbuff_parse_rules_t
const *p_rules)
2517 cast, allow_enum ? t_rules->
enumv : NULL,
2518 &our_in, p_rules) < 0) {
2548 fr_sbuff_parse_rules_t
const *p_rules)
2567 vpt->data.literal.vb_bool = a_bool;
2586 fr_sbuff_parse_rules_t
const *p_rules)
2626 MEM(bin = talloc_realloc_size(
vpt, bin, binlen));
2645 fr_sbuff_parse_rules_t
const *p_rules)
2652 uint8_t addr[4] = {}, prefix = 32;
2657 if (
count == 3)
break;
2690 vpt->data.literal.vb_ip.af = AF_INET;
2691 vpt->data.literal.vb_ip.prefix = prefix;
2698 ipaddr &= ~((
uint32_t) 0) << (32 - prefix);
2700 vpt->data.literal.vb_ip.addr.v4.s_addr = htonl(ipaddr);
2718 fr_sbuff_parse_rules_t
const *p_rules)
2725 char *sep_a, *sep_b;
2727 static bool ipv6_chars[
UINT8_MAX + 1] = {
2728 [
'0'] =
true, [
'1'] =
true, [
'2'] =
true, [
'3'] =
true, [
'4'] =
true,
2729 [
'5'] =
true, [
'6'] =
true, [
'7'] =
true, [
'8'] =
true, [
'9'] =
true,
2730 [
'a'] =
true, [
'b'] =
true, [
'c'] =
true, [
'd'] =
true, [
'e'] =
true,
2732 [
'A'] =
true, [
'B'] =
true, [
'C'] =
true, [
'D'] =
true, [
'E'] =
true,
2734 [
':'] =
true, [
'.'] =
true
2741 fr_sbuff_marker(&m, &our_in);
2761 if (sep_a && (!(sep_b = memchr(
fr_sbuff_current(&m),
':', len)) || (sep_b > sep_a))) {
2781 if ((len < 1) || (len > IFNAMSIZ)) {
2836 fr_sbuff_parse_rules_t
const *p_rules)
2885 memcpy(vb->vb_ether,
buff,
sizeof(vb->vb_ether));
2903 fr_sbuff_parse_rules_t
const *p_rules)
2917 if (slen <= 0)
return 0;
2928 if (a_int >= INT8_MIN) {
2930 vb->vb_int8 = (int8_t)a_int;
2931 }
else if (a_int >= INT16_MIN) {
2933 vb->vb_int16 = (int16_t)a_int;
2934 }
else if (a_int >= INT32_MIN) {
2936 vb->vb_int32 = (int32_t)a_int;
2939 vb->vb_int64 = (int64_t)a_int;
2948 if (slen <= 0)
return slen;
2960 vb->vb_uint8 = (
uint8_t)a_uint;
2961 }
else if (a_uint <= UINT16_MAX) {
2964 }
else if (a_uint <= UINT32_MAX) {
2969 vb->vb_uint64 = (uint64_t)a_uint;
2979 fr_sbuff_parse_rules_t
const *p_rules)
2988 if (slen <= 0)
return 0;
2999 vb->vb_float64 = a_float;
3007 fr_sbuff_parse_rules_t
const *p_rules)
3016 if (slen <= 0)
return 0;
3022 vb->vb_time_delta = a_delta;
3052 fr_sbuff_parse_rules_t
const *p_rules,
3071 }
else if (t_rules->
enumv &&
3099 "'quoted literal', \"%{expansion}\", or enum value");
3118 if (t_rules->
enumv) {
3126 vpt->data.literal.enumv = t_rules->
enumv;
3142 vpt->data.unescaped = str;
3177 fr_sbuff_parse_rules_t
const *p_rules,
3230 t_rules,
true, p_rules);
3241 my_t_rules.
cast = my_t_rules.
enumv->type;
3251 if (slen > 0)
goto done_bareword;
3271 if (slen > 0)
goto done_bareword;
3282 if (slen > 0)
goto done_bareword;
3289 if (slen > 0)
goto done_bareword;
3296 if (slen > 0)
goto done_bareword;
3300 if (slen > 0)
goto done_bareword;
3307 if (slen > 0)
goto done_bareword;
3314 if (slen > 0)
goto done_bareword;
3325 if (slen > 0)
goto done_bareword;
3333 if (slen > 0)
goto done_bareword;
3369 "'quoted literal', \"%{expansion}\", or enum value");
3387 vpt->data.unescaped = str;
3402 slen = fr_sbuff_out_aunescape_until(
vpt, &str, &our_in, SIZE_MAX,
3403 p_rules ? p_rules->terminals : NULL,
3404 p_rules ? p_rules->escapes : NULL);
3406 vpt->data.unescaped = str;
3430 t_rules,
false, p_rules);
3443 vpt->data.unescaped = str;
3475 if ((slen <= 0) || !
head) {
3506 fr_sbuff_set_to_start(&our_in);
3528 vpt->data.unescaped = str;
3570 vpt->rules =
in->rules;
3593 vpt->data.reg_flags =
in->data.reg_flags;
3606 if (
unlikely(tmpl_regex_compile(
vpt,
vpt->data.reg.subcaptures) < 0))
goto error;
3621 if (!
vpt->data.xlat.ex)
goto error;
3673 fr_sbuff_marker(&m, &our_in);
3690 if (rules) rules->
cast = cast;
3727 switch (
vpt->type) {
3763 if (da->type == dst_type) {
3764 if (da->flags.has_value)
goto done;
3767 src_type = da->type;
3775 if (src_type == dst_type) {
3796 vpt->rules.cast = dst_type;
3818 slen = regex_flags_parse(&
err, &
vpt->data.reg_flags,
in, terminals,
true);
3851static inline CC_HINT(always_inline)
3854 char const *unescaped,
size_t unescaped_len)
3865 switch (existing_quote) {
3868 return existing_quote;
3896 switch (
vpt->type) {
3899 char *unescaped =
vpt->data.unescaped;
3918 (
uint8_t const *)unescaped, talloc_array_length(unescaped) - 1,
3919 false) < 0)
return -1;
3923 unescaped, talloc_array_length(unescaped) - 1,
3924 NULL) < 0)
return -1;
3928 unescaped, talloc_array_length(unescaped) - 1);
4015 dict_def =
vpt->rules.attr.dict_def;
4031 talloc_array_length(ar->ar_unresolved) - 1),
4034 vpt->rules.attr.allow_foreign);
4054 next->ar_parent = da;
4055 next->ar_unresolved_namespace = da;
4062 while ((ar = tmpl_attr_list_next(
tmpl_attr(
vpt), ar))) {
4086 talloc_array_length(ar->ar_unresolved) - 1),
4103 talloc_array_length(ar->ar_unresolved) - 1),
4119 fr_assert(ar->ar_parent && !ar->ar_parent->flags.is_unknown);
4127 next->ar_parent = da;
4128 next->ar_unresolved_namespace = da;
4141 ar->ar_parent = prev->ar_parent;
4168static inline CC_HINT(always_inline)
4173 .tr_rules = tr_rules,
4174 .allow_unresolved = false
4207 if (!tr_rules) tr_rules = &default_tr_rules;
4221 fr_strerror_printf(
"mismatch between parse-time enumv '%s' and resolution-time enumv '%s'",
4245 if (ret < 0)
return ret;
4267 if (!enumv) enumv = tr_rules->
enumv;
4279 dst_type = enumv->type;
4284 }
else if (strncmp(
vpt->data.unescaped,
"::", 2) != 0) {
4288 fr_strerror_printf(
"Failed resolving data '%s' - it is not an attribute name or a quoted string",
vpt->data.unescaped);
4338 switch (
vpt->type) {
4360 tmpl_request_list_talloc_free(&
vpt->data.attribute.rr);
4372 TALLOC_FREE(
vpt->data.xlat.ex);
4381 memcpy(
vpt, &tmp,
sizeof(*
vpt));
4390 switch (ref->
type) {
4396 ref->ar_unknown->flags.is_unknown = 1;
4442 if (
vpt->rules.at_runtime)
return 1;
4450 while ((ar = tmpl_attr_list_next(
tmpl_attr(
vpt), ar))) {
4466 unknown = ar->ar_unknown;
4468 if (!known)
return -1;
4476 (next->ar_da->parent == unknown)) {
4478 known) < 0)
return -1;
4479 next->ar_parent = known;
4543 if (!
vpt)
return -1;
4556 if (
type != da->type) {
4563 if (memcmp(flags, &da->flags,
sizeof(*flags)) != 0) {
4582 char *unescaped =
vpt->data.unescaped;
4588 slen = regex_compile(
vpt, &
vpt->data.reg.ex,
4589 unescaped, talloc_array_length(unescaped) - 1,
4590 &
vpt->data.reg_flags, subcaptures,
vpt->rules.at_runtime);
4591 if (slen <= 0)
return vpt->quote !=
T_BARE_WORD ? slen - 1 : slen;
4594 vpt->data.reg.src = unescaped;
4595 vpt->data.reg.subcaptures = subcaptures;
4617 rr = tmpl_request_list_next(rql, rr);
4647 switch (
vpt->type) {
4662 if (slen < 0)
return slen;
4679 while ((ar = tmpl_attr_list_next(
tmpl_attr(
vpt), ar))) {
4697 depth = ar->ar_parent->depth - 1;
4702 depth = ar->ar_parent->depth;
4723 for (i =
depth; (
unsigned int)i < ar->
ar_da->depth; i++) {
4741 unsigned int i,
depth;
4748 if (ar->ar_parent && !ar->ar_parent->flags.is_root) {
4750 if (ar->ar_parent->flags.is_root) {
4753 depth = ar->ar_parent->depth - 1;
4756 for (i =
depth; i < ar->ar_parent->depth; i++) {
4773 switch (ar->ar_num) {
4796 (void)
xlat_print(&our_out, ar->ar_cond, NULL);
4835 switch (
vpt->type) {
4856 fr_sbuff_terminate(
out);
4882 fr_sbuff_terminate(
out);
4925#ifdef WITH_VERIFY_PTR
4938 for (i = 0; i < len; i++) {
4939 if (ptr[i] != 0x00)
return ptr + i;
4948#define CHECK_ZEROED(_vpt, _field) is_zeroed(((uint8_t const *)&(_vpt)->data) + sizeof((_vpt)->data._field), sizeof((_vpt)->data) - sizeof((_vpt)->data._field))
4954#define PRINT_NON_ZEROED(_vpt, _field, _nz_ptr) \
4956 DEBUG("Expected live portion %p-%p (0-%zu)", \
4958 (uint8_t const *)&(_vpt)->data + sizeof((_vpt)->data._field), \
4959 sizeof((_vpt)->data._field)); \
4960 DEBUG("Expected zero portion %p-%p (%zu-%zu)", \
4961 (uint8_t const *)&(_vpt)->data + sizeof((_vpt)->data._field), \
4962 (uint8_t const *)&(_vpt)->data + sizeof((_vpt)->data), \
4963 sizeof((_vpt)->data._field), sizeof((_vpt)->data)); \
4964 HEX_MARKER1((uint8_t const *)&vpt->data, sizeof(vpt->data), nz - (uint8_t const *)&vpt->data, "non-zero memory", ""); \
4988 while ((slow = tmpl_attr_list_next(
tmpl_attr(
vpt), slow)) &&
4996 "CONSISTENCY CHECK FAILED %s[%u]: Looping reference list found. "
4997 "Fast pointer hit slow pointer at \"%s\"",
5000 slow->da ? slow->da->
name :
"(null-attr)");
5015 "TMPL_TYPE_ATTR known attribute \"%s\" "
5016 "occurred after unknown attribute %s "
5020 ar->unknown.
da->name);
5022 if (seen_unresolved) {
5025 "TMPL_TYPE_ATTR known attribute \"%s\" "
5026 "occurred after unresolved attribute \"%s\""
5033 "CONSISTENCY CHECK FAILED %s[%u]: attr ref missing parent",
5041 "TMPL_TYPE_ATTR unspecified attribute "
5042 "occurred after unknown attribute %s "
5045 ar->unknown.
da->name);
5047 if (seen_unresolved) {
5050 "TMPL_TYPE_ATTR unspecified attribute "
5051 "occurred after unresolved attribute \"%s\""
5059 seen_unresolved = ar;
5061 "CONSISTENCY CHECK FAILED %s[%u]: unresolved attr ref missing namespace",
5067 if (seen_unresolved) {
5070 "TMPL_TYPE_ATTR unknown attribute \"%s\" "
5071 "occurred after unresolved attribute %s "
5097 "TMPL_TYPE_UNINITIALISED (uninitialised)",
file,
line);
5102 "(outside range of tmpl_type_table)",
file,
line,
vpt->type);
5108 fr_fatal_assert_fail(
"CONSISTENCY CHECK FAILED %s[%u]: Quote type '%c' (%i) was set for NULL name",
5113 fr_fatal_assert_fail(
"CONSISTENCY CHECK FAILED %s[%u]: No quoting type was set for name \"%.*s\"",
5125 switch (
vpt->type) {
5127 if ((nz = is_zeroed((
uint8_t const *)&
vpt->data,
sizeof(
vpt->data)))) {
5129 nz - (
uint8_t const *)&
vpt->data,
"non-zero memory",
"");
5131 "has non-zero bytes in its data union",
file,
line);
5136 if (!
vpt->data.unescaped) {
5138 "unescaped field is NULL",
file,
line);
5143 if (!
vpt->data.xlat.ex) {
5145 "has a NULL xlat.ex field",
file,
line);
5151 "does not have 'needs resolving' flag set",
file,
line);
5156 if (!
vpt->data.xlat.ex) {
5158 "has a NULL xlat.ex field",
file,
line);
5185 if ((tmpl_attr_list_num_elements(
tmpl_attr(
vpt)) > 0) &&
5196 if ((nz = CHECK_ZEROED(
vpt, attribute))) {
5197 PRINT_NON_ZEROED(
vpt, attribute, nz);
5199 "has non-zero bytes after the data.attribute struct in the union",
5211 "da is marked as unknown, but address is not equal to the template's "
5227 "attribute \"%s\" (%s) not rooted in a dictionary",
5235 "dictionary pointer %p \"%s\" (%s) "
5236 "and global dictionary pointer %p \"%s\" (%s) differ",
5249 if ((nz = CHECK_ZEROED(
vpt, literal))) {
5250 PRINT_NON_ZEROED(
vpt, literal, nz);
5252 "has non-zero bytes after the data.literal struct in the union",
5258 "FR_TYPE_NULL (uninitialised)",
file,
line);
5291 fr_fatal_assert_fail(
"CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_REGEX_XLAT_UNRESOLVED - No regex support",
5298 if (tmpl_regex(
vpt) == NULL) {
5300 "reg.ex field was NULL",
file,
line);
5317#define return_P(_x) fr_strerror_const(_x);goto return_p
5348 while (isspace((
uint8_t) *p) && (p < end)) p++;
5349 if (p >= end)
return p -
in;
5364 while ((q < end) && (isalnum((
int) *q) || (*q ==
'.') || (*q ==
'_') || (*q ==
'-'))) {
5409 if ((*p ==
'}') || (*p ==
')')) {
5410 bool match = (*p ==
close);
5418 *outlen = p - (*out);
5427 return_P(
"End of string after escape");
5434 if ((p[0] ==
'%') && ((p[1] ==
'{') || (p[1] ==
'('))) {
5436 return_P(
"End of string after expansion");
5447 if ((*p ==
'{') || (*p ==
'(')) {
5461 return_P(
"Unterminated expansion");
5489 if ((
inlen > 3) && (p[0] == quote) && (p[1] == quote)) {
5498 if (p >= end)
goto unterminated;
5508 *outlen = p - (*out);
5514 if (((end - p) >= 3) && (p[1] == quote) && (p[2] == quote)) {
5515 *outlen = p - (*out);
5527 return_P(
"End of string after escape");
5570 }
else if ((p[1] ==
'E') &&
5624 if ((*p ==
'-') || (*p ==
':')) {
5625 if (p[1] ==
'=')
break;
5634 if ((*p ==
'.') || (*p ==
'/') || (*p ==
'_') || (*p ==
'*') ||
5635 (*p ==
']') || (*p ==
'@')) {
5643 if ((p ==
in) && (*p ==
'[')) {
5651 if (((*p >=
'a') && (*p <=
'z')) ||
5652 ((*p >=
'A') && (*p <=
'Z')) ||
5653 ((*p >=
'0') && (*p <=
'9'))) {
5661 if (*(
uint8_t const *)p > 0x80) {
5678 if ((*p ==
'#') || (*p ==
'*') || (*p ==
'n')) {
5685 while ((*p >=
'0') && (*p <=
'9')) {
5690 return_P(
"Array index is not an integer");
5713 if ((*p ==
'"') || (*p ==
'\'') || (*p ==
'`')) {
5714 return_P(
"Unexpected start of string");
5718 return_P(
"Empty string is invalid");
5721 *outlen = p - (*out);
5737 switch (
vpt->type) {
5778 if (
vpt->rules.attr.request_def) {
5788 out->attr.namespace = da;
5799 if ((dict != internal) && (dict !=
out->attr.dict_def)) {
5800 out->attr.dict_def = dict;
5801 out->attr.namespace = ref;
5816 FR_FAULT_LOG(
"\tnamespace = %s", at_rules->namespace ? at_rules->namespace->name :
"");
static int const char char buffer[256]
static int const char * fmt
#define fr_base16_decode(_err, _out, _in, _no_trailing)
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define L(_str)
Helper for initialising arrays of string literals.
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
static char const * skip_word(char const *text)
#define fr_dbuff_init(_out, _start, _len_or_end)
Initialise an dbuff for encoding or decoding.
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
#define fr_fatal_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
#define FR_FAULT_LOG(_fmt,...)
#define fr_fatal_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
fr_slen_t fr_dict_attr_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out, fr_dict_attr_t const *parent, fr_sbuff_t *name, fr_sbuff_term_t const *tt))
unsigned int name_only
this attribute should always be referred to by name.
fr_dict_t * fr_dict_unconst(fr_dict_t const *dict)
Coerce to non-const.
fr_dict_t const * fr_dict_by_da(fr_dict_attr_t const *da)
Attempt to locate the protocol dictionary containing an attribute.
fr_dict_attr_t const * fr_dict_attr_common_parent(fr_dict_attr_t const *a, fr_dict_attr_t const *b, bool is_ancestor)
Find a common ancestor that two TLV type attributes share.
static fr_dict_attr_t * fr_dict_attr_unknown_vendor_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int vendor)
bool const fr_dict_attr_allowed_chars[UINT8_MAX+1]
Characters that are allowed in dictionary attribute names.
static fr_dict_attr_t * fr_dict_attr_unknown_copy(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
fr_dict_attr_t const * fr_dict_attr_unknown_add(fr_dict_t *dict, fr_dict_attr_t const *old)
Converts an unknown to a known by adding it to the internal dictionaries.
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
fr_dict_attr_t * fr_dict_attr_unconst(fr_dict_attr_t const *da)
Coerce to non-const.
fr_dict_attr_t * fr_dict_attr_unknown_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da))
Copy a known or unknown attribute to produce an unknown attribute with the specified name.
static fr_dict_attr_t * fr_dict_attr_unknown_raw_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
int fr_dict_attr_unknown_parent_to_known(fr_dict_attr_t *da, fr_dict_attr_t const *parent)
Fixup the parent of an unknown attribute using an equivalent known attribute.
fr_value_box_t const * value
Enum value (what name maps to).
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
void fr_dict_attr_unknown_free(fr_dict_attr_t const **da)
Free dynamically allocated (unknown attributes)
fr_dict_t const * fr_dict_internal(void)
fr_slen_t fr_dict_attr_search_by_qualified_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out, fr_dict_t const *dict_def, fr_sbuff_t *name, fr_sbuff_term_t const *tt, bool internal, bool foreign))
Locate a qualified fr_dict_attr_t by its name and a dictionary qualifier.
fr_slen_t fr_dict_attr_search_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out, fr_dict_t const *dict_def, fr_sbuff_t *name, fr_sbuff_term_t const *tt, bool internal, bool foreign))
Locate a fr_dict_attr_t by its name in the top level namespace of a dictionary.
static fr_slen_t fr_dict_enum_name_afrom_substr(TALLOC_CTX *ctx, char **out, fr_sbuff_parse_error_t *err, fr_sbuff_t *in, fr_sbuff_term_t const *tt) 1(fr_dict_enum_name_from_substr
#define FR_DICT_MAX_TLV_STACK
Maximum TLV stack size.
fr_dict_attr_err_t
Errors returned by attribute lookup functions.
@ FR_DICT_ATTR_OK
No error.
@ FR_DICT_ATTR_NOT_DESCENDENT
Attribute is not a descendent of the parent attribute.
@ FR_DICT_ATTR_NO_CHILDREN
Child lookup in attribute with no children.
int fr_dict_attr_add(fr_dict_t *dict, fr_dict_attr_t const *parent, char const *name, unsigned int attr, fr_type_t type, fr_dict_attr_flags_t const *flags))
Add an attribute to the dictionary.
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
#define fr_dict_attr_is_key_field(_da)
#define FR_DICT_ATTR_MAX_NAME_LEN
Maximum length of a attribute name.
Values of the encryption flags.
Value of an enumerated attribute.
static fr_dict_attr_t const * fr_dict_attr_ref(fr_dict_attr_t const *da)
Return the reference associated with a group type attribute.
#define FR_DLIST_HEAD(_name)
Expands to the type name used for the head wrapper structure.
#define FR_IPADDR_STRLEN
Like INET6_ADDRSTRLEN but includes space for the textual Zone ID.
#define HEX_MARKER1(_data, _len, _slen, _error, _fmt,...)
static char * stack[MAX_STACK]
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_INT8
8 Bit signed integer.
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_MAX
Number of defined data types.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_INT16
16 Bit signed integer.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_VENDOR
Attribute that represents a vendor in the attribute tree.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
@ FR_TYPE_FLOAT64
Double precision floating point.
@ FR_SBUFF_PARSE_ERROR_NOT_FOUND
String does not contain a token matching the output type.
@ FR_SBUFF_PARSE_ERROR_FORMAT
Format of data was invalid.
@ FR_SBUFF_PARSE_OK
No error.
static uint8_t depth(fr_minmax_heap_index_t i)
char * fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
void fr_proto_da_stack_build_partial(fr_da_stack_t *stack, fr_dict_attr_t const *parent, fr_dict_attr_t const *da)
Complete the DA stack for a child attribute.
fr_dict_attr_t const * request_attr_request
fr_dict_attr_t const * request_attr_control
fr_dict_attr_t const * request_attr_local
fr_dict_attr_t const * request_attr_state
fr_dict_attr_t const * request_attr_reply
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_hex[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_past_strcase(fr_sbuff_t *sbuff, char const *needle, size_t needle_len)
Return true and advance past the end of the needle if needle occurs next in the sbuff.
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.
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
#define fr_sbuff_start(_sbuff_or_marker)
#define fr_sbuff_out_by_longest_prefix(_match_len, _out, _table, _sbuff, _def)
#define FR_SBUFF_IN_TABLE_STR_RETURN(_sbuff, _table, _number, _def)
#define fr_sbuff_adv_past_str_literal(_sbuff, _needle)
#define fr_sbuff_is_str_literal(_sbuff, _str)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define fr_sbuff_set(_dst, _src)
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt)
#define fr_sbuff_adv_past_strcase_literal(_sbuff, _needle)
#define fr_sbuff_current(_sbuff_or_marker)
#define FR_SBUFF_REPARSE(_sbuff_or_marker)
#define FR_SBUFF_IN_ESCAPE_BUFFER_RETURN(...)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
#define FR_SBUFF_IN_STRCPY_LITERAL_RETURN(_sbuff, _str)
#define fr_sbuff_extend(_sbuff_or_marker)
#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 FR_SBUFF(_sbuff_or_marker)
#define FR_SBUFF_IN_BSTRNCPY_RETURN(...)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_out(_err, _out, _in)
#define fr_sbuff_switch(_sbuff_or_marker, _eob)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_IN_STRCPY_RETURN(...)
#define FR_SBUFF_IN_BSTRCPY_BUFFER_RETURN(...)
Set of terminal elements.
#define tmpl_contains_xlat(vpt)
#define TMPL_VERIFY(_vpt)
#define tmpl_value_length(_tmpl)
static char const * tmpl_type_to_str(tmpl_type_t type)
Return a static string containing the type name.
#define tmpl_is_uninitialised(vpt)
Helpers to verify the type of tmpl_t.
#define tmpl_is_attr_unresolved(vpt)
enum requests_ref_e tmpl_request_ref_t
static bool tmpl_attr_tail_is_unspecified(tmpl_t const *vpt)
Return true if the last attribute reference is "unspecified".
#define tmpl_rules_enumv(_tmpl)
static bool tmpl_attr_tail_is_normal(tmpl_t const *vpt)
Return true if the last attribute reference is "normal".
#define tmpl_value(_tmpl)
#define ar_is_unknown(_ar)
static bool tmpl_attr_tail_is_unknown(tmpl_t const *vpt)
Return true if the last attribute reference is "unknown".
#define tmpl_contains_regex(vpt)
fr_value_box_safe_for_t literals_safe_for
safe_for value assigned to literal values in xlats, execs, and data.
#define tmpl_is_attr(vpt)
fr_dict_attr_t const * enumv
Enumeration attribute used to resolve enum values.
tmpl_rules_t const * parent
for parent / child relationships
#define tmpl_value_enumv(_tmpl)
static fr_dict_attr_t const * tmpl_list(tmpl_t const *vpt)
static bool tmpl_attr_is_list_attr(tmpl_attr_t const *ar)
Return true if the tmpl_attr is one of the list types.
#define ar_filter_is_num(_ar)
#define tmpl_rules_cast(_tmpl)
@ TMPL_TYPE_REGEX_UNCOMPILED
Regex where compilation is possible but hasn't been performed yet.
@ TMPL_TYPE_MAX
Marker for the last tmpl type.
@ TMPL_TYPE_ATTR_UNRESOLVED
An attribute reference that we couldn't resolve but looked valid.
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
@ TMPL_TYPE_XLAT
Pre-parsed xlat expansion.
@ TMPL_TYPE_NULL
Has no value.
@ TMPL_TYPE_EXEC
Callout to an external script or program.
@ TMPL_TYPE_REGEX_XLAT_UNRESOLVED
A regular expression with unresolved xlat functions or attribute references.
@ TMPL_TYPE_DATA
Value in native boxed format.
@ TMPL_TYPE_REGEX
Compiled (and possibly JIT'd) regular expression.
@ TMPL_TYPE_DATA_UNRESOLVED
Unparsed literal string.
@ TMPL_TYPE_XLAT_UNRESOLVED
A xlat expansion with unresolved xlat functions or attribute references.
@ TMPL_TYPE_REGEX_XLAT
A regex containing xlat expansions.
@ TMPL_TYPE_EXEC_UNRESOLVED
An exec with unresolved xlat function or attribute references.
@ TMPL_TYPE_UNINITIALISED
Uninitialised.
#define tmpl_is_regex_xlat(vpt)
#define tmpl_assert_type(_cond)
Convenience macro for printing a meaningful assert message when we get a bad tmpl type.
#define tmpl_contains_attr(vpt)
#define TMPL_FLAG_REGEX
Is a type of regular expression.
#define ar_filter_is_cond(_ar)
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 bool tmpl_is_list(tmpl_t const *vpt)
#define TMPL_ATTR_VERIFY(_vpt)
bool force_dict_def
Use supplied dict_def even if original vpt->rules->dict_def was not NULL.
#define tmpl_is_data(vpt)
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_INVALID_ARRAY_INDEX
Invalid array index.
@ TMPL_ATTR_ERROR_LIST_NOT_ALLOWED
List qualifier is not allowed here.
@ TMPL_ATTR_ERROR_UNRESOLVED_NOT_ALLOWED
Attribute couldn't be found in the dictionaries.
@ TMPL_ATTR_ERROR_BAD_CAST
Specified cast was invalid.
@ TMPL_ATTR_ERROR_INVALID_NAME
Attribute ref length is zero, or longer than the maximum.
@ TMPL_ATTR_ERROR_MISSING_TERMINATOR
Unexpected text found after attribute reference.
@ TMPL_ATTR_ERROR_LIST_MISSING
List qualifier is required, but missing.
@ TMPL_ATTR_ERROR_NONE
No error.
@ TMPL_ATTR_ERROR_FOREIGN_NOT_ALLOWED
Attribute resolved in a dictionary different to the one specified.
@ TMPL_ATTR_ERROR_UNKNOWN_NOT_ALLOWED
Attribute specified as OID, could not be found in the dictionaries, and is disallowed because 'disall...
@ TMPL_ATTR_ERROR_FILTER_NOT_ALLOWED
Filters disallowed by rules.
@ TMPL_ATTR_ERROR_EMPTY
Attribute ref contains no data.
@ TMPL_ATTR_ERROR_NESTING_TOO_DEEP
Too many levels of nesting.
#define tmpl_is_data_unresolved(vpt)
fr_type_t cast
Whether there was an explicit cast.
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
@ TMPL_ATTR_LIST_REQUIRE
Attribute refs are required to have a list.
@ TMPL_ATTR_LIST_ALLOW
Attribute refs are allowed to have a list.
@ TMPL_ATTR_LIST_FORBID
Attribute refs are forbidden from having a list.
enum tmpl_type_e tmpl_type_t
Types of tmpl_t.
static fr_dict_attr_t const * tmpl_attr_tail_unknown(tmpl_t const *vpt)
Return the last attribute reference unknown da.
#define tmpl_is_regex(vpt)
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.
static bool tmpl_attr_tail_is_raw(tmpl_t const *vpt)
Return true if the last attribute reference is "raw".
@ REQUEST_OUTER
request_t containing the outer layer of the EAP conversation.
@ REQUEST_PARENT
Parent (whatever it is).
@ REQUEST_UNKNOWN
Unknown request.
@ REQUEST_CURRENT
The current request (default).
struct tmpl_rules_s tmpl_rules_t
#define tmpl_is_regex_xlat_unresolved(vpt)
#define tmpl_is_regex_uncompiled(vpt)
fr_dict_attr_t const * enumv
for resolving T_BARE_WORD
#define TMPL_MAX_REQUEST_REF_NESTING
The maximum number of request references allowed.
@ TMPL_ATTR_TYPE_UNSPEC
No attribute was specified as this level only a filter.
@ TMPL_ATTR_TYPE_NORMAL
Normal, resolved, attribute ref.
@ TMPL_ATTR_TYPE_UNKNOWN
We have an attribute number but it doesn't match anything in the dictionary, or isn't a child of the ...
@ TMPL_ATTR_TYPE_UNRESOLVED
We have a name, but nothing else to identify the attribute.
@ TMPL_ATTR_FILTER_TYPE_TMPL
Filter is a tmpl.
@ TMPL_ATTR_FILTER_TYPE_INDEX
Filter is an index type.
@ TMPL_ATTR_FILTER_TYPE_CONDITION
Filter is a condition.
@ TMPL_ATTR_FILTER_TYPE_NONE
No filter present.
@ TMPL_ATTR_FILTER_TYPE_EXPR
Filter is an expression.
fr_event_list_t * runtime_el
The eventlist to use for runtime instantiation of xlats.
#define tmpl_needs_resolving(vpt)
tmpl_attr_filter_type_t _CONST type
Type of filter this is.
#define ar_filter_is_none(_ar)
Similar to tmpl_rules_t, but used to specify parameters that may change during subsequent resolution ...
Optional arguments passed to vp_tmpl functions.
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 entry and head types for tmpl request references.
tmpl_attr_list_presence_t list_presence
Whether the attribute reference can have a list, forbid it, or require it.
fr_dict_attr_t const * list_def
Default list to use with unqualified attribute reference.
uint8_t disallow_filters
disallow filters.
uint8_t allow_unresolved
Allow attributes that look valid but were not found in the dictionaries.
uint8_t allow_foreign
Allow arguments not found in dict_def.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
uint8_t allow_wildcard
Allow the special case of .
uint8_t allow_unknown
Allow unknown attributes i.e.
An element in a list of nested attribute references.
unsigned int _CONST resolve_only
This reference and those before it.
unsigned int _CONST is_raw
fr_dict_attr_t const *_CONST da
Resolved dictionary attribute.
fr_dict_attr_t const *_CONST parent
The parent we used when trying to resolve the attribute originally.
tmpl_attr_filter_t _CONST filter
Filter associated with the attribute reference.
tmpl_attr_type_t _CONST type
is a raw reference
Define manipulation functions for the attribute reference list.
tmpl_request_ref_t _CONST request
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in an arbitrarily ordered array of name to num mappings.
An element in a lexicographically sorted array of name to num mappings.
char * talloc_bstrdup(TALLOC_CTX *ctx, char const *in)
Binary safe strdup function.
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.
#define talloc_get_type_abort_const
static int talloc_const_free(void const *ptr)
Free const'd memory.
#define talloc_pooled_object(_ctx, _type, _num_subobjects, _total_subobjects_size)
fr_slen_t fr_time_delta_from_substr(fr_time_delta_t *out, fr_sbuff_t *in, fr_time_res_t hint, bool no_trailing, fr_sbuff_term_t const *tt)
Create fr_time_delta_t from a string.
A time delta, a difference in time measured in nanoseconds.
Escaping rules for tmpls.
int8_t tmpl_request_ref_list_cmp(FR_DLIST_HEAD(tmpl_request_list) const *a, FR_DLIST_HEAD(tmpl_request_list) const *b)
Compare a list of request qualifiers.
static ssize_t tmpl_afrom_time_delta(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules)
void tmpl_request_ref_list_debug(FR_DLIST_HEAD(tmpl_request_list) const *rql)
Dump a request list to stderr.
fr_slen_t tmpl_request_ref_list_print(fr_sbuff_t *out, FR_DLIST_HEAD(tmpl_request_list) const *rql)
void tmpl_attr_set_list(tmpl_t *vpt, fr_dict_attr_t const *list)
tmpl_t * tmpl_init_shallow(tmpl_t *vpt, tmpl_type_t type, fr_token_t quote, char const *name, ssize_t len, tmpl_rules_t const *t_rules)
Initialise a tmpl without copying the input name string.
fr_slen_t tmpl_request_ref_list_afrom_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, FR_DLIST_HEAD(tmpl_request_list) **out, fr_sbuff_t *in)
Parse one or more request references, allocing a new list and adding the references to it.
static fr_table_num_sorted_t const attr_num_table[]
Special attribute reference indexes.
void tmpl_unresolve(tmpl_t *vpt)
Reset the tmpl, leaving only the name in place.
void tmpl_set_xlat(tmpl_t *vpt, xlat_exp_head_t *xlat)
Change the default dictionary in the tmpl's resolution rules.
static void tmpl_type_init(tmpl_t *vpt, tmpl_type_t type)
Initialise fields inside a tmpl depending on its type.
#define RESOLVED_SET(_flags)
static fr_slen_t tmpl_attr_ref_afrom_unresolved_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t *vpt, fr_dict_attr_t const *parent, fr_dict_attr_t const *namespace, fr_sbuff_t *name, tmpl_attr_rules_t const *at_rules)
Parse an unresolved attribute, i.e.
void tmpl_attr_set_request_ref(tmpl_t *vpt, FR_DLIST_HEAD(tmpl_request_list) const *request_def)
Set the request for an attribute ref.
void tmpl_set_name_printf(tmpl_t *vpt, fr_token_t quote, char const *fmt,...)
Set the name on a pre-initialised tmpl.
int tmpl_attr_set_da(tmpl_t *vpt, fr_dict_attr_t const *da)
Replace the current attribute reference.
static fr_table_num_ordered_t const attr_table[]
Attr ref types.
static int tmpl_xlat_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules)
Resolve an unresolved xlat, i.e.
fr_table_num_sorted_t const tmpl_request_ref_table[]
Map keywords to tmpl_request_ref_t values.
int tmpl_afrom_value_box(TALLOC_CTX *ctx, tmpl_t **out, fr_value_box_t *data, bool steal)
Create a tmpl_t from a fr_value_box_t.
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.
int tmpl_attr_unknown_add(tmpl_t *vpt)
Add an unknown fr_dict_attr_t specified by a tmpl_t to the main dictionary.
fr_slen_t tmpl_attr_print(fr_sbuff_t *out, tmpl_t const *vpt)
Print an attribute or list tmpl_t to a string.
void tmpl_set_escape(tmpl_t *vpt, tmpl_escape_t const *escape)
Set escape parameters for the tmpl output.
bool tmpl_async_required(tmpl_t const *vpt)
Return whether or not async is required for this tmpl.
void tmpl_rules_child_init(TALLOC_CTX *ctx, tmpl_rules_t *out, tmpl_rules_t const *parent, tmpl_t *vpt)
Initialize a set of rules from a parent set of rules, and a parsed tmpl_t.
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.
static fr_slen_t tmpl_attr_ref_from_unspecified_substr(tmpl_attr_t *ar, tmpl_attr_error_t *err, tmpl_t *vpt, fr_sbuff_t *name, tmpl_attr_rules_t const *at_rules)
static void attr_to_raw(tmpl_t *vpt, tmpl_attr_t *ref)
tmpl_t * tmpl_init_printf(tmpl_t *vpt, tmpl_type_t type, fr_token_t quote, char const *fmt,...)
Initialise a tmpl using a format string to create the name.
static void tmpl_attr_insert(tmpl_t *vpt, tmpl_attr_t *ar)
Insert an attribute reference into a tmpl.
int tmpl_cast_set(tmpl_t *vpt, fr_type_t dst_type)
Set a cast for a tmpl.
static fr_slen_t tmpl_afrom_ipv4_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules)
Parse bareword as an IPv4 address or prefix.
void tmpl_set_name(tmpl_t *vpt, fr_token_t quote, char const *name, ssize_t len)
Set the name on a pre-initialised tmpl.
int tmpl_attr_afrom_list(TALLOC_CTX *ctx, tmpl_t **out, tmpl_t const *list, fr_dict_attr_t const *da)
Create a new tmpl from a list tmpl and a da.
void tmpl_attr_to_raw(tmpl_t *vpt)
Convert the leaf attribute of a tmpl to a unknown/raw type.
tmpl_t * tmpl_copy(TALLOC_CTX *ctx, tmpl_t const *in)
Copy a tmpl.
void tmpl_attr_ref_debug(const tmpl_attr_t *ar, int i)
void tmpl_attr_rewrite_leaf_num(tmpl_t *vpt, int16_t to)
Rewrite the leaf's instance number.
static bool tmpl_substr_terminal_check(fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules)
Verify, after skipping whitespace, that a substring ends in a terminal char, or ends without further ...
static void tmpl_request_ref_list_copy(TALLOC_CTX *ctx, FR_DLIST_HEAD(tmpl_request_list) *out, FR_DLIST_HEAD(tmpl_request_list) const *in)
Allocate a new request reference and add it to the end of the attribute reference list.
static void tmpl_attr_rules_debug(tmpl_attr_rules_t const *at_rules)
ssize_t tmpl_preparse(char const **out, size_t *outlen, char const *in, size_t inlen, fr_token_t *type)
Preparse a string in preparation for passing it to tmpl_afrom_substr()
#define TMPL_REQUEST_REF_DEF(_name, _ref)
Define a global variable for specifying a default request reference.
#define UNRESOLVED_SET(_flags)
void tmpl_debug(tmpl_t const *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.
static int tmpl_attr_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t *vpt, fr_dict_attr_t const *parent, fr_dict_attr_t const *namespace, fr_sbuff_t *name, fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *at_rules, unsigned int depth)
Parse an attribute reference, either an OID or attribute name.
static fr_slen_t tmpl_afrom_ipv6_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules)
Parse bareword as an IPv6 address or prefix.
static fr_slen_t tmpl_afrom_bool_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules)
Parse a truth value.
static tmpl_attr_t * tmpl_attr_add(tmpl_t *vpt, tmpl_attr_type_t type)
Allocate a new attribute reference and add it to the end of the attribute reference list.
static size_t attr_num_table_len
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, char const *name, tmpl_rules_t const *t_rules)
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
void tmpl_attr_ref_list_debug(FR_DLIST_HEAD(tmpl_attr_list) const *ar_head)
ssize_t tmpl_cast_from_substr(tmpl_rules_t *rules, fr_sbuff_t *in)
Parse a cast specifier.
static tmpl_t * tmpl_alloc_null(TALLOC_CTX *ctx)
Create a new heap allocated tmpl_t.
static fr_slen_t tmpl_request_ref_list_from_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, FR_DLIST_HEAD(tmpl_request_list) *out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, fr_dict_attr_t const **namespace)
Parse one or more request references, writing the list to out.
void tmpl_rules_debug(tmpl_rules_t const *rules)
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 ssize_t tmpl_afrom_ether_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules)
Try and parse signed or unsigned integers.
static ssize_t tmpl_afrom_float_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules)
static fr_slen_t tmpl_afrom_octets_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules)
Parse bareword as an octet string.
size_t tmpl_type_table_len
static int tmpl_attr_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules)
Resolve an unresolved attribute.
static ssize_t tmpl_afrom_enum(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
int tmpl_attr_set_leaf_da(tmpl_t *vpt, fr_dict_attr_t const *da)
Replace the leaf attribute only.
fr_slen_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
Convert an arbitrary string into a tmpl_t.
static fr_token_t tmpl_cast_quote(fr_token_t existing_quote, fr_type_t type, fr_dict_attr_t const *enumv, char const *unescaped, size_t unescaped_len)
Determine the correct quoting after a cast.
fr_dict_attr_t const * tmpl_attr_unspec
Placeholder attribute for uses of unspecified attribute references.
static fr_slen_t tmpl_afrom_value_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, tmpl_rules_t const *t_rules, bool allow_enum, fr_sbuff_parse_rules_t const *p_rules)
Create TMPL_TYPE_DATA from a string.
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules)
Attempt to resolve functions and attributes in xlats and attribute references.
void tmpl_set_dict_def(tmpl_t *vpt, fr_dict_t const *dict)
Change the default dictionary in the tmpl's resolution rules.
tmpl_t * tmpl_init(tmpl_t *vpt, tmpl_type_t type, fr_token_t quote, char const *name, ssize_t len, tmpl_rules_t const *t_rules)
Initialise a tmpl using a literal string to create the name.
static void tmpl_request_ref_list_acopy(TALLOC_CTX *ctx, FR_DLIST_HEAD(tmpl_request_list) **out, FR_DLIST_HEAD(tmpl_request_list) const *in)
Allocate a new request reference list and copy request references into it.
fr_slen_t tmpl_print(fr_sbuff_t *out, tmpl_t const *vpt, fr_sbuff_escape_rules_t const *e_rules)
Print a tmpl_t to a string.
static fr_slen_t tmpl_afrom_integer_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules)
Try and parse signed or unsigned integers.
int tmpl_cast_in_place(tmpl_t *vpt, fr_type_t type, fr_dict_attr_t const *enumv)
Convert tmpl_t of type TMPL_TYPE_DATA_UNRESOLVED or TMPL_TYPE_DATA to TMPL_TYPE_DATA of type specifie...
fr_slen_t tmpl_print_quoted(fr_sbuff_t *out, tmpl_t const *vpt)
Print a tmpl_t to a string with quotes.
static void tmpl_attr_ref_fixup(TALLOC_CTX *ctx, tmpl_t *vpt, fr_dict_attr_t const *da, fr_dict_attr_t const *parent)
static fr_slen_t tmpl_attr_parse_filter(tmpl_attr_error_t *err, tmpl_attr_t *ar, fr_sbuff_t *name, tmpl_attr_rules_t const *at_rules)
Parse array subscript and in future other filters.
fr_slen_t tmpl_attr_list_from_substr(fr_dict_attr_t const **da_p, fr_sbuff_t *in)
Parse one a single list reference.
#define DEFAULT_RULES
Default parser rules.
fr_table_num_ordered_t const tmpl_type_table[]
Map tmpl_type_t values to descriptive strings.
void tmpl_attr_debug(tmpl_t const *vpt)
static size_t attr_table_len
int tmpl_attr_tail_unresolved_add(fr_dict_t *dict_def, tmpl_t *vpt, fr_type_t type, fr_dict_attr_flags_t const *flags)
Add an unresolved fr_dict_attr_t specified by a tmpl_t to the main dictionary.
size_t tmpl_request_ref_table_len
fr_table_num_sorted_t const fr_token_quotes_table[]
const char fr_token_quote[T_TOKEN_LAST]
Convert tokens back to a quoting character.
@ T_SOLIDUS_QUOTED_STRING
bool xlat_needs_resolving(xlat_exp_head_t const *head)
Check to see if the expansion needs resolving.
bool xlat_is_literal(xlat_exp_head_t const *head)
Check to see if the expansion consists entirely of value-box elements.
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.
bool xlat_impure_func(xlat_exp_head_t const *head)
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.
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
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.
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 spaces))
Tokenize an xlat expansion into a series of XLAT_TYPE_CHILD arguments.
#define xlat_copy(_ctx, _out, _in)
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 xlat_finalize(xlat_exp_head_t *head, fr_event_list_t *runtime_el)
Bootstrap static xlats, or instantiate ephemeral ones.
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)
Structure for holding the stack of dictionary attributes being encoded.
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_const_push(_msg)
#define fr_strerror_const(_msg)
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
bool fr_type_cast(fr_type_t dst, fr_type_t src)
Return if we're allowed to cast the types.
bool const fr_type_numeric[FR_TYPE_MAX+1]
bool const fr_type_structural[FR_TYPE_MAX+1]
#define fr_type_is_non_leaf(_x)
#define fr_type_is_octets(_x)
#define fr_type_is_structural(_x)
#define fr_type_is_string(_x)
#define FR_TYPE_STRUCTURAL
#define fr_type_is_null(_x)
#define fr_type_is_leaf(_x)
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
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.
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_memdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Assign a buffer to a box, but don't copy it.
void fr_value_box_copy_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *src)
Perform a shallow copy of a value_box.
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)
fr_sbuff_escape_rules_t * fr_value_escape_by_quote[T_TOKEN_LAST]
int fr_value_box_steal(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t *src)
Copy value data verbatim moving any buffers to the specified context.
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
ssize_t fr_value_box_from_substr(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *rules)
Convert string value to a fr_value_box_t type.
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
#define fr_value_box_mark_safe_for(_box, _safe_for)
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print
#define fr_box_strvalue_len(_val, _len)
static size_t char fr_sbuff_t size_t inlen
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
static size_t char ** out
#define xlat_exp_head_alloc(_ctx)