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