25 RCSID(
"$Id: ae1abd172f1c138f3a209e97cb6fb630feeca3db $")
27 #include <freeradius-devel/server/request_data.h>
28 #include <freeradius-devel/server/tmpl_dcursor.h>
29 #include <freeradius-devel/unlang/xlat_func.h>
44 "Foreach-Variable-9"};
48 #define BUFFER_SIZE (256)
120 if (
vp->
da->parent != from_parent) {
121 if (
vp->
da->flags.internal) {
129 if (!child)
continue;
148 #define FOREACH_REQUEST_DATA (void *)unlang_foreach_xlat_func
193 switch (
vp->vp_type) {
204 *p_result = frame->
result;
212 RDEBUG2(
"# looping with: Foreach-Variable-%d = %pV", state->
depth, &
vp->data);
227 if (!state->
key)
return 0;
234 RDEBUG(
"Failed casting 'foreach' key variable '%s' from %u", state->
key->
da->name, state->
index);
252 *p_result = frame->
result;
260 RDEBUG(
"Failed casting 'foreach' iteration variable '%s' from %pV", state->
value->
da->name, box);
279 RDEBUG(
"Failed expanding 'foreach' list");
295 RDEBUG(
"Failed casting 'foreach' iteration variable '%s' from %pV", state->
value->
da->name, box);
318 fr_value_box_list_init(&state->
list);
321 REDEBUG(
"Failed starting expansion of %s", state->
vpt->name);
339 if (!state->
key)
return;
363 if (
vp->vp_type == state->
value->vp_type) {
376 *p_result = frame->
result;
413 RDEBUG(
"Failed casting 'foreach' iteration variable '%s' from %pP", state->
value->
da->name,
vp);
453 REDEBUG(
"Cannot do nested 'foreach' loops over the same attribute %pP",
vp);
480 if (state->
value->vp_type ==
vp->vp_type) {
495 RDEBUG(
"Failed casting 'foreach' iteration variable '%s' from %pP", state->
value->
da->name,
vp);
542 state->
indent = request->log.indent.unlang;
563 REDEBUG(
"Failed creating %s", gext->
key->name);
583 if (
stack->depth > 0)
for (i = (
stack->depth - 1); i >= 0; i--) {
585 our_instruction =
stack->frame[i].instruction;
591 REDEBUG(
"foreach Nesting too deep!");
619 switch (
vp->vp_type) {
659 *p_result = frame->
result;
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
#define fr_dcursor_init(_cursor, _head)
Initialise a cursor.
static void fr_dcursor_free_list(fr_dcursor_t *cursor)
Free the current item and all items after it.
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
static int unlang_foreach_pair_copy(fr_pair_t *to, fr_pair_t *from, fr_dict_attr_t const *from_parent)
uint32_t index
for xlat results
static char const *const xlat_foreach_names[]
static void unlang_foreach_attr_key_update(UNUSED request_t *request, unlang_frame_state_foreach_t *state)
static unlang_action_t unlang_foreach_attr_next(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
char * buffer
for key values
static int xlat_foreach_inst[]
fr_dcursor_t cursor
Used to track our place in the list.
tmpl_t const * vpt
pointer to the vpt
void unlang_foreach_init(TALLOC_CTX *ctx)
fr_pair_t * key
local variable which contains the key
static unlang_action_t unlang_foreach_attr_init(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame, unlang_frame_state_foreach_t *state)
static unlang_action_t unlang_foreach_xlat_next(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
bool success
for xlat expansion
fr_value_box_list_t list
value box list for looping over xlats
fr_pair_t * value
local variable which contains the value
int depth
Level of nesting of this foreach loop.
static unlang_action_t unlang_foreach(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
#define FOREACH_REQUEST_DATA
static unlang_action_t unlang_foreach_next_old(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
static unlang_action_t unlang_break(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
tmpl_dcursor_ctx_t cc
tmpl cursor state
int indent
for catching indentation issues
request_t * request
The current request.
static unlang_action_t unlang_foreach_xlat_expanded(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
static unlang_action_t unlang_foreach_xlat_init(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame, unlang_frame_state_foreach_t *state)
fr_pair_list_t vps
List containing the attribute(s) we're iterating over.
static int unlang_foreach_xlat_key_update(request_t *request, unlang_frame_state_foreach_t *state)
static int _free_unlang_frame_state_foreach(unlang_frame_state_foreach_t *state)
Ensure request data is pulled out of the request if the frame is popped.
static unlang_foreach_t * unlang_group_to_foreach(unlang_group_t *g)
Cast a group structure to the foreach keyword extension.
fr_dict_attr_t const * value
value variable in the foreach loop
fr_dict_attr_t const * key
key variable for the foreach loop
static xlat_action_t unlang_foreach_xlat_func(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
Implements the Foreach-Variable-X.
unlang_action_t unlang_interpret_push_children(rlm_rcode_t *p_result, request_t *request, rlm_rcode_t default_rcode, bool do_next_sibling)
Push the children of the current frame onto a new frame onto the stack.
void unlang_register(int type, unlang_op_t *op)
Register an operation with the interpreter.
unlang_op_t unlang_ops[UNLANG_TYPE_MAX]
Different operations the interpreter can execute.
static char * stack[MAX_STACK]
@ FR_TYPE_GROUP
A grouping of other attributes.
static uint8_t depth(fr_minmax_heap_index_t i)
int fr_pair_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and append)
int fr_pair_list_copy(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from)
Duplicate a list of pairs.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
fr_pair_t * fr_pair_afrom_child_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
Create a new valuepair.
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
void * request_data_get(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request.
void * request_data_reference(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request without removing it.
#define request_data_add(_request, _unique_ptr, _unique_int, _opaque, _free_on_replace, _free_on_parent, _persist)
Add opaque data to a request_t.
Declarations for the "return" keyword, used to implement other keywords.
#define FR_SBUFF_IN(_start, _len_or_end)
#define tmpl_is_xlat(vpt)
#define tmpl_is_attr(vpt)
int tmpl_copy_pairs(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, tmpl_t const *vpt))
Copy pairs matching a tmpl_t in the current request_t.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
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.
ssize_t tmpl_dcursor_print(fr_sbuff_t *out, tmpl_dcursor_ctx_t const *cc)
void tmpl_dcursor_clear(tmpl_dcursor_ctx_t *cc)
Clear any temporary state allocations.
#define tmpl_dcursor_init(_err, _ctx, _cc, _cursor, _request, _vpt)
Maintains state between cursor calls.
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.
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
#define UNLANG_NEXT_SIBLING
void * state
Stack frame specialisations.
static unlang_group_t * unlang_generic_to_group(unlang_t const *p)
@ UNLANG_TYPE_BREAK
Break statement (within a UNLANG_TYPE_FOREACH).
@ UNLANG_TYPE_FOREACH
Foreach section.
unlang_t const * instruction
The unlang node we're evaluating.
static void break_point_set(unlang_stack_frame_t *frame)
rlm_rcode_t result
The result from executing the instruction.
char const * name
Name of the operation.
static bool is_stack_unwinding_to_break(unlang_stack_t *stack)
static void repeatable_set(unlang_stack_frame_t *frame)
static unlang_action_t unwind_to_break(unlang_stack_t *stack)
unlang_process_t process
function to call for interpreting this stack frame
unlang_type_t type
The specialisation of this node.
Generic representation of a grouping.
A node in a graph of unlang_op_t (s) that we execute.
Our interpreter stack, as distinct from the C stack.
An unlang stack associated with a request.
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
#define fr_pair_list_foreach(_list_head, _iter)
Iterate over the contents of a fr_pair_list_t.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
#define fr_type_is_structural(_x)
#define fr_type_is_leaf(_x)
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.
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.
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
#define fr_value_box(_box, _var, _tainted)
Automagically fill in a box, determining the value type from the type of the C variable.
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
static size_t char ** out
void const * inst
xlat instance data.
void xlat_func_flags_set(xlat_t *x, xlat_func_flags_t flags)
Specify flags that alter the xlat's behaviour.
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
@ XLAT_FUNC_FLAG_INTERNAL
String expansion ("translation").
void * uctx
uctx to pass to instantiation functions.