25RCSID(
"$Id: e9a2e4b743028943788bd11d0faf893917e87b81 $")
27#include <freeradius-devel/unlang/action.h>
28#include <freeradius-devel/unlang/interpret.h>
29#include <freeradius-devel/util/timer.h>
30#include <freeradius-devel/server/base.h>
31#include <freeradius-devel/server/modpriv.h>
32#include <freeradius-devel/unlang/xlat_func.h>
126 if (!instruction->
number)
return NULL;
205 t->tracking.running_total =
fr_time_delta_add(t->tracking.running_total, frame->tracking.running_total);
206 t->tracking.waiting_total =
fr_time_delta_add(t->tracking.waiting_total, frame->tracking.waiting_total);
217 if (!instruction || !instruction->
number)
return;
246 fr_log(log,
L_DBG,
file,
line,
"count=%" PRIu64
" cpu_time=%" PRId64
" yielded_time=%" PRId64 ,
249 if (!unlang_list_empty(&g->
children)) {
251 unlang_perf_dump(log, child,
depth + 1);
264void unlang_perf_virtual_server(
fr_log_t *log,
char const *
name)
288 char const *name1, *name2;
295 if (!instruction)
continue;
309 unlang_perf_dump(log, instruction, 2);
350 if (!thread_data)
return -1;
398#include <freeradius-devel/unlang/module_priv.h>
419 for (i = 0; i <= (
unsigned int)
stack->depth; i++) {
420 frame = &
stack->frame[i];
421 if (frame->
state && (ptr >= (
void *)frame->
state) &&
424 *chunk = frame->
state;
447 if (!mod_state->
rctx)
continue;
449 if ((ptr >= (
void *)mod_state->
rctx) &&
450 (ptr < ((
void *)((
uint8_t *)mod_state->
rctx + talloc_get_size(mod_state->
rctx))))) {
452 *chunk = mod_state->
rctx;
540 location, frame->
p_result, chunk ? talloc_get_name(chunk) :
"<none>"
565 if (op && op->
dump) op->
dump(request, frame);
574 RDEBUG2(
"----- Begin stack debug [depth %i] -----",
576 for (i =
stack->depth; i >= 0; i--) {
578 RDEBUG2(
"[%d] Frame contents", i);
581 RDEBUG2(
"----- End stack debug [depth %i] -------",
stack->depth);
593#define DUMP_STACK if (DEBUG_ENABLED5) stack_dump(request)
629 if (!instruction)
return -1;
632 if (
DEBUG_ENABLED5)
RDEBUG3(
"unlang_interpret_push called with instruction type \"%s\" - args %s %s",
634 do_next_sibling ?
"UNLANG_NEXT_SIBLING" :
"UNLANG_NEXT_STOP",
635 conf->top_frame ?
"UNLANG_TOP_FRAME" :
"UNLANG_SUB_FRAME");
644 RERROR(
"Call stack is too deep");
654 memset(frame, 0,
sizeof(*frame));
658 if (do_next_sibling && instruction->
list) {
659 frame->
next = unlang_list_next(instruction->
list, instruction);
669 frame->
indent = request->log.indent;
736 if (unlang_list_empty(&g->
children)) {
737 RDEBUG2(
"... ignoring empty subsection ...");
764 ref->
old_dict = request->local_dict;
784static inline CC_HINT(always_inline)
787 unlang_t const *instruction = frame->instruction;
792 RDEBUG4(
"** [%i] %s - unwinding frame",
stack->depth, __FUNCTION__);
801 RDEBUG4(
"** [%i] %s - skipping frame, no result set",
802 stack->depth, __FUNCTION__);
809 RDEBUG4(
"** [%i] %s - have (%s %s) frame or module returned (%s %s)",
810 stack->depth, __FUNCTION__,
823 if (
is_rcode_set(frame) && (request->rcode != result->rcode)) {
824 RDEBUG3(
"Setting request->rcode to '%s'",
826 request->rcode = result->rcode;
838 RDEBUG4(
"** [%i] %s - using default instruction priority for %s, %s",
839 stack->depth, __FUNCTION__,
849 switch (result->priority) {
855 RDEBUG4(
"** [%i] %s - action says to return with (%s %s)",
856 stack->depth, __FUNCTION__,
873 RDEBUG4(
"** [%i] %s - action says to return with (%s %s)",
874 stack->depth, __FUNCTION__,
885 RDEBUG4(
"** [%i] %s - action says to retry with",
886 stack->depth, __FUNCTION__);
910 RPEDEBUG(
"Failed inserting retry event");
949 TALLOC_FREE(frame->state);
964 if (result->priority >= frame_result->
priority) {
968 RDEBUG4(
"** [%i] %s - overwriting existing result (%s %s) with higher priority (%s %s)",
969 stack->depth, __FUNCTION__,
974 *frame->p_result = *result;
994static inline CC_HINT(always_inline)
1014 our_result.
priority = frame->instruction->actions.actions[result->rcode];
1017 RDEBUG4(
"** [%i] %s - using instruction priority for higher frame (%s, %s)",
1018 stack->depth, __FUNCTION__,
1068static inline CC_HINT(always_inline)
1077 while (frame->instruction) {
1078 unlang_t const *instruction = frame->instruction;
1103 if (request->ins_max) {
1104 request->ins_count++;
1106 if (request->ins_count >= request->ins_max) {
1107 RERROR(
"Failing request due to maximum instruction count %" PRIu64, request->ins_max);
1140 RDEBUG4(
"** [%i] %s >> %s",
stack->depth, __FUNCTION__,
1161 ua = frame->process(&frame->scratch_result, request, frame);
1166 RDEBUG4(
"** [%i] %s << %s (%s %s)",
stack->depth, __FUNCTION__,
1188 "Instruction %s returned UNLANG_ACTION_PUSHED_CHILD, "
1189 "but stack depth was not increased",
1200 "Instruction %s returned UNLANG_ACTION_YIELD, but pushed additional "
1201 "frames for evaluation. Instruction should return UNLANG_ACTION_PUSHED_CHILD "
1202 "instead", instruction->
name);
1205 RDEBUG4(
"** [%i] %s - yielding with current (%s %s)",
stack->depth, __FUNCTION__,
1244 RDEBUG2(
"} # retrying the same section");
1270 RDEBUG4(
"** [%i] %s - done current subsection with (%s %s), %s",
1271 stack->depth, __FUNCTION__,
1274 frame->p_result == &(frame->section_result) ?
"will set higher frame rcode" :
"will NOT set higher frame rcode (p_result)");
1309 fr_assert_msg(intp,
"request has no interpreter associated");
1311 RDEBUG4(
"** [%i] %s - interpret entered",
stack->depth, __FUNCTION__);
1318 RDEBUG4(
"** [%i] %s - frame action %s",
stack->depth, __FUNCTION__,
1322 RDEBUG4(
"** [%i] %s - frame action next",
stack->depth, __FUNCTION__);
1330 RDEBUG4(
"** [%i] %s - frame action %s",
stack->depth, __FUNCTION__,
1354 RDEBUG4(
"** [%i] %s - frame popped",
stack->depth + 1, __FUNCTION__);
1377 if (private_result) {
1388 fa =
result_pop(request, frame, §ion_result);
1417 DEBUG4(
"** [%i] %s - continuing after subsection with (%s %s)",
1418 stack->depth, __FUNCTION__,
1429 RDEBUG4(
"** [%i] %s - done current subsection with (%s %s)",
1430 stack->depth, __FUNCTION__,
1442 RDEBUG4(
"** [%i] %s - interpret yielding",
stack->depth, __FUNCTION__);
1458 RDEBUG4(
"** [%i] %s - interpret exiting, returning (%s)",
stack->depth, __FUNCTION__,
1490 .name =
"empty-group",
1491 .debug_name =
"empty-group",
1533 REDEBUG(
"Failed to find pre-compiled unlang for section %s ... { ... }",
1561 RDEBUG4(
"** [%i] %s - substack begins",
stack->depth, __FUNCTION__);
1579 static unlang_t unlang_instruction = {
1599 stack->frame[0].p_result = &
stack->frame[0].section_result;
1602 stack->frame[0].instruction = &unlang_instruction;
1620 switch (request->type) {
1640static inline CC_HINT(always_inline)
1664 request->priority = priority;
1678 TALLOC_FREE(frame->
retry);
1710 (void)talloc_get_type_abort(request,
request_t);
1735 for (i =
depth; i >= limit; i--) {
1736 frame = &
stack->frame[i];
1738 frame->
signal(request, frame, action);
1750 TALLOC_FREE(frame->
retry);
1847 RDEBUG(
"retry timeout reached, signalling interpreter to cancel.");
1862 RDEBUG(
"Maximum timeout reached, signalling interpreter to stop the request.");
1886 if (!frame->
retry)
return -1;
1905 return stack->depth;
2015 RDEBUG3(
"Not marking request %s as runnable due to%s%s",
2018 " it not being yielded " :
"", scheduled ?
" it already being scheduled" :
"");
2022 RDEBUG3(
"Interpreter - Request marked as runnable");
2038 if (frame->
state)
return (TALLOC_CTX *)frame->
state;
2045 return (TALLOC_CTX *)(frame->
state = talloc_new(
stack));
2067 RDEBUG2(
"Request canceled by dynamic timeout");
2130 RPERROR(
"Failed inserting cancellation event");
2136 RPERROR(
"Failed associating cancellation event with request");
2179 char const *
fmt = arg->vb_strvalue;
2187 while (*
fmt ==
'.') {
2210 if (!instruction)
goto clear;
2215 if (strcmp(
fmt,
"depth") == 0) {
2216 fr_value_box_int32(vb, NULL,
depth,
false);
2223 if (strcmp(
fmt,
"module") == 0) {
2224 if (!request->module)
goto clear;
2234 if (strcmp(
fmt,
"name") == 0) {
2235 if (!instruction->
name)
goto clear;
2238 strlen(instruction->
name),
false) < 0)
goto error;
2245 if (strcmp(
fmt,
"processing_stage") == 0) {
2246 if (!request->component)
goto clear;
2256 if (strcmp(
fmt,
"rcode") == 0) {
2265 if (strcmp(
fmt,
"server") == 0) {
2279 for (our_request = request; our_request && server == NULL; our_request = our_request->parent) {
2282 if (server == NULL)
goto finish;
2292 if (strcmp(
fmt,
"type") == 0) {
2302 if (!instruction->
ci) {
2311 if (strcmp(
fmt,
"line") == 0) {
2312 fr_value_box_int32(vb, NULL,
cf_lineno(instruction->
ci),
false);
2320 if (strcmp(
fmt,
"filename") == 0) {
2413 if (!
stack->intp)
return NULL;
2415 return stack->intp->el;
#define RETURN_UNLANG_ACTION_FATAL
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_EXECUTE_NEXT
Execute the next unlang_t.
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
@ UNLANG_ACTION_YIELD
Temporarily pause execution until an event occurs.
static int const char * fmt
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define L(_str)
Helper for initialising arrays of string literals.
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
CONF_SECTION * unlang_call_current(request_t *request)
Return the last virtual server that was called.
Common header for all CONF_* types.
A section grouping multiple CONF_PAIR.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
char const * cf_section_name1(CONF_SECTION const *cs)
Return the first identifier of a CONF_SECTION.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
#define cf_data_find(_cf, _type, _name)
#define cf_item_next(_parent, _curr)
fr_table_num_sorted_t const mod_rcode_table[]
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_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
static xlat_action_t unlang_interpret_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Get information about the interpreter state.
void unlang_interpret_request_prioritise(request_t *request, uint32_t priority)
static size_t unlang_action_table_len
void stack_dump_with_actions(request_t *request)
static fr_table_num_ordered_t const unlang_frame_action_table[]
static void unlang_interpret_request_detach(request_t *request)
Tell the interpreter to detach the request.
rlm_rcode_t unlang_interpret(request_t *request, bool running)
Run the interpreter for a current request.
bool unlang_request_is_done(request_t const *request)
Return whether a request has been marked done.
static void stack_dump_body(request_t *request, bool with_actions)
static unlang_group_t empty_group
unlang_result_t * unlang_interpret_result(request_t *request)
Get the last instruction result OR the last frame that was popped.
static int find_p_result_location(p_result_location_t *location, void **chunk, request_t *request, void *ptr)
Try and figure out where p_result points to.
void unlang_interpet_frame_discard(request_t *request)
Discard the bottom most frame on the request's stack.
int unlang_interpret_set_timeout(request_t *request, fr_time_delta_t timeout)
Set a timeout for a request.
void unlang_interpret_request_done(request_t *request)
Indicate to the caller of the interpreter that this request is complete.
static unlang_frame_action_t frame_eval(request_t *request, unlang_stack_frame_t *frame)
Evaluates all the unlang nodes in a section.
void unlang_interpret_set(request_t *request, unlang_interpret_t *intp)
Set a specific interpreter for a request.
unlang_interpret_t * unlang_interpret_get(request_t *request)
Get the interpreter set for a request.
int unlang_interpret_stack_depth(request_t *request)
Return the depth of the request's stack.
int unlang_thread_instantiate(TALLOC_CTX *ctx)
Create thread-specific data structures for unlang.
void unlang_interpret_mark_runnable(request_t *request)
Mark a request as resumable.
static xlat_arg_parser_t const unlang_interpret_xlat_args[]
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
bool unlang_request_is_scheduled(request_t const *request)
Return whether a request is currently scheduled.
static char const unlang_spaces[]
int unlang_interpret_init_global(TALLOC_CTX *ctx)
void stack_dump(request_t *request)
@ P_RESULT_LOCATION_FRAME
@ P_RESULT_LOCATION_FUNCTION_RCTX
@ P_RESULT_LOCATION_UNKNOWN
@ P_RESULT_LOCATION_SCRATCH
@ P_RESULT_LOCATION_MODULE_RCTX
@ P_RESULT_LOCATION_STATE
unlang_interpret_t * unlang_interpret_get_thread_default(void)
Get the default interpreter for this thread.
fr_dict_t const * old_dict
the previous dictionary for the request
void * unlang_interpret_stack_alloc(TALLOC_CTX *ctx)
Allocate a new unlang stack.
unlang_t const * unlang_interpret_instruction(request_t *request)
Get the current instruction.
void unlang_interpret_set_thread_default(unlang_interpret_t *intp)
Set the default interpreter for this thread.
static fr_table_num_ordered_t const p_result_location_table[]
unlang_mod_action_t unlang_interpret_priority(request_t *request)
Get the last instruction priority OR the last frame that was popped.
static void instruction_retry_handler(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now, void *ctx)
unlang_interpret_t * unlang_interpret_init(TALLOC_CTX *ctx, fr_event_list_t *el, unlang_request_func_t *funcs, void *uctx)
Initialize a unlang compiler / interpret.
static void instruction_timeout_handler(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now, void *ctx)
bool unlang_request_is_cancelled(request_t const *request)
Return whether a request has been cancelled.
int unlang_interpret_push_instruction(unlang_result_t *p_result, request_t *request, void *instruction, unlang_frame_conf_t const *conf)
Push an instruction onto the request stack for later interpretation.
static void unlang_cancel_event(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now, void *uctx)
Signal the request to stop executing.
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
static xlat_arg_parser_t const unlang_cancel_xlat_args[]
int unlang_interpret_push_section(unlang_result_t *p_result, request_t *request, CONF_SECTION *cs, unlang_frame_conf_t const *conf)
Push a configuration section onto the request stack for later interpretation.
static unlang_frame_action_t result_calculate(request_t *request, unlang_stack_frame_t *frame, unlang_result_t *result)
Update the current result after each instruction, and after popping each stack frame.
static fr_table_num_ordered_t const unlang_action_table[]
static int _local_variables_free(unlang_variable_ref_t *ref)
static size_t p_result_location_table_len
static void instruction_dump(request_t *request, unlang_t const *instruction)
bool unlang_interpret_is_resumable(request_t *request)
Check if a request as resumable.
int unlang_interpret_push(unlang_result_t *p_result, request_t *request, unlang_t const *instruction, unlang_frame_conf_t const *conf, bool do_next_sibling)
Push a new frame onto the stack.
int unlang_interpret_force_result(unlang_t const *instruction, unlang_result_t *p_result, fr_timer_list_t *tl, fr_time_delta_t expire)
Set (or clear) a forced result.
static void instruction_done_debug(request_t *request, unlang_stack_frame_t *frame, unlang_t const *instruction)
fr_rb_tree_t * unlang_instruction_tree
request_t * request
the request
static void forced_result_expiry_handler(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now, void *ctx)
void unlang_interpret_request_cancel_retry(request_t *request)
Cancel any pending retry.
static unlang_thread_t * unlang_thread_data(unlang_t const *instruction)
Get the thread-instance data for an instruction.
static unlang_frame_action_t result_pop(request_t *request, unlang_stack_frame_t *frame, unlang_result_t *result)
Function called to merge inter-stack-frame results.
void unlang_stack_signal(request_t *request, fr_signal_t action, int limit)
Delivers a frame to one or more frames in the stack.
void * unlang_thread_instance(unlang_t const *instruction)
Get the thread-instance data for an instruction.
static _Thread_local unlang_thread_t * unlang_thread_array
static xlat_action_t unlang_cancel_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Allows a request to dynamically alter its own lifetime.
static size_t unlang_frame_action_table_len
rlm_rcode_t unlang_interpret_rcode(request_t *request)
Get the last instruction result OR the last frame that was popped.
static void frame_dump(request_t *request, unlang_stack_frame_t *frame, bool with_actions)
unlang_action_t unlang_interpret_push_children(unlang_result_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.
static void actions_dump(request_t *request, unlang_t const *instruction)
static _Thread_local unlang_interpret_t * intp_thread_default
The default interpreter instance for this thread.
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
unlang_result_t default_result
The default result for the frame.
#define UNLANG_STACK_MAX
The maximum depth of the stack.
unlang_request_prioritise_t prioritise
Function to re-prioritise a request in the runnable queue.
unlang_mod_action_t priority
The priority or action for that rcode.
#define UNLANG_RESULT_NOT_SET
#define FRAME_CONF(_default_rcode, _top_frame)
unlang_request_done_t done_internal
Function called when an internal request completes.
#define UNLANG_FRAME_POOL_SIZE
total size of all frame states
unlang_request_resume_t resume
Function called when a request is resumed.
unlang_request_done_t done_external
Function called when a external request completes.
unlang_request_init_t detach
Function called when a request is detached.
unlang_request_runnable_t mark_runnable
Function called when a request needs to be added back to the runnable queue.
rlm_rcode_t rcode
The current rcode, from executing the instruction or merging the result from a frame.
unlang_request_yield_t yield
Function called when a request yields.
unlang_request_done_t done_detached
Function called when a detached request completes.
unlang_request_scheduled_t scheduled
Function to check if a request is already scheduled.
#define UNLANG_RESULT_RCODE(_x)
unlang_request_init_t init_internal
Function called to initialise an internal request.
struct unlang_interpret_s unlang_interpret_t
Interpreter handle.
Configuration structure to make it easier to pass configuration options to initialise the frame with.
External functions provided by the owner of the interpret.
Private declarations for the unlang interpreter.
unlang_request_func_t funcs
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define DEBUG_ENABLED5
True if global debug level 1-5 messages are enabled.
#define RPEDEBUG(fmt,...)
#define RINDENT()
Indent R* messages by one level.
unlang_op_t unlang_ops[UNLANG_TYPE_MAX]
Different operations the interpreter can execute.
Stores all information relating to an event list.
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
@ L_DBG
Only displayed when debugging is enabled.
static char * stack[MAX_STACK]
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
static uint8_t depth(fr_minmax_heap_index_t i)
const char * mod_action_name[MOD_PRIORITY_MAX+1]
#define DEFAULT_MOD_ACTIONS
@ MOD_ACTION_NOT_SET
default "not set by anything"
@ MOD_ACTION_RETURN
stop processing the section, and return the rcode with unset priority
@ MOD_ACTION_REJECT
change the rcode to REJECT, with unset priority
@ MOD_ACTION_RETRY
retry the instruction, MUST also set a retry config
#define MOD_ACTION_VALID(_x)
unlang_mod_action_t actions[RLM_MODULE_NUMCODES]
Declarations for the unlang module interface.
void * rctx
for resume / signal
int fr_pair_delete(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list and free.
#define RDEBUG_ENABLED2()
void * fr_rb_iter_init_inorder(fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Initialise an in-order iterator.
void * fr_rb_iter_next_inorder(UNUSED fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Return the next node.
Iterator structure for in-order traversal of an rbtree.
The main red black tree structure.
fr_table_num_sorted_t const rcode_table[]
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_TIMEOUT
Module (or section) timed out.
@ RLM_MODULE_NOT_SET
Error resolving rcode (should not be returned by modules).
@ RLM_MODULE_NUMCODES
How many valid return codes there are.
#define REQUEST_VERIFY(_x)
@ REQUEST_TYPE_EXTERNAL
A request received on the wire.
@ REQUEST_TYPE_INTERNAL
A request generated internally.
@ REQUEST_TYPE_DETACHED
A request that was generated internally, but is now detached (not associated with a parent request....
#define request_is_detachable(_x)
@ REQUEST_DONE
Request has completed.
@ REQUEST_STOP_PROCESSING
Request has been signalled to stop.
void * request_data_get(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request.
#define request_data_add(_request, _unique_ptr, _unique_int, _opaque, _free_on_replace, _free_on_parent, _persist)
Add opaque data to a request_t.
fr_signal_t
Signals that can be generated/processed by request signal handlers.
@ FR_SIGNAL_CANCEL
Request has been cancelled.
@ FR_SIGNAL_DETACH
Request is being detached from its parent.
fr_aka_sim_id_type_t type
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.
An element in an arbitrarily ordered array of name to num mappings.
#define talloc_zero_pooled_object(_ctx, _type, _num_subobjects, _total_subobjects_size)
static fr_time_delta_t fr_time_delta_add(fr_time_delta_t a, fr_time_delta_t b)
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_delta_ispos(_a)
#define fr_time_delta_eq(_a, _b)
static fr_time_t fr_time_from_sec(time_t when)
Convert a time_t (wallclock time) to a fr_time_t (internal time)
#define fr_time_sub(_a, _b)
Subtract one time from another.
A time delta, a difference in time measured in nanoseconds.
@ FR_TIME_TRACKING_YIELDED
We're currently tracking time in the yielded state.
static void fr_time_tracking_yield(fr_time_tracking_t *tt, fr_time_t now)
Transition to the yielded state, recording the time we just spent running.
static void fr_time_tracking_end(fr_time_delta_t *predicted, fr_time_tracking_t *tt, fr_time_t now)
End time tracking for this entity.
static void fr_time_tracking_start(fr_time_tracking_t *parent, fr_time_tracking_t *tt, fr_time_t now)
Start time tracking for a tracked entity.
static void fr_time_tracking_resume(fr_time_tracking_t *tt, fr_time_t now)
Track that a request resumed.
fr_time_t fr_timer_when(fr_timer_t *ev)
Internal timestamp representing when the timer should fire.
int fr_timer_delete(fr_timer_t **ev_p)
Delete a timer event and free its memory.
static fr_event_list_t * el
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
unsigned int required
Argument must be present, and non-empty.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumed by an xlat function.
Private interpreter structures and functions.
#define unlang_frame_perf_resume(_x)
unlang_result_t section_result
The aggregate result of executing all siblings in this section.
static void frame_pop(request_t *request, unlang_stack_t *stack)
Pop a stack frame, removing any associated dynamically allocated state.
static void frame_next(unlang_stack_t *stack, unlang_stack_frame_t *frame)
Advance to the next sibling instruction.
@ UNLANG_FRAME_FLAG_NONE
No flags.
static bool is_repeatable(unlang_stack_frame_t const *frame)
#define UNLANG_NEXT_SIBLING
unlang_result_t * p_result
Where to write the result of executing the current instruction.
static void repeatable_clear(unlang_stack_frame_t *frame)
static unlang_action_t unwind_to_depth(unlang_stack_t *stack, unsigned int to_depth)
Mark up frames as cancelled so they're immediately popped by the interpreter.
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.
void * state
Stack frame specialisations.
unlang_mod_actions_t actions
Priorities, etc. for the various return codes.
char const * thread_inst_type
static void frame_state_init(unlang_stack_t *stack, unlang_stack_frame_t *frame)
Initialise memory and instruction for a frame when a new instruction is to be evaluated.
#define unlang_frame_perf_init(_x)
unlang_dump_t dump
Dump additional information about the frame state.
static unlang_t * unlang_group_to_generic(unlang_group_t const *p)
rindent_t indent
Indent level of the request when the frame was created.
#define unlang_list_foreach(_list_head, _iter)
unlang_process_t interpret
Function to interpret the keyword.
unlang_result_t scratch_result
The result of executing the current instruction.
int depth
of this retry structure
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)
unsigned int number
unique node number
static unlang_stack_frame_t * frame_current(request_t *request)
fr_timer_t * ev
run on expiry
static bool is_private_result(unlang_stack_frame_t const *frame)
char const * name
Unknown...
bool use_forced_result
Do we force a result for this module?
static bool is_break_point(unlang_stack_frame_t const *frame)
#define has_debug_braces(_thing)
@ UNLANG_TYPE_GROUP
Grouping section.
@ UNLANG_TYPE_POLICY
Policy section.
@ UNLANG_TYPE_MODULE
Module method.
unlang_t const * instruction
The unlang node we're evaluating.
static bool is_rcode_set(unlang_stack_frame_t const *frame)
static bool is_yielded(unlang_stack_frame_t const *frame)
static void top_frame_set(unlang_stack_frame_t *frame)
unlang_variable_t * variables
rarely used, so we don't usually need it
#define debug_braces(_type)
unlang_t const * instruction
instruction which we're executing
char const * name
Name of the keyword.
unlang_frame_action_t
Allows the frame evaluator to signal the interpreter.
@ UNLANG_FRAME_ACTION_POP
Pop the current frame, and check the next one further up in the stack for what to do next.
@ UNLANG_FRAME_ACTION_YIELD
Temporarily return control back to the caller on the C stack.
@ UNLANG_FRAME_ACTION_NEXT
Process the next instruction at this level.
@ UNLANG_FRAME_ACTION_RETRY
retry the current frame
static void yielded_set(unlang_stack_frame_t *frame)
static bool is_continue_point(unlang_stack_frame_t const *frame)
static void yielded_clear(unlang_stack_frame_t *frame)
#define unlang_frame_perf_yield(_x)
#define unlang_frame_perf_cleanup(_x)
unlang_t const * next
The next unlang node we will evaluate.
unlang_result_t forced_result
the result to force
unlang_thread_instantiate_t thread_instantiate
per-thread instantiation function
fr_dict_t * dict
our dictionary
static bool is_return_point(unlang_stack_frame_t const *frame)
unlang_process_t process
function to call for interpreting this stack frame
unlang_type_t type
The specialisation of this node.
unlang_frame_flag_t flag
Flags that mark up the frame for various things such as being the point where break,...
unlang_list_t * list
so we have fewer run-time dereferences
static bool is_unwinding(unlang_stack_frame_t const *frame)
void * thread_inst
thread-specific instance data
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.
fr_pair_t * fr_pair_list_tail(fr_pair_list_t const *list)
Get the tail of a valuepair list.
fr_pair_t * fr_pair_list_prev(fr_pair_list_t const *list, fr_pair_t const *item))
Get the previous item in a valuepair list before a specific entry.
uint32_t mrc
Maximum retransmission count.
@ FR_RETRY_MRC
reached maximum retransmission count
@ FR_RETRY_MRD
reached maximum retransmission duration
fr_time_delta_t mrd
Maximum retransmission duration.
#define fr_strerror_const(_msg)
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.
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
static size_t char ** out
virtual_server_t const * virtual_server_find(char const *name)
Return virtual server matching the specified name.
CONF_SECTION * virtual_server_cs(virtual_server_t const *vs)
Return the configuration section for a virtual server.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.