The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
unlang_priv.h
Go to the documentation of this file.
1#pragma once
2/*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 */
17
18/**
19 * $Id: 7ce023a20285895c77791290cb4f8dceeff6524f $
20 *
21 * @file unlang/unlang_priv.h
22 * @brief Private interpreter structures and functions
23 *
24 * @author Alan DeKok (aland@freeradius.org)
25 *
26 * @copyright 2016-2019 The FreeRADIUS server project
27 */
28#include <freeradius-devel/server/cf_util.h> /* Need CONF_* definitions */
29#include <freeradius-devel/server/map_proc.h>
30#include <freeradius-devel/server/modpriv.h>
31#include <freeradius-devel/util/debug.h>
32#include <freeradius-devel/unlang/base.h>
33#include <freeradius-devel/io/listen.h>
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39/** Types of unlang_t nodes
40 *
41 * Here are our basic types: unlang_t, unlang_group_t, and unlang_module_t. For an
42 * explanation of what they are all about, see doc/unlang/configurable_failover.adoc
43 */
44typedef enum {
45 UNLANG_TYPE_NULL = 0, //!< unlang type not set.
46 UNLANG_TYPE_MODULE = 1, //!< Module method.
47 UNLANG_TYPE_FUNCTION, //!< Internal call to a function or submodule.
48 UNLANG_TYPE_GROUP, //!< Grouping section.
49 UNLANG_TYPE_REDUNDANT, //!< exactly like group, but with different default return codes
50 UNLANG_TYPE_LOAD_BALANCE, //!< Load balance section.
51 UNLANG_TYPE_REDUNDANT_LOAD_BALANCE, //!< Redundant load balance section.
52 UNLANG_TYPE_PARALLEL, //!< execute statements in parallel
53 UNLANG_TYPE_IF, //!< Condition.
54 UNLANG_TYPE_ELSE, //!< !Condition.
55 UNLANG_TYPE_ELSIF, //!< !Condition && Condition.
56 UNLANG_TYPE_UPDATE, //!< Update block.
57 UNLANG_TYPE_SWITCH, //!< Switch section.
58 UNLANG_TYPE_CASE, //!< Case section (within a #UNLANG_TYPE_SWITCH).
59 UNLANG_TYPE_FOREACH, //!< Foreach section.
60 UNLANG_TYPE_BREAK, //!< Break statement (within a #UNLANG_TYPE_FOREACH).
61 UNLANG_TYPE_RETURN, //!< Return statement.
62 UNLANG_TYPE_MAP, //!< Mapping section (like #UNLANG_TYPE_UPDATE, but uses
63 //!< values from a #map_proc_t call).
64 UNLANG_TYPE_SUBREQUEST, //!< create a child subrequest
65 UNLANG_TYPE_DETACH, //!< detach a child
66 UNLANG_TYPE_CALL, //!< call another virtual server
67 UNLANG_TYPE_CALLER, //!< conditionally check parent dictionary type
68 UNLANG_TYPE_TIMEOUT, //!< time-based timeouts.
69 UNLANG_TYPE_LIMIT, //!< limit number of requests in a section
70 UNLANG_TYPE_TRANSACTION, //!< transactions for editing lists
71 UNLANG_TYPE_TRY, //!< try / catch blocks
72 UNLANG_TYPE_CATCH, //!< catch a previous try
73 UNLANG_TYPE_POLICY, //!< Policy section.
74 UNLANG_TYPE_XLAT, //!< Represents one level of an xlat expansion.
75 UNLANG_TYPE_TMPL, //!< asynchronously expand a tmpl_t
76 UNLANG_TYPE_EDIT, //!< edit VPs in place. After 20 years!
79
80/** Allows the frame evaluator to signal the interpreter
81 *
82 */
83typedef enum {
84 UNLANG_FRAME_ACTION_POP = 1, //!< Pop the current frame, and check the next one further
85 ///< up in the stack for what to do next.
86 UNLANG_FRAME_ACTION_RETRY, //!< retry the current frame
87 UNLANG_FRAME_ACTION_NEXT, //!< Process the next instruction at this level.
88 UNLANG_FRAME_ACTION_YIELD //!< Temporarily return control back to the caller on the C
89 ///< stack.
91
92#define UNLANG_NEXT_STOP (false)
93#define UNLANG_NEXT_SIBLING (true)
94
95#define UNLANG_DETACHABLE (true)
96#define UNLANG_NORMAL_CHILD (false)
97
98typedef struct unlang_s unlang_t;
100
101/** A node in a graph of #unlang_op_t (s) that we execute
102 *
103 * The interpreter acts like a turing machine, with #unlang_t nodes forming the tape
104 * and the #unlang_action_t the instructions.
105 *
106 * This is the parent 'class' for multiple #unlang_t node specialisations.
107 * The #unlang_t struct is listed first in the specialisation so that we can cast between
108 * parent/child classes without knowledge of the layout of the structures.
109 *
110 * The specialisations of the nodes describe additional details of the operation to be performed.
111 */
112struct unlang_s {
113 unlang_t *parent; //!< Previous node.
114 unlang_t *next; //!< Next node (executed on #UNLANG_ACTION_EXECUTE_NEXT et al).
115 char const *name; //!< Unknown...
116 char const *debug_name; //!< Printed in log messages when the node is executed.
117 unlang_type_t type; //!< The specialisation of this node.
118 bool closed; //!< whether or not this section is closed to new statements
119 CONF_ITEM *ci; //!< used to generate this item
120 unsigned int number; //!< unique node number
121 unlang_mod_actions_t actions; //!< Priorities, etc. for the various return codes.
122};
123
124/** Describes how to allocate an #unlang_group_t with additional memory keyword specific data
125 *
126 */
127typedef struct {
128 unlang_type_t type; //!< Keyword.
129 size_t len; //!< Total length of the unlang_group_t + specialisation struct.
130 unsigned pool_headers; //!< How much additional space to allocate for chunk headers.
131 size_t pool_len; //!< How much additional space to allocate for extensions.
132 char const *type_name; //!< Talloc type name.
134
135typedef struct {
136 fr_dict_t *dict; //!< our dictionary
137 fr_dict_attr_t const *root; //!< the root of our dictionary
138 int max_attr; //!< 1..N local attributes have been defined
140
141/** Generic representation of a grouping
142 *
143 * Can represent IF statements, maps, update sections etc...
144 */
145typedef struct {
147 unlang_t *children; //!< Children beneath this group. The body of an if
148 //!< section for example.
149 unlang_t **tail; //!< pointer to the tail which gets updated
152
153 unlang_variable_t *variables; //!< rarely used, so we don't usually need it
155
156/** A naked xlat
157 *
158 * @note These are vestigial and may be removed in future.
159 */
160typedef struct {
162 tmpl_t const *tmpl;
164
165/** Function to call when interpreting a frame
166 *
167 * @param[in,out] p_result Pointer to the current rcode, may be modified by the function.
168 * @param[in] request The current request.
169 * @param[in] frame being executed.
170 *
171 * @return an action for the interpreter to perform.
172 */
174 unlang_stack_frame_t *frame);
175
176/** Function to call if the request was signalled
177 *
178 * This is the instruction specific cancellation function.
179 * This function will usually either call a more specialised cancellation function
180 * set when something like a module yielded, or just cleanup the state of the original
181 * #unlang_process_t.
182 *
183 * @param[in] request The current request.
184 * @param[in] frame being signalled.
185 * @param[in] action We're being signalled with.
186 */
187typedef void (*unlang_signal_t)(request_t *request,
188 unlang_stack_frame_t *frame, fr_signal_t action);
189
190/** Custom callback for dumping information about frame state
191 *
192 * @param[in] request The current request.
193 * @param[in] frame to provide additional information for.
194 */
195typedef void (*unlang_dump_t)(request_t *request, unlang_stack_frame_t *frame);
196
197typedef int (*unlang_thread_instantiate_t)(unlang_t const *instruction, void *thread_inst);
198
199/** An unlang operation
200 *
201 * These are like the opcodes in other interpreters. Each operation, when executed
202 * will return an #unlang_action_t, which determines what the interpreter does next.
203 */
204typedef struct {
205 char const *name; //!< Name of the operation.
206
207 unlang_process_t interpret; //!< Function to interpret the keyword
208
209 unlang_signal_t signal; //!< Function to signal stop / dup / whatever
210
211 unlang_dump_t dump; //!< Dump additional information about the frame state.
212
213 unlang_thread_instantiate_t thread_instantiate; //!< per-thread instantiation function
215 char const *thread_inst_type;
216
217
218 bool debug_braces; //!< Whether the operation needs to print braces
219 ///< in debug mode.
220
221 bool rcode_set; //!< Set request->rcode to the result of this operation.
222
223 size_t frame_state_size; //!< size of instance data in the stack frame
224
225 char const *frame_state_type; //!< talloc name of the frame instance data
226
227 size_t frame_state_pool_objects; //!< How many sub-allocations we expect.
228
229 size_t frame_state_pool_size; //!< The total size of the pool to alloc.
231
232typedef struct {
233 unlang_t const *instruction; //!< instruction which we're executing
234 void *thread_inst; //!< thread-specific instance data
235#ifdef WITH_PERF
236 uint64_t use_count; //!< how many packets it has processed
237 uint64_t running; //!< currently running this instruction
238 uint64_t yielded; //!< currently yielded
239 fr_time_tracking_t tracking; //!< tracking cpu time
240#endif
242
243void *unlang_thread_instance(unlang_t const *instruction);
244
245#ifdef WITH_PERF
250#else
251#define unlang_frame_perf_init(_x)
252#define unlang_frame_perf_yield(_x)
253#define unlang_frame_perf_resume(_x)
254#define unlang_frame_perf_cleanup(_x)
255#endif
256
257void unlang_frame_signal(request_t *request, fr_signal_t action, int limit);
258
267
268/** Our interpreter stack, as distinct from the C stack
269 *
270 * We don't call the modules recursively. Instead we iterate over a list of #unlang_t and
271 * and manage the call stack ourselves.
272 *
273 * After looking at various green thread implementations, it was decided that using the existing
274 * unlang interpreter stack was the best way to perform async I/O.
275 *
276 * Each request as an unlang interpreter stack associated with it, which represents its progress
277 * through the server. Because the interpreter stack is distinct from the C stack, we can have
278 * a single system thread with many thousands of pending requests.
279 */
281 unlang_t const *instruction; //!< The unlang node we're evaluating.
282 unlang_t const *next; //!< The next unlang node we will evaluate
283
284 unlang_process_t process; //!< function to call for interpreting this stack frame
285 unlang_signal_t signal; //!< function to call when signalling this stack frame
286
287 /** Stack frame specialisations
288 *
289 * These store extra (mutable) state data, for the immutable (#unlang_t)
290 * instruction. Instructions can't be used to store data because they
291 * might be shared between multiple threads.
292 *
293 * Which stack_entry specialisation to use is determined by the
294 * instruction->type.
295 */
296 void *state;
297
298 unlang_retry_t *retry; //!< if the frame is being retried.
299
300 rlm_rcode_t result; //!< The result from executing the instruction.
301 int priority; //!< Result priority. When we pop this stack frame
302 ///< this priority will be compared with the one of the
303 ///< frame lower in the stack to determine if the
304 ///< result stored in the lower stack frame should
305 uint8_t uflags; //!< Unwind markers
306#ifdef WITH_PERF
307 fr_time_tracking_t tracking; //!< track this instance of this instruction
308#endif
309};
310
311/** An unlang stack associated with a request
312 *
313 */
314typedef struct {
315 unlang_interpret_t *intp; //!< Interpreter that the request is currently
316 ///< associated with.
317 int priority; //!< Current priority.
318 rlm_rcode_t result; //!< The current stack rcode.
319 int depth; //!< Current depth we're executing at.
320 uint8_t unwind; //!< Unwind to this frame if it exists.
321 ///< This is used for break and return.
322 unlang_stack_frame_t frame[UNLANG_STACK_MAX]; //!< The stack...
324
325/** Different operations the interpreter can execute
326 */
327extern unlang_op_t unlang_ops[];
328
329#define MOD_NUM_TYPES (UNLANG_TYPE_XLAT + 1)
330
332extern size_t mod_rcode_table_len;
333
334#define UNWIND_FLAG_NONE 0x00 //!< No flags.
335#define UNWIND_FLAG_REPEAT 0x01 //!< Repeat the frame on the way up the stack.
336#define UNWIND_FLAG_TOP_FRAME 0x02 //!< are we the top frame of the stack?
337 ///< If true, causes the interpreter to stop
338 ///< interpreting and return, control then passes
339 ///< to whatever called the interpreter.
340#define UNWIND_FLAG_BREAK_POINT 0x04 //!< 'break' stops here.
341#define UNWIND_FLAG_RETURN_POINT 0x08 //!< 'return' stops here.
342#define UNWIND_FLAG_NO_CLEAR 0x10 //!< Keep unwinding, don't clear the unwind flag.
343#define UNWIND_FLAG_YIELDED 0x20 //!< frame has yielded
344
345static inline void repeatable_set(unlang_stack_frame_t *frame) { frame->uflags |= UNWIND_FLAG_REPEAT; }
346static inline void top_frame_set(unlang_stack_frame_t *frame) { frame->uflags |= UNWIND_FLAG_TOP_FRAME; }
349static inline void yielded_set(unlang_stack_frame_t *frame) { frame->uflags |= UNWIND_FLAG_YIELDED; }
350
351static inline void repeatable_clear(unlang_stack_frame_t *frame) { frame->uflags &= ~UNWIND_FLAG_REPEAT; }
352static inline void top_frame_clear(unlang_stack_frame_t *frame) { frame->uflags &= ~UNWIND_FLAG_TOP_FRAME; }
353static inline void break_point_clear(unlang_stack_frame_t *frame) { frame->uflags &= ~UNWIND_FLAG_BREAK_POINT; }
354static inline void return_point_clear(unlang_stack_frame_t *frame) { frame->uflags &= ~UNWIND_FLAG_RETURN_POINT; }
355static inline void yielded_clear(unlang_stack_frame_t *frame) { frame->uflags &= ~UNWIND_FLAG_YIELDED; }
356
357static inline bool is_repeatable(unlang_stack_frame_t const *frame) { return frame->uflags & UNWIND_FLAG_REPEAT; }
358static inline bool is_top_frame(unlang_stack_frame_t const *frame) { return frame->uflags & UNWIND_FLAG_TOP_FRAME; }
359static inline bool is_break_point(unlang_stack_frame_t const *frame) { return frame->uflags & UNWIND_FLAG_BREAK_POINT; }
360static inline bool is_return_point(unlang_stack_frame_t const *frame) { return frame->uflags & UNWIND_FLAG_RETURN_POINT; }
361static inline bool is_yielded(unlang_stack_frame_t const *frame) { return frame->uflags & UNWIND_FLAG_YIELDED; }
362
378
382static inline void stack_unwind_top_frame_clear(unlang_stack_t *stack) { stack->unwind &= ~UNWIND_FLAG_TOP_FRAME; }
383static inline void stack_unwind_break_clear(unlang_stack_t *stack) { stack->unwind &= ~UNWIND_FLAG_BREAK_POINT; }
384static inline void stack_unwind_return_clear(unlang_stack_t *stack) { stack->unwind &= ~UNWIND_FLAG_RETURN_POINT; }
385
387{
388 unlang_stack_t *stack = request->stack;
389
390 return &stack->frame[stack->depth];
391}
392
393static inline int stack_depth_current(request_t *request)
394{
395 unlang_stack_t *stack = request->stack;
396
397 return stack->depth;
398}
399
401{
402 unlang_t const *instruction = frame->instruction;
403 unlang_op_t *op;
404 char const *name;
405
407
408 op = &unlang_ops[instruction->type];
409 name = op->frame_state_type ? op->frame_state_type : __location__;
410
411 frame->process = op->interpret;
412 frame->signal = op->signal;
413
414#ifdef HAVE_TALLOC_ZERO_POOLED_OBJECT
415 /*
416 * Pooled object
417 */
419 MEM(frame->state = _talloc_zero_pooled_object(stack,
423 } else
424#endif
425 /*
426 * Pool
427 */
428 if (op->frame_state_pool_size && !op->frame_state_size) {
429 MEM(frame->state = talloc_pool(stack,
431 ((20 + 68 + 15) * op->frame_state_pool_objects))); /* from samba talloc.c */
432 talloc_set_name_const(frame->state, name);
433 /*
434 * Object
435 */
436 } else if (op->frame_state_size) {
437 MEM(frame->state = _talloc_zero(stack, op->frame_state_size, name));
438 }
439
440 /*
441 * Don't change frame->retry, it may be left over from a previous retry.
442 */
443}
444
445/** Cleanup any lingering frame state
446 *
447 */
448static inline void frame_cleanup(unlang_stack_frame_t *frame)
449{
451
452 /*
453 * Don't clear top_frame flag, bad things happen...
454 */
456 if (frame->state) {
457 talloc_free_children(frame->state); /* *(ev->parent) = NULL in event.c */
458 TALLOC_FREE(frame->state);
459 }
460}
461
462/** Advance to the next sibling instruction
463 *
464 */
466{
467 frame_cleanup(frame);
468 frame->instruction = frame->next;
469
470 if (!frame->instruction) return;
471
472 frame->next = frame->instruction->next;
473
474 frame_state_init(stack, frame);
475}
476
477/** Pop a stack frame, removing any associated dynamically allocated state
478 *
479 * @param[in] request The current request.
480 * @param[in] stack frame to pop.
481 */
482static inline void frame_pop(request_t *request, unlang_stack_t *stack)
483{
485
486 fr_assert(stack->depth > 1);
487
488 frame = &stack->frame[stack->depth];
489
490 /*
491 * We clean up the retries when we pop the frame, not
492 * when we do a frame_cleanup(). That's because
493 * frame_cleanup() is called from the signal handler, and
494 * we need to keep frame->retry around to ensure that we
495 * know how to _stop_ the retries after they've hit a timeout.
496 */
497 TALLOC_FREE(frame->retry);
498
499 frame_cleanup(frame);
500
501 frame = &stack->frame[--stack->depth];
502
503 /*
504 * Signal the frame to get it back into a consistent state
505 * as we won't be calling the resume function.
506 */
507 if (stack->unwind && is_repeatable(frame) &&
510 if (frame->signal) frame->signal(request, frame, FR_SIGNAL_CANCEL);
511 repeatable_clear(frame);
512 }
513}
514
515/** Mark the current stack frame up for repeat, and set a new process function
516 *
517 */
518static inline void frame_repeat(unlang_stack_frame_t *frame, unlang_process_t process)
519{
520 repeatable_set(frame);
521 frame->process = process;
522}
523
524/** @name Conversion functions for converting #unlang_t to its specialisations
525 *
526 * Simple conversions: #unlang_module_t and #unlang_group_t are subclasses of #unlang_t,
527 * so we often want to go back and forth between them.
528 *
529 * @{
530 */
532{
534
535 return UNCONST(unlang_group_t *, p);
536}
537
539{
540 return UNCONST(unlang_t *, p);
541}
542
548
550{
551 return UNCONST(unlang_t *, p);
552}
553/** @} */
554
555/** @name Internal interpreter functions needed by ops
556 *
557 * @{
558 */
559int unlang_interpret_push(request_t *request, unlang_t const *instruction,
560 rlm_rcode_t default_rcode, bool do_next_sibling, bool top_frame)
561 CC_HINT(warn_unused_result);
562
564 rlm_rcode_t default_rcode, bool do_next_sibling)
565 CC_HINT(warn_unused_result);
566
568
569void unlang_op_free(void);
570
571/** @} */
572
573/** @name io shims
574 *
575 * Functions to simulate a 'proto' module when we're running 'fake'
576 * requests. i.e. those created by parallel and subrequest.
577 *
578 * @{
579 */
580request_t *unlang_io_subrequest_alloc(request_t *parent, fr_dict_t const *namespace, bool detachable);
581
582/** @} */
583
584/** @name op init functions
585 *
586 * Functions to trigger registration of the various unlang ops.
587 *
588 * @{
589 */
590void unlang_register(int type, unlang_op_t *op);
591
592void unlang_call_init(void);
593
594void unlang_caller_init(void);
595
596void unlang_condition_init(void);
597
598void unlang_foreach_init(TALLOC_CTX *ctx);
599
600void unlang_function_init(void);
601
602void unlang_group_init(void);
603
604void unlang_load_balance_init(void);
605
606void unlang_map_init(void);
607
608void unlang_module_init(void);
609
610void unlang_return_init(void);
611
612void unlang_parallel_init(void);
613
615
617
618void unlang_detach_init(void);
619
620void unlang_switch_init(void);
621
622void unlang_tmpl_init(void);
623
624void unlang_edit_init(void);
625
626void unlang_timeout_init(void);
627
628void unlang_transaction_init(void);
629
630void unlang_limit_init(void);
631
632void unlang_try_init(void);
633
634void unlang_catch_init(void);
635
636 /** @} */
637
638#ifdef __cplusplus
639}
640#endif
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_UNWIND
Break out of the current group.
Definition action.h:41
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
Common header for all CONF_* types.
Definition cf_priv.h:49
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
#define MEM(x)
Definition debug.h:36
#define UNLANG_STACK_MAX
The maximum depth of the stack.
Definition interpret.h:38
A timer event.
Definition event.c:102
static char * stack[MAX_STACK]
Definition radmin.c:158
unsigned int uint32_t
unsigned char uint8_t
#define fr_assert(_expr)
Definition rad_assert.h:38
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
static char const * name
fr_signal_t
Signals that can be generated/processed by request signal handlers.
Definition signal.h:38
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
fr_aka_sim_id_type_t type
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
#define talloc_get_type_abort_const
Definition talloc.h:282
"server local" time.
Definition time.h:69
#define UNWIND_FLAG_RETURN_POINT
'return' stops here.
fr_retry_state_t state
#define unlang_frame_perf_resume(_x)
size_t frame_state_pool_objects
How many sub-allocations we expect.
void unlang_register(int type, unlang_op_t *op)
Register an operation with the interpreter.
Definition base.c:63
static void frame_pop(request_t *request, unlang_stack_t *stack)
Pop a stack frame, removing any associated dynamically allocated state.
unlang_t * next
Next node (executed on UNLANG_ACTION_EXECUTE_NEXT et al).
static void frame_next(unlang_stack_t *stack, unlang_stack_frame_t *frame)
Advance to the next sibling instruction.
static unlang_action_t unwind_to_return(unlang_stack_t *stack)
void unlang_switch_init(void)
Definition switch.c:142
static bool is_repeatable(unlang_stack_frame_t const *frame)
#define UNWIND_FLAG_TOP_FRAME
are we the top frame of the stack? If true, causes the interpreter to stop interpreting and return,...
unlang_interpret_t * intp
Interpreter that the request is currently associated with.
CONF_SECTION * cs
static void repeatable_clear(unlang_stack_frame_t *frame)
unlang_retry_t * retry
if the frame is being retried.
unlang_signal_t signal
function to call when signalling this stack frame
char const * debug_name
Printed in log messages when the node is executed.
char const * frame_state_type
talloc name of the frame instance data
char const * type_name
Talloc type name.
void * state
Stack frame specialisations.
void unlang_foreach_init(TALLOC_CTX *ctx)
Definition foreach.c:693
unlang_mod_actions_t actions
Priorities, etc. for the various return codes.
void(* unlang_signal_t)(request_t *request, unlang_stack_frame_t *frame, fr_signal_t action)
Function to call if the request was signalled.
unlang_t * parent
Previous node.
void unlang_limit_init(void)
Definition limit.c:124
unlang_action_t(* unlang_process_t)(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Function to call when interpreting a frame.
unlang_signal_t signal
Function to signal stop / dup / whatever.
int unlang_subrequest_op_init(void)
Initialise subrequest ops.
Definition subrequest.c:295
size_t frame_state_size
size of instance data in the stack frame
char const * thread_inst_type
fr_dict_attr_t const * root
the root of our dictionary
rlm_rcode_t result
The current stack rcode.
int(* unlang_thread_instantiate_t)(unlang_t const *instruction, void *thread_inst)
void unlang_timeout_init(void)
Definition timeout.c:140
static void frame_state_init(unlang_stack_t *stack, unlang_stack_frame_t *frame)
void unlang_frame_signal(request_t *request, fr_signal_t action, int limit)
Send a signal (usually stop) to a request.
Definition interpret.c:1142
#define unlang_frame_perf_init(_x)
bool rcode_set
Set request->rcode to the result of this operation.
void unlang_edit_init(void)
Definition edit.c:1731
void unlang_tmpl_init(void)
Definition tmpl.c:330
void unlang_call_init(void)
Definition call.c:249
int priority
Result priority.
void unlang_map_init(void)
Definition map.c:381
#define UNWIND_FLAG_YIELDED
frame has yielded
bool closed
whether or not this section is closed to new statements
unlang_dump_t dump
Dump additional information about the frame state.
static unlang_t * unlang_group_to_generic(unlang_group_t const *p)
static unlang_action_t unwind_all(unlang_stack_t *stack)
void unlang_condition_init(void)
Definition condition.c:103
#define UNWIND_FLAG_NO_CLEAR
Keep unwinding, don't clear the unwind flag.
uint8_t unwind
Unwind to this frame if it exists.
#define UNWIND_FLAG_BREAK_POINT
'break' stops here.
unlang_t ** tail
pointer to the tail which gets updated
static void top_frame_clear(unlang_stack_frame_t *frame)
unlang_process_t interpret
Function to interpret the keyword.
uint8_t uflags
Unwind markers.
int unlang_interpret_push(request_t *request, unlang_t const *instruction, rlm_rcode_t default_rcode, bool do_next_sibling, bool top_frame)
Push a new frame onto the stack.
Definition interpret.c:161
unlang_t self
int depth
of this retry structure
static void frame_cleanup(unlang_stack_frame_t *frame)
Cleanup any lingering frame state.
static unlang_t * unlang_tmpl_to_generic(unlang_tmpl_t const *p)
void unlang_op_free(void)
request_t * request
void unlang_load_balance_init(void)
static void break_point_clear(unlang_stack_frame_t *frame)
CONF_ITEM * ci
used to generate this item
static bool is_top_frame(unlang_stack_frame_t const *frame)
static unlang_group_t * unlang_generic_to_group(unlang_t const *p)
void(* unlang_dump_t)(request_t *request, unlang_stack_frame_t *frame)
Custom callback for dumping information about frame state.
unsigned int number
unique node number
#define UNWIND_FLAG_REPEAT
Repeat the frame on the way up the stack.
void unlang_group_init(void)
Definition group.c:46
size_t mod_rcode_table_len
Definition compile.c:94
void unlang_parallel_init(void)
Definition parallel.c:493
static unlang_stack_frame_t * frame_current(request_t *request)
fr_event_timer_t const * ev
void unlang_transaction_init(void)
static void stack_unwind_break_clear(unlang_stack_t *stack)
static void return_point_set(unlang_stack_frame_t *frame)
int depth
Current depth we're executing at.
char const * name
Unknown...
request_t * unlang_io_subrequest_alloc(request_t *parent, fr_dict_t const *namespace, bool detachable)
Allocate a child request based on the parent.
Definition io.c:39
static int stack_depth_current(request_t *request)
static bool is_break_point(unlang_stack_frame_t const *frame)
void unlang_return_init(void)
Definition return.c:43
void unlang_detach_init(void)
Initialise subrequest ops.
Definition detach.c:54
unlang_type_t
Types of unlang_t nodes.
Definition unlang_priv.h:44
@ UNLANG_TYPE_SWITCH
Switch section.
Definition unlang_priv.h:57
@ UNLANG_TYPE_TRANSACTION
transactions for editing lists
Definition unlang_priv.h:70
@ UNLANG_TYPE_SUBREQUEST
create a child subrequest
Definition unlang_priv.h:64
@ UNLANG_TYPE_UPDATE
Update block.
Definition unlang_priv.h:56
@ UNLANG_TYPE_ELSIF
!Condition && Condition.
Definition unlang_priv.h:55
@ UNLANG_TYPE_ELSE
!Condition.
Definition unlang_priv.h:54
@ UNLANG_TYPE_LOAD_BALANCE
Load balance section.
Definition unlang_priv.h:50
@ UNLANG_TYPE_DETACH
detach a child
Definition unlang_priv.h:65
@ UNLANG_TYPE_GROUP
Grouping section.
Definition unlang_priv.h:48
@ UNLANG_TYPE_POLICY
Policy section.
Definition unlang_priv.h:73
@ UNLANG_TYPE_TMPL
asynchronously expand a tmpl_t
Definition unlang_priv.h:75
@ UNLANG_TYPE_CASE
Case section (within a UNLANG_TYPE_SWITCH).
Definition unlang_priv.h:58
@ UNLANG_TYPE_LIMIT
limit number of requests in a section
Definition unlang_priv.h:69
@ UNLANG_TYPE_BREAK
Break statement (within a UNLANG_TYPE_FOREACH).
Definition unlang_priv.h:60
@ UNLANG_TYPE_TRY
try / catch blocks
Definition unlang_priv.h:71
@ UNLANG_TYPE_CALL
call another virtual server
Definition unlang_priv.h:66
@ UNLANG_TYPE_RETURN
Return statement.
Definition unlang_priv.h:61
@ UNLANG_TYPE_REDUNDANT
exactly like group, but with different default return codes
Definition unlang_priv.h:49
@ UNLANG_TYPE_MAX
Definition unlang_priv.h:77
@ UNLANG_TYPE_IF
Condition.
Definition unlang_priv.h:53
@ UNLANG_TYPE_XLAT
Represents one level of an xlat expansion.
Definition unlang_priv.h:74
@ UNLANG_TYPE_NULL
unlang type not set.
Definition unlang_priv.h:45
@ UNLANG_TYPE_MAP
Mapping section (like UNLANG_TYPE_UPDATE, but uses values from a map_proc_t call).
Definition unlang_priv.h:62
@ UNLANG_TYPE_CALLER
conditionally check parent dictionary type
Definition unlang_priv.h:67
@ UNLANG_TYPE_TIMEOUT
time-based timeouts.
Definition unlang_priv.h:68
@ UNLANG_TYPE_MODULE
Module method.
Definition unlang_priv.h:46
@ UNLANG_TYPE_REDUNDANT_LOAD_BALANCE
Redundant load balance section.
Definition unlang_priv.h:51
@ UNLANG_TYPE_CATCH
catch a previous try
Definition unlang_priv.h:72
@ UNLANG_TYPE_FUNCTION
Internal call to a function or submodule.
Definition unlang_priv.h:47
@ UNLANG_TYPE_EDIT
edit VPs in place. After 20 years!
Definition unlang_priv.h:76
@ UNLANG_TYPE_FOREACH
Foreach section.
Definition unlang_priv.h:59
@ UNLANG_TYPE_PARALLEL
execute statements in parallel
Definition unlang_priv.h:52
static void frame_repeat(unlang_stack_frame_t *frame, unlang_process_t process)
Mark the current stack frame up for repeat, and set a new process function.
unlang_t const * instruction
The unlang node we're evaluating.
bool debug_braces
Whether the operation needs to print braces in debug mode.
size_t len
Total length of the unlang_group_t + specialisation struct.
void unlang_try_init(void)
Definition try.c:42
static void break_point_set(unlang_stack_frame_t *frame)
static bool is_yielded(unlang_stack_frame_t const *frame)
void unlang_catch_init(void)
Definition catch.c:114
size_t frame_state_pool_size
The total size of the pool to alloc.
unlang_type_t type
Keyword.
static void top_frame_set(unlang_stack_frame_t *frame)
unlang_variable_t * variables
rarely used, so we don't usually need it
static unlang_tmpl_t * unlang_generic_to_tmpl(unlang_t const *p)
void unlang_module_init(void)
Definition module.c:931
unlang_t const * instruction
instruction which we're executing
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.
Definition interpret.c:243
rlm_rcode_t result
The result from executing the instruction.
char const * name
Name of the operation.
unlang_frame_action_t
Allows the frame evaluator to signal the interpreter.
Definition unlang_priv.h:83
@ UNLANG_FRAME_ACTION_POP
Pop the current frame, and check the next one further up in the stack for what to do next.
Definition unlang_priv.h:84
@ UNLANG_FRAME_ACTION_YIELD
Temporarily return control back to the caller on the C stack.
Definition unlang_priv.h:88
@ UNLANG_FRAME_ACTION_NEXT
Process the next instruction at this level.
Definition unlang_priv.h:87
@ UNLANG_FRAME_ACTION_RETRY
retry the current frame
Definition unlang_priv.h:86
static void yielded_set(unlang_stack_frame_t *frame)
void unlang_function_init(void)
Definition function.c:337
static void yielded_clear(unlang_stack_frame_t *frame)
#define unlang_frame_perf_yield(_x)
int priority
Current priority.
static bool is_stack_unwinding_to_return(unlang_stack_t *stack)
static bool is_stack_unwinding_to_top_frame(unlang_stack_t *stack)
size_t pool_len
How much additional space to allocate for extensions.
unsigned pool_headers
How much additional space to allocate for chunk headers.
fr_time_t timeout
#define unlang_frame_perf_cleanup(_x)
unlang_t const * next
The next unlang node we will evaluate.
unlang_op_t unlang_ops[]
Different operations the interpreter can execute.
Definition base.c:31
fr_table_num_sorted_t const mod_rcode_table[]
Definition compile.c:82
static void stack_unwind_return_clear(unlang_stack_t *stack)
static bool is_stack_unwinding_to_break(unlang_stack_t *stack)
int max_attr
1..N local attributes have been defined
unlang_thread_instantiate_t thread_instantiate
per-thread instantiation function
fr_dict_t * dict
our dictionary
void * unlang_thread_instance(unlang_t const *instruction)
Get the thread-instance data for an instruction.
Definition compile.c:5168
static bool is_return_point(unlang_stack_frame_t const *frame)
static void return_point_clear(unlang_stack_frame_t *frame)
tmpl_t const * tmpl
static void repeatable_set(unlang_stack_frame_t *frame)
void unlang_subrequest_op_free(void)
Definition subrequest.c:313
void unlang_caller_init(void)
Definition caller.c:55
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.
unlang_t * children
Children beneath this group.
size_t thread_inst_size
int unlang_op_init(void)
static void stack_unwind_top_frame_clear(unlang_stack_t *stack)
void * thread_inst
thread-specific instance data
Describes how to allocate an unlang_group_t with additional memory keyword specific data.
Generic representation of a grouping.
An unlang operation.
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.
A naked xlat.
static fr_slen_t parent
Definition pair.h:851
fr_retry_state_t
Definition retry.h:45