26RCSID(
"$Id: 5cfa9ba0b8f13e52287a24e1057817d49bdad142 $")
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/server/rcode.h>
32#include <freeradius-devel/unlang/action.h>
52 RDEBUG3(
"subrequest detached during its execution - Not sending signal to child");
56 RDEBUG3(
"subrequest is cancelled - Not sending signal to child");
118 RDEBUG3(
"subrequest detached during its execution - Not updating rcode or reply attributes");
128 RDEBUG3(
"subrequest completeed with rcode %s",
154 RPDEBUG(
"Discarding subrequest attributes - Failed allocating groups");
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");
334 if (cr->
config.free_child) {
375 cr->
config.session_unique_ptr,
433 static unlang_t subrequest_instruction = {
435 .name =
"subrequest",
436 .debug_name =
"subrequest",
453 fr_assert_msg(free_child || child->parent,
"Child's request pointer must not be NULL when calling subrequest_child_push");
456 "Child stack depth must be 0 (not %d), when calling subrequest_child_push",
511 RPEDEBUG(
"Failed detaching request");
538 char *
namespace = NULL;
541 tmpl_t *
vpt = NULL, *src_vpt = NULL, *dst_vpt = NULL;
555 goto get_packet_type;
559 cf_log_err(cs,
"The arguments to 'subrequest' must be a name or an attribute reference");
578 if ((name2[0] ==
'@') ||
579 ((name2[0] !=
':') && (name2[0] !=
'&') && (strchr(name2 + 1,
':') != NULL))) {
582 if (name2[0] ==
'@') name2++;
584 MEM(
namespace = talloc_strdup(
parent, name2));
596 cf_log_err(cs,
"Unknown namespace in '%s'", name2);
606 name2 += (q -
namespace);
607 TALLOC_FREE(
namespace);
614 if ((name2[0] ==
':') && (name2[1] ==
':')) {
616 goto get_packet_type;
622 if (strchr(name2,
':') != NULL) {
623 cf_log_err(cs,
"Reference cannot contain enum value in '%s'", name2);
633 &
FR_SBUFF_IN(name2, talloc_array_length(name2) - 1),
636 cf_log_perr(cs,
"Invalid argument to 'subrequest', failed parsing packet-type");
653 cf_log_err(cs,
"Invalid data type for attribute %s. "
654 "Must be an integer type or string", name2 + 1);
692 cf_log_err(cs,
"No such value '%s' for attribute 'Packet-Type' in namespace '%s'",
707 char const *dst, *src;
717 cf_log_perr(cs,
"Invalid argument to 'subrequest', failed parsing src");
722 cf_log_err(cs,
"Invalid argument to 'subrequest' src must be an attr or list, got %s",
736 cf_log_perr(cs,
"Invalid argument to 'subrequest', failed parsing dst");
741 cf_log_err(cs,
"Invalid argument to 'subrequest' dst must be an "
742 "attr or list, got %s",
776 unlang_ctx2.
rules = &t_rules;
797 talloc_steal(gext, dict_ref);
799 if (
vpt) gext->
vpt = talloc_steal(gext,
vpt);
817 .name =
"subrequest",
838 .unlang_name =
"unlang_subrequest_t",
843 .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_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.
#define RULES_VERIFY(_cs, _rules)
Common header for all CONF_* types.
A section grouping multiple CONF_PAIR.
fr_token_t cf_section_argv_quote(CONF_SECTION const *cs, int argc)
Return the quoting for one of the variadic arguments.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
char const * cf_section_argv(CONF_SECTION const *cs, int argc)
Return variadic argument at the specified index.
fr_token_t cf_section_name2_quote(CONF_SECTION const *cs)
Return the quoting of the name2 identifier.
#define cf_log_err(_cf, _fmt,...)
#define cf_item_next(_parent, _curr)
#define cf_log_perr(_cf, _fmt,...)
int unlang_child_request_op_init(void)
int unlang_child_request_init(TALLOC_CTX *ctx, unlang_child_request_t *out, request_t *child, unlang_result_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.
unlang_result_t result
The result of the child request.
unlang_child_request_state_t state
State of the child.
unlang_result_t * p_result
Pointer to the result of the child request.
@ 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.
unlang_t * unlang_compile_section(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_SECTION *cs, unlang_type_t type)
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.
#define fr_dict_autoload_talloc(_ctx, _dict_out, _proto)
fr_dict_t const * fr_dict_proto_dict(fr_dict_t const *dict)
bool const fr_dict_attr_allowed_chars[UINT8_MAX+1]
Characters that are allowed in dictionary attribute names.
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
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_t const * fr_dict_by_protocol_name(char const *name)
Lookup a protocol by its name.
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.
Structure used to managed the lifetime of a dictionary.
bool unlang_request_is_done(request_t const *request)
Return whether a request has been marked done.
bool unlang_request_is_scheduled(request_t const *request)
Return whether a request is currently scheduled.
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
int unlang_interpret_push(unlang_result_t *result_p, request_t *request, unlang_t const *instruction, unlang_frame_conf_t const *conf, bool do_next_sibling)
Push a new frame onto the stack.
#define FRAME_CONF(_default_rcode, _top_frame)
rlm_rcode_t rcode
The current rcode, from executing the instruction or merging the result from a frame.
Private declarations for the unlang interpreter.
static void interpret_child_init(request_t *request)
#define RPEDEBUG(fmt,...)
static TALLOC_CTX * unlang_ctx
void unlang_register(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.
static const char * packet_name[]
@ 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.
#define RETURN_UNLANG_NOOP
int request_detach(request_t *child)
Unlink a subrequest from its parent.
#define request_is_detachable(_x)
#define FR_SBUFF_IN(_start, _len_or_end)
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 char const * tmpl_type_to_str(tmpl_type_t type)
Return a static string containing the type name.
#define tmpl_is_attr(vpt)
tmpl_rules_t const * parent
for parent / child relationships
#define tmpl_contains_attr(vpt)
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, fr_sbuff_t *name, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
#define TMPL_POOL_DEF_HEADERS
Define manipulation functions for the attribute reference list.
#define TMPL_POOL_DEF_LEN
How many additional bytes to allocate in a pool for a tmpl_t.
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
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.
Optional arguments passed to vp_tmpl functions.
fr_signal_t
Signals that can be generated/processed by request signal handlers.
@ FR_SIGNAL_DETACH
Request is being detached from its parent.
fr_aka_sim_id_type_t type
uint8_t allow_foreign
Allow arguments not found in dict_def.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Stores an attribute, a value and various bits of other data.
static unlang_action_t unlang_subrequest_parent_resume(UNUSED unlang_result_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Parent being resumed after a child completes.
static unlang_action_t unlang_subrequest_init(unlang_result_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Allocates a new subrequest and initialises it.
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.
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.
void unlang_subrequest_detach_and_free(request_t **child)
Free a child request, detaching it from its parent and freeing allocated memory.
static unlang_action_t unlang_subrequest_child_done(unlang_result_t *p_result, UNUSED request_t *request, unlang_stack_frame_t *frame)
Function to run in the context of the parent on resumption.
static unlang_t * unlang_compile_subrequest(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_ITEM const *ci)
int unlang_subrequest_child_push(unlang_result_t *p_result, request_t *child, void const *unique_session_ptr, bool free_child, bool top_frame)
Push a pre-existing child back onto the stack as a subrequest.
unlang_action_t unlang_subrequest_child_run(UNUSED unlang_result_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.
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.
tmpl_rules_t const * rules
static void unlang_compile_ctx_copy(unlang_compile_ctx_t *dst, unlang_compile_ctx_t const *src)
static unlang_group_t * unlang_generic_to_group(unlang_t const *p)
char const * section_name1
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.
@ UNLANG_OP_FLAG_NO_FORCE_UNWIND
Must not be cancelled.
@ UNLANG_OP_FLAG_DEBUG_BRACES
Print debug braces.
@ UNLANG_OP_FLAG_RCODE_SET
Set request->rcode to the result of this operation.
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.
char const * section_name2
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.
#define FR_TYPE_INTEGER_EXCEPT_BOOL
#define DOC_KEYWORD_REF(_x)
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.