26RCSID(
"$Id: 06fb3ba4fa974b3569dfec812b2b9494c65490ef $")
28#include <freeradius-devel/server/state.h>
29#include <freeradius-devel/server/tmpl_dcursor.h>
30#include <freeradius-devel/server/request.h>
31#include <freeradius-devel/unlang/action.h>
47 RDEBUG3(
"subrequest detached during its execution - Not sending signal to child");
51 RDEBUG3(
"subrequest is cancelled - Not sending signal to child");
109 RDEBUG3(
"subrequest detached during its execution - Not updating rcode or reply attributes");
119 RDEBUG3(
"subrequest completeed with rcode %s",
122 *p_result = cr->
result.rcode;
148 RPDEBUG(
"Discarding subrequest attributes - Failed allocating groups");
194 if (cr->
result.p_result) *cr->
result.p_result = *p_result;
208 RDEBUG(
"Failed finding attribute %s", gext->
vpt->name);
215 RDEBUG(
"Unknown Packet-Type %pV", &attr->data);
219 child->packet->code =
vp->vp_uint32 = type_enum->
value->vb_uint32;
225 RDEBUG(
"Failed casting value from %pV to data type uint32", &attr->data);
238 RDEBUG(
"Invalid value %pV for Packet-Type", &box);
242 child->packet->code =
vp->vp_uint32 = box.vb_uint32;
249 RPEDEBUG(
"Failed copying source attributes into subrequest");
328 if (cr->
config.free_child) {
369 cr->
config.session_unique_ptr,
423 rlm_rcode_t *p_result,
void const *unique_session_ptr,
bool free_child,
bool top_frame)
428 static unlang_t subrequest_instruction = {
430 .name =
"subrequest",
431 .debug_name =
"subrequest",
448 fr_assert_msg(free_child || child->parent,
"Child's request pointer must not be NULL when calling subrequest_child_push");
451 "Child stack depth must be 0 (not %d), when calling subrequest_child_push",
506 RPEDEBUG(
"Failed detaching request");
520 .name =
"subrequest",
536 .frame_state_type =
"unlang_child_request_t",
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_EXECUTE_NEXT
Execute the next unlang_t.
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
@ UNLANG_ACTION_YIELD
Temporarily pause execution until an event occurs.
int unlang_child_request_op_init(void)
int unlang_child_request_init(TALLOC_CTX *ctx, unlang_child_request_t *out, request_t *child, rlm_rcode_t *p_result, unsigned int *sibling_count, void const *unique_session_ptr, bool free_child)
Initialize a child request.
struct unlang_child_request_t::@100 config
request_t * request
Child request. The actual request the child will run.
struct unlang_child_request_t::@101 result
unlang_child_request_state_t state
State of the child.
@ CHILD_RUNNABLE
Running/runnable.
@ CHILD_DETACHED
Child has detached, we can't signal it or communicate with it anymore.
@ CHILD_CANCELLED
Child was cancelled.
Each child has a state, a number, a request, and a count of their siblings.
fr_table_num_sorted_t const mod_rcode_table[]
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
fr_value_box_t const * value
Enum value (what name maps to).
fr_dict_enum_value_t const * fr_dict_enum_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value)
Lookup the structure representing an enum value in a fr_dict_attr_t.
fr_dict_enum_value_t const * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Value of an enumerated attribute.
bool unlang_request_is_done(request_t const *request)
Return whether a request has been marked done.
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.
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
Private declarations for the unlang interpreter.
static void interpret_child_init(request_t *request)
#define RPEDEBUG(fmt,...)
void unlang_register(int type, unlang_op_t *op)
Register an operation with the interpreter.
request_t * unlang_io_subrequest_alloc(request_t *parent, fr_dict_t const *namespace, bool detachable)
Allocate a child request based on the parent.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
int fr_pair_list_copy(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from)
Duplicate a list of pairs.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_INVALID
The module considers the request invalid.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_NOTFOUND
User not found.
@ RLM_MODULE_UPDATED
OK (pairs modified).
@ RLM_MODULE_NOT_SET
Error resolving rcode (should not be returned by modules).
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
int request_detach(request_t *child)
Unlink a subrequest from its parent.
#define request_is_detachable(_x)
void fr_state_restore_to_child(request_t *child, void const *unique_ptr, int unique_int)
Restore subrequest data from a parent request.
int tmpl_find_vp(fr_pair_t **out, request_t *request, tmpl_t const *vpt))
Returns the first VP matching a tmpl_t.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
int tmpl_copy_pair_children(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, tmpl_t const *vpt))
Copy children of pairs matching a tmpl_t in the current request_t.
fr_signal_t
Signals that can be generated/processed by request signal handlers.
@ FR_SIGNAL_DETACH
Request is being detached from its parent.
Stores an attribute, a value and various bits of other data.
static unlang_action_t unlang_subrequest_parent_resume(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Parent being resumed after a child completes.
int unlang_subrequest_child_push(request_t *child, rlm_rcode_t *p_result, void const *unique_session_ptr, bool free_child, bool top_frame)
Push a pre-existing child back onto the stack as a subrequest.
static unlang_action_t unlang_subrequest_child_done(rlm_rcode_t *p_result, UNUSED request_t *request, unlang_stack_frame_t *frame)
Function to run in the context of the parent on resumption.
int unlang_subrequest_op_init(void)
Initialise subrequest ops.
static void unlang_subrequest_signal(UNUSED request_t *request, unlang_stack_frame_t *frame, fr_signal_t action)
Send a signal from parent request to subrequest.
int unlang_subrequest_child_push_and_detach(request_t *request)
Add a child request to the runnable queue.
static unlang_action_t unlang_subrequest_init(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Allocates a new subrequest and initialises it.
request_t * unlang_subrequest_alloc(request_t *parent, fr_dict_t const *namespace)
Allocate a subrequest to run through a virtual server at some point in the future.
unlang_action_t unlang_subrequest_child_run(UNUSED rlm_rcode_t *p_result, UNUSED request_t *request, unlang_stack_frame_t *frame)
Function called by the unlang interpreter, or manually to start the child running.
void unlang_subrequest_detach_and_free(request_t **child)
Free a child request, detaching it from its parent and freeing allocated memory.
static unlang_subrequest_t * unlang_group_to_subrequest(unlang_group_t *g)
Cast a group structure to the subrequest keyword extension.
tmpl_t * vpt
Value to expand to find the value to place into the packet-type attribute.
fr_dict_attr_t const * attr_packet_type
Packet-type attribute in the subrequest protocol.
tmpl_t * src
Pairs to copy into the subrequest request list.
fr_dict_t const * dict
Dictionary of the subrequest protocol.
tmpl_t * dst
Where to copy pairs from the reply list in the subrequest to.
fr_dict_enum_value_t const * type_enum
Static enumeration value for attr_packet_type.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
fr_pair_t * tmpl_dcursor_pair_build(fr_pair_t *parent, fr_dcursor_t *cursor, fr_dict_attr_t const *da, UNUSED void *uctx)
Simple pair building callback for use with tmpl_dcursors.
void tmpl_dcursor_clear(tmpl_dcursor_ctx_t *cc)
Clear any temporary state allocations.
#define tmpl_dcursor_build_init(_err, _ctx, _cc, _cursor, _request, _vpt, _build, _uctx)
Maintains state between cursor calls.
Private interpreter structures and functions.
#define UNLANG_NORMAL_CHILD
#define UNLANG_DETACHABLE
#define UNLANG_NEXT_SIBLING
void * state
Stack frame specialisations.
int priority
Result priority.
static unlang_group_t * unlang_generic_to_group(unlang_t const *p)
static unlang_stack_frame_t * frame_current(request_t *request)
static int stack_depth_current(request_t *request)
@ UNLANG_TYPE_SUBREQUEST
create a child subrequest
static void frame_repeat(unlang_stack_frame_t *frame, unlang_process_t process)
Mark the current stack frame up for repeat, and set a new process function.
unlang_t const * instruction
The unlang node we're evaluating.
rlm_rcode_t result
The result from executing the instruction.
@ UNLANG_OP_FLAG_DEBUG_BRACES
Print debug braces.
@ UNLANG_OP_FLAG_RCODE_SET
Set request->rcode to the result of this operation.
@ UNLANG_OP_FLAG_NO_CANCEL
Must not be cancelled.
unlang_process_t process
function to call for interpreting this stack frame
unlang_type_t type
The specialisation of this node.
unlang_t * children
Children beneath this group.
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.
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.