25 RCSID(
"$Id: 46578ae6aea94392125e6ac15c86eb4ae151197a $")
27 #include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
28 #include <freeradius-devel/server/cf_file.h>
29 #include <freeradius-devel/server/cf_parse.h>
30 #include <freeradius-devel/server/cf_util.h>
31 #include <freeradius-devel/server/exec.h>
32 #include <freeradius-devel/server/main_loop.h>
33 #include <freeradius-devel/server/request_data.h>
34 #include <freeradius-devel/server/trigger.h>
35 #include <freeradius-devel/unlang/function.h>
36 #include <freeradius-devel/unlang/interpret.h>
37 #include <freeradius-devel/unlang/subrequest.h>
38 #include <freeradius-devel/unlang/xlat.h>
40 #include <freeradius-devel/util/atexit.h>
41 #include <freeradius-devel/util/debug.h>
53 #define REQUEST_INDEX_TRIGGER_NAME 1
54 #define REQUEST_INDEX_TRIGGER_ARGS 2
84 ERROR(
"Triggers are not enabled");
89 ERROR(
"trigger xlat may only be used in a trigger command");
96 in_head->vb_strvalue);
98 ERROR(
"Unknown attribute \"%pV\"", in_head);
104 ERROR(
"Attribute \"%pV\" is not valid for this trigger", in_head);
129 return CMP(a->
ci, b->ci);
169 if (fr_value_box_list_empty(&trigger->
args)) {
170 RERROR(
"Failed trigger \"%s\" - did not expand to anything", trigger->
command);
182 false, NULL, trigger->
timeout) < 0) {
263 attr = strrchr(
name,
'.');
281 if (!subcs)
return -1;
285 DEBUG3(
"No trigger configured for: %s", attr);
290 ERROR(
"Trigger is not a configuration variable: %s", attr);
358 PERROR(
"Failed copying trigger arguments");
365 false,
false,
false) < 0)
goto args_error;
371 memcpy(&name_tmp, &
name,
sizeof(name_tmp));
374 name_tmp,
false,
false,
false) < 0) {
381 fr_value_box_list_init(&trigger->
args);
387 NULL, NULL, NULL,
false,
false);
393 cf_log_err(cp,
"Failed parsing trigger command");
411 PERROR(
"Running trigger failed");
462 ERROR(
"Incomplete dictionary: Missing definition for \"Connection-Pool-Server\"");
468 ERROR(
"Incomplete dictionary: Missing definition for \"Connection-Pool-Port\"");
477 vp->vp_uint16 = port;
483 pthread_mutex_destroy(mutex);
516 ERROR(
"%s - Pointer to main_config was NULL", __FUNCTION__);
524 WARN(
"trigger { ... } subsection not found, triggers will be disabled");
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_YIELD
Temporarily pause execution until an event occurs.
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
#define cf_log_perr(_cf, _fmt,...)
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
fr_dcursor_eval_t void const * uctx
static char const * spaces
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_dict_t const * fr_dict_internal(void)
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
int fr_exec_oneshot(TALLOC_CTX *ctx, fr_exec_state_t *exec, request_t *request, fr_value_box_list_t *args, fr_pair_list_t *env_pairs, bool env_escape, bool env_inherit, bool need_stdin, bool store_stdout, TALLOC_CTX *stdout_ctx, fr_time_delta_t timeout)
Call an child program, optionally reading it's output.
void fr_exec_oneshot_cleanup(fr_exec_state_t *exec, int signal)
Cleans up an exec'd process on error.
int status
return code of the program
#define unlang_function_repeat_set(_request, _repeat)
Set a new repeat function for an existing function frame.
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
void unlang_interpret_set(request_t *request, unlang_interpret_t *intp)
Set a specific interpreter for a request.
rlm_rcode_t unlang_interpret_synchronous(fr_event_list_t *el, request_t *request)
Execute an unlang section synchronously.
void fr_canonicalize_error(TALLOC_CTX *ctx, char **sp, char **text, ssize_t slen, char const *fmt)
Canonicalize error strings, removing tabs, and generate spaces for error marker.
fr_event_list_t * main_loop_event_list(void)
Return the main loop event list.
@ FR_TYPE_STRING
String of printable characters.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
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.
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_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
#define fr_rb_inline_talloc_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
The main red black tree structure.
rlm_rcode_t
Return codes indicating the result of the module call.
#define request_alloc_internal(_ctx, _args)
Allocate a new internal request.
Optional arguments for initialising requests.
void * request_data_reference(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request without removing it.
#define request_data_add(_request, _unique_ptr, _unique_int, _opaque, _free_on_replace, _free_on_parent, _persist)
Add opaque data to a request_t.
#define FR_SBUFF_IN(_start, _len_or_end)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
#define fr_time()
Allow us to arbitrarily manipulate time.
Stores an attribute, a value and various bits of other data.
int unlang_subrequest_child_push_and_detach(request_t *child)
void * talloc_null_ctx(void)
Retrieve the current talloc NULL ctx.
static int64_t fr_time_to_sec(fr_time_t when)
Convert an fr_time_t (internal time) to number of sec since the unix epoch (wallclock time)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_wrap(_time)
A time delta, a difference in time measured in nanoseconds.
static int _trigger_exec_init(void *cs_arg)
Set the global trigger section trigger_exec will search in, and register xlats.
static CONF_SECTION const * trigger_exec_subcs
fr_value_box_list_t args
Arguments to pass to the trigger exec.
static unlang_action_t trigger_done(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *rctx)
void trigger_args_afrom_server(TALLOC_CTX *ctx, fr_pair_list_t *list, char const *server, uint16_t port)
Create trigger arguments to describe the server the pool connects to.
xlat_arg_parser_t const trigger_xlat_args[]
static unlang_action_t trigger_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *rctx)
static int _mutex_free(pthread_mutex_t *mutex)
xlat_exp_head_t * xlat
xlat representation of the trigger args.
int trigger_exec_init(CONF_SECTION const *cs)
fr_rb_node_t node
Entry in the trigger last fired tree.
static bool triggers_init
Whether triggers are enabled globally.
fr_exec_state_t exec
Used for asynchronous execution.
fr_time_t last_fired
When this trigger last fired.
static int _trigger_exec_free(UNUSED void *uctx)
Free trigger resources.
#define REQUEST_INDEX_TRIGGER_NAME
static fr_rb_tree_t * trigger_last_fired_tree
static unlang_action_t trigger_run(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
#define REQUEST_INDEX_TRIGGER_ARGS
xlat_action_t trigger_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Retrieve attributes from a special trigger list.
char * command
Name of the trigger.
int trigger_exec(unlang_interpret_t *intp, CONF_SECTION const *cs, char const *name, bool rate_limit, fr_pair_list_t *args)
Execute a trigger - call an executable to process an event.
CONF_ITEM * ci
Config item this rate limit counter is associated with.
static pthread_mutex_t * trigger_mutex
static int8_t _trigger_last_fired_cmp(void const *one, void const *two)
Compares two last fired structures.
fr_time_delta_t timeout
How long the trigger has to run.
static void _trigger_last_fired_free(void *data)
bool trigger_enabled(void)
Return whether triggers are enabled.
static CONF_SECTION const * trigger_exec_main
Describes a rate limiting entry for a trigger.
int unlang_xlat_push(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, request_t *request, xlat_exp_head_t const *xlat, bool top_frame)
Push a pre-compiled xlat onto the stack for evaluation.
bool required
Argument must be present, and non-empty.
fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, xlat_t const *xlat, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool comma, bool allow_attr)
Tokenize an xlat expansion into a series of XLAT_TYPE_CHILD arguments.
#define XLAT_ARG_PARSER_TERMINATOR
int xlat_finalize(xlat_exp_head_t *head, fr_event_list_t *runtime_el)
Bootstrap static xlats, or instantiate ephemeral ones.
@ 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.
#define fr_strerror_const(_msg)
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
static size_t char ** out