The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
trigger.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/*
18 * $Id: e16037bd13bff2cea22e2d079b25dbdaa24f9d5c $
19 *
20 * @file trigger.c
21 * @brief Execute scripts when a server event occurs.
22 *
23 * @copyright 2015 The FreeRADIUS server project
24 */
25RCSID("$Id: e16037bd13bff2cea22e2d079b25dbdaa24f9d5c $")
26
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/exec.h>
31#include <freeradius-devel/server/main_loop.h>
32#include <freeradius-devel/server/request_data.h>
33#include <freeradius-devel/server/trigger.h>
34#include <freeradius-devel/unlang/function.h>
35#include <freeradius-devel/unlang/subrequest.h>
36#include <freeradius-devel/unlang/xlat.h>
37
38
39#include <sys/wait.h>
40
41/** Whether triggers are enabled globally
42 *
43 */
44static bool triggers_init;
48
49#define REQUEST_INDEX_TRIGGER_NAME 1
50#define REQUEST_INDEX_TRIGGER_ARGS 2
51
52/** Describes a rate limiting entry for a trigger
53 *
54 */
55typedef struct {
56 fr_rb_node_t node; //!< Entry in the trigger last fired tree.
57 CONF_ITEM *ci; //!< Config item this rate limit counter is associated with.
58 fr_time_t last_fired; //!< When this trigger last fired.
60
62 { .required = true, .single = true, .type = FR_TYPE_STRING },
64};
65
66/** Retrieve attributes from a special trigger list
67 *
68 */
70 UNUSED xlat_ctx_t const *xctx,
71 request_t *request, fr_value_box_list_t *in)
72{
73 fr_pair_list_t *head = NULL;
74 fr_dict_attr_t const *da;
76 fr_value_box_t *in_head = fr_value_box_list_head(in);
78
79 if (!triggers_init) {
80 ERROR("Triggers are not enabled");
81 return XLAT_ACTION_FAIL;
82 }
83
85 ERROR("trigger xlat may only be used in a trigger command");
86 return XLAT_ACTION_FAIL;
87 }
88
90
91 da = fr_dict_attr_by_name(NULL, fr_dict_root(request->local_dict), in_head->vb_strvalue);
92 if (!da) {
93 ERROR("Unknown attribute \"%pV\"", in_head);
94 return XLAT_ACTION_FAIL;
95 }
96
97 vp = fr_pair_find_by_da(head, NULL, da);
98 if (!vp) {
99 ERROR("Attribute \"%pV\" is not valid for this trigger", in_head);
100 return XLAT_ACTION_FAIL;
101 }
102
103 MEM(vb = fr_value_box_alloc_null(ctx));
104 fr_value_box_copy(vb, vb, &vp->data);
106 return XLAT_ACTION_DONE;
107}
108
110{
112}
113
114/** Compares two last fired structures
115 *
116 * @param one first pointer to compare.
117 * @param two second pointer to compare.
118 * @return CMP(one, two)
119 */
120static int8_t _trigger_last_fired_cmp(void const *one, void const *two)
121{
122 trigger_last_fired_t const *a = one, *b = two;
123
124 return CMP(a->ci, b->ci);
125}
126
127/** Return whether triggers are enabled
128 *
129 */
131{
132 return triggers_init;
133}
134
135typedef struct {
136 char *command; //!< Name of the trigger.
137 xlat_exp_head_t *xlat; //!< xlat representation of the trigger args.
138 fr_value_box_list_t args; //!< Arguments to pass to the trigger exec.
139
140 fr_exec_state_t exec; //!< Used for asynchronous execution.
141 fr_time_delta_t timeout; //!< How long the trigger has to run.
143
144static unlang_action_t trigger_done(rlm_rcode_t *p_result, UNUSED int *priority,
145 request_t *request, void *rctx)
146{
147 fr_trigger_t *trigger = talloc_get_type_abort(rctx, fr_trigger_t);
148
149 if (trigger->exec.status == 0) {
150 RDEBUG2("Trigger \"%s\" done", trigger->command);
152 }
153
154 RERROR("Trigger \"%s\" failed", trigger->command);
155
157}
158
159static unlang_action_t trigger_resume(rlm_rcode_t *p_result, UNUSED int *priority,
160 request_t *request, void *rctx)
161{
162 fr_trigger_t *trigger = talloc_get_type_abort(rctx, fr_trigger_t);
163
164 if (fr_value_box_list_empty(&trigger->args)) {
165 RERROR("Failed trigger \"%s\" - did not expand to anything", trigger->command);
167 }
168
169 /*
170 * fr_exec_oneshot just calls request_resume when it's
171 * done.
172 */
173 if (fr_exec_oneshot(request, &trigger->exec, request,
174 &trigger->args,
175 NULL, false, true,
176 false,
177 false, NULL, trigger->timeout) < 0) {
178 fail:
179 RPERROR("Failed running trigger \"%s\"", trigger->command);
181 }
182
183 /*
184 * Swap out the repeat function so that when we're
185 * resumed the code path in the interpreter pops
186 * the frame. If we don't do this trigger_run just
187 * gets called repeatedly.
188 */
189 if (unlang_function_repeat_set(request, trigger_done) < 0) {
190 fr_exec_oneshot_cleanup(&trigger->exec, SIGKILL);
191 goto fail;
192 }
193
194 return UNLANG_ACTION_YIELD;
195}
196
197static unlang_action_t trigger_run(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
198{
199 fr_trigger_t *trigger = talloc_get_type_abort(uctx, fr_trigger_t);
200
201 RDEBUG("Running trigger \"%s\"", trigger->command);
202
203 if (unlang_xlat_push(request, NULL, &trigger->args, request,
205
207}
208
209
210/** Execute a trigger - call an executable to process an event
211 *
212 * @note Calls to this function will be ignored if #trigger_exec_init has not been called.
213 *
214 * @param[in] intp Interpreter to run the trigger with. If this is NULL the
215 * trigger will be executed synchronously.
216 * @param[in] cs to search for triggers in.
217 * If cs is not NULL, the portion after the last '.' in name is used for the trigger.
218 * If cs is NULL, the entire name is used to find the trigger in the global trigger
219 * section.
220 * @param[in] name the path relative to the global trigger section ending in the trigger name
221 * e.g. module.ldap.pool.start.
222 * @param[in] rate_limit whether to rate limit triggers.
223 * @param[in] args to make available via the @verbatim %trigger(<arg>) @endverbatim xlat.
224 * @return
225 * - 0 on success.
226 * - -1 on failure.
227 */
229 CONF_SECTION const *cs, char const *name, bool rate_limit, fr_pair_list_t *args)
230{
231 CONF_SECTION const *subcs;
232
233 CONF_ITEM *ci;
234 CONF_PAIR *cp;
235
236 char const *attr;
237 char const *value;
238
239 request_t *request;
240 fr_trigger_t *trigger;
241 ssize_t slen;
242
243 /*
244 * noop if trigger_exec_init was never called
245 */
246 if (!triggers_init) return 0;
247
248 /*
249 * Use global "trigger" section if no local config is given.
250 */
251 if (!cs) {
253 attr = name;
254 } else {
255 /*
256 * Try to use pair name, rather than reference.
257 */
258 attr = strrchr(name, '.');
259 if (attr) {
260 attr++;
261 } else {
262 attr = name;
263 }
264 }
265
266 /*
267 * Find local "trigger" subsection. If it isn't found,
268 * try using the global "trigger" section, and reset the
269 * reference to the full path, rather than the sub-path.
270 */
271 subcs = cf_section_find(cs, "trigger", NULL);
272 if (!subcs && trigger_exec_main && (cs != trigger_exec_main)) {
273 subcs = trigger_exec_subcs;
274 attr = name;
275 }
276 if (!subcs) return -1;
277
278 ci = cf_reference_item(subcs, trigger_exec_main, attr);
279 if (!ci) {
280 DEBUG3("No trigger configured for: %s", attr);
281 return -1;
282 }
283
284 if (!cf_item_is_pair(ci)) {
285 ERROR("Trigger is not a configuration variable: %s", attr);
286 return -1;
287 }
288
289 cp = cf_item_to_pair(ci);
290 if (!cp) return -1;
291
292 value = cf_pair_value(cp);
293 if (!value) {
294 ERROR("Trigger has no value: %s", name);
295 return -1;
296 }
297
298 /*
299 * Don't do any real work if we're checking the
300 * configuration. i.e. don't run "start" or "stop"
301 * triggers on "radiusd -XC".
302 */
303 if (check_config) return 0;
304
305 /*
306 * Perform periodic rate_limiting.
307 */
308 if (rate_limit) {
309 trigger_last_fired_t find, *found;
310 fr_time_t now = fr_time();
311
312 find.ci = ci;
313
314 pthread_mutex_lock(trigger_mutex);
315
316 found = fr_rb_find(trigger_last_fired_tree, &find);
317 if (!found) {
318 MEM(found = talloc(NULL, trigger_last_fired_t));
319 found->ci = ci;
320 /*
321 * Initialise last_fired to 2 seconds ago so
322 * the trigger fires on the first occurrence
323 */
324 found->last_fired = fr_time_wrap(NSEC * -2);
325
327 }
328
329 pthread_mutex_unlock(trigger_mutex);
330
331 /*
332 * Send the rate_limited traps at most once per second.
333 */
334 if (fr_time_to_sec(found->last_fired) == fr_time_to_sec(now)) return -1;
335 found->last_fired = now;
336 }
337
338 /*
339 * Allocate a request to run asynchronously in the interpreter.
340 */
341 request = request_local_alloc_internal(NULL, (&(request_init_args_t){ .detachable = true }));
342
343 /*
344 * Add the args to the request data, so they can be picked up by the
345 * trigger_xlat function.
346 */
347 if (args) {
348 fr_pair_list_t *local_args;
349
350 MEM(local_args = talloc_zero(request, fr_pair_list_t));
351 fr_pair_list_init(local_args);
352 if (fr_pair_list_copy(local_args, local_args, args) < 0) {
353 PERROR("Failed copying trigger arguments");
354 args_error:
355 talloc_free(request);
356 return -1;
357 }
358
360 false, false, false) < 0) goto args_error;
361 }
362
363 {
364 void *name_tmp;
365
366 memcpy(&name_tmp, &name, sizeof(name_tmp));
367
369 name_tmp, false, false, false) < 0) {
370 talloc_free(request);
371 return -1;
372 }
373 }
374
375 MEM(trigger = talloc_zero(request, fr_trigger_t));
376 fr_value_box_list_init(&trigger->args);
377 trigger->command = talloc_strdup(trigger, value);
378 trigger->timeout = fr_time_delta_from_sec(5); /* @todo - Should be configurable? */
379
380 slen = xlat_tokenize_argv(trigger, &trigger->xlat,
381 &FR_SBUFF_IN(trigger->command, talloc_array_length(trigger->command) - 1),
382 NULL, NULL, &(tmpl_rules_t) {
383 .attr = {
384 .dict_def = request->local_dict,
385 .list_def = request_attr_request,
386 .allow_unresolved = false,
387 },
388 }, true);
389 if (slen <= 0) {
390 char *spaces, *text;
391
392 fr_canonicalize_error(trigger, &spaces, &text, slen, trigger->command);
393
394 cf_log_err(cp, "Failed parsing trigger command");
395 cf_log_err(cp, "%s", text);
396 cf_log_perr(cp, "%s^", spaces);
397
398 talloc_free(request);
400 talloc_free(text);
401 return -1;
402 }
403
404 /*
405 * If we're not running it locally use the default
406 * interpreter for the thread.
407 */
408 if (intp) {
409 unlang_interpret_set(request, intp);
411 error:
412 PERROR("Running trigger failed");
413 talloc_free(request);
414 return -1;
415 }
416 }
417
418 if (xlat_finalize(trigger->xlat, intp ? unlang_interpret_event_list(request) : main_loop_event_list()) < 0) {
419 fr_strerror_const("Failed performing ephemeral instantiation for xlat");
420 talloc_free(request);
421 return -1;
422 }
423
425 NULL, 0, UNLANG_TOP_FRAME, trigger) < 0) goto error;
426
427 if (!intp) {
428 /*
429 * Wait for the exec to finish too,
430 * so where there are global events
431 * the request processes don't race
432 * with something like the server
433 * shutting down.
434 */
435 unlang_interpret_synchronous(NULL, request);
436 talloc_free(request);
437 }
438
439 /*
440 * Otherwise the worker cleans up the request request.
441 */
442 return 0;
443}
444
445/** Create trigger arguments to describe the server the pool connects to
446 *
447 * @note #trigger_exec_init must be called before calling this function,
448 * else it will return NULL.
449 *
450 * @param[in] ctx to allocate fr_pair_t s in.
451 * @param[out] list to append Pool-Server and Pool-Port pairs to
452 * @param[in] server we're connecting to.
453 * @param[in] port on that server.
454 */
455void trigger_args_afrom_server(TALLOC_CTX *ctx, fr_pair_list_t *list, char const *server, uint16_t port)
456{
457 fr_dict_attr_t const *server_da;
458 fr_dict_attr_t const *port_da;
459 fr_pair_t *vp;
460
461 server_da = fr_dict_attr_child_by_num(fr_dict_root(fr_dict_internal()), FR_CONNECTION_POOL_SERVER);
462 if (!server_da) {
463 ERROR("Incomplete dictionary: Missing definition for \"Connection-Pool-Server\"");
464 return;
465 }
466
467 port_da = fr_dict_attr_child_by_num(fr_dict_root(fr_dict_internal()), FR_CONNECTION_POOL_PORT);
468 if (!port_da) {
469 ERROR("Incomplete dictionary: Missing definition for \"Connection-Pool-Port\"");
470 return;
471 }
472
473 MEM(vp = fr_pair_afrom_da(ctx, server_da));
474 fr_pair_value_strdup(vp, server, false);
475 fr_pair_append(list, vp);
476
477 MEM(vp = fr_pair_afrom_da(ctx, port_da));
478 vp->vp_uint16 = port;
479 fr_pair_append(list, vp);
480}
481
482static int _mutex_free(pthread_mutex_t *mutex)
483{
484 pthread_mutex_destroy(mutex);
485 return 0;
486}
487
488/** Free trigger resources
489 *
490 */
491static int _trigger_exec_free(UNUSED void *uctx)
492{
493 TALLOC_FREE(trigger_last_fired_tree);
494 TALLOC_FREE(trigger_mutex);
495
496 return 0;
497}
498
499/** Set the global trigger section trigger_exec will search in, and register xlats
500 *
501 * This function exists because triggers are used by the connection pool, which
502 * is used in the server library which may not have the mainconfig available.
503 * Additionally, utilities may want to set their own root config sections.
504 *
505 * We don't register the trigger xlat here, as we may inadvertently initialise
506 * the xlat code, which is annoying when this is called from a utility.
507 *
508 * @param[in] cs_arg to use as global trigger section.
509 * @return
510 * - 0 on success.
511 * - -1 on failure.
512 */
513static int _trigger_exec_init(void *cs_arg)
514{
515 CONF_SECTION *cs = talloc_get_type_abort(cs_arg, CONF_SECTION);
516 if (!cs) {
517 ERROR("%s - Pointer to main_config was NULL", __FUNCTION__);
518 return -1;
519 }
520
522 trigger_exec_subcs = cf_section_find(cs, "trigger", NULL);
523
524 if (!trigger_exec_subcs) {
525 WARN("trigger { ... } subsection not found, triggers will be disabled");
526 return 0;
527 }
528
532
534 pthread_mutex_init(trigger_mutex, 0);
535 talloc_set_destructor(trigger_mutex, _mutex_free);
536 triggers_init = true;
537
538 return 0;
539}
540
542{
543 int ret;
544
545 fr_atexit_global_once_ret(&ret, _trigger_exec_init, _trigger_exec_free, UNCONST(CONF_SECTION *, cs));
546
547 return ret;
548}
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
Definition action.h:39
@ UNLANG_ACTION_YIELD
Temporarily pause execution until an event occurs.
Definition action.h:42
va_list args
Definition acutest.h:770
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
#define RCSID(id)
Definition build.h:485
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:112
#define UNUSED
Definition build.h:317
bool check_config
Definition cf_file.c:62
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
Definition cf_file.c:3710
Common header for all CONF_* types.
Definition cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition cf_util.c:631
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1027
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:663
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1593
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:296
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:406
#define MEM(x)
Definition debug.h:36
static char const * spaces
Definition dependency.c:370
#define ERROR(fmt,...)
Definition dhcpclient.c:41
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.
Definition dict_util.c:3265
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2402
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4612
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.
Definition dict_util.c:3330
static fr_slen_t in
Definition dict.h:833
Test enumeration values.
Definition dict_test.h:92
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.
Definition exec.c:982
void fr_exec_oneshot_cleanup(fr_exec_state_t *exec, int signal)
Cleans up an exec'd process on error.
Definition exec.c:664
int status
return code of the program
Definition exec.h:77
#define unlang_function_repeat_set(_request, _repeat)
Set a new repeat function for an existing function frame.
Definition function.h:89
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
Definition function.h:111
void unlang_interpret_set(request_t *request, unlang_interpret_t *intp)
Set a specific interpreter for a request.
Definition interpret.c:1803
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
Definition interpret.c:1822
#define UNLANG_SUB_FRAME
Definition interpret.h:36
#define UNLANG_TOP_FRAME
Definition interpret.h:35
rlm_rcode_t unlang_interpret_synchronous(fr_event_list_t *el, request_t *request)
Execute an unlang section synchronously.
#define PERROR(_fmt,...)
Definition log.h:228
#define DEBUG3(_fmt,...)
Definition log.h:266
#define RERROR(fmt,...)
Definition log.h:298
#define RPERROR(fmt,...)
Definition log.h:302
talloc_free(reap)
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.
Definition log.c:87
fr_event_list_t * main_loop_event_list(void)
Return the main loop event list.
Definition main_loop.c:164
unsigned short uint16_t
@ FR_TYPE_STRING
String of printable characters.
long int ssize_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.
Definition pair.c:2321
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
Definition pair.c:2637
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.
Definition pair.c:695
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1347
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.
Definition pair.c:285
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
#define RDEBUG2(fmt,...)
Definition radclient.h:54
#define RDEBUG(fmt,...)
Definition radclient.h:53
#define WARN(fmt,...)
Definition radclient.h:47
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
Definition rb.c:577
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition rb.c:626
#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.
Definition rb.h:246
The main red black tree structure.
Definition rb.h:73
#define RETURN_MODULE_OK
Definition rcode.h:57
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
#define request_local_alloc_internal(_ctx, _args)
Allocate a new internal request outside of the request pool.
Definition request.h:339
Optional arguments for initialising requests.
Definition request.h:283
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.
static char const * name
#define FR_SBUFF_IN(_start, _len_or_end)
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:332
fr_pair_t * vp
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition state_test.c:8
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
int unlang_subrequest_child_push_and_detach(request_t *child)
void * talloc_null_ctx(void)
Retrieve the current talloc NULL ctx.
Definition talloc.c:49
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)
Definition time.h:731
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
#define fr_time_wrap(_time)
Definition time.h:145
#define NSEC
Definition time.h:379
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"server local" time.
Definition time.h:69
static int _trigger_exec_init(void *cs_arg)
Set the global trigger section trigger_exec will search in, and register xlats.
Definition trigger.c:513
static CONF_SECTION const * trigger_exec_subcs
Definition trigger.c:45
fr_value_box_list_t args
Arguments to pass to the trigger exec.
Definition trigger.c:138
static unlang_action_t trigger_done(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *rctx)
Definition trigger.c:144
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.
Definition trigger.c:455
xlat_arg_parser_t const trigger_xlat_args[]
Definition trigger.c:61
static unlang_action_t trigger_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *rctx)
Definition trigger.c:159
static int _mutex_free(pthread_mutex_t *mutex)
Definition trigger.c:482
xlat_exp_head_t * xlat
xlat representation of the trigger args.
Definition trigger.c:137
int trigger_exec_init(CONF_SECTION const *cs)
Definition trigger.c:541
fr_rb_node_t node
Entry in the trigger last fired tree.
Definition trigger.c:56
static bool triggers_init
Whether triggers are enabled globally.
Definition trigger.c:44
fr_exec_state_t exec
Used for asynchronous execution.
Definition trigger.c:140
fr_time_t last_fired
When this trigger last fired.
Definition trigger.c:58
static int _trigger_exec_free(UNUSED void *uctx)
Free trigger resources.
Definition trigger.c:491
#define REQUEST_INDEX_TRIGGER_NAME
Definition trigger.c:49
static fr_rb_tree_t * trigger_last_fired_tree
Definition trigger.c:46
static unlang_action_t trigger_run(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Definition trigger.c:197
#define REQUEST_INDEX_TRIGGER_ARGS
Definition trigger.c:50
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.
Definition trigger.c:69
char * command
Name of the trigger.
Definition trigger.c:136
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.
Definition trigger.c:228
CONF_ITEM * ci
Config item this rate limit counter is associated with.
Definition trigger.c:57
static pthread_mutex_t * trigger_mutex
Definition trigger.c:47
static int8_t _trigger_last_fired_cmp(void const *one, void const *two)
Compares two last fired structures.
Definition trigger.c:120
fr_time_delta_t timeout
How long the trigger has to run.
Definition trigger.c:141
static void _trigger_last_fired_free(void *data)
Definition trigger.c:109
bool trigger_enabled(void)
Return whether triggers are enabled.
Definition trigger.c:130
static CONF_SECTION const * trigger_exec_main
Definition trigger.c:45
Describes a rate limiting entry for a trigger.
Definition trigger.c:55
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.
Definition xlat.c:282
bool required
Argument must be present, and non-empty.
Definition xlat.h:145
static fr_slen_t head
Definition xlat.h:416
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 spaces))
Tokenize an xlat expansion into a series of XLAT_TYPE_CHILD arguments.
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:166
int xlat_finalize(xlat_exp_head_t *head, fr_event_list_t *runtime_el)
Bootstrap static xlats, or instantiate ephemeral ones.
Definition xlat_inst.c:693
xlat_action_t
Definition xlat.h:37
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition xlat.h:44
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition xlat.h:43
Definition for a single argument consumend by an xlat function.
Definition xlat.h:144
#define fr_strerror_const(_msg)
Definition strerror.h:223
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.
Definition value.c:3963
static fr_slen_t data
Definition value.h:1274
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:643
static size_t char ** out
Definition value.h:1012
An xlat calling ctx.
Definition xlat_ctx.h:49