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: 46578ae6aea94392125e6ac15c86eb4ae151197a $
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: 46578ae6aea94392125e6ac15c86eb4ae151197a $")
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/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>
39
40#include <freeradius-devel/util/atexit.h>
41#include <freeradius-devel/util/debug.h>
42
43#include <sys/wait.h>
44
45/** Whether triggers are enabled globally
46 *
47 */
48static bool triggers_init;
52
53#define REQUEST_INDEX_TRIGGER_NAME 1
54#define REQUEST_INDEX_TRIGGER_ARGS 2
55
56/** Describes a rate limiting entry for a trigger
57 *
58 */
59typedef struct {
60 fr_rb_node_t node; //!< Entry in the trigger last fired tree.
61 CONF_ITEM *ci; //!< Config item this rate limit counter is associated with.
62 fr_time_t last_fired; //!< When this trigger last fired.
64
66 { .required = true, .single = true, .type = FR_TYPE_STRING },
68};
69
70/** Retrieve attributes from a special trigger list
71 *
72 */
74 UNUSED xlat_ctx_t const *xctx,
75 request_t *request, fr_value_box_list_t *in)
76{
77 fr_pair_list_t *head = NULL;
78 fr_dict_attr_t const *da;
80 fr_value_box_t *in_head = fr_value_box_list_head(in);
82
83 if (!triggers_init) {
84 ERROR("Triggers are not enabled");
85 return XLAT_ACTION_FAIL;
86 }
87
89 ERROR("trigger xlat may only be used in a trigger command");
90 return XLAT_ACTION_FAIL;
91 }
92
94
95 da = fr_dict_attr_by_name(NULL, fr_dict_root(request->dict ? request->dict : fr_dict_internal()),
96 in_head->vb_strvalue);
97 if (!da) {
98 ERROR("Unknown attribute \"%pV\"", in_head);
99 return XLAT_ACTION_FAIL;
100 }
101
102 vp = fr_pair_find_by_da(head, NULL, da);
103 if (!vp) {
104 ERROR("Attribute \"%pV\" is not valid for this trigger", in_head);
105 return XLAT_ACTION_FAIL;
106 }
107
108 MEM(vb = fr_value_box_alloc_null(ctx));
109 fr_value_box_copy(vb, vb, &vp->data);
111 return XLAT_ACTION_DONE;
112}
113
115{
117}
118
119/** Compares two last fired structures
120 *
121 * @param one first pointer to compare.
122 * @param two second pointer to compare.
123 * @return CMP(one, two)
124 */
125static int8_t _trigger_last_fired_cmp(void const *one, void const *two)
126{
127 trigger_last_fired_t const *a = one, *b = two;
128
129 return CMP(a->ci, b->ci);
130}
131
132/** Return whether triggers are enabled
133 *
134 */
136{
137 return triggers_init;
138}
139
140typedef struct {
141 char *command; //!< Name of the trigger.
142 xlat_exp_head_t *xlat; //!< xlat representation of the trigger args.
143 fr_value_box_list_t args; //!< Arguments to pass to the trigger exec.
144
145 fr_exec_state_t exec; //!< Used for asynchronous execution.
146 fr_time_delta_t timeout; //!< How long the trigger has to run.
148
149static unlang_action_t trigger_done(rlm_rcode_t *p_result, UNUSED int *priority,
150 request_t *request, void *rctx)
151{
152 fr_trigger_t *trigger = talloc_get_type_abort(rctx, fr_trigger_t);
153
154 if (trigger->exec.status == 0) {
155 RDEBUG2("Trigger \"%s\" done", trigger->command);
157 }
158
159 RERROR("Trigger \"%s\" failed", trigger->command);
160
162}
163
164static unlang_action_t trigger_resume(rlm_rcode_t *p_result, UNUSED int *priority,
165 request_t *request, void *rctx)
166{
167 fr_trigger_t *trigger = talloc_get_type_abort(rctx, fr_trigger_t);
168
169 if (fr_value_box_list_empty(&trigger->args)) {
170 RERROR("Failed trigger \"%s\" - did not expand to anything", trigger->command);
172 }
173
174 /*
175 * fr_exec_oneshot just calls request_resume when it's
176 * done.
177 */
178 if (fr_exec_oneshot(request, &trigger->exec, request,
179 &trigger->args,
180 NULL, false, true,
181 false,
182 false, NULL, trigger->timeout) < 0) {
183 fail:
184 RPERROR("Failed running trigger \"%s\"", trigger->command);
186 }
187
188 /*
189 * Swap out the repeat function so that when we're
190 * resumed the code path in the interpreter pops
191 * the frame. If we don't do this trigger_run just
192 * gets called repeatedly.
193 */
194 if (unlang_function_repeat_set(request, trigger_done) < 0) {
195 fr_exec_oneshot_cleanup(&trigger->exec, SIGKILL);
196 goto fail;
197 }
198
199 return UNLANG_ACTION_YIELD;
200}
201
202static unlang_action_t trigger_run(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
203{
204 fr_trigger_t *trigger = talloc_get_type_abort(uctx, fr_trigger_t);
205
206 RDEBUG("Running trigger \"%s\"", trigger->command);
207
208 if (unlang_xlat_push(request, NULL, &trigger->args, request,
210
212}
213
214
215/** Execute a trigger - call an executable to process an event
216 *
217 * @note Calls to this function will be ignored if #trigger_exec_init has not been called.
218 *
219 * @param[in] intp Interpreter to run the trigger with. If this is NULL the
220 * trigger will be executed synchronously.
221 * @param[in] cs to search for triggers in.
222 * If cs is not NULL, the portion after the last '.' in name is used for the trigger.
223 * If cs is NULL, the entire name is used to find the trigger in the global trigger
224 * section.
225 * @param[in] name the path relative to the global trigger section ending in the trigger name
226 * e.g. module.ldap.pool.start.
227 * @param[in] rate_limit whether to rate limit triggers.
228 * @param[in] args to make available via the @verbatim %trigger(<arg>) @endverbatim xlat.
229 * @return
230 * - 0 on success.
231 * - -1 on failure.
232 */
234 CONF_SECTION const *cs, char const *name, bool rate_limit, fr_pair_list_t *args)
235{
236 CONF_SECTION const *subcs;
237
238 CONF_ITEM *ci;
239 CONF_PAIR *cp;
240
241 char const *attr;
242 char const *value;
243
244 request_t *request;
245 fr_trigger_t *trigger;
246 ssize_t slen;
247
248 /*
249 * noop if trigger_exec_init was never called
250 */
251 if (!triggers_init) return 0;
252
253 /*
254 * Use global "trigger" section if no local config is given.
255 */
256 if (!cs) {
258 attr = name;
259 } else {
260 /*
261 * Try to use pair name, rather than reference.
262 */
263 attr = strrchr(name, '.');
264 if (attr) {
265 attr++;
266 } else {
267 attr = name;
268 }
269 }
270
271 /*
272 * Find local "trigger" subsection. If it isn't found,
273 * try using the global "trigger" section, and reset the
274 * reference to the full path, rather than the sub-path.
275 */
276 subcs = cf_section_find(cs, "trigger", NULL);
277 if (!subcs && trigger_exec_main && (cs != trigger_exec_main)) {
278 subcs = trigger_exec_subcs;
279 attr = name;
280 }
281 if (!subcs) return -1;
282
283 ci = cf_reference_item(subcs, trigger_exec_main, attr);
284 if (!ci) {
285 DEBUG3("No trigger configured for: %s", attr);
286 return -1;
287 }
288
289 if (!cf_item_is_pair(ci)) {
290 ERROR("Trigger is not a configuration variable: %s", attr);
291 return -1;
292 }
293
294 cp = cf_item_to_pair(ci);
295 if (!cp) return -1;
296
297 value = cf_pair_value(cp);
298 if (!value) {
299 ERROR("Trigger has no value: %s", name);
300 return -1;
301 }
302
303 /*
304 * Don't do any real work if we're checking the
305 * configuration. i.e. don't run "start" or "stop"
306 * triggers on "radiusd -XC".
307 */
308 if (check_config) return 0;
309
310 /*
311 * Perform periodic rate_limiting.
312 */
313 if (rate_limit) {
314 trigger_last_fired_t find, *found;
315 fr_time_t now = fr_time();
316
317 find.ci = ci;
318
319 pthread_mutex_lock(trigger_mutex);
320
321 found = fr_rb_find(trigger_last_fired_tree, &find);
322 if (!found) {
323 MEM(found = talloc(NULL, trigger_last_fired_t));
324 found->ci = ci;
325 /*
326 * Initialise last_fired to 2 seconds ago so
327 * the trigger fires on the first occurrence
328 */
329 found->last_fired = fr_time_wrap(NSEC * -2);
330
332 }
333
334 pthread_mutex_unlock(trigger_mutex);
335
336 /*
337 * Send the rate_limited traps at most once per second.
338 */
339 if (fr_time_to_sec(found->last_fired) == fr_time_to_sec(now)) return -1;
340 found->last_fired = now;
341 }
342
343 /*
344 * Allocate a request to run asynchronously in the interpreter.
345 */
346 request = request_alloc_internal(NULL, (&(request_init_args_t){ .detachable = true }));
347
348 /*
349 * Add the args to the request data, so they can be picked up by the
350 * trigger_xlat function.
351 */
352 if (args) {
353 fr_pair_list_t *local_args;
354
355 MEM(local_args = talloc_zero(request, fr_pair_list_t));
356 fr_pair_list_init(local_args);
357 if (fr_pair_list_copy(local_args, local_args, args) < 0) {
358 PERROR("Failed copying trigger arguments");
359 args_error:
360 talloc_free(request);
361 return -1;
362 }
363
365 false, false, false) < 0) goto args_error;
366 }
367
368 {
369 void *name_tmp;
370
371 memcpy(&name_tmp, &name, sizeof(name_tmp));
372
374 name_tmp, false, false, false) < 0) {
375 talloc_free(request);
376 return -1;
377 }
378 }
379
380 MEM(trigger = talloc_zero(request, fr_trigger_t));
381 fr_value_box_list_init(&trigger->args);
382 trigger->command = talloc_strdup(trigger, value);
383 trigger->timeout = fr_time_delta_from_sec(5); /* FIXME - Should be configurable? */
384
385 slen = xlat_tokenize_argv(trigger, &trigger->xlat,
386 &FR_SBUFF_IN(trigger->command, talloc_array_length(trigger->command) - 1),
387 NULL, NULL, NULL, false, false);
388 if (slen <= 0) {
389 char *spaces, *text;
390
391 fr_canonicalize_error(trigger, &spaces, &text, slen, trigger->command);
392
393 cf_log_err(cp, "Failed parsing trigger command");
394 cf_log_err(cp, "%s", text);
395 cf_log_perr(cp, "%s^", spaces);
396
397 talloc_free(request);
399 talloc_free(text);
400 return -1;
401 }
402
403 /*
404 * If we're not running it locally use the default
405 * interpreter for the thread.
406 */
407 if (intp) {
408 unlang_interpret_set(request, intp);
410 error:
411 PERROR("Running trigger failed");
412 talloc_free(request);
413 return -1;
414 }
415 }
416
417 if (xlat_finalize(trigger->xlat, intp ? unlang_interpret_event_list(request) : main_loop_event_list()) < 0) {
418 fr_strerror_const("Failed performing ephemeral instantiation for xlat");
419 talloc_free(request);
420 return -1;
421 }
422
424 NULL, 0, UNLANG_TOP_FRAME, trigger) < 0) goto error;
425
426 if (!intp) {
427 /*
428 * Wait for the exec to finish too,
429 * so where there are global events
430 * the request processes don't race
431 * with something like the server
432 * shutting down.
433 */
434 unlang_interpret_synchronous(NULL, request);
435 talloc_free(request);
436 }
437
438 /*
439 * Otherwise the worker cleans up the request request.
440 */
441 return 0;
442}
443
444/** Create trigger arguments to describe the server the pool connects to
445 *
446 * @note #trigger_exec_init must be called before calling this function,
447 * else it will return NULL.
448 *
449 * @param[in] ctx to allocate fr_pair_t s in.
450 * @param[out] list to append Pool-Server and Pool-Port pairs to
451 * @param[in] server we're connecting to.
452 * @param[in] port on that server.
453 */
454void trigger_args_afrom_server(TALLOC_CTX *ctx, fr_pair_list_t *list, char const *server, uint16_t port)
455{
456 fr_dict_attr_t const *server_da;
457 fr_dict_attr_t const *port_da;
458 fr_pair_t *vp;
459
460 server_da = fr_dict_attr_child_by_num(fr_dict_root(fr_dict_internal()), FR_CONNECTION_POOL_SERVER);
461 if (!server_da) {
462 ERROR("Incomplete dictionary: Missing definition for \"Connection-Pool-Server\"");
463 return;
464 }
465
466 port_da = fr_dict_attr_child_by_num(fr_dict_root(fr_dict_internal()), FR_CONNECTION_POOL_PORT);
467 if (!port_da) {
468 ERROR("Incomplete dictionary: Missing definition for \"Connection-Pool-Port\"");
469 return;
470 }
471
472 MEM(vp = fr_pair_afrom_da(ctx, server_da));
473 fr_pair_value_strdup(vp, server, false);
474 fr_pair_append(list, vp);
475
476 MEM(vp = fr_pair_afrom_da(ctx, port_da));
477 vp->vp_uint16 = port;
478 fr_pair_append(list, vp);
479}
480
481static int _mutex_free(pthread_mutex_t *mutex)
482{
483 pthread_mutex_destroy(mutex);
484 return 0;
485}
486
487/** Free trigger resources
488 *
489 */
490static int _trigger_exec_free(UNUSED void *uctx)
491{
492 TALLOC_FREE(trigger_last_fired_tree);
493 TALLOC_FREE(trigger_mutex);
494
495 return 0;
496}
497
498/** Set the global trigger section trigger_exec will search in, and register xlats
499 *
500 * This function exists because triggers are used by the connection pool, which
501 * is used in the server library which may not have the mainconfig available.
502 * Additionally, utilities may want to set their own root config sections.
503 *
504 * We don't register the trigger xlat here, as we may inadvertently initialise
505 * the xlat code, which is annoying when this is called from a utility.
506 *
507 * @param[in] cs_arg to use as global trigger section.
508 * @return
509 * - 0 on success.
510 * - -1 on failure.
511 */
512static int _trigger_exec_init(void *cs_arg)
513{
514 CONF_SECTION *cs = talloc_get_type_abort(cs_arg, CONF_SECTION);
515 if (!cs) {
516 ERROR("%s - Pointer to main_config was NULL", __FUNCTION__);
517 return -1;
518 }
519
521 trigger_exec_subcs = cf_section_find(cs, "trigger", NULL);
522
523 if (!trigger_exec_subcs) {
524 WARN("trigger { ... } subsection not found, triggers will be disabled");
525 return 0;
526 }
527
531
533 pthread_mutex_init(trigger_mutex, 0);
534 talloc_set_destructor(trigger_mutex, _mutex_free);
535 triggers_init = true;
536
537 return 0;
538}
539
541{
542 int ret;
543
544 fr_atexit_global_once_ret(&ret, _trigger_exec_init, _trigger_exec_free, UNCONST(CONF_SECTION *, cs));
545
546 return ret;
547}
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:483
#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:315
bool check_config
Definition cf_file.c:67
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
Definition cf_file.c:3619
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:632
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:1028
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:664
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1594
#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:371
#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:3263
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2400
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4610
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:3328
static fr_slen_t in
Definition dict.h:824
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:984
void fr_exec_oneshot_cleanup(fr_exec_state_t *exec, int signal)
Cleans up an exec'd process on error.
Definition exec.c:666
int status
return code of the program
Definition exec.h:76
#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:1745
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
Definition interpret.c:1764
#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:90
fr_event_list_t * main_loop_event_list(void)
Return the main loop event list.
Definition main_loop.c:165
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:2319
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
Definition pair.c:2634
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:693
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:1345
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:283
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_alloc_internal(_ctx, _args)
Allocate a new internal request.
Definition request.h:305
Optional arguments for initialising requests.
Definition request.h:254
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)
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:53
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:512
static CONF_SECTION const * trigger_exec_subcs
Definition trigger.c:49
fr_value_box_list_t args
Arguments to pass to the trigger exec.
Definition trigger.c:143
static unlang_action_t trigger_done(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *rctx)
Definition trigger.c:149
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:454
xlat_arg_parser_t const trigger_xlat_args[]
Definition trigger.c:65
static unlang_action_t trigger_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *rctx)
Definition trigger.c:164
static int _mutex_free(pthread_mutex_t *mutex)
Definition trigger.c:481
xlat_exp_head_t * xlat
xlat representation of the trigger args.
Definition trigger.c:142
int trigger_exec_init(CONF_SECTION const *cs)
Definition trigger.c:540
fr_rb_node_t node
Entry in the trigger last fired tree.
Definition trigger.c:60
static bool triggers_init
Whether triggers are enabled globally.
Definition trigger.c:48
fr_exec_state_t exec
Used for asynchronous execution.
Definition trigger.c:145
fr_time_t last_fired
When this trigger last fired.
Definition trigger.c:62
static int _trigger_exec_free(UNUSED void *uctx)
Free trigger resources.
Definition trigger.c:490
#define REQUEST_INDEX_TRIGGER_NAME
Definition trigger.c:53
static fr_rb_tree_t * trigger_last_fired_tree
Definition trigger.c:50
static unlang_action_t trigger_run(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Definition trigger.c:202
#define REQUEST_INDEX_TRIGGER_ARGS
Definition trigger.c:54
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:73
char * command
Name of the trigger.
Definition trigger.c:141
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:233
CONF_ITEM * ci
Config item this rate limit counter is associated with.
Definition trigger.c:61
static pthread_mutex_t * trigger_mutex
Definition trigger.c:51
static int8_t _trigger_last_fired_cmp(void const *one, void const *two)
Compares two last fired structures.
Definition trigger.c:125
fr_time_delta_t timeout
How long the trigger has to run.
Definition trigger.c:146
static void _trigger_last_fired_free(void *data)
Definition trigger.c:114
bool trigger_enabled(void)
Return whether triggers are enabled.
Definition trigger.c:135
static CONF_SECTION const * trigger_exec_main
Definition trigger.c:49
Describes a rate limiting entry for a trigger.
Definition trigger.c:59
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:286
bool required
Argument must be present, and non-empty.
Definition xlat.h:148
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.
static fr_slen_t head
Definition xlat.h:422
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:168
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:695
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:147
#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:3740
static fr_slen_t data
Definition value.h:1265
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:632
static size_t char ** out
Definition value.h:997
An xlat calling ctx.
Definition xlat_ctx.h:49