27 RCSID(
"$Id: 10c829ad1e0f3b97c878f7c0b817bbb44533b35c $")
29 #include <freeradius-devel/server/exec.h>
30 #include <freeradius-devel/server/exec_legacy.h>
31 #include <freeradius-devel/server/tmpl.h>
32 #include <freeradius-devel/server/tmpl_dcursor.h>
33 #include <freeradius-devel/util/dlist.h>
34 #include <freeradius-devel/util/proto.h>
35 #include <freeradius-devel/util/value.h>
36 #include <freeradius-devel/util/edit.h>
38 static inline CC_HINT(always_inline)
82 static inline CC_HINT(always_inline)
87 if (tmpl_attr_list_next(&cc->vpt->data.attribute.ar, ar)) {
124 static inline CC_HINT(always_inline)
137 if (!ar)
goto all_inst;
156 if (
tmpl_expand(&ref, NULL, 0, cc->request, ar->ar_tmpl, NULL, NULL) < 0) {
183 RPEDEBUG(
"Failed evaluating expression");
194 RDEBUG(
"Attribute filter is unsupported");
258 if (!
vp && cc->build && ar)
switch (num) {
302 ar = tmpl_attr_list_next(&
vpt->data.attribute.ar, ar);
306 list_head = &
vp->vp_group;
325 #ifdef TMPL_DCURSOR_MOD
401 .list = &list->vp_group,
423 #ifndef TMPL_DCURSOR_MOD
484 memset(cc, 0,
sizeof(*cc));
487 list = request->pair_root;
501 if (!cc->
pool)
return;
506 TALLOC_FREE(cc->
pool);
531 #define EXTENT_ADD(_out, _ar, _list_ctx, _list) \
533 tmpl_attr_extent_t *_extent; \
534 MEM(_extent = talloc(ctx, tmpl_attr_extent_t)); \
535 *_extent = (tmpl_attr_extent_t){ \
537 .list_ctx = _list_ctx, \
540 fr_dlist_insert_tail(_out, _extent); \
576 TALLOC_CTX *list_ctx = NULL;
592 list_head = &request->pair_root->vp_group;
593 list_ctx = request->pair_root;
604 ar = tmpl_attr_list_head(&
vpt->data.attribute.ar);
605 switch (ar->ar_da->
type) {
610 if (existing)
EXTENT_ADD(existing, NULL, list_ctx, list_head);
658 n_ar = tmpl_attr_list_next(&
vpt->data.attribute.ar, ar);
661 list_head = &curr->vp_group;
676 if (existing)
EXTENT_ADD(existing, NULL, list_ctx, list_head);
701 TALLOC_CTX *list_ctx;
711 for (ar = extent->
ar, list = extent->
list, list_ctx = extent->
list_ctx;
713 ar = tmpl_attr_list_next(&
vpt->data.attribute.ar, ar)) {
724 list = &
vp->vp_group;
729 fr_assert_fail(
"references of this type should have been resolved");
754 char const *ctx_name;
763 ctx_name = talloc_get_name(extent->
list_ctx);
764 if (strcmp(ctx_name,
"fr_pair_t") == 0) {
791 while ((rr = tmpl_request_list_next(&cc->
vpt->data.attribute.rr, rr))) {
801 while ((ar = tmpl_attr_list_next(
tmpl_attr(cc->
vpt), ar))) {
802 if (ns->
ar == ar)
break;
static void * fr_dcursor_remove(fr_dcursor_t *cursor)
Remove the current item.
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
static int fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
Insert directly after the current item.
#define fr_dcursor_init(_cursor, _head)
Initialise a cursor.
static void * fr_dcursor_set_current(fr_dcursor_t *cursor, void *item)
Set the cursor to a specified item.
fr_dcursor_eval_t void const * uctx
fr_dcursor_iter_t void * current
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
#define fr_dcursor_iter_mod_init(_cursor, _list, _iter, _peek, _iter_uctx, _insert, _remove, _mod_uctx)
Initialise a cursor with a custom iterator.
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
#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,...)
static int8_t fr_dict_attr_cmp(fr_dict_attr_t const *a, fr_dict_attr_t const *b)
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
static void fr_dlist_talloc_free(fr_dlist_head_t *head)
Free all items in a doubly linked list (with talloc)
static void * fr_dlist_pop_tail(fr_dlist_head_t *list_head)
Remove the tail item in a list.
static void * fr_dlist_tail(fr_dlist_head_t const *list_head)
Return the TAIL item of a list or NULL if the list is empty.
static void * fr_dlist_head(fr_dlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
static void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
Head of a doubly linked list.
#define RPEDEBUG(fmt,...)
@ FR_TYPE_UINT8
8 Bit unsigned integer.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
fr_dict_attr_t const * request_attr_local
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define FR_SBUFF_IN_SPRINTF_RETURN(...)
#define FR_SBUFF(_sbuff_or_marker)
#define FR_SBUFF_IN_STRCPY_RETURN(...)
#define TMPL_VERIFY(_vpt)
#define ar_is_unspecified(_ar)
#define ar_filter_is_tmpl(_ar)
TALLOC_CTX * list_ctx
Where to allocate new attributes if building out from the current extents of the tree.
fr_table_num_sorted_t const tmpl_request_ref_table[]
Map keywords to tmpl_request_ref_t values.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
void tmpl_attr_ref_debug(const tmpl_attr_t *ar, int idx)
#define tmpl_is_attr(vpt)
#define ar_filter_is_num(_ar)
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
static bool tmpl_is_list(tmpl_t const *vpt)
#define ar_filter_is_expr(_ar)
int tmpl_request_ptr(request_t **request, FR_DLIST_HEAD(tmpl_request_list) const *rql)
Resolve a tmpl_request_ref_t to a request_t.
fr_pair_list_t * list
List that we tried to evaluate ar in and failed.
#define ar_is_normal(_ar)
#define tmpl_expand(_out, _buff, _buff_len, _request, _vpt, _escape, _escape_ctx)
Expand a tmpl to a C type, using existing storage to hold variably sized types.
@ 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_t const * ar
Attribute representing the ar after the deepest node that was found in the existing pair tree when ev...
#define ar_filter_is_none(_ar)
Describes the current extents of a pair tree in relation to the tree described by a tmpl_t.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
An element in a list of nested attribute references.
unsigned int _CONST resolve_only
This reference and those before it.
fr_dict_attr_t const *_CONST da
Resolved dictionary attribute.
tmpl_attr_type_t _CONST type
is a raw reference
Define manipulation functions for the attribute reference list.
tmpl_request_ref_t _CONST request
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
fr_pair_t * tmpl_dcursor_init_relative(int *err, TALLOC_CTX *ctx, tmpl_dcursor_ctx_t *cc, fr_dcursor_t *cursor, request_t *request, fr_pair_t *list, tmpl_t const *vpt, tmpl_dcursor_build_t build, void *uctx)
Initialise a fr_dcursor_t at the specified point in a pair tree.
static void * _tmpl_cursor_next(UNUSED fr_dlist_head_t *list, void *curr, void *uctx)
ssize_t tmpl_dcursor_print(fr_sbuff_t *out, tmpl_dcursor_ctx_t const *cc)
static void _tmpl_cursor_pair_init(TALLOC_CTX *list_ctx, fr_pair_list_t *list, tmpl_attr_t const *ar, tmpl_dcursor_ctx_t *cc)
Initialise the evaluation context for traversing a group attribute.
fr_pair_t * _tmpl_dcursor_init(int *err, TALLOC_CTX *ctx, tmpl_dcursor_ctx_t *cc, fr_dcursor_t *cursor, request_t *request, tmpl_t const *vpt, tmpl_dcursor_build_t build, void *uctx)
Initialise a fr_dcursor_t to the fr_pair_t specified by a tmpl_t.
static fr_pair_t * _tmpl_cursor_eval(fr_pair_t *curr, tmpl_dcursor_ctx_t *cc)
Evaluates, then, sometimes, pops evaluation contexts from the tmpl stack.
int tmpl_extents_build_to_leaf_parent(fr_dlist_head_t *existing, fr_dlist_head_t *to_build, tmpl_t const *vpt)
Allocate interior pairs.
int tmpl_extents_find(TALLOC_CTX *ctx, fr_dlist_head_t *existing, fr_dlist_head_t *to_build, request_t *request, tmpl_t const *vpt)
Determines points where the reference list extends beyond the current pair tree.
fr_pair_t * tmpl_dcursor_pair_build(fr_pair_t *parent, fr_dcursor_t *cursor, fr_dict_attr_t const *da, UNUSED void *uctx)
Simple pair building callback for use with tmpl_dcursors.
static void tmpl_cursor_nested_push(tmpl_dcursor_ctx_t *cc, tmpl_dcursor_nested_t *ns)
static void tmpl_cursor_nested_pop(tmpl_dcursor_ctx_t *cc)
static void _tmpl_cursor_pool_init(tmpl_dcursor_ctx_t *cc)
static void * _tmpl_cursor_child_next(fr_dlist_head_t *list, void *curr, void *uctx)
Traverse a list of attributes.
void tmpl_dcursor_clear(tmpl_dcursor_ctx_t *cc)
Clear any temporary state allocations.
void tmpl_extents_debug(fr_dlist_head_t *head)
#define EXTENT_ADD(_out, _ar, _list_ctx, _list)
tmpl_dcursor_nested_t leaf
Pre-allocated leaf state.
fr_pair_list_t * list
List within the request.
fr_dcursor_t cursor
Cursor to track where we are in the list in case we're doing counts.
fr_pair_t *(* tmpl_dcursor_build_t)(fr_pair_t *parent, fr_dcursor_t *cursor, fr_dict_attr_t const *da, void *uctx)
Callback function for populating missing pair.
struct tmpl_dcursor_ctx_s tmpl_dcursor_ctx_t
size_t num
which attribute number we are looking at
fr_dlist_head_t nested
Nested state.
tmpl_t const * vpt
tmpl we're evaluating.
struct tmpl_dcursor_nested_s tmpl_dcursor_nested_t
TALLOC_CTX * pool
Temporary pool.
TALLOC_CTX * list_ctx
Track where we should be allocating attributes.
tmpl_attr_t const * ar
Attribute reference this state entry is associated with.
Maintains state between cursor calls.
State for traversing an attribute reference.
int unlang_xlat_eval_type(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t type, fr_dict_attr_t const *enumv, request_t *request, xlat_exp_head_t const *xlat)
Evaluate a "pure" (or not impure) xlat.
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
#define fr_pair_dcursor_iter_init(_cursor, _list, _iter, _uctx)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
fr_dlist_head_t * fr_pair_list_to_dlist(fr_pair_list_t const *list)
Get the dlist head from a pair list.
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_type_is_structural(_x)
#define FR_TYPE_STRUCTURAL
FR_SBUFF_SET_RETURN(sbuff, &our_sbuff)
static size_t char ** out