25RCSID(
"$Id: b742daa1ef0923cc963081f06a0b5e10016b10b9 $")
 
   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/server/rcode.h> 
   33#include <freeradius-devel/unlang/xlat_func.h> 
   34#include <freeradius-devel/unlang/mod_action.h> 
   62#include <freeradius-devel/unlang/module_priv.h> 
   83        for (i = 0; i <= (
unsigned int)
stack->depth; i++) {
 
   84                frame = &
stack->frame[i];
 
   85                if (frame->
state && (ptr >= (
void *)frame->
state) &&
 
   88                        *chunk = frame->
state;
 
  111                        if (!mod_state->
rctx) 
continue;
 
  113                        if ((ptr >= (
void *)mod_state->
rctx) &&
 
  114                            (ptr < ((
void *)((
uint8_t *)mod_state->
rctx + talloc_get_size(mod_state->
rctx))))) {
 
  116                                *chunk = mod_state->
rctx;
 
 
  204                        location, frame->
p_result, chunk ? talloc_get_name(chunk) : 
"<none>" 
  229        if (op && op->
dump) op->
dump(request, frame);
 
 
  238        RDEBUG2(
"----- Begin stack debug [depth %i] -----",
 
  240        for (i = 
stack->depth; i >= 0; i--) {
 
  242                RDEBUG2(
"[%d] Frame contents", i);
 
  245        RDEBUG2(
"----- End stack debug [depth %i] -------", 
stack->depth);
 
 
  257#define DUMP_STACK if (DEBUG_ENABLED5) stack_dump(request) 
  296        if (
DEBUG_ENABLED5) 
RDEBUG3(
"unlang_interpret_push called with instruction type \"%s\" - args %s %s",
 
  297                                    instruction ? instruction->
debug_name : 
"<none>",
 
  298                                    do_next_sibling ? 
"UNLANG_NEXT_SIBLING" : 
"UNLANG_NEXT_STOP",
 
  299                                    conf->top_frame ? 
"UNLANG_TOP_FRAME" : 
"UNLANG_SUB_FRAME");
 
  308                RERROR(
"Call stack is too deep");
 
  318        memset(frame, 0, 
sizeof(*frame));
 
  322        if (do_next_sibling && instruction->
list) {
 
  324                frame->
next = unlang_list_next(instruction->
list, instruction);
 
  334        frame->
indent = request->log.indent;
 
  336        if (!instruction) 
return 0;
 
 
  401        if (unlang_list_empty(&g->
children)) {
 
  402                RDEBUG2(
"... ignoring empty subsection ...");
 
  429        ref->
old_dict = request->local_dict;
 
 
  449static inline CC_HINT(always_inline)
 
  452        unlang_t const  *instruction = frame->instruction;
 
  457                RDEBUG4(
"** [%i] %s - unwinding frame", 
stack->depth, __FUNCTION__);
 
  466                RDEBUG4(
"** [%i] %s - skipping frame, no result set",
 
  467                        stack->depth, __FUNCTION__);
 
  474        RDEBUG4(
"** [%i] %s - have (%s %s) frame or module returned (%s %s)",
 
  475                stack->depth, __FUNCTION__,
 
  488        if (
is_rcode_set(frame) && (request->rcode != result->rcode)) {
 
  489                RDEBUG3(
"Setting request->rcode to '%s'",
 
  491                request->rcode = result->rcode;
 
  503                RDEBUG4(
"** [%i] %s - using default instruction priority for %s, %s",
 
  504                        stack->depth, __FUNCTION__,
 
  514        switch (result->priority) {
 
  520                RDEBUG4(
"** [%i] %s - action says to return with (%s %s)",
 
  521                        stack->depth, __FUNCTION__,
 
  538                RDEBUG4(
"** [%i] %s - action says to return with (%s %s)",
 
  539                        stack->depth, __FUNCTION__,
 
  550                RDEBUG4(
"** [%i] %s - action says to retry with",
 
  551                        stack->depth, __FUNCTION__);
 
  575                                        RPEDEBUG(
"Failed inserting retry event");
 
  628        if (result->priority >= frame_result->
priority) {
 
  632                RDEBUG4(
"** [%i] %s - overwriting existing result (%s %s) with higher priority (%s %s)",
 
  633                        stack->depth, __FUNCTION__,
 
  638                *frame->p_result = *result;
 
 
  658static inline CC_HINT(always_inline)
 
  678                our_result.
priority = frame->instruction->actions.actions[result->rcode];
 
  681        RDEBUG4(
"** [%i] %s - using instruction priority for higher frame (%s, %s)",
 
  682                stack->depth, __FUNCTION__,
 
 
  732static inline CC_HINT(always_inline)
 
  741        while (frame->instruction) {
 
  742                unlang_t const          *instruction = frame->instruction;
 
  766                if (request->ins_max) {
 
  767                        request->ins_count++;
 
  769                        if (request->ins_count >= request->ins_max) {
 
  770                                RERROR(
"Failing request due to maximum instruction count %" PRIu64, request->ins_max);
 
  815                ua = frame->process(&frame->scratch_result, request, frame);
 
  819                RDEBUG4(
"** [%i] %s << %s (%s %s)", 
stack->depth, __FUNCTION__,
 
  841                                      "Instruction %s returned UNLANG_ACTION_PUSHED_CHILD, " 
  842                                      "but stack depth was not increased",
 
  853                                      "Instruction %s returned UNLANG_ACTION_YIELD, but pushed additional " 
  854                                      "frames for evaluation.  Instruction should return UNLANG_ACTION_PUSHED_CHILD " 
  855                                      "instead", instruction->
name);
 
  858                        RDEBUG4(
"** [%i] %s - yielding with current (%s %s)", 
stack->depth, __FUNCTION__,
 
  897                                        RDEBUG2(
"} # retrying the same section");
 
  923        RDEBUG4(
"** [%i] %s - done current subsection with (%s %s), %s",
 
  924                stack->depth, __FUNCTION__,
 
  927                frame->p_result == &(frame->section_result) ? 
"will set higher frame rcode" : 
"will NOT set higher frame rcode (p_result)");
 
 
  962        fr_assert_msg(intp, 
"request has no interpreter associated");
 
  964        RDEBUG4(
"** [%i] %s - interpret entered", 
stack->depth, __FUNCTION__);
 
  971                RDEBUG4(
"** [%i] %s - frame action %s", 
stack->depth, __FUNCTION__,
 
  975                        RDEBUG4(
"** [%i] %s - frame action next", 
stack->depth, __FUNCTION__);
 
  983                        RDEBUG4(
"** [%i] %s - frame action %s", 
stack->depth, __FUNCTION__,
 
 1007                        RDEBUG4(
"** [%i] %s - frame popped", 
stack->depth + 1, __FUNCTION__);
 
 1030                        if (private_result) {
 
 1041                                fa = 
result_pop(request, frame, §ion_result);
 
 1066                                DEBUG4(
"** [%i] %s - continuing after subsection with (%s %s)",
 
 1067                                        stack->depth, __FUNCTION__,
 
 1078                                RDEBUG4(
"** [%i] %s - done current subsection with (%s %s)",
 
 1079                                        stack->depth, __FUNCTION__,
 
 1091                        RDEBUG4(
"** [%i] %s - interpret yielding", 
stack->depth, __FUNCTION__);
 
 1107        RDEBUG4(
"** [%i] %s - interpret exiting, returning (%s)", 
stack->depth, __FUNCTION__,
 
 
 1139                .debug_name = 
"empty-group",
 
 
 1171                        REDEBUG(
"Failed to find pre-compiled unlang for section %s %s { ... }",
 
 
 1199        RDEBUG4(
"** [%i] %s - substack begins", 
stack->depth, __FUNCTION__);
 
 
 1217        static unlang_t unlang_instruction = {
 
 1238        stack->frame[0].p_result = &
stack->frame[0].section_result;
 
 1241        stack->frame[0].instruction = &unlang_instruction;      
 
 
 1259        switch (request->type) {
 
 
 1279static inline CC_HINT(always_inline)
 
 1303        request->priority = priority;
 
 
 1336        (void)talloc_get_type_abort(request, 
request_t);        
 
 1361        for (i = 
depth; i >= limit; i--) {
 
 1362                frame = &
stack->frame[i];
 
 1364                        frame->
signal(request, frame, action);
 
 
 1468        RDEBUG(
"retry timeout reached, signalling interpreter to cancel.");
 
 
 1483        RDEBUG(
"Maximum timeout reached, signalling interpreter to stop the request.");
 
 
 1502        TALLOC_CTX                      *frame_ctx;
 
 1507        frame_ctx = frame->
state;
 
 1508        if (!frame_ctx) frame_ctx = 
stack;
 
 1511        if (!frame->
retry) 
return -1;
 
 
 1530        return stack->depth;
 
 
 1640                RDEBUG3(
"Not marking request %s as runnable due to%s%s",
 
 1643                        " it not being yielded " : 
"", scheduled ? 
" it already being scheduled" : 
"");
 
 1647        RDEBUG3(
"Interpreter - Request marked as runnable");
 
 
 1663        if (frame->
state) 
return (TALLOC_CTX *)frame->
state;
 
 1670        return (TALLOC_CTX *)(frame->
state = talloc_new(request));
 
 
 1692        RDEBUG2(
"Request canceled by dynamic timeout");
 
 
 1751                RPERROR(
"Failed inserting cancellation event");
 
 1757                RPERROR(
"Failed associating cancellation event with request");
 
 
 1800        char const              *
fmt = arg->vb_strvalue;
 
 1808        while (*
fmt == 
'.') {
 
 1839        if (strcmp(
fmt, 
"depth") == 0) {
 
 1840                fr_value_box_int32(vb, NULL, 
depth, 
false);
 
 1847        if (strcmp(
fmt, 
"module") == 0) {
 
 1856        if (strcmp(
fmt, 
"name") == 0) {
 
 1858                                          strlen(instruction->
name), 
false) < 0) 
goto error;
 
 1865        if (strcmp(
fmt, 
"processing_stage") == 0) {
 
 1874        if (strcmp(
fmt, 
"rcode") == 0) {
 
 1883        if (strcmp(
fmt, 
"server") == 0) {
 
 1894        if (strcmp(
fmt, 
"type") == 0) {
 
 1904        if (!instruction->
ci) {
 
 1913        if (strcmp(
fmt, 
"line") == 0) {
 
 1914                fr_value_box_int32(vb, NULL, 
cf_lineno(instruction->
ci), 
false);
 
 1922        if (strcmp(
fmt, 
"filename") == 0) {
 
 
 2014        if (!
stack->intp) 
return NULL;
 
 2016        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.
 
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 second identifier of a CONF_SECTION.
 
#define cf_data_find(_cf, _type, _name)
 
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.
 
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.
 
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.
 
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.
 
static void instruction_done_debug(request_t *request, unlang_stack_frame_t *frame, unlang_t const *instruction)
 
request_t * request
the request
 
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.
 
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-priotise 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.
 
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.
 
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()
 
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_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_t fr_timer_when(fr_timer_t *ev)
Internal timestamp representing when the timer should fire.
 
static fr_event_list_t * el
 
uint8_t required
Argument must be present, and non-empty.
 
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
 
#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 consumend 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.
 
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.
 
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.
 
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)
 
static unlang_stack_frame_t * frame_current(request_t *request)
 
static bool is_private_result(unlang_stack_frame_t const *frame)
 
char const  * name
Unknown...
 
static bool is_break_point(unlang_stack_frame_t const *frame)
 
#define has_debug_braces(_thing)
 
@ UNLANG_TYPE_GROUP
Grouping 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
 
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.
 
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)
 
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.
 
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
 
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.